summaryrefslogtreecommitdiff
path: root/payloads/libpayload/drivers
diff options
context:
space:
mode:
authorJim Lin <jilin@nvidia.com>2014-09-26 19:12:41 +0800
committerPatrick Georgi <pgeorgi@google.com>2015-03-23 17:57:40 +0100
commit654cf9c2d812dbb614e37db41b22f186553ced81 (patch)
treed63fb61584404f8ea70c513bcd80f80dc52cd9c1 /payloads/libpayload/drivers
parent052b7fec0712bb0e1332cd6ff6d42e9243ce40b5 (diff)
libpayload: EHCI: Support root-hub TT feature
If EHCI controller has TT (Transaction Translator) support in root-hub, then we need to keep control over this controller when USB keyboard (low-speed device) is connected to root-hub port. Need to add "CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT=y" to config file (e.g. payloads/libpayload/configs/config.nyan_big) to support this feature. BUG=chrome-os-partner:32355 TEST=Tested on nyan_big platform. Press ESC+REFRESH+POWER keys on internal keyboard to power up. Press Left Arrow or Right Arrow on USB keyboard to switch between "English" and "Default Locale" in coreboot UI. Or unplug and plug in device and try again. Root hub <- low-speed USB keyboard Root hub <- full-speed hub <- low-speed USB keyboard Root hub <- high-speed hub <- low-speed USB keyboard Change-Id: Iaa2823f64c8769fc808ee7a316c378f18f004e63 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 4ad57fd673d6dc8814fe99a4ac420566bb17e77b Original-Change-Id: Id86a289bc587653b85227c1d50f7a4f476f37983 Original-Signed-off-by: Jim Lin <jilin@nvidia.com> Original-Reviewed-on: https://chromium-review.googlesource.com/220125 Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: http://review.coreboot.org/8737 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'payloads/libpayload/drivers')
-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
3 files changed, 24 insertions, 8 deletions
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;
}