aboutsummaryrefslogtreecommitdiffstats
path: root/payloads
diff options
context:
space:
mode:
Diffstat (limited to 'payloads')
-rw-r--r--payloads/libpayload/Config.in10
-rw-r--r--payloads/libpayload/drivers/usb/ehci.c2
-rw-r--r--payloads/libpayload/drivers/usb/ehci_private.h3
-rw-r--r--payloads/libpayload/drivers/usb/ehci_rh.c27
4 files changed, 34 insertions, 8 deletions
diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in
index 7587b6ac8..8ac96b586 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 aa7ea3b98..578db37a9 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 c9fa6e07d..8519c0f2a 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 6109505c7..da8d8aff8 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;
}