MLK-23110-1 usb: Decouple the CI_UDC DM gadget driver with EHCI MX6 driver
authorYe Li <ye.li@nxp.com>
Wed, 11 Dec 2019 08:28:17 +0000 (00:28 -0800)
committerYe Li <ye.li@nxp.com>
Thu, 29 Apr 2021 07:56:36 +0000 (00:56 -0700)
On 2019.04 SPL, we enabled DM gadget driver for QM/QXP to support
dual USB ports. The CI_UDC DM gadget driver will call init function
inside EHCI mx6 driver, so when building SPL on iMX8QM/QXP with CI UDC
enabled, we have to enable usb host driver as well, and this introduces
about more than 40KB size to SPL.

Move the common codes to a independent file, so that both host driver
and gadget driver can call it, then decouple the host and gadget driver.

Note: the patch only applies to ci_udc gadget DM driver. For non-DM gadget
driver, it still depends ehci host interfaces.

Signed-off-by: Ye Li <ye.li@nxp.com>
Acked-by: Peng Fan <peng.fan@nxp.com>
(cherry picked from commit 1afed171a77b4c95cd4ea76f29d5a0a6bb199820)
(cherry picked from commit 6680499ca4d3a740df5c0aa5a5e66f6d93f827fb)

Makefile
drivers/usb/gadget/ci_udc.c
drivers/usb/host/ehci-mx6.c
drivers/usb/imx/Makefile [new file with mode: 0644]
drivers/usb/imx/usb-mx6-common.c [new file with mode: 0644]
include/usb/ci_udc.h
include/usb/usb_mx6_common.h [new file with mode: 0644]
scripts/Makefile.spl

index 7b526f4..0451f44 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -783,6 +783,7 @@ libs-$(CONFIG_SYS_FSL_MMDC) += drivers/ddr/fsl/
 libs-$(CONFIG_$(SPL_)ALTERA_SDRAM) += drivers/ddr/altera/
 libs-y += drivers/serial/
 libs-y += drivers/usb/cdns3/
+libs-y += drivers/usb/imx/
 libs-y += drivers/usb/dwc3/
 libs-y += drivers/usb/common/
 libs-y += drivers/usb/emul/
index e8cc85a..0dfb0c0 100644 (file)
@@ -33,6 +33,7 @@
 #include <dm/pinctrl.h>
 #include <usb/ci_udc.h>
 #include <usb/ehci-ci.h>
+#include <usb/usb_mx6_common.h>
 #include "../host/ehci.h"
 #include "ci_udc.h"
 
index ee27160..5dd5cd4 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
  * Copyright (C) 2010 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
