From 5dfff995f9cb21c2910e40f5d4da53473356a792 Mon Sep 17 00:00:00 2001 From: Suresh Gupta Date: Mon, 24 Jun 2019 15:22:16 +0800 Subject: [PATCH] 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 Signed-off-by: Yinbo Zhu Link: https://lore.kernel.org/r/20190624072219.15258-2-yinbo.zhu@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 37 ++++++++++++++++++++++++++----------- drivers/usb/host/ehci-fsl.h | 3 +++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 38674b7aa51e..8f3bf3efb038 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -183,6 +183,17 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev) return retval; } +static bool usb_phy_clk_valid(struct usb_hcd *hcd) +{ + void __iomem *non_ehci = hcd->regs; + bool ret = true; + + if (!(ioread32be(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) + ret = false; + + return ret; +} + static int ehci_fsl_setup_phy(struct usb_hcd *hcd, enum fsl_usb2_phy_modes phy_mode, unsigned int port_offset) @@ -226,6 +237,16 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, /* fall through */ case FSL_USB2_PHY_UTMI: case FSL_USB2_PHY_UTMI_DUAL: + /* PHY_CLK_VALID bit is de-featured from all controller + * versions below 2.4 and is to be checked only for + * internal UTMI phy + */ + if (pdata->controller_ver > FSL_USB_VER_2_4 && + pdata->have_sysif_regs && !usb_phy_clk_valid(hcd)) { + dev_err(dev, "USB PHY clock invalid\n"); + return -EINVAL; + } + if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ tmp = ioread32be(non_ehci + FSL_SOC_USB_CTRL); @@ -249,17 +270,11 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, break; } - /* - * check PHY_CLK_VALID to determine phy clock presence before writing - * to portsc - */ - if (pdata->check_phy_clk_valid) { - if (!(ioread32be(non_ehci + FSL_SOC_USB_CTRL) & - PHY_CLK_VALID)) { - dev_warn(hcd->self.controller, - "USB PHY clock invalid\n"); - return -EINVAL; - } + if (pdata->have_sysif_regs && + pdata->controller_ver > FSL_USB_VER_1_6 && + !usb_phy_clk_valid(hcd)) { + dev_warn(hcd->self.controller, "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 cbc422032e50..9d18c6e6ab27 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -50,4 +50,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 */