[PATCH v2 0/4] usb: xhci: Prepare xHCI driver for MIPS Octeon big-endian support

These patches fix a few issues, found while porting the xHCI to the MIPS Octeon platforms. The basic issues here are:
- Endianess issues: missing cpu_to_leXX() & leXX_to_cpu() conversions - Use physical (DMA) address for the xHCI DMA controller
These patches are the groundwork for the upcoming xHCI Octeon support that will follow soon.
Thanks, Stefan
Changes in v2: - Add missing (uintptr_t) cast to remove compile time warning
Stefan Roese (4): usb: xhci: Add missing endian conversions (cpu_to_leXX / leXX_to_cpu) usb: xhci: xhci_mem_init: Use cpu_to_le64() and not xhci_writeq() usb: usb-uclass.c: Drop le16_to_cpu() as values are already swapped usb: xhci: Add virt_to_phys() to support mapped platforms
drivers/usb/host/usb-uclass.c | 8 ++++---- drivers/usb/host/xhci-mem.c | 30 +++++++++++++++--------------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 4 files changed, 24 insertions(+), 25 deletions(-)

While trying to use the U-Boot xHCI driver on the MIPS Octeon platform, which is big endian, I noticed that the driver is missing a few endian conversion calls. This patch adds these missing endian conversion calls.
Signed-off-by: Stefan Roese sr@denx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Cc: Bin Meng bmeng.cn@gmail.com Cc: Marek Vasut marex@denx.de
---
Changes in v2: - Add missing (uintptr_t) cast to remove compile time warning
drivers/usb/host/xhci-mem.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2d968aafb0..7d55944765 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
ctrl->dcbaa->dev_context_ptrs[0] = 0;
- free((void *)(uintptr_t)ctrl->scratchpad->sp_array[0]); + free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0])); free(ctrl->scratchpad->sp_array); free(ctrl->scratchpad); ctrl->scratchpad = NULL; @@ -225,7 +225,8 @@ static void xhci_link_segments(struct xhci_segment *prev, prev->next = next; if (link_trbs) { val_64 = (uintptr_t)next->trbs; - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = val_64; + prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = + cpu_to_le64(val_64);
/* * Set the last TRB in the segment to @@ -486,7 +487,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes);
/* Point to output device context in dcbaa. */ - ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; + ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64);
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], sizeof(__le64)); @@ -768,7 +769,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
debug("route string %x\n", route); #endif - slot_ctx->dev_info |= route; + slot_ctx->dev_info |= cpu_to_le32(route);
switch (speed) { case USB_SPEED_SUPER:

xhci_writeq() makes the CPU->LE swapping only when addressing registers in the xHCI controller address range and not in the local memory (RAM). We need to use cpu_to_le64() here to ensure that the conversion is done correctly.
Signed-off-by: Stefan Roese sr@denx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Cc: Bin Meng bmeng.cn@gmail.com Cc: Marek Vasut marex@denx.de ---
(no changes since v1)
drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7d55944765..6cd55fee94 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -562,7 +562,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, trb_64 = 0; trb_64 = (uintptr_t)seg->trbs; struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; - xhci_writeq(&entry->seg_addr, trb_64); + entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; seg = seg->next;

These values are already swapped to CPU endianess, so swapping them again is a bug. Let's remove the swap here instead.
Signed-off-by: Stefan Roese sr@denx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Cc: Bin Meng bmeng.cn@gmail.com Cc: Marek Vasut marex@denx.de ---
(no changes since v1)
drivers/usb/host/usb-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index cb79dfbbd5..aa08d4ffc6 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -416,21 +416,21 @@ static int usb_match_device(const struct usb_device_descriptor *desc, const struct usb_device_id *id) { if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - id->idVendor != le16_to_cpu(desc->idVendor)) + id->idVendor != desc->idVendor) return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - id->idProduct != le16_to_cpu(desc->idProduct)) + id->idProduct != desc->idProduct) return 0;
/* No need to test id->bcdDevice_lo != 0, since 0 is never greater than any unsigned number. */ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && - (id->bcdDevice_lo > le16_to_cpu(desc->bcdDevice))) + (id->bcdDevice_lo > desc->bcdDevice)) return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && - (id->bcdDevice_hi < le16_to_cpu(desc->bcdDevice))) + (id->bcdDevice_hi < desc->bcdDevice)) return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&

