global: Migrate CONFIG_MXC_USB_FLAGS et al to CFG
[platform/kernel/u-boot.git] / drivers / usb / host / ehci-mx6.c
index 06be9de..0a12db6 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/mach-types.h>
 #include <power/regulator.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/phy.h>
 
 #include "ehci.h"
 
@@ -69,8 +70,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #define UCMD_RESET             (1 << 1) /* controller reset */
 
 /* If this is not defined, assume MX6/MX7/MX8M SoC default */
-#ifndef CONFIG_MXC_USB_PORTSC
-#define CONFIG_MXC_USB_PORTSC  (PORT_PTS_UTMI | PORT_PTS_PTW)
+#ifndef CFG_MXC_USB_PORTSC
+#define CFG_MXC_USB_PORTSC     (PORT_PTS_UTMI | PORT_PTS_PTW)
 #endif
 
 /* Base address for this IP block is 0x02184800 */
@@ -177,7 +178,7 @@ static void __maybe_unused
 usb_power_config_mx7ulp(void *usbphy) { }
 #endif
 
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT)
 static const unsigned phy_bases[] = {
        USB_PHY0_BASE_ADDR,
 #if defined(USB_PHY1_BASE_ADDR)
@@ -271,12 +272,7 @@ static void usb_oc_config(struct usbnc_regs *usbnc, int index)
 {
        void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
 
-#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
-       /* mx6qarm2 seems to required a different setting*/
-       clrbits_le32(ctrl, UCTRL_OVER_CUR_POL);
-#else
        setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
-#endif
 
        setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
 
@@ -340,7 +336,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
        enum usb_init_type type;
-#if defined(CONFIG_MX6)
+#if defined(CONFIG_MX6) || defined(CONFIG_IMXRT)
        u32 controller_spacing = 0x200;
        struct anatop_regs __iomem *anatop =
                (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
@@ -382,7 +378,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                return ret;
        }
 
-#if defined(CONFIG_MX6)
+#if defined(CONFIG_MX6) || defined(CONFIG_IMXRT)
        usb_power_config_mx6(anatop, index);
 #elif defined (CONFIG_MX7)
        usb_power_config_mx7(usbnc);
@@ -392,7 +388,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
 
        usb_oc_config(usbnc, index);
 
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT)
        if (index < ARRAY_SIZE(phy_bases)) {
                usb_internal_phy_clock_gate((void __iomem *)phy_bases[index], 1);
                usb_phy_enable(ehci, (void __iomem *)phy_bases[index]);
@@ -415,7 +411,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                return 0;
 
        setbits_le32(&ehci->usbmode, CM_HOST);
-       writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+       writel(CFG_MXC_USB_PORTSC, &ehci->portsc);
        setbits_le32(&ehci->portsc, USB_EN);
 
        mdelay(10);
@@ -435,6 +431,7 @@ struct ehci_mx6_priv_data {
        struct clk clk;
        struct phy phy;
        enum usb_init_type init_type;
+       enum usb_phy_interface phy_type;
 #if !defined(CONFIG_PHY)
        int portnr;
        void __iomem *phy_addr;
@@ -443,6 +440,24 @@ struct ehci_mx6_priv_data {
 #endif
 };
 
+static u32 mx6_portsc(enum usb_phy_interface phy_type)
+{
+       switch (phy_type) {
+       case USBPHY_INTERFACE_MODE_UTMI:
+               return PORT_PTS_UTMI;
+       case USBPHY_INTERFACE_MODE_UTMIW:
+               return PORT_PTS_UTMI | PORT_PTS_PTW;
+       case USBPHY_INTERFACE_MODE_ULPI:
+               return PORT_PTS_ULPI;
+       case USBPHY_INTERFACE_MODE_SERIAL:
+               return PORT_PTS_SERIAL;
+       case USBPHY_INTERFACE_MODE_HSIC:
+               return PORT_PTS_HSIC;
+       default:
+               return CFG_MXC_USB_PORTSC;
+       }
+}
+
 static int mx6_init_after_reset(struct ehci_ctrl *dev)
 {
        struct ehci_mx6_priv_data *priv = dev->priv;
@@ -479,7 +494,7 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev)
                return 0;
 
        setbits_le32(&ehci->usbmode, CM_HOST);
-       writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+       writel(mx6_portsc(priv->phy_type), &ehci->portsc);
        setbits_le32(&ehci->portsc, USB_EN);
 
        mdelay(10);
@@ -504,7 +519,7 @@ static int ehci_usb_phy_mode(struct udevice *dev)
         * About fsl,usbphy, Refer to
         * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt.
         */
-       if (is_mx6() || is_mx7ulp()) {
+       if (is_mx6() || is_mx7ulp() || is_imxrt()) {
                phy_off = fdtdec_lookup_phandle(blob,
                                                offset,
                                                "fsl,usbphy");
@@ -523,7 +538,7 @@ static int ehci_usb_phy_mode(struct udevice *dev)
                        plat->init_type = USB_INIT_DEVICE;
                else
                        plat->init_type = USB_INIT_HOST;
-       } else if (is_mx7()) {
+       } else if (is_mx7() || is_imx8mm() || is_imx8mn()) {
                phy_status = (void __iomem *)(addr +
                                              USBNC_PHY_STATUS_OFFSET);
                val = readl(phy_status);
@@ -553,9 +568,8 @@ static int ehci_usb_of_to_plat(struct udevice *dev)
        case USB_DR_MODE_PERIPHERAL:
                plat->init_type = USB_INIT_DEVICE;
                break;
-       case USB_DR_MODE_OTG:
-       case USB_DR_MODE_UNKNOWN:
-               return ehci_usb_phy_mode(dev);
+       default:
+               plat->init_type = USB_INIT_UNKNOWN;
        };
 
        return 0;
@@ -569,7 +583,6 @@ static int mx6_parse_dt_addrs(struct udevice *dev)
        const void *blob = gd->fdt_blob;
        int offset = dev_of_offset(dev);
        void *__iomem addr;
-       int ret, devnump;
 
        phy_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbphy");
        if (phy_off < 0) {
@@ -578,21 +591,15 @@ static int mx6_parse_dt_addrs(struct udevice *dev)
                        return -EINVAL;
        }
 
-       ret = fdtdec_get_alias_seq(blob, dev->uclass->uc_drv->name,
-                                  phy_off, &devnump);
-       if (ret < 0)
-               return ret;
-
        misc_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbmisc");
        if (misc_off < 0)
                return -EINVAL;
 
        addr = (void __iomem *)fdtdec_get_addr(blob, phy_off, "reg");
        if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
-               return -EINVAL;
+               addr = NULL;
 
        priv->phy_addr = addr;
-       priv->portnr = devnump;
 
        addr = (void __iomem *)fdtdec_get_addr(blob, misc_off, "reg");
        if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
@@ -601,7 +608,13 @@ static int mx6_parse_dt_addrs(struct udevice *dev)
        priv->misc_addr = addr;
 
 #if defined(CONFIG_MX6)
-       int anatop_off;
+       int anatop_off, ret, devnump;
+
+       ret = fdtdec_get_alias_seq(blob, dev->uclass->uc_drv->name,
+                                  phy_off, &devnump);
+       if (ret < 0)
+               return ret;
+       priv->portnr = devnump;
 
        /* Resolve ANATOP offset through USB PHY node */
        anatop_off = fdtdec_lookup_phandle(blob, phy_off, "fsl,anatop");
@@ -642,6 +655,7 @@ static int ehci_usb_probe(struct udevice *dev)
 
        priv->ehci = ehci;
        priv->init_type = type;
+       priv->phy_type = usb_get_phy_mode(dev_ofnode(dev));
 
 #if CONFIG_IS_ENABLED(CLK)
        ret = clk_get_by_index(dev, 0, &priv->clk);
@@ -657,6 +671,20 @@ static int ehci_usb_probe(struct udevice *dev)
        mdelay(1);
 #endif
 
+       /*
+        * If the device tree didn't specify host or device,
+        * the default is USB_INIT_UNKNOWN, so we need to check
+        * the register. For imx8mm and imx8mn, the clocks need to be
+        * running first, so we defer the check until they are.
+        */
+       if (priv->init_type == USB_INIT_UNKNOWN) {
+               ret = ehci_usb_phy_mode(dev);
+               if (ret)
+                       goto err_clk;
+               else
+                       priv->init_type = plat->init_type;
+       }
+
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
        ret = device_get_supply_regulator(dev, "vbus-supply",
                                          &priv->vbus_supply);
@@ -671,7 +699,7 @@ static int ehci_usb_probe(struct udevice *dev)
 
        usb_oc_config(priv->misc_addr, priv->portnr);
 
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT)
        usb_internal_phy_clock_gate(priv->phy_addr, 1);
        usb_phy_enable(ehci, priv->phy_addr);
 #endif
@@ -691,14 +719,14 @@ static int ehci_usb_probe(struct udevice *dev)
 
        if (priv->init_type == USB_INIT_HOST) {
                setbits_le32(&ehci->usbmode, CM_HOST);
-               writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+               writel(mx6_portsc(priv->phy_type), &ehci->portsc);
                setbits_le32(&ehci->portsc, USB_EN);
        }
 
        mdelay(10);
 
 #if defined(CONFIG_PHY)
-       ret = ehci_setup_phy(dev, &priv->phy, 0);
+       ret = generic_setup_phy(dev, &priv->phy, 0);
        if (ret)
                goto err_regulator;
 #endif
@@ -715,14 +743,14 @@ static int ehci_usb_probe(struct udevice *dev)
 
 err_phy:
 #if defined(CONFIG_PHY)
-       ehci_shutdown_phy(dev, &priv->phy);
+       generic_shutdown_phy(&priv->phy);
 err_regulator:
 #endif
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
        if (priv->vbus_supply)
                regulator_set_enable(priv->vbus_supply, false);
-err_clk:
 #endif
+err_clk:
 #if CONFIG_IS_ENABLED(CLK)
        clk_disable(&priv->clk);
 #else
@@ -739,7 +767,7 @@ int ehci_usb_remove(struct udevice *dev)
        ehci_deregister(dev);
 
 #if defined(CONFIG_PHY)
-       ehci_shutdown_phy(dev, &priv->phy);
+       generic_shutdown_phy(&priv->phy);
 #endif
 
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
@@ -757,6 +785,7 @@ int ehci_usb_remove(struct udevice *dev)
 static const struct udevice_id mx6_usb_ids[] = {
        { .compatible = "fsl,imx27-usb" },
        { .compatible = "fsl,imx7d-usb" },
+       { .compatible = "fsl,imxrt-usb" },
        { }
 };