XHCI hardware fixes, ordering of writes, send noop to test
This commit is contained in:
@@ -180,6 +180,7 @@ static void xhci_irq (void* arg, void* regs, bool user, struct reschedule_ctx* r
|
||||
|
||||
/* ack */
|
||||
xhci_write32 (ir_base, XHCI_IMAN, xhci_read32 (ir_base, XHCI_IMAN) | (1 << 0));
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_USBSTS, (1 << 3));
|
||||
|
||||
xhci_poll_events (xhci);
|
||||
|
||||
@@ -214,9 +215,16 @@ void xhci_send_cmd (struct xhci* xhci, uint64_t param, uint32_t status, uint32_t
|
||||
xhci_write32 (xhci->xhci_doorbell_base, 0, 0);
|
||||
|
||||
spin_unlock (&xhci->device->lock, fd);
|
||||
while (atomic_load (&xhci->pending))
|
||||
spin_lock_relax ();
|
||||
|
||||
int timeout = 100;
|
||||
|
||||
while (atomic_load (&xhci->pending) && --timeout > 0)
|
||||
stall_ms (1);
|
||||
|
||||
spin_lock (&xhci->device->lock, &fd);
|
||||
|
||||
if (timeout == 0)
|
||||
DEBUG ("timed out\n");
|
||||
} else {
|
||||
while (atomic_load (&xhci->pending)) {
|
||||
xhci_poll_events (xhci);
|
||||
@@ -227,6 +235,7 @@ void xhci_send_cmd (struct xhci* xhci, uint64_t param, uint32_t status, uint32_t
|
||||
spin_unlock (&xhci->device->lock, fd);
|
||||
}
|
||||
|
||||
/* Make or break on real hardware. We need to take over ownership from the BIOS. */
|
||||
static void xhci_bios_handover (struct xhci* xhci) {
|
||||
uint32_t hccparams1 = xhci_read32 (xhci->xhci_mmio_base, XHCI_HCCPARAMS1);
|
||||
uint32_t ext_offset = (hccparams1 >> 16) << 2;
|
||||
@@ -246,18 +255,17 @@ static void xhci_bios_handover (struct xhci* xhci) {
|
||||
|
||||
xhci_write8 (cap_ptr, 3, 1);
|
||||
|
||||
/* Wait for BIOS Semaphore owned bit to be cleared */
|
||||
int timeout = 1000;
|
||||
while (timeout--) {
|
||||
while (--timeout > 0) {
|
||||
uint32_t val = xhci_read32 (cap_ptr, 0);
|
||||
if (!(val & (1 << 16)) && (val & (1 << 24)))
|
||||
break;
|
||||
stall_ms (1);
|
||||
|
||||
stall_ms (100);
|
||||
}
|
||||
|
||||
if (timeout <= 0)
|
||||
DEBUG ("Warning: XHCI BIOS handover timed out!\n");
|
||||
else
|
||||
DEBUG ("XHCI Handover successful.\n");
|
||||
DEBUG ("XHCI Handover OK\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -265,6 +273,7 @@ static void xhci_bios_handover (struct xhci* xhci) {
|
||||
uint8_t next = (cap >> 8) & 0xFF;
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
ext_offset += (next << 2);
|
||||
}
|
||||
}
|
||||
@@ -318,7 +327,8 @@ DEFINE_DEVICE_INIT (xhci_init) {
|
||||
usbcmd |= (1 << 1);
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_USBCMD, usbcmd);
|
||||
|
||||
stall_ms (1000);
|
||||
while (xhci_read32 (xhci->xhci_oper_base, XHCI_USBSTS) & (1 << 11))
|
||||
spin_lock_relax ();
|
||||
|
||||
DEBUG ("controller reset\n");
|
||||
|
||||
@@ -349,10 +359,10 @@ DEFINE_DEVICE_INIT (xhci_init) {
|
||||
xhci->xhci_dcbaa[0] = xhci->scratchpads_phys;
|
||||
}
|
||||
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_DCBAAP + 4, (uint32_t)(xhci->xhci_dcbaa_phys >> 32));
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_DCBAAP, (uint32_t)xhci->xhci_dcbaa_phys);
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_DCBAAP + 4, (uint32_t)(xhci->xhci_dcbaa_phys >> 32));
|
||||
|
||||
xhci->cmd_ring_phys = pmm_alloc_aligned (1, 64);
|
||||
xhci->cmd_ring_phys = pmm_alloc (1);
|
||||
xhci->cmd_ring = (struct xhci_trb*)(xhci->cmd_ring_phys + (uintptr_t)hhdm->offset);
|
||||
memset (xhci->cmd_ring, 0, PAGE_SIZE);
|
||||
xhci->cmd_ring_size = PAGE_SIZE / sizeof (struct xhci_trb);
|
||||
@@ -360,17 +370,17 @@ DEFINE_DEVICE_INIT (xhci_init) {
|
||||
xhci->cmd_cycle_bit = 1;
|
||||
|
||||
uint64_t crcr = xhci->cmd_ring_phys | xhci->cmd_cycle_bit;
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_CRCR + 4, (uint32_t)(crcr >> 32));
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_CRCR, (uint32_t)crcr);
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_CRCR + 4, (uint32_t)(crcr >> 32));
|
||||
|
||||
xhci->event_ring_phys = pmm_alloc_aligned (1, 64);
|
||||
xhci->event_ring_phys = pmm_alloc (1);
|
||||
xhci->event_ring = (struct xhci_trb*)(xhci->event_ring_phys + (uintptr_t)hhdm->offset);
|
||||
memset (xhci->event_ring, 0, PAGE_SIZE);
|
||||
xhci->event_ring_size = PAGE_SIZE / sizeof (struct xhci_trb);
|
||||
xhci->event_ring_idx = 0;
|
||||
xhci->event_cycle_bit = 1;
|
||||
|
||||
xhci->erst_phys = pmm_alloc_aligned (1, 64);
|
||||
xhci->erst_phys = pmm_alloc (1);
|
||||
xhci->erst = (struct xhci_erst_entry*)(xhci->erst_phys + (uintptr_t)hhdm->offset);
|
||||
memset (xhci->erst, 0, PAGE_SIZE);
|
||||
xhci->erst[0].ptr = xhci->event_ring_phys;
|
||||
@@ -382,8 +392,8 @@ DEFINE_DEVICE_INIT (xhci_init) {
|
||||
xhci_write32 (ir_base, XHCI_ERSTBA, (uint32_t)xhci->erst_phys);
|
||||
xhci_write32 (ir_base, XHCI_ERSTBA + 4, (uint32_t)(xhci->erst_phys >> 32));
|
||||
|
||||
xhci_write32 (ir_base, XHCI_ERDP + 4, (uint32_t)(xhci->event_ring_phys >> 32));
|
||||
xhci_write32 (ir_base, XHCI_ERDP, (uint32_t)xhci->event_ring_phys | (1 << 3));
|
||||
xhci_write32 (ir_base, XHCI_ERDP + 4, (uint32_t)(xhci->event_ring_phys >> 32));
|
||||
|
||||
if (xhci->irqs_support) {
|
||||
/* enable interrupter */
|
||||
@@ -394,11 +404,10 @@ DEFINE_DEVICE_INIT (xhci_init) {
|
||||
usbcmd = xhci_read32 (xhci->xhci_oper_base, XHCI_USBCMD);
|
||||
xhci_write32 (xhci->xhci_oper_base, XHCI_USBCMD, usbcmd | (1 << 0) | (1 << 2));
|
||||
|
||||
while (xhci_read32 (xhci->xhci_oper_base, XHCI_USBSTS) & (1 << 11))
|
||||
spin_lock_relax ();
|
||||
|
||||
xhci_send_cmd (xhci, 0, 0, XHCI_TRB_SLOT_ENAB_CMD << 10);
|
||||
|
||||
xhci_send_cmd (xhci, 0, 0, XHCI_TRB_NOOP_CMD << 10);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user