[PATCH V2 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 marex@denx.de Cc: Alexey Brodkin alexey.brodkin@synopsys.com Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Cc: Fabio Estevam festevam@gmail.com Cc: Jean-Jacques Hiblot jjhiblot@ti.com Cc: Murali Karicheri m-karicheri2@ti.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 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" }, { } };

The standard compatible string is "usb-nop-xceiv", use it.
Signed-off-by: Marek Vasut marex@denx.de Cc: Alexey Brodkin alexey.brodkin@synopsys.com Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Cc: Fabio Estevam festevam@gmail.com Cc: Jean-Jacques Hiblot jjhiblot@ti.com Cc: Murali Karicheri m-karicheri2@ti.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 c0173fa5ab..2122827527 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>; };

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 marex@denx.de Cc: Alexey Brodkin alexey.brodkin@synopsys.com Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Cc: Fabio Estevam festevam@gmail.com Cc: Jean-Jacques Hiblot jjhiblot@ti.com Cc: Murali Karicheri m-karicheri2@ti.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 7c5deef808..b5b511cbd6 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"; };

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: Isolate to iMX8MM --- 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 c824f2615f..fa2d73f180 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"; };

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: New patch for iMX8MN --- 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 16ea500895..63005ce9d1 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>;

Add power domain nodes to DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 fa2d73f180..b142b80734 100644 --- a/arch/arm/dts/imx8mm.dtsi +++ b/arch/arm/dts/imx8mm.dtsi @@ -4,6 +4,8 @@ */
#include <dt-bindings/clock/imx8mm-clock.h> +#include <dt-bindings/power/imx8mm-power.h> +#include <dt-bindings/reset/imx8mq-reset.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> @@ -592,6 +594,75 @@ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; #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 = <IMX8MM_POWER_DOMAIN_HSIOMIX>; + clocks = <&clk IMX8MM_CLK_USB_BUS>; + }; + + pgc_pcie: power-domain@1 { + #power-domain-cells = <0>; + reg = <IMX8MM_POWER_DOMAIN_PCIE>; + power-domains = <&pgc_hsiomix>; + }; + + pgc_otg1: power-domain@2 { + #power-domain-cells = <0>; + reg = <IMX8MM_POWER_DOMAIN_OTG1>; + power-domains = <&pgc_hsiomix>; + }; + + pgc_otg2: power-domain@3 { + #power-domain-cells = <0>; + reg = <IMX8MM_POWER_DOMAIN_OTG2>; + power-domains = <&pgc_hsiomix>; + }; + + pgc_gpumix: power-domain@4 { + #power-domain-cells = <0>; + reg = <IMX8MM_POWER_DOMAIN_GPUMIX>; + clocks = <&clk IMX8MM_CLK_GPU_BUS_ROOT>, + <&clk IMX8MM_CLK_GPU_AHB>; + }; + + pgc_gpu: power-domain@5 { + #power-domain-cells = <0>; + reg = <IMX8MM_POWER_DOMAIN_GPU>; + 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 = <IMX8MM_POWER_DOMAIN_DISPMIX>; + 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 = <IMX8MM_POWER_DOMAIN_MIPI>; + 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 0000000000..fc9c2e16aa --- /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 kernel@pengutronix.de + */ + +#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

Add power domain nodes to DT.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: New patch --- 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 63005ce9d1..edcb415b53 100644 --- a/arch/arm/dts/imx8mn.dtsi +++ b/arch/arm/dts/imx8mn.dtsi @@ -4,6 +4,8 @@ */
#include <dt-bindings/clock/imx8mn-clock.h> +#include <dt-bindings/power/imx8mn-power.h> +#include <dt-bindings/reset/imx8mq-reset.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> @@ -612,6 +614,54 @@ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; #reset-cells = <1>; }; + + gpc: gpc@303a0000 { + compatible = "fsl,imx8mn-gpc"; + reg = <0x303a0000 0x10000>; + interrupt-parent = <&gic>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + + pgc { + #address-cells = <1>; + #size-cells = <0>; + + pgc_hsiomix: power-domain@0 { + #power-domain-cells = <0>; + reg = <IMX8MN_POWER_DOMAIN_HSIOMIX>; + clocks = <&clk IMX8MN_CLK_USB_BUS>; + }; + + pgc_otg1: power-domain@1 { + #power-domain-cells = <0>; + reg = <IMX8MN_POWER_DOMAIN_OTG1>; + power-domains = <&pgc_hsiomix>; + }; + + pgc_gpumix: power-domain@2 { + #power-domain-cells = <0>; + reg = <IMX8MN_POWER_DOMAIN_GPUMIX>; + 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 = <IMX8MN_POWER_DOMAIN_DISPMIX>; + 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 = <IMX8MN_POWER_DOMAIN_MIPI>; + 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 0000000000..102ee85a9b --- /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

