Commit 8e595a5d authored by Sarah Sharp's avatar Sarah Sharp Committed by Greg Kroah-Hartman

USB: xhci: Represent 64-bit addresses with one u64.

There are several xHCI data structures that use two 32-bit fields to
represent a 64-bit address.  Since some architectures don't support 64-bit
PCI writes, the fields need to be written in two 32-bit writes.  The xHCI
specification says that if a platform is incapable of generating 64-bit
writes, software must write the low 32-bits first, then the high 32-bits.
Hardware that supports 64-bit addressing will wait for the high 32-bit
write before reading the revised value, and hardware that only supports
32-bit writes will ignore the high 32-bit write.

Previous xHCI code represented 64-bit addresses with two u32 values.  This
lead to buggy code that would write the 32-bits in the wrong order, or
forget to write the upper 32-bits.  Change the two u32s to one u64 and
create a function call to write all 64-bit addresses in the proper order.
This new function could be modified in the future if all platforms support
64-bit writes.
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b11069f5
...@@ -173,6 +173,7 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int ...@@ -173,6 +173,7 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int
{ {
void *addr; void *addr;
u32 temp; u32 temp;
u64 temp_64;
addr = &ir_set->irq_pending; addr = &ir_set->irq_pending;
temp = xhci_readl(xhci, addr); temp = xhci_readl(xhci, addr);
...@@ -200,25 +201,15 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int ...@@ -200,25 +201,15 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int
xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n", xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n",
addr, (unsigned int)temp); addr, (unsigned int)temp);
addr = &ir_set->erst_base[0]; addr = &ir_set->erst_base;
temp = xhci_readl(xhci, addr); temp_64 = xhci_read_64(xhci, addr);
xhci_dbg(xhci, " %p: ir_set.erst_base[0] = 0x%x\n", xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
addr, (unsigned int) temp); addr, temp_64);
addr = &ir_set->erst_base[1];
temp = xhci_readl(xhci, addr);
xhci_dbg(xhci, " %p: ir_set.erst_base[1] = 0x%x\n",
addr, (unsigned int) temp);
addr = &ir_set->erst_dequeue[0];
temp = xhci_readl(xhci, addr);
xhci_dbg(xhci, " %p: ir_set.erst_dequeue[0] = 0x%x\n",
addr, (unsigned int) temp);
addr = &ir_set->erst_dequeue[1]; addr = &ir_set->erst_dequeue;
temp = xhci_readl(xhci, addr); temp_64 = xhci_read_64(xhci, addr);
xhci_dbg(xhci, " %p: ir_set.erst_dequeue[1] = 0x%x\n", xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
addr, (unsigned int) temp); addr, temp_64);
} }
void xhci_print_run_regs(struct xhci_hcd *xhci) void xhci_print_run_regs(struct xhci_hcd *xhci)
...@@ -268,8 +259,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) ...@@ -268,8 +259,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
xhci_dbg(xhci, "Link TRB:\n"); xhci_dbg(xhci, "Link TRB:\n");
xhci_print_trb_offsets(xhci, trb); xhci_print_trb_offsets(xhci, trb);
address = trb->link.segment_ptr[0] + address = trb->link.segment_ptr;
(((u64) trb->link.segment_ptr[1]) << 32);
xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address); xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
xhci_dbg(xhci, "Interrupter target = 0x%x\n", xhci_dbg(xhci, "Interrupter target = 0x%x\n",
...@@ -282,8 +272,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) ...@@ -282,8 +272,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
(unsigned int) (trb->link.control & TRB_NO_SNOOP)); (unsigned int) (trb->link.control & TRB_NO_SNOOP));
break; break;
case TRB_TYPE(TRB_TRANSFER): case TRB_TYPE(TRB_TRANSFER):
address = trb->trans_event.buffer[0] + address = trb->trans_event.buffer;
(((u64) trb->trans_event.buffer[1]) << 32);
/* /*
* FIXME: look at flags to figure out if it's an address or if * FIXME: look at flags to figure out if it's an address or if
* the data is directly in the buffer field. * the data is directly in the buffer field.
...@@ -291,8 +280,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) ...@@ -291,8 +280,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address); xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
break; break;
case TRB_TYPE(TRB_COMPLETION): case TRB_TYPE(TRB_COMPLETION):
address = trb->event_cmd.cmd_trb[0] + address = trb->event_cmd.cmd_trb;
(((u64) trb->event_cmd.cmd_trb[1]) << 32);
xhci_dbg(xhci, "Command TRB pointer = %llu\n", address); xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
xhci_dbg(xhci, "Completion status = %u\n", xhci_dbg(xhci, "Completion status = %u\n",
(unsigned int) GET_COMP_CODE(trb->event_cmd.status)); (unsigned int) GET_COMP_CODE(trb->event_cmd.status));
...@@ -328,8 +316,8 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg) ...@@ -328,8 +316,8 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
for (i = 0; i < TRBS_PER_SEGMENT; ++i) { for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
trb = &seg->trbs[i]; trb = &seg->trbs[i];
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr, xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
(unsigned int) trb->link.segment_ptr[0], lower_32_bits(trb->link.segment_ptr),
(unsigned int) trb->link.segment_ptr[1], upper_32_bits(trb->link.segment_ptr),
(unsigned int) trb->link.intr_target, (unsigned int) trb->link.intr_target,
(unsigned int) trb->link.control); (unsigned int) trb->link.control);
addr += sizeof(*trb); addr += sizeof(*trb);
...@@ -386,8 +374,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) ...@@ -386,8 +374,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
entry = &erst->entries[i]; entry = &erst->entries[i];
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
(unsigned int) addr, (unsigned int) addr,
(unsigned int) entry->seg_addr[0], lower_32_bits(entry->seg_addr),
(unsigned int) entry->seg_addr[1], upper_32_bits(entry->seg_addr),
(unsigned int) entry->seg_size, (unsigned int) entry->seg_size,
(unsigned int) entry->rsvd); (unsigned int) entry->rsvd);
addr += sizeof(*entry); addr += sizeof(*entry);
...@@ -396,12 +384,13 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) ...@@ -396,12 +384,13 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
{ {
u32 val; u64 val;
val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]); val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = 0x%x\n", val); xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[1]); lower_32_bits(val));
xhci_dbg(xhci, "// xHC command ring deq ptr high bits = 0x%x\n", val); xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
upper_32_bits(val));
} }
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep) void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
...@@ -462,14 +451,10 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_ad ...@@ -462,14 +451,10 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_ad
&ctx->ep[i].ep_info2, &ctx->ep[i].ep_info2,
(unsigned long long)dma, ctx->ep[i].ep_info2); (unsigned long long)dma, ctx->ep[i].ep_info2);
dma += field_size; dma += field_size;
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[0]\n", xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
&ctx->ep[i].deq[0], &ctx->ep[i].deq,
(unsigned long long)dma, ctx->ep[i].deq[0]); (unsigned long long)dma, ctx->ep[i].deq);
dma += field_size; dma += 2*field_size;
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[1]\n",
&ctx->ep[i].deq[1],
(unsigned long long)dma, ctx->ep[i].deq[1]);
dma += field_size;
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n", xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
&ctx->ep[i].tx_info, &ctx->ep[i].tx_info,
(unsigned long long)dma, ctx->ep[i].tx_info); (unsigned long long)dma, ctx->ep[i].tx_info);
......
...@@ -226,6 +226,7 @@ int xhci_init(struct usb_hcd *hcd) ...@@ -226,6 +226,7 @@ int xhci_init(struct usb_hcd *hcd)
static void xhci_work(struct xhci_hcd *xhci) static void xhci_work(struct xhci_hcd *xhci)
{ {
u32 temp; u32 temp;
u64 temp_64;
/* /*
* Clear the op reg interrupt status first, * Clear the op reg interrupt status first,
...@@ -249,8 +250,8 @@ static void xhci_work(struct xhci_hcd *xhci) ...@@ -249,8 +250,8 @@ static void xhci_work(struct xhci_hcd *xhci)
xhci_handle_event(xhci); xhci_handle_event(xhci);
/* Clear the event handler busy flag; the event ring should be empty. */ /* Clear the event handler busy flag; the event ring should be empty. */
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
xhci_writel(xhci, temp & ~ERST_EHB, &xhci->ir_set->erst_dequeue[0]); xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue);
/* Flush posted writes -- FIXME is this necessary? */ /* Flush posted writes -- FIXME is this necessary? */
xhci_readl(xhci, &xhci->ir_set->irq_pending); xhci_readl(xhci, &xhci->ir_set->irq_pending);
} }
...@@ -295,6 +296,7 @@ void xhci_event_ring_work(unsigned long arg) ...@@ -295,6 +296,7 @@ void xhci_event_ring_work(unsigned long arg)
{ {
unsigned long flags; unsigned long flags;
int temp; int temp;
u64 temp_64;
struct xhci_hcd *xhci = (struct xhci_hcd *) arg; struct xhci_hcd *xhci = (struct xhci_hcd *) arg;
int i, j; int i, j;
...@@ -311,9 +313,9 @@ void xhci_event_ring_work(unsigned long arg) ...@@ -311,9 +313,9 @@ void xhci_event_ring_work(unsigned long arg)
xhci_dbg(xhci, "Event ring:\n"); xhci_dbg(xhci, "Event ring:\n");
xhci_debug_segment(xhci, xhci->event_ring->deq_seg); xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
xhci_dbg_ring_ptrs(xhci, xhci->event_ring); xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK; temp_64 &= ~ERST_PTR_MASK;
xhci_dbg(xhci, "ERST deq = 0x%x\n", temp); xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
xhci_dbg(xhci, "Command ring:\n"); xhci_dbg(xhci, "Command ring:\n");
xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg); xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg);
xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
...@@ -356,6 +358,7 @@ void xhci_event_ring_work(unsigned long arg) ...@@ -356,6 +358,7 @@ void xhci_event_ring_work(unsigned long arg)
int xhci_run(struct usb_hcd *hcd) int xhci_run(struct usb_hcd *hcd)
{ {
u32 temp; u32 temp;
u64 temp_64;
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
void (*doorbell)(struct xhci_hcd *) = NULL; void (*doorbell)(struct xhci_hcd *) = NULL;
...@@ -416,11 +419,9 @@ int xhci_run(struct usb_hcd *hcd) ...@@ -416,11 +419,9 @@ int xhci_run(struct usb_hcd *hcd)
xhci_dbg(xhci, "Event ring:\n"); xhci_dbg(xhci, "Event ring:\n");
xhci_debug_ring(xhci, xhci->event_ring); xhci_debug_ring(xhci, xhci->event_ring);
xhci_dbg_ring_ptrs(xhci, xhci->event_ring); xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK; temp_64 &= ~ERST_PTR_MASK;
xhci_dbg(xhci, "ERST deq = 0x%x\n", temp); xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]);
xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp);
temp = xhci_readl(xhci, &xhci->op_regs->command); temp = xhci_readl(xhci, &xhci->op_regs->command);
temp |= (CMD_RUN); temp |= (CMD_RUN);
...@@ -888,8 +889,7 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev) ...@@ -888,8 +889,7 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
ep_ctx = &virt_dev->in_ctx->ep[i]; ep_ctx = &virt_dev->in_ctx->ep[i];
ep_ctx->ep_info = 0; ep_ctx->ep_info = 0;
ep_ctx->ep_info2 = 0; ep_ctx->ep_info2 = 0;
ep_ctx->deq[0] = 0; ep_ctx->deq = 0;
ep_ctx->deq[1] = 0;
ep_ctx->tx_info = 0; ep_ctx->tx_info = 0;
} }
} }
...@@ -1165,7 +1165,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -1165,7 +1165,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_virt_device *virt_dev; struct xhci_virt_device *virt_dev;
int ret = 0; int ret = 0;
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
u32 temp; u64 temp_64;
if (!udev->slot_id) { if (!udev->slot_id) {
xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
...@@ -1227,18 +1227,13 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -1227,18 +1227,13 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
if (ret) { if (ret) {
return ret; return ret;
} }
temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]); temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp); xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]); xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp);
xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%p = %#08x\n",
udev->slot_id,
&xhci->dcbaa->dev_context_ptrs[2*udev->slot_id],
xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]);
xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%p = %#08x\n",
udev->slot_id, udev->slot_id,
&xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1], &xhci->dcbaa->dev_context_ptrs[udev->slot_id],
xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]); (unsigned long long)
xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
(unsigned long long)virt_dev->out_ctx_dma); (unsigned long long)virt_dev->out_ctx_dma);
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
......
...@@ -88,7 +88,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, ...@@ -88,7 +88,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
return; return;
prev->next = next; prev->next = next;
if (link_trbs) { if (link_trbs) {
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr[0] = next->dma; prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma;
/* Set the last TRB in the segment to have a TRB type ID of Link TRB */ /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
val = prev->trbs[TRBS_PER_SEGMENT-1].link.control; val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
...@@ -200,8 +200,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) ...@@ -200,8 +200,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
return; return;
dev = xhci->devs[slot_id]; dev = xhci->devs[slot_id];
xhci->dcbaa->dev_context_ptrs[2*slot_id] = 0; xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
if (!dev) if (!dev)
return; return;
...@@ -265,13 +264,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, ...@@ -265,13 +264,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
* Point to output device context in dcbaa; skip the output control * Point to output device context in dcbaa; skip the output control
* context, which is eight 32 bit fields (or 32 bytes long) * context, which is eight 32 bit fields (or 32 bytes long)
*/ */
xhci->dcbaa->dev_context_ptrs[2*slot_id] = xhci->dcbaa->dev_context_ptrs[slot_id] =
(u32) dev->out_ctx_dma + (32); (u32) dev->out_ctx_dma + (32);
xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
slot_id, slot_id,
&xhci->dcbaa->dev_context_ptrs[2*slot_id], &xhci->dcbaa->dev_context_ptrs[slot_id],
(unsigned long long)dev->out_ctx_dma); (unsigned long long)dev->out_ctx_dma);
xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
return 1; return 1;
fail: fail:
...@@ -360,10 +358,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud ...@@ -360,10 +358,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
ep0_ctx->ep_info2 |= MAX_BURST(0); ep0_ctx->ep_info2 |= MAX_BURST(0);
ep0_ctx->ep_info2 |= ERROR_COUNT(3); ep0_ctx->ep_info2 |= ERROR_COUNT(3);
ep0_ctx->deq[0] = ep0_ctx->deq =
dev->ep_rings[0]->first_seg->dma; dev->ep_rings[0]->first_seg->dma;
ep0_ctx->deq[0] |= dev->ep_rings[0]->cycle_state; ep0_ctx->deq |= dev->ep_rings[0]->cycle_state;
ep0_ctx->deq[1] = 0;
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */ /* Steps 7 and 8 were done in xhci_alloc_virt_device() */
...@@ -477,8 +474,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ...@@ -477,8 +474,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
if (!virt_dev->new_ep_rings[ep_index]) if (!virt_dev->new_ep_rings[ep_index])
return -ENOMEM; return -ENOMEM;
ep_ring = virt_dev->new_ep_rings[ep_index]; ep_ring = virt_dev->new_ep_rings[ep_index];
ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state; ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
ep_ctx->deq[1] = 0;
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
...@@ -535,8 +531,7 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, ...@@ -535,8 +531,7 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
ep_ctx->ep_info = 0; ep_ctx->ep_info = 0;
ep_ctx->ep_info2 = 0; ep_ctx->ep_info2 = 0;
ep_ctx->deq[0] = 0; ep_ctx->deq = 0;
ep_ctx->deq[1] = 0;
ep_ctx->tx_info = 0; ep_ctx->tx_info = 0;
/* Don't free the endpoint ring until the set interface or configuration /* Don't free the endpoint ring until the set interface or configuration
* request succeeds. * request succeeds.
...@@ -551,10 +546,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) ...@@ -551,10 +546,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
/* Free the Event Ring Segment Table and the actual Event Ring */ /* Free the Event Ring Segment Table and the actual Event Ring */
xhci_writel(xhci, 0, &xhci->ir_set->erst_size); xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]); xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]); xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]);
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries) if (xhci->erst.entries)
pci_free_consistent(pdev, size, pci_free_consistent(pdev, size,
...@@ -566,8 +559,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) ...@@ -566,8 +559,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->event_ring = NULL; xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n"); xhci_dbg(xhci, "Freed event ring\n");
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]); xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]);
if (xhci->cmd_ring) if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring); xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL; xhci->cmd_ring = NULL;
...@@ -586,8 +578,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) ...@@ -586,8 +578,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->device_pool = NULL; xhci->device_pool = NULL;
xhci_dbg(xhci, "Freed device context pool\n"); xhci_dbg(xhci, "Freed device context pool\n");
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]); xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
if (xhci->dcbaa) if (xhci->dcbaa)
pci_free_consistent(pdev, sizeof(*xhci->dcbaa), pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
xhci->dcbaa, xhci->dcbaa->dma); xhci->dcbaa, xhci->dcbaa->dma);
...@@ -602,6 +593,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -602,6 +593,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
dma_addr_t dma; dma_addr_t dma;
struct device *dev = xhci_to_hcd(xhci)->self.controller; struct device *dev = xhci_to_hcd(xhci)->self.controller;
unsigned int val, val2; unsigned int val, val2;
u64 val_64;
struct xhci_segment *seg; struct xhci_segment *seg;
u32 page_size; u32 page_size;
int i; int i;
...@@ -647,8 +639,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -647,8 +639,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci->dcbaa->dma = dma; xhci->dcbaa->dma = dma;
xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n", xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n",
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa); (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]); xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
/* /*
* Initialize the ring segment pool. The ring must be a contiguous * Initialize the ring segment pool. The ring must be a contiguous
...@@ -675,14 +666,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -675,14 +666,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
(unsigned long long)xhci->cmd_ring->first_seg->dma); (unsigned long long)xhci->cmd_ring->first_seg->dma);
/* Set the address in the Command Ring Control register */ /* Set the address in the Command Ring Control register */
val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]); val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
val = (val & ~CMD_RING_ADDR_MASK) | val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) | (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
xhci->cmd_ring->cycle_state; xhci->cmd_ring->cycle_state;
xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val); xhci_dbg(xhci, "// Setting command ring address to 0x%x\n", val);
xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]); xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n");
xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]);
xhci_dbg_cmd_ptrs(xhci); xhci_dbg_cmd_ptrs(xhci);
val = xhci_readl(xhci, &xhci->cap_regs->db_off); val = xhci_readl(xhci, &xhci->cap_regs->db_off);
...@@ -722,8 +711,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -722,8 +711,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
/* set ring base address and size for each segment table entry */ /* set ring base address and size for each segment table entry */
for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
struct xhci_erst_entry *entry = &xhci->erst.entries[val]; struct xhci_erst_entry *entry = &xhci->erst.entries[val];
entry->seg_addr[0] = seg->dma; entry->seg_addr = seg->dma;
entry->seg_addr[1] = 0;
entry->seg_size = TRBS_PER_SEGMENT; entry->seg_size = TRBS_PER_SEGMENT;
entry->rsvd = 0; entry->rsvd = 0;
seg = seg->next; seg = seg->next;
...@@ -741,11 +729,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -741,11 +729,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
/* set the segment table base address */ /* set the segment table base address */
xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n", xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n",
(unsigned long long)xhci->erst.erst_dma_addr); (unsigned long long)xhci->erst.erst_dma_addr);
val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]); val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
val &= ERST_PTR_MASK; val_64 &= ERST_PTR_MASK;
val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK); val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]); xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
/* Set the event ring dequeue address */ /* Set the event ring dequeue address */
xhci_set_hc_event_deq(xhci); xhci_set_hc_event_deq(xhci);
......
...@@ -237,7 +237,7 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, ...@@ -237,7 +237,7 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
void xhci_set_hc_event_deq(struct xhci_hcd *xhci) void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
{ {
u32 temp; u64 temp;
dma_addr_t deq; dma_addr_t deq;
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
...@@ -246,13 +246,12 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci) ...@@ -246,13 +246,12 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
xhci_warn(xhci, "WARN something wrong with SW event ring " xhci_warn(xhci, "WARN something wrong with SW event ring "
"dequeue ptr.\n"); "dequeue ptr.\n");
/* Update HC event ring dequeue pointer */ /* Update HC event ring dequeue pointer */
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK; temp &= ERST_PTR_MASK;
if (!in_interrupt()) if (!in_interrupt())
xhci_dbg(xhci, "// Write event ring dequeue pointer\n"); xhci_dbg(xhci, "// Write event ring dequeue pointer\n");
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]); xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
xhci_writel(xhci, (deq & ~ERST_PTR_MASK) | temp, &xhci->ir_set->erst_dequeue);
&xhci->ir_set->erst_dequeue[0]);
} }
/* Ring the host controller doorbell after placing a command on the ring */ /* Ring the host controller doorbell after placing a command on the ring */
...@@ -352,7 +351,7 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci, ...@@ -352,7 +351,7 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci,
if (!state->new_deq_seg) if (!state->new_deq_seg)
BUG(); BUG();
/* Dig out the cycle state saved by the xHC during the stop ep cmd */ /* Dig out the cycle state saved by the xHC during the stop ep cmd */
state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq[0]; state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq;
state->new_deq_ptr = cur_td->last_trb; state->new_deq_ptr = cur_td->last_trb;
state->new_deq_seg = find_trb_seg(state->new_deq_seg, state->new_deq_seg = find_trb_seg(state->new_deq_seg,
...@@ -594,10 +593,8 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, ...@@ -594,10 +593,8 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
* cancelling URBs, which might not be an error... * cancelling URBs, which might not be an error...
*/ */
} else { } else {
xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq[0] = 0x%x, " xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
"deq[1] = 0x%x.\n", dev->out_ctx->ep[ep_index].deq);
dev->out_ctx->ep[ep_index].deq[0],
dev->out_ctx->ep[ep_index].deq[1]);
} }
ep_ring->state &= ~SET_DEQ_PENDING; ep_ring->state &= ~SET_DEQ_PENDING;
...@@ -631,7 +628,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, ...@@ -631,7 +628,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
u64 cmd_dma; u64 cmd_dma;
dma_addr_t cmd_dequeue_dma; dma_addr_t cmd_dequeue_dma;
cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0]; cmd_dma = event->cmd_trb;
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
xhci->cmd_ring->dequeue); xhci->cmd_ring->dequeue);
/* Is the command ring deq ptr out of sync with the deq seg ptr? */ /* Is the command ring deq ptr out of sync with the deq seg ptr? */
...@@ -794,10 +791,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -794,10 +791,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
return -ENODEV; return -ENODEV;
} }
event_dma = event->buffer[0]; event_dma = event->buffer;
if (event->buffer[1] != 0)
xhci_warn(xhci, "WARN ignoring upper 32-bits of 64-bit TRB dma address\n");
/* This TRB should be in the TD at the head of this ring's TD list */ /* This TRB should be in the TD at the head of this ring's TD list */
if (list_empty(&ep_ring->td_list)) { if (list_empty(&ep_ring->td_list)) {
xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
...@@ -821,10 +815,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -821,10 +815,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)]; event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
(unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
xhci_dbg(xhci, "Offset 0x00 (buffer[0]) = 0x%x\n", xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n",
(unsigned int) event->buffer[0]); lower_32_bits(event->buffer));
xhci_dbg(xhci, "Offset 0x04 (buffer[0]) = 0x%x\n", xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n",
(unsigned int) event->buffer[1]); upper_32_bits(event->buffer));
xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n", xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n",
(unsigned int) event->transfer_len); (unsigned int) event->transfer_len);
xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n", xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n",
...@@ -1343,8 +1337,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ...@@ -1343,8 +1337,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
TD_REMAINDER(urb->transfer_buffer_length - running_total) | TD_REMAINDER(urb->transfer_buffer_length - running_total) |
TRB_INTR_TARGET(0); TRB_INTR_TARGET(0);
queue_trb(xhci, ep_ring, false, queue_trb(xhci, ep_ring, false,
(u32) addr, lower_32_bits(addr),
(u32) ((u64) addr >> 32), upper_32_bits(addr),
length_field, length_field,
/* We always want to know if the TRB was short, /* We always want to know if the TRB was short,
* or we won't get an event when it completes. * or we won't get an event when it completes.
...@@ -1475,8 +1469,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, ...@@ -1475,8 +1469,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
TD_REMAINDER(urb->transfer_buffer_length - running_total) | TD_REMAINDER(urb->transfer_buffer_length - running_total) |
TRB_INTR_TARGET(0); TRB_INTR_TARGET(0);
queue_trb(xhci, ep_ring, false, queue_trb(xhci, ep_ring, false,
(u32) addr, lower_32_bits(addr),
(u32) ((u64) addr >> 32), upper_32_bits(addr),
length_field, length_field,
/* We always want to know if the TRB was short, /* We always want to know if the TRB was short,
* or we won't get an event when it completes. * or we won't get an event when it completes.
...@@ -1637,7 +1631,8 @@ int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id) ...@@ -1637,7 +1631,8 @@ int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id) u32 slot_id)
{ {
return queue_command(xhci, in_ctx_ptr, 0, 0, return queue_command(xhci, lower_32_bits(in_ctx_ptr),
upper_32_bits(in_ctx_ptr), 0,
TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id)); TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id));
} }
...@@ -1645,7 +1640,8 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, ...@@ -1645,7 +1640,8 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id) u32 slot_id)
{ {
return queue_command(xhci, in_ctx_ptr, 0, 0, return queue_command(xhci, lower_32_bits(in_ctx_ptr),
upper_32_bits(in_ctx_ptr), 0,
TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id)); TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
} }
...@@ -1677,7 +1673,8 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, ...@@ -1677,7 +1673,8 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n", xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
deq_seg, deq_ptr); deq_seg, deq_ptr);
return queue_command(xhci, (u32) addr | cycle_state, 0, 0, return queue_command(xhci, lower_32_bits(addr) | cycle_state,
upper_32_bits(addr), 0,
trb_slot_id | trb_ep_index | type); trb_slot_id | trb_ep_index | type);
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/kernel.h>
#include "../core/hcd.h" #include "../core/hcd.h"
/* Code sharing between pci-quirks and xhci hcd */ /* Code sharing between pci-quirks and xhci hcd */
...@@ -42,14 +43,6 @@ ...@@ -42,14 +43,6 @@
* xHCI register interface. * xHCI register interface.
* This corresponds to the eXtensible Host Controller Interface (xHCI) * This corresponds to the eXtensible Host Controller Interface (xHCI)
* Revision 0.95 specification * Revision 0.95 specification
*
* Registers should always be accessed with double word or quad word accesses.
*
* Some xHCI implementations may support 64-bit address pointers. Registers
* with 64-bit address pointers should be written to with dword accesses by
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
* xHCI implementations that do not support 64-bit address pointers will ignore
* the high dword, and write order is irrelevant.
*/ */
/** /**
...@@ -166,10 +159,10 @@ struct xhci_op_regs { ...@@ -166,10 +159,10 @@ struct xhci_op_regs {
u32 reserved1; u32 reserved1;
u32 reserved2; u32 reserved2;
u32 dev_notification; u32 dev_notification;
u32 cmd_ring[2]; u64 cmd_ring;
/* rsvd: offset 0x20-2F */ /* rsvd: offset 0x20-2F */
u32 reserved3[4]; u32 reserved3[4];
u32 dcbaa_ptr[2]; u64 dcbaa_ptr;
u32 config_reg; u32 config_reg;
/* rsvd: offset 0x3C-3FF */ /* rsvd: offset 0x3C-3FF */
u32 reserved4[241]; u32 reserved4[241];
...@@ -254,7 +247,7 @@ struct xhci_op_regs { ...@@ -254,7 +247,7 @@ struct xhci_op_regs {
#define CMD_RING_RUNNING (1 << 3) #define CMD_RING_RUNNING (1 << 3)
/* bits 4:5 reserved and should be preserved */ /* bits 4:5 reserved and should be preserved */
/* Command Ring pointer - bit mask for the lower 32 bits. */ /* Command Ring pointer - bit mask for the lower 32 bits. */
#define CMD_RING_ADDR_MASK (0xffffffc0) #define CMD_RING_RSVD_BITS (0x3f)
/* CONFIG - Configure Register - config_reg bitmasks */ /* CONFIG - Configure Register - config_reg bitmasks */
/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
...@@ -382,8 +375,8 @@ struct xhci_intr_reg { ...@@ -382,8 +375,8 @@ struct xhci_intr_reg {
u32 irq_control; u32 irq_control;
u32 erst_size; u32 erst_size;
u32 rsvd; u32 rsvd;
u32 erst_base[2]; u64 erst_base;
u32 erst_dequeue[2]; u64 erst_dequeue;
}; };
/* irq_pending bitmasks */ /* irq_pending bitmasks */
...@@ -538,7 +531,7 @@ struct xhci_slot_ctx { ...@@ -538,7 +531,7 @@ struct xhci_slot_ctx {
struct xhci_ep_ctx { struct xhci_ep_ctx {
u32 ep_info; u32 ep_info;
u32 ep_info2; u32 ep_info2;
u32 deq[2]; u64 deq;
u32 tx_info; u32 tx_info;
/* offset 0x14 - 0x1f reserved for HC internal use */ /* offset 0x14 - 0x1f reserved for HC internal use */
u32 reserved[3]; u32 reserved[3];
...@@ -641,7 +634,7 @@ struct xhci_virt_device { ...@@ -641,7 +634,7 @@ struct xhci_virt_device {
*/ */
struct xhci_device_context_array { struct xhci_device_context_array {
/* 64-bit device addresses; we only write 32-bit addresses */ /* 64-bit device addresses; we only write 32-bit addresses */
u32 dev_context_ptrs[2*MAX_HC_SLOTS]; u64 dev_context_ptrs[MAX_HC_SLOTS];
/* private xHCD pointers */ /* private xHCD pointers */
dma_addr_t dma; dma_addr_t dma;
}; };
...@@ -654,7 +647,7 @@ struct xhci_device_context_array { ...@@ -654,7 +647,7 @@ struct xhci_device_context_array {
struct xhci_stream_ctx { struct xhci_stream_ctx {
/* 64-bit stream ring address, cycle state, and stream type */ /* 64-bit stream ring address, cycle state, and stream type */
u32 stream_ring[2]; u64 stream_ring;
/* offset 0x14 - 0x1f reserved for HC internal use */ /* offset 0x14 - 0x1f reserved for HC internal use */
u32 reserved[2]; u32 reserved[2];
}; };
...@@ -662,7 +655,7 @@ struct xhci_stream_ctx { ...@@ -662,7 +655,7 @@ struct xhci_stream_ctx {
struct xhci_transfer_event { struct xhci_transfer_event {
/* 64-bit buffer address, or immediate data */ /* 64-bit buffer address, or immediate data */
u32 buffer[2]; u64 buffer;
u32 transfer_len; u32 transfer_len;
/* This field is interpreted differently based on the type of TRB */ /* This field is interpreted differently based on the type of TRB */
u32 flags; u32 flags;
...@@ -744,7 +737,7 @@ struct xhci_transfer_event { ...@@ -744,7 +737,7 @@ struct xhci_transfer_event {
struct xhci_link_trb { struct xhci_link_trb {
/* 64-bit segment pointer*/ /* 64-bit segment pointer*/
u32 segment_ptr[2]; u64 segment_ptr;
u32 intr_target; u32 intr_target;
u32 control; u32 control;
}; };
...@@ -755,7 +748,7 @@ struct xhci_link_trb { ...@@ -755,7 +748,7 @@ struct xhci_link_trb {
/* Command completion event TRB */ /* Command completion event TRB */
struct xhci_event_cmd { struct xhci_event_cmd {
/* Pointer to command TRB, or the value passed by the event data trb */ /* Pointer to command TRB, or the value passed by the event data trb */
u32 cmd_trb[2]; u64 cmd_trb;
u32 status; u32 status;
u32 flags; u32 flags;
}; };
...@@ -943,7 +936,7 @@ struct xhci_ring { ...@@ -943,7 +936,7 @@ struct xhci_ring {
struct xhci_erst_entry { struct xhci_erst_entry {
/* 64-bit event ring segment address */ /* 64-bit event ring segment address */
u32 seg_addr[2]; u64 seg_addr;
u32 seg_size; u32 seg_size;
/* Set to zero */ /* Set to zero */
u32 rsvd; u32 rsvd;
...@@ -1079,6 +1072,38 @@ static inline void xhci_writel(struct xhci_hcd *xhci, ...@@ -1079,6 +1072,38 @@ static inline void xhci_writel(struct xhci_hcd *xhci,
writel(val, regs); writel(val, regs);
} }
/*
* Registers should always be accessed with double word or quad word accesses.
*
* Some xHCI implementations may support 64-bit address pointers. Registers
* with 64-bit address pointers should be written to with dword accesses by
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
* xHCI implementations that do not support 64-bit address pointers will ignore
* the high dword, and write order is irrelevant.
*/
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
__u64 __iomem *regs)
{
__u32 __iomem *ptr = (__u32 __iomem *) regs;
u64 val_lo = readl(ptr);
u64 val_hi = readl(ptr + 1);
return val_lo + (val_hi << 32);
}
static inline void xhci_write_64(struct xhci_hcd *xhci,
const u64 val, __u64 __iomem *regs)
{
__u32 __iomem *ptr = (__u32 __iomem *) regs;
u32 val_lo = lower_32_bits(val);
u32 val_hi = upper_32_bits(val);
if (!in_interrupt())
xhci_dbg(xhci,
"`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n",
regs, (long unsigned int) val);
writel(val_lo, ptr);
writel(val_hi, ptr + 1);
}
/* xHCI debugging */ /* xHCI debugging */
void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
void xhci_print_registers(struct xhci_hcd *xhci); void xhci_print_registers(struct xhci_hcd *xhci);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment