Skip to contentSkip to conversation

tegra: seaboard: Initialize multiple USB controllers at once

PATCH New Jim Lin 3 participants 3 messages Jun 14, 2012

Subsystems (4)
lore
Share & tools
lore

Jim Lin

author
#0 lore raw

PATCH 1/1 tegra: seaboard: Initialize multiple USB controllers at once

From: Jim Lin <[email protected]>

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

---
 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(-)
arch/arm/cpu/armv7/tegra2/usb.c +15 -0
index c80de7f..3d2cfb9 100644
@@ -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);
arch/arm/include/asm/arch-tegra2/usb.h +4 -0
index 638033b..119d7b4 100644
@@ -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_ */
common/cmd_usb.c +10 -0
index 9eba271..4c01a78 100644
@@ -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) {
common/usb.c +108 -0

144 lines not on this page · raw message

common/usb_hub.c +4 -0
index e0edaad..6c27761 100644
@@ -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;
drivers/usb/host/ehci-hcd.c +192 -0

347 lines not on this page · raw message

drivers/usb/host/ehci-tegra.c +16 -1
index a7e105b..f676902 100644
@@ -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
drivers/usb/host/ehci.h +5 -0
index cc00ce4..059827a 100644
@@ -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 */
include/configs/seaboard.h +2 -0
index f46740e..0c66e16 100644
@@ -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
include/usb.h +12 -0
index 48e4bcd..018567c 100644
@@ -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

#1 lore raw

PATCH 1/1 tegra: seaboard: Initialize multiple USB controllers at once

Quoted 3 lines · Jim Lin

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.

These patches also need to be sent to the USB maintainer since they touch core USB code. (Now CC'd)

Rather than one mega-patch that touch the USB core, and the Tegra driver, can't the patch be split up a bit so that one patch adds the ability to support multiple controllers, and then another patch modifies the Tegra USB driver to support this, etc. Many smaller patches are much easier to review.

This patch adds a huge number of ifdefs. I'm sure many of them can be removed completely. For example, in the following code, why not /always/ get the rootdev from dev->controller->rootdev, and remove the global variable. I would guess that the code size increase would be extremely minimal, but it would make the code a lot more maintainable by removing all the ifdefs.

Quoted 12 lines

submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int length, struct devrequest *setup)
{

drivers/usb/host/ehci-hcd.c +3 -0
+#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;
        }
 

drivers/usb/host/ehci-hcd.c int · line 1094

Quoted 10 lines
drivers/usb/host/ehci-hcd.c +5 -0
+#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);
        }

The patch above removes the use of the global variable "rootdev", but I don't see anywhere that ifdef's that variable out of existence. Not doing so would allow code to accidentally use the global when it should be using the per-device value; how can you be sure you've patched all the places in the code that you need to? What about future changes to the code by people who aren't aware of the USB_INIT_MULTI feature?

Similarly, why not just outright change the prototype of tegrausb_stop_port() so that it always takes a port number; the existing calls can hard-code a port ID of 0 for compatibility:

Quoted 12 lines
drivers/usb/host/ehci-tegra.c +7 -0
+#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;
 }
Quoted 1 line
Quoted 1 line

+#endif

In the end, I think if you rework the patch to remove all/most of the ifdefs, the only thing that's left will be that the loop to initialize USB would loop over either just device 0 or devices 0..n-1, and even that wouldn't need to be ifdef'd...

#2 lore raw

PATCH 1/1 tegra: seaboard: Initialize multiple USB controllers at once

Dear Stephen Warren,

Quoted 7 lines · Jim Lin
Quoted 3 lines

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.

These patches also need to be sent to the USB maintainer since they touch core USB code. (Now CC'd)

Ok, waiting for smaller patches indeed,

Best regards,
Marek Vasut