The driver is compatible with iMX8MM, add missing compatible string.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 c4cd07ffaf..ebac90d81c 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" }, { } };

On 4/12/21 1:28 AM, Marek Vasut wrote:
The driver is compatible with iMX8MM, add missing compatible string.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon chung
V2: No change
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 c4cd07ffaf..ebac90d81c 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" }, { }
};

The driver is compatible with iMX8MN, add missing compatible string.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: New patch --- 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 ebac90d81c..5d34bc1290 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" }, { } };

On 4/12/21 1:28 AM, Marek Vasut wrote:
The driver is compatible with iMX8MN, add missing compatible string.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon chung
V2: New patch
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 ebac90d81c..5d34bc1290 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" }, { }
};

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: Mark struct ehci_mx6_priv_data *priv as "__maybe_unused", because it gets used only if either DM_REGULATOR or later DM_CLK or PHY are enabled. So avoid a warning that priv is defined but not used. --- 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 aeea539999..7b538b6dcb 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),

Add support for using DM clock framework to enable and disable all the necessary clock for the USB controller.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 7b538b6dcb..04b072e717 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> @@ -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; }

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 04b072e717..915b25a618 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*/

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: - Move anatop_off variable inside if defined(CONFIG_MX6) to avoid warning, that the variable is defined and not used on !MX6 - Parse PHY and USBMISC addresses unconditionally, with or without CONFIG_PHY enabled or disabled --- 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 915b25a618..164054eaf8 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;

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: Declare ret only if CONFIG_IS_ENABLED(DM_REGULATOR) , to avoid warning that it is declared, but not used --- 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 164054eaf8..19c010b5ad 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) {

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 19c010b5ad..b43c55765c 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)

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: - Always call usb_oc_config(), independent of whether CONFIG_PHY is or is not enabled - Only call usb_internal_phy_clock_gate() and usb_phy_enable() if CONFIG_PHY is disabled - Always define usb_power_config_*() and mark the empty implementations with __maybe_unused, since this vastly simplifies the ifdeffery and makes it much clearer what the intention of the ifdefs is --- drivers/usb/host/ehci-mx6.c | 143 +++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 51 deletions(-)
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index b43c55765c..d022df04ab 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

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 d022df04ab..99fd0e7183 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);

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: Mostly new patch, since the old one no longer makes sense --- 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 99fd0e7183..68f6ecc872 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,

In case PHY support is enabled, use the generic EHCI PHY support to start and stop the PHY.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: Shift ifdefs around error handling goto labels to avoid warnings that the labels are defined but not used --- 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 68f6ecc872..8e20941855 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);

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: New patch --- 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 8e20941855..d3308c60ee 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 */

Add new compatible string, used by some more up-to-date DTs.
Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: No change --- 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 d3308c60ee..28db593b7e 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" }, { } };

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: New patch --- 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 28db593b7e..7642a31b65 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);

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 marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com --- V2: Permit the driver on all iMX8M SoCs, not just iMX8MM --- 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 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.

Enable USB host support on MX8MM Verdin.
Signed-off-by: Marek Vasut marex@denx.de Cc: Marcel Ziswiler marcel.ziswiler@toradex.com Cc: Max Krummenacher max.krummenacher@toradex.com Cc: Oleksandr Suvorov oleksandr.suvorov@toradex.com --- V2: No change --- 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 ea0b5978f1..c8c3420b6a 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 4751bf5a5a..e2a817891c 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 */