+ * Copyright 2017-2019 NXP
  *
  */
 
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <usb/ehci-ci.h>
+#include <usb/usb_mx6_common.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define USB_OTGREGS_OFFSET     0x000
-#define USB_H1REGS_OFFSET      0x200
-#define USB_H2REGS_OFFSET      0x400
-#define USB_H3REGS_OFFSET      0x600
-#define USB_OTHERREGS_OFFSET   0x800
-
-#define USB_H1_CTRL_OFFSET     0x04
-
-#define ANADIG_USB2_CHRG_DETECT_EN_B           0x00100000
-#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B     0x00080000
-
-#define ANADIG_USB2_PLL_480_CTRL_BYPASS                0x00010000
-#define ANADIG_USB2_PLL_480_CTRL_ENABLE                0x00002000
-#define ANADIG_USB2_PLL_480_CTRL_POWER         0x00001000
-#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS   0x00000040
-
-#define USBNC_OFFSET           0x200
-#define USBNC_PHYCFG2_ACAENB   (1 << 4) /* otg_id detection enable */
-#define UCTRL_PWR_POL          (1 << 9) /* OTG Polarity of Power Pin */
-#define UCTRL_OVER_CUR_POL     (1 << 8) /* OTG Polarity of Overcurrent */
-#define UCTRL_OVER_CUR_DIS     (1 << 7) /* Disable OTG Overcurrent Detection */
-
-#define PLL_USB_EN_USB_CLKS_MASK       (0x01 << 6)
-#define PLL_USB_PWR_MASK               (0x01 << 12)
-#define PLL_USB_ENABLE_MASK            (0x01 << 13)
-#define PLL_USB_BYPASS_MASK            (0x01 << 16)
-#define PLL_USB_REG_ENABLE_MASK                (0x01 << 21)
-#define PLL_USB_DIV_SEL_MASK           (0x07 << 22)
-#define PLL_USB_LOCK_MASK              (0x01 << 31)
-
-/* USBCMD */
-#define UCMD_RUN_STOP           (1 << 0) /* controller run/stop */
-#define UCMD_RESET             (1 << 1) /* controller reset */
-
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8)
-static const ulong phy_bases[] = {
-       USB_PHY0_BASE_ADDR,
-#if defined(USB_PHY1_BASE_ADDR)
-       USB_PHY1_BASE_ADDR,
-#endif
-};
-
-static void usb_internal_phy_clock_gate(int index, int on)
-{
-       void __iomem *phy_reg;
-
-       if (index >= ARRAY_SIZE(phy_bases))
-               return;
-
-       phy_reg = (void __iomem *)phy_bases[index];
-       phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
-       writel(USBPHY_CTRL_CLKGATE, phy_reg);
-}
-
-static void usb_power_config(int index)
-{
-#if defined(CONFIG_MX7ULP)
-       struct usbphy_regs __iomem *usbphy =
-               (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
-
-       if (index > 0)
-               return;
-
-       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
-                  ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
-                  &usbphy->usb1_chrg_detect);
-
-       scg_enable_usb_pll(true);
-
-#elif defined(CONFIG_IMX8)
-       struct usbphy_regs __iomem *usbphy =
-               (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
-       int timeout = 1000000;
-
-       if (index > 0)
-               return;
-
-       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
-                  ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
-                  &usbphy->usb1_chrg_detect);
-
-       if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) {
-
-               /* Enable the regulator first */
-               writel(PLL_USB_REG_ENABLE_MASK,
-                      &usbphy->usb1_pll_480_ctrl_set);
-
-               /* Wait at least 25us */
-               udelay(25);
-
-               /* Enable the power */
-               writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set);
-
-               /* Wait lock */
-               while (timeout--) {
-                       if (readl(&usbphy->usb1_pll_480_ctrl) &
-                           PLL_USB_LOCK_MASK)
-                               break;
-                       udelay(10);
-               }
-
-               if (timeout <= 0) {
-                       /* If timeout, we power down the pll */
-                       writel(PLL_USB_PWR_MASK,
-                              &usbphy->usb1_pll_480_ctrl_clr);
-                       return;
-               }
-       }
-
-       /* Clear the bypass */
-       writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr);
-
-       /* Enable the PLL clock out to USB */
-       writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK),
-              &usbphy->usb1_pll_480_ctrl_set);
-
-#else
-       struct anatop_regs __iomem *anatop =
-               (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
-       void __iomem *chrg_detect;
-       void __iomem *pll_480_ctrl_clr;
-       void __iomem *pll_480_ctrl_set;
-
-       switch (index) {
-       case 0:
-               chrg_detect = &anatop->usb1_chrg_detect;
-               pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr;
-               pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set;
-               break;
-       case 1:
-               chrg_detect = &anatop->usb2_chrg_detect;
-               pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr;
-               pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set;
-               break;
-       default:
-               return;
-       }
-       /*
-        * Some phy and power's special controls
-        * 1. The external charger detector needs to be disabled
-        * or the signal at DP will be poor
-        * 2. The PLL's power and output to usb
-        * is totally controlled by IC, so the Software only needs
-        * to enable them at initializtion.
-        */
-       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
-                    ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
-                    chrg_detect);
-
-       writel(ANADIG_USB2_PLL_480_CTRL_BYPASS,
-                    pll_480_ctrl_clr);
-
-       writel(ANADIG_USB2_PLL_480_CTRL_ENABLE |
-                    ANADIG_USB2_PLL_480_CTRL_POWER |
-                    ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
-                    pll_480_ctrl_set);
-
-#endif
-}
-
-/* Return 0 : host node, <>0 : device mode */
-static int usb_phy_enable(int index, struct usb_ehci *ehci)
-{
-       void __iomem *phy_reg;
-       void __iomem *phy_ctrl;
-       void __iomem *usb_cmd;
-       int ret;
-
-       if (index >= ARRAY_SIZE(phy_bases))
-               return 0;
-
-       phy_reg = (void __iomem *)phy_bases[index];
-       phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
-       usb_cmd = (void __iomem *)&ehci->usbcmd;
-
-       /* Stop then Reset */
-       clrbits_le32(usb_cmd, UCMD_RUN_STOP);
-       ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
-       if (ret)
-               return ret;
-
-       setbits_le32(usb_cmd, UCMD_RESET);
-       ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
-       if (ret)
-               return ret;
-
-       /* Reset USBPHY module */
-       setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
-       udelay(10);
-
-       /* Remove CLKGATE and SFTRST */
-       clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
-       udelay(10);
-
-       /* Power up the PHY */
-       writel(0, phy_reg + USBPHY_PWD);
-       /* enable FS/LS device */
-       setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
-                       USBPHY_CTRL_ENUTMILEVEL3);
-
-       return 0;
-}
-
-int usb_phy_mode(int port)
-{
-       void __iomem *phy_reg;
-       void __iomem *phy_ctrl;
-       u32 val;
-
-       phy_reg = (void __iomem *)phy_bases[port];
-       phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
-
-       val = readl(phy_ctrl);
-
-       if (val & USBPHY_CTRL_OTG_ID)
-               return USB_INIT_DEVICE;
-       else
-               return USB_INIT_HOST;
-}
-
-#if defined(CONFIG_MX7ULP)
-struct usbnc_regs {
-       u32 ctrl1;
-       u32 ctrl2;
-       u32 reserve0[2];
-       u32 hsic_ctrl;
-};
-#elif defined(CONFIG_IMX8)
-struct usbnc_regs {
-       u32 ctrl1;
-       u32 ctrl2;
-       u32 reserve1[10];
-       u32 phy_cfg1;
-       u32 phy_cfg2;
-       u32 reserve2;
-       u32 phy_status;
-       u32 reserve3[4];
-       u32 adp_cfg1;
-       u32 adp_cfg2;
-       u32 adp_status;
-};
-#else
-/* Base address for this IP block is 0x02184800 */
-struct usbnc_regs {
-       u32     ctrl[4];        /* otg/host1-3 */
-       u32     uh2_hsic_ctrl;
-       u32     uh3_hsic_ctrl;
-       u32     otg_phy_ctrl_0;
-       u32     uh1_phy_ctrl_0;
-};
-#endif
-
-#elif defined(CONFIG_USB_EHCI_MX7)
-struct usbnc_regs {
-       u32 ctrl1;
-       u32 ctrl2;
-       u32 reserve1[10];
-       u32 phy_cfg1;
-       u32 phy_cfg2;
-       u32 reserve2;
-       u32 phy_status;
-       u32 reserve3[4];
-       u32 adp_cfg1;
-       u32 adp_cfg2;
-       u32 adp_status;
-};
-
-static void usb_power_config(int index)
-{
-       struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR +
-                       (0x10000 * index) + USBNC_OFFSET);
-       void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
-
-       /*
-        * Clear the ACAENB to enable usb_otg_id detection,
-        * otherwise it is the ACA detection enabled.
-        */
-       clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
-}
-
-int usb_phy_mode(int port)
-{
-       struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR +
-                       (0x10000 * port) + USBNC_OFFSET);
-       void __iomem *status = (void __iomem *)(&usbnc->phy_status);
-       u32 val;
-
-       val = readl(status);
-
-       if (val & USBNC_PHYSTATUS_ID_DIG)
-               return USB_INIT_DEVICE;
-       else
-               return USB_INIT_HOST;
-}
-#endif
-
 static void ehci_mx6_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
                                   uint32_t *reg)
 {
@@ -348,35 +53,6 @@ static void ehci_mx6_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
        *reg = ehci_readl(status_reg);
 }
 
