diff options
author | John Zhao <john.zhao@intel.com> | 2018-07-30 13:54:25 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2018-08-20 15:50:27 +0000 |
commit | 7dff726b78a7f53f9670611d6b3cf6a40cde5515 (patch) | |
tree | b9b5d46a3c63c5a6a8830253d80a0b15d82a0ffa | |
parent | 5251ff7204e2753a005f676ce122c738f66622d5 (diff) |
soc/intel/apollolake: Force USB-C into host mode
When USB OTG is set, GLK FSP enables xHCI SW ID pin and configures
USB-C as device mode. Force USB-C into host mode.
BUG=b:111623911
TEST=Verified that USB-C being host mode once USB OTG is set.
Change-Id: Iaca3d25a1159f922b743963cbc508d8defa7b6ff
Signed-off-by: John Zhao <john.zhao@intel.com>
Reviewed-on: https://review.coreboot.org/27746
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
-rw-r--r-- | src/soc/intel/apollolake/chip.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index 081bba373e..83a6baa5f5 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -49,9 +49,19 @@ #include <soc/cpu.h> #include <soc/pm.h> #include <soc/systemagent.h> +#include <timer.h> #include "chip.h" +#define DUAL_ROLE_CFG0 0x80d8 +#define SW_VBUS_VALID_MASK (1 << 24) +#define SW_IDPIN_EN_MASK (1 << 21) +#define SW_IDPIN_MASK (1 << 20) +#define SW_IDPIN_HOST (0 << 20) +#define DUAL_ROLE_CFG1 0x80dc +#define DRD_MODE_MASK (1 << 29) +#define DRD_MODE_HOST (1 << 29) + const char *soc_acpi_name(const struct device *dev) { if (dev->path.type == DEVICE_PATH_DOMAIN) @@ -654,6 +664,46 @@ static void drop_privilege_all(void) printk(BIOS_ERR, "failed to enable untrusted mode\n"); } +static void configure_xhci_host_mode_port0(void) +{ + uint32_t *cfg0; + uint32_t *cfg1; + const struct resource *res; + uint32_t reg; + struct stopwatch sw; + struct device *xhci_dev = PCH_DEV_XHCI; + + printk(BIOS_INFO, "Putting xHCI port 0 into host mode.\n"); + res = find_resource(xhci_dev, PCI_BASE_ADDRESS_0); + cfg0 = (void *)(uintptr_t)(res->base + DUAL_ROLE_CFG0); + cfg1 = (void *)(uintptr_t)(res->base + DUAL_ROLE_CFG1); + reg = read32(cfg0); + if (!(reg && SW_IDPIN_EN_MASK)) + return; + + reg &= ~(SW_IDPIN_MASK | SW_VBUS_VALID_MASK); + write32(cfg0, reg); + + stopwatch_init_msecs_expire(&sw, 10); + /* Wait for the host mode status bit. */ + while ((read32(cfg1) & DRD_MODE_MASK) != DRD_MODE_HOST) { + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "Timed out waiting for host mode.\n"); + return; + } + } + + printk(BIOS_INFO, "xHCI port 0 host switch over took %lu ms\n", + stopwatch_duration_msecs(&sw)); +} + +static int check_xdci_enable(void) +{ + struct device *dev = PCH_DEV_XDCI; + + return !!dev->enabled; +} + void platform_fsp_notify_status(enum fsp_notify_phase phase) { if (phase == END_OF_FIRMWARE) { @@ -666,6 +716,13 @@ void platform_fsp_notify_status(enum fsp_notify_phase phase) * security. */ drop_privilege_all(); + + /* + * When USB OTG is set, GLK FSP enables xHCI SW ID pin and + * configures USB-C as device mode. Force USB-C into host mode. + */ + if (check_xdci_enable()) + configure_xhci_host_mode_port0(); } } |