On Sun, Apr 11, 2021 at 9:35 AM Marek Vasut marex@denx.de wrote:
Enable USB host support on MX8MM Verdin.
Signed-off-by: Marek Vasut marex@denx.de Cc: Marcel Ziswiler marcel.ziswiler@toradex.com Cc: Max Krummenacher max.krummenacher@toradex.com Cc: Oleksandr Suvorov oleksandr.suvorov@toradex.com
V2: No change
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 ea0b5978f1..c8c3420b6a 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 4751bf5a5a..e2a817891c 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 */
-- 2.30.2
Marek,
Thanks for your work on USB support for IMX8M!
I'm attempting to add USB support to the venice board following this example but I think there are still some things missing from the dt to make this work. I find that mx6_parse_dt_adds failes; Looks like it is required to have an alias that points to the phy but then it fails because the phy doesn't have a reg. Also, it would see the CONFIG_MXC_USB_PORTSC is no longer needed as that is now the default.
Best regards,
Tim

Hi Marek,
I have the same issue on my iMX8MM based board. Are you continue working on the patch for iMX8MM or should I dig into this problem?
I'm asking this just for not duplicating efforts. So if you are not working on this then I'll see if I can properly retrieve the necessary patches to make this work.
I think something is missing from previous patch set
https://lists.denx.de/pipermail/u-boot/2020-September/426757.html
Yours, Paul
Tim Harvey 於 2021/4/20 上午8:33 寫道:
On Sun, Apr 11, 2021 at 9:35 AM Marek Vasut marex@denx.de wrote:
Enable USB host support on MX8MM Verdin.
Signed-off-by: Marek Vasut marex@denx.de Cc: Marcel Ziswiler marcel.ziswiler@toradex.com Cc: Max Krummenacher max.krummenacher@toradex.com Cc: Oleksandr Suvorov oleksandr.suvorov@toradex.com
V2: No change
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 ea0b5978f1..c8c3420b6a 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 4751bf5a5a..e2a817891c 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 */
-- 2.30.2
Marek,
Thanks for your work on USB support for IMX8M!
I'm attempting to add USB support to the venice board following this example but I think there are still some things missing from the dt to make this work. I find that mx6_parse_dt_adds failes; Looks like it is required to have an alias that points to the phy but then it fails because the phy doesn't have a reg. Also, it would see the CONFIG_MXC_USB_PORTSC is no longer needed as that is now the default.
Best regards,
Tim

On Thu, Apr 22, 2021 at 3:34 AM Ying-Chun Liu (PaulLiu) paulliu@debian.org wrote:
Hi Marek,
I have the same issue on my iMX8MM based board. Are you continue working on the patch for iMX8MM or should I dig into this problem?
I'm asking this just for not duplicating efforts. So if you are not working on this then I'll see if I can properly retrieve the necessary patches to make this work.
I think something is missing from previous patch set
https://lists.denx.de/pipermail/u-boot/2020-September/426757.html
Paul,
It's not something missing from Peng's previous patchset since that didn't support DM. Marek added the dm bits but it requires some dt changes that are still not present to make mx6_parse_dt_addrs work (or some changes are needed to that func).
The way mx6_parse_dt_addrs is written you need to have a 'usb0' alias for example that points to the phy node (compatible 'fsl,usbmisc') but that is not what has typically been done for USB as typically the alias points to the host controller instead.
I'm still interested in what Marek tested with and also think there's a dt patch missing. The aliases should be added to imx8mm.dtsi, but I also think they should point to the controller and not the phy so there may be a code change needed as well.
Also, I wasn't aware that the power-domain dt bindings were accepted upstream to Linux as there has been quite a bit of controversy there.
cc'ing some others that are probably interested in mainline USB on IMX8M and likely know what's going on with IMX8M power domain. I regret missing this patchset when it was submitted or I would have asked these questions then... I just can't keep up with Linux and U-Boot mailing lists with my work-load in other areas.
Best regards,
Tim

