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>
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 89908e8..10f11cd 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -31,7 +31,7 @@
  * @param len	the length of the cache line to be flushed
  * @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);
 
@@ -46,7 +46,7 @@
  * @param len	the length of the cache line to be invalidated
  * @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);
 
@@ -175,7 +175,7 @@
 	BUG_ON(!ptr);
 	memset(ptr, '\0', size);
 
-	xhci_flush_cache((uint32_t)ptr, size);
+	xhci_flush_cache((uintptr_t)ptr, size);
 
 	return ptr;
 }
@@ -400,8 +400,8 @@
 	/* Point to output device context in dcbaa. */
 	ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64;
 
-	xhci_flush_cache((uint32_t)&ctrl->dcbaa->dev_context_ptrs[slot_id],
-							sizeof(__le64));
+	xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[slot_id],
+			 sizeof(__le64));
 	return 0;
 }
 
@@ -478,8 +478,8 @@
 		entry->rsvd = 0;
 		seg = seg->next;
 	}
-	xhci_flush_cache((uint32_t)ctrl->erst.entries,
-			ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
+	xhci_flush_cache((uintptr_t)ctrl->erst.entries,
+			 ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
 
 	deq = (unsigned long)ctrl->event_ring->dequeue;
 
@@ -496,7 +496,7 @@
 	/* this is the event ring segment table pointer */
 	val_64 = xhci_readq(&ctrl->ir_set->erst_base);
 	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);
 
@@ -715,6 +715,6 @@
 
 	/* 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((uint32_t)slot_ctx, sizeof(struct xhci_slot_ctx));
+	xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx));
+	xhci_flush_cache((uintptr_t)slot_ctx, sizeof(struct xhci_slot_ctx));
 }
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b5aade9..f3759d4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -122,8 +122,8 @@
 			next->link.control |= cpu_to_le32(chain);
 
 			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. */
 		if (last_trb_on_last_seg(ctrl, ring,
@@ -191,7 +191,7 @@
 	for (i = 0; i < 4; 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);
 
@@ -244,7 +244,7 @@
 
 		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. */
 		if (last_trb_on_last_seg(ctrl, ep_ring,
@@ -364,7 +364,7 @@
 	else
 		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 */
 	xhci_writel(&ctrl->dba->doorbell[udev->slot_id],
@@ -403,8 +403,8 @@
 {
 	union xhci_trb *event;
 
-	xhci_inval_cache((uint32_t)ctrl->event_ring->dequeue,
-					sizeof(union xhci_trb));
+	xhci_inval_cache((uintptr_t)ctrl->event_ring->dequeue,
+			 sizeof(union xhci_trb));
 
 	event = ctrl->event_ring->dequeue;
 
@@ -576,8 +576,8 @@
 	ep_index = usb_pipe_ep_index(pipe);
 	virt_dev = ctrl->devs[slot_id];
 
-	xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes,
-					virt_dev->out_ctx->size);
+	xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
+			 virt_dev->out_ctx->size);
 
 	ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
 
@@ -644,7 +644,7 @@
 	first_trb = true;
 
 	/* 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 */
 	do {
@@ -722,7 +722,7 @@
 
 	record_transfer_result(udev, event, length);
 	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;
 }
@@ -776,8 +776,8 @@
 			return ret;
 	}
 
-	xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes,
-				virt_dev->out_ctx->size);
+	xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
+			 virt_dev->out_ctx->size);
 
 	struct xhci_ep_ctx *ep_ctx = NULL;
 	ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
@@ -874,7 +874,7 @@
 		trb_fields[2] = length_field;
 		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);
 	}
 
@@ -915,7 +915,7 @@
 
 	/* Invalidate buffer to make it available to usb-core */
 	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))
 			== COMP_SHORT_TX) {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 87f2972..f8b5ce4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -256,7 +256,7 @@
 	virt_dev = ctrl->devs[udev->slot_id];
 	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,
 			   ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP);
 	event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
@@ -325,7 +325,7 @@
 			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 */
 	xhci_slot_copy(ctrl, in_ctx, out_ctx);
@@ -442,8 +442,8 @@
 		 */
 		return ret;
 
-	xhci_inval_cache((uint32_t)virt_dev->out_ctx->bytes,
-				virt_dev->out_ctx->size);
+	xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
+			 virt_dev->out_ctx->size);
 	slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->out_ctx);
 
 	debug("xHC internal address is: %d\n",
@@ -525,7 +525,7 @@
 	ifdesc = &udev->config.if_desc[0];
 
 	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);
 	hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6685ed2..0951e87 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -17,6 +17,7 @@
 #ifndef HOST_XHCI_H_
 #define HOST_XHCI_H_
 
+#include <asm/types.h>
 #include <asm/cache.h>
 #include <asm/io.h>
 #include <linux/list.h>
@@ -1108,20 +1109,28 @@
  */
 static inline u64 xhci_readq(__le64 volatile *regs)
 {
+#if BITS_PER_LONG == 64
+	return readq(regs);
+#else
 	__u32 *ptr = (__u32 *)regs;
 	u64 val_lo = readl(ptr);
 	u64 val_hi = readl(ptr + 1);
 	return val_lo + (val_hi << 32);
+#endif
 }
 
 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 val_lo = lower_32_bits(val);
 	/* FIXME */
 	u32 val_hi = upper_32_bits(val);
 	writel(val_lo, ptr);
 	writel(val_hi, ptr + 1);
+#endif
 }
 
 int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr,
@@ -1242,8 +1251,8 @@
 int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
 		 struct devrequest *req, int length, void *buffer);
 int xhci_check_maxpacket(struct usb_device *udev);
-void xhci_flush_cache(uint32_t addr, u32 type_len);
-void xhci_inval_cache(uint32_t addr, u32 type_len);
+void xhci_flush_cache(uintptr_t addr, u32 type_len);
+void xhci_inval_cache(uintptr_t addr, u32 type_len);
 void xhci_cleanup(struct xhci_ctrl *ctrl);
 struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs);
 int xhci_alloc_virt_device(struct usb_device *udev);