summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
authorSriharsha Allenki <sallenki@codeaurora.org>2017-03-21 18:46:16 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-26 21:58:11 -0700
commita2552776b9dfbb61c6979d4d6e3b4de33cf01065 (patch)
tree847fdf8392e8bea9f6b30a1fe0c37bcdf6425ee3 /drivers/platform
parent0257146bf5b77f9cac0fa7fb626dfa61b7d89539 (diff)
platform: msm: Support ID detection using extcon framework
Support ID detection for dual role USB port on 8996 automotive kernel v4.4 using extcon framework. Change-Id: I3f523f9a52dc8e2e8458c661ff11c93156e1c232 Signed-off-by: Sriharsha Allenki <sallenki@codeaurora.org>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/msm/gpio-usbdetect.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/platform/msm/gpio-usbdetect.c b/drivers/platform/msm/gpio-usbdetect.c
index a622bf962fb9..789b14dcfeca 100644
--- a/drivers/platform/msm/gpio-usbdetect.c
+++ b/drivers/platform/msm/gpio-usbdetect.c
@@ -27,9 +27,11 @@ struct gpio_usbdetect {
struct platform_device *pdev;
struct regulator *vin;
int vbus_det_irq;
+ int id_det_irq;
int gpio;
struct extcon_dev *extcon_dev;
int vbus_state;
+ bool id_state;
};
static const unsigned int gpio_usb_extcon_table[] = {
@@ -56,6 +58,37 @@ static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t gpio_usbdetect_id_irq(int irq, void *data)
+{
+ struct gpio_usbdetect *usb = data;
+ int ret;
+
+ ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL,
+ &usb->id_state);
+ if (ret < 0) {
+ dev_err(&usb->pdev->dev, "unable to read ID IRQ LINE\n");
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t gpio_usbdetect_id_irq_thread(int irq, void *data)
+{
+ struct gpio_usbdetect *usb = data;
+
+ if (usb->id_state) {
+ dev_dbg(&usb->pdev->dev, "stopping usb host\n");
+ extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 0);
+ enable_irq(usb->vbus_det_irq);
+ } else {
+ dev_dbg(&usb->pdev->dev, "starting usb HOST\n");
+ disable_irq(usb->vbus_det_irq);
+ extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 1);
+ }
+ return IRQ_HANDLED;
+}
+
static const u32 gpio_usb_extcon_exclusive[] = {0x3, 0};
static int gpio_usbdetect_probe(struct platform_device *pdev)
@@ -132,7 +165,25 @@ static int gpio_usbdetect_probe(struct platform_device *pdev)
goto error;
}
+ usb->id_det_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
+ if (usb->id_det_irq < 0) {
+ dev_err(&pdev->dev, "get id_det_irq failed\n");
+ rc = usb->id_det_irq;
+ goto error;
+ }
+
+ rc = devm_request_threaded_irq(&pdev->dev, usb->id_det_irq,
+ gpio_usbdetect_id_irq,
+ gpio_usbdetect_id_irq_thread,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT, "id_det_irq", usb);
+ if (rc) {
+ dev_err(&pdev->dev, "request for id_det_irq failed: %d\n", rc);
+ goto error;
+ }
+
enable_irq_wake(usb->vbus_det_irq);
+ enable_irq_wake(usb->id_det_irq);
dev_set_drvdata(&pdev->dev, usb);
/* Read and report initial VBUS state */
@@ -152,6 +203,8 @@ static int gpio_usbdetect_remove(struct platform_device *pdev)
disable_irq_wake(usb->vbus_det_irq);
disable_irq(usb->vbus_det_irq);
+ disable_irq_wake(usb->id_det_irq);
+ disable_irq(usb->id_det_irq);
if (usb->vin)
regulator_disable(usb->vin);