
From: Jim Lin jilin@nvidia.com
Add support for command line "usb reset" or "usb start" to initialize , "usb stop" to stop multiple USB controllers at once. Other commands like "usb tree" also support multiple controllers.
New added definitions in header file are: CONFIG_USB_INIT_MULTI CONFIG_USB_MAX_CONTROLLER_COUNT
Signed-off-by: Jim Lin jilin@nvidia.com --- arch/arm/cpu/armv7/tegra2/usb.c | 15 +++ arch/arm/include/asm/arch-tegra2/usb.h | 4 + common/cmd_usb.c | 10 ++ common/usb.c | 108 ++++++++++++++++++ common/usb_hub.c | 4 + drivers/usb/host/ehci-hcd.c | 192 ++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-tegra.c | 17 +++- drivers/usb/host/ehci.h | 5 + include/configs/seaboard.h | 2 + include/usb.h | 12 ++ 10 files changed, 368 insertions(+), 1 deletions(-)
diff --git a/arch/arm/cpu/armv7/tegra2/usb.c b/arch/arm/cpu/armv7/tegra2/usb.c index c80de7f..3d2cfb9 100644 --- a/arch/arm/cpu/armv7/tegra2/usb.c +++ b/arch/arm/cpu/armv7/tegra2/usb.c @@ -352,7 +352,11 @@ int tegrausb_start_port(unsigned portnum, u32 *hccr, u32 *hcor)
if (portnum >= port_count) return -1; +#ifdef CONFIG_USB_INIT_MULTI + tegrausb_stop_port(portnum); +#else tegrausb_stop_port(); +#endif set_host_mode(&port[portnum]);
usbctlr = port[portnum].reg; @@ -362,6 +366,16 @@ int tegrausb_start_port(unsigned portnum, u32 *hccr, u32 *hcor) return 0; }
+#ifdef CONFIG_USB_INIT_MULTI +int tegrausb_stop_port(unsigned portnum) +{ + struct usb_ctlr *usbctlr; + + if (portnum >= port_count) + return -1; + + usbctlr = port[portnum].reg; +#else int tegrausb_stop_port(void) { struct usb_ctlr *usbctlr; @@ -370,6 +384,7 @@ int tegrausb_stop_port(void) return -1;
usbctlr = port[port_current].reg; +#endif
/* Stop controller */ writel(0, &usbctlr->usb_cmd); diff --git a/arch/arm/include/asm/arch-tegra2/usb.h b/arch/arm/include/asm/arch-tegra2/usb.h index 638033b..119d7b4 100644 --- a/arch/arm/include/asm/arch-tegra2/usb.h +++ b/arch/arm/include/asm/arch-tegra2/usb.h @@ -247,6 +247,10 @@ int tegrausb_start_port(unsigned portnum, u32 *hccr, u32 *hcor); * * @return 0 if ok, -1 if no port was active */ +#ifdef CONFIG_USB_INIT_MULTI +int tegrausb_stop_port(unsigned portnum); +#else int tegrausb_stop_port(void); +#endif
#endif /* _TEGRA_USB_H_ */ diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 9eba271..4c01a78 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -553,7 +553,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_INIT_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 1ec30bc..b4275c5 100644 --- a/common/usb.c +++ b/common/usb.c @@ -81,6 +81,86 @@ char usb_started; /* flag for the started/stopped USB status */ */ static void usb_scan_devices(void);
+#ifdef CONFIG_USB_INIT_MULTI +/*************************************************************************** + * Init USB Device + */ + +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 /*************************************************************************** * Init USB Device */ @@ -126,6 +206,7 @@ int usb_stop(void) } return res; } +#endif
/* * disables the asynch behaviour of the control message. This is used for data @@ -747,7 +828,31 @@ struct usb_device *usb_get_dev_index(int index) return &usb_dev[index]; }
+#ifdef CONFIG_USB_INIT_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) +{ + int i;
+ USB_PRINTF("New Device %d\n", dev_index); + if (dev_index == USB_MAX_DEVICE) { + printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE); + return NULL; + } + /* default Address is 0, real addresses start with 1 */ + usb_dev[dev_index].devnum = dev_index + 1; + usb_dev[dev_index].maxchild = 0; + for (i = 0; i < USB_MAXCHILDREN; i++) + usb_dev[dev_index].children[i] = NULL; + usb_dev[dev_index].parent = NULL; + usb_dev[dev_index].controller = controller; + dev_index++; + return &usb_dev[dev_index - 1]; +} +#else /* returns a pointer of a new device structure or NULL, if * no device struct is available */ @@ -769,6 +874,7 @@ struct usb_device *usb_alloc_new_device(void) return &usb_dev[dev_index - 1]; }
+#endif
/* * By the time we get here, the device has gotten a new device ID @@ -940,6 +1046,7 @@ int usb_new_device(struct usb_device *dev) return 0; }
+#ifndef CONFIG_USB_INIT_MULTI /* build device Tree */ static void usb_scan_devices(void) { @@ -964,5 +1071,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 e0edaad..6c27761 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_INIT_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 38d6ae0..7d9d33a 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -29,12 +29,25 @@
#include "ehci.h"
+#ifdef CONFIG_USB_INIT_MULTI +static struct ehci_ctrl { + struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ + volatile struct ehci_hcor *hcor; + int rootdev; + uint16_t portreset; + struct QH qh_list __attribute__((aligned(32))); + struct QH qh_pool __attribute__((aligned(32))); + struct qTD td_pool[3] __attribute__((aligned (32))); + int ntds; +} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; +#else int rootdev; struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ volatile struct ehci_hcor *hcor;
static uint16_t portreset; static struct QH qh_list __attribute__((aligned(32))); +#endif
static struct descriptor { struct usb_hub_descriptor hub; @@ -230,7 +243,11 @@ static void ehci_free(void *p, size_t sz)
}
+#ifdef CONFIG_USB_INIT_MULTI +static int ehci_reset(volatile struct ehci_hcor *hcor) +#else static int ehci_reset(void) +#endif { uint32_t cmd; uint32_t tmp; @@ -266,6 +283,33 @@ out: return ret; }
+#ifdef CONFIG_USB_INIT_MULTI +static void *ehci_alloc(struct ehci_ctrl *ctrl, size_t sz, size_t align) +{ + void *p; + + switch (sz) { + case sizeof(struct QH): + p = &ctrl->qh_pool; + ctrl->ntds = 0; + break; + case sizeof(struct qTD): + if (ctrl->ntds == 3) { + debug("out of TDs\n"); + return NULL; + } + p = &ctrl->td_pool[ctrl->ntds]; + ctrl->ntds++; + break; + default: + debug("unknown allocation size\n"); + return NULL; + } + + memset(p, 0, sz); + return p; +} +#else static void *ehci_alloc(size_t sz, size_t align) { static struct QH qh __attribute__((aligned(32))); @@ -294,6 +338,7 @@ static void *ehci_alloc(size_t sz, size_t align) memset(p, 0, sz); return p; } +#endif
static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) { @@ -336,6 +381,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t cmd; int timeout; int ret = 0; +#ifdef CONFIG_USB_INIT_MULTI + struct ehci_ctrl *ctrl = dev->controller; + volatile struct ehci_hcor *hcor = ctrl->hcor; +#endif
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); @@ -346,12 +395,20 @@ 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));
+#ifdef CONFIG_USB_INIT_MULTI + qh = (struct QH *) ehci_alloc(ctrl, sizeof(struct QH), 32); +#else qh = ehci_alloc(sizeof(struct QH), 32); +#endif if (qh == NULL) { debug("unable to allocate QH\n"); return -1; } +#ifdef CONFIG_USB_INIT_MULTI + qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH); +#else qh->qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); +#endif c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0; endpt = (8 << 28) | @@ -376,7 +433,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
if (req != NULL) { +#ifdef CONFIG_USB_INIT_MULTI + td = ehci_alloc(ctrl, sizeof(struct qTD), 32); +#else td = ehci_alloc(sizeof(struct qTD), 32); +#endif if (td == NULL) { debug("unable to allocate SETUP td\n"); goto fail; @@ -398,7 +459,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, }
if (length > 0 || req == NULL) { +#ifdef CONFIG_USB_INIT_MULTI + td = ehci_alloc(ctrl, sizeof(struct qTD), 32); +#else td = ehci_alloc(sizeof(struct qTD), 32); +#endif if (td == NULL) { debug("unable to allocate DATA td\n"); goto fail; @@ -422,7 +487,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, }
if (req != NULL) { +#ifdef CONFIG_USB_INIT_MULTI + td = ehci_alloc(ctrl, sizeof(struct qTD), 32); +#else td = ehci_alloc(sizeof(struct qTD), 32); +#endif if (td == NULL) { debug("unable to allocate ACK td\n"); goto fail; @@ -440,10 +509,17 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, tdp = &td->qt_next; }
+#ifdef CONFIG_USB_INIT_MULTI + ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); + + /* Flush dcache */ + ehci_flush_dcache(&ctrl->qh_list); +#else qh_list.qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
/* Flush dcache */ ehci_flush_dcache(&qh_list); +#endif
usbsts = ehci_readl(&hcor->or_usbsts); ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f)); @@ -466,7 +542,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, timeout = USB_TIMEOUT_MS(pipe); do { /* Invalidate dcache */ +#ifdef CONFIG_USB_INIT_MULTI + ehci_invalidate_dcache(&ctrl->qh_list); +#else ehci_invalidate_dcache(&qh_list); +#endif token = hc32_to_cpu(vtd->qt_token); if (!(token & 0x80)) break; @@ -490,7 +570,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, goto fail; }
+#ifdef CONFIG_USB_INIT_MULTI + ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list + | QH_LINK_TYPE_QH); +#else qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH); +#endif
token = hc32_to_cpu(qh->qh_overlay.qt_token); if (!(token & 0x80)) { @@ -561,6 +646,11 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int len, srclen; uint32_t reg; uint32_t *status_reg; +#ifdef CONFIG_USB_INIT_MULTI + struct ehci_ctrl *ctrl = dev->controller; + struct ehci_hccr *hccr = ctrl->hccr; + volatile struct ehci_hcor *hcor = ctrl->hcor; +#endif
if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { printf("The request port(%d) is not configured\n", @@ -633,7 +723,11 @@ 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"); +#ifdef CONFIG_USB_INIT_MULTI + ctrl->rootdev = le16_to_cpu(req->value); +#else rootdev = le16_to_cpu(req->value); +#endif break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: debug("USB_REQ_SET_CONFIGURATION\n"); @@ -683,7 +777,11 @@ 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; +#ifdef CONFIG_USB_INIT_MULTI + if (ctrl->portreset & (1 << le16_to_cpu(req->index))) +#else if (portreset & (1 << le16_to_cpu(req->index))) +#endif tmpbuf[2] |= USB_PORT_STAT_C_RESET;
srcptr = tmpbuf; @@ -735,8 +833,13 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000); if (!ret) +#ifdef CONFIG_USB_INIT_MULTI + ctrl->portreset |= + 1 << le16_to_cpu(req->index); +#else portreset |= 1 << le16_to_cpu(req->index); +#endif else printf("port(%d) reset error\n", le16_to_cpu(req->index) - 1); @@ -768,7 +871,11 @@ 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: +#ifdef CONFIG_USB_INIT_MULTI + ctrl->portreset &= ~(1 << le16_to_cpu(req->index)); +#else portreset &= ~(1 << le16_to_cpu(req->index)); +#endif break; default: debug("unknown feature %x\n", le16_to_cpu(req->value)); @@ -804,6 +911,82 @@ unknown: return -1; }
+#ifdef CONFIG_USB_INIT_MULTI +int usb_lowlevel_stop(int index) +{ + return ehci_hcd_stop(index); +} + +void *usb_lowlevel_init(int index) +{ + uint32_t reg; + uint32_t cmd; + struct ehci_hccr *hccr; + volatile struct ehci_hcor *hcor; + struct QH *qh_list; + + if (ehci_hcd_init(index, &hccr, (struct ehci_hcor **)&hcor) != 0) + return NULL; + + /* EHCI spec section 4.1 */ + if (ehci_reset(hcor) != 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 + 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)); + qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH); + qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12)); + qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); + qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); + qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + qh_list->qh_overlay.qt_token = cpu_to_hc32(0x40); + + /* Set async. queue head pointer. */ + ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list); + + reg = ehci_readl(&hccr->cr_hcsparams); + descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); + printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); + /* Port Indicators */ + if (HCS_INDICATOR(reg)) + descriptor.hub.wHubCharacteristics |= 0x80; + /* Port Power Control */ + if (HCS_PPC(reg)) + descriptor.hub.wHubCharacteristics |= 0x01; + + /* Start the host controller. */ + cmd = ehci_readl(&hcor->or_usbcmd); + /* + * Philips, Intel, and maybe others need CMD_RUN before the + * root hub will detect new devices (why?); NEC doesn't + */ + cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); + cmd |= CMD_RUN; + ehci_writel(&hcor->or_usbcmd, cmd); + + /* take control over the ports */ + cmd = ehci_readl(&hcor->or_configflag); + cmd |= FLAG_CF; + ehci_writel(&hcor->or_configflag, cmd); + /* unblock posted write */ + cmd = ehci_readl(&hcor->or_usbcmd); + mdelay(5); + reg = HC_VERSION(ehci_readl(&hccr->cr_capbase)); + printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); + + ehcic[index].rootdev = 0; + + return ehcic + index; +} +#else int usb_lowlevel_stop(void) { return ehci_hcd_stop(); @@ -872,6 +1055,7 @@ int usb_lowlevel_init(void)
return 0; } +#endif
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, @@ -889,14 +1073,22 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *setup) { +#ifdef CONFIG_USB_INIT_MULTI + struct ehci_ctrl *ctrl = dev->controller; +#endif
if (usb_pipetype(pipe) != PIPE_CONTROL) { debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); return -1; }
+#ifdef CONFIG_USB_INIT_MULTI + if (usb_pipedevice(pipe) == ctrl->rootdev) { + if (ctrl->rootdev == 0) +#else if (usb_pipedevice(pipe) == rootdev) { if (rootdev == 0) +#endif dev->speed = USB_SPEED_HIGH; return ehci_submit_root(dev, pipe, buffer, length, setup); } diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index a7e105b..f676902 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 NVIDIA Corporation + * Copyright (c) 2009-2012 NVIDIA Corporation * * See file CREDITS for list of people who contributed to this * project. @@ -34,6 +34,12 @@ * Create the appropriate control structures to manage * a new EHCI host controller. */ +#ifdef CONFIG_USB_INIT_MULTI +int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) +{ + return tegrausb_start_port(index, hccr, hcor); +} +#else int ehci_hcd_init(void) { u32 our_hccr, our_hcor; @@ -50,13 +56,22 @@ int ehci_hcd_init(void)
return 0; } +#endif
/* * Destroy the appropriate control structures corresponding * the the EHCI host controller. */ +#ifdef CONFIG_USB_INIT_MULTI +int ehci_hcd_stop(int index) +{ + tegrausb_stop_port(index); + return 0; +} +#else int ehci_hcd_stop(void) { tegrausb_stop_port(); return 0; } +#endif diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index cc00ce4..059827a 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_INIT_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/configs/seaboard.h b/include/configs/seaboard.h index f46740e..0c66e16 100644 --- a/include/configs/seaboard.h +++ b/include/configs/seaboard.h @@ -107,6 +107,8 @@ #define CONFIG_USB_EHCI_TEGRA #define CONFIG_USB_STORAGE #define CONFIG_CMD_USB +#define CONFIG_USB_INIT_MULTI +#define CONFIG_USB_MAX_CONTROLLER_COUNT 3
/* USB networking support */ #define CONFIG_USB_HOST_ETHER diff --git a/include/usb.h b/include/usb.h index 48e4bcd..018567c 100644 --- a/include/usb.h +++ b/include/usb.h @@ -128,6 +128,9 @@ struct usb_device { int portnr; struct usb_device *parent; struct usb_device *children[USB_MAXCHILDREN]; +#ifdef CONFIG_USB_INIT_MULTI + void *controller; /* hardware controller private data */ +#endif };
/********************************************************************** @@ -141,8 +144,13 @@ struct usb_device { defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \ defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X)
+#ifdef CONFIG_USB_INIT_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, @@ -370,7 +378,11 @@ void usb_hub_reset(void); int hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat);
+#ifdef CONFIG_USB_INIT_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