[U-Boot] [PATCH 00/16] usb: convert dwc2 gadget to driver model, used in stm32mp1

This patch-set created after Marek remarks on patch board: stm32mp1: Add tx_fifo_sz_array support http://patchwork.ozlabs.org/patch/1056452/
This serie convert the DWC2 to driver model and use it for the stm32mp1 boards.
USB device and cable connection tested on EV1 and DK2.
This serie superseded the Patrice patches: http://patchwork.ozlabs.org/project/uboot/list/?series=97121
Warning: the serie need to be apply after http://patchwork.ozlabs.org/project/uboot/list/?series=91422 http://patchwork.ozlabs.org/project/uboot/list/?series=91497
Patrice Chotard (1): usb: dwc2_udc_otg: Add tx_fifo_sz array support
Patrick Delaunay (15): phy: usbphyc: remove unused variable index phy: usbphyc: update xlate with DT binding phy: usbphyc: Binding update of vdda supply phy: usbphyc: move vdda1v1 and vdda1v8 in phy_init phy: usbphyc: increase PLL wait timeout usb: dwc2: remove unused variable regs_otg usb: dwc2: convert driver to DM_USB_GADGET usb: dwc2: force reset assert before to probe the driver usb: dwc2: Add force-b-session-valid support usb: dwc2: Add function for session B check usb: dwc2_udc_otg: Read MAX_HW_ENDPOINT from HWCFG4 register usb: dwc2: add support for STM32MP1 stm32mp1: remove CONFIG_USB_DWC2, HOST support for USBO stm32mp1: migrate USBOTG device to driver model stm32mp1: add stusb1600 support for DK1 and DK2 board
arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 + arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 3 +- arch/arm/dts/stm32mp157a-dk1.dts | 34 +- arch/arm/dts/stm32mp157c-ed1.dts | 8 - arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 1 + arch/arm/dts/stm32mp157c.dtsi | 5 +- board/st/stm32mp1/stm32mp1.c | 185 +++------- configs/stm32mp15_basic_defconfig | 2 +- configs/stm32mp15_trusted_defconfig | 2 +- doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt | 4 +- doc/device-tree-bindings/usb/dwc2.txt | 58 +++ drivers/phy/phy-stm32-usbphyc.c | 111 +++--- drivers/usb/gadget/dwc2_udc_otg.c | 388 ++++++++++++++++++++- drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 31 +- include/usb/dwc2_udc.h | 7 + 16 files changed, 627 insertions(+), 220 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt

Remove unused field index in struct stm32_usbphyc_phy.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/phy/phy-stm32-usbphyc.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 8e98b4b..fc53df2 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -55,7 +55,6 @@ struct stm32_usbphyc { struct udevice *vdd; struct udevice *vdda1v1; struct udevice *vdda1v8; - int index; bool init; bool powered; } phys[MAX_PHYS]; @@ -359,7 +358,6 @@ static int stm32_usbphyc_probe(struct udevice *dev) for (i = 0; i < MAX_PHYS; i++) { struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + i;
- usbphyc_phy->index = i; usbphyc_phy->init = false; usbphyc_phy->powered = false; ret = stm32_usbphyc_get_regulator(dev, node, "phy-supply",

Parameter added for port 1, for example:
&usbh_ehci { phys = <&usbphyc_port0>; phy-names = "usb"; vbus-supply = <&vbus_sw>; status = "okay"; };
&usbotg_hs { pinctrl-names = "default"; pinctrl-0 = <&usbotg_hs_pins_a>; phys = <&usbphyc_port1 0>; phy-names = "usb2-phy"; status = "okay"; };
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/phy/phy-stm32-usbphyc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index fc53df2..ec5b47c 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -297,19 +297,20 @@ static int stm32_usbphyc_get_regulator(struct udevice *dev, ofnode node, static int stm32_usbphyc_of_xlate(struct phy *phy, struct ofnode_phandle_args *args) { - if (args->args_count > 1) { - pr_debug("%s: invalid args_count: %d\n", __func__, - args->args_count); - return -EINVAL; - } + if (args->args_count < 1) + return -ENODEV;
if (args->args[0] >= MAX_PHYS) return -ENODEV;
- if (args->args_count) - phy->id = args->args[0]; - else - phy->id = 0; + phy->id = args->args[0]; + + if ((phy->id == 0 && args->args_count != 1) || + (phy->id == 1 && args->args_count != 2)) { + dev_err(dev, "invalid number of cells for phy port%ld\n", + phy->id); + return -EINVAL; + }
return 0; }

Move supply vdda1v1 and vdda1v8 in usbphyc node and no more in port
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/dts/stm32mp157c-ed1.dts | 8 ---- arch/arm/dts/stm32mp157c.dtsi | 3 ++ doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt | 4 +- drivers/phy/phy-stm32-usbphyc.c | 54 ++++++++++++---------- 4 files changed, 35 insertions(+), 34 deletions(-)
diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts index 2664c9c..0366782 100644 --- a/arch/arm/dts/stm32mp157c-ed1.dts +++ b/arch/arm/dts/stm32mp157c-ed1.dts @@ -382,18 +382,10 @@ status = "okay"; };
-&usbotg_hs { - usb33d-supply = <&usb33>; -}; - &usbphyc_port0 { phy-supply = <&vdd_usb>; - vdda1v1-supply = <®11>; - vdda1v8-supply = <®18>; };
&usbphyc_port1 { phy-supply = <&vdd_usb>; - vdda1v1-supply = <®11>; - vdda1v8-supply = <®18>; }; diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index 223af2e..f1375a9 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -836,6 +836,7 @@ g-np-tx-fifo-size = <32>; g-tx-fifo-size = <128 128 64 64 64 64 32 32>; dr_mode = "otg"; + usb33d-supply = <&usb33>; status = "disabled"; };
@@ -1165,6 +1166,8 @@ reg = <0x5a006000 0x1000>; clocks = <&rcc USBPHY_K>; resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; status = "disabled";
usbphyc_port0: usb-phy@0 { diff --git a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt index 725ae71..da98407 100644 --- a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt +++ b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt @@ -23,6 +23,8 @@ Required properties: - compatible: must be "st,stm32mp1-usbphyc" - reg: address and length of the usb phy control register set - clocks: phandle + clock specifier for the PLL phy clock +- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY +- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY - #address-cells: number of address cells for phys sub-nodes, must be <1> - #size-cells: number of size cells for phys sub-nodes, must be <0>
@@ -40,8 +42,6 @@ Required properties: - reg: phy port index - phy-supply: phandle to the regulator providing 3V3 power to the PHY, see phy-bindings.txt in the same directory. -- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY -- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY - #phy-cells: see phy-bindings.txt in the same directory, must be <0> for PHY port#1 and must be <1> for PHY port#2, to select USB controller
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index ec5b47c..617c5a0 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -51,10 +51,10 @@ struct pll_params { struct stm32_usbphyc { fdt_addr_t base; struct clk clk; + struct udevice *vdda1v1; + struct udevice *vdda1v8; struct stm32_usbphyc_phy { struct udevice *vdd; - struct udevice *vdda1v1; - struct udevice *vdda1v8; bool init; bool powered; } phys[MAX_PHYS]; @@ -212,19 +212,20 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy) int ret;
pr_debug("%s phy ID = %lu\n", __func__, phy->id); - if (usbphyc_phy->vdda1v1) { - ret = regulator_set_enable(usbphyc_phy->vdda1v1, true); + if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, true); if (ret) return ret; }
- if (usbphyc_phy->vdda1v8) { - ret = regulator_set_enable(usbphyc_phy->vdda1v8, true); + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, true); if (ret) return ret; } - if (usbphyc_phy->vdd) { - ret = regulator_set_enable(usbphyc_phy->vdd, true); + + if (usbphyc->vdd) { + ret = regulator_set_enable(usbphyc->vdd, true); if (ret) return ret; } @@ -246,20 +247,20 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy) if (stm32_usbphyc_is_powered(usbphyc)) return 0;
- if (usbphyc_phy->vdda1v1) { - ret = regulator_set_enable(usbphyc_phy->vdda1v1, false); + if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, false); if (ret) return ret; }
- if (usbphyc_phy->vdda1v8) { - ret = regulator_set_enable(usbphyc_phy->vdda1v8, false); + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, false); if (ret) return ret; }
- if (usbphyc_phy->vdd) { - ret = regulator_set_enable(usbphyc_phy->vdd, false); + if (usbphyc->vdd) { + ret = regulator_set_enable(usbphyc->vdd, false); if (ret) return ret; } @@ -351,6 +352,21 @@ static int stm32_usbphyc_probe(struct udevice *dev) reset_deassert(&reset); }
+ /* get usbphyc regulator */ + ret = device_get_supply_regulator(dev, "vdda1v1-supply", + &usbphyc->vdda1v1); + if (ret) { + dev_err(dev, "Can't get vdda1v1-supply regulator\n"); + return ret; + } + + ret = device_get_supply_regulator(dev, "vdda1v8-supply", + &usbphyc->vdda1v8); + if (ret) { + dev_err(dev, "Can't get vdda1v8-supply regulator\n"); + return ret; + } + /* * parse all PHY subnodes in order to populate regulator associated * to each PHY port @@ -366,16 +382,6 @@ static int stm32_usbphyc_probe(struct udevice *dev) if (ret) return ret;
- ret = stm32_usbphyc_get_regulator(dev, node, "vdda1v1-supply", - &usbphyc_phy->vdda1v1); - if (ret) - return ret; - - ret = stm32_usbphyc_get_regulator(dev, node, "vdda1v8-supply", - &usbphyc_phy->vdda1v8); - if (ret) - return ret; - node = dev_read_next_subnode(node); }

vdda1v1 and vdda1v8 are used by the PLL. Both need to be enabled before starting the PLL.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/phy/phy-stm32-usbphyc.c | 60 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-)
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 617c5a0..54363cd 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -60,7 +60,8 @@ struct stm32_usbphyc { } phys[MAX_PHYS]; };
-void stm32_usbphyc_get_pll_params(u32 clk_rate, struct pll_params *pll_params) +static void stm32_usbphyc_get_pll_params(u32 clk_rate, + struct pll_params *pll_params) { unsigned long long fvco, ndiv, frac;
@@ -153,6 +154,18 @@ static int stm32_usbphyc_phy_init(struct phy *phy) if (pllen && stm32_usbphyc_is_init(usbphyc)) goto initialized;
+ if (usbphyc->vdda1v1) { + ret = regulator_set_enable(usbphyc->vdda1v1, true); + if (ret) + return ret; + } + + if (usbphyc->vdda1v8) { + ret = regulator_set_enable(usbphyc->vdda1v8, true); + if (ret) + return ret; + } + if (pllen) { clrbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN); udelay(PLL_PWR_DOWN_TIME_US); @@ -183,6 +196,7 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) { struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; + int ret;
pr_debug("%s phy ID = %lu\n", __func__, phy->id); usbphyc_phy->init = false; @@ -202,30 +216,30 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) if (readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN) return -EIO;
- return 0; -} - -static int stm32_usbphyc_phy_power_on(struct phy *phy) -{ - struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); - struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; - int ret; - - pr_debug("%s phy ID = %lu\n", __func__, phy->id); if (usbphyc->vdda1v1) { - ret = regulator_set_enable(usbphyc->vdda1v1, true); + ret = regulator_set_enable(usbphyc->vdda1v1, false); if (ret) return ret; }
if (usbphyc->vdda1v8) { - ret = regulator_set_enable(usbphyc->vdda1v8, true); + ret = regulator_set_enable(usbphyc->vdda1v8, false); if (ret) return ret; }
- if (usbphyc->vdd) { - ret = regulator_set_enable(usbphyc->vdd, true); + return 0; +} + +static int stm32_usbphyc_phy_power_on(struct phy *phy) +{ + struct stm32_usbphyc *usbphyc = dev_get_priv(phy->dev); + struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id; + int ret; + + pr_debug("%s phy ID = %lu\n", __func__, phy->id); + if (usbphyc_phy->vdd) { + ret = regulator_set_enable(usbphyc_phy->vdd, true); if (ret) return ret; } @@ -247,20 +261,8 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy) if (stm32_usbphyc_is_powered(usbphyc)) return 0;
- if (usbphyc->vdda1v1) { - ret = regulator_set_enable(usbphyc->vdda1v1, false); - if (ret) - return ret; - } - - if (usbphyc->vdda1v8) { - ret = regulator_set_enable(usbphyc->vdda1v8, false); - if (ret) - return ret; - } - - if (usbphyc->vdd) { - ret = regulator_set_enable(usbphyc->vdd, false); + if (usbphyc_phy->vdd) { + ret = regulator_set_enable(usbphyc_phy->vdd, false); if (ret) return ret; }

wait 200us to solve USB init issue on device mode (ums and stm32prog commands)
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/phy/phy-stm32-usbphyc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 54363cd..6f11190 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -37,7 +37,8 @@
#define MAX_PHYS 2
-#define PLL_LOCK_TIME_US 100 +/* max 100 us for PLL lock and 100 us for PHY init */ +#define PLL_INIT_TIME_US 200 #define PLL_PWR_DOWN_TIME_US 5 #define PLL_FVCO 2880 /* in MHz */ #define PLL_INFF_MIN_RATE 19200000 /* in Hz */ @@ -177,11 +178,8 @@ static int stm32_usbphyc_phy_init(struct phy *phy)
setbits_le32(usbphyc->base + STM32_USBPHYC_PLL, PLLEN);
- /* - * We must wait PLL_LOCK_TIME_US before checking that PLLEN - * bit is still set - */ - udelay(PLL_LOCK_TIME_US); + /* We must wait PLL_INIT_TIME_US before using PHY */ + udelay(PLL_INIT_TIME_US);
if (!(readl(usbphyc->base + STM32_USBPHYC_PLL) & PLLEN)) return -EIO;

