From cd695eda33299e50362f1096c46f2f5260c49036 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Mon, 21 Nov 2016 20:14:18 -0800 Subject: [PATCH] google/gru: Power-cycle USB ports in developer/recovery modes Gru only uses USB 2.0 in firmware to avoid all the madness associated with Type-C port orientation and USB 3.0 tuning. We do this by isolating the SuperSpeed lines in the Type-C PHY so it looks like they aren't connected to the device. Unfortunately, some devices seem to already get "locked" into SuperSpeed mode as soon as they detect Rx terminations once, and can never snap out again on their own. Since the terminations are already connected during power-on reset we cannot disable them fast enough to prevent this, and the only solution we found to date is to power-cycle the whole USB port. Now, Gru's USB port power is controlled by the EC, and unfortunately we have no direct host command to control it. We do however have a command to force a certain USB PD "role", and forcing our host into "sink" mode makes it stop sourcing power to the port. So for lack of a saner solution we'll use this to work around our problem. BRANCH=gru BUG=chrome-os-partner:59346 TEST=Booted Kevin in recovery mode, confirmed that my "problem stick" gets detected immediately (whereas previously I had to unplug/replug it). Booted Kevin to OS in both developer and normal mode and confirmed that USB still seems to work. Change-Id: I2db3d6d3710d18a8b8030e94eb1ac2e931f22638 Signed-off-by: Julius Werner Reviewed-on: https://chromium-review.googlesource.com/413031 --- src/mainboard/google/gru/mainboard.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/mainboard/google/gru/mainboard.c b/src/mainboard/google/gru/mainboard.c index 0180329ddb..bb27352686 100644 --- a/src/mainboard/google/gru/mainboard.c +++ b/src/mainboard/google/gru/mainboard.c @@ -15,9 +15,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -229,6 +231,17 @@ static void configure_display(void) gpio_output(GPIO(4, D, 3), 1); /* CPU3_EDP_VDDEN for P3.3V_DISP */ } +static void usb_power_cycle(int port) +{ + if (google_chromeec_set_usb_pd_role(port, USB_PD_CTRL_ROLE_FORCE_SINK)) + printk(BIOS_ERR, "ERROR: Cannot force USB%d PD sink\n", port); + + mdelay(10); /* Make sure USB stick is fully depowered. */ + + if (google_chromeec_set_usb_pd_role(port, USB_PD_CTRL_ROLE_TOGGLE_ON)) + printk(BIOS_ERR, "ERROR: Cannot restore USB%d PD mode\n", port); +} + static void setup_usb(void) { /* A few magic PHY tuning values that improve eye diagram amplitude @@ -268,6 +281,17 @@ static void setup_usb(void) setup_usb_otg0(); setup_usb_otg1(); + + /* + * Need to power-cycle USB ports for use in firmware, since some devices + * can't fall back to USB 2.0 after they saw SuperSpeed terminations. + * This takes about a dozen milliseconds, so only do it in boot modes + * that have firmware UI (which one could select USB boot from). + */ + if (display_init_required()) { + usb_power_cycle(0); + usb_power_cycle(1); + } } static void mainboard_init(device_t dev)