aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2013-10-01 08:05:07 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2013-10-01 08:05:05 -0700
commit9c6475f3bbc709dba3e2fc25354472a2cdfcdebc (patch)
tree51355a1d0103f604cefc66d80b314090c68c84dc
parenta883420fb5a99527eabf05202c8fb9870629543c (diff)
parentbfed0ed2670d2bafef2bf0e1fde7fc1755821e7f (diff)
Merge "usb: xhci-msm-hsic: Add wakeup gpio support for out of band remote wakeup"
-rw-r--r--Documentation/devicetree/bindings/usb/msm-xhci-hsic.txt15
-rw-r--r--drivers/usb/host/xhci-msm-hsic.c50
2 files changed, 42 insertions, 23 deletions
diff --git a/Documentation/devicetree/bindings/usb/msm-xhci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-xhci-hsic.txt
index 4d1cb35118f..1cac58eb4f1 100644
--- a/Documentation/devicetree/bindings/usb/msm-xhci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-xhci-hsic.txt
@@ -17,13 +17,22 @@ Required properties :
values (no, min, max) where each value represents either a voltage in
microvolts or a value corresponding to voltage corner.
+Optional properties :
+- interrupt-names : Optional interrupt resource entry is:
+ "wakeup_irq" : Interrupt generated by out of band remote wakeup gpio.
+
Example MSM HSIC XHCI controller device node :
xhci_hsic_host: qcom,xhci-msm-hsic@0xf9c00000 {
compatible = "qcom,xhci-msm-hsic";
reg = <0xf9c00000 0xfc000>;
- interrupts = <0 32 0>,
- <0 29 0>;
- interrupt-names = "core_irq", "pwr_event_irq";
+ interrupt-parent = <&xhci_hsic_host>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 32 0
+ 1 &intc 0 29 0
+ 2 &msmgpio 107 0x8>;
+ interrupt-names = "core_irq", "pwr_event_irq", "wakeup_irq";
hsic-vdd-dig-supply = <&pma8084_s2_corner>;
hsic-gdsc-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 134 0x00>;
diff --git a/drivers/usb/host/xhci-msm-hsic.c b/drivers/usb/host/xhci-msm-hsic.c
index d15d0ed4ce3..445c9184654 100644
--- a/drivers/usb/host/xhci-msm-hsic.c
+++ b/drivers/usb/host/xhci-msm-hsic.c
@@ -405,6 +405,7 @@ static void mxhci_hsic_reset(struct mxhci_hsic_hcd *mxhci)
static void mxhci_hsic_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
struct xhci_plat_data *pdata = dev->platform_data;
+ struct mxhci_hsic_hcd *mxhci = hcd_to_hsic(xhci_to_hcd(xhci));
/*
* As of now platform drivers don't provide MSI support so we ensure
@@ -413,6 +414,10 @@ static void mxhci_hsic_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
*/
xhci->quirks |= XHCI_BROKEN_MSI;
+ /* Single port controller using out of band remote wakeup */
+ if (mxhci->wakeup_irq)
+ xhci->quirks |= XHCI_NO_SELECTIVE_SUSPEND;
+
if (!pdata)
return;
if (pdata->vendor == SYNOPSIS_DWC3_VENDOR &&
@@ -544,9 +549,11 @@ static int mxhci_hsic_suspend(struct mxhci_hsic_hcd *mxhci)
enable_irq(hcd->irq);
- mxhci->wakeup_irq_enabled = 1;
- enable_irq_wake(mxhci->wakeup_irq);
- enable_irq(mxhci->wakeup_irq);
+ if (mxhci->wakeup_irq) {
+ mxhci->wakeup_irq_enabled = 1;
+ enable_irq_wake(mxhci->wakeup_irq);
+ enable_irq(mxhci->wakeup_irq);
+ }
pm_relax(mxhci->dev);
@@ -557,6 +564,7 @@ static int mxhci_hsic_suspend(struct mxhci_hsic_hcd *mxhci)
static int mxhci_hsic_resume(struct mxhci_hsic_hcd *mxhci)
{
+ struct usb_hcd *hcd = hsic_to_hcd(mxhci);
int ret;
unsigned long flags;
@@ -593,6 +601,9 @@ static int mxhci_hsic_resume(struct mxhci_hsic_hcd *mxhci)
clk_prepare_enable(mxhci->hsic_clk);
clk_prepare_enable(mxhci->cal_clk);
+ if (mxhci->wakeup_irq)
+ usb_hcd_resume_root_hub(hcd);
+
mxhci->in_lpm = 0;
dev_info(mxhci->dev, "HSIC-USB exited from low power mode\n");
@@ -777,6 +788,22 @@ static int mxhci_hsic_probe(struct platform_device *pdev)
/* enable pwr event irq for LPM_IN_L2_IRQ */
writel_relaxed(LPM_IN_L2_IRQ_MASK, MSM_HSIC_PWR_EVNT_IRQ_MASK);
+ mxhci->wakeup_irq = platform_get_irq_byname(pdev, "wakeup_irq");
+ if (mxhci->wakeup_irq < 0) {
+ mxhci->wakeup_irq = 0;
+ dev_err(&pdev->dev, "failed to init wakeup_irq\n");
+ } else {
+ /* enable wakeup irq only when entering lpm */
+ irq_set_status_flags(mxhci->wakeup_irq, IRQ_NOAUTOEN);
+ ret = devm_request_irq(&pdev->dev, mxhci->wakeup_irq,
+ mxhci_hsic_wakeup_irq, 0, "mxhci_hsic_wakeup", mxhci);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "request irq failed (wakeup irq)\n");
+ goto deinit_vddcx;
+ }
+ }
+
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret)
goto deinit_vddcx;
@@ -824,23 +851,6 @@ static int mxhci_hsic_probe(struct platform_device *pdev)
goto remove_usb3_hcd;
}
- mxhci->wakeup_irq = gpio_to_irq(mxhci->strobe);
- if (mxhci->wakeup_irq < 0) {
- dev_err(&pdev->dev, "gpio_to_irq for strobe gpio failed\n");
- goto remove_usb3_hcd;
- } else {
-
- /* enable wakeup irq while entring lpm */
- irq_set_status_flags(mxhci->wakeup_irq, IRQ_NOAUTOEN);
- ret = devm_request_irq(&pdev->dev, mxhci->wakeup_irq,
- mxhci_hsic_wakeup_irq,
- IRQF_TRIGGER_LOW, "mxhci_hsic_wakeup", mxhci);
- if (ret) {
- dev_err(&pdev->dev,
- "request irq failed (wakeup irq)\n");
- goto remove_usb3_hcd;
- }
- }
init_completion(&mxhci->phy_in_lpm);