From bd234de11cc79859e348993018c6101df94e519d Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 7 Sep 2018 14:11:20 -0500 Subject: [PATCH] xhci: Turn OpsReg waits into common function Change-Id: I52ada3447b638db07622fa51746e75ce6cce7a46 Reviewed-on: https://review.haiku-os.org/518 Reviewed-by: Alexander von Gluck IV --- src/add-ons/kernel/busses/usb/xhci.cpp | 72 ++++++++++++++++---------- src/add-ons/kernel/busses/usb/xhci.h | 1 + 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp index 6fd0c00e6f..6bc23fda23 100644 --- a/src/add-ons/kernel/busses/usb/xhci.cpp +++ b/src/add-ons/kernel/busses/usb/xhci.cpp @@ -386,6 +386,14 @@ XHCI::Start() TRACE("usbcmd: 0x%08" B_PRIx32 "; usbsts: 0x%08" B_PRIx32 "\n", ReadOpReg(XHCI_CMD), ReadOpReg(XHCI_STS)); + if (WaitOpBits(XHCI_STS, STS_CNR, 0) != B_OK) { + TRACE("Start() failed STS_CNR\n"); + } + + if ((ReadOpReg(XHCI_CMD) & CMD_RUN) != 0) { + TRACE_ERROR("Start() warning, starting running XHCI controller!\n"); + } + if ((ReadOpReg(XHCI_PAGESIZE) & (1 << 0)) == 0) { TRACE_ERROR("Controller does not support 4K page size.\n"); return B_ERROR; @@ -555,13 +563,8 @@ XHCI::Start() WriteOpReg(XHCI_CMD, CMD_RUN | CMD_INTE | CMD_HSEE); // wait for start up state - int32 tries = 100; - while ((ReadOpReg(XHCI_STS) & STS_HCH) != 0) { - snooze(1000); - if (tries-- < 0) { - TRACE_ERROR("start up timeout\n"); - break; - } + if (WaitOpBits(XHCI_STS, STS_HCH, 0) != B_OK) { + TRACE_ERROR("HCH start up timeout\n"); } fRootHubAddress = AllocateAddress(); @@ -1883,15 +1886,14 @@ XHCI::ClearPortFeature(uint8 index, uint16 feature) status_t XHCI::ControllerHalt() { - WriteOpReg(XHCI_CMD, 0); + // Mask off run state + WriteOpReg(XHCI_CMD, ReadOpReg(XHCI_CMD) & ~CMD_RUN); - int32 tries = 100; - while ((ReadOpReg(XHCI_STS) & STS_HCH) == 0) { - snooze(1000); - if (tries-- < 0) - return B_ERROR; + // wait for shutdown state + if (WaitOpBits(XHCI_STS, STS_HCH, STS_HCH) != B_OK) { + TRACE_ERROR("HCH shutdown timeout\n"); + return B_ERROR; } - return B_OK; } @@ -1903,22 +1905,14 @@ XHCI::ControllerReset() ReadOpReg(XHCI_CMD), ReadOpReg(XHCI_STS)); WriteOpReg(XHCI_CMD, ReadOpReg(XHCI_CMD) | CMD_HCRST); - int32 tries = 250; - while (ReadOpReg(XHCI_CMD) & CMD_HCRST) { - snooze(1000); - if (tries-- < 0) { - TRACE("ControllerReset() failed CMD_HCRST\n"); - return B_ERROR; - } + if (WaitOpBits(XHCI_CMD, CMD_HCRST, 0) != B_OK) { + TRACE_ERROR("ControllerReset() failed CMD_HCRST\n"); + return B_ERROR; } - tries = 250; - while (ReadOpReg(XHCI_STS) & STS_CNR) { - snooze(1000); - if (tries-- < 0) { - TRACE("ControllerReset() failed STS_CNR\n"); - return B_ERROR; - } + if (WaitOpBits(XHCI_STS, STS_CNR, 0) != B_OK) { + TRACE_ERROR("ControllerReset() failed STS_CNR\n"); + return B_ERROR; } return B_OK; @@ -2477,6 +2471,28 @@ XHCI::ReadOpReg(uint32 reg) } +inline status_t +XHCI::WaitOpBits(uint32 reg, uint32 mask, uint32 expected) +{ + int loops = 0; + uint32 value = ReadOpReg(reg); + while ((value & mask) != expected) { + snooze(1000); + value = ReadOpReg(reg); + if (loops == 25) { + TRACE("delay waiting on reg 0x%x match 0x%x (0x%x)\n", + reg, expected, mask); + } else if (loops > 100) { + TRACE_ERROR("timeout waiting on reg 0x%x match 0x%x (0x%x)\n", + reg, expected, mask); + return B_ERROR; + } + loops++; + } + return B_OK; +} + + inline uint32 XHCI::ReadCapReg32(uint32 reg) { diff --git a/src/add-ons/kernel/busses/usb/xhci.h b/src/add-ons/kernel/busses/usb/xhci.h index cea95cee91..0dc5878322 100644 --- a/src/add-ons/kernel/busses/usb/xhci.h +++ b/src/add-ons/kernel/busses/usb/xhci.h @@ -184,6 +184,7 @@ private: // Operational register functions inline void WriteOpReg(uint32 reg, uint32 value); inline uint32 ReadOpReg(uint32 reg); + inline status_t WaitOpBits(uint32 reg, uint32 mask, uint32 expected); // Capability register functions inline uint32 ReadCapReg32(uint32 reg);