[PATCH 12/13] usb: ehci-mx6: Fix PHY power up issue on iMX8 platforms

peng.fan at nxp.com peng.fan at nxp.com
Wed Sep 16 14:57:04 CEST 2020


From: Ye Li <ye.li at nxp.com>

On iMX8 platforms like 8QM/QXP, we must power up the USB PHY resource
before accessing the PHY. However, current init flow access the USB PHY
in ehci_mx6_common_init prior than ehci_usb_phy_mode where the PHY is power
up.

Fix the issue by adding ehci_get_usb_phy function to parse the PHY address
from DTB and power up the PHY before ehci_mx6_common_init.

Signed-off-by: Ye Li <ye.li at nxp.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/usb/host/ehci-mx6.c | 58 +++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 7079750a93..080bde71d3 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -517,6 +517,7 @@ struct ehci_mx6_priv_data {
 	struct usb_ehci *ehci;
 	struct udevice *vbus_supply;
 	enum usb_init_type init_type;
+	void *__iomem phy_base;
 	int portnr;
 };
 
@@ -592,11 +593,39 @@ int __weak board_ehci_usb_phy_mode(struct udevice *dev)
 static int ehci_usb_phy_mode(struct udevice *dev)
 {
 	struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
-	void *__iomem addr = dev_read_addr_ptr(dev);
 	void *__iomem phy_ctrl, *__iomem phy_status;
+	u32 val;
+
+	if (is_mx6() || is_mx7ulp() || is_imx8()) {
+		phy_ctrl = (void __iomem *)(priv->phy_base + USBPHY_CTRL);
+		val = readl(phy_ctrl);
+
+		if (val & USBPHY_CTRL_OTG_ID)
+			priv->init_type = USB_INIT_DEVICE;
+		else
+			priv->init_type = USB_INIT_HOST;
+	} else if (is_mx7() || is_imx8mm() || is_imx8mn()) {
+		phy_status = (void __iomem *)(priv->phy_base +
+					      USBNC_PHY_STATUS_OFFSET);
+		val = readl(phy_status);
+
+		if (val & USBNC_PHYSTATUS_ID_DIG)
+			priv->init_type = USB_INIT_DEVICE;
+		else
+			priv->init_type = USB_INIT_HOST;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ehci_get_usb_phy(struct udevice *dev)
+{
+	struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
+	void *__iomem addr = (void *__iomem)devfdt_get_addr(dev);
 	const void *blob = gd->fdt_blob;
 	int offset = dev_of_offset(dev), phy_off;
-	u32 val;
 
 	/*
 	 * About fsl,usbphy, Refer to
@@ -627,23 +656,9 @@ static int ehci_usb_phy_mode(struct udevice *dev)
 				return ret;
 		}
 #endif
-
-		phy_ctrl = (void __iomem *)(addr + USBPHY_CTRL);
-		val = readl(phy_ctrl);
-
-		if (val & USBPHY_CTRL_OTG_ID)
-			priv->init_type = USB_INIT_DEVICE;
-		else
-			priv->init_type = USB_INIT_HOST;
+		priv->phy_base = addr;
 	} else if (is_mx7() || is_imx8mm() || is_imx8mn()) {
-		phy_status = (void __iomem *)(addr +
-					      USBNC_PHY_STATUS_OFFSET);
-		val = readl(phy_status);
-
-		if (val & USBNC_PHYSTATUS_ID_DIG)
-			priv->init_type = USB_INIT_DEVICE;
-		else
-			priv->init_type = USB_INIT_HOST;
+		priv->phy_base = addr;
 	} else {
 		return -EINVAL;
 	}
@@ -765,6 +780,13 @@ static int ehci_usb_probe(struct udevice *dev)
 	if (ret)
 		debug("%s: No vbus supply\n", dev->name);
 #endif
+
+	ret = ehci_get_usb_phy(dev);
+	if (ret) {
+		debug("%s: fail to get USB PHY base\n", dev->name);
+		return ret;
+	}
+
 	ret = ehci_mx6_common_init(ehci, priv->portnr);
 	if (ret)
 		return ret;
-- 
2.28.0



More information about the U-Boot mailing list