On 4/20/21 2:33 AM, Tim Harvey wrote:
[...]
+/* 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 */
-- 2.30.2
Marek,
Thanks for your work on USB support for IMX8M!
I'm attempting to add USB support to the venice board following this example but I think there are still some things missing from the dt to make this work. I find that mx6_parse_dt_adds failes; Looks like it is required to have an alias that points to the phy but then it fails because the phy doesn't have a reg. Also, it would see the CONFIG_MXC_USB_PORTSC is no longer needed as that is now the default.
Have a look at this patch:
https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/8203ee09275c307...
That should fix it for you.
It would be good however if you could take the mx6 ventana and test the driver there, and possibly submit fixes in case the USB is still broken there. What would be even better is if you could implement the MXS PHY driver, so all the !CONFIG_PHY stuff can be removed for MX6 too. That shouldn't be much effort.

On Thu, Apr 22, 2021 at 12:16 PM Marek Vasut marex@denx.de wrote:
On 4/20/21 2:33 AM, Tim Harvey wrote:
[...]
+/* 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 */
-- 2.30.2
Marek,
Thanks for your work on USB support for IMX8M!
I'm attempting to add USB support to the venice board following this example but I think there are still some things missing from the dt to make this work. I find that mx6_parse_dt_adds failes; Looks like it is required to have an alias that points to the phy but then it fails because the phy doesn't have a reg. Also, it would see the CONFIG_MXC_USB_PORTSC is no longer needed as that is now the default.
Have a look at this patch:
https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/8203ee09275c307...
That should fix it for you.
It would be good however if you could take the mx6 ventana and test the driver there, and possibly submit fixes in case the USB is still broken there. What would be even better is if you could implement the MXS PHY driver, so all the !CONFIG_PHY stuff can be removed for MX6 too. That shouldn't be much effort.
Marek,
That does resolve the issue with mx6_parse_dt_adds failing and works for IMX8MM host mode (and likely peripheral mode) but not for otg. For otg we also need something like: @@ -523,7 +568,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST; - } else if (is_mx7()) { + } else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status);
but then the issue is we hang due to the otg power domain not being enabled when ehci_usb_of_to_plat is called and I'm not quite clear why that is. Why would the power domain get probed/enabled for the usbotg2 bus but not the usbotg1 bus? Here is some debugging: u-boot=> usb start starting USB... Bus usb@32e40000: ehci_usb_phy_mode usb@32e40000 usb@32e40000 probe ret=-22 probe failed, error -22 ^^^ probe fails here because ehci_usb_phy_mode returns EINVAL for dr_mode=otg but if we try to read the phy_status reg we will hang b/c power domain is not enabled yet Bus usb@32e50000: imx8m_power_domain_probe gpc@303a0000 imx8m_power_domain_probe pgc ^^^ why did power domain get probed on the 2nd bus and not the first? imx8m_power_domain_probe power-domain@0 imx8m_power_domain_probe power-domain@3 imx8m_power_domain_on power-domain@3 imx8m_power_domain_on power-domain@0 ehci_usb_probe usb@32e50000 USB EHCI 1.00 usb@32e50000 probe ret=0 scanning bus usb@32e50000 for devices... imx8m_power_domain_on power-domain@3 imx8m_power_domain_on power-domain@0 3 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found u-boot=>
I also verified your patch does not break USB for IMX6Q/DL ventana as well.
I am still a bit concerned that the power-domain patches you merged in this series are introducing bindings that are not approved upstream: d78f7d8199 ARM: dts: imx8mn: Add power domain nodes f0e10e33e5 ARM: dts: imx8mm: Add power domain nodes
Are you under the impression that is what will go upstream? I'm still waiting to see what this 'virtual power-domain' patch looks like that I believe Abel or Jacky was going to work on. Perhaps you, Adam, or Frieder took part in that discussion?
Best regards,
Tim

