According to the XHCI specification, ERSTBA should be written in Low-High order. The Linux kernel writes the high word first. This results in an initialization failure.
The following information is found in the Linux kernel commit log. [Synopsys]- The host controller was design to support ERST setting during the RUN state. But since there is a limitation in controller in supporting separate ERSTBA_HI and ERSTBA_LO programming, It is supported when the ERSTBA is programmed in 64bit, or in 32 bit mode ERSTBA_HI before ERSTBA_LO [Synopsys]- The internal initialization of event ring fetches the "Event Ring Segment Table Entry" based on the indication of ERSTBA_LO written. Add property to support writing the high word first. Signed-off-by: Guenter Roeck <li...@roeck-us.net> --- hw/usb/hcd-xhci.c | 8 +++++++- hw/usb/hcd-xhci.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 64c3a23b9b..8c0ba569c8 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3107,10 +3107,15 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, } else { intr->erstba_low = val & 0xffffffc0; } + if (xhci->erstba_hi_lo) { + xhci_er_reset(xhci, v); + } break; case 0x14: /* ERSTBA high */ intr->erstba_high = val; - xhci_er_reset(xhci, v); + if (!xhci->erstba_hi_lo) { + xhci_er_reset(xhci, v); + } break; case 0x18: /* ERDP low */ if (val & ERDP_EHB) { @@ -3636,6 +3641,7 @@ static const Property xhci_properties[] = { DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4), DEFINE_PROP_LINK("host", XHCIState, hostOpaque, TYPE_DEVICE, DeviceState *), + DEFINE_PROP_BOOL("erstba-hi-lo", XHCIState, erstba_hi_lo, false), }; static void xhci_class_init(ObjectClass *klass, void *data) diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index 9c3974f148..cf3f074261 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -189,6 +189,7 @@ typedef struct XHCIState { uint32_t numports_3; uint32_t numintrs; uint32_t numslots; + bool erstba_hi_lo; uint32_t flags; uint32_t max_pstreams_mask; void (*intr_update)(XHCIState *s, int n, bool enable); -- 2.45.2