summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuresh Gupta <B42813@freescale.com>2013-08-01 07:09:48 (GMT)
committerRivera Jose-B46482 <German.Rivera@freescale.com>2013-08-29 14:04:18 (GMT)
commit63479e74d5bf8cad9e7f7bde52d5eb4d43925df9 (patch)
tree0bb810651f5377cb1e8b856925730ced19155aa8
parenta133e4d9e7412890f61a978a24f80fc085b4eca5 (diff)
downloadlinux-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.c51
-rw-r--r--drivers/usb/host/ehci-fsl.h3
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 */