[PATCH 0/2] Fixes for the dwc3 driver

dwc3 driver fixes to work better with the linux kernel.
Angus Ainslie (2): usb: dwc3: dwc3-generic: check the parent nodes usb: dwc3: core: stop the core when it's removed
drivers/usb/dwc3/core.c | 9 +++++++++ drivers/usb/dwc3/dwc3-generic.c | 25 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-)

The kernel devicetree has definitions for port and hub nodes as subnodes to the USB devices. These subnodes don't contain all of the data required to properly configure the dwc3. Check the parent nodes if the data is not in the port/hub node.
Here's an example from the librem5 kernel dts file
&usb_dwc3_0 { #address-cells = <1>; #size-cells = <0>; dr_mode = "otg"; snps,dis_u3_susphy_quirk; status = "okay";
port@0 { reg = <0>;
typec_hs: endpoint { remote-endpoint = <&usb_con_hs>; }; };
port@1 { reg = <1>;
typec_ss: endpoint { remote-endpoint = <&usb_con_ss>; }; }; };
&usb_dwc3_1 { dr_mode = "host"; status = "okay"; #address-cells = <1>; #size-cells = <0>;
/* Microchip USB2642 */ hub@1 { compatible = "usb424,2640"; reg = <1>; #address-cells = <1>; #size-cells = <0>;
mass-storage@1 { compatible = "usb424,4041"; reg = <1>; }; }; };
Signed-off-by: Angus Ainslie angus@akkea.ca --- drivers/usb/dwc3/dwc3-generic.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 8d53ba7790..01bd0ca190 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -110,7 +110,12 @@ static int dwc3_generic_of_to_plat(struct udevice *dev) struct dwc3_generic_plat *plat = dev_get_plat(dev); ofnode node = dev_ofnode(dev);
- plat->base = dev_read_addr(dev); + if (!strncmp(dev->name, "port", 4) || !strncmp(dev->name, "hub", 3)) { + /* This is a leaf so check the parent */ + plat->base = dev_read_addr(dev->parent); + } else { + plat->base = dev_read_addr(dev); + }
plat->maximum_speed = usb_get_maximum_speed(node); if (plat->maximum_speed == USB_SPEED_UNKNOWN) { @@ -120,8 +125,13 @@ static int dwc3_generic_of_to_plat(struct udevice *dev)
plat->dr_mode = usb_get_dr_mode(node); if (plat->dr_mode == USB_DR_MODE_UNKNOWN) { - pr_err("Invalid usb mode setup\n"); - return -ENODEV; + /* might be a leaf so check the parent for mode */ + node = dev_ofnode(dev->parent); + plat->dr_mode = usb_get_dr_mode(node); + if (plat->dr_mode == USB_DR_MODE_UNKNOWN) { + pr_err("Invalid usb mode setup\n"); + return -ENODEV; + } }
return 0; @@ -301,16 +311,20 @@ static int dwc3_glue_bind(struct udevice *parent) { ofnode node; int ret; + enum usb_dr_mode dr_mode; + + dr_mode = usb_get_dr_mode(dev_ofnode(parent));
ofnode_for_each_subnode(node, dev_ofnode(parent)) { const char *name = ofnode_get_name(node); - enum usb_dr_mode dr_mode; struct udevice *dev; const char *driver = NULL;
debug("%s: subnode name: %s\n", __func__, name);
- dr_mode = usb_get_dr_mode(node); + /* if the parent node doesn't have a mode check the leaf */ + if (!dr_mode) + dr_mode = usb_get_dr_mode(node);
switch (dr_mode) { case USB_DR_MODE_PERIPHERAL: @@ -450,6 +464,7 @@ static const struct udevice_id dwc3_glue_ids[] = { { .compatible = "rockchip,rk3328-dwc3" }, { .compatible = "rockchip,rk3399-dwc3" }, { .compatible = "qcom,dwc3" }, + { .compatible = "fsl,imx8mq-dwc3" }, { .compatible = "intel,tangier-dwc3" }, { } };

On Thu, Feb 3, 2022 at 7:09 AM Angus Ainslie angus@akkea.ca wrote:
The kernel devicetree has definitions for port and hub nodes as subnodes to the USB devices. These subnodes don't contain all of the data required to properly configure the dwc3. Check the parent nodes if the data is not in the port/hub node.
Here's an example from the librem5 kernel dts file
&usb_dwc3_0 { #address-cells = <1>; #size-cells = <0>; dr_mode = "otg"; snps,dis_u3_susphy_quirk; status = "okay";
port@0 { reg = <0>; typec_hs: endpoint { remote-endpoint = <&usb_con_hs>; }; }; port@1 { reg = <1>; typec_ss: endpoint { remote-endpoint = <&usb_con_ss>; }; };
};
&usb_dwc3_1 { dr_mode = "host"; status = "okay"; #address-cells = <1>; #size-cells = <0>;
/* Microchip USB2642 */ hub@1 { compatible = "usb424,2640"; reg = <1>; #address-cells = <1>; #size-cells = <0>; mass-storage@1 { compatible = "usb424,4041"; reg = <1>; }; };
};
Signed-off-by: Angus Ainslie angus@akkea.ca
drivers/usb/dwc3/dwc3-generic.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 2/16/22 08:37, Bin Meng wrote:
On Thu, Feb 3, 2022 at 7:09 AM Angus Ainslie angus@akkea.ca wrote:
The kernel devicetree has definitions for port and hub nodes as subnodes to the USB devices. These subnodes don't contain all of the data required to properly configure the dwc3. Check the parent nodes if the data is not in the port/hub node.
Applied, thanks.

If u-boot doesn't stop the core when it's finished with it then linux can't find it.
Signed-off-by: Angus Ainslie angus@akkea.ca --- drivers/usb/dwc3/core.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ce1c0e88c2..b592a487e0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -706,6 +706,14 @@ static void dwc3_gadget_run(struct dwc3 *dwc) mdelay(100); }
+static void dwc3_core_stop(struct dwc3 *dwc) +{ + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP)); +} + static void dwc3_core_exit_mode(struct dwc3 *dwc) { switch (dwc->dr_mode) { @@ -1128,6 +1136,7 @@ void dwc3_remove(struct dwc3 *dwc) dwc3_core_exit_mode(dwc); dwc3_event_buffers_cleanup(dwc); dwc3_free_event_buffers(dwc); + dwc3_core_stop(dwc); dwc3_core_exit(dwc); kfree(dwc->mem); }

On Thu, Feb 3, 2022 at 7:09 AM Angus Ainslie angus@akkea.ca wrote:
If u-boot doesn't stop the core when it's finished with it then linux can't find it.
Signed-off-by: Angus Ainslie angus@akkea.ca
drivers/usb/dwc3/core.c | 9 +++++++++ 1 file changed, 9 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 2/16/22 08:37, Bin Meng wrote:
On Thu, Feb 3, 2022 at 7:09 AM Angus Ainslie angus@akkea.ca wrote:
If u-boot doesn't stop the core when it's finished with it then linux can't find it.
Signed-off-by: Angus Ainslie angus@akkea.ca
drivers/usb/dwc3/core.c | 9 +++++++++ 1 file changed, 9 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied, thanks.
participants (3)
-
Angus Ainslie
-
Bin Meng
-
Marek Vasut