[U-Boot] [PATCH 0/5] usb: host: dwc2: use driver model for PHY and CLOCK

In this serie I update the DWC2 host driver to use the device tree information and the associated PHY and CLOCK drivers when they are available.
I test this serie on stm32mp157c-ev1 board; The U-CLASS are provided by: - PHY by USBPHYC driver = ./drivers/phy/phy-stm32-usbphyc.c - CLOCK by RCC clock driver = drivers/clk/clk_stm32mp1.c - RESET by RCC reset driver = drivers/reset/stm32-reset.c
And I activate the configuration +CONFIG_USB_DWC2=y
PS: it is not the default configuration to avoid conflict with gadget driver
To solve a binding issue, I also deactivate the gadget support: by default only one driver is bound to theusbotg_hs node with "snps,dwc2" compatible, and today it is the device one (the first in the driver list).
I also need to deactivate hnp-srp support with:
&usbotg_hs { /* need to disable ONLY for HOST support */ hnp-srp-disable; };
WARNING: OTG with device or host support is not correctly handle by DWC2 driver (see example for dynamic OTG role in DWC3 driver).
The tests executed on the stm32mp157c-ev1 target:
STM32MP> usb start starting USB... Bus usb-otg@49000000: USB DWC2 Bus usbh-ehci@5800d000: USB EHCI 1.00 scanning bus usb-otg@49000000 for devices... 2 USB Device(s) found scanning bus usbh-ehci@5800d000 for devices... 3 USB Device(s) found scanning usb for storage devices... 2 Storage Device(s) found STM32MP> usb tree USB device tree: 1 Hub (480 Mb/s, 0mA) | U-Boot Root Hub | +-2 Mass Storage (480 Mb/s, 300mA) Verbatim STORE N GO 070731C8ACD7EE97
1 Hub (480 Mb/s, 0mA) | u-boot EHCI Host Controller | +-2 Hub (480 Mb/s, 2mA) | +-3 Mass Storage (480 Mb/s, 500mA) Generic USB Storage
STM32MP> ls usb 0 <DIR> 4096 . <DIR> 4096 .. <DIR> 16384 lost+found <DIR> 4096 record 1490212 xipImage 21058006 vmlinux
STM32MP> load usb 0 0xC0000000 vmlinux 21058006 bytes read in 10851 ms (1.9 MiB/s)
Patrick Delaunay (5): usb: host: dwc2: add phy support usb: host: dwc2: add support for clk usb: host: dwc2: force reset assert usb: host: dwc2: add usb33d supply support for stm32mp1 usb: host: dwc2: add trace to have clean usb start
drivers/usb/host/dwc2.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-)

Use generic phy to initialize the PHY associated to the DWC2 device and available in the device tree.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/host/dwc2.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index a62a2f8..6c46979 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -7,6 +7,7 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <generic-phy.h> #include <usb.h> #include <malloc.h> #include <memalign.h> @@ -35,6 +36,7 @@ struct dwc2_priv { #ifdef CONFIG_DM_REGULATOR struct udevice *vbus_supply; #endif + struct phy phy; #else uint8_t *aligned_buffer; uint8_t *status_buffer; @@ -1317,13 +1319,70 @@ static int dwc2_usb_ofdata_to_platdata(struct udevice *dev) return 0; }
+static int dwc2_setup_phy(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + ret = generic_phy_get_by_index(dev, 0, &priv->phy); + if (ret) { + if (ret != -ENOENT) { + dev_err(dev, "failed to get usb phy\n"); + return ret; + } + return 0; + } + + ret = generic_phy_init(&priv->phy); + if (ret) { + dev_err(dev, "failed to init usb phy\n"); + return ret; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + dev_err(dev, "failed to power on usb phy\n"); + return generic_phy_exit(&priv->phy); + } + + return 0; +} + +static int dwc2_shutdown_phy(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + if (!generic_phy_valid(&priv->phy)) + return 0; + + ret = generic_phy_power_off(&priv->phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + + ret = generic_phy_exit(&priv->phy); + if (ret) { + dev_err(dev, "failed to power off usb phy\n"); + return ret; + } + + return 0; +} + static int dwc2_usb_probe(struct udevice *dev) { struct dwc2_priv *priv = dev_get_priv(dev); struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev); + int ret;
bus_priv->desc_before_addr = true;
+ ret = dwc2_setup_phy(dev); + if (ret) + return ret; + return dwc2_init_common(dev, priv); }
@@ -1336,6 +1395,8 @@ static int dwc2_usb_remove(struct udevice *dev) if (ret) return ret;
+ dwc2_shutdown_phy(dev); + dwc2_uninit_common(priv->regs);
reset_release_bulk(&priv->resets);

Add support for clock with driver model.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/host/dwc2.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 6c46979..5c4c21b 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -5,13 +5,14 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> #include <errno.h> #include <generic-phy.h> -#include <usb.h> #include <malloc.h> #include <memalign.h> #include <phys2bus.h> +#include <usb.h> #include <usbroothubdes.h> #include <wait_bit.h> #include <asm/io.h> @@ -37,6 +38,7 @@ struct dwc2_priv { struct udevice *vbus_supply; #endif struct phy phy; + struct clk_bulk clks; #else uint8_t *aligned_buffer; uint8_t *status_buffer; @@ -1371,6 +1373,26 @@ static int dwc2_shutdown_phy(struct udevice *dev) return 0; }
+static int dwc2_clk_init(struct udevice *dev) +{ + struct dwc2_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(&priv->clks); + if (ret) { + clk_release_bulk(&priv->clks); + return ret; + } + + return 0; +} + static int dwc2_usb_probe(struct udevice *dev) { struct dwc2_priv *priv = dev_get_priv(dev); @@ -1379,6 +1401,10 @@ static int dwc2_usb_probe(struct udevice *dev)
bus_priv->desc_before_addr = true;
+ ret = dwc2_clk_init(dev); + if (ret) + return ret; + ret = dwc2_setup_phy(dev); if (ret) return ret; @@ -1400,6 +1426,7 @@ static int dwc2_usb_remove(struct udevice *dev) dwc2_uninit_common(priv->regs);
reset_release_bulk(&priv->resets); + clk_release_bulk(&priv->clks);
return 0; }

Assert reset before deassert in dwc2_reset; It should be more safe for DWC2.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/host/dwc2.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 5c4c21b..836f706 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1148,6 +1148,8 @@ static int dwc2_reset(struct udevice *dev) return ret; }
+ reset_assert_bulk(&priv->resets); + udelay(2); ret = reset_deassert_bulk(&priv->resets); if (ret) { reset_release_bulk(&priv->resets);

Enable the usb33d-supply on STM32MP1 SoCs (with "st,stm32mp1-hsotg" compatible), it is the external VBUS and ID sensing comparators supply needed to perform OTG operation.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/host/dwc2.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 836f706..1639bf2 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1411,6 +1411,24 @@ static int dwc2_usb_probe(struct udevice *dev) if (ret) return ret;
+ if (CONFIG_IS_ENABLED(ARCH_STM32MP) && + device_is_compatible(dev, "st,stm32mp1-hsotg")) { + struct udevice *usb33d_supply; + + ret = device_get_supply_regulator(dev, "usb33d-supply", + &usb33d_supply); + if (ret) { + dev_err(dev, + "can't get voltage level detector supply\n"); + } else { + ret = regulator_set_enable(usb33d_supply, true); + if (ret) { + dev_err(dev, + "can't enable voltage level detector supply\n"); + } + } + } + return dwc2_init_common(dev, priv); }

Solve issue for the display of "usb start" command on stm32mp1 because one carriage return is missing in DWC2 probe.
STM32MP> usb start starting USB... Bus usb-otg@49000000: Bus usbh-ehci@5800d000: USB EHCI 1.00
after the patch:
STM32MP> usb start starting USB... Bus usb-otg@49000000: USB DWC2 Bus usbh-ehci@5800d000: USB EHCI 1.00
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/host/dwc2.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 1639bf2..7c1af0a 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1216,6 +1216,8 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) mdelay(1000);
+ printf("USB DWC2\n"); + return 0; }
participants (1)
-
Patrick Delaunay