On 4/23/21 5:04 PM, Tim Harvey wrote:
On Thu, Apr 22, 2021 at 12:16 PM Marek Vasut marex@denx.de wrote:
On 4/20/21 2:33 AM, Tim Harvey wrote:
[...]
+/* 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 */
-- 2.30.2
Marek,
Thanks for your work on USB support for IMX8M!
I'm attempting to add USB support to the venice board following this example but I think there are still some things missing from the dt to make this work. I find that mx6_parse_dt_adds failes; Looks like it is required to have an alias that points to the phy but then it fails because the phy doesn't have a reg. Also, it would see the CONFIG_MXC_USB_PORTSC is no longer needed as that is now the default.
Have a look at this patch:
https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/8203ee09275c307...
That should fix it for you.
It would be good however if you could take the mx6 ventana and test the driver there, and possibly submit fixes in case the USB is still broken there. What would be even better is if you could implement the MXS PHY driver, so all the !CONFIG_PHY stuff can be removed for MX6 too. That shouldn't be much effort.
Marek,
That does resolve the issue with mx6_parse_dt_adds failing and works for IMX8MM host mode (and likely peripheral mode) but not for otg. For otg we also need something like: @@ -523,7 +568,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST;
} else if (is_mx7()) {
} else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status);
but then the issue is we hang due to the otg power domain not being enabled when ehci_usb_of_to_plat is called and I'm not quite clear why that is.
ehci_usb_phy_mode() is called from ehci_usb_of_to_plat(), which happens before probe(), so the power domain at that point is off. You would have to move that entire code to probe() to get OTG working properly, without the current workaround.
Why would the power domain get probed/enabled for the usbotg2 bus but not the usbotg1 bus? Here is some debugging: u-boot=> usb start starting USB... Bus usb@32e40000: ehci_usb_phy_mode usb@32e40000 usb@32e40000 probe ret=-22 probe failed, error -22 ^^^ probe fails here because ehci_usb_phy_mode returns EINVAL for dr_mode=otg but if we try to read the phy_status reg we will hang b/c power domain is not enabled yet Bus usb@32e50000: imx8m_power_domain_probe gpc@303a0000 imx8m_power_domain_probe pgc ^^^ why did power domain get probed on the 2nd bus and not the first?
I don't know, can you have a look ?
imx8m_power_domain_probe power-domain@0 imx8m_power_domain_probe power-domain@3 imx8m_power_domain_on power-domain@3 imx8m_power_domain_on power-domain@0 ehci_usb_probe usb@32e50000 USB EHCI 1.00 usb@32e50000 probe ret=0 scanning bus usb@32e50000 for devices... imx8m_power_domain_on power-domain@3 imx8m_power_domain_on power-domain@0 3 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found u-boot=>
I also verified your patch does not break USB for IMX6Q/DL ventana as well.
That's good, thank you
I am still a bit concerned that the power-domain patches you merged in this series are introducing bindings that are not approved upstream: d78f7d8199 ARM: dts: imx8mn: Add power domain nodes f0e10e33e5 ARM: dts: imx8mm: Add power domain nodes
Are you under the impression that is what will go upstream?
Pretty much, yes. And if there are some changes further down the line, we can pick those later when they hit upstream. I think this is better than having no working USB at all.
I'm still waiting to see what this 'virtual power-domain' patch looks like that I believe Abel or Jacky was going to work on. Perhaps you, Adam, or Frieder took part in that discussion?
That is still going on, yes.

