summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/usb.c98
-rw-r--r--drivers/usb/host/dwc2.c7
-rw-r--r--drivers/usb/host/ehci-hcd.c50
-rw-r--r--drivers/usb/musb-new/musb_host.c10
-rw-r--r--drivers/usb/musb-new/usb-compat.h53
-rw-r--r--include/usb.h17
6 files changed, 115 insertions, 120 deletions
diff --git a/common/usb.c b/common/usb.c
index 700bfc315b..9f67cc1e8e 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -566,13 +566,12 @@ static int usb_get_descriptor(struct usb_device *dev, unsigned char type,
}
/**********************************************************************
- * gets configuration cfgno and store it in the buffer
+ * gets len of configuration cfgno
*/
-int usb_get_configuration_no(struct usb_device *dev,
- unsigned char *buffer, int cfgno)
+int usb_get_configuration_len(struct usb_device *dev, int cfgno)
{
int result;
- unsigned int length;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9);
struct usb_config_descriptor *config;
config = (struct usb_config_descriptor *)&buffer[0];
@@ -586,17 +585,23 @@ int usb_get_configuration_no(struct usb_device *dev,
"(expected %i, got %i)\n", 9, result);
return -EIO;
}
- length = le16_to_cpu(config->wTotalLength);
+ return le16_to_cpu(config->wTotalLength);
+}
- if (length > USB_BUFSIZ) {
- printf("%s: failed to get descriptor - too long: %d\n",
- __func__, length);
- return -EIO;
- }
+/**********************************************************************
+ * gets configuration cfgno and store it in the buffer
+ */
+int usb_get_configuration_no(struct usb_device *dev, int cfgno,
+ unsigned char *buffer, int length)
+{
+ int result;
+ struct usb_config_descriptor *config;
+ config = (struct usb_config_descriptor *)&buffer[0];
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
- debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, length);
- config->wTotalLength = length; /* validated, with CPU byte order */
+ debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result,
+ le16_to_cpu(config->wTotalLength));
+ config->wTotalLength = result; /* validated, with CPU byte order */
return result;
}
@@ -1070,7 +1075,7 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
int usb_select_config(struct usb_device *dev)
{
- ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
+ unsigned char *tmpbuf = 0;
int err;
err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
@@ -1084,14 +1089,23 @@ int usb_select_config(struct usb_device *dev)
le16_to_cpus(&dev->descriptor.bcdDevice);
/* only support for one config for now */
- err = usb_get_configuration_no(dev, tmpbuf, 0);
+ err = usb_get_configuration_len(dev, 0);
+ if (err >= 0) {
+ tmpbuf = (unsigned char *)malloc_cache_aligned(err);
+ if (!tmpbuf)
+ err = -ENOMEM;
+ else
+ err = usb_get_configuration_no(dev, 0, tmpbuf, err);
+ }
if (err < 0) {
printf("usb_new_device: Cannot read configuration, " \
"skipping device %04x:%04x\n",
dev->descriptor.idVendor, dev->descriptor.idProduct);
+ free(tmpbuf);
return err;
}
usb_parse_config(dev, tmpbuf, 0);
+ free(tmpbuf);
usb_set_maxpacket(dev);
/*
* we set the default configuration here
@@ -1200,4 +1214,60 @@ bool usb_device_has_child_on_port(struct usb_device *parent, int port)
#endif
}
+#ifdef CONFIG_DM_USB
+void usb_find_usb2_hub_address_port(struct usb_device *udev,
+ uint8_t *hub_address, uint8_t *hub_port)
+{
+ struct udevice *parent;
+ struct usb_device *uparent, *ttdev;
+
+ /*
+ * When called from usb-uclass.c: usb_scan_device() udev->dev points
+ * to the parent udevice, not the actual udevice belonging to the
+ * udev as the device is not instantiated yet. So when searching
+ * for the first usb-2 parent start with udev->dev not
+ * udev->dev->parent .
+ */
+ ttdev = udev;
+ parent = udev->dev;
+ uparent = dev_get_parent_priv(parent);
+
+ while (uparent->speed != USB_SPEED_HIGH) {
+ struct udevice *dev = parent;
+
+ if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
+ printf("Error: Cannot find high speed parent of usb-1 device\n");
+ *hub_address = 0;
+ *hub_port = 0;
+ return;
+ }
+
+ ttdev = dev_get_parent_priv(dev);
+ parent = dev->parent;
+ uparent = dev_get_parent_priv(parent);
+ }
+ *hub_address = uparent->devnum;
+ *hub_port = ttdev->portnr;
+}
+#else
+void usb_find_usb2_hub_address_port(struct usb_device *udev,
+ uint8_t *hub_address, uint8_t *hub_port)
+{
+ /* Find out the nearest parent which is high speed */
+ while (udev->parent->parent != NULL)
+ if (udev->parent->speed != USB_SPEED_HIGH) {
+ udev = udev->parent;
+ } else {
+ *hub_address = udev->parent->devnum;
+ *hub_port = udev->portnr;
+ return;
+ }
+
+ printf("Error: Cannot find high speed parent of usb-1 device\n");
+ *hub_address = 0;
+ *hub_port = 0;
+}
+#endif
+
+
/* EOF */
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 541c0f9687..5ef6debd9a 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -823,12 +823,13 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev,
(*pid << DWC2_HCTSIZ_PID_OFFSET),
&hc_regs->hctsiz);
- if (!in) {
- memcpy(priv->aligned_buffer, (char *)buffer + done, len);
+ if (!in && xfer_len) {
+ memcpy(priv->aligned_buffer, (char *)buffer + done,
+ xfer_len);
flush_dcache_range((unsigned long)priv->aligned_buffer,
(unsigned long)((void *)priv->aligned_buffer +
- roundup(len, ARCH_DMA_MINALIGN)));
+ roundup(xfer_len, ARCH_DMA_MINALIGN)));
}
writel(phys_to_bus((unsigned long)priv->aligned_buffer),
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c85dbcecfa..c664b1629e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -279,56 +279,16 @@ static inline u8 ehci_encode_speed(enum usb_device_speed speed)
static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
struct QH *qh)
{
- struct usb_device *ttdev;
- int parent_devnum;
+ uint8_t portnr = 0;
+ uint8_t hubaddr = 0;
if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL)
return;
- /*
- * For full / low speed devices we need to get the devnum and portnr of
- * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs
- * in the tree before that one!
- */
-#ifdef CONFIG_DM_USB
- /*
- * When called from usb-uclass.c: usb_scan_device() udev->dev points
- * to the parent udevice, not the actual udevice belonging to the
- * udev as the device is not instantiated yet. So when searching
- * for the first usb-2 parent start with udev->dev not
- * udev->dev->parent .
- */
- struct udevice *parent;
- struct usb_device *uparent;
-
- ttdev = udev;
- parent = udev->dev;
- uparent = dev_get_parent_priv(parent);
-
- while (uparent->speed != USB_SPEED_HIGH) {
- struct udevice *dev = parent;
-
- if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
- printf("ehci: Error cannot find high-speed parent of usb-1 device\n");
- return;
- }
-
- ttdev = dev_get_parent_priv(dev);
- parent = dev->parent;
- uparent = dev_get_parent_priv(parent);
- }
- parent_devnum = uparent->devnum;
-#else
- ttdev = udev;
- while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH)
- ttdev = ttdev->parent;
- if (!ttdev->parent)
- return;
- parent_devnum = ttdev->parent->devnum;
-#endif
+ usb_find_usb2_hub_address_port(udev, &hubaddr, &portnr);
- qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) |
- QH_ENDPT2_HUBADDR(parent_devnum));
+ qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(portnr) |
+ QH_ENDPT2_HUBADDR(hubaddr));
}
static int
diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c
index 40b9c66af8..2515447308 100644
--- a/drivers/usb/musb-new/musb_host.c
+++ b/drivers/usb/musb-new/musb_host.c
@@ -2092,9 +2092,13 @@ int musb_urb_enqueue(
}
#else
if (tt_needed(musb, urb->dev)) {
- u16 hub_port = find_tt(urb->dev);
- qh->h_addr_reg = (u8) (hub_port >> 8);
- qh->h_port_reg = (u8) (hub_port & 0xff);
+ uint8_t portnr = 0;
+ uint8_t hubaddr = 0;
+ usb_find_usb2_hub_address_port(urb->dev,
+ &hubaddr,
+ &portnr);
+ qh->h_addr_reg = hubaddr;
+ qh->h_port_reg = portnr;
}
#endif
}
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
index 1c41e2aade..760bd787bc 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -68,38 +68,6 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
}
#ifdef CONFIG_DM_USB
-static inline u16 find_tt(struct usb_device *udev)
-{
- struct udevice *parent;
- struct usb_device *uparent, *ttdev;
-
- /*
- * When called from usb-uclass.c: usb_scan_device() udev->dev points
- * to the parent udevice, not the actual udevice belonging to the
- * udev as the device is not instantiated yet. So when searching
- * for the first usb-2 parent start with udev->dev not
- * udev->dev->parent .
- */
- ttdev = udev;
- parent = udev->dev;
- uparent = dev_get_parent_priv(parent);
-
- while (uparent->speed != USB_SPEED_HIGH) {
- struct udevice *dev = parent;
-
- if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
- printf("musb: Error cannot find high speed parent of usb-1 device\n");
- return 0;
- }
-
- ttdev = dev_get_parent_priv(dev);
- parent = dev->parent;
- uparent = dev_get_parent_priv(parent);
- }
-
- return (uparent->devnum << 8) | (ttdev->portnr - 1);
-}
-
static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
{
struct udevice *parent = udev->dev->parent;
@@ -129,27 +97,6 @@ static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
return NULL;
}
#else
-static inline u16 find_tt(struct usb_device *dev)
-{
- u8 chid;
- u8 hub;
-
- /* Find out the nearest parent which is high speed */
- while (dev->parent->parent != NULL)
- if (dev->parent->speed != USB_SPEED_HIGH)
- dev = dev->parent;
- else
- break;
-
- /* determine the port address at that hub */
- hub = dev->parent->devnum;
- for (chid = 0; chid < USB_MAXCHILDREN; chid++)
- if (dev->parent->children[chid] == dev)
- break;
-
- return (hub << 8) | chid;
-}
-
static inline struct usb_device *usb_dev_get_parent(struct usb_device *dev)
{
return dev->parent;
diff --git a/include/usb.h b/include/usb.h
index 55b9268ea1..2539364565 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -266,8 +266,9 @@ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int transfer_len, int interval);
int usb_disable_asynch(int disable);
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
-int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer,
- int cfgno);
+int usb_get_configuration_no(struct usb_device *dev, int cfgno,
+ unsigned char *buffer, int length);
+int usb_get_configuration_len(struct usb_device *dev, int cfgno);
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
unsigned char id, void *buf, int size);
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
@@ -874,6 +875,18 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,
int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat);
+/*
+ * usb_find_usb2_hub_address_port() - Get hub address and port for TT setting
+ *
+ * Searches for the first HS hub above the given device. If a
+ * HS hub is found, the hub address and the port the device is
+ * connected to is return, as required for SPLIT transactions
+ *
+ * @param: udev full speed or low speed device
+ */
+void usb_find_usb2_hub_address_port(struct usb_device *udev,
+ uint8_t *hub_address, uint8_t *hub_port);
+
/**
* usb_alloc_new_device() - Allocate a new device
*