From: Ye Li <ye...@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...@nxp.com>
Signed-off-by: Peng Fan <peng....@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

Reply via email to