mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 14:41:31 +00:00
usb: 64-bit architectures support for xHCI
This commit allows xHCI to use both 64 and 32 bit memory physical addresses depending on architecture it's being built for. Also it makes use of readq()/writeq() on 64-bit systems Signed-off-by: Sergey Temerkhanov <s.temerkhanov@gmail.com> Signed-off-by: Radha Mohan Chintakuntla <rchintakuntla@cavium.com>
This commit is contained in:
parent
b12242aceb
commit
421a5a0c98
4 changed files with 41 additions and 32 deletions
|
@ -31,7 +31,7 @@
|
||||||
* @param len the length of the cache line to be flushed
|
* @param len the length of the cache line to be flushed
|
||||||
* @return none
|
* @return none
|
||||||
*/
|
*/
|
||||||
void xhci_flush_cache(uint32_t addr, u32 len)
|
void xhci_flush_cache(uintptr_t addr, u32 len)
|
||||||
{
|
{
|
||||||
BUG_ON((void *)addr == NULL || len == 0);
|
BUG_ON((void *)addr == NULL || len == 0);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ void xhci_flush_cache(uint32_t addr, u32 len)
|
||||||
* @param len the length of the cache line to be invalidated
|
* @param len the length of the cache line to be invalidated
|
||||||
* @return none
|
* @return none
|
||||||
*/
|
*/
|
||||||
void xhci_inval_cache(uint32_t addr, u32 len)
|
void xhci_inval_cache(uintptr_t addr, u32 len)
|
||||||
{
|
{
|
||||||
BUG_ON((void *)addr == NULL || len == 0);
|
BUG_ON((void *)addr == NULL || len == 0);
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ static void *xhci_malloc(unsigned int size)
|
||||||
BUG_ON(!ptr);
|
BUG_ON(!ptr);
|
||||||
memset(ptr, '\0', size);
|
memset(ptr, '\0', size);
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)ptr, size);
|
xhci_flush_cache((uintptr_t)ptr, size);
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -400,8 +400,8 @@ int xhci_alloc_virt_device(struct usb_device *udev)
|
||||||
/* Point to output device context in dcbaa. */
|
/* Point to output device context in dcbaa. */
|
||||||
ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64;
|
ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64;
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)&ctrl->dcbaa->dev_context_ptrs[slot_id],
|
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[slot_id],
|
||||||
sizeof(__le64));
|
sizeof(__le64));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,8 +478,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
|
||||||
entry->rsvd = 0;
|
entry->rsvd = 0;
|
||||||
seg = seg->next;
|
seg = seg->next;
|
||||||
}
|
}
|
||||||
xhci_flush_cache((uint32_t)ctrl->erst.entries,
|
xhci_flush_cache((uintptr_t)ctrl->erst.entries,
|
||||||
ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
|
ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
|
||||||
|
|
||||||
deq = (unsigned long)ctrl->event_ring->dequeue;
|
deq = (unsigned long)ctrl->event_ring->dequeue;
|
||||||
|
|
||||||
|
@ -496,7 +496,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
|
||||||
/* this is the event ring segment table pointer */
|
/* this is the event ring segment table pointer */
|
||||||
val_64 = xhci_readq(&ctrl->ir_set->erst_base);
|
val_64 = xhci_readq(&ctrl->ir_set->erst_base);
|
||||||
val_64 &= ERST_PTR_MASK;
|
val_64 &= ERST_PTR_MASK;
|
||||||
val_64 |= ((u32)(ctrl->erst.entries) & ~ERST_PTR_MASK);
|
val_64 |= ((uintptr_t)(ctrl->erst.entries) & ~ERST_PTR_MASK);
|
||||||
|
|
||||||
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
|
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
|
||||||
|
|
||||||
|
@ -715,6 +715,6 @@ void xhci_setup_addressable_virt_dev(struct usb_device *udev)
|
||||||
|
|
||||||
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
|
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)ep0_ctx, sizeof(struct xhci_ep_ctx));
|
xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx));
|
||||||
xhci_flush_cache((uint32_t)slot_ctx, sizeof(struct xhci_slot_ctx));
|
xhci_flush_cache((uintptr_t)slot_ctx, sizeof(struct xhci_slot_ctx));
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,8 +122,8 @@ static void inc_enq(struct xhci_ctrl *ctrl, struct xhci_ring *ring,
|
||||||
next->link.control |= cpu_to_le32(chain);
|
next->link.control |= cpu_to_le32(chain);
|
||||||
|
|
||||||
next->link.control ^= cpu_to_le32(TRB_CYCLE);
|
next->link.control ^= cpu_to_le32(TRB_CYCLE);
|
||||||
xhci_flush_cache((uint32_t)next,
|
xhci_flush_cache((uintptr_t)next,
|
||||||
sizeof(union xhci_trb));
|
sizeof(union xhci_trb));
|
||||||
}
|
}
|
||||||
/* Toggle the cycle bit after the last ring segment. */
|
/* Toggle the cycle bit after the last ring segment. */
|
||||||
if (last_trb_on_last_seg(ctrl, ring,
|
if (last_trb_on_last_seg(ctrl, ring,
|
||||||
|
@ -191,7 +191,7 @@ static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl,
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
trb->field[i] = cpu_to_le32(trb_fields[i]);
|
trb->field[i] = cpu_to_le32(trb_fields[i]);
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)trb, sizeof(struct xhci_generic_trb));
|
xhci_flush_cache((uintptr_t)trb, sizeof(struct xhci_generic_trb));
|
||||||
|
|
||||||
inc_enq(ctrl, ring, more_trbs_coming);
|
inc_enq(ctrl, ring, more_trbs_coming);
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring,
|
||||||
|
|
||||||
next->link.control ^= cpu_to_le32(TRB_CYCLE);
|
next->link.control ^= cpu_to_le32(TRB_CYCLE);
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)next, sizeof(union xhci_trb));
|
xhci_flush_cache((uintptr_t)next, sizeof(union xhci_trb));
|
||||||
|
|
||||||
/* Toggle the cycle bit after the last ring segment. */
|
/* Toggle the cycle bit after the last ring segment. */
|
||||||
if (last_trb_on_last_seg(ctrl, ep_ring,
|
if (last_trb_on_last_seg(ctrl, ep_ring,
|
||||||
|
@ -364,7 +364,7 @@ static void giveback_first_trb(struct usb_device *udev, int ep_index,
|
||||||
else
|
else
|
||||||
start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE);
|
start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE);
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)start_trb, sizeof(struct xhci_generic_trb));
|
xhci_flush_cache((uintptr_t)start_trb, sizeof(struct xhci_generic_trb));
|
||||||
|
|
||||||
/* Ringing EP doorbell here */
|
/* Ringing EP doorbell here */
|
||||||
xhci_writel(&ctrl->dba->doorbell[udev->slot_id],
|
xhci_writel(&ctrl->dba->doorbell[udev->slot_id],
|
||||||
|
@ -403,8 +403,8 @@ static int event_ready(struct xhci_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
union xhci_trb *event;
|
union xhci_trb *event;
|
||||||
|
|
||||||
xhci_inval_cache((uint32_t)ctrl->event_ring->dequeue,
|
xhci_inval_cache((uintptr_t)ctrl->event_ring->dequeue,
|
||||||
sizeof(union xhci_trb));
|
sizeof(union xhci_trb));
|
||||||
|
|
||||||
event = ctrl->event_ring->dequeue;
|
event = ctrl->event_ring->dequeue;
|
||||||
|
|
||||||
|
@ -576,8 +576,8 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
ep_index = usb_pipe_ep_index(pipe);
|
ep_index = usb_pipe_ep_index(pipe);
|
||||||
virt_dev = ctrl->devs[slot_id];
|
virt_dev = ctrl->devs[slot_id];
|
||||||
|
|
||||||
xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes,
|
xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
|
||||||
virt_dev->out_ctx->size);
|
virt_dev->out_ctx->size);
|
||||||
|
|
||||||
ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
|
ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
first_trb = true;
|
first_trb = true;
|
||||||
|
|
||||||
/* flush the buffer before use */
|
/* flush the buffer before use */
|
||||||
xhci_flush_cache((uint32_t)buffer, length);
|
xhci_flush_cache((uintptr_t)buffer, length);
|
||||||
|
|
||||||
/* Queue the first TRB, even if it's zero-length */
|
/* Queue the first TRB, even if it's zero-length */
|
||||||
do {
|
do {
|
||||||
|
@ -722,7 +722,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
|
|
||||||
record_transfer_result(udev, event, length);
|
record_transfer_result(udev, event, length);
|
||||||
xhci_acknowledge_event(ctrl);
|
xhci_acknowledge_event(ctrl);
|
||||||
xhci_inval_cache((uint32_t)buffer, length);
|
xhci_inval_cache((uintptr_t)buffer, length);
|
||||||
|
|
||||||
return (udev->status != USB_ST_NOT_PROC) ? 0 : -1;
|
return (udev->status != USB_ST_NOT_PROC) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
@ -776,8 +776,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes,
|
xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
|
||||||
virt_dev->out_ctx->size);
|
virt_dev->out_ctx->size);
|
||||||
|
|
||||||
struct xhci_ep_ctx *ep_ctx = NULL;
|
struct xhci_ep_ctx *ep_ctx = NULL;
|
||||||
ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
|
ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
|
||||||
|
@ -874,7 +874,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
trb_fields[2] = length_field;
|
trb_fields[2] = length_field;
|
||||||
trb_fields[3] = field | ep_ring->cycle_state;
|
trb_fields[3] = field | ep_ring->cycle_state;
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)buffer, length);
|
xhci_flush_cache((uintptr_t)buffer, length);
|
||||||
queue_trb(ctrl, ep_ring, true, trb_fields);
|
queue_trb(ctrl, ep_ring, true, trb_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,7 +915,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
|
|
||||||
/* Invalidate buffer to make it available to usb-core */
|
/* Invalidate buffer to make it available to usb-core */
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
xhci_inval_cache((uint32_t)buffer, length);
|
xhci_inval_cache((uintptr_t)buffer, length);
|
||||||
|
|
||||||
if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))
|
if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))
|
||||||
== COMP_SHORT_TX) {
|
== COMP_SHORT_TX) {
|
||||||
|
|
|
@ -256,7 +256,7 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change)
|
||||||
virt_dev = ctrl->devs[udev->slot_id];
|
virt_dev = ctrl->devs[udev->slot_id];
|
||||||
in_ctx = virt_dev->in_ctx;
|
in_ctx = virt_dev->in_ctx;
|
||||||
|
|
||||||
xhci_flush_cache((uint32_t)in_ctx->bytes, in_ctx->size);
|
xhci_flush_cache((uintptr_t)in_ctx->bytes, in_ctx->size);
|
||||||
xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0,
|
xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0,
|
||||||
ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP);
|
ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP);
|
||||||
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
|
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
|
||||||
|
@ -325,7 +325,7 @@ static int xhci_set_configuration(struct usb_device *udev)
|
||||||
max_ep_flag = ep_flag;
|
max_ep_flag = ep_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
xhci_inval_cache((uint32_t)out_ctx->bytes, out_ctx->size);
|
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
|
||||||
|
|
||||||
/* slot context */
|
/* slot context */
|
||||||
xhci_slot_copy(ctrl, in_ctx, out_ctx);
|
xhci_slot_copy(ctrl, in_ctx, out_ctx);
|
||||||
|
@ -442,8 +442,8 @@ static int xhci_address_device(struct usb_device *udev)
|
||||||
*/
|
*/
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes,
|
xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
|
||||||
virt_dev->out_ctx->size);
|
virt_dev->out_ctx->size);
|
||||||
slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->out_ctx);
|
slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->out_ctx);
|
||||||
|
|
||||||
debug("xHC internal address is: %d\n",
|
debug("xHC internal address is: %d\n",
|
||||||
|
@ -525,7 +525,7 @@ int xhci_check_maxpacket(struct usb_device *udev)
|
||||||
ifdesc = &udev->config.if_desc[0];
|
ifdesc = &udev->config.if_desc[0];
|
||||||
|
|
||||||
out_ctx = ctrl->devs[slot_id]->out_ctx;
|
out_ctx = ctrl->devs[slot_id]->out_ctx;
|
||||||
xhci_inval_cache((uint32_t)out_ctx->bytes, out_ctx->size);
|
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
|
||||||
|
|
||||||
ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index);
|
ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index);
|
||||||
hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
|
hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef HOST_XHCI_H_
|
#ifndef HOST_XHCI_H_
|
||||||
#define HOST_XHCI_H_
|
#define HOST_XHCI_H_
|
||||||
|
|
||||||
|
#include <asm/types.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
@ -1108,20 +1109,28 @@ static inline void xhci_writel(uint32_t volatile *regs, const unsigned int val)
|
||||||
*/
|
*/
|
||||||
static inline u64 xhci_readq(__le64 volatile *regs)
|
static inline u64 xhci_readq(__le64 volatile *regs)
|
||||||
{
|
{
|
||||||
|
#if BITS_PER_LONG == 64
|
||||||
|
return readq(regs);
|
||||||
|
#else
|
||||||
__u32 *ptr = (__u32 *)regs;
|
__u32 *ptr = (__u32 *)regs;
|
||||||
u64 val_lo = readl(ptr);
|
u64 val_lo = readl(ptr);
|
||||||
u64 val_hi = readl(ptr + 1);
|
u64 val_hi = readl(ptr + 1);
|
||||||
return val_lo + (val_hi << 32);
|
return val_lo + (val_hi << 32);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void xhci_writeq(__le64 volatile *regs, const u64 val)
|
static inline void xhci_writeq(__le64 volatile *regs, const u64 val)
|
||||||
{
|
{
|
||||||
|
#if BITS_PER_LONG == 64
|
||||||
|
writeq(val, regs);
|
||||||
|
#else
|
||||||
__u32 *ptr = (__u32 *)regs;
|
__u32 *ptr = (__u32 *)regs;
|
||||||
u32 val_lo = lower_32_bits(val);
|
u32 val_lo = lower_32_bits(val);
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
u32 val_hi = upper_32_bits(val);
|
u32 val_hi = upper_32_bits(val);
|
||||||
writel(val_lo, ptr);
|
writel(val_lo, ptr);
|
||||||
writel(val_hi, ptr + 1);
|
writel(val_hi, ptr + 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr,
|
int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr,
|
||||||
|
@ -1242,8 +1251,8 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
||||||
struct devrequest *req, int length, void *buffer);
|
struct devrequest *req, int length, void *buffer);
|
||||||
int xhci_check_maxpacket(struct usb_device *udev);
|
int xhci_check_maxpacket(struct usb_device *udev);
|
||||||
void xhci_flush_cache(uint32_t addr, u32 type_len);
|
void xhci_flush_cache(uintptr_t addr, u32 type_len);
|
||||||
void xhci_inval_cache(uint32_t addr, u32 type_len);
|
void xhci_inval_cache(uintptr_t addr, u32 type_len);
|
||||||
void xhci_cleanup(struct xhci_ctrl *ctrl);
|
void xhci_cleanup(struct xhci_ctrl *ctrl);
|
||||||
struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs);
|
struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs);
|
||||||
int xhci_alloc_virt_device(struct usb_device *udev);
|
int xhci_alloc_virt_device(struct usb_device *udev);
|
||||||
|
|
Loading…
Add table
Reference in a new issue