Merge "dcache: Skipping dcache flush when no destination pointer"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index fe1e33c..e7ef65d 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -46,7 +46,6 @@
ipq40xx-dk04-c2.dtb \
ipq40xx-dk04-c3.dtb \
ipq40xx-dk04-c4.dtb \
- ipq40xx-dk04-c5.dtb \
ipq40xx-dk07-c1.dtb \
ipq40xx-dk07-c2.dtb \
ipq40xx-dk07-c3.dtb \
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 0eb8f15..c9b530b 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -46,9 +46,6 @@
#define USB_BUFSIZ 512
-/* TODO(sjg@chromium.org): Remove this when CONFIG_DM_USB is defined */
-static struct usb_hub_device hub_dev[USB_MAX_HUB];
-static int usb_hub_index;
__weak void usb_hub_reset_devices(int port)
{
@@ -68,6 +65,16 @@
return false;
}
+
+static int usb_set_hub_depth(struct usb_device *dev, int depth)
+{
+ if (depth < 0 || depth > 4)
+ return -EINVAL;
+
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_HUB_DEPTH, USB_DIR_OUT | USB_RT_HUB,
+ depth, 0, NULL, 0, USB_CNTL_TIMEOUT);
+}
#endif
static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
@@ -105,9 +112,40 @@
int usb_get_port_status(struct usb_device *dev, int port, void *data)
{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ int ret;
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
+
+#ifdef CONFIG_DM_USB
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Translate the USB 3.0 hub port status field into the old version
+ * that U-Boot understands. Do this only when the hub is not root hub.
+ * For root hub, the port status field has already been translated
+ * in the host controller driver (see xhci_submit_root() in xhci.c).
+ *
+ * Note: this only supports driver model.
+ */
+
+ if (!usb_hub_is_root_hub(dev->dev) && usb_hub_is_superspeed(dev)) {
+ struct usb_port_status *status = (struct usb_port_status *)data;
+ u16 tmp = (status->wPortStatus) & USB_SS_PORT_STAT_MASK;
+
+ if (status->wPortStatus & USB_SS_PORT_STAT_POWER)
+ tmp |= USB_PORT_STAT_POWER;
+ if ((status->wPortStatus & USB_SS_PORT_STAT_SPEED) ==
+ USB_SS_PORT_STAT_SPEED_5GBPS)
+ tmp |= USB_PORT_STAT_SUPER_SPEED;
+
+ status->wPortStatus = tmp;
+ }
+#endif
+
+ return ret;
}
@@ -140,6 +178,10 @@
mdelay(pgood_delay + 1000);
}
+#ifndef CONFIG_DM_USB
+static struct usb_hub_device hub_dev[USB_MAX_HUB];
+static int usb_hub_index;
+
void usb_hub_reset(void)
{
usb_hub_index = 0;
@@ -153,6 +195,7 @@
printf("ERROR: USB_MAX_HUB (%d) reached\n", USB_MAX_HUB);
return NULL;
}
+#endif
#define MAX_TRIES 5
@@ -351,6 +394,20 @@
}
+static struct usb_hub_device *usb_get_hub_device(struct usb_device *dev)
+{
+ struct usb_hub_device *hub;
+
+#ifndef CONFIG_DM_USB
+ /* "allocate" Hub device */
+ hub = usb_hub_allocate();
+#else
+ hub = dev_get_uclass_priv(dev->dev);
+#endif
+
+ return hub;
+}
+
static int usb_hub_configure(struct usb_device *dev)
{
int i, length;
@@ -362,11 +419,11 @@
__maybe_unused struct usb_hub_status *hubsts;
int ret;
- /* "allocate" Hub device */
- hub = usb_hub_allocate();
+ hub = usb_get_hub_device(dev);
if (hub == NULL)
return -ENOMEM;
hub->pusb_dev = dev;
+
/* Get the the hub descriptor */
ret = usb_get_hub_descriptor(dev, buffer, 4);
if (ret < 0) {
@@ -476,6 +533,48 @@
debug("%sover-current condition exists\n",
(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \
"" : "no ");
+
+#ifdef CONFIG_DM_USB
+ /*
+ * A maximum of seven tiers are allowed in a USB topology, and the
+ * root hub occupies the first tier. The last tier ends with a normal
+ * USB device. USB 3.0 hubs use a 20-bit field called 'route string'
+ * to route packets to the designated downstream port. The hub uses a
+ * hub depth value multiplied by four as an offset into the 'route
+ * string' to locate the bits it uses to determine the downstream
+ * port number.
+ */
+ if (usb_hub_is_root_hub(dev->dev)) {
+ hub->hub_depth = -1;
+ } else {
+ struct udevice *hdev;
+ int depth = 0;
+
+ hdev = dev->dev->parent;
+ while (!usb_hub_is_root_hub(hdev)) {
+ depth++;
+ hdev = hdev->parent;
+ }
+
+ hub->hub_depth = depth;
+
+ if (usb_hub_is_superspeed(dev)) {
+ debug("set hub (%p) depth to %d\n", dev, depth);
+ /*
+ * This request sets the value that the hub uses to
+ * determine the index into the 'route string index'
+ * for this hub.
+ */
+ ret = usb_set_hub_depth(dev, depth);
+ if (ret < 0) {
+ debug("%s: failed to set hub depth (%lX)\n",
+ __func__, dev->status);
+ return ret;
+ }
+ }
+ }
+#endif
+
usb_hub_power_on(hub);
/*
@@ -677,6 +776,7 @@
.child_pre_probe = usb_child_pre_probe,
.per_child_auto_alloc_size = sizeof(struct usb_device),
.per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
+ .per_device_auto_alloc_size = sizeof(struct usb_hub_device),
};
static const struct usb_device_id hub_id_table[] = {
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index ec8b403..0b268d1 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -174,7 +174,6 @@
#ifdef CONFIG_USB_STORAGE
usb_stor_reset();
#endif
- usb_hub_reset();
uc_priv->companion_device_count = 0;
usb_started = 0;
@@ -227,7 +226,6 @@
int ret;
asynch_allowed = 1;
- usb_hub_reset();
ret = uclass_get(UCLASS_USB, &uc);
if (ret)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 3744452..d6cefc1 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -626,14 +626,21 @@
* @param udev pointer to the Device Data Structure
* @return returns negative value on failure else 0 on success
*/
-void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, int slot_id,
- int speed, int hop_portnr)
+void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
+ struct usb_device *udev, int hop_portnr)
{
struct xhci_virt_device *virt_dev;
struct xhci_ep_ctx *ep0_ctx;
struct xhci_slot_ctx *slot_ctx;
u32 port_num = 0;
u64 trb_64 = 0;
+ int slot_id = udev->slot_id;
+ int speed = udev->speed;
+ int route = 0;
+#ifdef CONFIG_DM_USB
+ struct usb_device *dev = udev;
+ struct usb_hub_device *hub;
+#endif
virt_dev = ctrl->devs[slot_id];
@@ -644,7 +651,32 @@
slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx);
/* Only the control endpoint is valid - one endpoint context */
- slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | 0);
+ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
+
+#ifdef CONFIG_DM_USB
+ /* Calculate the route string for this device */
+ port_num = dev->portnr;
+ while (!usb_hub_is_root_hub(dev->dev)) {
+ hub = dev_get_uclass_priv(dev->dev);
+ /*
+ * Each hub in the topology is expected to have no more than
+ * 15 ports in order for the route string of a device to be
+ * unique. SuperSpeed hubs are restricted to only having 15
+ * ports, but FS/LS/HS hubs are not. The xHCI specification
+ * says that if the port number the device is greater than 15,
+ * that portion of the route string shall be set to 15.
+ */
+ if (port_num > 15)
+ port_num = 15;
+ route |= port_num << (hub->hub_depth * 4);
+ dev = dev_get_parent_priv(dev->dev);
+ port_num = dev->portnr;
+ dev = dev_get_parent_priv(dev->dev->parent);
+ }
+
+ debug("route string %x\n", route);
+#endif
+ slot_ctx->dev_info |= route;
switch (speed) {
case USB_SPEED_SUPER:
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 3a0c79d..97d64ca 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -415,8 +415,7 @@
* so setting up the slot context.
*/
debug("Setting up addressable devices %p\n", ctrl->dcbaa);
- xhci_setup_addressable_virt_dev(ctrl, udev->slot_id, udev->speed,
- root_portnr);
+ xhci_setup_addressable_virt_dev(ctrl, udev, root_portnr);
ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx);
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b683850..c081b3c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1244,8 +1244,8 @@
void xhci_slot_copy(struct xhci_ctrl *ctrl,
struct xhci_container_ctx *in_ctx,
struct xhci_container_ctx *out_ctx);
-void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, int slot_id,
- int speed, int hop_portnr);
+void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
+ struct usb_device *udev, int hop_portnr);
void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr,
u32 slot_id, u32 ep_index, trb_type cmd);
void xhci_acknowledge_event(struct xhci_ctrl *ctrl);
diff --git a/include/usb.h b/include/usb.h
index f2bd76e..fea4cb2 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -566,6 +566,7 @@
struct usb_hub_device {
struct usb_device *pusb_dev;
struct usb_hub_descriptor desc;
+ int hub_depth; /* USB 3.0 hub depth */
};
#ifdef CONFIG_DM_USB
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 608a0ca..273337f 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -262,12 +262,17 @@
/*
* Changes to wPortStatus bit field in USB 3.0
- * See USB 3.0 spec Table 10-11
+ * See USB 3.0 spec Table 10-10
*/
#define USB_SS_PORT_STAT_LINK_STATE 0x01e0
#define USB_SS_PORT_STAT_POWER 0x0200
#define USB_SS_PORT_STAT_SPEED 0x1c00
#define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000
+/* Bits that are the same from USB 2.0 */
+#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \
+ USB_PORT_STAT_ENABLE | \
+ USB_PORT_STAT_OVERCURRENT | \
+ USB_PORT_STAT_RESET)
/* wPortChange bits */
#define USB_PORT_STAT_C_CONNECTION 0x0001
@@ -301,6 +306,9 @@
/* Mask for wIndex in get/set port feature */
#define USB_HUB_PORT_MASK 0xf
+/* Hub class request codes */
+#define USB_REQ_SET_HUB_DEPTH 0x0c
+
/*
* CBI style
*/