]> git.karo-electronics.de Git - linux-beck.git/commitdiff
fsl/usb: Workarourd for USB erratum-A005697
authorChangming Huang <jerry.huang@nxp.com>
Tue, 29 Nov 2016 05:45:38 +0000 (13:45 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Dec 2016 14:13:58 +0000 (15:13 +0100)
The EHCI specification states the following in the SUSP bit description:
In the Suspend state, the port is sensitive to resume detection.
Note that the bit status does not change until the port is suspended and
that there may be a delay in suspending a port if there is a transaction
currently in progress on the USB.

However, in NXP USBDR controller, the PORTSCx[SUSP] bit changes immediately
when the application sets it and not when the port is actually suspended.

So the application must wait for at least 10 milliseconds after a port
indicates that it is suspended, to make sure this port has entered
suspended state before initiating this port resume using the Force Port
Resume bit. This bit is for NXP controller, not EHCI compatible.

Signed-off-by: Changming Huang <jerry.huang@nxp.com>
Signed-off-by: Ramneek Mehresh <ramneek.mehresh@nxp.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci.h
drivers/usb/host/fsl-mph-dr-of.c
include/linux/fsl_devices.h

index 9f5ffb62997303dedd1d6c7d929191992a039c81..91701cc680824189a634807d2aed8a33467d712f 100644 (file)
@@ -286,6 +286,9 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
        if (pdata->has_fsl_erratum_a005275 == 1)
                ehci->has_fsl_hs_errata = 1;
 
+       if (pdata->has_fsl_erratum_a005697 == 1)
+               ehci->has_fsl_susp_errata = 1;
+
        if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
                        (pdata->operating_mode == FSL_USB2_DR_OTG))
                if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
index 74f62d68f01362d144e8de21bd188c06e31a7945..df169c8e7225f611cf52411c1d6d171f6fb3546a 100644 (file)
@@ -310,6 +310,14 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        }
        spin_unlock_irq(&ehci->lock);
 
+       if (changed && ehci_has_fsl_susp_errata(ehci))
+               /*
+                * Wait for at least 10 millisecondes to ensure the controller
+                * enter the suspend status before initiating a port resume
+                * using the Force Port Resume bit (Not-EHCI compatible).
+                */
+               usleep_range(10000, 20000);
+
        if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
                /*
                 * Wait for HCD to enter low-power mode or for the bus
@@ -1200,6 +1208,12 @@ int ehci_hub_control(
                                        wIndex, (temp1 & HOSTPC_PHCD) ?
                                        "succeeded" : "failed");
                        }
+                       if (ehci_has_fsl_susp_errata(ehci)) {
+                               /* 10ms for HCD enter suspend */
+                               spin_unlock_irqrestore(&ehci->lock, flags);
+                               usleep_range(10000, 20000);
+                               spin_lock_irqsave(&ehci->lock, flags);
+                       }
                        set_bit(wIndex, &ehci->suspended_ports);
                        break;
                case USB_PORT_FEAT_POWER:
index 3f3b74aeca9740c67f45831762beea1d3c2d9097..a8e36170d8b8a623e4726265b4d194156f231d4f 100644 (file)
@@ -219,6 +219,7 @@ struct ehci_hcd {                   /* one per controller */
        unsigned                no_selective_suspend:1;
        unsigned                has_fsl_port_bug:1; /* FreeScale */
        unsigned                has_fsl_hs_errata:1;    /* Freescale HS quirk */
+       unsigned                has_fsl_susp_errata:1;  /* NXP SUSP quirk */
        unsigned                big_endian_mmio:1;
        unsigned                big_endian_desc:1;
        unsigned                big_endian_capbase:1;
@@ -709,6 +710,13 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 #define ehci_has_fsl_hs_errata(e)      (0)
 #endif
 
+/*
+ * Some Freescale/NXP processors have an erratum (USB A-005697)
+ * in which we need to wait for 10ms for bus to enter suspend mode
+ * after setting SUSP bit.
+ */
+#define ehci_has_fsl_susp_errata(e)    ((e)->has_fsl_susp_errata)
+
 /*
  * While most USB host controllers implement their registers in
  * little-endian format, a minority (celleb companion chip) implement
index f07ccb25bc244f4f98c33a80d12a9c874e3696c1..e90ddb5307653f7a61b3054def1e5e6c82217efb 100644 (file)
@@ -226,6 +226,8 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
                of_property_read_bool(np, "fsl,usb-erratum-a007792");
        pdata->has_fsl_erratum_a005275 =
                of_property_read_bool(np, "fsl,usb-erratum-a005275");
+       pdata->has_fsl_erratum_a005697 =
+               of_property_read_bool(np, "fsl,usb_erratum-a005697");
 
        /*
         * Determine whether phy_clk_valid needs to be checked
index f2912914141a83df04090ab1f95b04521517188a..60cef8227534077aedcee9bdc39cf163bb325e59 100644 (file)
@@ -100,6 +100,7 @@ struct fsl_usb2_platform_data {
        unsigned        already_suspended:1;
        unsigned        has_fsl_erratum_a007792:1;
        unsigned        has_fsl_erratum_a005275:1;
+       unsigned        has_fsl_erratum_a005697:1;
        unsigned        check_phy_clk_valid:1;
 
        /* register save area for suspend/resume */