ehci: hsic: Add resume gpio support
some peripherals connected to hsic controller cannot wakeup from XO
shutdown using in-band bus resume signalling. If present, use resume
gpio to bring peripherals out of XO shutdown before resuming the bus.
Change-Id: I7b80c95f31e854a09e673a9367ab85e4977a0fa0
Signed-off-by: Vamsi Krishna <vskrishn@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1885e8a..9f8bbd9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -15,7 +15,10 @@
"wakeup" : Wakeup interrupt from HSIC during suspend (or XO shutdown).
- hsic,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
in Documentation/devicetree/bindings/gpio/gpio.txt.
- Optional "gpio-name" can be "strobe" and "data".
+ Optional "gpio-name" can be "strobe", "data" and "resume".
+- hsic,resume-gpio : if present then periperal connected to hsic controller
+ cannot wakeup from XO shutdown using in-band hsic resume. Use resume
+ gpio to wakeup peripheral
- hsic,ignore-cal-pad-config : If present then HSIC CAL PAD configuration
using TLMM is not performed.
- hsic,strobe-pad-offset : Offset of TLMM register for configuring HSIC
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 8c0894c..ca4b01a 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -624,6 +624,15 @@
int ret;
void __iomem *reg;
+ if (pdata && pdata->resume_gpio) {
+ ret = gpio_request(pdata->resume_gpio, "HSIC_RESUME_GPIO");
+ if (ret < 0) {
+ dev_err(mehci->dev,
+ "gpio req failed for hsic resume:%d\n", ret);
+ pdata->resume_gpio = 0;
+ }
+ }
+
/* HSIC init sequence when HSIC signals (Strobe/Data) are
routed via GPIOs */
if (pdata && pdata->strobe && pdata->data) {
@@ -645,7 +654,7 @@
ret = msm_hsic_config_gpios(mehci, 1);
if (ret) {
dev_err(mehci->dev, " gpio configuarion failed\n");
- return ret;
+ goto free_resume_gpio;
}
if (pdata->strobe_pad_offset) {
/* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
@@ -694,6 +703,12 @@
ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
return 0;
+
+free_resume_gpio:
+ if (pdata && pdata->resume_gpio)
+ gpio_free(pdata->resume_gpio);
+
+ return ret;
}
#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
@@ -1312,6 +1327,10 @@
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 temp;
struct task_struct *resume_thread = NULL;
+ struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+
+ if (pdata->resume_gpio)
+ gpio_direction_output(pdata->resume_gpio, 1);
mehci->resume_status = 0;
resume_thread = kthread_run(msm_hsic_resume_thread,
@@ -1351,6 +1370,9 @@
spin_unlock_irq(&ehci->lock);
+ if (pdata->resume_gpio)
+ gpio_direction_output(pdata->resume_gpio, 0);
+
return 0;
}
@@ -1781,6 +1803,11 @@
res_gpio = 0;
pdata->data = res_gpio;
+ res_gpio = of_get_named_gpio(node, "hsic,resume-gpio", 0);
+ if (res_gpio < 0)
+ res_gpio = 0;
+ pdata->resume_gpio = res_gpio;
+
pdata->ignore_cal_pad_config = of_property_read_bool(node,
"hsic,ignore-cal-pad-config");
of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -2099,6 +2126,10 @@
destroy_workqueue(ehci_wq);
msm_hsic_config_gpios(mehci, 0);
+
+ if (pdata && pdata->resume_gpio)
+ gpio_free(pdata->resume_gpio);
+
msm_hsic_init_vddcx(mehci, 0);
msm_hsic_init_gdsc(mehci, 0);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c5943c9..ea45a8c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -406,6 +406,9 @@
struct msm_bus_scale_pdata *bus_scale_table;
unsigned log2_irq_thresh;
+ /* gpio used to resume peripheral */
+ unsigned resume_gpio;
+
/*swfi latency is required while driving resume on to the bus */
u32 swfi_latency;