libpayload: xhci: Add delay to get reset working more reliably

Existing Intel xHCI controllers require a delay of 1 ms,
after setting the CMD_RESET bit in command register, before
accessing any HC registers. This allows the HC to complete
the reset operation and be ready for HC register access.
Without this delay, the subsequent HC register access,
may result in a system hang, very rarely.

Verified CherryView / Braswell platforms go through over
1000 warm reboot cycles (which was not possible without
this patch), without any xHCI reset hang in depthcharge.

BRANCH=None
BUG=None
TEST=Verified CherryView / Braswell platforms go through
over 1000 warm reboot cycles, without any xHCI reset hang
in depthcharge.

Change-Id: I8eff5115ca52738bdcf8bc65fbfb2a5f60a0abe1
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 3e7ea70df36e3bf35a6ee1297640900ee76bfdac
Original-Change-Id: Id681a19d0eedb0e2c29e259c5467bcde577e3460
Original-Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/310022
Original-Reviewed-by: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-on: http://review.coreboot.org/12325
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Tested-by: build bot (Jenkins)
Reviewed-by: Nico Huber <nico.h@gmx.de>
This commit is contained in:
Rajmohan Mani 2015-10-30 17:00:24 -07:00 committed by Patrick Georgi
parent 77d37d21db
commit 1528ffa57c
1 changed files with 11 additions and 0 deletions

View File

@ -328,6 +328,17 @@ xhci_reset(hci_t *const controller)
xhci_stop(controller); xhci_stop(controller);
xhci->opreg->usbcmd |= USBCMD_HCRST; xhci->opreg->usbcmd |= USBCMD_HCRST;
/* Existing Intel xHCI controllers require a delay of 1 ms,
* after setting the CMD_RESET bit, and before accessing any
* HC registers. This allows the HC to complete the
* reset operation and be ready for HC register access.
* Without this delay, the subsequent HC register access,
* may result in a system hang very rarely.
*/
if (IS_ENABLED(CONFIG_LP_ARCH_X86))
mdelay(1);
xhci_debug("Resetting controller... "); xhci_debug("Resetting controller... ");
if (!xhci_handshake(&xhci->opreg->usbcmd, USBCMD_HCRST, 0, 1000000L)) if (!xhci_handshake(&xhci->opreg->usbcmd, USBCMD_HCRST, 0, 1000000L))
usb_debug("timeout!\n"); usb_debug("timeout!\n");