summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuresh Gupta <B42813@freescale.com>2013-08-01 07:09:48 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-09-25 07:25:27 (GMT)
commitfe3536c043c399c36e03c2b0bd8a59182bce527a (patch)
tree6a9fc32155f05f55b04b228f921644b37ae7343f
parent8c005b58a206367b30ffbdd04e1dd1a250e5d65f (diff)
downloadlinux-fe3536c043c399c36e03c2b0bd8a59182bce527a.tar.xz
usb: phy: Workaround for USB erratum-A005728
PHY_CLK_VALID bit for UTMI PHY in USBDR does not set even if PHY is providing valid clock. Workaround for this involves resetting of PHY and check PHY_CLK_VALID bit multiple times. If PHY_CLK_VALID bit is still not set even after 5 retries, it would be safe to deaclare that PHY clock is not available. This erratum is applicable for USBDR less then ver 2.4. Signed-off-by: Suresh Gupta <B42813@freescale.com> Signed-off-by: yinbo.zhu <yinbo.zhu@nxp.com>
-rw-r--r--drivers/usb/host/ehci-fsl.c40
-rw-r--r--drivers/usb/host/ehci-fsl.h3
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 04d7a28..f903521 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -280,6 +280,46 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
return retval;
}
+static bool usb_phy_clk_valid(struct usb_hcd *hcd,
+ enum fsl_usb2_phy_modes phy_mode)
+{
+ void __iomem *non_ehci = hcd->regs;
+ struct device *dev = hcd->self.controller;
+ struct fsl_usb2_platform_data *pdata = dev->platform_data;
+ bool ret = true;
+ int retry = UTMI_PHY_CLK_VALID_CHK_RETRY;
+
+ if (phy_mode == FSL_USB2_PHY_ULPI) {
+ /* check PHY_CLK_VALID to get phy clk valid */
+ if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
+ PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
+ in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
+ ret = false;
+ }
+ } else if (phy_mode == FSL_USB2_PHY_UTMI) {
+ if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) {
+ ret = false;
+ if (pdata->controller_ver < FSL_USB_VER_2_4) {
+ while (retry--) {
+ clrbits32(non_ehci + FSL_SOC_USB_CTRL,
+ CTRL_UTMI_PHY_EN);
+ setbits32(non_ehci + FSL_SOC_USB_CTRL,
+ CTRL_UTMI_PHY_EN);
+ /* delay required for Clk to appear */
+ mdelay(FSL_UTMI_PHY_DLY);
+ if ((in_be32(non_ehci +
+ FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) {
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
enum fsl_usb2_phy_modes phy_mode,
unsigned int port_offset)
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 1a8a60a..42ea297 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -63,4 +63,7 @@
#define UTMI_PHY_EN (1<<9)
#define ULPI_PHY_CLK_SEL (1<<10)
#define PHY_CLK_VALID (1<<17)
+
+/* Retry count for checking UTMI PHY CLK validity */
+#define UTMI_PHY_CLK_VALID_CHK_RETRY 5
#endif /* _EHCI_FSL_H */