Detailed description for this pull request: 1. Support the extcon property and add the synchronization APIs. - This feature supports the extcon property for external connector because each external connector might have the property according to the H/W design. - The property name should keep the following style. : EXTCON_PROP_USB_[property_name] : EXTCON_PROP_CHG_[property_name] : EXTCON_PROP_JACK_[property_name] : EXTCON_PROP_DISP_[property_name] - Add the new extcon APIs to support the extcon property. : extcon_set_property() : extcon_get_property() : extcon_set_property_capability() : extcon_get_property_capability() - Add the new synchronization extcon APIs. : This feature adds the synchronization extcon APIs to support the noti for both state and property. When extcon_*_sync() functions is called, the extcon informs the information from extcon provider to extcon client. The extcon driver may need to change the both state and multiple properties at the same time. After setting the data of a external connector, the extcon send the notification to client driver with the extcon_*_sync(). : extcon_sync() : extcon_set_state_sync() : extcon_set_property_sync() - Change the name of existing APIs. : extcon_set_cable_state_() -> extcon_set_cable() : extcon_get_cable_state_() -> extcon_get_cable() 2. Add the extcon type to group the connector into five category. - EXTCON_TYPE_USB : USB connector - EXTCON_TYPE_CHG : Charger connector - EXTCON_TYPE_JACK : Jack connector - EXTCON_TYPE_DISP : Display connector - EXTCON_TYPE_MISC : Miscellaneous connector 3. Add the new property for external connector. - EXTCON_PROP_USB_VBUS - EXTCON_PROP_USB_TYPEC_POLARITY - EXTCON_PROP_USB_SS (SuperSpeed) - EXTCON_PROP_DISP_HPD (Hot Plug Detect) 4. Add the new type of external connector. - EXTCON_DISP_DP : Display Port - EXTCON_DISP_HMD : Head Mounted Device - EXTCON_CHG_WPT : Wireless Power Transfer device 5. Add the new extcon driver. - Qualcomm SPMI PMIC USB id detection driver detects whether EXTCON_USB_HOST is attached or detached. (extcon-qcom-spmi-mis.c) 6. Remove the usage of extcon_update_state() and old extcon_set_state() - Both extcon_update_state() and extcon_set_state() should change the state of all external connectors with bit masking handling. It may occur the problem. Instead, extcon provides the extcon_set/get_state() functions. 7. Fix the minor issues on extcon drivers. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJX15NdAAoJEJzN3yze689THBUP/jnchjajptYuKY/Y/TkDfdHF ffEQX/V4lJ1rZfQe4TOWf/f4Pa/+AssFXlOH08in9mAqphsYVZb6d05yVxZgK2cA 3C0JH2SigpcnpIbxDAmz+IuJCzA9BIyhj3+qqzo72vRE8lS+CBQk0jsuQgbNVRG+ T9Dg7GvqcWOpvlGXFhMszznYMQIXfnYSuY4JbT5YjEN6k7qC+fYPwyXN7iJfZ70r B9mQwjynimE82VV7xfeYwUhoXCSu+MS8YlfxayWP7p8//kNyID17LjCZttH/deF4 bMr+PfUmn3Uv8PoOQL+hONRruVNbzp8fPaBERk1G/7CS9Gtf1jZUHYyG4Hn7cmpt i/WAvFc2aDJyZEzVRborbnZ4KAwas8ftfNy13fIzsXKwPg6FKoIGoj8+4cxO61fc rP+GDWpCOheCMLI9oRuXM1Ub6f8z5uZl3xDgWuGb2LCp7uquIC483AaZAKqpPNll Xo4oLFTWecyA0lt1FsHC/qTbSW104VtYeQv644zsDTMyVvarQ4daf9lce9Qw5dYc jM2EN8CYHw38jpgFquNXqRArNoTbdsLWQ9shv6MlQNguX8hao6lZZgFtWYq9j3dj I1YjkyyYyr5VwF+xUjTQFrLWXPZ77/7LRwgeifcIPI3MC+tYFhhBojIT709ri8L/ QwgUF2ukSoPxPVT/jUVv =LF4N -----END PGP SIGNATURE----- Merge tag 'extcon-next-for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into usb-testing Chanwoo writes: Update extcon for 4.9 Detailed description for this pull request: 1. Support the extcon property and add the synchronization APIs. - This feature supports the extcon property for external connector because each external connector might have the property according to the H/W design. - The property name should keep the following style. : EXTCON_PROP_USB_[property_name] : EXTCON_PROP_CHG_[property_name] : EXTCON_PROP_JACK_[property_name] : EXTCON_PROP_DISP_[property_name] - Add the new extcon APIs to support the extcon property. : extcon_set_property() : extcon_get_property() : extcon_set_property_capability() : extcon_get_property_capability() - Add the new synchronization extcon APIs. : This feature adds the synchronization extcon APIs to support the noti for both state and property. When extcon_*_sync() functions is called, the extcon informs the information from extcon provider to extcon client. The extcon driver may need to change the both state and multiple properties at the same time. After setting the data of a external connector, the extcon send the notification to client driver with the extcon_*_sync(). : extcon_sync() : extcon_set_state_sync() : extcon_set_property_sync() - Change the name of existing APIs. : extcon_set_cable_state_() -> extcon_set_cable() : extcon_get_cable_state_() -> extcon_get_cable() 2. Add the extcon type to group the connector into five category. - EXTCON_TYPE_USB : USB connector - EXTCON_TYPE_CHG : Charger connector - EXTCON_TYPE_JACK : Jack connector - EXTCON_TYPE_DISP : Display connector - EXTCON_TYPE_MISC : Miscellaneous connector 3. Add the new property for external connector. - EXTCON_PROP_USB_VBUS - EXTCON_PROP_USB_TYPEC_POLARITY - EXTCON_PROP_USB_SS (SuperSpeed) - EXTCON_PROP_DISP_HPD (Hot Plug Detect) 4. Add the new type of external connector. - EXTCON_DISP_DP : Display Port - EXTCON_DISP_HMD : Head Mounted Device - EXTCON_CHG_WPT : Wireless Power Transfer device 5. Add the new extcon driver. - Qualcomm SPMI PMIC USB id detection driver detects whether EXTCON_USB_HOST is attached or detached. (extcon-qcom-spmi-mis.c) 6. Remove the usage of extcon_update_state() and old extcon_set_state() - Both extcon_update_state() and extcon_set_state() should change the state of all external connectors with bit masking handling. It may occur the problem. Instead, extcon provides the extcon_set/get_state() functions. 7. Fix the minor issues on extcon drivers.tirimbino
commit
4d719209be
@ -0,0 +1,41 @@ |
||||
Qualcomm's PM8941 USB ID Extcon device |
||||
|
||||
Some Qualcomm PMICs have a "misc" module that can be used to detect when |
||||
the USB ID pin has been pulled low or high. |
||||
|
||||
PROPERTIES |
||||
|
||||
- compatible: |
||||
Usage: required |
||||
Value type: <string> |
||||
Definition: Should contain "qcom,pm8941-misc"; |
||||
|
||||
- reg: |
||||
Usage: required |
||||
Value type: <u32> |
||||
Definition: Should contain the offset to the misc address space |
||||
|
||||
- interrupts: |
||||
Usage: required |
||||
Value type: <prop-encoded-array> |
||||
Definition: Should contain the usb id interrupt |
||||
|
||||
- interrupt-names: |
||||
Usage: required |
||||
Value type: <stringlist> |
||||
Definition: Should contain the string "usb_id" for the usb id interrupt |
||||
|
||||
Example: |
||||
|
||||
pmic { |
||||
usb_id: misc@900 { |
||||
compatible = "qcom,pm8941-misc"; |
||||
reg = <0x900>; |
||||
interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>; |
||||
interrupt-names = "usb_id"; |
||||
}; |
||||
} |
||||
|
||||
usb-controller { |
||||
extcon = <&usb_id>; |
||||
}; |
@ -0,0 +1,170 @@ |
||||
/**
|
||||
* extcon-qcom-spmi-misc.c - Qualcomm USB extcon driver to support USB ID |
||||
* detection based on extcon-usb-gpio.c. |
||||
* |
||||
* Copyright (C) 2016 Linaro, Ltd. |
||||
* Stephen Boyd <stephen.boyd@linaro.org> |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#include <linux/extcon.h> |
||||
#include <linux/init.h> |
||||
#include <linux/interrupt.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/module.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/slab.h> |
||||
#include <linux/workqueue.h> |
||||
|
||||
#define USB_ID_DEBOUNCE_MS 5 /* ms */ |
||||
|
||||
struct qcom_usb_extcon_info { |
||||
struct extcon_dev *edev; |
||||
int irq; |
||||
struct delayed_work wq_detcable; |
||||
unsigned long debounce_jiffies; |
||||
}; |
||||
|
||||
static const unsigned int qcom_usb_extcon_cable[] = { |
||||
EXTCON_USB_HOST, |
||||
EXTCON_NONE, |
||||
}; |
||||
|
||||
static void qcom_usb_extcon_detect_cable(struct work_struct *work) |
||||
{ |
||||
bool id; |
||||
int ret; |
||||
struct qcom_usb_extcon_info *info = container_of(to_delayed_work(work), |
||||
struct qcom_usb_extcon_info, |
||||
wq_detcable); |
||||
|
||||
/* check ID and update cable state */ |
||||
ret = irq_get_irqchip_state(info->irq, IRQCHIP_STATE_LINE_LEVEL, &id); |
||||
if (ret) |
||||
return; |
||||
|
||||
extcon_set_state(info->edev, EXTCON_USB_HOST, !id); |
||||
} |
||||
|
||||
static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id) |
||||
{ |
||||
struct qcom_usb_extcon_info *info = dev_id; |
||||
|
||||
queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, |
||||
info->debounce_jiffies); |
||||
|
||||
return IRQ_HANDLED; |
||||
} |
||||
|
||||
static int qcom_usb_extcon_probe(struct platform_device *pdev) |
||||
{ |
||||
struct device *dev = &pdev->dev; |
||||
struct qcom_usb_extcon_info *info; |
||||
int ret; |
||||
|
||||
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); |
||||
if (!info) |
||||
return -ENOMEM; |
||||
|
||||
info->edev = devm_extcon_dev_allocate(dev, qcom_usb_extcon_cable); |
||||
if (IS_ERR(info->edev)) { |
||||
dev_err(dev, "failed to allocate extcon device\n"); |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
ret = devm_extcon_dev_register(dev, info->edev); |
||||
if (ret < 0) { |
||||
dev_err(dev, "failed to register extcon device\n"); |
||||
return ret; |
||||
} |
||||
|
||||
info->debounce_jiffies = msecs_to_jiffies(USB_ID_DEBOUNCE_MS); |
||||
INIT_DELAYED_WORK(&info->wq_detcable, qcom_usb_extcon_detect_cable); |
||||
|
||||
info->irq = platform_get_irq_byname(pdev, "usb_id"); |
||||
if (info->irq < 0) |
||||
return info->irq; |
||||
|
||||
ret = devm_request_threaded_irq(dev, info->irq, NULL, |
||||
qcom_usb_irq_handler, |
||||
IRQF_TRIGGER_RISING | |
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
||||
pdev->name, info); |
||||
if (ret < 0) { |
||||
dev_err(dev, "failed to request handler for ID IRQ\n"); |
||||
return ret; |
||||
} |
||||
|
||||
platform_set_drvdata(pdev, info); |
||||
device_init_wakeup(dev, 1); |
||||
|
||||
/* Perform initial detection */ |
||||
qcom_usb_extcon_detect_cable(&info->wq_detcable.work); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int qcom_usb_extcon_remove(struct platform_device *pdev) |
||||
{ |
||||
struct qcom_usb_extcon_info *info = platform_get_drvdata(pdev); |
||||
|
||||
cancel_delayed_work_sync(&info->wq_detcable); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#ifdef CONFIG_PM_SLEEP |
||||
static int qcom_usb_extcon_suspend(struct device *dev) |
||||
{ |
||||
struct qcom_usb_extcon_info *info = dev_get_drvdata(dev); |
||||
int ret = 0; |
||||
|
||||
if (device_may_wakeup(dev)) |
||||
ret = enable_irq_wake(info->irq); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int qcom_usb_extcon_resume(struct device *dev) |
||||
{ |
||||
struct qcom_usb_extcon_info *info = dev_get_drvdata(dev); |
||||
int ret = 0; |
||||
|
||||
if (device_may_wakeup(dev)) |
||||
ret = disable_irq_wake(info->irq); |
||||
|
||||
return ret; |
||||
} |
||||
#endif |
||||
|
||||
static SIMPLE_DEV_PM_OPS(qcom_usb_extcon_pm_ops, |
||||
qcom_usb_extcon_suspend, qcom_usb_extcon_resume); |
||||
|
||||
static const struct of_device_id qcom_usb_extcon_dt_match[] = { |
||||
{ .compatible = "qcom,pm8941-misc", }, |
||||
{ } |
||||
}; |
||||
MODULE_DEVICE_TABLE(of, qcom_usb_extcon_dt_match); |
||||
|
||||
static struct platform_driver qcom_usb_extcon_driver = { |
||||
.probe = qcom_usb_extcon_probe, |
||||
.remove = qcom_usb_extcon_remove, |
||||
.driver = { |
||||
.name = "extcon-pm8941-misc", |
||||
.pm = &qcom_usb_extcon_pm_ops, |
||||
.of_match_table = qcom_usb_extcon_dt_match, |
||||
}, |
||||
}; |
||||
module_platform_driver(qcom_usb_extcon_driver); |
||||
|
||||
MODULE_DESCRIPTION("QCOM USB ID extcon driver"); |
||||
MODULE_AUTHOR("Stephen Boyd <stephen.boyd@linaro.org>"); |
||||
MODULE_LICENSE("GPL v2"); |
Loading…
Reference in new issue