summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2012-05-21 14:56:21 +0200
committerPatrick Georgi <patrick@georgi-clan.de>2012-06-01 12:22:08 +0200
commit5c4e7aa9e5914293877ef98e007d46732666cfaf (patch)
treed583e5d510fdc4f341521adcf0362138cb6c50dd
parent5f595cb6ebd8edddb1e253353753bf1c5433395e (diff)
libpayload: Correct port power settings for EHCI root hub
Enable power on EHCI root hub ports only if the controller supports it. Wait 20ms for the power to become stable. Change-Id: I8897756ed2bfcb88408fe5e9f9e3f8af5dd900ac Signed-off-by: Nico Huber <nico.huber@secunet.com> Reviewed-on: http://review.coreboot.org/1078 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
-rw-r--r--payloads/libpayload/drivers/usb/ehci_private.h1
-rw-r--r--payloads/libpayload/drivers/usb/ehci_rh.c13
2 files changed, 13 insertions, 1 deletions
diff --git a/payloads/libpayload/drivers/usb/ehci_private.h b/payloads/libpayload/drivers/usb/ehci_private.h
index 6fa5f0344d..8ac15b3093 100644
--- a/payloads/libpayload/drivers/usb/ehci_private.h
+++ b/payloads/libpayload/drivers/usb/ehci_private.h
@@ -49,6 +49,7 @@ typedef volatile u32 portsc_t;
typedef volatile struct {
#define HCS_NPORTS_MASK 0xf
+#define HCS_PORT_POWER_CONTROL 0x10
u8 caplength;
u8 res1;
u16 hciversion;
diff --git a/payloads/libpayload/drivers/usb/ehci_rh.c b/payloads/libpayload/drivers/usb/ehci_rh.c
index dd073a3b99..d84069e613 100644
--- a/payloads/libpayload/drivers/usb/ehci_rh.c
+++ b/payloads/libpayload/drivers/usb/ehci_rh.c
@@ -137,10 +137,21 @@ ehci_rh_init (usbdev_t *dev)
debug("root hub has %x ports\n", RH_INST(dev)->n_ports);
+ /* If the host controller has port power control, enable power on
+ * all ports and wait 20ms.
+ */
+ if (EHCI_INST(dev->controller)->capabilities->hcsparams
+ & HCS_PORT_POWER_CONTROL) {
+ debug("host controller has port power control, "
+ "giving power to all ports.\n");
+ for (i=0; i < RH_INST(dev)->n_ports; i++)
+ RH_INST(dev)->ports[i] |= P_PP;
+ }
+ mdelay(20); // ehci spec 2.3.9
+
RH_INST(dev)->devices = malloc(RH_INST(dev)->n_ports * sizeof(int));
for (i=0; i < RH_INST(dev)->n_ports; i++) {
RH_INST(dev)->devices[i] = -1;
- RH_INST(dev)->ports[i] |= P_PP;
ehci_rh_scanport(dev, i);
}