Remove the global regs_otg variable.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/gadget/dwc2_udc_otg.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3c7ad03..edca05d 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -140,7 +140,6 @@ static struct usb_ep_ops dwc2_ep_ops = {
/***********************************************************/
-void __iomem *regs_otg; struct dwc2_usbotg_reg *reg;
bool dfu_usb_get_reset(void) @@ -818,8 +817,6 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata)
reg = (struct dwc2_usbotg_reg *)pdata->regs_otg;
- /* regs_otg = (void *)pdata->regs_otg; */ - dev->gadget.is_dualspeed = 1; /* Hack only*/ dev->gadget.is_otg = 0; dev->gadget.is_a_peripheral = 0;

On Fri, 29 Mar 2019 15:42:14 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Remove the global regs_otg variable.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/usb/gadget/dwc2_udc_otg.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3c7ad03..edca05d 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -140,7 +140,6 @@ static struct usb_ep_ops dwc2_ep_ops = {
/***********************************************************/
-void __iomem *regs_otg; struct dwc2_usbotg_reg *reg;
bool dfu_usb_get_reset(void) @@ -818,8 +817,6 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) reg = (struct dwc2_usbotg_reg *)pdata->regs_otg;
- /* regs_otg = (void *)pdata->regs_otg; */
- dev->gadget.is_dualspeed = 1; /* Hack only*/ dev->gadget.is_otg = 0; dev->gadget.is_a_peripheral = 0;
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Minimal conversion to driver model by using the uclass UCLASS_USB_GADGET_GENERIC based on: - reset uclass - clock uclass - generic uclass.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
doc/device-tree-bindings/usb/dwc2.txt | 54 +++++++ drivers/usb/gadget/dwc2_udc_otg.c | 292 +++++++++++++++++++++++++++++++++- 2 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt new file mode 100644 index 0000000..6dc3c4a --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -0,0 +1,54 @@ +Platform DesignWare HS OTG USB 2.0 controller +----------------------------------------------------- + +Required properties: +- compatible : One of: + - brcm,bcm2835-usb: The DWC2 USB controller instance in the BCM2835 SoC. + - hisilicon,hi6220-usb: The DWC2 USB controller instance in the hi6220 SoC. + - rockchip,rk3066-usb: The DWC2 USB controller instance in the rk3066 Soc; + - "rockchip,px30-usb", "rockchip,rk3066-usb", "snps,dwc2": for px30 Soc; + - "rockchip,rk3188-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3188 Soc; + - "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc; + - "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs; + - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs; + - "amlogic,meson8-usb": The DWC2 USB controller instance in Amlogic Meson8 SoCs; + - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs; + - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs; + - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs; + - snps,dwc2: A generic DWC2 USB controller with default parameters. + - "st,stm32f4x9-fsotg": The DWC2 USB FS/HS controller instance in STM32F4x9 SoCs + configured in FS mode; + - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs + configured in HS mode; + - "st,stm32f7-hsotg": The DWC2 USB HS controller instance in STM32F7 SoCs + configured in HS mode; +- reg : Should contain 1 register range (address and length) +- interrupts : Should contain 1 interrupt +- clocks: clock provider specifier +- clock-names: shall be "otg" +Refer to clk/clock-bindings.txt for generic clock consumer properties + +Optional properties: +- phys: phy provider specifier +- phy-names: shall be "usb2-phy" +Refer to phy/phy-bindings.txt for generic phy consumer properties +- dr_mode: shall be one of "host", "peripheral" and "otg" + Refer to usb/generic.txt +- g-rx-fifo-size: size of rx fifo size in gadget mode. +- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode. +- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. + +Deprecated properties: +- g-use-dma: gadget DMA mode is automatically detected + +Example: + + usb@101c0000 { + compatible = "ralink,rt3050-usb, snps,dwc2"; + reg = <0x101c0000 40000>; + interrupts = <18>; + clocks = <&usb_otg_ahb_clk>; + clock-names = "otg"; + phys = <&usbphy>; + phy-names = "usb2-phy"; + }; diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index edca05d..af16fc1 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -18,11 +18,17 @@ */ #undef DEBUG #include <common.h> +#include <clk.h> +#include <dm.h> +#include <generic-phy.h> +#include <malloc.h> +#include <reset.h> + #include <linux/errno.h> #include <linux/list.h> -#include <malloc.h>
#include <linux/usb/ch9.h> +#include <linux/usb/otg.h> #include <linux/usb/gadget.h>
#include <asm/byteorder.h> @@ -31,6 +37,8 @@
#include <asm/mach-types.h>
+#include <power/regulator.h> + #include "dwc2_udc_otg_regs.h" #include "dwc2_udc_otg_priv.h"
@@ -222,6 +230,7 @@ static int udc_enable(struct dwc2_udc *dev) return 0; }
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET) /* Register entry point for the peripheral controller driver. */ @@ -296,6 +305,54 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_disable(dev); return 0; } +#else /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */ + +static int dwc2_gadget_start(struct usb_gadget *g, + struct usb_gadget_driver *driver) +{ + struct dwc2_udc *dev = the_controller; + + debug_cond(DEBUG_SETUP != 0, "%s: %s\n", __func__, "no name"); + + if (!driver || + (driver->speed != USB_SPEED_FULL && + driver->speed != USB_SPEED_HIGH) || + !driver->bind || !driver->disconnect || !driver->setup) + return -EINVAL; + + if (!dev) + return -ENODEV; + + if (dev->driver) + return -EBUSY; + + /* first hook up the driver ... */ + dev->driver = driver; + + debug_cond(DEBUG_SETUP != 0, + "Registered gadget driver %s\n", dev->gadget.name); + return udc_enable(dev); +} + +static int dwc2_gadget_stop(struct usb_gadget *g) +{ + struct dwc2_udc *dev = the_controller; + + if (!dev) + return -ENODEV; + + if (!dev->driver) + return -EINVAL; + + dev->driver = 0; + stop_activity(dev, dev->driver); + + udc_disable(dev); + + return 0; +} + +#endif /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
/* * done - retire a request; caller blocked irqs @@ -730,6 +787,10 @@ static void dwc2_fifo_flush(struct usb_ep *_ep)
static const struct usb_gadget_ops dwc2_udc_ops = { /* current versions must always be self-powered */ +#if CONFIG_IS_ENABLED(DM_USB_GADGET) + .udc_start = dwc2_gadget_start, + .udc_stop = dwc2_gadget_stop, +#endif };
static struct dwc2_udc memory = { @@ -841,12 +902,239 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) return retval; }
-int usb_gadget_handle_interrupts(int index) +int dwc2_udc_handle_interrupt(void) { u32 intr_status = readl(®->gintsts); u32 gintmsk = readl(®->gintmsk);
if (intr_status & gintmsk) return dwc2_udc_irq(1, (void *)the_controller); + + return 0; +} + +#if !CONFIG_IS_ENABLED(DM_USB_GADGET) + +int usb_gadget_handle_interrupts(int index) +{ + return dwc2_udc_handle_interrupt(); +} + +#else /* CONFIG_IS_ENABLED(DM_USB_GADGET) */ + +struct dwc2_priv_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + struct phy *phys; + int num_phys; +}; + +int dm_usb_gadget_handle_interrupts(struct udevice *dev) +{ + return dwc2_udc_handle_interrupt(); +} + +int dwc2_phy_setup(struct udevice *dev, struct phy **array, int *num_phys) +{ + int i, ret, count; + struct phy *usb_phys; + + /* Return if no phy declared */ + if (!dev_read_prop(dev, "phys", NULL)) + return 0; + + count = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); + if (count <= 0) + return count; + + usb_phys = devm_kcalloc(dev, count, sizeof(struct phy), + GFP_KERNEL); + if (!usb_phys) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = generic_phy_get_by_index(dev, i, &usb_phys[i]); + if (ret && ret != -ENOENT) { + dev_err(dev, "Failed to get USB PHY%d for %s\n", + i, dev->name); + return ret; + } + } + + for (i = 0; i < count; i++) { + ret = generic_phy_init(&usb_phys[i]); + if (ret) { + dev_err(dev, "Can't init USB PHY%d for %s\n", + i, dev->name); + goto phys_init_err; + } + } + + for (i = 0; i < count; i++) { + ret = generic_phy_power_on(&usb_phys[i]); + if (ret) { + dev_err(dev, "Can't power USB PHY%d for %s\n", + i, dev->name); + goto phys_poweron_err; + } + } + + *array = usb_phys; + *num_phys = count; + return 0; + +phys_poweron_err: + for (i = count - 1; i >= 0; i--) + generic_phy_power_off(&usb_phys[i]); + + for (i = 0; i < count; i++) + generic_phy_exit(&usb_phys[i]); + + return ret; + +phys_init_err: + for (; i >= 0; i--) + generic_phy_exit(&usb_phys[i]); + + return ret; } + +void dwc2_phy_shutdown(struct udevice *dev, struct phy *usb_phys, int num_phys) +{ + int i, ret; + + for (i = 0; i < num_phys; i++) { + if (!generic_phy_valid(&usb_phys[i])) + continue; + + ret = generic_phy_power_off(&usb_phys[i]); + ret |= generic_phy_exit(&usb_phys[i]); + if (ret) { + dev_err(dev, "Can't shutdown USB PHY%d for %s\n", + i, dev->name); + } + } +} + +static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) +{ + struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); + int node = dev_of_offset(dev); + + if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) { + dev_dbg(dev, "Invalid mode\n"); + return -ENODEV; + } + + platdata->regs_otg = dev_read_addr(dev); + + platdata->rx_fifo_sz = dev_read_u32_default(dev, "g-rx-fifo-size", 0); + platdata->np_tx_fifo_sz = dev_read_u32_default(dev, + "g-np-tx-fifo-size", 0); + platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0); + + return 0; +} + +static int dwc2_udc_otg_reset_init(struct udevice *dev, + struct reset_ctl_bulk *resets) +{ + int ret; + + ret = reset_get_bulk(dev, resets); + if (ret == -ENOTSUPP) + return 0; + + if (ret) + return ret; + + ret = reset_deassert_bulk(resets); + if (ret) { + reset_release_bulk(resets); + return ret; + } + + return 0; +} + +static int dwc2_udc_otg_clk_init(struct udevice *dev, + struct clk_bulk *clks) +{ + int ret; + + ret = clk_get_bulk(dev, clks); + if (ret == -ENOSYS) + return 0; + + if (ret) + return ret; + + ret = clk_enable_bulk(clks); + if (ret) { + clk_release_bulk(clks); + return ret; + } + + return 0; +} + +static int dwc2_udc_otg_probe(struct udevice *dev) +{ + struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); + struct dwc2_priv_data *priv = dev_get_priv(dev); + int ret; + + ret = dwc2_udc_otg_clk_init(dev, &priv->clks); + if (ret) + return ret; + + ret = dwc2_udc_otg_reset_init(dev, &priv->resets); + if (ret) + return ret; + + ret = dwc2_phy_setup(dev, &priv->phys, &priv->num_phys); + if (ret) + return ret; + + ret = dwc2_udc_probe(platdata); + if (ret) + return ret; + + the_controller->driver = 0; + + ret = usb_add_gadget_udc((struct device *)dev, &the_controller->gadget); + + return ret; +} + +static int dwc2_udc_otg_remove(struct udevice *dev) +{ + struct dwc2_priv_data *priv = dev_get_priv(dev); + + usb_del_gadget_udc(&the_controller->gadget); + + reset_release_bulk(&priv->resets); + + clk_release_bulk(&priv->clks); + + dwc2_phy_shutdown(dev, priv->phys, priv->num_phys); + + return dm_scan_fdt_dev(dev); +} + +static const struct udevice_id dwc2_udc_otg_ids[] = { + { .compatible = "snps,dwc2" }, +}; + +U_BOOT_DRIVER(dwc2_udc_otg) = { + .name = "dwc2-udc-otg", + .id = UCLASS_USB_GADGET_GENERIC, + .of_match = dwc2_udc_otg_ids, + .ofdata_to_platdata = dwc2_udc_otg_ofdata_to_platdata, + .probe = dwc2_udc_otg_probe, + .remove = dwc2_udc_otg_remove, + .platdata_auto_alloc_size = sizeof(struct dwc2_plat_otg_data), + .priv_auto_alloc_size = sizeof(struct dwc2_priv_data), +}; +#endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */

On Fri, 29 Mar 2019 15:42:15 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Minimal conversion to driver model by using the uclass UCLASS_USB_GADGET_GENERIC based on:
- reset uclass
- clock uclass
- generic uclass.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
doc/device-tree-bindings/usb/dwc2.txt | 54 +++++++ drivers/usb/gadget/dwc2_udc_otg.c | 292 +++++++++++++++++++++++++++++++++- 2 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt new file mode 100644 index 0000000..6dc3c4a --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -0,0 +1,54 @@ +Platform DesignWare HS OTG USB 2.0 controller +-----------------------------------------------------
+Required properties: +- compatible : One of:
- brcm,bcm2835-usb: The DWC2 USB controller instance in the
BCM2835 SoC.
- hisilicon,hi6220-usb: The DWC2 USB controller instance in the
hi6220 SoC.
- rockchip,rk3066-usb: The DWC2 USB controller instance in the
rk3066 Soc;
- "rockchip,px30-usb", "rockchip,rk3066-usb", "snps,dwc2": for
px30 Soc;
- "rockchip,rk3188-usb", "rockchip,rk3066-usb", "snps,dwc2": for
rk3188 Soc;
- "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for
rk3288 Soc;
- "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq
ARX SoCs;
- "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq
XRX SoCs;
- "amlogic,meson8-usb": The DWC2 USB controller instance in
Amlogic Meson8 SoCs;
- "amlogic,meson8b-usb": The DWC2 USB controller instance in
Amlogic Meson8b SoCs;
- "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in
Amlogic S905 SoCs;
- "amcc,dwc-otg": The DWC2 USB controller instance in AMCC
Canyonlands 460EX SoCs;
- snps,dwc2: A generic DWC2 USB controller with default parameters.
- "st,stm32f4x9-fsotg": The DWC2 USB FS/HS controller instance in
STM32F4x9 SoCs
- configured in FS mode;
- "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in
STM32F4x9 SoCs
- configured in HS mode;
- "st,stm32f7-hsotg": The DWC2 USB HS controller instance in
STM32F7 SoCs
- configured in HS mode;
+- reg : Should contain 1 register range (address and length) +- interrupts : Should contain 1 interrupt +- clocks: clock provider specifier +- clock-names: shall be "otg" +Refer to clk/clock-bindings.txt for generic clock consumer properties
+Optional properties: +- phys: phy provider specifier +- phy-names: shall be "usb2-phy" +Refer to phy/phy-bindings.txt for generic phy consumer properties +- dr_mode: shall be one of "host", "peripheral" and "otg"
- Refer to usb/generic.txt
+- g-rx-fifo-size: size of rx fifo size in gadget mode. +- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode. +- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. + +Deprecated properties: +- g-use-dma: gadget DMA mode is automatically detected
+Example:
usb@101c0000 {
compatible = "ralink,rt3050-usb, snps,dwc2";
reg = <0x101c0000 40000>;
interrupts = <18>;
clocks = <&usb_otg_ahb_clk>;
clock-names = "otg";
phys = <&usbphy>;
phy-names = "usb2-phy";
};
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index edca05d..af16fc1 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -18,11 +18,17 @@ */ #undef DEBUG #include <common.h> +#include <clk.h> +#include <dm.h> +#include <generic-phy.h> +#include <malloc.h> +#include <reset.h>
#include <linux/errno.h> #include <linux/list.h> -#include <malloc.h>
#include <linux/usb/ch9.h> +#include <linux/usb/otg.h> #include <linux/usb/gadget.h>
#include <asm/byteorder.h> @@ -31,6 +37,8 @@
#include <asm/mach-types.h>
+#include <power/regulator.h>
#include "dwc2_udc_otg_regs.h" #include "dwc2_udc_otg_priv.h"
@@ -222,6 +230,7 @@ static int udc_enable(struct dwc2_udc *dev) return 0; }
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET) /* Register entry point for the peripheral controller driver. */ @@ -296,6 +305,54 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_disable(dev); return 0; } +#else /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
+static int dwc2_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
+{
- struct dwc2_udc *dev = the_controller;
- debug_cond(DEBUG_SETUP != 0, "%s: %s\n", __func__, "no
name"); +
- if (!driver ||
(driver->speed != USB_SPEED_FULL &&
driver->speed != USB_SPEED_HIGH) ||
!driver->bind || !driver->disconnect || !driver->setup)
return -EINVAL;
- if (!dev)
return -ENODEV;
- if (dev->driver)
return -EBUSY;
- /* first hook up the driver ... */
- dev->driver = driver;
- debug_cond(DEBUG_SETUP != 0,
"Registered gadget driver %s\n",
dev->gadget.name);
- return udc_enable(dev);
+}
+static int dwc2_gadget_stop(struct usb_gadget *g) +{
- struct dwc2_udc *dev = the_controller;
- if (!dev)
return -ENODEV;
- if (!dev->driver)
return -EINVAL;
- dev->driver = 0;
- stop_activity(dev, dev->driver);
- udc_disable(dev);
- return 0;
+}
+#endif /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
/*
- done - retire a request; caller blocked irqs
@@ -730,6 +787,10 @@ static void dwc2_fifo_flush(struct usb_ep *_ep)
static const struct usb_gadget_ops dwc2_udc_ops = { /* current versions must always be self-powered */ +#if CONFIG_IS_ENABLED(DM_USB_GADGET)
- .udc_start = dwc2_gadget_start,
- .udc_stop = dwc2_gadget_stop,
+#endif };
static struct dwc2_udc memory = { @@ -841,12 +902,239 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) return retval; }
-int usb_gadget_handle_interrupts(int index) +int dwc2_udc_handle_interrupt(void) { u32 intr_status = readl(®->gintsts); u32 gintmsk = readl(®->gintmsk);
if (intr_status & gintmsk) return dwc2_udc_irq(1, (void *)the_controller);
- return 0;
+}
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
+int usb_gadget_handle_interrupts(int index) +{
- return dwc2_udc_handle_interrupt();
+}
+#else /* CONFIG_IS_ENABLED(DM_USB_GADGET) */
+struct dwc2_priv_data {
- struct clk_bulk clks;
- struct reset_ctl_bulk resets;
- struct phy *phys;
- int num_phys;
+};
+int dm_usb_gadget_handle_interrupts(struct udevice *dev) +{
- return dwc2_udc_handle_interrupt();
+}
+int dwc2_phy_setup(struct udevice *dev, struct phy **array, int *num_phys) +{
- int i, ret, count;
- struct phy *usb_phys;
- /* Return if no phy declared */
- if (!dev_read_prop(dev, "phys", NULL))
return 0;
- count = dev_count_phandle_with_args(dev, "phys",
"#phy-cells");
- if (count <= 0)
return count;
- usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
GFP_KERNEL);
- if (!usb_phys)
return -ENOMEM;
- for (i = 0; i < count; i++) {
ret = generic_phy_get_by_index(dev, i, &usb_phys[i]);
if (ret && ret != -ENOENT) {
dev_err(dev, "Failed to get USB PHY%d for
%s\n",
i, dev->name);
return ret;
}
- }
- for (i = 0; i < count; i++) {
ret = generic_phy_init(&usb_phys[i]);
if (ret) {
dev_err(dev, "Can't init USB PHY%d for %s\n",
i, dev->name);
goto phys_init_err;
}
- }
- for (i = 0; i < count; i++) {
ret = generic_phy_power_on(&usb_phys[i]);
if (ret) {
dev_err(dev, "Can't power USB PHY%d for
%s\n",
i, dev->name);
goto phys_poweron_err;
}
- }
- *array = usb_phys;
- *num_phys = count;
- return 0;
+phys_poweron_err:
- for (i = count - 1; i >= 0; i--)
generic_phy_power_off(&usb_phys[i]);
- for (i = 0; i < count; i++)
generic_phy_exit(&usb_phys[i]);
- return ret;
+phys_init_err:
- for (; i >= 0; i--)
generic_phy_exit(&usb_phys[i]);
- return ret;
}
+void dwc2_phy_shutdown(struct udevice *dev, struct phy *usb_phys, int num_phys) +{
- int i, ret;
- for (i = 0; i < num_phys; i++) {
if (!generic_phy_valid(&usb_phys[i]))
continue;
ret = generic_phy_power_off(&usb_phys[i]);
ret |= generic_phy_exit(&usb_phys[i]);
if (ret) {
dev_err(dev, "Can't shutdown USB PHY%d for
%s\n",
i, dev->name);
}
- }
+}
+static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) +{
- struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
- int node = dev_of_offset(dev);
- if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) {
dev_dbg(dev, "Invalid mode\n");
return -ENODEV;
- }
- platdata->regs_otg = dev_read_addr(dev);
- platdata->rx_fifo_sz = dev_read_u32_default(dev,
"g-rx-fifo-size", 0);
- platdata->np_tx_fifo_sz = dev_read_u32_default(dev,
"g-np-tx-fifo-size", 0);
- platdata->tx_fifo_sz = dev_read_u32_default(dev,
"g-tx-fifo-size", 0); +
- return 0;
+}
+static int dwc2_udc_otg_reset_init(struct udevice *dev,
struct reset_ctl_bulk *resets)
+{
- int ret;
- ret = reset_get_bulk(dev, resets);
- if (ret == -ENOTSUPP)
return 0;
- if (ret)
return ret;
- ret = reset_deassert_bulk(resets);
- if (ret) {
reset_release_bulk(resets);
return ret;
- }
- return 0;
+}
+static int dwc2_udc_otg_clk_init(struct udevice *dev,
struct clk_bulk *clks)
+{
- int ret;
- ret = clk_get_bulk(dev, clks);
- if (ret == -ENOSYS)
return 0;
- if (ret)
return ret;
- ret = clk_enable_bulk(clks);
- if (ret) {
clk_release_bulk(clks);
return ret;
- }
- return 0;
+}
+static int dwc2_udc_otg_probe(struct udevice *dev) +{
- struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
- struct dwc2_priv_data *priv = dev_get_priv(dev);
- int ret;
- ret = dwc2_udc_otg_clk_init(dev, &priv->clks);
- if (ret)
return ret;
- ret = dwc2_udc_otg_reset_init(dev, &priv->resets);
- if (ret)
return ret;
- ret = dwc2_phy_setup(dev, &priv->phys, &priv->num_phys);
- if (ret)
return ret;
- ret = dwc2_udc_probe(platdata);
- if (ret)
return ret;
- the_controller->driver = 0;
- ret = usb_add_gadget_udc((struct device *)dev,
&the_controller->gadget); +
- return ret;
+}
+static int dwc2_udc_otg_remove(struct udevice *dev) +{
- struct dwc2_priv_data *priv = dev_get_priv(dev);
- usb_del_gadget_udc(&the_controller->gadget);
- reset_release_bulk(&priv->resets);
- clk_release_bulk(&priv->clks);
- dwc2_phy_shutdown(dev, priv->phys, priv->num_phys);
- return dm_scan_fdt_dev(dev);
+}
+static const struct udevice_id dwc2_udc_otg_ids[] = {
- { .compatible = "snps,dwc2" },
+};
+U_BOOT_DRIVER(dwc2_udc_otg) = {
- .name = "dwc2-udc-otg",
- .id = UCLASS_USB_GADGET_GENERIC,
- .of_match = dwc2_udc_otg_ids,
- .ofdata_to_platdata = dwc2_udc_otg_ofdata_to_platdata,
- .probe = dwc2_udc_otg_probe,
- .remove = dwc2_udc_otg_remove,
- .platdata_auto_alloc_size = sizeof(struct
dwc2_plat_otg_data),
- .priv_auto_alloc_size = sizeof(struct dwc2_priv_data),
+}; +#endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Reset the hardware to be sure of the device state.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/gadget/dwc2_udc_otg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index af16fc1..8169fdb 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1049,7 +1049,12 @@ static int dwc2_udc_otg_reset_init(struct udevice *dev, if (ret) return ret;
- ret = reset_deassert_bulk(resets); + ret = reset_assert_bulk(resets); + + if (!ret) { + udelay(2); + ret = reset_deassert_bulk(resets); + } if (ret) { reset_release_bulk(resets); return ret;

On Fri, 29 Mar 2019 15:42:16 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Reset the hardware to be sure of the device state.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/usb/gadget/dwc2_udc_otg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index af16fc1..8169fdb 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1049,7 +1049,12 @@ static int dwc2_udc_otg_reset_init(struct udevice *dev, if (ret) return ret;
- ret = reset_deassert_bulk(resets);
- ret = reset_assert_bulk(resets);
- if (!ret) {
udelay(2);
ret = reset_deassert_bulk(resets);
- } if (ret) { reset_release_bulk(resets); return ret;
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Handle "force-b-session-valid" property from DT.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/gadget/dwc2_udc_otg.c | 9 +++++++++ drivers/usb/gadget/dwc2_udc_otg_regs.h | 8 ++++++-- include/usb/dwc2_udc.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 8169fdb..146f11e 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1034,6 +1034,9 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) "g-np-tx-fifo-size", 0); platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0);
+ platdata->force_b_session_valid = + dev_read_bool(dev, "force-b-session-valid"); + return 0; }
@@ -1088,6 +1091,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev) { struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); struct dwc2_priv_data *priv = dev_get_priv(dev); + struct dwc2_usbotg_reg *usbotg_reg = + (struct dwc2_usbotg_reg *)platdata->regs_otg; int ret;
ret = dwc2_udc_otg_clk_init(dev, &priv->clks); @@ -1102,6 +1107,10 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (ret) return ret;
+ if (platdata->force_b_session_valid) + /* Override B session bits : value and enable */ + setbits_le32(&usbotg_reg->gotgctl, B_VALOEN | B_VALOVAL); + ret = dwc2_udc_probe(platdata); if (ret) return ret; diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a1829b3..0aee4ee 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -83,8 +83,12 @@ struct dwc2_usbotg_reg { /*definitions related to CSR setting */
/* DWC2_UDC_OTG_GOTGCTL */ -#define B_SESSION_VALID (0x1<<19) -#define A_SESSION_VALID (0x1<<18) +#define B_SESSION_VALID BIT(19) +#define A_SESSION_VALID BIT(18) +#define B_VALOVAL BIT(7) +#define B_VALOEN BIT(6) +#define A_VALOVAL BIT(5) +#define A_VALOEN BIT(4)
/* DWC2_UDC_OTG_GAHBCFG */ #define PTXFE_HALF (0<<8) diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 4068de0..3cf20ea 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -22,6 +22,7 @@ struct dwc2_plat_otg_data { unsigned int rx_fifo_sz; unsigned int np_tx_fifo_sz; unsigned int tx_fifo_sz; + bool force_b_session_valid; };
int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);

