[U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once

Jim Lin jilin at nvidia.com
Fri Aug 10 11:36:39 CEST 2012


Add support for command line "usb reset" or "usb start" to initialize
, "usb stop" to stop multiple USB controllers at once.
Other command like "usb tree" also supports multiple controllers.

New added definitions in header file are:
CONFIG_USB_MULTI
CONFIG_USB_MAX_CONTROLLER_COUNT

Signed-off-by: Jim Lin <jilin at nvidia.com>
---
Changes in v2:
- Renaming from CONFIG_USB_INIT_MULTI to CONFIG_USB_MULTI
- Define CONFIG_USB_MAX_CONTROLLER_COUNT as 1 if not defined
- Remove volatile from structure ehci_ctrl of ehci-hcd.c for a checkpatch.pl warning

 common/cmd_usb.c            |   10 +++
 common/usb.c                |   98 +++++++++++++++++++++++++-
 common/usb_hub.c            |    4 +
 drivers/usb/host/ehci-hcd.c |  167 +++++++++++++++++++++++++++++++-----------
 drivers/usb/host/ehci.h     |    5 ++
 include/usb.h               |   12 +++
 6 files changed, 251 insertions(+), 45 deletions(-)

diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index a8e3ae5..8d3093b 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -554,7 +554,17 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	}
 	if (strncmp(argv[1], "tree", 4) == 0) {
 		printf("\nDevice Tree:\n");
+#ifdef CONFIG_USB_MULTI
+		for (i = 0; i < USB_MAX_DEVICE; i++) {
+			dev = usb_get_dev_index(i);
+			if (dev == NULL)
+				break;
+			if (dev->parent == NULL)
+				usb_show_tree(dev);
+		}
+#else
 		usb_show_tree(usb_get_dev_index(0));
+#endif
 		return 0;
 	}
 	if (strncmp(argv[1], "inf", 3) == 0) {
diff --git a/common/usb.c b/common/usb.c
index 1b40228..065c70c 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -77,6 +77,89 @@ static int asynch_allowed;
 
 char usb_started; /* flag for the started/stopped USB status */
 
+#ifdef CONFIG_USB_MULTI
+/***************************************************************************
+ * Init USB Device
+ */
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+#endif
+
+int usb_init(void)
+{
+	void *ctrl;
+	int i;
+	struct usb_device *dev;
+
+	running = 0;
+	dev_index = 0;
+	asynch_allowed = 1;
+	usb_hub_reset();
+
+	/* first make all devices unknown */
+	for (i = 0; i < USB_MAX_DEVICE; i++) {
+		memset(&usb_dev[i], 0, sizeof(struct usb_device));
+		usb_dev[i].devnum = -1;
+	}
+
+	/* init low_level USB */
+	printf("USB:   ");
+	for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
+		/* init low_level USB */
+		ctrl = usb_lowlevel_init(i);
+		/*
+		 * if lowlevel init is OK, scan the bus for devices
+		 * i.e. search HUBs and configure them
+		 */
+		if (ctrl) {
+			running = 1;
+
+			printf("scanning bus for devices... ");
+			dev = usb_alloc_new_device(ctrl);
+			/*
+			 * device 0 is always present
+			 * (root hub, so let it analyze)
+			 */
+			if (dev)
+				usb_new_device(dev);
+		}
+	}
+
+	if (running) {
+		if (!dev_index)
+			printf("No USB Device found\n");
+		else
+			printf("%d USB Device(s) found\n", dev_index);
+#ifdef CONFIG_USB_KEYBOARD
+	drv_usb_kbd_init();
+#endif
+	USB_PRINTF("scan end\n");
+		usb_started = 1;
+		return 0;
+	} else {
+		printf("Error, couldn't init Lowlevel part\n");
+		usb_started = 0;
+		return -1;
+	}
+}
+
+/******************************************************************************
+ * Stop USB this stops the LowLevel Part and deregisters USB devices.
+ */
+int usb_stop(void)
+{
+	int i;
+
+	if (usb_started) {
+		asynch_allowed = 1;
+		usb_started = 0;
+		usb_hub_reset();
+		for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++)
+			usb_lowlevel_stop(i);
+	}
+	return 0;
+}
+#else
 /**********************************************************************
  * some forward declerations...
  */
@@ -127,6 +210,7 @@ int usb_stop(void)
 	}
 	return res;
 }
+#endif
 
 /*
  * disables the asynch behaviour of the control message. This is used for data
@@ -750,11 +834,18 @@ struct usb_device *usb_get_dev_index(int index)
 		return &usb_dev[index];
 }
 
-
+#ifdef CONFIG_USB_MULTI
+/* Save input pointer 'controller' into device structure.
+ * returns a pointer of a new device structure or NULL, if
+ * no device struct is available
+ */
+struct usb_device *usb_alloc_new_device(void *controller)
+#else
 /* returns a pointer of a new device structure or NULL, if
  * no device struct is available
  */
 struct usb_device *usb_alloc_new_device(void)
+#endif
 {
 	int i;
 	USB_PRINTF("New Device %d\n", dev_index);
@@ -768,6 +859,9 @@ struct usb_device *usb_alloc_new_device(void)
 	for (i = 0; i < USB_MAXCHILDREN; i++)
 		usb_dev[dev_index].children[i] = NULL;
 	usb_dev[dev_index].parent = NULL;
+#ifdef CONFIG_USB_MULTI
+	usb_dev[dev_index].controller = controller;
+#endif
 	dev_index++;
 	return &usb_dev[dev_index - 1];
 }
@@ -945,6 +1039,7 @@ int usb_new_device(struct usb_device *dev)
 	return 0;
 }
 
+#ifndef CONFIG_USB_MULTI
 /* build device Tree  */
 static void usb_scan_devices(void)
 {
@@ -969,5 +1064,6 @@ static void usb_scan_devices(void)
 #endif
 	USB_PRINTF("scan end\n");
 }
+#endif
 
 /* EOF */
diff --git a/common/usb_hub.c b/common/usb_hub.c
index f35ad95..8f2e3e3 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -243,7 +243,11 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
 	mdelay(200);
 
 	/* Allocate a new device struct for it */
+#ifdef CONFIG_USB_MULTI
+	usb = usb_alloc_new_device(dev->controller);
+#else
 	usb = usb_alloc_new_device();
+#endif
 
 	if (portstatus & USB_PORT_STAT_HIGH_SPEED)
 		usb->speed = USB_SPEED_HIGH;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 2a82a29..7f8c734 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -29,13 +29,24 @@
 
 #include "ehci.h"
 
-int rootdev;
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+#endif
+
+static struct ehci_ctrl {
+	struct ehci_hccr *hccr;	/* R/O registers, not need for volatile */
+	struct ehci_hcor *hcor;
+	int rootdev;
+	uint16_t portreset;
+	struct QH qh_list __attribute__((aligned(USB_DMA_MINALIGN)));
+	struct QH qh_pool __attribute__((aligned(USB_DMA_MINALIGN)));
+	struct qTD td_pool[3] __attribute__((aligned(USB_DMA_MINALIGN)));
+	int qtd_counter;
+} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
+
 struct ehci_hccr *hccr;	/* R/O registers, not need for volatile */
 volatile struct ehci_hcor *hcor;
 
-static uint16_t portreset;
-DEFINE_ALIGN_BUFFER(struct QH, qh_list, 1, USB_DMA_MINALIGN);
-
 #define ALIGN_END_ADDR(type, ptr, size)			\
 	((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
 
@@ -207,10 +218,8 @@ static int
 ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		   int length, struct devrequest *req)
 {
-	ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
-	ALLOC_ALIGN_BUFFER(struct qTD, qtd, 3, USB_DMA_MINALIGN);
-	int qtd_counter = 0;
-
+	struct QH *qh;
+	struct qTD *qtd;
 	volatile struct qTD *vtd;
 	unsigned long ts;
 	uint32_t *tdp;
@@ -219,6 +228,13 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	uint32_t cmd;
 	int timeout;
 	int ret = 0;
+	struct ehci_ctrl *ctrl;
+#ifdef CONFIG_USB_MULTI
+	ctrl = dev->controller;
+#else
+	ctrl = &ehcic[0];
+#endif
+	hcor = ctrl->hcor;
 
 	debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
 	      buffer, length, req);
@@ -229,6 +245,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		      le16_to_cpu(req->value), le16_to_cpu(req->value),
 		      le16_to_cpu(req->index));
 
