From 1220aa9a65f6ff909740a6f0eb54b57ab62b5fee Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 11:21:07 +0200 Subject: [PATCH 01/24] phy: nop-phy: Add standard usb-nop-xceiv compat string The USB no-op PHY uses "usb-nop-xceiv" compatible string. This driver is compatible with USB no-op PHY, so add the compatible string. Signed-off-by: Marek Vasut Cc: Alexey Brodkin Cc: Eugeniy Paltsev Cc: Fabio Estevam Cc: Jean-Jacques Hiblot Cc: Murali Karicheri Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/phy/nop-phy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/phy/nop-phy.c b/drivers/phy/nop-phy.c index 84aac806230..9f12ebc0624 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" }, { } }; From b31e16b32e1e60d5cc0b05d85ca172818148288b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 11:23:36 +0200 Subject: [PATCH 02/24] arc: emsdp/iotdk: Use standard compatible string for USB no-op PHY The standard compatible string is "usb-nop-xceiv", use it. Signed-off-by: Marek Vasut Cc: Alexey Brodkin Cc: Eugeniy Paltsev Cc: Fabio Estevam Cc: Jean-Jacques Hiblot Cc: Murali Karicheri Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- arch/arc/dts/iot_devkit.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/dts/iot_devkit.dts b/arch/arc/dts/iot_devkit.dts index c0173fa5ab4..2122827527e 100644 --- a/arch/arc/dts/iot_devkit.dts +++ b/arch/arc/dts/iot_devkit.dts @@ -39,7 +39,7 @@ }; usbphy: phy { - compatible = "nop-phy"; + compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; From c7eb5d2c2ece7dba9eddba8967a3ffa457936aa7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 11:24:31 +0200 Subject: [PATCH 03/24] ARM: dts: k2g-evm: Use standard compatible string for USB no-op PHY The standard compatible string is "usb-nop-xceiv", use it. Note that keystone-k2g.dtsi already uses the aforementioned compat string, so this patch can only remove the override. Signed-off-by: Marek Vasut Cc: Alexey Brodkin Cc: Eugeniy Paltsev Cc: Fabio Estevam Cc: Jean-Jacques Hiblot Cc: Murali Karicheri Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- arch/arm/dts/keystone-k2g-evm.dts | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/dts/keystone-k2g-evm.dts b/arch/arm/dts/keystone-k2g-evm.dts index 7c5deef8083..b5b511cbd61 100644 --- a/arch/arm/dts/keystone-k2g-evm.dts +++ b/arch/arm/dts/keystone-k2g-evm.dts @@ -38,7 +38,6 @@ &usb0_phy { status = "okay"; - compatible = "nop-phy"; }; &usb0 { @@ -51,7 +50,6 @@ }; &usb1_phy { - compatible = "nop-phy"; status = "okay"; }; From aded940f4fb7e2af6a388e20f1bfb09410962566 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 11:47:25 +0200 Subject: [PATCH 04/24] ARM: dts: imx8mm: Replace deprecated fsl,usbphy DT props with phys The fsl,usbphy DT property is deprecated, replace it with phys DT property and specify #phy-cells, so that the generic PHY framework can parse the PHY bindings without any extra hacking. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- arch/arm/dts/imx8mm.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/imx8mm.dtsi b/arch/arm/dts/imx8mm.dtsi index c824f2615fe..fa2d73f1803 100644 --- a/arch/arm/dts/imx8mm.dtsi +++ b/arch/arm/dts/imx8mm.dtsi @@ -241,6 +241,7 @@ }; usbphynop1: usbphynop1 { + #phy-cells = <0>; compatible = "usb-nop-xceiv"; clocks = <&clk IMX8MM_CLK_USB_PHY_REF>; assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>; @@ -249,6 +250,7 @@ }; usbphynop2: usbphynop2 { + #phy-cells = <0>; compatible = "usb-nop-xceiv"; clocks = <&clk IMX8MM_CLK_USB_PHY_REF>; assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>; @@ -936,7 +938,7 @@ clock-names = "usb1_ctrl_root_clk"; assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>; assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>; - fsl,usbphy = <&usbphynop1>; + phys = <&usbphynop1>; fsl,usbmisc = <&usbmisc1 0>; status = "disabled"; }; @@ -955,7 +957,7 @@ clock-names = "usb1_ctrl_root_clk"; assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>; assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>; - fsl,usbphy = <&usbphynop2>; + phys = <&usbphynop2>; fsl,usbmisc = <&usbmisc2 0>; status = "disabled"; }; From 5781f465f5d548f31b0446815393fae676f94535 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 10 Apr 2021 00:12:03 +0200 Subject: [PATCH 05/24] ARM: dts: imx8mn: Replace deprecated fsl,usbphy DT props with phys The fsl,usbphy DT property is deprecated, replace it with phys DT property and specify #phy-cells, so that the generic PHY framework can parse the PHY bindings without any extra hacking. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- arch/arm/dts/imx8mn.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/imx8mn.dtsi b/arch/arm/dts/imx8mn.dtsi index 16ea5008956..63005ce9d1e 100644 --- a/arch/arm/dts/imx8mn.dtsi +++ b/arch/arm/dts/imx8mn.dtsi @@ -962,7 +962,7 @@ clock-names = "usb1_ctrl_root_clk"; assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>; assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>; - fsl,usbphy = <&usbphynop1>; + phys = <&usbphynop1>; fsl,usbmisc = <&usbmisc1 0>; status = "disabled"; }; @@ -1030,6 +1030,7 @@ }; usbphynop1: usbphynop1 { + #phy-cells = <0>; compatible = "usb-nop-xceiv"; clocks = <&clk IMX8MN_CLK_USB_PHY_REF>; assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>; From f0e10e33e5978515c878e1ec18952ccdd1bf5a83 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 2 Apr 2021 13:14:53 +0200 Subject: [PATCH 06/24] ARM: dts: imx8mm: Add power domain nodes Add power domain nodes to DT. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- arch/arm/dts/imx8mm.dtsi | 73 ++++++++++++++++++++++++ include/dt-bindings/power/imx8mm-power.h | 22 +++++++ 2 files changed, 95 insertions(+) create mode 100644 include/dt-bindings/power/imx8mm-power.h diff --git a/arch/arm/dts/imx8mm.dtsi b/arch/arm/dts/imx8mm.dtsi index fa2d73f1803..b142b80734d 100644 --- a/arch/arm/dts/imx8mm.dtsi +++ b/arch/arm/dts/imx8mm.dtsi @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include #include @@ -592,6 +594,75 @@ interrupts = ; #reset-cells = <1>; }; + + gpc: gpc@303a0000 { + compatible = "fsl,imx8mm-gpc"; + reg = <0x303a0000 0x10000>; + interrupt-parent = <&gic>; + interrupt-controller; + #interrupt-cells = <3>; + + pgc { + #address-cells = <1>; + #size-cells = <0>; + + pgc_hsiomix: power-domain@0 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MM_CLK_USB_BUS>; + }; + + pgc_pcie: power-domain@1 { + #power-domain-cells = <0>; + reg = ; + power-domains = <&pgc_hsiomix>; + }; + + pgc_otg1: power-domain@2 { + #power-domain-cells = <0>; + reg = ; + power-domains = <&pgc_hsiomix>; + }; + + pgc_otg2: power-domain@3 { + #power-domain-cells = <0>; + reg = ; + power-domains = <&pgc_hsiomix>; + }; + + pgc_gpumix: power-domain@4 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MM_CLK_GPU_BUS_ROOT>, + <&clk IMX8MM_CLK_GPU_AHB>; + }; + + pgc_gpu: power-domain@5 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MM_CLK_GPU_AHB>, + <&clk IMX8MM_CLK_GPU_BUS_ROOT>, + <&clk IMX8MM_CLK_GPU2D_ROOT>, + <&clk IMX8MM_CLK_GPU3D_ROOT>; + resets = <&src IMX8MQ_RESET_GPU_RESET>; + power-domains = <&pgc_gpumix>; + }; + + dispmix_pd: power-domain@10 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MM_CLK_DISP_ROOT>, + <&clk IMX8MM_CLK_DISP_AXI_ROOT>, + <&clk IMX8MM_CLK_DISP_APB_ROOT>; + }; + + mipi_pd: power-domain@11 { + #power-domain-cells = <0>; + reg = ; + power-domains = <&dispmix_pd>; + }; + }; + }; }; aips2: bus@30400000 { @@ -940,6 +1011,7 @@ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>; phys = <&usbphynop1>; fsl,usbmisc = <&usbmisc1 0>; + power-domains = <&pgc_otg1>; status = "disabled"; }; @@ -959,6 +1031,7 @@ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>; phys = <&usbphynop2>; fsl,usbmisc = <&usbmisc2 0>; + power-domains = <&pgc_otg2>; status = "disabled"; }; diff --git a/include/dt-bindings/power/imx8mm-power.h b/include/dt-bindings/power/imx8mm-power.h new file mode 100644 index 00000000000..fc9c2e16aad --- /dev/null +++ b/include/dt-bindings/power/imx8mm-power.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (C) 2020 Pengutronix, Lucas Stach + */ + +#ifndef __DT_BINDINGS_IMX8MM_POWER_H__ +#define __DT_BINDINGS_IMX8MM_POWER_H__ + +#define IMX8MM_POWER_DOMAIN_HSIOMIX 0 +#define IMX8MM_POWER_DOMAIN_PCIE 1 +#define IMX8MM_POWER_DOMAIN_OTG1 2 +#define IMX8MM_POWER_DOMAIN_OTG2 3 +#define IMX8MM_POWER_DOMAIN_GPUMIX 4 +#define IMX8MM_POWER_DOMAIN_GPU 5 +#define IMX8MM_POWER_DOMAIN_VPUMIX 6 +#define IMX8MM_POWER_DOMAIN_VPUG1 7 +#define IMX8MM_POWER_DOMAIN_VPUG2 8 +#define IMX8MM_POWER_DOMAIN_VPUH1 9 +#define IMX8MM_POWER_DOMAIN_DISPMIX 10 +#define IMX8MM_POWER_DOMAIN_MIPI 11 + +#endif From d78f7d8199ba6b6137e0c2d371171f5798148499 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 10 Apr 2021 00:16:06 +0200 Subject: [PATCH 07/24] ARM: dts: imx8mn: Add power domain nodes Add power domain nodes to DT. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- arch/arm/dts/imx8mn.dtsi | 51 ++++++++++++++++++++++++ include/dt-bindings/power/imx8mn-power.h | 15 +++++++ 2 files changed, 66 insertions(+) create mode 100644 include/dt-bindings/power/imx8mn-power.h diff --git a/arch/arm/dts/imx8mn.dtsi b/arch/arm/dts/imx8mn.dtsi index 63005ce9d1e..edcb415b53d 100644 --- a/arch/arm/dts/imx8mn.dtsi +++ b/arch/arm/dts/imx8mn.dtsi @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include #include @@ -612,6 +614,54 @@ interrupts = ; #reset-cells = <1>; }; + + gpc: gpc@303a0000 { + compatible = "fsl,imx8mn-gpc"; + reg = <0x303a0000 0x10000>; + interrupt-parent = <&gic>; + interrupts = ; + + pgc { + #address-cells = <1>; + #size-cells = <0>; + + pgc_hsiomix: power-domain@0 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MN_CLK_USB_BUS>; + }; + + pgc_otg1: power-domain@1 { + #power-domain-cells = <0>; + reg = ; + power-domains = <&pgc_hsiomix>; + }; + + pgc_gpumix: power-domain@2 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MN_CLK_GPU_CORE_ROOT>, + <&clk IMX8MN_CLK_GPU_SHADER_DIV>, + <&clk IMX8MN_CLK_GPU_BUS_ROOT>, + <&clk IMX8MN_CLK_GPU_AHB>; + resets = <&src IMX8MQ_RESET_GPU_RESET>; + }; + + dispmix_pd: power-domain@3 { + #power-domain-cells = <0>; + reg = ; + clocks = <&clk IMX8MN_CLK_DISP_PIXEL_ROOT>, + <&clk IMX8MN_CLK_DISP_AXI_ROOT>, + <&clk IMX8MN_CLK_DISP_APB_ROOT>; + }; + + mipi_pd: power-domain@4 { + #power-domain-cells = <0>; + reg = ; + power-domains = <&dispmix_pd>; + }; + }; + }; }; aips2: bus@30400000 { @@ -964,6 +1014,7 @@ assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>; phys = <&usbphynop1>; fsl,usbmisc = <&usbmisc1 0>; + power-domains = <&pgc_otg1>; status = "disabled"; }; diff --git a/include/dt-bindings/power/imx8mn-power.h b/include/dt-bindings/power/imx8mn-power.h new file mode 100644 index 00000000000..102ee85a9b6 --- /dev/null +++ b/include/dt-bindings/power/imx8mn-power.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (C) 2020 Compass Electronics Group, LLC + */ + +#ifndef __DT_BINDINGS_IMX8MN_POWER_H__ +#define __DT_BINDINGS_IMX8MN_POWER_H__ + +#define IMX8MN_POWER_DOMAIN_HSIOMIX 0 +#define IMX8MN_POWER_DOMAIN_OTG1 1 +#define IMX8MN_POWER_DOMAIN_GPUMIX 2 +#define IMX8MN_POWER_DOMAIN_DISPMIX 3 +#define IMX8MN_POWER_DOMAIN_MIPI 4 + +#endif From da16034daa8ba65cb62ac49bb2280d50beeeb419 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 2 Apr 2021 13:32:40 +0200 Subject: [PATCH 08/24] imx: power-domain: Add fsl,imx8mm-gpc compatible string The driver is compatible with iMX8MM, add missing compatible string. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/power/domain/imx8m-power-domain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index c4cd07ffaf4..ebac90d81c1 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -120,6 +120,7 @@ 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" }, { } }; From f174a0dbce0b787053bf921eee3a635aef304957 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 10 Apr 2021 00:19:27 +0200 Subject: [PATCH 09/24] imx: power-domain: Add fsl,imx8mn-gpc compatible string The driver is compatible with iMX8MN, add missing compatible string. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/power/domain/imx8m-power-domain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index ebac90d81c1..5d34bc12902 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -121,6 +121,7 @@ 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" }, { } }; From 7e1f1e16fe75b0a5a2ef8dcbba5b6a543d6ec442 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 12:19:27 +0200 Subject: [PATCH 10/24] usb: ehci-mx6: Turn off Vbus on probe failure The driver turns on Vbus regulator in probe, but fails to turn it back off in case of probe failure. Add the missing code. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index aeea5399995..7b538b6dcb8 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -640,7 +640,32 @@ static int ehci_usb_probe(struct udevice *dev) hcor = (struct ehci_hcor *)((uint32_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_regulator; + + return ret; + +err_regulator: +#if CONFIG_IS_ENABLED(DM_REGULATOR) + if (priv->vbus_supply) + regulator_set_enable(priv->vbus_supply, false); +#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 CONFIG_IS_ENABLED(DM_REGULATOR) + if (priv->vbus_supply) + regulator_set_enable(priv->vbus_supply, false); +#endif + + return 0; } static const struct udevice_id mx6_usb_ids[] = { @@ -655,7 +680,7 @@ U_BOOT_DRIVER(usb_mx6) = { .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), From 7f2c10eec68de9c4d6820e95fdec59f9d21245ab Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 12:28:03 +0200 Subject: [PATCH 11/24] usb: ehci-mx6: Add DM clock support Add support for using DM clock framework to enable and disable all the necessary clock for the USB controller. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 7b538b6dcb8..04b072e717f 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -347,9 +348,6 @@ 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) @@ -391,6 +389,9 @@ int ehci_hcd_init(int index, enum usb_init_type init, } } + enable_usboh3_clk(1); + mdelay(1); + ret = ehci_mx6_common_init(ehci, index); if (ret) return ret; @@ -428,6 +429,7 @@ struct ehci_mx6_priv_data { struct ehci_ctrl ctrl; struct usb_ehci *ehci; struct udevice *vbus_supply; + struct clk clk; enum usb_init_type init_type; int portnr; }; @@ -606,6 +608,20 @@ static int ehci_usb_probe(struct udevice *dev) 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); @@ -614,7 +630,7 @@ static int ehci_usb_probe(struct udevice *dev) #endif ret = ehci_mx6_common_init(ehci, priv->portnr); if (ret) - return ret; + goto err_clk; #if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->vbus_supply) { @@ -623,7 +639,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 @@ -650,6 +666,13 @@ err_regulator: #if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->vbus_supply) regulator_set_enable(priv->vbus_supply, false); +#endif +err_clk: +#if CONFIG_IS_ENABLED(CLK) + clk_disable(&priv->clk); +#else + /* Compatibility with DM_USB and !CLK */ + enable_usboh3_clk(0); #endif return ret; } @@ -665,6 +688,10 @@ int ehci_usb_remove(struct udevice *dev) regulator_set_enable(priv->vbus_supply, false); #endif +#if CONFIG_IS_ENABLED(CLK) + clk_disable(&priv->clk); +#endif + return 0; } From 598fa7e106c8d0632f75800db2082709c0ea3416 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 22:19:00 +0200 Subject: [PATCH 12/24] usb: ehci-mx6: Unify USBNC registers Merge USBNC register layout structure into a single one, instead of having three separate structures and a lot of ifdeffery. No functional change. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 53 +++++++++++++------------------------ 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 04b072e717f..915b25a618d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -68,6 +68,24 @@ DECLARE_GLOBAL_DATA_PTR; #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ #define UCMD_RESET (1 << 1) /* controller reset */ +/* 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; +}; + #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) static const unsigned phy_bases[] = { USB_PHY0_BASE_ADDR, @@ -207,39 +225,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 + @@ -274,12 +260,11 @@ 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_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 + void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 /* mx6qarm2 seems to required a different setting*/ From 4dcfa3bcbcbc5e0f7da145fff41e120392433062 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 23:06:07 +0200 Subject: [PATCH 13/24] usb: ehci-mx6: Parse USB PHY and MISC offsets from DT In case DM and OF controler is enabled, but PHY support is disabled, parse USB PHY and MISC component addresses from DT manually. Those component addresses will be used in subsequent patches to access the ANATOP, PHY and MISC registers matching the controller and thus get rid of the ad-hoc controller sequence number mapping. Fixes: 4de51cc25b5 ("usb: ehci-mx6: Drop assignment of sequence number") Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 915b25a618d..164054eaf8b 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -417,6 +417,9 @@ struct ehci_mx6_priv_data { struct clk clk; 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) @@ -571,6 +574,54 @@ static int ehci_usb_bind(struct udevice *dev) return 0; } +static int mx6_parse_dt_addrs(struct udevice *dev) +{ + 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; + + 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; + } + + 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; + + 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; +} + static int ehci_usb_probe(struct udevice *dev) { struct usb_plat *plat = dev_get_plat(dev); @@ -589,6 +640,10 @@ 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; From ef464e4c362f154465dcd315e17c6601642117d1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 21:40:24 +0200 Subject: [PATCH 14/24] usb: ehci-mx6: Split ehci_mx6_common_init() In order to pass component addresses around easily instead of passing ad-hoc sequence numbers, it is necessary to split ehci_mx6_common_init(). Make it so and call the separate functions instead. Since board_ehci_hcd_init() makes no sense in DM case, do not call it in DM case. Fixes: 4de51cc25b5 ("usb: ehci-mx6: Drop assignment of sequence number") Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 164054eaf8b..19c010b5ad1 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -283,6 +283,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 @@ -329,27 +330,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; - - /* 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) { @@ -377,9 +357,20 @@ int ehci_hcd_init(int index, enum usb_init_type init, enable_usboh3_clk(1); mdelay(1); - ret = ehci_mx6_common_init(ehci, index); - if (ret) + /* Do board specific initialization */ + ret = board_ehci_hcd_init(index); + if (ret) { + enable_usboh3_clk(0); 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 type = board_usb_phy_mode(index); @@ -427,14 +418,18 @@ 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; + usb_power_config(priv->portnr); + usb_oc_config(priv->portnr); + +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) + usb_internal_phy_clock_gate(priv->portnr, 1); + usb_phy_enable(priv->portnr, ehci); +#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); @@ -668,9 +663,14 @@ static int ehci_usb_probe(struct udevice *dev) if (ret) debug("%s: No vbus supply\n", dev->name); #endif - ret = ehci_mx6_common_init(ehci, priv->portnr); - if (ret) - goto err_clk; + + usb_power_config(priv->portnr); + usb_oc_config(priv->portnr); + +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) + usb_internal_phy_clock_gate(priv->portnr, 1); + usb_phy_enable(priv->portnr, ehci); +#endif #if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->vbus_supply) { From eb64f598dc569cc139b309aa7778c286d9ac6f4f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 22:10:35 +0200 Subject: [PATCH 15/24] usb: ehci-mx6: Pass PHY address to usb_*_phy*() Instead of passing ad-hoc index to USB PHY handling functions and then try and figure out the PHY address, pass in the PHY address itself. For DM case, this address comes easily from DT. For non-DM case, the previous method is still present, however the non-DM case will soon be removed. Fixes: 4de51cc25b5 ("usb: ehci-mx6: Drop assignment of sequence number") Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 19c010b5ad1..b43c55765c6 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -94,14 +94,8 @@ static const unsigned phy_bases[] = { #endif }; -static void usb_internal_phy_clock_gate(int index, int on) +static void usb_internal_phy_clock_gate(void __iomem *phy_reg, 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); } @@ -166,17 +160,12 @@ static void usb_power_config(int index) } /* 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; @@ -368,8 +357,10 @@ int ehci_hcd_init(int index, enum usb_init_type init, usb_oc_config(index); #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) - usb_internal_phy_clock_gate(index, 1); - usb_phy_enable(index, ehci); + 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); @@ -423,8 +414,8 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev) usb_oc_config(priv->portnr); #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) - usb_internal_phy_clock_gate(priv->portnr, 1); - usb_phy_enable(priv->portnr, ehci); + usb_internal_phy_clock_gate(priv->phy_addr, 1); + usb_phy_enable(ehci, priv->phy_addr); #endif #if CONFIG_IS_ENABLED(DM_REGULATOR) @@ -668,8 +659,8 @@ static int ehci_usb_probe(struct udevice *dev) usb_oc_config(priv->portnr); #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) - usb_internal_phy_clock_gate(priv->portnr, 1); - usb_phy_enable(priv->portnr, ehci); + usb_internal_phy_clock_gate(priv->phy_addr, 1); + usb_phy_enable(ehci, priv->phy_addr); #endif #if CONFIG_IS_ENABLED(DM_REGULATOR) From 849763b9635da45d2eaf947e79745af44b7433b0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 23:00:23 +0200 Subject: [PATCH 16/24] usb: ehci-mx6: Split usb_power_config() Split usb_power_config() per SoC and pass in USB PHY, USBNC and ANATOP addresses instead of ad-hoc sequence numbers. This is only applicable on legacy systems which do not implement proper PHY support. Once PHY support is available, parts of this can be removed altogether and moved to the PHY driver, similar to Linux phy-mxs-usb.c . Fixes: 4de51cc25b5 ("usb: ehci-mx6: Drop assignment of sequence number") Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 145 +++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 52 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index b43c55765c6..d022df04ab1 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -86,43 +86,18 @@ struct usbnc_regs { u32 adp_status; }; -#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 -}; - -static void usb_internal_phy_clock_gate(void __iomem *phy_reg, int on) +#if defined(CONFIG_MX6) && !defined(CONFIG_PHY) +static void usb_power_config_mx6(struct anatop_regs __iomem *anatop, + int anatop_bits_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); - -#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; @@ -155,8 +130,61 @@ 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 */ @@ -196,6 +224,7 @@ static int usb_phy_enable(struct usb_ehci *ehci, void __iomem *phy_reg) return 0; } +#endif int usb_phy_mode(int port) { @@ -215,19 +244,6 @@ int usb_phy_mode(int port) } #elif defined(CONFIG_MX7) -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 + @@ -325,8 +341,16 @@ int ehci_hcd_init(int index, enum usb_init_type init, 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; +#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; #endif struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR + (controller_spacing * index)); @@ -353,7 +377,14 @@ int ehci_hcd_init(int index, enum usb_init_type init, return ret; } - usb_power_config(index); +#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(index); #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) @@ -410,10 +441,15 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev) enum usb_init_type type = priv->init_type; struct usb_ehci *ehci = priv->ehci; - usb_power_config(priv->portnr); +#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->portnr); -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) +#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 @@ -655,10 +691,15 @@ static int ehci_usb_probe(struct udevice *dev) debug("%s: No vbus supply\n", dev->name); #endif - usb_power_config(priv->portnr); +#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->portnr); -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) +#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 From 668646995fbde99b6c96c523c0e94e5deb029fe0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 23:24:41 +0200 Subject: [PATCH 17/24] usb: ehci-mx6: Pass MISC address to usb_oc_config() Instead of passing ad-hoc sequence number to usb_oc_config(), pass in the USB MISC address itself. The USB MISC address comes from DT in DM case, and from the old method using controller index in non-DM case. Fixes: 4de51cc25b5 ("usb: ehci-mx6: Drop assignment of sequence number") Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index d022df04ab1..99fd0e71834 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -260,15 +260,8 @@ 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); -#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + - (0x10000 * index) + USBNC_OFFSET); -#endif void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 @@ -343,6 +336,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, u32 controller_spacing = 0x200; 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 + @@ -351,6 +346,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, 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)); @@ -385,7 +382,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, usb_power_config_mx7ulp(usbphy); #endif - usb_oc_config(index); + usb_oc_config(usbnc, index); #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) if (index < ARRAY_SIZE(phy_bases)) { @@ -447,7 +444,7 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev) usb_power_config_mx7ulp(priv->phy_addr); #endif - usb_oc_config(priv->portnr); + 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); @@ -697,7 +694,7 @@ static int ehci_usb_probe(struct udevice *dev) usb_power_config_mx7ulp(priv->phy_addr); #endif - usb_oc_config(priv->portnr); + 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); From 6443a3bc40d247f0a02376e763f6e03085528631 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 2 Apr 2021 13:56:28 +0200 Subject: [PATCH 18/24] usb: ehci-mx6: Use portnr from DT in DM case In case the platform uses DM, determine port number, which is used as offset in USBMISC registers, from PHY node DT aliases, just like Linux does. Fixes: 4de51cc25b5 ("usb: ehci-mx6: Drop assignment of sequence number") Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 52 +++++-------------------------------- 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 99fd0e71834..68f6ecc8722 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -550,49 +550,6 @@ static int ehci_usb_of_to_plat(struct udevice *dev) return 0; } -static int ehci_usb_bind(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. - */ - - /* - * 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; - */ - - return 0; -} - static int mx6_parse_dt_addrs(struct udevice *dev) { struct ehci_mx6_priv_data *priv = dev_get_priv(dev); @@ -600,6 +557,7 @@ 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) { @@ -608,6 +566,11 @@ 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; @@ -617,6 +580,7 @@ static int mx6_parse_dt_addrs(struct udevice *dev) 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) @@ -664,7 +628,6 @@ static int ehci_usb_probe(struct udevice *dev) return ret; priv->ehci = ehci; - priv->portnr = dev_seq(dev); priv->init_type = type; #if CONFIG_IS_ENABLED(CLK) @@ -774,7 +737,6 @@ 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_usb_remove, .ops = &ehci_usb_ops, From 50d0146cb70abc76ac3c363cd0e30b8ea4e91d1d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 2 Apr 2021 13:07:49 +0200 Subject: [PATCH 19/24] usb: ehci-mx6: Add generic EHCI PHY support In case PHY support is enabled, use the generic EHCI PHY support to start and stop the PHY. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 68f6ecc8722..8e209418555 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -425,6 +425,7 @@ struct ehci_mx6_priv_data { 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; @@ -684,22 +685,32 @@ static int ehci_usb_probe(struct udevice *dev) mdelay(10); +#if defined(CONFIG_PHY) + ret = ehci_setup_phy(dev, &priv->phy, 0); + if (ret) + goto err_regulator; +#endif + hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); hcor = (struct ehci_hcor *)((uint32_t)hccr + HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); ret = ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type); if (ret) - goto err_regulator; + 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); -#endif err_clk: +#endif #if CONFIG_IS_ENABLED(CLK) clk_disable(&priv->clk); #else @@ -715,6 +726,10 @@ int ehci_usb_remove(struct udevice *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); From 1aae8a35a202d4400adbb7780e1b384aa7aada37 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 10 Apr 2021 16:03:04 +0200 Subject: [PATCH 20/24] usb: ehci-mx6: Set default CONFIG_MXC_USB_PORTSC if not defined There is now multiple copies of CONFIG_MXC_USB_PORTSC in configs set to PORT_PTS_UTMI | PORT_PTS_PTW, which is in fact the default register value for MX6, MX7 and MX7ULP. Define the default value of CONFIG_MXC_USB_PORTSC in the driver and use it in case CONFIG_MXC_USB_PORTSC is not defined in config, to reduce the duplication. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 8e209418555..d3308c60ee6 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -68,6 +68,11 @@ DECLARE_GLOBAL_DATA_PTR; #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ #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) +#endif + /* Base address for this IP block is 0x02184800 */ struct usbnc_regs { u32 ctrl[4]; /* otg/host1-3 */ From e87015ff05d49b8e18367d05658cc092b5f94cc8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 2 Apr 2021 13:07:59 +0200 Subject: [PATCH 21/24] usb: ehci-mx6: Add fsl,imx7d-usb compatible string Add new compatible string, used by some more up-to-date DTs. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index d3308c60ee6..28db593b7e3 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -749,6 +749,7 @@ int ehci_usb_remove(struct udevice *dev) static const struct udevice_id mx6_usb_ids[] = { { .compatible = "fsl,imx27-usb" }, + { .compatible = "fsl,imx7d-usb" }, { } }; From f444f8986b4c74b63cbf421635387df120d3cb4f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 6 Apr 2021 20:37:16 +0200 Subject: [PATCH 22/24] usb: ehci-mx6: Fix aarch64 build warnings Fix cast from pointer to integer of different size by casting the pointer to uintptr_t instead of uint32_t, the former has correct size on both 32bit and 64bit architectures. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/ehci-mx6.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 28db593b7e3..7642a31b655 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -399,8 +399,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, 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))); } @@ -696,8 +696,8 @@ static int ehci_usb_probe(struct udevice *dev) goto err_regulator; #endif - 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))); ret = ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type); From 5e7e2a8e4f1e6d480f66822270bbf14c045aace0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 2 Apr 2021 14:07:22 +0200 Subject: [PATCH 23/24] usb: ehci-mx6: Add iMX8M support The iMX8M uses nop PHY, select PHY and NOP_PHY automatically. Otherwise, the DM capable driver is now perfectly compatible. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Peng Fan Cc: Stefano Babic Cc: Ye Li Cc: uboot-imx --- drivers/usb/host/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0971a7c8139..bf5d82f0350 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. From d08cdc223db1023ebb8c03d6341fdf45b303700c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 31 Mar 2021 23:46:35 +0200 Subject: [PATCH 24/24] ARM: imx8m: verdin-imx8mm: Enable USB Host support Enable USB host support on MX8MM Verdin. Signed-off-by: Marek Vasut Cc: Marcel Ziswiler Cc: Max Krummenacher Cc: Oleksandr Suvorov --- configs/verdin-imx8mm_defconfig | 8 +++++++- include/configs/verdin-imx8mm.h | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/configs/verdin-imx8mm_defconfig b/configs/verdin-imx8mm_defconfig index ea0b5978f1f..c8c3420b6a5 100644 --- a/configs/verdin-imx8mm_defconfig +++ b/configs/verdin-imx8mm_defconfig @@ -37,7 +37,6 @@ CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_POWER_SUPPORT=y -CONFIG_SPL_USB_HOST_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y CONFIG_SYS_PROMPT="Verdin iMX8MM # " # CONFIG_BOOTM_NETBSD is not set @@ -50,6 +49,7 @@ CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y CONFIG_CMD_CACHE=y CONFIG_CMD_UUID=y CONFIG_CMD_REGULATOR=y @@ -89,6 +89,8 @@ CONFIG_MII=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_IMX8M=y +CONFIG_POWER_DOMAIN=y +CONFIG_IMX8M_POWER_DOMAIN=y CONFIG_DM_PMIC=y CONFIG_SPL_DM_PMIC_PCA9450=y CONFIG_DM_PMIC_PFUZE100=y @@ -101,5 +103,9 @@ CONFIG_SPL_SYSRESET=y CONFIG_SYSRESET_PSCI=y CONFIG_SYSRESET_WATCHDOG=y CONFIG_DM_THERMAL=y +CONFIG_USB=y +CONFIG_DM_USB=y +# CONFIG_SPL_DM_USB is not set +CONFIG_USB_EHCI_HCD=y CONFIG_IMX_WATCHDOG=y CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/include/configs/verdin-imx8mm.h b/include/configs/verdin-imx8mm.h index 4751bf5a5af..e2a817891c2 100644 --- a/include/configs/verdin-imx8mm.h +++ b/include/configs/verdin-imx8mm.h @@ -117,5 +117,10 @@ #define FEC_QUIRK_ENET_MAC #define IMX_FEC_BASE 0x30BE0000 +/* USB Configs */ +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET +#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 + #endif /*_VERDIN_IMX8MM_H */