[PATCH v2 1/1] usb: chipidea: host: add .bus_suspend quirk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For chipidea, its resume sequence is not-EHCI compatible, see
below description for FPR at portsc. So in order to send SoF in
time for remote wakeup sequence(within 3ms), the RUN/STOP bit must
be set before the resume signal is ended, but the usb resume
code may run after resume signal is ended, so we had to set it
at suspend path.

Force Port Resume - RW. Default = 0b.
1= Resume detected/driven on port.
0=No resume (K-state) detected/driven on port.
Host mode:
Software sets this bit to one to drive resume signaling. The Controller sets this bit to '1' if
a J-to-K transition is detected while the port is in the Suspend state. When this bit
transitions to a '1' because a J-to-K transition is detected, the Port Change Detect bit in
the USBSTS register is also set to '1'. This bit will automatically change to '0' after the
resume sequence is complete. This behavior is different from EHCI where the controller
driver is required to set this bit to a '0' after the resume duration is timed in the driver.
Note that when the controller owns the port, the resume sequence follows the defined

sequence documented in the USB Specification Revision 2.0. The resume signaling
(Full-speed 'K') is driven on the port as long as this bit remains a '1'. This bit will remain
a '1' until the port has switched to idle. Writing a '0' has no affect because the port
controller will time the resume operation, clear the bit and the port control state switches
to HS or FS idle.
This field is '0' if Port Power(PP) is '0' in host mode.

This bit is not-EHCI compatible.

Signed-off-by: Peter Chen <peter.chen@xxxxxxxxxxxxx>
---

Changes for v2:
- Delete the wrong roothub remote wakeup setting 
- Change busy-loop to sleep-loop
- Change some comments, the device enters full speed state wrongly
  if RS bit is not set.

 drivers/usb/chipidea/host.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 48731d0..6d4fdbe 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -33,6 +33,7 @@
 #include "host.h"
 
 static struct hc_driver __read_mostly ci_ehci_hc_driver;
+static int (*orig_bus_suspend)(struct usb_hcd *hcd);
 
 struct ehci_ci_priv {
 	struct regulator *reg_vbus;
@@ -158,6 +159,47 @@ void ci_hdrc_host_destroy(struct ci_hdrc *ci)
 		host_stop(ci);
 }
 
+static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int port;
+	u32 tmp;
+
+	int ret = orig_bus_suspend(hcd);
+
+	if (ret)
+		return ret;
+
+	port = HCS_N_PORTS(ehci->hcs_params);
+	while (port--) {
+		u32 __iomem *reg = &ehci->regs->port_status[port];
+		u32 portsc = ehci_readl(ehci, reg);
+
+		if (portsc & PORT_CONNECT) {
+			/*
+			 * For chipidea, the resume signal will be ended
+			 * automatically, so for remote wakeup case, the
+			 * usbcmd.rs may not be set before the resume has
+			 * ended if other resume paths consumes too much
+			 * time (~24ms), in that case, the SOF will not
+			 * send out within 3ms after resume ends, then the
+			 * high speed device will enter full speed mode.
+			 */
+
+			tmp = ehci_readl(ehci, &ehci->regs->command);
+			tmp |= CMD_RUN;
+			ehci_writel(ehci, tmp, &ehci->regs->command);
+			/*
+			 * It needs a short delay between set RS bit and PHCD.
+			 */
+			usleep_range(150, 200);
+			break;
+		}
+	}
+
+	return 0;
+}
+
 int ci_hdrc_host_init(struct ci_hdrc *ci)
 {
 	struct ci_role_driver *rdrv;
@@ -176,6 +218,8 @@ int ci_hdrc_host_init(struct ci_hdrc *ci)
 	ci->roles[CI_ROLE_HOST] = rdrv;
 
 	ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
+	orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
+	ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
 
 	return 0;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux