From 614ccd4b2e77faf4504469eeeee104cc3e76e761 Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Wed, 14 Feb 2018 19:05:48 +0530 Subject: [PATCH 1/2] extcon: qcom-spmi: Add support for VBUS detection VBUS can be detected via a dedicated PMIC pin. Add support for reporting the VBUS status. Change-Id: If1739017f33a502df1c15ca720f9df830e66bfbd Signed-off-by: Anirudh Ghayal Signed-off-by: Kavya Nunna --- .../bindings/extcon/qcom,pm8941-misc.txt | 2 +- drivers/extcon/extcon-qcom-spmi-misc.c | 102 ++++++++++++++---- 2 files changed, 83 insertions(+), 21 deletions(-) diff --git a/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt b/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt index 35383adb10f1..91a49af6a122 100644 --- a/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt +++ b/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt @@ -8,7 +8,7 @@ PROPERTIES - compatible: Usage: required Value type: - Definition: Should contain "qcom,pm8941-misc"; + Definition: Should contain "qcom,pm8941-misc" or "qcom,pmd-vbus-det"; - reg: Usage: required diff --git a/drivers/extcon/extcon-qcom-spmi-misc.c b/drivers/extcon/extcon-qcom-spmi-misc.c index b8cde096a808..15100b6a3baf 100644 --- a/drivers/extcon/extcon-qcom-spmi-misc.c +++ b/drivers/extcon/extcon-qcom-spmi-misc.c @@ -1,6 +1,6 @@ /** * extcon-qcom-spmi-misc.c - Qualcomm USB extcon driver to support USB ID - * detection based on extcon-usb-gpio.c. + * and VBUS detection based on extcon-usb-gpio.c. * * Copyright (C) 2016 Linaro, Ltd. * Stephen Boyd @@ -28,30 +28,56 @@ struct qcom_usb_extcon_info { struct extcon_dev *edev; - int irq; + int id_irq; + int vbus_irq; struct delayed_work wq_detcable; unsigned long debounce_jiffies; }; static const unsigned int qcom_usb_extcon_cable[] = { + EXTCON_USB, EXTCON_USB_HOST, EXTCON_NONE, }; static void qcom_usb_extcon_detect_cable(struct work_struct *work) { - bool id; + bool state = 0; int ret; + union extcon_property_value val; 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; + if (info->id_irq > 0) { + /* check ID and update cable state */ + ret = irq_get_irqchip_state(info->id_irq, + IRQCHIP_STATE_LINE_LEVEL, &state); + if (ret) + return; - extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !id); + if (!state) { + val.intval = true; + extcon_set_property(info->edev, EXTCON_USB_HOST, + EXTCON_PROP_USB_SS, val); + } + extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !state); + } + + if (info->vbus_irq > 0) { + /* check VBUS and update cable state */ + ret = irq_get_irqchip_state(info->vbus_irq, + IRQCHIP_STATE_LINE_LEVEL, &state); + if (ret) + return; + + if (state) { + val.intval = true; + extcon_set_property(info->edev, EXTCON_USB, + EXTCON_PROP_USB_SS, val); + } + extcon_set_state_sync(info->edev, EXTCON_USB, state); + } } static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id) @@ -86,21 +112,48 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev) return ret; } + ret = extcon_set_property_capability(info->edev, + EXTCON_USB, EXTCON_PROP_USB_SS); + ret |= extcon_set_property_capability(info->edev, + EXTCON_USB_HOST, EXTCON_PROP_USB_SS); + if (ret) { + dev_err(dev, "failed to register extcon props rc=%d\n", + ret); + 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, + info->id_irq = platform_get_irq_byname(pdev, "usb_id"); + if (info->id_irq > 0) { + ret = devm_request_threaded_irq(dev, info->id_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; + if (ret < 0) { + dev_err(dev, "failed to request handler for ID IRQ\n"); + return ret; + } + } + + info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus"); + if (info->vbus_irq > 0) { + ret = devm_request_threaded_irq(dev, info->vbus_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 VBUS IRQ\n"); + return ret; + } + } + + if (info->id_irq < 0 && info->vbus_irq < 0) { + dev_err(dev, "ID and VBUS IRQ not found\n"); + return -EINVAL; } platform_set_drvdata(pdev, info); @@ -127,8 +180,12 @@ 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); + if (device_may_wakeup(dev)) { + if (info->id_irq > 0) + ret = enable_irq_wake(info->id_irq); + if (info->vbus_irq > 0) + ret = enable_irq_wake(info->vbus_irq); + } return ret; } @@ -138,8 +195,12 @@ 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); + if (device_may_wakeup(dev)) { + if (info->id_irq > 0) + ret = disable_irq_wake(info->id_irq); + if (info->vbus_irq > 0) + ret = disable_irq_wake(info->vbus_irq); + } return ret; } @@ -150,6 +211,7 @@ static SIMPLE_DEV_PM_OPS(qcom_usb_extcon_pm_ops, static const struct of_device_id qcom_usb_extcon_dt_match[] = { { .compatible = "qcom,pm8941-misc", }, + { .compatible = "qcom,pmd-vbus-det", }, { } }; MODULE_DEVICE_TABLE(of, qcom_usb_extcon_dt_match); From 3752fcb2500a68f1fe7f5680cc3c495350de6123 Mon Sep 17 00:00:00 2001 From: Kavya Nunna Date: Mon, 1 Apr 2019 15:17:46 +0530 Subject: [PATCH 2/2] defconfig: sdxprairie: Enable SPMI MISC driver Enable SPMI misc driver which supports USB VBUS/ID detection and use extcon framework to send notifictaion to USB driver. Change-Id: Id818b0b7081d981ea565d10c5defe87a99ee1ee2 Signed-off-by: Kavya Nunna --- arch/arm/configs/vendor/sdxprairie-perf_defconfig | 1 + arch/arm/configs/vendor/sdxprairie_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/sdxprairie-perf_defconfig b/arch/arm/configs/vendor/sdxprairie-perf_defconfig index 4e917f628773..da67a34bd232 100644 --- a/arch/arm/configs/vendor/sdxprairie-perf_defconfig +++ b/arch/arm/configs/vendor/sdxprairie-perf_defconfig @@ -408,6 +408,7 @@ CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y CONFIG_ARM_MEMLAT_MON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_EXTCON_QCOM_SPMI_MISC=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y diff --git a/arch/arm/configs/vendor/sdxprairie_defconfig b/arch/arm/configs/vendor/sdxprairie_defconfig index 8aa9d1daa962..cc588bdfb1c6 100644 --- a/arch/arm/configs/vendor/sdxprairie_defconfig +++ b/arch/arm/configs/vendor/sdxprairie_defconfig @@ -413,6 +413,7 @@ CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y CONFIG_ARM_MEMLAT_MON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_EXTCON_QCOM_SPMI_MISC=y CONFIG_IIO=y CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y