Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsl/usb: Workarourd for USB erratum-A005697

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>

authored by

Changming Huang and committed by
Greg Kroah-Hartman
9d4b8270 22547c4c

+28
+3
drivers/usb/host/ehci-fsl.c
··· 286 286 if (pdata->has_fsl_erratum_a005275 == 1) 287 287 ehci->has_fsl_hs_errata = 1; 288 288 289 + if (pdata->has_fsl_erratum_a005697 == 1) 290 + ehci->has_fsl_susp_errata = 1; 291 + 289 292 if ((pdata->operating_mode == FSL_USB2_DR_HOST) || 290 293 (pdata->operating_mode == FSL_USB2_DR_OTG)) 291 294 if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
+14
drivers/usb/host/ehci-hub.c
··· 310 310 } 311 311 spin_unlock_irq(&ehci->lock); 312 312 313 + if (changed && ehci_has_fsl_susp_errata(ehci)) 314 + /* 315 + * Wait for at least 10 millisecondes to ensure the controller 316 + * enter the suspend status before initiating a port resume 317 + * using the Force Port Resume bit (Not-EHCI compatible). 318 + */ 319 + usleep_range(10000, 20000); 320 + 313 321 if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) { 314 322 /* 315 323 * Wait for HCD to enter low-power mode or for the bus ··· 1207 1199 ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", 1208 1200 wIndex, (temp1 & HOSTPC_PHCD) ? 1209 1201 "succeeded" : "failed"); 1202 + } 1203 + if (ehci_has_fsl_susp_errata(ehci)) { 1204 + /* 10ms for HCD enter suspend */ 1205 + spin_unlock_irqrestore(&ehci->lock, flags); 1206 + usleep_range(10000, 20000); 1207 + spin_lock_irqsave(&ehci->lock, flags); 1210 1208 } 1211 1209 set_bit(wIndex, &ehci->suspended_ports); 1212 1210 break;
+8
drivers/usb/host/ehci.h
··· 219 219 unsigned no_selective_suspend:1; 220 220 unsigned has_fsl_port_bug:1; /* FreeScale */ 221 221 unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */ 222 + unsigned has_fsl_susp_errata:1; /* NXP SUSP quirk */ 222 223 unsigned big_endian_mmio:1; 223 224 unsigned big_endian_desc:1; 224 225 unsigned big_endian_capbase:1; ··· 709 708 #else 710 709 #define ehci_has_fsl_hs_errata(e) (0) 711 710 #endif 711 + 712 + /* 713 + * Some Freescale/NXP processors have an erratum (USB A-005697) 714 + * in which we need to wait for 10ms for bus to enter suspend mode 715 + * after setting SUSP bit. 716 + */ 717 + #define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata) 712 718 713 719 /* 714 720 * While most USB host controllers implement their registers in
+2
drivers/usb/host/fsl-mph-dr-of.c
··· 226 226 of_property_read_bool(np, "fsl,usb-erratum-a007792"); 227 227 pdata->has_fsl_erratum_a005275 = 228 228 of_property_read_bool(np, "fsl,usb-erratum-a005275"); 229 + pdata->has_fsl_erratum_a005697 = 230 + of_property_read_bool(np, "fsl,usb_erratum-a005697"); 229 231 230 232 /* 231 233 * Determine whether phy_clk_valid needs to be checked
+1
include/linux/fsl_devices.h
··· 100 100 unsigned already_suspended:1; 101 101 unsigned has_fsl_erratum_a007792:1; 102 102 unsigned has_fsl_erratum_a005275:1; 103 + unsigned has_fsl_erratum_a005697:1; 103 104 unsigned check_phy_clk_valid:1; 104 105 105 106 /* register save area for suspend/resume */