diff mbox series

[v6,1/2] usb: provide a device tree node to USB devices

Message ID 20200522163820.22963-1-michael@walle.cc
State Accepted
Commit c03b7612ea346ad7454086d1623fb57098faf315
Headers show
Series [v6,1/2] usb: provide a device tree node to USB devices | expand

Commit Message

Michael Walle May 22, 2020, 4:38 p.m. UTC
It is possible to specify a device tree node for an USB device. This is
useful if you have a static USB setup and want to use aliases which
point to these nodes, like on the Raspberry Pi.
The nodes are matched against their hub port number, the compatible
strings are not matched for now.

Signed-off-by: Michael Walle <michael at walle.cc>
Reviewed-by: Marek Vasut <marex at denx.de>
---
Changes since v5:
  - added test cases

This is a new patch in v5:
  Fixes the ethernet0 alias on Raspberry Pis. This has never been
  working, but wasn't a problem until recently. Patch 2/2 changes
  the allocation of the numbers and reserves possible aliases.

 arch/sandbox/dts/test.dts     |  9 ++++++++
 drivers/usb/host/usb-uclass.c | 41 ++++++++++++++++++++++++++++++-----
 test/dm/usb.c                 | 22 +++++++++++++++++++
 3 files changed, 67 insertions(+), 5 deletions(-)

Comments

Simon Glass May 22, 2020, 11:13 p.m. UTC | #1
On Fri, 22 May 2020 at 10:38, Michael Walle <michael at walle.cc> wrote:
>
> It is possible to specify a device tree node for an USB device. This is
> useful if you have a static USB setup and want to use aliases which
> point to these nodes, like on the Raspberry Pi.
> The nodes are matched against their hub port number, the compatible
> strings are not matched for now.
>
> Signed-off-by: Michael Walle <michael at walle.cc>
> Reviewed-by: Marek Vasut <marex at denx.de>
> ---
> Changes since v5:
>   - added test cases
>
> This is a new patch in v5:
>   Fixes the ethernet0 alias on Raspberry Pis. This has never been
>   working, but wasn't a problem until recently. Patch 2/2 changes
>   the allocation of the numbers and reserves possible aliases.
>
>  arch/sandbox/dts/test.dts     |  9 ++++++++
>  drivers/usb/host/usb-uclass.c | 41 ++++++++++++++++++++++++++++++-----
>  test/dm/usb.c                 | 22 +++++++++++++++++++
>  3 files changed, 67 insertions(+), 5 deletions(-)

Reviewed-by: Simon Glass <sjg at chromium.org>
diff mbox series

Patch

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5ce5e28476..b9255e4593 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -810,6 +810,8 @@ 
 		hub {
 			compatible = "usb-hub";
 			usb,device-class = <9>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			hub-emul {
 				compatible = "sandbox,usb-hub";
 				#address-cells = <1>;
@@ -838,6 +840,13 @@ 
 				};
 
 			};
+
+			usbstor at 1 {
+				reg = <1>;
+			};
+			usbstor at 3 {
+				reg = <3>;
+			};
 		};
 	};
 
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index cb79dfbbd5..f42c0625cb 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -494,6 +494,35 @@  static int usb_match_one_id(struct usb_device_descriptor *desc,
 	return usb_match_one_id_intf(desc, int_desc, id);
 }
 
+static ofnode usb_get_ofnode(struct udevice *hub, int port)
+{
+	ofnode node;
+	u32 reg;
+
+	if (!dev_has_of_node(hub))
+		return ofnode_null();
+
+	/*
+	 * The USB controller and its USB hub are two different udevices,
+	 * but the device tree has only one node for both. Thus we are
+	 * assigning this node to both udevices.
+	 * If port is zero, the controller scans its root hub, thus we
+	 * are using the same ofnode as the controller here.
+	 */
+	if (!port)
+		return dev_ofnode(hub);
+
+	ofnode_for_each_subnode(node, dev_ofnode(hub)) {
+		if (ofnode_read_u32(node, "reg", &reg))
+			continue;
+
+		if (reg == port)
+			return node;
+	}
+
+	return ofnode_null();
+}
+
 /**
  * usb_find_and_bind_driver() - Find and bind the right USB driver
  *
@@ -502,13 +531,14 @@  static int usb_match_one_id(struct usb_device_descriptor *desc,
 static int usb_find_and_bind_driver(struct udevice *parent,
 				    struct usb_device_descriptor *desc,
 				    struct usb_interface_descriptor *iface,
-				    int bus_seq, int devnum,
+				    int bus_seq, int devnum, int port,
 				    struct udevice **devp)
 {
 	struct usb_driver_entry *start, *entry;
 	int n_ents;
 	int ret;
 	char name[30], *str;
+	ofnode node = usb_get_ofnode(parent, port);
 
 	*devp = NULL;
 	debug("%s: Searching for driver\n", __func__);
@@ -533,8 +563,8 @@  static int usb_find_and_bind_driver(struct udevice *parent,
 			 * find another driver. For now this doesn't seem
 			 * necesssary, so just bind the first match.
 			 */
-			ret = device_bind(parent, drv, drv->name, NULL, -1,
-					  &dev);
+			ret = device_bind_ofnode(parent, drv, drv->name, NULL,
+						 node, &dev);
 			if (ret)
 				goto error;
 			debug("%s: Match found: %s\n", __func__, drv->name);
@@ -651,9 +681,10 @@  int usb_scan_device(struct udevice *parent, int port,
 	if (ret) {
 		if (ret != -ENOENT)
 			return ret;
-		ret = usb_find_and_bind_driver(parent, &udev->descriptor, iface,
+		ret = usb_find_and_bind_driver(parent, &udev->descriptor,
+					       iface,
 					       udev->controller_dev->seq,
-					       udev->devnum, &dev);
+					       udev->devnum, port, &dev);
 		if (ret)
 			return ret;
 		created = true;
diff --git a/test/dm/usb.c b/test/dm/usb.c
index a25c2c1482..b273a515ef 100644
--- a/test/dm/usb.c
+++ b/test/dm/usb.c
@@ -78,6 +78,28 @@  static int dm_test_usb_multi(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_usb_multi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* test that we have an associated ofnode with the usb device */
+static int dm_test_usb_fdt_node(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	ofnode node;
+
+	state_set_skip_delays(true);
+	ut_assertok(usb_init());
+	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
+	node = ofnode_path("/usb at 1/hub/usbstor at 1");
+	ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev)));
+	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
+	ut_asserteq(1, ofnode_equal(ofnode_null(), dev_ofnode(dev)));
+	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
+	node = ofnode_path("/usb at 1/hub/usbstor at 3");
+	ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev)));
+	ut_assertok(usb_stop());
+
+	return 0;
+}
+DM_TEST(dm_test_usb_fdt_node, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 static int count_usb_devices(void)
 {
 	struct udevice *hub;