On Fri, 29 Mar 2019 15:42:17 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Handle "force-b-session-valid" property from DT.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/usb/gadget/dwc2_udc_otg.c | 9 +++++++++ drivers/usb/gadget/dwc2_udc_otg_regs.h | 8 ++++++-- include/usb/dwc2_udc.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 8169fdb..146f11e 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1034,6 +1034,9 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) "g-np-tx-fifo-size", 0); platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0);
- platdata->force_b_session_valid =
dev_read_bool(dev, "force-b-session-valid");
- return 0;
}
@@ -1088,6 +1091,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev) { struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); struct dwc2_priv_data *priv = dev_get_priv(dev);
struct dwc2_usbotg_reg *usbotg_reg =
(struct dwc2_usbotg_reg *)platdata->regs_otg;
int ret;
ret = dwc2_udc_otg_clk_init(dev, &priv->clks);
@@ -1102,6 +1107,10 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (ret) return ret;
- if (platdata->force_b_session_valid)
/* Override B session bits : value and enable */
setbits_le32(&usbotg_reg->gotgctl, B_VALOEN |
B_VALOVAL); + ret = dwc2_udc_probe(platdata); if (ret) return ret; diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a1829b3..0aee4ee 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -83,8 +83,12 @@ struct dwc2_usbotg_reg { /*definitions related to CSR setting */
/* DWC2_UDC_OTG_GOTGCTL */ -#define B_SESSION_VALID (0x1<<19) -#define A_SESSION_VALID (0x1<<18) +#define B_SESSION_VALID BIT(19) +#define A_SESSION_VALID BIT(18) +#define B_VALOVAL BIT(7) +#define B_VALOEN BIT(6) +#define A_VALOVAL BIT(5) +#define A_VALOEN BIT(4)
/* DWC2_UDC_OTG_GAHBCFG */ #define PTXFE_HALF (0<<8) diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 4068de0..3cf20ea 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -22,6 +22,7 @@ struct dwc2_plat_otg_data { unsigned int rx_fifo_sz; unsigned int np_tx_fifo_sz; unsigned int tx_fifo_sz;
- bool force_b_session_valid;
};
int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Add a new function to check the session B validity, to be use to check cable connection.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/gadget/dwc2_udc_otg.c | 9 +++++++++ include/usb/dwc2_udc.h | 2 ++ 2 files changed, 11 insertions(+)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 146f11e..b1efad1 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1151,4 +1151,13 @@ U_BOOT_DRIVER(dwc2_udc_otg) = { .platdata_auto_alloc_size = sizeof(struct dwc2_plat_otg_data), .priv_auto_alloc_size = sizeof(struct dwc2_priv_data), }; + +int dwc2_udc_B_session_valid(struct udevice *dev) +{ + struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); + struct dwc2_usbotg_reg *usbotg_reg = + (struct dwc2_usbotg_reg *)platdata->regs_otg; + + return readl(&usbotg_reg->gotgctl) & B_SESSION_VALID; +} #endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */ diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 3cf20ea..8a426b6 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -27,4 +27,6 @@ struct dwc2_plat_otg_data {
int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);
+int dwc2_udc_B_session_valid(struct udevice *dev); + #endif /* __DWC2_USB_GADGET */

