Merge "usb: hub: Add a new API to test if a hub device is root hub"
diff --git a/common/usb_hub.c b/common/usb_hub.c
index e1de813..0eb8f15 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -55,11 +55,31 @@
return;
}
+static inline bool usb_hub_is_superspeed(struct usb_device *hdev)
+{
+ return hdev->descriptor.bDeviceProtocol == 3;
+}
+
+#ifdef CONFIG_DM_USB
+bool usb_hub_is_root_hub(struct udevice *hub)
+{
+ if (device_get_uclass_id(hub->parent) != UCLASS_USB_HUB)
+ return true;
+
+ return false;
+}
+#endif
+
static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
{
+ unsigned short dtype = USB_DT_HUB;
+
+ if (usb_hub_is_superspeed(dev))
+ dtype = USB_DT_SS_HUB;
+
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
- USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT);
+ dtype << 8, 0, data, size, USB_CNTL_TIMEOUT);
}
static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
@@ -371,17 +391,19 @@
&descriptor->wHubCharacteristics)),
&hub->desc.wHubCharacteristics);
/* set the bitmap */
- bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0];
+ bitmap = (unsigned char *)&hub->desc.u.hs.DeviceRemovable[0];
/* devices not removable by default */
memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8);
- bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0];
+ bitmap = (unsigned char *)&hub->desc.u.hs.PortPowerCtrlMask[0];
memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */
for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
- hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i];
+ hub->desc.u.hs.DeviceRemovable[i] =
+ descriptor->u.hs.DeviceRemovable[i];
for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
- hub->desc.PortPowerCtrlMask[i] = descriptor->PortPowerCtrlMask[i];
+ hub->desc.u.hs.PortPowerCtrlMask[i] =
+ descriptor->u.hs.PortPowerCtrlMask[i];
dev->maxchild = descriptor->bNbrPorts;
debug("%d ports detected\n", dev->maxchild);
@@ -425,7 +447,7 @@
for (i = 0; i < dev->maxchild; i++)
debug("port %d is%s removable\n", i + 1,
- hub->desc.DeviceRemovable[(i + 1) / 8] & \
+ hub->desc.u.hs.DeviceRemovable[(i + 1) / 8] & \
(1 << ((i + 1) % 8)) ? " not" : "");
if (sizeof(struct usb_hub_status) > USB_BUFSIZ) {
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index 624fbde..a86aa7a 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -96,7 +96,12 @@
1 << 7),
.bPwrOn2PwrGood = 2,
.bHubContrCurrent = 5,
- .DeviceRemovable = {0, 0xff}, /* all ports removeable */
+ {
+ {
+ /* all ports removeable */
+ .DeviceRemovable = {0, 0xff}
+ }
+ }
#if SANDBOX_NUM_PORTS > 8
#error "This code sets up an incorrect mask"
#endif
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c664b16..ba12808 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -52,8 +52,8 @@
0, /* wHubCharacteristics */
10, /* bPwrOn2PwrGood */
0, /* bHubCntrCurrent */
- {}, /* Device removable */
- {} /* at most 7 ports! XXX */
+ { /* Device removable */
+ } /* at most 7 ports! XXX */
},
{
0x12, /* bLength */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d599117..3a0c79d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -50,8 +50,8 @@
cpu_to_le16(0x8), /* wHubCharacteristics */
10, /* bPwrOn2PwrGood */
0, /* bHubCntrCurrent */
- {}, /* Device removable */
- {} /* at most 7 ports! XXX */
+ { /* Device removable */
+ } /* at most 7 ports! XXX */
},
{
0x12, /* bLength */
@@ -727,6 +727,7 @@
case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
switch (le16_to_cpu(req->value) >> 8) {
case USB_DT_HUB:
+ case USB_DT_SS_HUB:
debug("USB_DT_HUB config\n");
srcptr = &descriptor.hub;
srclen = 0x8;
@@ -1111,26 +1112,6 @@
#endif /* CONFIG_DM_USB */
#ifdef CONFIG_DM_USB
-/*
-static struct usb_device *get_usb_device(struct udevice *dev)
-{
- struct usb_device *udev;
-
- if (device_get_uclass_id(dev) == UCLASS_USB)
- udev = dev_get_uclass_priv(dev);
- else
- udev = dev_get_parent_priv(dev);
-
- return udev;
-}
-*/
-static bool is_root_hub(struct udevice *dev)
-{
- if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB)
- return true;
-
- return false;
-}
static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
@@ -1145,10 +1126,10 @@
hub = udev->dev;
if (device_get_uclass_id(hub) == UCLASS_USB_HUB) {
/* Figure out our port number on the root hub */
- if (is_root_hub(hub)) {
+ if (usb_hub_is_root_hub(hub)) {
root_portnr = udev->portnr;
} else {
- while (!is_root_hub(hub->parent))
+ while (!usb_hub_is_root_hub(hub->parent))
hub = hub->parent;
uhop = dev_get_parent_priv(hub);
root_portnr = uhop->portnr;
diff --git a/include/usb.h b/include/usb.h
index 0b410b6..f2bd76e 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -546,10 +546,20 @@
unsigned short wHubCharacteristics;
unsigned char bPwrOn2PwrGood;
unsigned char bHubContrCurrent;
- unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8];
- unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8];
- /* DeviceRemovable and PortPwrCtrlMask want to be variable-length
- bitmaps that hold max 255 entries. (bit0 is ignored) */
+ /* 2.0 and 3.0 hubs differ here */
+ union {
+ struct {
+ /* add 1 bit for hub status change; round to bytes */
+ __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+ __u8 PortPowerCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
+ } __attribute__ ((packed)) hs;
+
+ struct {
+ __u8 bHubHdrDecLat;
+ __le16 wHubDelay;
+ __le16 DeviceRemovable;
+ } __attribute__ ((packed)) ss;
+ } u;
} __attribute__ ((packed));
@@ -762,6 +772,14 @@
struct usb_device *parent);
/**
+ * usb_hub_is_root_hub() - Test whether a hub device is root hub or not
+ *
+ * @hub: USB hub device to test
+ * @return: true if the hub device is root hub, false otherwise.
+ */
+bool usb_hub_is_root_hub(struct udevice *hub);
+
+/**
* usb_hub_scan() - Scan a hub and find its devices
*
* @hub: Hub device to scan
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 8214ba9..608a0ca 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -93,6 +93,7 @@
#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
+#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a)
/* Descriptor sizes per descriptor type */
#define USB_DT_DEVICE_SIZE 18