Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfed0ed2 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

usb: xhci-msm-hsic: Add wakeup gpio support for out of band remote wakeup



Some peripherals connected to HSIC host controller cannot use in-band
remote-wakeup to wakeup host controller from usb bus suspend and use
gpio instead. Add support for wakeup gpio to support out of band
remote-wakeup.

Change-Id: I9c7299bab5dd5c2a9c7d664afe6dbf0b7f7e6e19
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent cb167fec
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -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>;
+30 −20
Original line number Diff line number Diff line
@@ -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);

	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);