On Fri, Apr 23, 2021 at 8:21 AM Marek Vasut marex@denx.de wrote:
On 4/23/21 5:04 PM, Tim Harvey wrote:
On Thu, Apr 22, 2021 at 12:16 PM Marek Vasut marex@denx.de wrote:
On 4/20/21 2:33 AM, Tim Harvey wrote:
[...]
+/* 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 */
-- 2.30.2
Marek,
Thanks for your work on USB support for IMX8M!
I'm attempting to add USB support to the venice board following this example but I think there are still some things missing from the dt to make this work. I find that mx6_parse_dt_adds failes; Looks like it is required to have an alias that points to the phy but then it fails because the phy doesn't have a reg. Also, it would see the CONFIG_MXC_USB_PORTSC is no longer needed as that is now the default.
Have a look at this patch:
https://source.denx.de/u-boot/custodians/u-boot-usb/-/commit/8203ee09275c307...
That should fix it for you.
It would be good however if you could take the mx6 ventana and test the driver there, and possibly submit fixes in case the USB is still broken there. What would be even better is if you could implement the MXS PHY driver, so all the !CONFIG_PHY stuff can be removed for MX6 too. That shouldn't be much effort.
Marek,
That does resolve the issue with mx6_parse_dt_adds failing and works for IMX8MM host mode (and likely peripheral mode) but not for otg. For otg we also need something like: @@ -523,7 +568,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST;
} else if (is_mx7()) {
} else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status);
but then the issue is we hang due to the otg power domain not being enabled when ehci_usb_of_to_plat is called and I'm not quite clear why that is.
ehci_usb_phy_mode() is called from ehci_usb_of_to_plat(), which happens before probe(), so the power domain at that point is off. You would have to move that entire code to probe() to get OTG working properly, without the current workaround.
Why would the power domain get probed/enabled for the usbotg2 bus but not the usbotg1 bus? Here is some debugging: u-boot=> usb start starting USB... Bus usb@32e40000: ehci_usb_phy_mode usb@32e40000 usb@32e40000 probe ret=-22 probe failed, error -22 ^^^ probe fails here because ehci_usb_phy_mode returns EINVAL for dr_mode=otg but if we try to read the phy_status reg we will hang b/c power domain is not enabled yet Bus usb@32e50000: imx8m_power_domain_probe gpc@303a0000 imx8m_power_domain_probe pgc ^^^ why did power domain get probed on the 2nd bus and not the first?
I don't know, can you have a look ?
Marek,
The reg domain does not get enabled for usbotg1 because device_of_to_plat gets called 'before' dev_power_domain_on in device_probe.
The following will get imx8mm USB otg working:
For OTG defer setting type until probe after clock and power have been brought up. index 06be9deaaa..2183ae4f9d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -523,7 +523,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST; - } else if (is_mx7()) { + } else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status); @@ -555,7 +555,10 @@ static int ehci_usb_of_to_plat(struct udevice *dev) break; case USB_DR_MODE_OTG: case USB_DR_MODE_UNKNOWN: - return ehci_usb_phy_mode(dev); + if (is_imx8mm()) + plat->init_type = USB_INIT_HOST; + else + return ehci_usb_phy_mode(dev); };
return 0; @@ -657,6 +660,13 @@ static int ehci_usb_probe(struct udevice *dev) mdelay(1); #endif
+ if (is_imx8mm() && (usb_get_dr_mode(dev_ofnode(dev)) == USB_DR_MODE_OTG)) { + ret = ehci_usb_phy_mode(dev); + if (ret) + return ret; + priv->init_type = plat->init_type; + }; + #if CONFIG_IS_ENABLED(DM_REGULATOR) ret = device_get_supply_regulator(dev, "vbus-supply", &priv->vbus_supply);
imx8m_power_domain_probe power-domain@0 imx8m_power_domain_probe power-domain@3 imx8m_power_domain_on power-domain@3 imx8m_power_domain_on power-domain@0 ehci_usb_probe usb@32e50000 USB EHCI 1.00 usb@32e50000 probe ret=0 scanning bus usb@32e50000 for devices... imx8m_power_domain_on power-domain@3 imx8m_power_domain_on power-domain@0 3 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found u-boot=>
I also verified your patch does not break USB for IMX6Q/DL ventana as well.
That's good, thank you
I am still a bit concerned that the power-domain patches you merged in this series are introducing bindings that are not approved upstream: d78f7d8199 ARM: dts: imx8mn: Add power domain nodes f0e10e33e5 ARM: dts: imx8mm: Add power domain nodes
Are you under the impression that is what will go upstream?
Pretty much, yes. And if there are some changes further down the line, we can pick those later when they hit upstream. I think this is better than having no working USB at all.
I'm still waiting to see what this 'virtual power-domain' patch looks like that I believe Abel or Jacky was going to work on. Perhaps you, Adam, or Frieder took part in that discussion?
That is still going on, yes.