On Fri, 29 Mar 2019 15:42:18 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Add a new function to check the session B validity, to be use to check cable connection.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/usb/gadget/dwc2_udc_otg.c | 9 +++++++++ include/usb/dwc2_udc.h | 2 ++ 2 files changed, 11 insertions(+)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 146f11e..b1efad1 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1151,4 +1151,13 @@ U_BOOT_DRIVER(dwc2_udc_otg) = { .platdata_auto_alloc_size = sizeof(struct dwc2_plat_otg_data), .priv_auto_alloc_size = sizeof(struct dwc2_priv_data), };
+int dwc2_udc_B_session_valid(struct udevice *dev) +{
- struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
- struct dwc2_usbotg_reg *usbotg_reg =
(struct dwc2_usbotg_reg *)platdata->regs_otg;
- return readl(&usbotg_reg->gotgctl) & B_SESSION_VALID;
+} #endif /* CONFIG_IS_ENABLED(DM_USB_GADGET) */ diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 3cf20ea..8a426b6 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -27,4 +27,6 @@ struct dwc2_plat_otg_data {
int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);
+int dwc2_udc_B_session_valid(struct udevice *dev);
#endif /* __DWC2_USB_GADGET */
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Some DWC2 ip variant doesn't use 16 hardware endpoint as hardcoded in the driver. Bits INEps [29:26] of HWCFG4 register allows to get this information.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/gadget/dwc2_udc_otg.c | 11 ++++++++--- drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 17 ++++++++++++----- 3 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index b1efad1..5c7d131 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -456,6 +456,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); uint32_t dflt_gusbcfg; uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; + u32 max_hw_ep;
debug("Reseting OTG controller\n");
@@ -538,9 +539,13 @@ static void reconfig_usbd(struct dwc2_udc *dev) writel((np_tx_fifo_sz << 16) | rx_fifo_sz, ®->gnptxfsiz);
- for (i = 1; i < DWC2_MAX_HW_ENDPOINTS; i++) - writel((rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz*(i-1)) | - tx_fifo_sz << 16, ®->dieptxf[i-1]); + /* retrieve the number of IN Endpoints (excluding ep0) */ + max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK) >> + GHWCFG4_NUM_IN_EPS_SHIFT; + + for (i = 0; i < max_hw_ep; i++) + writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz * i)) | + tx_fifo_sz << 16, ®->dieptxf[i]);
/* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl); diff --git a/drivers/usb/gadget/dwc2_udc_otg_priv.h b/drivers/usb/gadget/dwc2_udc_otg_priv.h index aaa9018..e72b22a 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_priv.h +++ b/drivers/usb/gadget/dwc2_udc_otg_priv.h @@ -23,7 +23,6 @@ #define EP_FIFO_SIZE2 1024 /* ep0-control, ep1in-bulk, ep2out-bulk, ep3in-int */ #define DWC2_MAX_ENDPOINTS 4 -#define DWC2_MAX_HW_ENDPOINTS 16
#define WAIT_FOR_SETUP 0 #define DATA_STATE_XMIT 1 diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index 0aee4ee..a389923 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,22 +60,25 @@ struct dwc2_usbotg_reg { u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ u32 grxfsiz; /* Receive FIFO Size */ u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */ - u8 res1[216]; + + u8 res1[36]; + u32 ghwcfg4; /* User HW Config4 */ + u8 res2[176]; u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */ - u8 res2[1728]; + u8 res3[1728]; /* Device Configuration */ u32 dcfg; /* Device Configuration Register */ u32 dctl; /* Device Control */ u32 dsts; /* Device Status */ - u8 res3[4]; + u8 res4[4]; u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */ u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */ u32 daint; /* Device All Endpoints Interrupt */ u32 daintmsk; /* Device All Endpoints Interrupt Mask */ - u8 res4[224]; + u8 res5[224]; struct dwc2_dev_in_endp in_endp[16]; struct dwc2_dev_out_endp out_endp[16]; - u8 res5[768]; + u8 res6[768]; struct ep_fifo ep[16]; };
@@ -273,4 +276,8 @@ struct dwc2_usbotg_reg { /* Device ALL Endpoints Interrupt Register (DAINT) */ #define DAINT_IN_EP_INT(x) (x << 0) #define DAINT_OUT_EP_INT(x) (x << 16) + +/* User HW Config4 */ +#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) +#define GHWCFG4_NUM_IN_EPS_SHIFT 26 #endif

On Fri, 29 Mar 2019 15:42:19 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Some DWC2 ip variant doesn't use 16 hardware endpoint as hardcoded in the driver. Bits INEps [29:26] of HWCFG4 register allows to get this information.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/usb/gadget/dwc2_udc_otg.c | 11 ++++++++--- drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 17 ++++++++++++----- 3 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index b1efad1..5c7d131 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -456,6 +456,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); uint32_t dflt_gusbcfg; uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz;
u32 max_hw_ep;
debug("Reseting OTG controller\n");
@@ -538,9 +539,13 @@ static void reconfig_usbd(struct dwc2_udc *dev) writel((np_tx_fifo_sz << 16) | rx_fifo_sz, ®->gnptxfsiz);
- for (i = 1; i < DWC2_MAX_HW_ENDPOINTS; i++)
writel((rx_fifo_sz + np_tx_fifo_sz +
tx_fifo_sz*(i-1)) |
tx_fifo_sz << 16, ®->dieptxf[i-1]);
- /* retrieve the number of IN Endpoints (excluding ep0) */
- max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK)
GHWCFG4_NUM_IN_EPS_SHIFT;
- for (i = 0; i < max_hw_ep; i++)
writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz *
i)) |
tx_fifo_sz << 16, ®->dieptxf[i]);
/* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl);
diff --git a/drivers/usb/gadget/dwc2_udc_otg_priv.h b/drivers/usb/gadget/dwc2_udc_otg_priv.h index aaa9018..e72b22a 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_priv.h +++ b/drivers/usb/gadget/dwc2_udc_otg_priv.h @@ -23,7 +23,6 @@ #define EP_FIFO_SIZE2 1024 /* ep0-control, ep1in-bulk, ep2out-bulk, ep3in-int */ #define DWC2_MAX_ENDPOINTS 4 -#define DWC2_MAX_HW_ENDPOINTS 16
#define WAIT_FOR_SETUP 0 #define DATA_STATE_XMIT 1 diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index 0aee4ee..a389923 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,22 +60,25 @@ struct dwc2_usbotg_reg { u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ u32 grxfsiz; /* Receive FIFO Size */ u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */
- u8 res1[216];
- u8 res1[36];
- u32 ghwcfg4; /* User HW Config4 */
- u8 res2[176]; u32 dieptxf[15]; /* Device Periodic Transmit FIFO size
register */
- u8 res2[1728];
- u8 res3[1728]; /* Device Configuration */ u32 dcfg; /* Device Configuration Register */ u32 dctl; /* Device Control */ u32 dsts; /* Device Status */
- u8 res3[4];
- u8 res4[4]; u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */ u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */ u32 daint; /* Device All Endpoints Interrupt */ u32 daintmsk; /* Device All Endpoints Interrupt Mask */
- u8 res4[224];
- u8 res5[224]; struct dwc2_dev_in_endp in_endp[16]; struct dwc2_dev_out_endp out_endp[16];
- u8 res5[768];
- u8 res6[768]; struct ep_fifo ep[16];
};
@@ -273,4 +276,8 @@ struct dwc2_usbotg_reg { /* Device ALL Endpoints Interrupt Register (DAINT) */ #define DAINT_IN_EP_INT(x) (x << 0) #define DAINT_OUT_EP_INT(x) (x << 16)
+/* User HW Config4 */ +#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) +#define GHWCFG4_NUM_IN_EPS_SHIFT 26 #endif
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

From: Patrice Chotard patrice.chotard@st.com
All TX fifo size can be different, add tx_fifo_sz_array[] into dwc2_plat_otg_data to be able to set them.
tx_fifo_sz_array[] is 17 Bytes long and can contains max 16 tx fifo size (synopsys IP supports max 16 IN endpoints). First entry of tx_fifo_sz_array[] is the number of valid fifo size the array contains.
In case of tx_fifo_sz_array[] doesn't contains the same number of element than max hardware endpoint, display a warning message.
Compatibility with board which doesn't use tx_fifo_sz_array[] (Rockchip rk322x/rk3128/rv1108/rk3288/rk3036) is kept.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/usb/gadget/dwc2_udc_otg.c | 14 ++++++++++++-- include/usb/dwc2_udc.h | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 5c7d131..106dec5 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -457,6 +457,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) uint32_t dflt_gusbcfg; uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; u32 max_hw_ep; + int pdata_hw_ep;
debug("Reseting OTG controller\n");
@@ -542,11 +543,20 @@ static void reconfig_usbd(struct dwc2_udc *dev) /* retrieve the number of IN Endpoints (excluding ep0) */ max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT; + pdata_hw_ep = dev->pdata->tx_fifo_sz_nb; + + /* tx_fifo_sz_nb should equal to number of IN Endpoint */ + if (pdata_hw_ep && max_hw_ep != pdata_hw_ep) + pr_warn("Got %d hw endpoint but %d tx-fifo-size in array !!\n", + max_hw_ep, pdata_hw_ep); + + for (i = 0; i < max_hw_ep; i++) { + if (pdata_hw_ep) + tx_fifo_sz = dev->pdata->tx_fifo_sz_array[i];
- for (i = 0; i < max_hw_ep; i++) writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz * i)) | tx_fifo_sz << 16, ®->dieptxf[i]); - + } /* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl); while (readl(®->grstctl) & RX_FIFO_FLUSH) diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 8a426b6..369f6fb 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -9,6 +9,7 @@ #define __DWC2_USB_GADGET
#define PHY0_SLEEP (1 << 5) +#define DWC2_MAX_HW_ENDPOINTS 16
struct dwc2_plat_otg_data { void *priv; @@ -22,6 +23,8 @@ struct dwc2_plat_otg_data { unsigned int rx_fifo_sz; unsigned int np_tx_fifo_sz; unsigned int tx_fifo_sz; + unsigned int tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS]; + unsigned char tx_fifo_sz_nb; bool force_b_session_valid; };

On Fri, 29 Mar 2019 15:42:20 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
All TX fifo size can be different, add tx_fifo_sz_array[] into dwc2_plat_otg_data to be able to set them.
tx_fifo_sz_array[] is 17 Bytes long and can contains max 16 tx fifo size (synopsys IP supports max 16 IN endpoints). First entry of tx_fifo_sz_array[] is the number of valid fifo size the array contains.
In case of tx_fifo_sz_array[] doesn't contains the same number of element than max hardware endpoint, display a warning message.
Compatibility with board which doesn't use tx_fifo_sz_array[] (Rockchip rk322x/rk3128/rv1108/rk3288/rk3036) is kept.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
drivers/usb/gadget/dwc2_udc_otg.c | 14 ++++++++++++-- include/usb/dwc2_udc.h | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 5c7d131..106dec5 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -457,6 +457,7 @@ static void reconfig_usbd(struct dwc2_udc *dev) uint32_t dflt_gusbcfg; uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; u32 max_hw_ep;
int pdata_hw_ep;
debug("Reseting OTG controller\n");
@@ -542,11 +543,20 @@ static void reconfig_usbd(struct dwc2_udc *dev) /* retrieve the number of IN Endpoints (excluding ep0) */ max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK)
GHWCFG4_NUM_IN_EPS_SHIFT;
- pdata_hw_ep = dev->pdata->tx_fifo_sz_nb;
- /* tx_fifo_sz_nb should equal to number of IN Endpoint */
- if (pdata_hw_ep && max_hw_ep != pdata_hw_ep)
pr_warn("Got %d hw endpoint but %d tx-fifo-size in
array !!\n",
max_hw_ep, pdata_hw_ep);
- for (i = 0; i < max_hw_ep; i++) {
if (pdata_hw_ep)
tx_fifo_sz = dev->pdata->tx_fifo_sz_array[i];
- for (i = 0; i < max_hw_ep; i++) writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz *
i)) | tx_fifo_sz << 16, ®->dieptxf[i]);
- } /* Flush the RX FIFO */ writel(RX_FIFO_FLUSH, ®->grstctl); while (readl(®->grstctl) & RX_FIFO_FLUSH)
diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 8a426b6..369f6fb 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -9,6 +9,7 @@ #define __DWC2_USB_GADGET
#define PHY0_SLEEP (1 << 5) +#define DWC2_MAX_HW_ENDPOINTS 16
struct dwc2_plat_otg_data { void *priv; @@ -22,6 +23,8 @@ struct dwc2_plat_otg_data { unsigned int rx_fifo_sz; unsigned int np_tx_fifo_sz; unsigned int tx_fifo_sz;
- unsigned int tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS];
- unsigned char tx_fifo_sz_nb; bool force_b_session_valid;
};
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Add compatible "st,stm32mp1-hsotg" and associated driver data to manage the usb33d-supply and the ST specific register for VBus sensing.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com # Conflicts: # drivers/usb/gadget/dwc2_udc_otg.c
---
doc/device-tree-bindings/usb/dwc2.txt | 2 ++ drivers/usb/gadget/dwc2_udc_otg.c | 45 ++++++++++++++++++++++++++++++++++ drivers/usb/gadget/dwc2_udc_otg_regs.h | 10 ++++++-- include/usb/dwc2_udc.h | 1 + 4 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt index 6dc3c4a..eb60ffa 100644 --- a/doc/device-tree-bindings/usb/dwc2.txt +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -37,6 +37,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties - g-rx-fifo-size: size of rx fifo size in gadget mode. - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode. - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. +- usb33d-supply: external VBUS and ID sensing comparators supply, in order to + perform OTG operation, used on STM32MP1 SoCs.
Deprecated properties: - g-use-dma: gadget DMA mode is automatically detected diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 106dec5..3fdaa10 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -942,6 +942,7 @@ struct dwc2_priv_data { struct reset_ctl_bulk resets; struct phy *phys; int num_phys; + struct udevice *usb33d_supply; };
int dm_usb_gadget_handle_interrupts(struct udevice *dev) @@ -1036,6 +1037,8 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) { struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); int node = dev_of_offset(dev); + ulong drvdata; + void (*set_params)(struct dwc2_plat_otg_data *data);
if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) { dev_dbg(dev, "Invalid mode\n"); @@ -1052,9 +1055,28 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) platdata->force_b_session_valid = dev_read_bool(dev, "force-b-session-valid");
+ /* force platdata according compatible */ + drvdata = dev_get_driver_data(dev); + if (drvdata) { + set_params = (void *)drvdata; + set_params(platdata); + } + return 0; }
+static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) +{ + p->activate_stm_id_vb_detection = true; + p->usb_gusbcfg = + 0 << 15 /* PHY Low Power Clock sel*/ + | 0x9 << 10 /* USB Turnaround time (0x9 for HS phy) */ + | 0 << 9 /* [0:HNP disable,1:HNP enable]*/ + | 0 << 8 /* [0:SRP disable 1:SRP enable]*/ + | 0 << 6 /* 0: high speed utmi+, 1: full speed serial*/ + | 0x7 << 0; /* FS timeout calibration**/ +} + static int dwc2_udc_otg_reset_init(struct udevice *dev, struct reset_ctl_bulk *resets) { @@ -1122,6 +1144,26 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (ret) return ret;
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && + platdata->activate_stm_id_vb_detection && + !platdata->force_b_session_valid) { + ret = device_get_supply_regulator(dev, "usb33d-supply", + &priv->usb33d_supply); + if (ret) { + dev_err(dev, "can't get voltage level detector supply\n"); + return ret; + } + ret = regulator_set_enable(priv->usb33d_supply, true); + if (ret) { + dev_err(dev, "can't enable voltage level detector supply\n"); + return ret; + } + /* Enable vbus sensing */ + setbits_le32(&usbotg_reg->ggpio, + GGPIO_STM32_OTG_GCCFG_VBDEN | + GGPIO_STM32_OTG_GCCFG_IDEN); + } + if (platdata->force_b_session_valid) /* Override B session bits : value and enable */ setbits_le32(&usbotg_reg->gotgctl, B_VALOEN | B_VALOVAL); @@ -1154,6 +1196,9 @@ static int dwc2_udc_otg_remove(struct udevice *dev)
static const struct udevice_id dwc2_udc_otg_ids[] = { { .compatible = "snps,dwc2" }, + { .compatible = "st,stm32mp1-hsotg", + .data = (ulong)dwc2_set_stm32mp1_hsotg_params }, + {}, };
U_BOOT_DRIVER(dwc2_udc_otg) = { diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a389923..b2a28d7 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,8 +60,9 @@ struct dwc2_usbotg_reg { u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ u32 grxfsiz; /* Receive FIFO Size */ u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */ - - u8 res1[36]; + u8 res0[12]; + u32 ggpio; /* 0x038 */ + u8 res1[20]; u32 ghwcfg4; /* User HW Config4 */ u8 res2[176]; u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */ @@ -280,4 +281,9 @@ struct dwc2_usbotg_reg { /* User HW Config4 */ #define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) #define GHWCFG4_NUM_IN_EPS_SHIFT 26 + +/* OTG general core configuration register (OTG_GCCFG:0x38) for STM32MP1 */ +#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21) +#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22) + #endif diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 369f6fb..a6c1221 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -26,6 +26,7 @@ struct dwc2_plat_otg_data { unsigned int tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS]; unsigned char tx_fifo_sz_nb; bool force_b_session_valid; + bool activate_stm_id_vb_detection; };
int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);

On Fri, 29 Mar 2019 15:42:21 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
Add compatible "st,stm32mp1-hsotg" and associated driver data to manage the usb33d-supply and the ST specific register for VBus sensing.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com # Conflicts: # drivers/usb/gadget/dwc2_udc_otg.c
doc/device-tree-bindings/usb/dwc2.txt | 2 ++ drivers/usb/gadget/dwc2_udc_otg.c | 45 ++++++++++++++++++++++++++++++++++ drivers/usb/gadget/dwc2_udc_otg_regs.h | 10 ++++++-- include/usb/dwc2_udc.h | 1 + 4 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt index 6dc3c4a..eb60ffa 100644 --- a/doc/device-tree-bindings/usb/dwc2.txt +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -37,6 +37,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
- g-rx-fifo-size: size of rx fifo size in gadget mode.
- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget
mode.
- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0)
in gadget mode. +- usb33d-supply: external VBUS and ID sensing comparators supply, in order to
- perform OTG operation, used on STM32MP1 SoCs.
Deprecated properties:
- g-use-dma: gadget DMA mode is automatically detected
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 106dec5..3fdaa10 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -942,6 +942,7 @@ struct dwc2_priv_data { struct reset_ctl_bulk resets; struct phy *phys; int num_phys;
- struct udevice *usb33d_supply;
};
int dm_usb_gadget_handle_interrupts(struct udevice *dev) @@ -1036,6 +1037,8 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) { struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev); int node = dev_of_offset(dev);
ulong drvdata;
void (*set_params)(struct dwc2_plat_otg_data *data);
if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) { dev_dbg(dev, "Invalid mode\n");
@@ -1052,9 +1055,28 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) platdata->force_b_session_valid = dev_read_bool(dev, "force-b-session-valid");
- /* force platdata according compatible */
- drvdata = dev_get_driver_data(dev);
- if (drvdata) {
set_params = (void *)drvdata;
set_params(platdata);
- }
- return 0;
}
+static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) +{
- p->activate_stm_id_vb_detection = true;
- p->usb_gusbcfg =
0 << 15 /* PHY Low Power Clock sel*/
| 0x9 << 10 /* USB Turnaround time (0x9 for
HS phy) */
| 0 << 9 /* [0:HNP disable,1:HNP enable]*/
| 0 << 8 /* [0:SRP disable 1:SRP enable]*/
| 0 << 6 /* 0: high speed utmi+, 1: full
speed serial*/
| 0x7 << 0; /* FS timeout calibration**/
+}
static int dwc2_udc_otg_reset_init(struct udevice *dev, struct reset_ctl_bulk *resets) { @@ -1122,6 +1144,26 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (ret) return ret;
- if (CONFIG_IS_ENABLED(DM_REGULATOR) &&
platdata->activate_stm_id_vb_detection &&
!platdata->force_b_session_valid) {
ret = device_get_supply_regulator(dev,
"usb33d-supply",
&priv->usb33d_supply);
if (ret) {
dev_err(dev, "can't get voltage level
detector supply\n");
return ret;
}
ret = regulator_set_enable(priv->usb33d_supply,
true);
if (ret) {
dev_err(dev, "can't enable voltage level
detector supply\n");
return ret;
}
/* Enable vbus sensing */
setbits_le32(&usbotg_reg->ggpio,
GGPIO_STM32_OTG_GCCFG_VBDEN |
GGPIO_STM32_OTG_GCCFG_IDEN);
- }
- if (platdata->force_b_session_valid) /* Override B session bits : value and enable */ setbits_le32(&usbotg_reg->gotgctl, B_VALOEN |
B_VALOVAL); @@ -1154,6 +1196,9 @@ static int dwc2_udc_otg_remove(struct udevice *dev) static const struct udevice_id dwc2_udc_otg_ids[] = { { .compatible = "snps,dwc2" },
- { .compatible = "st,stm32mp1-hsotg",
.data = (ulong)dwc2_set_stm32mp1_hsotg_params },
- {},
};
U_BOOT_DRIVER(dwc2_udc_otg) = { diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a389923..b2a28d7 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -60,8 +60,9 @@ struct dwc2_usbotg_reg { u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ u32 grxfsiz; /* Receive FIFO Size */ u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */
- u8 res1[36];
- u8 res0[12];
- u32 ggpio; /* 0x038 */
- u8 res1[20]; u32 ghwcfg4; /* User HW Config4 */ u8 res2[176]; u32 dieptxf[15]; /* Device Periodic Transmit FIFO size
register */ @@ -280,4 +281,9 @@ struct dwc2_usbotg_reg { /* User HW Config4 */ #define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) #define GHWCFG4_NUM_IN_EPS_SHIFT 26
+/* OTG general core configuration register (OTG_GCCFG:0x38) for STM32MP1 */ +#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21) +#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22)
#endif diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index 369f6fb..a6c1221 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -26,6 +26,7 @@ struct dwc2_plat_otg_data { unsigned int tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS]; unsigned char tx_fifo_sz_nb; bool force_b_session_valid;
- bool activate_stm_id_vb_detection;
};
int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

Remove the HOST support for STM32MP1 USBO device = OTG DWC2. The current DWC2 driver have no dynamic detection of device, So it is dangerous to have start 3V3 when PC is connected to the micro USB connector.
=> it is preferable to have only DEVICE support CONFIG_USB_GADGET_DWC2_OTG for OTG port
See DWC3 driver for clean dual role support...
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
configs/stm32mp15_basic_defconfig | 1 - configs/stm32mp15_trusted_defconfig | 1 - 2 files changed, 2 deletions(-)
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index c54dcfa..b6d994c 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -73,7 +73,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y -CONFIG_USB_DWC2=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index a050cee..ed2a2e6 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -62,7 +62,6 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y -CONFIG_USB_DWC2=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483

Use the DWC2 device driver with DM_USB_GADGET support and cleanup the USB support in STM32MP1 board.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 3 +- arch/arm/dts/stm32mp157a-dk1.dts | 16 ++- arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 1 + arch/arm/dts/stm32mp157c.dtsi | 2 +- board/st/stm32mp1/stm32mp1.c | 165 +++---------------------------- configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 7 files changed, 32 insertions(+), 157 deletions(-)
diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index af7acfa..7e2c5d0 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -11,6 +11,7 @@ aliases { i2c3 = &i2c4; mmc0 = &sdmmc1; + usb0 = &usbotg_hs; }; config { u-boot,boot-led = "heartbeat"; @@ -190,7 +191,7 @@ };
&usbotg_hs { - usb1600; + force-b-session-valid; hnp-srp-disable; };
diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts index 0882765..b8ef820 100644 --- a/arch/arm/dts/stm32mp157a-dk1.dts +++ b/arch/arm/dts/stm32mp157a-dk1.dts @@ -249,11 +249,25 @@ status = "okay"; };
+&usbotg_hs { + dr_mode = "peripheral"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + status = "okay"; +}; + &usbphyc { - vdd3v3-supply = <&vdd_usb>; status = "okay"; };
+&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; + &vrefbuf { regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2500000>; diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi index 6a18d03..6025b64 100644 --- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi @@ -12,6 +12,7 @@ i2c4 = &i2c5; pinctrl2 = &stmfx_pinctrl; spi0 = &qspi; + usb0 = &usbotg_hs; }; };
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index f1375a9..82177b5 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -825,7 +825,7 @@ };
usbotg_hs: usb-otg@49000000 { - compatible = "snps,dwc2"; + compatible = "st,stm32mp1-hsotg", "snps,dwc2"; reg = <0x49000000 0x10000>; clocks = <&rcc USBO_K>; clock-names = "otg"; diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 9a68047..58b6d78 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,18 +7,17 @@ #include <config.h> #include <clk.h> #include <dm.h> +#include <g_dnl.h> #include <generic-phy.h> #include <led.h> #include <misc.h> #include <phy.h> #include <reset.h> #include <syscon.h> -#include <usb.h> #include <asm/io.h> #include <asm/gpio.h> #include <asm/arch/stm32.h> #include <power/regulator.h> -#include <usb/dwc2_udc.h>
/* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 @@ -58,11 +57,6 @@ */ DECLARE_GLOBAL_DATA_PTR;
-#define STM32MP_GUSBCFG 0x40002407 - -#define STM32MP_GGPIO 0x38 -#define STM32MP_GGPIO_VBUS_SENSING BIT(21) - #define USB_WARNING_LOW_THRESHOLD_UV 660000 #define USB_START_LOW_THRESHOLD_UV 1230000 #define USB_START_HIGH_THRESHOLD_UV 2100000 @@ -155,149 +149,22 @@ static void board_key_check(void) #endif }
-static struct dwc2_plat_otg_data stm32mp_otg_data = { - .usb_gusbcfg = STM32MP_GUSBCFG, -}; +#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
-static struct reset_ctl usbotg_reset; - -int board_usb_init(int index, enum usb_init_type init) +int g_dnl_board_usb_cable_connected(void) { - struct fdtdec_phandle_args args; - struct udevice *dev; - const void *blob = gd->fdt_blob; - struct clk clk; - struct phy phy; - int node; - int phy_provider; + struct udevice *dwc2_udc_otg; int ret;
- /* find the usb otg node */ - node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); - if (node < 0) { - debug("Not found usb_otg device\n"); - return -ENODEV; - } - - if (!fdtdec_get_is_enabled(blob, node)) { - debug("stm32 usbotg is disabled in the device tree\n"); - return -ENODEV; - } - - /* Enable clock */ - ret = fdtdec_parse_phandle_with_args(blob, node, "clocks", - "#clock-cells", 0, 0, &args); - if (ret) { - debug("usbotg has no clocks defined in the device tree\n"); - return ret; - } - - ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev); - if (ret) - return ret; - - if (args.args_count != 1) { - debug("Can't find clock ID in the device tree\n"); - return -ENODATA; - } - - clk.dev = dev; - clk.id = args.args[0]; - - ret = clk_enable(&clk); - if (ret) { - debug("Failed to enable usbotg clock\n"); - return ret; - } - - /* Reset */ - ret = fdtdec_parse_phandle_with_args(blob, node, "resets", - "#reset-cells", 0, 0, &args); - if (ret) { - debug("usbotg has no resets defined in the device tree\n"); - goto clk_err; - } - - ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev); - if (ret || args.args_count != 1) - goto clk_err; - - usbotg_reset.dev = dev; - usbotg_reset.id = args.args[0]; - - reset_assert(&usbotg_reset); - udelay(2); - reset_deassert(&usbotg_reset); - - /* Get USB PHY */ - ret = fdtdec_parse_phandle_with_args(blob, node, "phys", - "#phy-cells", 0, 0, &args); - if (!ret) { - phy_provider = fdt_parent_offset(blob, args.node); - ret = uclass_get_device_by_of_offset(UCLASS_PHY, - phy_provider, &dev); - if (ret) - goto clk_err; - - phy.dev = dev; - phy.id = fdtdec_get_uint(blob, args.node, "reg", -1); - - ret = generic_phy_power_on(&phy); - if (ret) { - debug("unable to power on the phy\n"); - goto clk_err; - } - - ret = generic_phy_init(&phy); - if (ret) { - debug("failed to init usb phy\n"); - goto phy_power_err; - } - } - - /* Parse and store data needed for gadget */ - stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); - if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) { - debug("usbotg: can't get base address\n"); - ret = -ENODATA; - goto phy_init_err; - } - - stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node, - "g-rx-fifo-size", 0); - stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node, - "g-np-tx-fifo-size", 0); - stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node, - "g-tx-fifo-size", 0); - /* Enable voltage level detector */ - if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply", - NULL, 0, 0, &args))) { - if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR, - args.node, &dev)) { - ret = regulator_set_enable(dev, true); - if (ret) { - debug("Failed to enable usb33d\n"); - goto phy_init_err; - } - } - } - /* Enable vbus sensing */ - setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO, - STM32MP_GGPIO_VBUS_SENSING); - - return dwc2_udc_probe(&stm32mp_otg_data); - -phy_init_err: - generic_phy_exit(&phy); - -phy_power_err: - generic_phy_power_off(&phy); - -clk_err: - clk_disable(&clk); + ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, + DM_GET_DRIVER(dwc2_udc_otg), + &dwc2_udc_otg); + if (!ret) + debug("dwc2_udc_otg init failed\n");
- return ret; + return dwc2_udc_B_session_valid(dwc2_udc_otg); } +#endif /* CONFIG_USB_GADGET */
static int get_led(struct udevice **dev, char *led_string) { @@ -438,16 +305,6 @@ static int board_check_usb_power(void) return 0; }
-int board_usb_cleanup(int index, enum usb_init_type init) -{ - /* Reset usbotg */ - reset_assert(&usbotg_reset); - udelay(2); - reset_deassert(&usbotg_reset); - - return 0; -} - static void sysconf_init(void) { #ifndef CONFIG_STM32MP1_TRUSTED diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index b6d994c..ff95dcd 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -71,6 +71,7 @@ CONFIG_SERIAL_RX_BUFFER=y CONFIG_STM32_SERIAL=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_GADGET=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index ed2a2e6..f82b770 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -60,6 +60,7 @@ CONFIG_SERIAL_RX_BUFFER=y CONFIG_STM32_SERIAL=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_GADGET=y

The DK1 and DK2 boards use the USB Type-C controller STUSB1600. This patch updates: - the device tree to add the I2C node in the DT - the board stm32mp1 to probe this I2C device and use this controller to check cable detection. - the DWC2 driver to support a new dt property "u-boot,force-b-session-valid" which forces B session and device mode; it is a workaround because the VBUS sensing and ID detection isn't available with stusb1600.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 ++++ arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 2 +- arch/arm/dts/stm32mp157a-dk1.dts | 18 ++++++++++ board/st/stm32mp1/stm32mp1.c | 56 ++++++++++++++++++++++++++++++++ doc/device-tree-bindings/usb/dwc2.txt | 2 ++ drivers/usb/gadget/dwc2_udc_otg.c | 8 +++-- 6 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi index 867d244..1962267 100644 --- a/arch/arm/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi @@ -380,6 +380,13 @@ }; };
+ stusb1600_pins_a: stusb1600-0 { + pins { + pinmux = <STM32_PINMUX('I', 11, ANALOG)>; + bias-pull-up; + }; + }; + uart4_pins_a: uart4-0 { pins1 { pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */ diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 7e2c5d0..0f32a38 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -191,7 +191,7 @@ };
&usbotg_hs { - force-b-session-valid; + u-boot,force-b-session-valid; hnp-srp-disable; };
diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts index b8ef820..e36773d 100644 --- a/arch/arm/dts/stm32mp157a-dk1.dts +++ b/arch/arm/dts/stm32mp157a-dk1.dts @@ -67,6 +67,24 @@ /delete-property/dmas; /delete-property/dma-names;
+ typec: stusb1600@28 { + compatible = "st,stusb1600"; + reg = <0x28>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpioi>; + pinctrl-names = "default"; + pinctrl-0 = <&stusb1600_pins_a>; + + status = "okay"; + + typec_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "sink"; + power-opmode = "default"; + }; + }; + pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 58b6d78..23737ce 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -9,15 +9,18 @@ #include <dm.h> #include <g_dnl.h> #include <generic-phy.h> +#include <i2c.h> #include <led.h> #include <misc.h> #include <phy.h> #include <reset.h> #include <syscon.h> +#include <usb.h> #include <asm/io.h> #include <asm/gpio.h> #include <asm/arch/stm32.h> #include <power/regulator.h> +#include <usb/dwc2_udc.h>
/* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 @@ -151,11 +154,64 @@ static void board_key_check(void)
#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+/* STMicroelectronics STUSB1600 Type-C controller */ +#define STUSB1600_CC_CONNECTION_STATUS 0x0E + +/* STUSB1600_CC_CONNECTION_STATUS bitfields */ +#define STUSB1600_CC_ATTACH BIT(0) + +static int stusb1600_init(struct udevice **dev_stusb1600) +{ + ofnode node; + struct udevice *dev, *bus; + int ret; + u32 chip_addr; + + *dev_stusb1600 = NULL; + + /* if node stusb1600 is present, means DK1 or DK2 board */ + node = ofnode_by_compatible(ofnode_null(), "st,stusb1600"); + if (!ofnode_valid(node)) + return -ENODEV; + + ret = ofnode_read_u32(node, "reg", &chip_addr); + if (ret) + return -EINVAL; + + ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node), + &bus); + if (ret) { + printf("bus for stusb1600 not found\n"); + return -ENODEV; + } + + ret = dm_i2c_probe(bus, chip_addr, 0, &dev); + if (!ret) + *dev_stusb1600 = dev; + + return ret; +} + +static int stusb1600_cable_connected(struct udevice *dev) +{ + u8 status; + + if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1)) + return 0; + + return status & STUSB1600_CC_ATTACH; +} + +#include <usb/dwc2_udc.h> int g_dnl_board_usb_cable_connected(void) { + struct udevice *stusb1600; struct udevice *dwc2_udc_otg; int ret;
+ if (!stusb1600_init(&stusb1600)) + return stusb1600_cable_connected(stusb1600); + ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, DM_GET_DRIVER(dwc2_udc_otg), &dwc2_udc_otg); diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt index eb60ffa..61493f7 100644 --- a/doc/device-tree-bindings/usb/dwc2.txt +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -39,6 +39,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. - usb33d-supply: external VBUS and ID sensing comparators supply, in order to perform OTG operation, used on STM32MP1 SoCs. +- u-boot,force-b-session-valid: force B-peripheral session instead of relying on + VBUS sensing (only valid when dr_mode = "peripheral" and for u-boot).
Deprecated properties: - g-use-dma: gadget DMA mode is automatically detected diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3fdaa10..494ab53 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1053,7 +1053,7 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0);
platdata->force_b_session_valid = - dev_read_bool(dev, "force-b-session-valid"); + dev_read_bool(dev, "u-boot,force-b-session-valid");
/* force platdata according compatible */ drvdata = dev_get_driver_data(dev); @@ -1075,6 +1075,9 @@ static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) | 0 << 8 /* [0:SRP disable 1:SRP enable]*/ | 0 << 6 /* 0: high speed utmi+, 1: full speed serial*/ | 0x7 << 0; /* FS timeout calibration**/ + + if (p->force_b_session_valid) + p->usb_gusbcfg |= 1 << 30; /* FDMOD: Force device mode */ }
static int dwc2_udc_otg_reset_init(struct udevice *dev, @@ -1166,7 +1169,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev)
if (platdata->force_b_session_valid) /* Override B session bits : value and enable */ - setbits_le32(&usbotg_reg->gotgctl, B_VALOEN | B_VALOVAL); + setbits_le32(&usbotg_reg->gotgctl, + A_VALOEN | A_VALOVAL | B_VALOEN | B_VALOVAL);
ret = dwc2_udc_probe(platdata); if (ret)

