[U-Boot] [PATCH 1/1] tegra: seaboard: Initialize multiple USB controllers at once

Jim Lin jilin at nvidia.com
Thu Jun 14 06:17:31 CEST 2012


From: Jim Lin <jilin at 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 at 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



More information about the U-Boot mailing list