diff options
Diffstat (limited to 'payloads/libpayload')
-rw-r--r-- | payloads/libpayload/Config.in | 10 | ||||
-rw-r--r-- | payloads/libpayload/drivers/usb/ehci.c | 2 | ||||
-rw-r--r-- | payloads/libpayload/drivers/usb/ehci_private.h | 3 | ||||
-rw-r--r-- | payloads/libpayload/drivers/usb/ehci_rh.c | 27 |
4 files changed, 34 insertions, 8 deletions
diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in index 7587b6ac8b..8ac96b5865 100644 --- a/payloads/libpayload/Config.in +++ b/payloads/libpayload/Config.in @@ -488,6 +488,16 @@ config USB_HUB Select this option if you want to compile in support for USB hubs. Say Y here unless you know exactly what you are doing. +config USB_EHCI_HOSTPC_ROOT_HUB_TT + bool "Support for USB EHCI ROOT HUB that has TT" + depends on USB_EHCI + default n + help + Select this option if USB EHCI root hub supports TT (Transaction + Translator). + To support this TT feature we read port-speed from non-standard + register HOSTPC (offset 84h of Operational Register base). + config USB_MSC bool "Support for USB storage" depends on USB diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c index aa7ea3b980..578db37a90 100644 --- a/payloads/libpayload/drivers/usb/ehci.c +++ b/payloads/libpayload/drivers/usb/ehci.c @@ -203,7 +203,7 @@ static int closest_usb2_hub(const usbdev_t *dev, int *const addr, int *const por const usbdev_t *usb1dev; do { usb1dev = dev; - if ((dev->hub > 0) && (dev->hub < 128)) + if ((dev->hub >= 0) && (dev->hub < 128)) dev = dev->controller->devices[dev->hub]; else dev = NULL; diff --git a/payloads/libpayload/drivers/usb/ehci_private.h b/payloads/libpayload/drivers/usb/ehci_private.h index c9fa6e07da..8519c0f2af 100644 --- a/payloads/libpayload/drivers/usb/ehci_private.h +++ b/payloads/libpayload/drivers/usb/ehci_private.h @@ -80,6 +80,9 @@ typedef volatile struct { u8 res1[0x40-0x1c]; u32 configflag; portsc_t portsc[0]; + u8 res2[0x40]; + u32 hostpc; + /* hostpc register is used for CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT */ } __attribute__ ((packed)) hc_op_t; typedef volatile struct { diff --git a/payloads/libpayload/drivers/usb/ehci_rh.c b/payloads/libpayload/drivers/usb/ehci_rh.c index 6109505c7f..da8d8aff8b 100644 --- a/payloads/libpayload/drivers/usb/ehci_rh.c +++ b/payloads/libpayload/drivers/usb/ehci_rh.c @@ -30,6 +30,7 @@ //#define USB_DEBUG #include <libpayload.h> +#include <kconfig.h> #include "ehci.h" #include "ehci_private.h" @@ -91,6 +92,8 @@ ehci_rh_hand_over_port (usbdev_t *dev, int port) static void ehci_rh_scanport (usbdev_t *dev, int port) { + usb_speed port_speed; + if (RH_INST(dev)->devices[port]!=-1) { usb_debug("Unregister device at port %x\n", port+1); usb_detach_device(dev->controller, RH_INST(dev)->devices[port]); @@ -99,7 +102,9 @@ ehci_rh_scanport (usbdev_t *dev, int port) /* device connected, handle */ if (RH_INST(dev)->ports[port] & P_CURR_CONN_STATUS) { mdelay(100); // usb20 spec 9.1.2 - if ((RH_INST(dev)->ports[port] & P_LINE_STATUS) == P_LINE_STATUS_LOWSPEED) { + if (!IS_ENABLED(CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT) && + (RH_INST(dev)->ports[port] & P_LINE_STATUS) == + P_LINE_STATUS_LOWSPEED) { ehci_rh_hand_over_port(dev, port); return; } @@ -133,8 +138,16 @@ ehci_rh_scanport (usbdev_t *dev, int port) ehci_rh_hand_over_port(dev, port); return; } - usb_debug("port %x hosts a USB2 device\n", port+1); - RH_INST(dev)->devices[port] = usb_attach_device(dev->controller, dev->address, port, 2); + if (IS_ENABLED(CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT)) { + port_speed = (usb_speed) + ((EHCI_INST(dev->controller)->operation->hostpc + >> 25) & 0x03); + } else { + usb_debug("port %x hosts a USB2 device\n", port+1); + port_speed = HIGH_SPEED; + } + RH_INST(dev)->devices[port] = usb_attach_device(dev->controller + , dev->address, port, port_speed); } /* RW/C register, so clear it by writing 1 */ RH_INST(dev)->ports[port] |= P_CONN_STATUS_CHANGE; @@ -186,12 +199,12 @@ ehci_rh_init (usbdev_t *dev) } mdelay(20); // ehci spec 2.3.9 + dev->speed = HIGH_SPEED; + dev->address = 0; + dev->hub = -1; + dev->port = -1; for (i=0; i < RH_INST(dev)->n_ports; i++) { RH_INST(dev)->devices[i] = -1; ehci_rh_scanport(dev, i); } - - dev->address = 0; - dev->hub = -1; - dev->port = -1; } |