On Fri, 29 Mar 2019 15:42:24 +0100 Patrick Delaunay patrick.delaunay@st.com wrote:
The DK1 and DK2 boards use the USB Type-C controller STUSB1600. This patch updates:
- the device tree to add the I2C node in the DT
- the board stm32mp1 to probe this I2C device and use this controller to check cable detection.
- the DWC2 driver to support a new dt property "u-boot,force-b-session-valid" which forces B session and device mode; it is a workaround because the VBUS sensing and ID detection isn't available with stusb1600.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 ++++ arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 2 +- arch/arm/dts/stm32mp157a-dk1.dts | 18 ++++++++++ board/st/stm32mp1/stm32mp1.c | 56 ++++++++++++++++++++++++++++++++ doc/device-tree-bindings/usb/dwc2.txt | 2 ++ drivers/usb/gadget/dwc2_udc_otg.c | 8 +++-- 6 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi index 867d244..1962267 100644 --- a/arch/arm/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi @@ -380,6 +380,13 @@ }; };
stusb1600_pins_a: stusb1600-0 {
pins {
pinmux = <STM32_PINMUX('I',
11, ANALOG)>;
bias-pull-up;
};
};
uart4_pins_a: uart4-0 { pins1 { pinmux = <STM32_PINMUX('G',
11, AF6)>; /* UART4_TX */ diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 7e2c5d0..0f32a38 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -191,7 +191,7 @@ };
&usbotg_hs {
- force-b-session-valid;
- u-boot,force-b-session-valid; hnp-srp-disable;
};
diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts index b8ef820..e36773d 100644 --- a/arch/arm/dts/stm32mp157a-dk1.dts +++ b/arch/arm/dts/stm32mp157a-dk1.dts @@ -67,6 +67,24 @@ /delete-property/dmas; /delete-property/dma-names;
- typec: stusb1600@28 {
compatible = "st,stusb1600";
reg = <0x28>;
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpioi>;
pinctrl-names = "default";
pinctrl-0 = <&stusb1600_pins_a>;
status = "okay";
typec_con: connector {
compatible = "usb-c-connector";
label = "USB-C";
power-role = "sink";
power-opmode = "default";
};
- };
- pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>;
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 58b6d78..23737ce 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -9,15 +9,18 @@ #include <dm.h> #include <g_dnl.h> #include <generic-phy.h> +#include <i2c.h> #include <led.h> #include <misc.h> #include <phy.h> #include <reset.h> #include <syscon.h> +#include <usb.h> #include <asm/io.h> #include <asm/gpio.h> #include <asm/arch/stm32.h> #include <power/regulator.h> +#include <usb/dwc2_udc.h>
/* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 @@ -151,11 +154,64 @@ static void board_key_check(void)
#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+/* STMicroelectronics STUSB1600 Type-C controller */ +#define STUSB1600_CC_CONNECTION_STATUS 0x0E
+/* STUSB1600_CC_CONNECTION_STATUS bitfields */ +#define STUSB1600_CC_ATTACH BIT(0)
+static int stusb1600_init(struct udevice **dev_stusb1600) +{
- ofnode node;
- struct udevice *dev, *bus;
- int ret;
- u32 chip_addr;
- *dev_stusb1600 = NULL;
- /* if node stusb1600 is present, means DK1 or DK2 board */
- node = ofnode_by_compatible(ofnode_null(), "st,stusb1600");
- if (!ofnode_valid(node))
return -ENODEV;
- ret = ofnode_read_u32(node, "reg", &chip_addr);
- if (ret)
return -EINVAL;
- ret = uclass_get_device_by_ofnode(UCLASS_I2C,
ofnode_get_parent(node),
&bus);
- if (ret) {
printf("bus for stusb1600 not found\n");
return -ENODEV;
- }
- ret = dm_i2c_probe(bus, chip_addr, 0, &dev);
- if (!ret)
*dev_stusb1600 = dev;
- return ret;
+}
+static int stusb1600_cable_connected(struct udevice *dev) +{
- u8 status;
- if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS,
&status, 1))
return 0;
- return status & STUSB1600_CC_ATTACH;
+}
+#include <usb/dwc2_udc.h> int g_dnl_board_usb_cable_connected(void) {
struct udevice *stusb1600; struct udevice *dwc2_udc_otg; int ret;
if (!stusb1600_init(&stusb1600))
return stusb1600_cable_connected(stusb1600);
ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, DM_GET_DRIVER(dwc2_udc_otg), &dwc2_udc_otg);
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt index eb60ffa..61493f7 100644 --- a/doc/device-tree-bindings/usb/dwc2.txt +++ b/doc/device-tree-bindings/usb/dwc2.txt @@ -39,6 +39,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0)
in gadget mode.
- usb33d-supply: external VBUS and ID sensing comparators supply, in
order to perform OTG operation, used on STM32MP1 SoCs. +- u-boot,force-b-session-valid: force B-peripheral session instead of relying on
- VBUS sensing (only valid when dr_mode = "peripheral" and for
u-boot). Deprecated properties:
- g-use-dma: gadget DMA mode is automatically detected
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 3fdaa10..494ab53 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -1053,7 +1053,7 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev) platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0); platdata->force_b_session_valid =
dev_read_bool(dev, "force-b-session-valid");
dev_read_bool(dev, "u-boot,force-b-session-valid");
/* force platdata according compatible */ drvdata = dev_get_driver_data(dev);
@@ -1075,6 +1075,9 @@ static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) | 0 << 8 /* [0:SRP disable 1:SRP enable]*/ | 0 << 6 /* 0: high speed utmi+, 1: full speed serial*/ | 0x7 << 0; /* FS timeout calibration**/ +
- if (p->force_b_session_valid)
p->usb_gusbcfg |= 1 << 30; /* FDMOD: Force device
mode */ }
static int dwc2_udc_otg_reset_init(struct udevice *dev, @@ -1166,7 +1169,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (platdata->force_b_session_valid) /* Override B session bits : value and enable */
setbits_le32(&usbotg_reg->gotgctl, B_VALOEN |
B_VALOVAL);
setbits_le32(&usbotg_reg->gotgctl,
A_VALOEN | A_VALOVAL | B_VALOEN |
B_VALOVAL); ret = dwc2_udc_probe(platdata); if (ret)
Reviewed-by: Lukasz Majewski lukma@denx.de
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de

On 29/03/2019 14:42, Patrick Delaunay wrote:
This patch-set created after Marek remarks on patch board: stm32mp1: Add tx_fifo_sz_array support http://patchwork.ozlabs.org/patch/1056452/
This serie convert the DWC2 to driver model and use it for the stm32mp1 boards.
USB device and cable connection tested on EV1 and DK2.
This serie superseded the Patrice patches: http://patchwork.ozlabs.org/project/uboot/list/?series=97121
Warning: the serie need to be apply after http://patchwork.ozlabs.org/project/uboot/list/?series=91422 http://patchwork.ozlabs.org/project/uboot/list/?series=91497
Hi Patrice,
The second patch series doesn't apply cleanly anymore, could you rebase and resend so I can test this series?
Regards, Jack.
Patrice Chotard (1): usb: dwc2_udc_otg: Add tx_fifo_sz array support
Patrick Delaunay (15): phy: usbphyc: remove unused variable index phy: usbphyc: update xlate with DT binding phy: usbphyc: Binding update of vdda supply phy: usbphyc: move vdda1v1 and vdda1v8 in phy_init phy: usbphyc: increase PLL wait timeout usb: dwc2: remove unused variable regs_otg usb: dwc2: convert driver to DM_USB_GADGET usb: dwc2: force reset assert before to probe the driver usb: dwc2: Add force-b-session-valid support usb: dwc2: Add function for session B check usb: dwc2_udc_otg: Read MAX_HW_ENDPOINT from HWCFG4 register usb: dwc2: add support for STM32MP1 stm32mp1: remove CONFIG_USB_DWC2, HOST support for USBO stm32mp1: migrate USBOTG device to driver model stm32mp1: add stusb1600 support for DK1 and DK2 board
arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 + arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 3 +- arch/arm/dts/stm32mp157a-dk1.dts | 34 +- arch/arm/dts/stm32mp157c-ed1.dts | 8 - arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 1 + arch/arm/dts/stm32mp157c.dtsi | 5 +- board/st/stm32mp1/stm32mp1.c | 185 +++------- configs/stm32mp15_basic_defconfig | 2 +- configs/stm32mp15_trusted_defconfig | 2 +- doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt | 4 +- doc/device-tree-bindings/usb/dwc2.txt | 58 +++ drivers/phy/phy-stm32-usbphyc.c | 111 +++--- drivers/usb/gadget/dwc2_udc_otg.c | 388 ++++++++++++++++++++- drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 31 +- include/usb/dwc2_udc.h | 7 + 16 files changed, 627 insertions(+), 220 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt

From: Jack Mitchell ml@embed.me.uk Sent: samedi 30 mars 2019 12:42
On 29/03/2019 14:42, Patrick Delaunay wrote:
This patch-set created after Marek remarks on patch board: stm32mp1: Add tx_fifo_sz_array support http://patchwork.ozlabs.org/patch/1056452/
This serie convert the DWC2 to driver model and use it for the stm32mp1 boards.
USB device and cable connection tested on EV1 and DK2.
This serie superseded the Patrice patches: http://patchwork.ozlabs.org/project/uboot/list/?series=97121
Warning: the serie need to be apply after http://patchwork.ozlabs.org/project/uboot/list/?series=91422 http://patchwork.ozlabs.org/project/uboot/list/?series=91497
Hi Patrice,
The second patch series doesn't apply cleanly anymore, could you rebase and resend so I can test this series?
Hi, Yes, I have many pending series for the next releases on stm32mp1 arch and for the 2 baord ev1 and dk2. So many conflicts.
I willl push a rebase this week, but you can use my downstream branch (based on v2019.04) with all the upstreamed patches, including the last one for USB; I have already solve the issues:
https://github.com/patrickdelaunay/u-boot/tree/v2019.04-stm32mp
Regards, Jack.
Patrick
Patrice Chotard (1): usb: dwc2_udc_otg: Add tx_fifo_sz array support
Patrick Delaunay (15): phy: usbphyc: remove unused variable index phy: usbphyc: update xlate with DT binding phy: usbphyc: Binding update of vdda supply phy: usbphyc: move vdda1v1 and vdda1v8 in phy_init phy: usbphyc: increase PLL wait timeout usb: dwc2: remove unused variable regs_otg usb: dwc2: convert driver to DM_USB_GADGET usb: dwc2: force reset assert before to probe the driver usb: dwc2: Add force-b-session-valid support usb: dwc2: Add function for session B check usb: dwc2_udc_otg: Read MAX_HW_ENDPOINT from HWCFG4 register usb: dwc2: add support for STM32MP1 stm32mp1: remove CONFIG_USB_DWC2, HOST support for USBO stm32mp1: migrate USBOTG device to driver model stm32mp1: add stusb1600 support for DK1 and DK2 board
arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 + arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 3 +- arch/arm/dts/stm32mp157a-dk1.dts | 34 +- arch/arm/dts/stm32mp157c-ed1.dts | 8 - arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 1 + arch/arm/dts/stm32mp157c.dtsi | 5 +- board/st/stm32mp1/stm32mp1.c | 185 +++------- configs/stm32mp15_basic_defconfig | 2 +- configs/stm32mp15_trusted_defconfig | 2 +- doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt | 4 +- doc/device-tree-bindings/usb/dwc2.txt | 58 +++ drivers/phy/phy-stm32-usbphyc.c | 111 +++--- drivers/usb/gadget/dwc2_udc_otg.c | 388
++++++++++++++++++++-
drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 31 +- include/usb/dwc2_udc.h | 7 + 16 files changed, 627 insertions(+), 220 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt

On 01/04/2019 10:49, Patrick DELAUNAY wrote:
From: Jack Mitchell ml@embed.me.uk Sent: samedi 30 mars 2019 12:42
On 29/03/2019 14:42, Patrick Delaunay wrote:
This patch-set created after Marek remarks on patch board: stm32mp1: Add tx_fifo_sz_array support http://patchwork.ozlabs.org/patch/1056452/
This serie convert the DWC2 to driver model and use it for the stm32mp1 boards.
USB device and cable connection tested on EV1 and DK2.
This serie superseded the Patrice patches: http://patchwork.ozlabs.org/project/uboot/list/?series=97121
Warning: the serie need to be apply after http://patchwork.ozlabs.org/project/uboot/list/?series=91422 http://patchwork.ozlabs.org/project/uboot/list/?series=91497
Hi Patrice,
The second patch series doesn't apply cleanly anymore, could you rebase and resend so I can test this series?
Hi, Yes, I have many pending series for the next releases on stm32mp1 arch and for the 2 baord ev1 and dk2. So many conflicts.
I willl push a rebase this week, but you can use my downstream branch (based on v2019.04) with all the upstreamed patches, including the last one for USB; I have already solve the issues:
https://github.com/patrickdelaunay/u-boot/tree/v2019.04-stm32mp
Thanks Patrick (and apologies for the previous wrong name), the reason I ask is I'm testing an rk3288 with the DM_USB_GADGET support enabled for it's dwc2 OTG controller. The controller still works without DM_USB_GADGET enabled, but it fails to enumerate any USB devices when it is enabled. Is there anything specific required apart from enabling DM_USB_GADGET?
=> usb start starting USB... scan end No controllers found =>
Regards, Jack.
Patrick
Patrice Chotard (1): usb: dwc2_udc_otg: Add tx_fifo_sz array support
Patrick Delaunay (15): phy: usbphyc: remove unused variable index phy: usbphyc: update xlate with DT binding phy: usbphyc: Binding update of vdda supply phy: usbphyc: move vdda1v1 and vdda1v8 in phy_init phy: usbphyc: increase PLL wait timeout usb: dwc2: remove unused variable regs_otg usb: dwc2: convert driver to DM_USB_GADGET usb: dwc2: force reset assert before to probe the driver usb: dwc2: Add force-b-session-valid support usb: dwc2: Add function for session B check usb: dwc2_udc_otg: Read MAX_HW_ENDPOINT from HWCFG4 register usb: dwc2: add support for STM32MP1 stm32mp1: remove CONFIG_USB_DWC2, HOST support for USBO stm32mp1: migrate USBOTG device to driver model stm32mp1: add stusb1600 support for DK1 and DK2 board
arch/arm/dts/stm32mp157-pinctrl.dtsi | 7 + arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 3 +- arch/arm/dts/stm32mp157a-dk1.dts | 34 +- arch/arm/dts/stm32mp157c-ed1.dts | 8 - arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi | 1 + arch/arm/dts/stm32mp157c.dtsi | 5 +- board/st/stm32mp1/stm32mp1.c | 185 +++------- configs/stm32mp15_basic_defconfig | 2 +- configs/stm32mp15_trusted_defconfig | 2 +- doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt | 4 +- doc/device-tree-bindings/usb/dwc2.txt | 58 +++ drivers/phy/phy-stm32-usbphyc.c | 111 +++--- drivers/usb/gadget/dwc2_udc_otg.c | 388
++++++++++++++++++++-
drivers/usb/gadget/dwc2_udc_otg_priv.h | 1 - drivers/usb/gadget/dwc2_udc_otg_regs.h | 31 +- include/usb/dwc2_udc.h | 7 + 16 files changed, 627 insertions(+), 220 deletions(-) create mode 100644 doc/device-tree-bindings/usb/dwc2.txt

Hi,
From: Jack Mitchell ml@embed.me.uk Sent: lundi 1 avril 2019 12:38
On 01/04/2019 10:49, Patrick DELAUNAY wrote:
From: Jack Mitchell ml@embed.me.uk Sent: samedi 30 mars 2019 12:42
On 29/03/2019 14:42, Patrick Delaunay wrote:
This patch-set created after Marek remarks on patch board: stm32mp1: Add tx_fifo_sz_array support http://patchwork.ozlabs.org/patch/1056452/
This serie convert the DWC2 to driver model and use it for the stm32mp1 boards.
USB device and cable connection tested on EV1 and DK2.
This serie superseded the Patrice patches: http://patchwork.ozlabs.org/project/uboot/list/?series=97121
Warning: the serie need to be apply after http://patchwork.ozlabs.org/project/uboot/list/?series=91422 http://patchwork.ozlabs.org/project/uboot/list/?series=91497
Hi Patrice,
The second patch series doesn't apply cleanly anymore, could you rebase and resend so I can test this series?
Hi, Yes, I have many pending series for the next releases on stm32mp1 arch and
for the 2 baord ev1 and dk2.
So many conflicts.
I willl push a rebase this week, but you can use my downstream branch (based on v2019.04) with all the upstreamed patches, including the last one for USB; I have already solve the issues:
https://github.com/patrickdelaunay/u-boot/tree/v2019.04-stm32mp
Thanks Patrick (and apologies for the previous wrong name),
:-)
the reason I ask is I'm testing an rk3288 with the DM_USB_GADGET support enabled for it's dwc2 OTG controller. The controller still works without DM_USB_GADGET enabled, but it fails to enumerate any USB devices when it is enabled. Is there anything specific required apart from enabling DM_USB_GADGET?
=> usb start starting USB... scan end No controllers found =>
I just add CONFIG_DM_USB_GADGET
But I also need to add a alias "usb0"
arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
/ { aliases { gpio26 = &stmfx_pinctrl; i2c1 = &i2c2; i2c4 = &i2c5; pinctrl2 = &stmfx_pinctrl; spi0 = &qspi; + usb0 = &usbotg_hs; }; };
The alias 'usb0" is needed to selecte the correct sed number
drivers/usb/gadget/udc/udc-uclass.c
int usb_gadget_initialize(int index) udc-uclass.c: ret = uclass_get_device_by_seq(UCLASS_USB_GADGET_GENERIC, index, &dev);
I spent some time to found it.
PS: sequence number is defined by alias in UCLASS :
UCLASS_DRIVER(usb_gadget_generic) = { .id = UCLASS_USB_GADGET_GENERIC, .name = "usb", .flags = DM_UC_FLAG_SEQ_ALIAS, };
Regards Patrick
participants (4)
-
Jack Mitchell
-
Lukasz Majewski
-
Patrick DELAUNAY
-
Patrick Delaunay