aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngus Ainslie <angus@akkea.ca>2022-02-02 15:08:54 -0800
committerMarek Vasut <marex@denx.de>2022-02-16 16:52:56 +0100
commitc08db05455bcb2259849a096acf2e90cce258849 (patch)
tree5a4ce756f120dd0b7df3c838496c3751ca91e9b4
parentab8903a24db11571d634ef255976bb364c3ba64d (diff)
downloadu-boot-c08db05455bcb2259849a096acf2e90cce258849.zip
u-boot-c08db05455bcb2259849a096acf2e90cce258849.tar.gz
u-boot-c08db05455bcb2259849a096acf2e90cce258849.tar.bz2
usb: dwc3: dwc3-generic: check the parent nodes
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>
-rw-r--r--drivers/usb/dwc3/dwc3-generic.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 8d53ba7..01bd0ca 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" },
{ }
};