-static void usb_oc_config(int index)
-{
-#if defined(CONFIG_MX6)
-       struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
-                       USB_OTHERREGS_OFFSET);
-       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
-#elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8)
-       struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR +
-                       (0x10000 * index) + USBNC_OFFSET);
-       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1);
-#endif
-
-#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);
-
-       /* Set power polarity to high active */
-#ifdef CONFIG_MXC_USB_OTG_HACTIVE
-       setbits_le32(ctrl, UCTRL_PWR_POL);
-#else
-       clrbits_le32(ctrl, UCTRL_PWR_POL);
-#endif
-}
-
 /**
  * board_usb_phy_mode - override usb phy mode
  * @port:      usb host/otg port
@@ -394,20 +70,6 @@ int __weak board_usb_phy_mode(int port)
        return usb_phy_mode(port);
 }
 
-/**
- * board_ehci_hcd_init - set usb vbus voltage
- * @port:      usb otg port
- *
- * Target board specific, setup iomux pad to setup supply vbus voltage
- * for usb otg port. Machine board file overrides board_ehci_hcd_init
- *
- * Return: 0 Success
- */
-int __weak board_ehci_hcd_init(int port)
-{
-       return 0;
-}
-
 /**
  * board_ehci_power - enables/disables usb vbus voltage
  * @port:      usb otg port
@@ -423,36 +85,6 @@ int __weak board_ehci_power(int port, int on)
        return 0;
 }
 
-int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
-{
-       int ret;
-       u32 portsc;
-
-       enable_usboh3_clk(1);
-       mdelay(1);
-
-       portsc = readl(&ehci->portsc);
-       if (portsc & PORT_PTS_PHCD) {
-               debug("suspended: portsc %x, enabled it.\n", portsc);
-               clrbits_le32(&ehci->portsc, PORT_PTS_PHCD);
-       }
-
-       /* Do board specific initialization */
-       ret = board_ehci_hcd_init(index);
-       if (ret)
-               return ret;
-
-       usb_power_config(index);
-       usb_oc_config(index);
-
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8)
-       usb_internal_phy_clock_gate(index, 1);
-       usb_phy_enable(index, ehci);
-#endif
-
-       return 0;
-}
-
 #if !CONFIG_IS_ENABLED(DM_USB)
 static const struct ehci_ops mx6_ehci_ops = {
        .powerup_fixup          = ehci_mx6_powerup_fixup,
diff --git a/drivers/usb/imx/Makefile b/drivers/usb/imx/Makefile
new file mode 100644 (file)
index 0000000..30c06b7
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2019 NXP
+#
+
+obj-$(CONFIG_USB_EHCI_MX6) += usb-mx6-common.o
+obj-$(CONFIG_USB_EHCI_MX7) += usb-mx6-common.o
+obj-$(CONFIG_CI_UDC) += usb-mx6-common.o
diff --git a/drivers/usb/imx/usb-mx6-common.c b/drivers/usb/imx/usb-mx6-common.c
new file mode 100644 (file)
index 0000000..42b9484
--- /dev/null
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ *
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <errno.h>
+#include <wait_bit.h>
+#include <linux/compiler.h>
+#include <usb/ehci-ci.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/mach-imx/iomux-v3.h>
+#include <asm/mach-imx/regs-usbphy.h>
+#include <asm/mach-imx/sys_proto.h>
+#include <asm/mach-types.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define USB_OTGREGS_OFFSET     0x000
+#define USB_H1REGS_OFFSET      0x200
+#define USB_H2REGS_OFFSET      0x400
+#define USB_H3REGS_OFFSET      0x600
+#define USB_OTHERREGS_OFFSET   0x800
+
+#define USB_H1_CTRL_OFFSET     0x04
+
+#define ANADIG_USB2_CHRG_DETECT_EN_B           0x00100000
+#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B     0x00080000
+
+#define ANADIG_USB2_PLL_480_CTRL_BYPASS                0x00010000
+#define ANADIG_USB2_PLL_480_CTRL_ENABLE                0x00002000
+#define ANADIG_USB2_PLL_480_CTRL_POWER         0x00001000
+#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS   0x00000040
+
+#define USBNC_OFFSET           0x200
+#define USBNC_PHYCFG2_ACAENB   (1 << 4) /* otg_id detection enable */
+#define UCTRL_PWR_POL          (1 << 9) /* OTG Polarity of Power Pin */
+#define UCTRL_OVER_CUR_POL     (1 << 8) /* OTG Polarity of Overcurrent */
+#define UCTRL_OVER_CUR_DIS     (1 << 7) /* Disable OTG Overcurrent Detection */
+
+#define PLL_USB_EN_USB_CLKS_MASK       (0x01 << 6)
+#define PLL_USB_PWR_MASK               (0x01 << 12)
+#define PLL_USB_ENABLE_MASK            (0x01 << 13)
+#define PLL_USB_BYPASS_MASK            (0x01 << 16)
+#define PLL_USB_REG_ENABLE_MASK                (0x01 << 21)
+#define PLL_USB_DIV_SEL_MASK           (0x07 << 22)
+#define PLL_USB_LOCK_MASK              (0x01 << 31)
+
+/* USBCMD */
+#define UCMD_RUN_STOP           (1 << 0) /* controller run/stop */
+#define UCMD_RESET             (1 << 1) /* controller reset */
+
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8)
+static const ulong phy_bases[] = {
+       USB_PHY0_BASE_ADDR,
+#if defined(USB_PHY1_BASE_ADDR)
+       USB_PHY1_BASE_ADDR,
+#endif
+};
+
+static void usb_internal_phy_clock_gate(int index, int on)
+{
+       void __iomem *phy_reg;
+
+       if (index >= ARRAY_SIZE(phy_bases))
+               return;
+
+       phy_reg = (void __iomem *)phy_bases[index];
+       phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
+       writel(USBPHY_CTRL_CLKGATE, phy_reg);
+}
+
+static void usb_power_config(int index)
+{
+#if defined(CONFIG_MX7ULP)
+       struct usbphy_regs __iomem *usbphy =
+               (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
+
+       if (index > 0)
+               return;
+
+       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
+                  ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
+                  &usbphy->usb1_chrg_detect);
+
+       scg_enable_usb_pll(true);
+
+#elif defined(CONFIG_IMX8)
+       struct usbphy_regs __iomem *usbphy =
+               (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
+       int timeout = 1000000;
+
+       if (index > 0)
+               return;
+
+       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
+                  ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
+                  &usbphy->usb1_chrg_detect);
+
+       if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) {
+
+               /* Enable the regulator first */
+               writel(PLL_USB_REG_ENABLE_MASK,
+                      &usbphy->usb1_pll_480_ctrl_set);
+
+               /* Wait at least 25us */
+               udelay(25);
+
+               /* Enable the power */
+               writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set);
+
+               /* Wait lock */
+               while (timeout--) {
+                       if (readl(&usbphy->usb1_pll_480_ctrl) &
+                           PLL_USB_LOCK_MASK)
+                               break;
+                       udelay(10);
+               }
+
+               if (timeout <= 0) {
+                       /* If timeout, we power down the pll */
+                       writel(PLL_USB_PWR_MASK,
+                              &usbphy->usb1_pll_480_ctrl_clr);
+                       return;
+               }
+       }
+
+       /* Clear the bypass */
+       writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr);
+
+       /* Enable the PLL clock out to USB */
+       writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK),
+              &usbphy->usb1_pll_480_ctrl_set);
+
+#else
+       struct anatop_regs __iomem *anatop =
+               (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
+       void __iomem *chrg_detect;
+       void __iomem *pll_480_ctrl_clr;
+       void __iomem *pll_480_ctrl_set;
+
+       switch (index) {
+       case 0:
+               chrg_detect = &anatop->usb1_chrg_detect;
+               pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr;
+               pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set;
+               break;
+       case 1:
+               chrg_detect = &anatop->usb2_chrg_detect;
+               pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr;
+               pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set;
+               break;
+       default:
+               return;
+       }
+       /*
+        * Some phy and power's special controls
+        * 1. The external charger detector needs to be disabled
+        * or the signal at DP will be poor
+        * 2. The PLL's power and output to usb
+        * is totally controlled by IC, so the Software only needs
+        * to enable them at initializtion.
+        */
+       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
+                    ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
+                    chrg_detect);
+
+       writel(ANADIG_USB2_PLL_480_CTRL_BYPASS,
+                    pll_480_ctrl_clr);
+
+       writel(ANADIG_USB2_PLL_480_CTRL_ENABLE |
+                    ANADIG_USB2_PLL_480_CTRL_POWER |
+                    ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
+                    pll_480_ctrl_set);
+
+#endif
+}
+
+/* Return 0 : host node, <>0 : device mode */
+static int usb_phy_enable(int index, struct usb_ehci *ehci)
+{
+       void __iomem *phy_reg;
+       void __iomem *phy_ctrl;
+       void __iomem *usb_cmd;
+       int ret;
+
+       if (index >= ARRAY_SIZE(phy_bases))
+               return 0;
+
+       phy_reg = (void __iomem *)phy_bases[index];
+       phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
+       usb_cmd = (void __iomem *)&ehci->usbcmd;
+
+       /* Stop then Reset */
+       clrbits_le32(usb_cmd, UCMD_RUN_STOP);
+       ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
+       if (ret)
+               return ret;
+
+       setbits_le32(usb_cmd, UCMD_RESET);
+       ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
+       if (ret)
+               return ret;
+
+       /* Reset USBPHY module */
+       setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
+       udelay(10);
+
+       /* Remove CLKGATE and SFTRST */
+       clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
+       udelay(10);
+
+       /* Power up the PHY */
+       writel(0, phy_reg + USBPHY_PWD);
+       /* enable FS/LS device */
+       setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
+                       USBPHY_CTRL_ENUTMILEVEL3);
+
+       return 0;
+}
+
+int usb_phy_mode(int port)
+{
+       void __iomem *phy_reg;
+       void __iomem *phy_ctrl;
+       u32 val;
+
+       if (port >= ARRAY_SIZE(phy_bases))
+               return USB_INIT_HOST;
+
+       phy_reg = (void __iomem *)phy_bases[port];
+       phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
+
+       val = readl(phy_ctrl);
+
+       if (val & USBPHY_CTRL_OTG_ID)
+               return USB_INIT_DEVICE;
+       else
+               return USB_INIT_HOST;
+}
+
+#if defined(CONFIG_MX7ULP)
+struct usbnc_regs {
+       u32 ctrl1;
+       u32 ctrl2;
+       u32 reserve0[2];
+       u32 hsic_ctrl;
+};
+#elif defined(CONFIG_IMX8)
+struct usbnc_regs {
+       u32 ctrl1;
+       u32 ctrl2;
+       u32 reserve1[10];
+       u32 phy_cfg1;
+       u32 phy_cfg2;
+       u32 reserve2;
+       u32 phy_status;
+       u32 reserve3[4];
+       u32 adp_cfg1;
+       u32 adp_cfg2;
+       u32 adp_status;
+};
+#else
+/* Base address for this IP block is 0x02184800 */
+struct usbnc_regs {
+       u32     ctrl[4];        /* otg/host1-3 */
+       u32     uh2_hsic_ctrl;
+       u32     uh3_hsic_ctrl;
+       u32     otg_phy_ctrl_0;
+       u32     uh1_phy_ctrl_0;
+};
+#endif
+
+#elif defined(CONFIG_USB_EHCI_MX7)
+struct usbnc_regs {
+       u32 ctrl1;
+       u32 ctrl2;
+       u32 reserve1[10];
+       u32 phy_cfg1;
+       u32 phy_cfg2;
+       u32 reserve2;
+       u32 phy_status;
+       u32 reserve3[4];
+       u32 adp_cfg1;
+       u32 adp_cfg2;
+       u32 adp_status;
+};
+
+static void usb_power_config(int index)
+{
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR +
+                       (0x10000 * index) + USBNC_OFFSET);
+       void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
+
+       /*
+        * Clear the ACAENB to enable usb_otg_id detection,
+        * otherwise it is the ACA detection enabled.
+        */
+       clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
+}
+
+int usb_phy_mode(int port)
+{
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR +
+                       (0x10000 * port) + USBNC_OFFSET);
+       void __iomem *status = (void __iomem *)(&usbnc->phy_status);
+       u32 val;
+
+       val = readl(status);
+
+       if (val & USBNC_PHYSTATUS_ID_DIG)
+               return USB_INIT_DEVICE;
+       else
+               return USB_INIT_HOST;
+}
+#endif
+
+static void usb_oc_config(int index)
+{
+#if defined(CONFIG_MX6)
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+                       USB_OTHERREGS_OFFSET);
+       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
+#elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8)
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR +
+                       (0x10000 * index) + USBNC_OFFSET);
+       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1);
+#endif
+
+#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);
+
+       /* Set power polarity to high active */
+#ifdef CONFIG_MXC_USB_OTG_HACTIVE
+       setbits_le32(ctrl, UCTRL_PWR_POL);
+#else
+       clrbits_le32(ctrl, UCTRL_PWR_POL);
+#endif
+}
+
+/**
+ * board_ehci_hcd_init - set usb vbus voltage
+ * @port:      usb otg port
+ *
+ * Target board specific, setup iomux pad to setup supply vbus voltage
+ * for usb otg port. Machine board file overrides board_ehci_hcd_init
+ *
+ * Return: 0 Success
+ */
+int __weak board_ehci_hcd_init(int port)
+{
+       return 0;
+}
+
+int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
+{
+       int ret;
+       u32 portsc;
+
+       enable_usboh3_clk(1);
+       mdelay(1);
+
+       portsc = readl(&ehci->portsc);
+       if (portsc & PORT_PTS_PHCD) {
+               debug("suspended: portsc %x, enabled it.\n", portsc);
+               clrbits_le32(&ehci->portsc, PORT_PTS_PHCD);
+       }
+
+       /* Do board specific initialization */
+       ret = board_ehci_hcd_init(index);
+       if (ret)
+               return ret;
+
+       usb_power_config(index);
+       usb_oc_config(index);
+
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8)
+       usb_internal_phy_clock_gate(index, 1);
+       usb_phy_enable(index, ehci);
+#endif
+
+       return 0;
+}
index ddae8e1..f72f688 100644 (file)
@@ -12,5 +12,4 @@
 #define EP_MAX_PACKET_SIZE     0x200
 #define EP0_MAX_PACKET_SIZE    64
 
-int ehci_mx6_common_init(struct usb_ehci *ehci, int index);
 #endif /* __CI_UDC_H__ */
diff --git a/include/usb/usb_mx6_common.h b/include/usb/usb_mx6_common.h
new file mode 100644 (file)
index 0000000..39751fd
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ *
+ */
+
+#ifndef __USB_MX6_COMMON_H__
+#define __USB_MX6_COMMON_H__
+#include <usb/ehci-ci.h>
+
+int ehci_mx6_common_init(struct usb_ehci *ehci, int index);
+#endif /* __USB_MX6_COMMON_H__ */
index 1fd63ef..8f502fd 100644 (file)
@@ -99,6 +99,7 @@ endif
 libs-y += drivers/
 libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
 libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
+libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/imx/
 libs-y += dts/
 libs-y += fs/
 libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/