Commit 5dfff995 authored by Suresh Gupta's avatar Suresh Gupta Committed by Greg Kroah-Hartman
Browse files

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: default avatarSuresh Gupta <B42813@freescale.com>
Signed-off-by: default avatarYinbo Zhu <yinbo.zhu@nxp.com>
Link: https://lore.kernel.org/r/20190624072219.15258-2-yinbo.zhu@nxp.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4f182835
Loading
Loading
Loading
Loading
+26 −11
Original line number Diff line number Diff line
@@ -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,18 +270,12 @@ 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");
	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]);

+3 −0
Original line number Diff line number Diff line
@@ -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 */