Some platforms, like MIPS Octeon, use mapped addresses (virtual address != physical address). On these platforms we need to make sure, that the local virtual addresses are converted to physical (DMA) addresses for the xHCI controller. This patch adds the missing virt_to_phys() calls, so that the correct addresses are used.
Signed-off-by: Stefan Roese sr@denx.de Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com Cc: Bin Meng bmeng.cn@gmail.com Cc: Marek Vasut marex@denx.de
---
(no changes since v1)
drivers/usb/host/xhci-mem.c | 19 +++++++++---------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 3 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6cd55fee94..8792a2957f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -224,7 +224,7 @@ static void xhci_link_segments(struct xhci_segment *prev, return; prev->next = next; if (link_trbs) { - val_64 = (uintptr_t)next->trbs; + val_64 = virt_to_phys(next->trbs); prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = cpu_to_le64(val_64);
@@ -484,7 +484,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) /* Allocate endpoint 0 ring */ virt_dev->eps[0].ring = xhci_ring_alloc(1, true);
- byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); + byte_64 = virt_to_phys(virt_dev->out_ctx->bytes);
/* Point to output device context in dcbaa. */ ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64); @@ -509,7 +509,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, uint64_t val_64; uint64_t trb_64; uint32_t val; - unsigned long deq; + uint64_t deq; int i; struct xhci_segment *seg;
@@ -521,7 +521,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, return -ENOMEM; }
- val_64 = (uintptr_t)ctrl->dcbaa; + val_64 = virt_to_phys(ctrl->dcbaa); /* Set the pointer in DCBAA register */ xhci_writeq(&hcor->or_dcbaap, val_64);
@@ -529,7 +529,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, ctrl->cmd_ring = xhci_ring_alloc(1, true);
/* Set the address in the Command Ring Control register */ - trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; + trb_64 = virt_to_phys(ctrl->cmd_ring->first_seg->trbs); val_64 = xhci_readq(&hcor->or_crcr); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | @@ -559,8 +559,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, for (val = 0, seg = ctrl->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { - trb_64 = 0; - trb_64 = (uintptr_t)seg->trbs; + trb_64 = virt_to_phys(seg->trbs); struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); @@ -570,7 +569,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, xhci_flush_cache((uintptr_t)ctrl->erst.entries, ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
- deq = (unsigned long)ctrl->event_ring->dequeue; + deq = virt_to_phys(ctrl->event_ring->dequeue);
/* Update HC event ring dequeue pointer */ xhci_writeq(&ctrl->ir_set->erst_dequeue, @@ -585,7 +584,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* this is the event ring segment table pointer */ val_64 = xhci_readq(&ctrl->ir_set->erst_base); val_64 &= ERST_PTR_MASK; - val_64 |= ((uintptr_t)(ctrl->erst.entries) & ~ERST_PTR_MASK); + val_64 |= virt_to_phys(ctrl->erst.entries) & ~ERST_PTR_MASK;
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
@@ -853,7 +852,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT));
- trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; + trb_64 = virt_to_phys(virt_dev->eps[0].ring->first_seg->trbs); ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state);
/* diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 86aeaab412..092ed6eaf1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -275,7 +275,7 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, u32 ep_index, trb_type cmd) { u32 fields[4]; - u64 val_64 = (uintptr_t)ptr; + u64 val_64 = virt_to_phys(ptr);
BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING));
@@ -399,7 +399,7 @@ void xhci_acknowledge_event(struct xhci_ctrl *ctrl)
/* Inform the hardware */ xhci_writeq(&ctrl->ir_set->erst_dequeue, - (uintptr_t)ctrl->event_ring->dequeue | ERST_EHB); + virt_to_phys(ctrl->event_ring->dequeue) | ERST_EHB); }
/** @@ -577,7 +577,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, u64 addr; int ret; u32 trb_fields[4]; - u64 val_64 = (uintptr_t)buffer; + u64 val_64 = virt_to_phys(buffer);
debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n", udev, pipe, buffer, length); @@ -876,7 +876,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (length > 0) { if (req->requesttype & USB_DIR_IN) field |= TRB_DIR_IN; - buf_64 = (uintptr_t)buffer; + buf_64 = virt_to_phys(buffer);
trb_fields[0] = lower_32_bits(buf_64); trb_fields[1] = upper_32_bits(buf_64); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ebd2954571..f89e274b0d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -600,8 +600,7 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(MAX_BURST(max_burst) | ERROR_COUNT(err_count));
- trb_64 = (uintptr_t) - virt_dev->eps[ep_index].ring->enqueue; + trb_64 = virt_to_phys(virt_dev->eps[ep_index].ring->enqueue); ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | virt_dev->eps[ep_index].ring->cycle_state);

Hi Bin,
On 21.07.20 10:46, Stefan Roese wrote:
These patches fix a few issues, found while porting the xHCI to the MIPS Octeon platforms. The basic issues here are:
- Endianess issues: missing cpu_to_leXX() & leXX_to_cpu() conversions
- Use physical (DMA) address for the xHCI DMA controller
These patches are the groundwork for the upcoming xHCI Octeon support that will follow soon.
Thanks, Stefan
Changes in v2:
- Add missing (uintptr_t) cast to remove compile time warning
Stefan Roese (4): usb: xhci: Add missing endian conversions (cpu_to_leXX / leXX_to_cpu) usb: xhci: xhci_mem_init: Use cpu_to_le64() and not xhci_writeq() usb: usb-uclass.c: Drop le16_to_cpu() as values are already swapped usb: xhci: Add virt_to_phys() to support mapped platforms
drivers/usb/host/usb-uclass.c | 8 ++++---- drivers/usb/host/xhci-mem.c | 30 +++++++++++++++--------------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 4 files changed, 24 insertions(+), 25 deletions(-)
Is everything okay with this series? If yes, I think it would be good to have it included soon into mainline, so that all platforms have time to test these changes to the common xHCI driver.
Thanks, Stefan

Hi Marek,
On Thu, Jul 30, 2020 at 2:32 PM Stefan Roese sr@denx.de wrote:
Hi Bin,
On 21.07.20 10:46, Stefan Roese wrote:
These patches fix a few issues, found while porting the xHCI to the MIPS Octeon platforms. The basic issues here are:
- Endianess issues: missing cpu_to_leXX() & leXX_to_cpu() conversions
- Use physical (DMA) address for the xHCI DMA controller
These patches are the groundwork for the upcoming xHCI Octeon support that will follow soon.
Thanks, Stefan
Changes in v2:
- Add missing (uintptr_t) cast to remove compile time warning
Stefan Roese (4): usb: xhci: Add missing endian conversions (cpu_to_leXX / leXX_to_cpu) usb: xhci: xhci_mem_init: Use cpu_to_le64() and not xhci_writeq() usb: usb-uclass.c: Drop le16_to_cpu() as values are already swapped usb: xhci: Add virt_to_phys() to support mapped platforms
drivers/usb/host/usb-uclass.c | 8 ++++---- drivers/usb/host/xhci-mem.c | 30 +++++++++++++++--------------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 4 files changed, 24 insertions(+), 25 deletions(-)
Is everything okay with this series? If yes, I think it would be good to have it included soon into mainline, so that all platforms have time to test these changes to the common xHCI driver.
Would you pick up this series? Or do you want me to pick this up via u-boot-x86 tree?
Regards, Bin

Hi Marek,
On 30.07.20 08:59, Bin Meng wrote:
Hi Marek,
On Thu, Jul 30, 2020 at 2:32 PM Stefan Roese sr@denx.de wrote:
Hi Bin,
On 21.07.20 10:46, Stefan Roese wrote:
These patches fix a few issues, found while porting the xHCI to the MIPS Octeon platforms. The basic issues here are:
- Endianess issues: missing cpu_to_leXX() & leXX_to_cpu() conversions
- Use physical (DMA) address for the xHCI DMA controller
These patches are the groundwork for the upcoming xHCI Octeon support that will follow soon.
Thanks, Stefan
Changes in v2:
- Add missing (uintptr_t) cast to remove compile time warning
Stefan Roese (4): usb: xhci: Add missing endian conversions (cpu_to_leXX / leXX_to_cpu) usb: xhci: xhci_mem_init: Use cpu_to_le64() and not xhci_writeq() usb: usb-uclass.c: Drop le16_to_cpu() as values are already swapped usb: xhci: Add virt_to_phys() to support mapped platforms
drivers/usb/host/usb-uclass.c | 8 ++++---- drivers/usb/host/xhci-mem.c | 30 +++++++++++++++--------------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 4 files changed, 24 insertions(+), 25 deletions(-)
Is everything okay with this series? If yes, I think it would be good to have it included soon into mainline, so that all platforms have time to test these changes to the common xHCI driver.
Would you pick up this series? Or do you want me to pick this up via u-boot-x86 tree?
Gently ping on this.
Thanks, Stefan

On 8/5/20 7:57 AM, Stefan Roese wrote:
Hi Marek,
On 30.07.20 08:59, Bin Meng wrote:
Hi Marek,
On Thu, Jul 30, 2020 at 2:32 PM Stefan Roese sr@denx.de wrote:
Hi Bin,
On 21.07.20 10:46, Stefan Roese wrote:
These patches fix a few issues, found while porting the xHCI to the MIPS Octeon platforms. The basic issues here are:
- Endianess issues: missing cpu_to_leXX() & leXX_to_cpu() conversions
- Use physical (DMA) address for the xHCI DMA controller
These patches are the groundwork for the upcoming xHCI Octeon support that will follow soon.
Thanks, Stefan
Changes in v2:
- Add missing (uintptr_t) cast to remove compile time warning
Stefan Roese (4): usb: xhci: Add missing endian conversions (cpu_to_leXX / leXX_to_cpu) usb: xhci: xhci_mem_init: Use cpu_to_le64() and not xhci_writeq() usb: usb-uclass.c: Drop le16_to_cpu() as values are already swapped usb: xhci: Add virt_to_phys() to support mapped platforms
drivers/usb/host/usb-uclass.c | 8 ++++---- drivers/usb/host/xhci-mem.c | 30 +++++++++++++++--------------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 4 files changed, 24 insertions(+), 25 deletions(-)
Is everything okay with this series? If yes, I think it would be good to have it included soon into mainline, so that all platforms have time to test these changes to the common xHCI driver.
Would you pick up this series? Or do you want me to pick this up via u-boot-x86 tree?
Gently ping on this.
Applied, thanks.
participants (3)
-
Bin Meng
-
Marek Vasut
-
Stefan Roese