[U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
Jim Lin
jilin at nvidia.com
Wed Aug 8 11:48:38 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
nvpublic
More information about the U-Boot
mailing list