diff options
author | Suresh Gupta <B42813@freescale.com> | 2013-08-01 07:09:48 (GMT) |
---|---|---|
committer | Rivera Jose-B46482 <German.Rivera@freescale.com> | 2013-08-29 14:04:18 (GMT) |
commit | 63479e74d5bf8cad9e7f7bde52d5eb4d43925df9 (patch) | |
tree | 0bb810651f5377cb1e8b856925730ced19155aa8 | |
parent | a133e4d9e7412890f61a978a24f80fc085b4eca5 (diff) | |
download | linux-fsl-qoriq-63479e74d5bf8cad9e7f7bde52d5eb4d43925df9.tar.xz |
fsl/usb: 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>
Change-Id: Ib2637f038020ec2429e4fbe196713fd66585ab17
Reviewed-on: http://git.am.freescale.net:8181/4209
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Wrobel Heinz-R39252 <Heinz.Wrobel@freescale.com>
Reviewed-by: Rivera Jose-B46482 <German.Rivera@freescale.com>
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 51 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.h | 3 |
2 files changed, 46 insertions, 8 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index f1e8547..8d79759 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -52,6 +52,46 @@ struct ehci_fsl { unsigned hcd_add:1; }; +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 struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -325,14 +365,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, } if (pdata->have_sysif_regs && pdata->controller_ver && - (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))) { - printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); - return -EINVAL; - } + !usb_phy_clk_valid(hcd, phy_mode)) { + printk(KERN_ERR "fsl-ehci: USB PHY clock invalid\n"); + return -EINVAL; } ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index dbd292e..a032358 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -62,4 +62,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 */ |