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>
This commit is contained in:
Jim Lin 2014-09-26 19:12:41 +08:00 committed by Patrick Georgi
parent 052b7fec07
commit 654cf9c2d8
4 changed files with 34 additions and 8 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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;
}