[U-Boot] [PATCH v2 0/5] usb: ss: Some fixes and cleanup for USB super-speed support

Based on 'u-boot-usb' master branch.
This patch-series includes majorly some clean-up, few fixes and then some basic super-speed usb infrastructure addition, to help put support for XHCI in near future.
Changes from v1: - Fixing the issue with 'ifno' as well as added 'if_desc'. - Instead of turning-on only powered-off hub ports, power-cycle all the hub ports (aka: turning off and then turning on again power to all the ports. - Fixing commenting style problem in 'usb: Update device class in usb device's descriptor' - Fixing typo in commit message for 'usb: hub: Fix enumration timeout' - Removing separate definition for 'struct usb_ep_desc'; thereby adding 'struct usb_ss_ep_comp_descriptor' to 'struct usb_interface' only. As a result modifying the patch accordingly also dropping the patch 'usb: eth: Fix for updated usb interface descriptor structure' - Dropping the patch 'usb: hub: Increase device enumeration timeout for broken drives' for now (will come back with a solution at later point of time).
Vivek Gautam (5): USB: Some cleanup prior to USB 3.0 interface addition usb: hub: Power-cycle on root-hub ports usb: Update device class in usb device's descriptor usb: hub: Fix enumration timeout USB: SS: Add support for Super Speed USB interface
common/cmd_usb.c | 4 +++- common/usb.c | 31 +++++++++++++++++++++++-------- common/usb_hub.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- common/usb_storage.c | 30 ++++++++++++++++-------------- include/usb.h | 6 ++++++ include/usb_defs.h | 26 ++++++++++++++++++++++++-- 6 files changed, 114 insertions(+), 28 deletions(-)

Some cleanup in usb framework, nothing much on feature side.
Signed-off-by: Vikas C Sajjan vikas.sajjan@samsung.com Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/usb.c | 21 +++++++++++++-------- common/usb_storage.c | 30 ++++++++++++++++-------------- include/usb_defs.h | 2 +- 3 files changed, 30 insertions(+), 23 deletions(-)
diff --git a/common/usb.c b/common/usb.c index 6fc0fc1..872d62f 100644 --- a/common/usb.c +++ b/common/usb.c @@ -360,6 +360,7 @@ static int usb_parse_config(struct usb_device *dev, int index, ifno, epno, curr_if_num; int i; u16 ep_wMaxPacketSize; + struct usb_interface *if_desc = NULL;
ifno = -1; epno = -1; @@ -387,23 +388,27 @@ static int usb_parse_config(struct usb_device *dev, &buffer[index])->bInterfaceNumber != curr_if_num) { /* this is a new interface, copy new desc */ ifno = dev->config.no_of_if; + if_desc = &dev->config.if_desc[ifno]; dev->config.no_of_if++; - memcpy(&dev->config.if_desc[ifno], - &buffer[index], buffer[index]); - dev->config.if_desc[ifno].no_of_ep = 0; - dev->config.if_desc[ifno].num_altsetting = 1; + memcpy(if_desc, &buffer[index], buffer[index]); + if_desc->no_of_ep = 0; + if_desc->num_altsetting = 1; curr_if_num = - dev->config.if_desc[ifno].desc.bInterfaceNumber; + if_desc->desc.bInterfaceNumber; } else { /* found alternate setting for the interface */ - dev->config.if_desc[ifno].num_altsetting++; + if (ifno >= 0) { + if_desc = &dev->config.if_desc[ifno]; + if_desc->num_altsetting++; + } } break; case USB_DT_ENDPOINT: epno = dev->config.if_desc[ifno].no_of_ep; + if_desc = &dev->config.if_desc[ifno]; /* found an endpoint */ - dev->config.if_desc[ifno].no_of_ep++; - memcpy(&dev->config.if_desc[ifno].ep_desc[epno], + if_desc->no_of_ep++; + memcpy(&if_desc->ep_desc[epno], &buffer[index], buffer[index]); ep_wMaxPacketSize = get_unaligned(&dev->config.\ if_desc[ifno].\ diff --git a/common/usb_storage.c b/common/usb_storage.c index fb322b4..7115992 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -278,9 +278,9 @@ int usb_stor_scan(int mode) lun++) { usb_dev_desc[usb_max_devs].lun = lun; if (usb_stor_get_info(dev, &usb_stor[start], - &usb_dev_desc[usb_max_devs]) == 1) { - usb_max_devs++; - } + &usb_dev_desc[usb_max_devs]) == 1) { + usb_max_devs++; + } } } /* if storage device */ @@ -511,7 +511,7 @@ static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us) dir_in = US_DIRECTION(srb->cmd[0]);
#ifdef BBB_COMDAT_TRACE - printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n", + printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n", dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen, srb->pdata); if (srb->cmdlen) { @@ -1218,6 +1218,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, { struct usb_interface *iface; int i; + struct usb_endpoint_descriptor *ep_desc; unsigned int flags = 0;
int protocol = 0; @@ -1300,24 +1301,25 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, * We will ignore any others. */ for (i = 0; i < iface->desc.bNumEndpoints; i++) { + ep_desc = &iface->ep_desc[i]; /* is it an BULK endpoint? */ - if ((iface->ep_desc[i].bmAttributes & + if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN) - ss->ep_in = iface->ep_desc[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; + if (ep_desc->bEndpointAddress & USB_DIR_IN) + ss->ep_in = ep_desc->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; else ss->ep_out = - iface->ep_desc[i].bEndpointAddress & + ep_desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; }
/* is it an interrupt endpoint? */ - if ((iface->ep_desc[i].bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { - ss->ep_int = iface->ep_desc[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - ss->irqinterval = iface->ep_desc[i].bInterval; + if ((ep_desc->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { + ss->ep_int = ep_desc->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + ss->irqinterval = ep_desc->bInterval; } } USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n", diff --git a/include/usb_defs.h b/include/usb_defs.h index 9502544..0c78d9d 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -234,7 +234,7 @@ #define HUB_CHAR_OCPM 0x0018
/* - *Hub Status & Hub Change bit masks + * Hub Status & Hub Change bit masks */ #define HUB_STATUS_LOCAL_POWER 0x0001 #define HUB_STATUS_OVERCURRENT 0x0002

XHCI ports are powered on after a H/W reset, however EHCI ports are not. So disabling and re-enabling power on all ports invariably.
Signed-off-by: Amar amarendra.xt@samsung.com Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/usb_hub.c | 36 ++++++++++++++++++++++++++++++++++++ 1 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index b5eeb62..4bfed09 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -111,11 +111,47 @@ static void usb_hub_power_on(struct usb_hub_device *hub) int i; struct usb_device *dev; unsigned pgood_delay = hub->desc.bPwrOn2PwrGood * 2; + ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); + unsigned short portstatus; + int ret;
dev = hub->pusb_dev; /* Enable power to the ports */ USB_HUB_PRINTF("enabling power on all ports\n"); for (i = 0; i < dev->maxchild; i++) { + /* + * Power-cycle the ports here: aka, + * turning them off and turning on again. + */ + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + USB_HUB_PRINTF("port %d returns %lX\n", i + 1, dev->status); + + /* Wait at least 2*bPwrOn2PwrGood for PP to change */ + mdelay(pgood_delay); + + ret = usb_get_port_status(dev, i + 1, portsts); + if (ret < 0) { + USB_HUB_PRINTF("port %d: get_port_status failed\n", + i + 1); + return; + } + + /* + * Check to confirm the state of Port Power: + * xHCI says "After modifying PP, s/w shall read + * PP and confirm that it has reached the desired state + * before modifying it again, undefined behavior may occur + * if this procedure is not followed". + * EHCI doesn't say anything like this, but no harm in keeping + * this. + */ + portstatus = le16_to_cpu(portsts->wPortStatus); + if (portstatus & (USB_PORT_STAT_POWER << 1)) { + USB_HUB_PRINTF("port %d: Port power change failed\n", + i + 1); + return; + } + usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); USB_HUB_PRINTF("port %d returns %lX\n", i + 1, dev->status); }

Fetch the device class into usb device's dwcriptors, so that the host controller's driver can use this info to differentiate between HUB and DEVICE.
Signed-off-by: Amar amarendra.xt@samsung.com --- common/usb.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/common/usb.c b/common/usb.c index 872d62f..fd1cad1 100644 --- a/common/usb.c +++ b/common/usb.c @@ -890,6 +890,11 @@ int usb_new_device(struct usb_device *dev) }
dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; + /* + * Fetch the device class, driver can use this info + * to differentiate between HUB and DEVICE. + */ + dev->descriptor.bDeviceClass = desc->bDeviceClass;
/* find the port number we're at */ if (parent) {

Patch b6d7852c increases timeout for enumeration, taking worst case to be 10 sec. get_timer() api returns timestamp in milliseconds, which is what we are checking in the do-while() loop in usb_hub_configure() (get_timer(start) < CONFIG_SYS_HZ * 10). This should give us a required check for 10 seconds, and thereby we don't need to add additional mdelay of 100 microseconds in each cycle.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com Reviewed-by: Vipin Kumar vipin.kumar@st.com --- common/usb_hub.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index 4bfed09..1757dc6 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -459,7 +459,6 @@ static int usb_hub_configure(struct usb_device *dev) (portstatus & USB_PORT_STAT_CONNECTION)) break;
- mdelay(100); } while (get_timer(start) < CONFIG_SYS_HZ * 10);
if (ret < 0)

This adds usb framework support for super-speed usb, which will further facilitate to add stack support for xHCI.
Signed-off-by: Vikas C Sajjan vikas.sajjan@samsung.com Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/cmd_usb.c | 4 +++- common/usb.c | 5 +++++ common/usb_hub.c | 8 ++++++-- include/usb.h | 6 ++++++ include/usb_defs.h | 24 +++++++++++++++++++++++- 5 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/common/cmd_usb.c b/common/cmd_usb.c index dacdc2d..5702c28 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -271,7 +271,9 @@ static void usb_display_config(struct usb_device *dev)
static inline char *portspeed(int speed) { - if (speed == USB_SPEED_HIGH) + if (speed == USB_SPEED_SUPER) + return "5 Gb/s"; + else if (speed == USB_SPEED_HIGH) return "480 Mb/s"; else if (speed == USB_SPEED_LOW) return "1.5 Mb/s"; diff --git a/common/usb.c b/common/usb.c index fd1cad1..6227f70 100644 --- a/common/usb.c +++ b/common/usb.c @@ -421,6 +421,11 @@ static int usb_parse_config(struct usb_device *dev, wMaxPacketSize); USB_PRINTF("if %d, ep %d\n", ifno, epno); break; + case USB_DT_SS_ENDPOINT_COMP: + if_desc = &dev->config.if_desc[ifno]; + memcpy(&(if_desc->ss_ep_comp_desc[epno]), + &buffer[index], buffer[index]); + break; default: if (head->bLength == 0) return 1; diff --git a/common/usb_hub.c b/common/usb_hub.c index 1757dc6..2462640 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -178,7 +178,9 @@ static struct usb_hub_device *usb_hub_allocate(void)
static inline char *portspeed(int portstatus) { - if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) + if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED)) + return "5 Gb/s"; + else if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) return "480 Mb/s"; else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) return "1.5 Mb/s"; @@ -282,7 +284,9 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) /* Allocate a new device struct for it */ usb = usb_alloc_new_device(dev->controller);
- if (portstatus & USB_PORT_STAT_HIGH_SPEED) + if (portstatus & USB_PORT_STAT_SUPER_SPEED) + usb->speed = USB_SPEED_SUPER; + else if (portstatus & USB_PORT_STAT_HIGH_SPEED) usb->speed = USB_SPEED_HIGH; else if (portstatus & USB_PORT_STAT_LOW_SPEED) usb->speed = USB_SPEED_LOW; diff --git a/include/usb.h b/include/usb.h index d79c865..d7b082d 100644 --- a/include/usb.h +++ b/include/usb.h @@ -76,6 +76,12 @@ struct usb_interface { unsigned char act_altsetting;
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; + /* + * Super Speed Device will have Super Speed Endpoint + * Companion Descriptor (section 9.6.7 of usb 3.0 spec) + * Revision 1.0 June 6th 2011 + */ + struct usb_ss_ep_comp_descriptor ss_ep_comp_desc[USB_MAXENDPOINTS]; } __attribute__ ((packed));
/* Configuration information.. */ diff --git a/include/usb_defs.h b/include/usb_defs.h index 0c78d9d..e2aaef3 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -203,6 +203,8 @@ #define USB_PORT_FEAT_POWER 8 #define USB_PORT_FEAT_LOWSPEED 9 #define USB_PORT_FEAT_HIGHSPEED 10 +#define USB_PORT_FEAT_FULLSPEED 11 +#define USB_PORT_FEAT_SUPERSPEED 12 #define USB_PORT_FEAT_C_CONNECTION 16 #define USB_PORT_FEAT_C_ENABLE 17 #define USB_PORT_FEAT_C_SUSPEND 18 @@ -218,8 +220,20 @@ #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_LOW_SPEED 0x0200 #define USB_PORT_STAT_HIGH_SPEED 0x0400 /* support for EHCI */ +#define USB_PORT_STAT_FULL_SPEED 0x0800 +#define USB_PORT_STAT_SUPER_SPEED 0x1000 /* support for XHCI */ #define USB_PORT_STAT_SPEED \ - (USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED) + (USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED | \ + USB_PORT_STAT_FULL_SPEED | USB_PORT_STAT_SUPER_SPEED) + +/* + * Additions to wPortStatus bit field from USB 3.0 + * See USB 3.0 spec Table 10-10 + */ +#define USB_PORT_STAT_LINK_STATE 0x01e0 +#define USB_SS_PORT_STAT_POWER 0x0200 +#define USB_SS_PORT_STAT_SPEED 0x1c00 +#define USB_PORT_STAT_SPEED_5GBPS 0x0000
/* wPortChange bits */ #define USB_PORT_STAT_C_CONNECTION 0x0001 @@ -228,6 +242,14 @@ #define USB_PORT_STAT_C_OVERCURRENT 0x0008 #define USB_PORT_STAT_C_RESET 0x0010
+/* + * Addition to wPortChange bit fields form USB 3.0 + * See USB 3.0 spec Table 10-11 + */ +#define USB_PORT_STAT_C_BH_RESET 0x0020 +#define USB_PORT_STAT_C_LINK_STATE 0x0040 +#define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 + /* wHubCharacteristics (masks) */ #define HUB_CHAR_LPSM 0x0003 #define HUB_CHAR_COMPOUND 0x0004

On Mon, Apr 8, 2013 at 4:05 PM, Vivek Gautam gautam.vivek@samsung.com wrote:
Based on 'u-boot-usb' master branch.
This patch-series includes majorly some clean-up, few fixes and then some basic super-speed usb infrastructure addition, to help put support for XHCI in near future.
Changes from v1:
- Fixing the issue with 'ifno' as well as added 'if_desc'.
- Instead of turning-on only powered-off hub ports, power-cycle all the hub ports (aka: turning off and then turning on again power to all the ports.
- Fixing commenting style problem in 'usb: Update device class in usb device's descriptor'
- Fixing typo in commit message for 'usb: hub: Fix enumration timeout'
- Removing separate definition for 'struct usb_ep_desc'; thereby adding 'struct usb_ss_ep_comp_descriptor' to 'struct usb_interface' only. As a result modifying the patch accordingly also dropping the patch 'usb: eth: Fix for updated usb interface descriptor structure'
- Dropping the patch 'usb: hub: Increase device enumeration timeout for broken drives' for now (will come back with a solution at later point of time).
Re-spinning this patch-series for V3.
participants (2)
-
Vivek Gautam
-
Vivek Gautam