public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
@ 2012-08-08  9:48 Jim Lin
  2012-08-11 23:46 ` Marek Vasut
  0 siblings, 1 reply; 9+ messages in thread
From: Jim Lin @ 2012-08-08  9:48 UTC (permalink / raw)
  To: u-boot

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@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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
@ 2012-08-10  9:36 Jim Lin
  2012-08-10 16:07 ` Stephen Warren
  0 siblings, 1 reply; 9+ messages in thread
From: Jim Lin @ 2012-08-10  9:36 UTC (permalink / raw)
  To: u-boot

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@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.
-----------------------------------------------------------------------------------

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-10  9:36 [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once Jim Lin
@ 2012-08-10 16:07 ` Stephen Warren
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Warren @ 2012-08-10 16:07 UTC (permalink / raw)
  To: u-boot

On 08/10/2012 03:36 AM, Jim Lin wrote:
> 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.

I assume these were reposted because you rebased on the latest
u-boot-tegra/master branch. It's usual to includes details of why you're
reposting.

I applied these two patches, without changing the Seaboard config file,
and built. I got the following warnings:

ehci-hcd.c: In function 'ehci_submit_async':
ehci-hcd.c:250:6: warning: assignment from incompatible pointer type
ehci-hcd.c: In function 'usb_lowlevel_multi_init':
ehci-hcd.c:800:20: warning: assignment discards qualifiers from pointer
target type

I tested the patches in this case and found no regressions on a regular
Seaboard.

I get slightly different warnings if I do enable the feature in the
Seaboard config file:

ehci-hcd.c: In function 'ehci_submit_async':
ehci-hcd.c:250:6: warning: assignment from incompatible pointer type
ehci-hcd.c: In function 'usb_lowlevel_multi_init':
ehci-hcd.c:800:20: warning: assignment discards qualifiers from pointer
target type
ehci-tegra.c: In function 'ehci_hcd_init':
ehci-tegra.c:56:2: warning: passing argument 2 of 'tegrausb_start_port'
from incompatible pointer type
/home/swarren/shared/git_wa/u-boot/include/asm/arch/usb.h:243:5: note:
expected 'u32 *' but argument is of type 'struct ehci_hccr **'
ehci-tegra.c:56:2: warning: passing argument 3 of 'tegrausb_start_port'
from incompatible pointer type
/home/swarren/shared/git_wa/u-boot/include/asm/arch/usb.h:243:5: note:
expected 'u32 *' but argument is of type 'struct ehci_hcor **'

I tested the patches on a regular Seaboard, and found that both USB
ports now work (great!).

However, this patch breaks the "enterrcm" command if "usb start" has
been run, I assume since the VBUS GPIO is asserted to USB port 1. Can we
add some hook into that command to shut down the USB1 VBUS GPIO? I can
live with this patch being applied before that's fixed though.

I also tested Springbank, and found that this also enables the USB port
there, but strangely "enterrcm" following "usb start" does still seem to
work on that board!

So overall, once the warnings are fixed, I'm OK with these patches,
assuming some followup work on "enterrcm" will happen.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-08  9:48 Jim Lin
@ 2012-08-11 23:46 ` Marek Vasut
  2012-08-13 10:25   ` Jim Lin
  2012-08-14  4:22   ` Jim Lin
  0 siblings, 2 replies; 9+ messages in thread
From: Marek Vasut @ 2012-08-11 23:46 UTC (permalink / raw)
  To: u-boot

Dear Jim Lin,

> 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@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

How's this supposed to work? Shouldn't this call usb_show_tree on roots of all 
the trees?

> +               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();

Will the keyboard driver survive this?

> +#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

I still believe it's possible to get rid of this MULTI crap, simply set the 
"multiness" to 1 for non-multi setups. How big overhead will that generate?
[...]
btw you might want to rebase on top of latest u-boot-usb.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-11 23:46 ` Marek Vasut
@ 2012-08-13 10:25   ` Jim Lin
  2012-08-14 17:29     ` Marek Vasut
  2012-08-14  4:22   ` Jim Lin
  1 sibling, 1 reply; 9+ messages in thread
From: Jim Lin @ 2012-08-13 10:25 UTC (permalink / raw)
  To: u-boot

>-----Original Message-----
>From: Marek Vasut [mailto:marex at denx.de] 
>Sent: Sunday, August 12, 2012 7:47 AM
>To: Jim Lin
>Cc: u-boot at lists.denx.de; Wolfgang Denk; Tom Warren
>Subject: Re: [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
>
>> 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
>
>How's this supposed to work? Shouldn't this call usb_show_tree on roots of all the trees?

You see the following  if dev->parent is NULL that means it's the only root hub under a controller
, then we show devices under this root hub of the controller by usb_show_tree.
Root hub under different controller is listed as separate device.

>> +               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
>
>> +#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
>
>I still believe it's possible to get rid of this MULTI crap, simply set the "multiness" to 1 for non-multi setups. How big overhead will that generate?
I assume you want me to use code in ifdef CONFIG_USB_MULTI block,
remove CONFIG_USB_MULTI and if  CONFIG_USB_MAX_CONTROLLER_COUNT is 1
, then do non-multi setups.

nvpublic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-11 23:46 ` Marek Vasut
  2012-08-13 10:25   ` Jim Lin
@ 2012-08-14  4:22   ` Jim Lin
  2012-08-14 16:18     ` Stephen Warren
  1 sibling, 1 reply; 9+ messages in thread
From: Jim Lin @ 2012-08-14  4:22 UTC (permalink / raw)
  To: u-boot

>-----Original Message-----
>From: Marek Vasut [mailto:marex at denx.de] 
>Sent: Sunday, August 12, 2012 7:47 AM
>To: Jim Lin
>Cc: u-boot at lists.denx.de; Wolfgang Denk; Tom Warren
>Subject: Re: [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
>
>Dear Jim Lin,
>
>> 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@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
>
>How's this supposed to work? Shouldn't this call usb_show_tree on roots of all the trees?
See the following code, if dev->parent is NULL, then current device is  root hub, we show devices below it

>> +               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();
>
>Will the keyboard driver survive this?
Yes I have tried it after doing the following.
1. Define CONFIG_USB_KEYBOARD, CONFIG_SYS_USB_EVENT_POLL, CONFIG_USB_MULTI, and CONFIG_USB_MAX_CONTROLLER_COUNT 3
 in config header file like seaboard.h to compile
2. Install USB keyboard
3. Run "usb reset" in u-boot serial console
4. Run "coninfo" to see usbkbd appeared
5. Run "setenv stdin usbkbd"
6. Typing u-boot console command on USB keyboard

--
nvpublic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-14  4:22   ` Jim Lin
@ 2012-08-14 16:18     ` Stephen Warren
  2012-08-14 17:30       ` Marek Vasut
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Warren @ 2012-08-14 16:18 UTC (permalink / raw)
  To: u-boot

On 08/13/2012 10:22 PM, Jim Lin wrote:
> Marek Vasut wrote at Sunday, August 12, 2012 7:47 AM:
>> Dear Jim Lin,
>>
>>> 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.
...
>>> +#ifdef CONFIG_USB_KEYBOARD
>>> +       drv_usb_kbd_init();
>>
>> Will the keyboard driver survive this?
>
> Yes I have tried it after doing the following.
> 1. Define CONFIG_USB_KEYBOARD, CONFIG_SYS_USB_EVENT_POLL, CONFIG_USB_MULTI, and CONFIG_USB_MAX_CONTROLLER_COUNT 3
>  in config header file like seaboard.h to compile
> 2. Install USB keyboard
> 3. Run "usb reset" in u-boot serial console
> 4. Run "coninfo" to see usbkbd appeared
> 5. Run "setenv stdin usbkbd"
> 6. Typing u-boot console command on USB keyboard

I've also tested this on Springbank, which has a built-in USB keyboard
and an external USB port via a separate host controller, which I
connected to an Ethernet device, and it appears to all work very well
for me.

So,

Tested-by: Stephen Warren <swarren@wwwdotorg.org>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-13 10:25   ` Jim Lin
@ 2012-08-14 17:29     ` Marek Vasut
  0 siblings, 0 replies; 9+ messages in thread
From: Marek Vasut @ 2012-08-14 17:29 UTC (permalink / raw)
  To: u-boot

Dear Jim Lin,

> >-----Original Message-----
> >From: Marek Vasut [mailto:marex at denx.de]
> >Sent: Sunday, August 12, 2012 7:47 AM
> >To: Jim Lin
> >Cc: u-boot at lists.denx.de; Wolfgang Denk; Tom Warren
> >Subject: Re: [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB
> >controllers at once
> >
> >> 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
> >
> >How's this supposed to work? Shouldn't this call usb_show_tree on roots of
> >all the trees?
> 
> You see the following  if dev->parent is NULL that means it's the only root
> hub under a controller , then we show devices under this root hub of the
> controller by usb_show_tree. Root hub under different controller is listed
> as separate device.

So if you set USB_MAX_DEVICE to 1, this code won't need the ifdefs? :)

> >> +               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
> >> 
> >> +#endif
> >> +       USB_PRINTF("scan end\n");
> >> +               usb_started = 1;
> >> +               return 0;
> >> +       } else {
> >> +               printf("Error, couldn't init Lowlevel part\n");

puts();

> >> +               usb_started = 0;
> >> +               return -1;
> >> +       }
> >> +}
> >> +
> >> +/********************************************************************
> >> +*****
> >> ***** + * Stop USB this stops the LowLevel Part and deregisters USB
> >> devices. + */
> >> +int usb_stop(void)
> >> +{
> >> +       int i;
> >> +

if (!started)
  return 0;

... do the work ...

;-)

> >> +       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
> >
> >I still believe it's possible to get rid of this MULTI crap, simply set
> >the "multiness" to 1 for non-multi setups. How big overhead will that
> >generate?
> 
> I assume you want me to use code in ifdef CONFIG_USB_MULTI block,
> remove CONFIG_USB_MULTI

Yes!

> and if  CONFIG_USB_MAX_CONTROLLER_COUNT is 1
> , then do non-multi setups.

No ;-) Why can't the "multi setups" be used for "non-multi" configuration?

> nvpublic
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once
  2012-08-14 16:18     ` Stephen Warren
@ 2012-08-14 17:30       ` Marek Vasut
  0 siblings, 0 replies; 9+ messages in thread
From: Marek Vasut @ 2012-08-14 17:30 UTC (permalink / raw)
  To: u-boot

Dear Stephen Warren,

> On 08/13/2012 10:22 PM, Jim Lin wrote:
> > Marek Vasut wrote at Sunday, August 12, 2012 7:47 AM:
> >> Dear Jim Lin,
> >> 
> >>> 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.
> 
> ...
> 
> >>> +#ifdef CONFIG_USB_KEYBOARD
> >>> +       drv_usb_kbd_init();
> >> 
> >> Will the keyboard driver survive this?
> > 
> > Yes I have tried it after doing the following.
> > 1. Define CONFIG_USB_KEYBOARD, CONFIG_SYS_USB_EVENT_POLL,
> > CONFIG_USB_MULTI, and CONFIG_USB_MAX_CONTROLLER_COUNT 3
> > 
> >  in config header file like seaboard.h to compile
> > 
> > 2. Install USB keyboard
> > 3. Run "usb reset" in u-boot serial console
> > 4. Run "coninfo" to see usbkbd appeared
> > 5. Run "setenv stdin usbkbd"
> > 6. Typing u-boot console command on USB keyboard
> 
> I've also tested this on Springbank, which has a built-in USB keyboard
> and an external USB port via a separate host controller, which I
> connected to an Ethernet device, and it appears to all work very well
> for me.
> 
> So,
> 
> Tested-by: Stephen Warren <swarren@wwwdotorg.org>

Good, thanks! :)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-08-14 17:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-10  9:36 [U-Boot] [PATCH v2 1/1] USB: EHCI: Initialize multiple USB controllers at once Jim Lin
2012-08-10 16:07 ` Stephen Warren
  -- strict thread matches above, loose matches on Subject: below --
2012-08-08  9:48 Jim Lin
2012-08-11 23:46 ` Marek Vasut
2012-08-13 10:25   ` Jim Lin
2012-08-14 17:29     ` Marek Vasut
2012-08-14  4:22   ` Jim Lin
2012-08-14 16:18     ` Stephen Warren
2012-08-14 17:30       ` Marek Vasut

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox