summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-04-18 15:46:58 +0300
committerTom Rini <trini@konsulko.com>2021-04-18 15:46:58 +0300
commitc6ae5e9869cf7a9fbf1c9cec5aaa3fd5b8def670 (patch)
tree8e2c23a2a0d6b1fee0c86a6202ce1ec8d65b2be7 /drivers
parent2fbc804715b7de41e5b378a7f61adc760c7836a1 (diff)
parentd08cdc223db1023ebb8c03d6341fdf45b303700c (diff)
downloadu-boot-c6ae5e9869cf7a9fbf1c9cec5aaa3fd5b8def670.tar.xz
Merge https://source.denx.de/u-boot/custodians/u-boot-usb
This is a patchset which makes away with the .bind() controller indexing workaround which was broken since before v2021.04, and then adds PHY support and MX8M support on top of that. Better add it into the release early to get as much testing as possible done, because this really does a lot of changes to the ehci-mx6 driver.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/phy/nop-phy.c1
-rw-r--r--drivers/power/domain/imx8m-power-domain.c2
-rw-r--r--drivers/usb/host/Kconfig4
-rw-r--r--drivers/usb/host/ehci-mx6.c454
4 files changed, 285 insertions, 176 deletions
diff --git a/drivers/phy/nop-phy.c b/drivers/phy/nop-phy.c
index 84aac80623..9f12ebc062 100644
--- a/drivers/phy/nop-phy.c
+++ b/drivers/phy/nop-phy.c
@@ -43,6 +43,7 @@ static int nop_phy_probe(struct udevice *dev)
static const struct udevice_id nop_phy_ids[] = {
{ .compatible = "nop-phy" },
+ { .compatible = "usb-nop-xceiv" },
{ }
};
diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c
index c4cd07ffaf..5d34bc1290 100644
--- a/drivers/power/domain/imx8m-power-domain.c
+++ b/drivers/power/domain/imx8m-power-domain.c
@@ -120,6 +120,8 @@ static int imx8m_power_domain_of_to_plat(struct udevice *dev)
static const struct udevice_id imx8m_power_domain_ids[] = {
{ .compatible = "fsl,imx8mq-gpc" },
+ { .compatible = "fsl,imx8mm-gpc" },
+ { .compatible = "fsl,imx8mn-gpc" },
{ }
};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0971a7c813..bf5d82f035 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -156,7 +156,9 @@ config USB_EHCI_MX6
config USB_EHCI_MX7
bool "Support for i.MX7 on-chip EHCI USB controller"
- depends on ARCH_MX7
+ depends on ARCH_MX7 || IMX8M
+ select PHY if IMX8M
+ select NOP_PHY if IMX8M
default y
---help---
Enables support for the on-chip EHCI controller on i.MX7 SoCs.
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index aeea539999..7642a31b65 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -5,6 +5,7 @@
*/
#include <common.h>
+#include <clk.h>
#include <log.h>
#include <usb.h>
#include <errno.h>
@@ -67,49 +68,41 @@ DECLARE_GLOBAL_DATA_PTR;
#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
#define UCMD_RESET (1 << 1) /* controller reset */
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
-static const unsigned phy_bases[] = {
- USB_PHY0_BASE_ADDR,
-#if defined(USB_PHY1_BASE_ADDR)
- USB_PHY1_BASE_ADDR,
+/* 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)
#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);
-}
+/* 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;
+ u32 reserve1[4];
+ 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)
+#if defined(CONFIG_MX6) && !defined(CONFIG_PHY)
+static void usb_power_config_mx6(struct anatop_regs __iomem *anatop,
+ int anatop_bits_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);
-
-#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) {
+ if (!is_mx6())
+ return;
+
+ switch (anatop_bits_index) {
case 0:
chrg_detect = &anatop->usb1_chrg_detect;
pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr;
@@ -142,22 +135,70 @@ static void usb_power_config(int index)
ANADIG_USB2_PLL_480_CTRL_POWER |
ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
pll_480_ctrl_set);
+}
+#else
+static void __maybe_unused
+usb_power_config_mx6(void *anatop, int anatop_bits_index) { }
+#endif
+
+#if defined(CONFIG_MX7) && !defined(CONFIG_PHY)
+static void usb_power_config_mx7(struct usbnc_regs *usbnc)
+{
+ void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
+
+ if (!is_mx7())
+ return;
+
+ /*
+ * Clear the ACAENB to enable usb_otg_id detection,
+ * otherwise it is the ACA detection enabled.
+ */
+ clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
+}
+#else
+static void __maybe_unused
+usb_power_config_mx7(void *usbnc) { }
+#endif
+
+#if defined(CONFIG_MX7ULP) && !defined(CONFIG_PHY)
+static void usb_power_config_mx7ulp(struct usbphy_regs __iomem *usbphy)
+{
+ if (!is_mx7ulp())
+ return;
+
+ writel(ANADIG_USB2_CHRG_DETECT_EN_B |
+ ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
+ &usbphy->usb1_chrg_detect);
+ scg_enable_usb_pll(true);
+}
+#else
+static void __maybe_unused
+usb_power_config_mx7ulp(void *usbphy) { }
#endif
+
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+static const unsigned phy_bases[] = {
+ USB_PHY0_BASE_ADDR,
+#if defined(USB_PHY1_BASE_ADDR)
+ USB_PHY1_BASE_ADDR,
+#endif
+};
+
+#if !defined(CONFIG_PHY)
+static void usb_internal_phy_clock_gate(void __iomem *phy_reg, int on)
+{
+ phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
+ writel(USBPHY_CTRL_CLKGATE, phy_reg);
}
/* Return 0 : host node, <>0 : device mode */
-static int usb_phy_enable(int index, struct usb_ehci *ehci)
+static int usb_phy_enable(struct usb_ehci *ehci, void __iomem *phy_reg)
{
- 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;
@@ -188,6 +229,7 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci)
return 0;
}
+#endif
int usb_phy_mode(int port)
{
@@ -206,52 +248,7 @@ int usb_phy_mode(int port)
return USB_INIT_HOST;
}
-#if defined(CONFIG_MX7ULP)
-struct usbnc_regs {
- u32 ctrl1;
- u32 ctrl2;
- u32 reserve0[2];
- u32 hsic_ctrl;
-};
-#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_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 *)(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 *)(USB_BASE_ADDR +
@@ -268,17 +265,9 @@ int usb_phy_mode(int port)
}
#endif
-static void usb_oc_config(int index)
+static void usb_oc_config(struct usbnc_regs *usbnc, 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_MX7) || defined(CONFIG_MX7ULP)
- struct usbnc_regs *usbnc = (struct usbnc_regs *)(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*/
@@ -297,6 +286,7 @@ static void usb_oc_config(int index)
#endif
}
+#if !CONFIG_IS_ENABLED(DM_USB)
/**
* board_usb_phy_mode - override usb phy mode
* @port: usb host/otg port
@@ -343,38 +333,26 @@ int __weak board_ehci_power(int port, int on)
return 0;
}
-int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
-{
- int ret;
-
- enable_usboh3_clk(1);
- mdelay(1);
-
- /* 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)
- usb_internal_phy_clock_gate(index, 1);
- usb_phy_enable(index, ehci);
-#endif
-
- return 0;
-}
-
-#if !CONFIG_IS_ENABLED(DM_USB)
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)
u32 controller_spacing = 0x200;
-#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP)
+ struct anatop_regs __iomem *anatop =
+ (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ USB_OTHERREGS_OFFSET);
+#elif defined(CONFIG_MX7)
u32 controller_spacing = 0x10000;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ (0x10000 * index) + USBNC_OFFSET);
+#elif defined(CONFIG_MX7ULP)
+ u32 controller_spacing = 0x10000;
+ struct usbphy_regs __iomem *usbphy =
+ (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ (0x10000 * index) + USBNC_OFFSET);
#endif
struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR +
(controller_spacing * index));
@@ -391,15 +369,38 @@ int ehci_hcd_init(int index, enum usb_init_type init,
}
}
- ret = ehci_mx6_common_init(ehci, index);
- if (ret)
+ enable_usboh3_clk(1);
+ mdelay(1);
+
+ /* Do board specific initialization */
+ ret = board_ehci_hcd_init(index);
+ if (ret) {
+ enable_usboh3_clk(0);
return ret;
+ }
+
+#if defined(CONFIG_MX6)
+ usb_power_config_mx6(anatop, index);
+#elif defined (CONFIG_MX7)
+ usb_power_config_mx7(usbnc);
+#elif defined (CONFIG_MX7ULP)
+ usb_power_config_mx7ulp(usbphy);
+#endif
+
+ usb_oc_config(usbnc, index);
+
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+ 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]);
+ }
+#endif
type = board_usb_phy_mode(index);
if (hccr && hcor) {
- *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
+ *hccr = (struct ehci_hccr *)((uintptr_t)&ehci->caplength);
+ *hcor = (struct ehci_hcor *)((uintptr_t)*hccr +
HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
}
@@ -428,8 +429,13 @@ struct ehci_mx6_priv_data {
struct ehci_ctrl ctrl;
struct usb_ehci *ehci;
struct udevice *vbus_supply;
+ struct clk clk;
+ struct phy phy;
enum usb_init_type init_type;
int portnr;
+ void __iomem *phy_addr;
+ void __iomem *misc_addr;
+ void __iomem *anatop_addr;
};
static int mx6_init_after_reset(struct ehci_ctrl *dev)
@@ -437,14 +443,23 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev)
struct ehci_mx6_priv_data *priv = dev->priv;
enum usb_init_type type = priv->init_type;
struct usb_ehci *ehci = priv->ehci;
- int ret;
- ret = ehci_mx6_common_init(priv->ehci, priv->portnr);
- if (ret)
- return ret;
+#if !defined(CONFIG_PHY)
+ usb_power_config_mx6(priv->anatop_addr, priv->portnr);
+ usb_power_config_mx7(priv->misc_addr);
+ usb_power_config_mx7ulp(priv->phy_addr);
+#endif
+
+ usb_oc_config(priv->misc_addr, priv->portnr);
+
+#if !defined(CONFIG_PHY) && (defined(CONFIG_MX6) || defined(CONFIG_MX7ULP))
+ usb_internal_phy_clock_gate(priv->phy_addr, 1);
+ usb_phy_enable(ehci, priv->phy_addr);
+#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
if (priv->vbus_supply) {
+ int ret;
ret = regulator_set_enable(priv->vbus_supply,
(type == USB_INIT_DEVICE) ?
false : true);
@@ -541,46 +556,58 @@ static int ehci_usb_of_to_plat(struct udevice *dev)
return 0;
}
-static int ehci_usb_bind(struct udevice *dev)
+static int mx6_parse_dt_addrs(struct udevice *dev)
{
- /*
- * TODO:
- * This driver is only partly converted to DT probing and still uses
- * a tremendous amount of hard-coded addresses. To make things worse,
- * the driver depends on specific sequential indexing of controllers,
- * from which it derives offsets in the PHY and ANATOP register sets.
- *
- * Here we attempt to calculate these indexes from DT information as
- * well as we can. The USB controllers on all existing iMX6 SoCs
- * are placed next to each other, at addresses incremented by 0x200,
- * and iMX7 their addresses are shifted by 0x10000.
- * Thus, the index is derived from the multiple of 0x200 (0x10000 for
- * iMX7) offset from the first controller address.
- *
- * However, to complete conversion of this driver to DT probing, the
- * following has to be done:
- * - DM clock framework support for iMX must be implemented
- * - usb_power_config() has to be converted to clock framework
- * -> Thus, the ad-hoc "index" variable goes away.
- * - USB PHY handling has to be factored out into separate driver
- * -> Thus, the ad-hoc "index" variable goes away from the PHY
- * code, the PHY driver must parse it's address from DT. This
- * USB driver must find the PHY driver via DT phandle.
- * -> usb_power_config() shall be moved to PHY driver
- * With these changes in place, the ad-hoc indexing goes away and
- * the driver is fully converted to DT probing.
- */
+ struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
+ int phy_off, misc_off;
+ const void *blob = gd->fdt_blob;
+ int offset = dev_of_offset(dev);
+ void *__iomem addr;
+ int ret, devnump;
- /*
- * FIXME: This cannot work with the new sequence numbers.
- * Please complete the DM conversion.
- *
- * u32 controller_spacing = is_mx7() ? 0x10000 : 0x200;
- * fdt_addr_t addr = devfdt_get_addr_index(dev, 0);
- *
- * dev->req_seq = (addr - USB_BASE_ADDR) / controller_spacing;
- */
+ phy_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbphy");
+ if (phy_off < 0) {
+ phy_off = fdtdec_lookup_phandle(blob, offset, "phys");
+ if (phy_off < 0)
+ 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;
+
+ 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)
+ return -EINVAL;
+
+ priv->misc_addr = addr;
+
+#if !defined(CONFIG_PHY) && defined(CONFIG_MX6)
+ int anatop_off;
+
+ /* Resolve ANATOP offset through USB PHY node */
+ anatop_off = fdtdec_lookup_phandle(blob, phy_off, "fsl,anatop");
+ if (anatop_off < 0)
+ return -EINVAL;
+
+ addr = (void __iomem *)fdtdec_get_addr(blob, anatop_off, "reg");
+ if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->anatop_addr = addr;
+#endif
return 0;
}
@@ -602,19 +629,46 @@ static int ehci_usb_probe(struct udevice *dev)
}
}
+ ret = mx6_parse_dt_addrs(dev);
+ if (ret)
+ return ret;
+
priv->ehci = ehci;
- priv->portnr = dev_seq(dev);
priv->init_type = type;
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&priv->clk);
+ if (ret)
+ return ret;
+#else
+ /* Compatibility with DM_USB and !CLK */
+ enable_usboh3_clk(1);
+ mdelay(1);
+#endif
+
#if CONFIG_IS_ENABLED(DM_REGULATOR)
ret = device_get_supply_regulator(dev, "vbus-supply",
&priv->vbus_supply);
if (ret)
debug("%s: No vbus supply\n", dev->name);
#endif
- ret = ehci_mx6_common_init(ehci, priv->portnr);
- if (ret)
- return ret;
+
+#if !defined(CONFIG_PHY)
+ usb_power_config_mx6(priv->anatop_addr, priv->portnr);
+ usb_power_config_mx7(priv->misc_addr);
+ usb_power_config_mx7ulp(priv->phy_addr);
+#endif
+
+ usb_oc_config(priv->misc_addr, priv->portnr);
+
+#if !defined(CONFIG_PHY) && (defined(CONFIG_MX6) || defined(CONFIG_MX7ULP))
+ usb_internal_phy_clock_gate(priv->phy_addr, 1);
+ usb_phy_enable(ehci, priv->phy_addr);
+#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
if (priv->vbus_supply) {
@@ -623,7 +677,7 @@ static int ehci_usb_probe(struct udevice *dev)
false : true);
if (ret && ret != -ENOSYS) {
printf("Error enabling VBUS supply (ret=%i)\n", ret);
- return ret;
+ goto err_clk;
}
}
#endif
@@ -636,15 +690,66 @@ static int ehci_usb_probe(struct udevice *dev)
mdelay(10);
- hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- hcor = (struct ehci_hcor *)((uint32_t)hccr +
+#if defined(CONFIG_PHY)
+ ret = ehci_setup_phy(dev, &priv->phy, 0);
+ if (ret)
+ goto err_regulator;
+#endif
+
+ hccr = (struct ehci_hccr *)((uintptr_t)&ehci->caplength);
+ hcor = (struct ehci_hcor *)((uintptr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
- return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type);
+ ret = ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type);
+ if (ret)
+ goto err_phy;
+
+ return ret;
+
+err_phy:
+#if defined(CONFIG_PHY)
+ ehci_shutdown_phy(dev, &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
+#if CONFIG_IS_ENABLED(CLK)
+ clk_disable(&priv->clk);
+#else
+ /* Compatibility with DM_USB and !CLK */
+ enable_usboh3_clk(0);
+#endif
+ return ret;
+}
+
+int ehci_usb_remove(struct udevice *dev)
+{
+ struct ehci_mx6_priv_data *priv __maybe_unused = dev_get_priv(dev);
+
+ ehci_deregister(dev);
+
+#if defined(CONFIG_PHY)
+ ehci_shutdown_phy(dev, &priv->phy);
+#endif
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->vbus_supply)
+ regulator_set_enable(priv->vbus_supply, false);
+#endif
+
+#if CONFIG_IS_ENABLED(CLK)
+ clk_disable(&priv->clk);
+#endif
+
+ return 0;
}
static const struct udevice_id mx6_usb_ids[] = {
{ .compatible = "fsl,imx27-usb" },
+ { .compatible = "fsl,imx7d-usb" },
{ }
};
@@ -653,9 +758,8 @@ U_BOOT_DRIVER(usb_mx6) = {
.id = UCLASS_USB,
.of_match = mx6_usb_ids,
.of_to_plat = ehci_usb_of_to_plat,
- .bind = ehci_usb_bind,
.probe = ehci_usb_probe,
- .remove = ehci_deregister,
+ .remove = ehci_usb_remove,
.ops = &ehci_usb_ops,
.plat_auto = sizeof(struct usb_plat),
.priv_auto = sizeof(struct ehci_mx6_priv_data),