usb: hsic_hcd: add remote wakeup support

With remote wakeup, usb peripheral can wakeup usb host using
resume signalling when usb bus is suspended. During XO shutdown
remote wakeup is over strobe line which is wakeup capable.
Register for strobe wakeup gpio while suspending usb hsic
controller to support remote wakeup.

Change-Id: Ia8b4d5371dbd0bdbbc86a77cc6236ae9b562a3f2
Signed-off-by: Vamsi Krishna <vskrishn@codeaurora.org>
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index fd482f3..6a3a10c 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -636,6 +636,12 @@
 		.name	= "peripheral_status_irq",
 		.flags	= IORESOURCE_IRQ,
 	},
+	{
+		.start	= MSM_GPIO_TO_INT(88),
+		.end	= MSM_GPIO_TO_INT(88),
+		.name	= "wakeup_irq",
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 dma_mask = DMA_BIT_MASK(32);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index dd3ec34..795e7a8 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -24,6 +24,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/irq.h>
 #include <linux/err.h>
 #include <linux/wakelock.h>
 #include <linux/pm_runtime.h>
@@ -53,6 +54,7 @@
 	struct msm_xo_voter	*xo_handle;
 	struct wake_lock	wlock;
 	int			peripheral_status_irq;
+	int			wakeup_irq;
 };
 
 static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
@@ -734,7 +736,7 @@
 {
 	struct msm_hsic_hcd *mehci = dev_id;
 
-	pr_debug("%s: mechi:%p dev_id:%p\n", __func__, mehci, dev_id);
+	pr_debug("%s: mehci:%p dev_id:%p\n", __func__, mehci, dev_id);
 
 	if (mehci)
 		msm_hsic_config_gpios(mehci, 0);
@@ -742,6 +744,16 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t msm_hsic_wakeup_irq(int irq, void *data)
+{
+	struct msm_hsic_hcd *mehci = data;
+
+	dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt\n", __func__);
+
+	return IRQ_HANDLED;
+}
+
+
 static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
@@ -856,6 +868,24 @@
 				__func__, mehci->peripheral_status_irq, ret);
 	}
 
+	/* configure wakeup irq */
+	ret = platform_get_irq(pdev, 2);
+	if (ret > 0) {
+		mehci->wakeup_irq = ret;
+		dev_dbg(&pdev->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
+		ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq,
+				IRQF_TRIGGER_LOW,
+				"msm_hsic_wakeup", mehci);
+		if (!ret) {
+			disable_irq_nosync(mehci->wakeup_irq);
+			enable_irq_wake(mehci->wakeup_irq);
+		} else {
+			dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
+					mehci->wakeup_irq, ret);
+			mehci->wakeup_irq = 0;
+		}
+	}
+
 	/*
 	 * This pdev->dev is assigned parent of root-hub by USB core,
 	 * hence, runtime framework automatically calls this driver's
@@ -893,6 +923,10 @@
 
 	if (mehci->peripheral_status_irq)
 		free_irq(mehci->peripheral_status_irq, mehci);
+	if (mehci->wakeup_irq) {
+		disable_irq_wake(mehci->wakeup_irq);
+		free_irq(mehci->wakeup_irq, mehci);
+	}
 
 	device_init_wakeup(&pdev->dev, 0);
 	pm_runtime_set_suspended(&pdev->dev);