diff options
author | Suresh Gupta <B42813@freescale.com> | 2013-08-01 07:09:48 (GMT) |
---|---|---|
committer | Xie Xiaobo <xiaobo.xie@nxp.com> | 2017-09-25 07:25:27 (GMT) |
commit | fe3536c043c399c36e03c2b0bd8a59182bce527a (patch) | |
tree | 6a9fc32155f05f55b04b228f921644b37ae7343f /drivers | |
parent | 8c005b58a206367b30ffbdd04e1dd1a250e5d65f (diff) | |
download | linux-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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 40 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.h | 3 |
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 */ |