diff mbox

[U-Boot,RFC] usb storage: set env variable to host controller no

Message ID 1389984631-18612-1-git-send-email-tharvey@gateworks.com
State RFC
Headers show

Commit Message

Tim Harvey Jan. 17, 2014, 6:50 p.m. UTC
In order to support boot scripts that dynamically create kernel arguments
that describe the boot device, a method is needed to determine what USB
host controller number is associated with current usb storage device set
via 'usb dev <n>'.

This patch dynamically sets the 'usbdevport' env variable according to the
instance number of the EHCI host controller when the usb storage device is
set with the 'usb dev <n>' command.

This is currently being used to be able to pass a kernel command-line argument
the the IMX Android kernel to tell it which USB host device to boot from:
fsl-ehci.0 (OTG) or fsl-ehci.1 (EHCI).

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 common/usb_storage.c | 71 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/common/usb_storage.c b/common/usb_storage.c
index 6ac358d..628eef3 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -160,10 +160,66 @@  unsigned long usb_stor_write(int device, lbaint_t blknr,
 struct usb_device * usb_get_dev_index(int index);
 void uhci_show_temp_int_td(void);
 
+struct usb_device *get_usb_dev(int index)
+{
+	struct usb_device *dev;
+	int i;
+
+	dev = NULL;
+	for (i = 0; i < USB_MAX_DEVICE; i++) {
+		dev = usb_get_dev_index(i);
+		if (dev == NULL)
+			return NULL;
+		if (dev->devnum == usb_dev_desc[index].target)
+			break;
+	}
+
+	return dev;
+}
+
 #ifdef CONFIG_PARTITIONS
 block_dev_desc_t *usb_stor_get_dev(int index)
 {
-	return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
+	block_dev_desc_t *ret;
+
+	ret = (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
+	if (ret) {
+		int port = -1;
+		struct usb_device *dev = get_usb_dev(index);
+
+		if (dev && dev->parent) {
+			/* dev->devnum is device number on USB bus */
+			struct usb_device *parent = dev->parent;
+			struct usb_device *p;
+			int i, j;
+
+			/* find host controller for this device */
+			while (parent->parent)
+				parent = parent->parent;
+			/* find host controller index */
+			for (i = 0, j = 0; i < USB_MAX_DEVICE; i++) {
+				p = usb_get_dev_index(i);
+				if (!p)
+					break;
+				/* host controller */
+				if (!p->parent) {
+					if (parent == p) {
+						port = j;
+						break;
+					}
+					j++;
+				}
+			}
+		}
+		if (port < 0) {
+			printf("cannot locate device's port.\n");
+		} else {
+			char buf[5];
+			sprintf(buf, "%d", port);
+			setenv("usbdevport", buf);
+		}
+	}
+	return ret;
 }
 #endif
 
@@ -1053,15 +1109,10 @@  unsigned long usb_stor_read(int device, lbaint_t blknr,
 
 	device &= 0xff;
 	/* Setup  device */
-	debug("\nusb_read: dev %d \n", device);
-	dev = NULL;
-	for (i = 0; i < USB_MAX_DEVICE; i++) {
-		dev = usb_get_dev_index(i);
-		if (dev == NULL)
-			return 0;
-		if (dev->devnum == usb_dev_desc[device].target)
-			break;
-	}
+	debug("\nusb_read: dev %d\n", device);
+	dev = get_usb_dev(device);
+	if (!dev)
+		return 0;
 	ss = (struct us_data *)dev->privptr;
 
 	usb_disable_asynch(1); /* asynch transfer not allowed */