+	qh = &ctrl->qh_pool;
+	ctrl->qtd_counter = 0;
+	qtd = &ctrl->td_pool;
 	memset(qh, 0, sizeof(struct QH));
 	memset(qtd, 0, 3 * sizeof(*qtd));
 
@@ -244,7 +263,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	 *   qh_overlay.qt_next ...... 13-10 H
 	 * - qh_overlay.qt_altnext
 	 */
-	qh->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
+	qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH);
 	c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
 	     usb_pipeendpoint(pipe) == 0) ? 1 : 0;
 	endpt = (8 << 28) |
@@ -274,19 +293,21 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		 *
 		 *   [ buffer, buffer_hi ] loaded with "req".
 		 */
-		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		qtd[ctrl->qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+		qtd[ctrl->qtd_counter].qt_altnext =
+			cpu_to_hc32(QT_NEXT_TERMINATE);
 		token = (0 << 31) |
 		    (sizeof(*req) << 16) |
 		    (0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
-		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
-		if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req)) != 0) {
+		qtd[ctrl->qtd_counter].qt_token = cpu_to_hc32(token);
+		if (ehci_td_buffer(&qtd[ctrl->qtd_counter], req, sizeof(*req))
+			!= 0) {
 			printf("unable construct SETUP td\n");
 			goto fail;
 		}
 		/* Update previous qTD! */
-		*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
-		tdp = &qtd[qtd_counter++].qt_next;
+		*tdp = cpu_to_hc32((uint32_t)&qtd[ctrl->qtd_counter]);
+		tdp = &qtd[ctrl->qtd_counter++].qt_next;
 		toggle = 1;
 	}
 
@@ -300,22 +321,25 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		 *
 		 *   [ buffer, buffer_hi ] loaded with "buffer".
 		 */
-		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		qtd[ctrl->qtd_counter].qt_next =
+			cpu_to_hc32(QT_NEXT_TERMINATE);
+		qtd[ctrl->qtd_counter].qt_altnext =
+			cpu_to_hc32(QT_NEXT_TERMINATE);
 		token = (toggle << 31) |
 		    (length << 16) |
 		    ((req == NULL ? 1 : 0) << 15) |
 		    (0 << 12) |
 		    (3 << 10) |
 		    ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
-		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
-		if (ehci_td_buffer(&qtd[qtd_counter], buffer, length) != 0) {
+		qtd[ctrl->qtd_counter].qt_token = cpu_to_hc32(token);
+		if (ehci_td_buffer(&qtd[ctrl->qtd_counter], buffer, length)
+				!= 0) {
 			printf("unable construct DATA td\n");
 			goto fail;
 		}
 		/* Update previous qTD! */
-		*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
-		tdp = &qtd[qtd_counter++].qt_next;
+		*tdp = cpu_to_hc32((uint32_t)&qtd[ctrl->qtd_counter]);
+		tdp = &qtd[ctrl->qtd_counter++].qt_next;
 	}
 
 	if (req != NULL) {
@@ -326,30 +350,32 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		 *   qt_altnext ............. 07-04 H
 		 *   qt_token ............... 0B-08 H
 		 */
-		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+		qtd[ctrl->qtd_counter].qt_next =
+			cpu_to_hc32(QT_NEXT_TERMINATE);
+		qtd[ctrl->qtd_counter].qt_altnext =
+			cpu_to_hc32(QT_NEXT_TERMINATE);
 		token = (toggle << 31) |
 		    (0 << 16) |
 		    (1 << 15) |
 		    (0 << 12) |
 		    (3 << 10) |
 		    ((usb_pipein(pipe) ? 0 : 1) << 8) | (0x80 << 0);
-		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
+		qtd[ctrl->qtd_counter].qt_token = cpu_to_hc32(token);
 		/* Update previous qTD! */
-		*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
-		tdp = &qtd[qtd_counter++].qt_next;
+		*tdp = cpu_to_hc32((uint32_t)&qtd[ctrl->qtd_counter]);
+		tdp = &qtd[ctrl->qtd_counter++].qt_next;
 	}
 