On 4/27/21 2:01 AM, Tim Harvey wrote: [...]
Why would the power domain get probed/enabled for the usbotg2 bus but not the usbotg1 bus? Here is some debugging: u-boot=> usb start starting USB... Bus usb@32e40000: ehci_usb_phy_mode usb@32e40000 usb@32e40000 probe ret=-22 probe failed, error -22 ^^^ probe fails here because ehci_usb_phy_mode returns EINVAL for dr_mode=otg but if we try to read the phy_status reg we will hang b/c power domain is not enabled yet Bus usb@32e50000: imx8m_power_domain_probe gpc@303a0000 imx8m_power_domain_probe pgc ^^^ why did power domain get probed on the 2nd bus and not the first?
I don't know, can you have a look ?
Marek,
The reg domain does not get enabled for usbotg1 because device_of_to_plat gets called 'before' dev_power_domain_on in device_probe.
The following will get imx8mm USB otg working:
For OTG defer setting type until probe after clock and power have been brought up. index 06be9deaaa..2183ae4f9d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -523,7 +523,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST;
} else if (is_mx7()) {
} else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status);
@@ -555,7 +555,10 @@ static int ehci_usb_of_to_plat(struct udevice *dev) break; case USB_DR_MODE_OTG: case USB_DR_MODE_UNKNOWN:
return ehci_usb_phy_mode(dev);
if (is_imx8mm())
Does this mean OTG doesn't work on the 8MM then ?
plat->init_type = USB_INIT_HOST;
else
return ehci_usb_phy_mode(dev); }; return 0;
@@ -657,6 +660,13 @@ static int ehci_usb_probe(struct udevice *dev) mdelay(1); #endif
if (is_imx8mm() && (usb_get_dr_mode(dev_ofnode(dev)) ==
USB_DR_MODE_OTG)) {
ret = ehci_usb_phy_mode(dev);
if (ret)
return ret;
priv->init_type = plat->init_type;
};
I have to wonder, why not move the whole OTG/Host/Device detection to probe then ?
Also, could you submit a regular patch ?

On Mon, Apr 26, 2021, 5:35 PM Marek Vasut marex@denx.de wrote:
On 4/27/21 2:01 AM, Tim Harvey wrote: [...]
Why would the power domain get probed/enabled for the usbotg2 bus but not the usbotg1 bus? Here is some debugging: u-boot=> usb start starting USB... Bus usb@32e40000: ehci_usb_phy_mode usb@32e40000 usb@32e40000 probe ret=-22 probe failed, error -22 ^^^ probe fails here because ehci_usb_phy_mode returns EINVAL for dr_mode=otg but if we try to read the phy_status reg we will hang b/c power domain is not enabled yet Bus usb@32e50000: imx8m_power_domain_probe gpc@303a0000 imx8m_power_domain_probe pgc ^^^ why did power domain get probed on the 2nd bus and not the first?
I don't know, can you have a look ?
Marek,
The reg domain does not get enabled for usbotg1 because device_of_to_plat gets called 'before' dev_power_domain_on in device_probe.
The following will get imx8mm USB otg working:
For OTG defer setting type until probe after clock and power have been brought up. index 06be9deaaa..2183ae4f9d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -523,7 +523,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST;
} else if (is_mx7()) {
} else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status);
@@ -555,7 +555,10 @@ static int ehci_usb_of_to_plat(struct udevice *dev) break; case USB_DR_MODE_OTG: case USB_DR_MODE_UNKNOWN:
return ehci_usb_phy_mode(dev);
if (is_imx8mm())
Does this mean OTG doesn't work on the 8MM then ?
IMX8MM USB in general still doesn't work without your: usb: ehci-mx6: Limit PHY address parsing to !CONFIG_PHY
With your patch, IMX8MM 'host' works but 'otg' will fail probe with -22 (due ehci_usb_phy_mode called from of_to_plat and it not having a case for imx8mm)
plat->init_type = USB_INIT_HOST;
else
return ehci_usb_phy_mode(dev); }; return 0;
@@ -657,6 +660,13 @@ static int ehci_usb_probe(struct udevice *dev) mdelay(1); #endif
if (is_imx8mm() && (usb_get_dr_mode(dev_ofnode(dev)) ==
USB_DR_MODE_OTG)) {
ret = ehci_usb_phy_mode(dev);
if (ret)
return ret;
priv->init_type = plat->init_type;
};
I have to wonder, why not move the whole OTG/Host/Device detection to probe then ?
Yes, I think that is the right thing to do.
Also, could you submit a regular patch ?
Yes, I will post patches to fix IMX8MM OTG. Can you submit your 'usb: ehci-mx6: Limit PHY address parsing to !CONFIG_PHY' patch so I can go on top of that or can I just pull that into my series?
Best regards,
Tim

On Tue, Apr 27, 2021 at 10:50 AM Tim Harvey tharvey@gateworks.com wrote:
On Mon, Apr 26, 2021, 5:35 PM Marek Vasut marex@denx.de wrote:
On 4/27/21 2:01 AM, Tim Harvey wrote: [...]
Why would the power domain get probed/enabled for the usbotg2 bus but not the usbotg1 bus? Here is some debugging: u-boot=> usb start starting USB... Bus usb@32e40000: ehci_usb_phy_mode usb@32e40000 usb@32e40000 probe ret=-22 probe failed, error -22 ^^^ probe fails here because ehci_usb_phy_mode returns EINVAL for dr_mode=otg but if we try to read the phy_status reg we will hang b/c power domain is not enabled yet Bus usb@32e50000: imx8m_power_domain_probe gpc@303a0000 imx8m_power_domain_probe pgc ^^^ why did power domain get probed on the 2nd bus and not the first?
I don't know, can you have a look ?
Marek,
The reg domain does not get enabled for usbotg1 because device_of_to_plat gets called 'before' dev_power_domain_on in device_probe.
The following will get imx8mm USB otg working:
For OTG defer setting type until probe after clock and power have been brought up. index 06be9deaaa..2183ae4f9d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -523,7 +523,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST;
} else if (is_mx7()) {
} else if (is_mx7() || is_imx8mm()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status);
@@ -555,7 +555,10 @@ static int ehci_usb_of_to_plat(struct udevice *dev) break; case USB_DR_MODE_OTG: case USB_DR_MODE_UNKNOWN:
return ehci_usb_phy_mode(dev);
if (is_imx8mm())
Does this mean OTG doesn't work on the 8MM then ?
IMX8MM USB in general still doesn't work without your: usb: ehci-mx6: Limit PHY address parsing to !CONFIG_PHY
With your patch, IMX8MM 'host' works but 'otg' will fail probe with -22 (due ehci_usb_phy_mode called from of_to_plat and it not having a case for imx8mm)
plat->init_type = USB_INIT_HOST;
else
return ehci_usb_phy_mode(dev); }; return 0;
@@ -657,6 +660,13 @@ static int ehci_usb_probe(struct udevice *dev) mdelay(1); #endif
if (is_imx8mm() && (usb_get_dr_mode(dev_ofnode(dev)) ==
USB_DR_MODE_OTG)) {
ret = ehci_usb_phy_mode(dev);
if (ret)
return ret;
priv->init_type = plat->init_type;
};
I have to wonder, why not move the whole OTG/Host/Device detection to probe then ?
Yes, I think that is the right thing to do.
Also, could you submit a regular patch ?
Yes, I will post patches to fix IMX8MM OTG. Can you submit your 'usb: ehci-mx6: Limit PHY address parsing to !CONFIG_PHY' patch so I can go on top of that or can I just pull that into my series?
If you want me to test it on either a Mini or Nano, feel free to CC me as well. I was out of town the last week, so I wasn't in a place to do any work. I am a little behind, so I might need some pointers to prerequisite patches if they're necessary.
thanks,
adam
Best regards,
Tim

On 4/11/21 12:28 PM, Marek Vasut wrote:
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 marex@denx.de Cc: Alexey Brodkin alexey.brodkin@synopsys.com Cc: Eugeniy Paltsev Eugeniy.Paltsev@synopsys.com Cc: Fabio Estevam festevam@gmail.com Cc: Jean-Jacques Hiblot jjhiblot@ti.com Cc: Murali Karicheri m-karicheri2@ti.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de Cc: Ye Li ye.li@nxp.com Cc: uboot-imx uboot-imx@nxp.com
V2: No change
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 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" }, { } };
For the whole series (on i.MX6ULLEVK with mx6ul_14x14_evk_defconfig):
Tested-by: Sean Anderson sean.anderson@seco.com
participants (6)
-
Adam Ford
-
Jaehoon Chung
-
Marek Vasut
-
Sean Anderson
-
Tim Harvey
-
Ying-Chun Liu (PaulLiu)