-	qh_list->qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
+	ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
 
 	/* Flush dcache */
-	flush_dcache_range((uint32_t)qh_list,
-		ALIGN_END_ADDR(struct QH, qh_list, 1));
+	flush_dcache_range((uint32_t)&ctrl->qh_list,
+		ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
 	flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
 	flush_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, 3));
 
 	/* Set async. queue head pointer. */
-	ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list);
+	ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list);
 
 	usbsts = ehci_readl(&hcor->or_usbsts);
 	ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
@@ -368,12 +394,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 	/* Wait for TDs to be processed. */
 	ts = get_timer(0);
-	vtd = &qtd[qtd_counter - 1];
+	vtd = &qtd[ctrl->qtd_counter - 1];
 	timeout = USB_TIMEOUT_MS(pipe);
 	do {
 		/* Invalidate dcache */
-		invalidate_dcache_range((uint32_t)qh_list,
-			ALIGN_END_ADDR(struct QH, qh_list, 1));
+		invalidate_dcache_range((uint32_t)&ctrl->qh_list,
+			ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
 		invalidate_dcache_range((uint32_t)qh,
 			ALIGN_END_ADDR(struct QH, qh, 1));
 		invalidate_dcache_range((uint32_t)qtd,
@@ -476,6 +502,14 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 	int len, srclen;
 	uint32_t reg;
 	uint32_t *status_reg;
+	struct ehci_ctrl *ctrl;
+#ifdef CONFIG_USB_MULTI
+	ctrl = dev->controller;
+#else
+	ctrl = &ehcic[0];
+#endif
+	hcor = ctrl->hcor;
+	hccr = ctrl->hccr;
 
 	if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
 		printf("The request port(%d) is not configured\n",
@@ -548,7 +582,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 		break;
 	case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
 		debug("USB_REQ_SET_ADDRESS\n");
-		rootdev = le16_to_cpu(req->value);
+		ctrl->rootdev = le16_to_cpu(req->value);
 		break;
 	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
 		debug("USB_REQ_SET_CONFIGURATION\n");
@@ -598,7 +632,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 			tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
 		if (reg & EHCI_PS_OCC)
 			tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
-		if (portreset & (1 << le16_to_cpu(req->index)))
+		if (ctrl->portreset & (1 << le16_to_cpu(req->index)))
 			tmpbuf[2] |= USB_PORT_STAT_C_RESET;
 
 		srcptr = tmpbuf;
@@ -650,7 +684,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 				ret = handshake(status_reg, EHCI_PS_PR, 0,
 						2 * 1000);
 				if (!ret)
-					portreset |=
+					ctrl->portreset |=
 						1 << le16_to_cpu(req->index);
 				else
 					printf("port(%d) reset error\n",
@@ -683,7 +717,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 			reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
 			break;
 		case USB_PORT_FEAT_C_RESET:
-			portreset &= ~(1 << le16_to_cpu(req->index));
+			ctrl->portreset &= ~(1 << le16_to_cpu(req->index));
 			break;
 		default:
 			debug("unknown feature %x\n", le16_to_cpu(req->value));
@@ -719,27 +753,52 @@ unknown:
 	return -1;
 }
 
+#ifdef CONFIG_USB_MULTI
+int usb_lowlevel_stop(int index)
+{
+	return ehci_hcd_stop(index);
+}
+#else
 int usb_lowlevel_stop(void)
 {
 	return ehci_hcd_stop();
 }
+#endif
 
-int usb_lowlevel_init(void)
+void *usb_lowlevel_multi_init(int index)
 {
 	uint32_t reg;
 	uint32_t cmd;
+	struct QH *qh_list;
+
+#ifdef CONFIG_USB_MULTI
+	if (ehci_hcd_init(index, &hccr, (struct ehci_hcor **)&hcor) != 0)
+		return NULL;
+
+	/* EHCI spec section 4.1 */
+	if (ehci_reset() != 0)
+		return NULL;
 
+#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
+	if (ehci_hcd_init(index, &hccr, (struct ehci_hcor **)&hcor) != 0)
+		return NULL;
+#endif
+#else
 	if (ehci_hcd_init() != 0)
-		return -1;
+		return NULL;
 
 	/* EHCI spec section 4.1 */
 	if (ehci_reset() != 0)
-		return -1;
+		return NULL;
 
 #if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
 	if (ehci_hcd_init() != 0)
-		return -1;
+		return NULL;
+#endif
 #endif
+	ehcic[index].hccr = hccr;
+	ehcic[index].hcor = hcor;
+	qh_list = &ehcic[index].qh_list;
 
 	/* Set head of reclaim list */
 	memset(qh_list, 0, sizeof(*qh_list));
@@ -780,10 +839,24 @@ int usb_lowlevel_init(void)
 	reg = HC_VERSION(ehci_readl(&hccr->cr_capbase));
 	printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
 
-	rootdev = 0;
+	ehcic[index].rootdev = 0;
+
+	return ehcic + index;
+}
 
+#ifdef CONFIG_USB_MULTI
+void *usb_lowlevel_init(int index)
+{
+	return usb_lowlevel_multi_init(index);
+}
+#else
+int usb_lowlevel_init(void)
+{
+	if (usb_lowlevel_multi_init(0) == NULL)
+		return -1;
 	return 0;
 }
+#endif
 
 int
 submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
@@ -801,14 +874,20 @@ int
 submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 		   int length, struct devrequest *setup)
 {
+	struct ehci_ctrl *ctrl;
 
 	if (usb_pipetype(pipe) != PIPE_CONTROL) {
 		debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
 		return -1;
 	}
 
-	if (usb_pipedevice(pipe) == rootdev) {
-		if (rootdev == 0)
+#ifdef CONFIG_USB_MULTI
+	ctrl = dev->controller;
+#else
+	ctrl = &ehcic[0];
+#endif
+	if (usb_pipedevice(pipe) == ctrl->rootdev) {
+		if (ctrl->rootdev == 0)
 			dev->speed = USB_SPEED_HIGH;
 		return ehci_submit_root(dev, pipe, buffer, length, setup);
 	}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index cc00ce4..1cc5c6e 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -201,7 +201,12 @@ struct QH {
 };
 
 /* Low level init functions */
+#ifdef CONFIG_USB_MULTI
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor);
+int ehci_hcd_stop(int index);
+#else
 int ehci_hcd_init(void);
 int ehci_hcd_stop(void);
+#endif
 
 #endif /* USB_EHCI_H */
diff --git a/include/usb.h b/include/usb.h
index ba3d169..628cfd5 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -140,6 +140,9 @@ struct usb_device {
 	int portnr;
 	struct usb_device *parent;
 	struct usb_device *children[USB_MAXCHILDREN];
+#ifdef CONFIG_USB_MULTI
+	void *controller;               /* hardware controller private data */
+#endif
 };
 
 /**********************************************************************
@@ -153,8 +156,13 @@ struct usb_device {
 	defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \
 	defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X)
 
+#ifdef CONFIG_USB_MULTI
+void *usb_lowlevel_init(int index);
+int usb_lowlevel_stop(int index);
+#else
 int usb_lowlevel_init(void);
 int usb_lowlevel_stop(void);
+#endif
 int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 			void *buffer, int transfer_len);
 int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
@@ -382,7 +390,11 @@ void usb_hub_reset(void);
 int hub_port_reset(struct usb_device *dev, int port,
 			  unsigned short *portstat);
 
+#ifdef CONFIG_USB_MULTI
+struct usb_device *usb_alloc_new_device(void *controller);
+#else
 struct usb_device *usb_alloc_new_device(void);
+#endif
 int usb_new_device(struct usb_device *dev);
 
 #endif /*_USB_H_ */
-- 
1.7.3


-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------


More information about the U-Boot mailing list