[PATCH 1/2] EHCI big endian data structures support (for 440EPx) 2nd try

Stefan Roese <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
This patch implements supports for EHCI controllers whose in-memory
data structures are represented in big-endian format. This is needed
(unfortunately) for the AMCC PPC440EPx SoC EHCI controller.

The guts of the patch are to introduce the hc32 type and change all
references from le32 to hc32. All access routines are converted from
cpu_to_le32(...) to cpu_to_hc32(ehci, ...) and similar for the other
"direction".

(Sorry, first try was line wrapped)

Signed-off-by: Stefan Roese <[email protected]>

---
commit d09a2a98cea958672fee269cc5e35e66570492c5
tree 596e465cf03c0a0005969a9f3e3695cd6d041efa
parent 2e175a90047a2dbc76fde169c990164895b25dfc
author Stefan Roese <[email protected]> Tue, 03 Apr 2007 10:34:21 +0200
committer Stefan Roese <[email protected]> Tue, 03 Apr 2007 10:34:21 +0200

 drivers/usb/host/Kconfig      |    5 +
 drivers/usb/host/ehci-dbg.c   |   94 ++++++++++++------------
 drivers/usb/host/ehci-hcd.c   |   13 ++-
 drivers/usb/host/ehci-mem.c   |    5 +
 drivers/usb/host/ehci-q.c     |   70 +++++++++---------
 drivers/usb/host/ehci-sched.c |  138 +++++++++++++++++++-----------------
 drivers/usb/host/ehci.h       |  159 +++++++++++++++++++++++++++++------------
 7 files changed, 282 insertions(+), 202 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6271187..a8faff6 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -72,6 +72,11 @@ config USB_EHCI_BIG_ENDIAN_MMIO
 	depends on USB_EHCI_HCD
 	default n
 
+config USB_EHCI_BIG_ENDIAN_DESC
+	bool
+	depends on USB_EHCI_HCD
+	default n
+
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
 	depends on USB
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 43eddae..48895c5 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -119,16 +119,16 @@ static void __attribute__((__unused__))
 dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
 	ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-		le32_to_cpup (&qtd->hw_next),
-		le32_to_cpup (&qtd->hw_alt_next),
-		le32_to_cpup (&qtd->hw_token),
-		le32_to_cpup (&qtd->hw_buf [0]));
+		  hc32_to_cpup (ehci, &qtd->hw_next),
+		  hc32_to_cpup (ehci, &qtd->hw_alt_next),
+		  hc32_to_cpup (ehci, &qtd->hw_token),
+		  hc32_to_cpup (ehci, &qtd->hw_buf [0]));
 	if (qtd->hw_buf [1])
 		ehci_dbg (ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-			le32_to_cpup (&qtd->hw_buf [1]),
-			le32_to_cpup (&qtd->hw_buf [2]),
-			le32_to_cpup (&qtd->hw_buf [3]),
-			le32_to_cpup (&qtd->hw_buf [4]));
+			  hc32_to_cpup (ehci, &qtd->hw_buf [1]),
+			  hc32_to_cpup (ehci, &qtd->hw_buf [2]),
+			  hc32_to_cpup (ehci, &qtd->hw_buf [3]),
+			  hc32_to_cpup (ehci, &qtd->hw_buf [4]));
 }
 
 static void __attribute__((__unused__))
@@ -144,26 +144,26 @@ static void __attribute__((__unused__))
 dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
 	ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
-		label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
+		label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), itd->urb);
 	ehci_dbg (ehci,
 		"  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-		le32_to_cpu(itd->hw_transaction[0]),
-		le32_to_cpu(itd->hw_transaction[1]),
-		le32_to_cpu(itd->hw_transaction[2]),
-		le32_to_cpu(itd->hw_transaction[3]),
-		le32_to_cpu(itd->hw_transaction[4]),
-		le32_to_cpu(itd->hw_transaction[5]),
-		le32_to_cpu(itd->hw_transaction[6]),
-		le32_to_cpu(itd->hw_transaction[7]));
+		hc32_to_cpu(ehci, itd->hw_transaction[0]),
+		hc32_to_cpu(ehci, itd->hw_transaction[1]),
+		hc32_to_cpu(ehci, itd->hw_transaction[2]),
+		hc32_to_cpu(ehci, itd->hw_transaction[3]),
+		hc32_to_cpu(ehci, itd->hw_transaction[4]),
+		hc32_to_cpu(ehci, itd->hw_transaction[5]),
+		hc32_to_cpu(ehci, itd->hw_transaction[6]),
+		hc32_to_cpu(ehci, itd->hw_transaction[7]));
 	ehci_dbg (ehci,
 		"  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
-		le32_to_cpu(itd->hw_bufp[0]),
-		le32_to_cpu(itd->hw_bufp[1]),
-		le32_to_cpu(itd->hw_bufp[2]),
-		le32_to_cpu(itd->hw_bufp[3]),
-		le32_to_cpu(itd->hw_bufp[4]),
-		le32_to_cpu(itd->hw_bufp[5]),
-		le32_to_cpu(itd->hw_bufp[6]));
+		hc32_to_cpu(ehci, itd->hw_bufp[0]),
+		hc32_to_cpu(ehci, itd->hw_bufp[1]),
+		hc32_to_cpu(ehci, itd->hw_bufp[2]),
+		hc32_to_cpu(ehci, itd->hw_bufp[3]),
+		hc32_to_cpu(ehci, itd->hw_bufp[4]),
+		hc32_to_cpu(ehci, itd->hw_bufp[5]),
+		hc32_to_cpu(ehci, itd->hw_bufp[6]));
 	ehci_dbg (ehci, "  index: %d %d %d %d %d %d %d %d\n",
 		itd->index[0], itd->index[1], itd->index[2],
 		itd->index[3], itd->index[4], itd->index[5],
@@ -174,14 +174,14 @@ static void __attribute__((__unused__))
 dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
 	ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
-		label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
+		label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), sitd->urb);
 	ehci_dbg (ehci,
 		"  addr %08x sched %04x result %08x buf %08x %08x\n",
-		le32_to_cpu(sitd->hw_fullspeed_ep),
-		le32_to_cpu(sitd->hw_uframe),
-		le32_to_cpu(sitd->hw_results),
-		le32_to_cpu(sitd->hw_buf [0]),
-		le32_to_cpu(sitd->hw_buf [1]));
+		hc32_to_cpu(ehci, sitd->hw_fullspeed_ep),
+		hc32_to_cpu(ehci, sitd->hw_uframe),
+		hc32_to_cpu(ehci, sitd->hw_results),
+		hc32_to_cpu(ehci, sitd->hw_buf [0]),
+		hc32_to_cpu(ehci, sitd->hw_buf [1]));
 }
 
 static int __attribute__((__unused__))
@@ -332,9 +332,9 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
 		default: tmp = '?'; break; \
 		}; tmp; })
 
-static inline char token_mark (__le32 token)
+static inline char token_mark (struct ehci_hcd *ehci, __hc32 token)
 {
-	__u32 v = le32_to_cpu (token);
+	__u32 v = hc32_to_cpu (ehci, token);
 	if (v & QTD_STS_ACTIVE)
 		return '*';
 	if (v & QTD_STS_HALT)
@@ -364,7 +364,7 @@ static void qh_lines (
 	if (qh->hw_qtd_next == EHCI_LIST_END)	/* NEC does this */
 		mark = '@';
 	else
-		mark = token_mark (qh->hw_token);
+		mark = token_mark (ehci, qh->hw_token);
 	if (mark == '/') {	/* qh_alt_next controls qh advance? */
 		if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
 			mark = '#';	/* blocked */
@@ -372,29 +372,29 @@ static void qh_lines (
 			mark = '.';	/* use hw_qtd_next */
 		/* else alt_next points to some other qtd */
 	}
-	scratch = le32_to_cpup (&qh->hw_info1);
-	hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
+	scratch = hc32_to_cpup (ehci, &qh->hw_info1);
+	hw_curr = (mark == '*') ? hc32_to_cpup (ehci, &qh->hw_current) : 0;
 	temp = scnprintf (next, size,
 			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
 			(scratch >> 8) & 0x000f,
-			scratch, le32_to_cpup (&qh->hw_info2),
-			le32_to_cpup (&qh->hw_token), mark,
-			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
+			scratch, hc32_to_cpup (ehci, &qh->hw_info2),
+			hc32_to_cpup (ehci, &qh->hw_token), mark,
+			(cpu_to_hc32 (ehci, QTD_TOGGLE) & qh->hw_token)
 				? "data1" : "data0",
-			(le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
+			(hc32_to_cpup (ehci, &qh->hw_alt_next) >> 1) & 0x0f);
 	size -= temp;
 	next += temp;
 
 	/* hc may be modifying the list as we read it ... */
 	list_for_each (entry, &qh->qtd_list) {
 		td = list_entry (entry, struct ehci_qtd, qtd_list);
-		scratch = le32_to_cpup (&td->hw_token);
+		scratch = hc32_to_cpup (ehci, &td->hw_token);
 		mark = ' ';
 		if (hw_curr == td->qtd_dma)
 			mark = '*';
-		else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma))
+		else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
 			mark = '+';
 		else if (QTD_LENGTH (scratch)) {
 			if (td->hw_alt_next == ehci->async->hw_alt_next)
@@ -490,7 +490,7 @@ show_periodic (struct class_device *class_dev, char *buf)
 	unsigned		temp, size, seen_count;
 	char			*next;
 	unsigned		i;
-	__le32			tag;
+	__hc32			tag;
 
 	if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
 		return 0;
@@ -521,11 +521,11 @@ show_periodic (struct class_device *class_dev, char *buf)
 		next += temp;
 
 		do {
-			switch (tag) {
+			switch (hc32_to_cpu(ehci, tag)) {
 			case Q_TYPE_QH:
 				temp = scnprintf (next, size, " qh%d-%04x/%p",
 						p.qh->period,
-						le32_to_cpup (&p.qh->hw_info2)
+						hc32_to_cpup (ehci, &p.qh->hw_info2)
 							/* uframe masks */
 							& (QH_CMASK | QH_SMASK),
 						p.qh);
@@ -543,7 +543,7 @@ show_periodic (struct class_device *class_dev, char *buf)
 				}
 				/* show more info the first time around */
 				if (temp == seen_count && p.ptr) {
-					u32	scratch = le32_to_cpup (
+					u32	scratch = hc32_to_cpup (ehci,
 							&p.qh->hw_info1);
 					struct ehci_qtd	*qtd;
 					char		*type = "";
@@ -554,7 +554,7 @@ show_periodic (struct class_device *class_dev, char *buf)
 							&p.qh->qtd_list,
 							qtd_list) {
 						temp++;
-						switch (0x03 & (le32_to_cpu (
+						switch (0x03 & (hc32_to_cpu (ehci,
 							qtd->hw_token) >> 8)) {
 						case 0: type = "out"; continue;
 						case 1: type = "in"; continue;
@@ -597,7 +597,7 @@ show_periodic (struct class_device *class_dev, char *buf)
 				temp = scnprintf (next, size,
 					" sitd%d-%04x/%p",
 					p.sitd->stream->interval,
-					le32_to_cpup (&p.sitd->hw_uframe)
+					hc32_to_cpup (ehci, &p.sitd->hw_uframe)
 						& 0x0000ffff,
 					p.sitd);
 				tag = Q_NEXT_TYPE (p.sitd->hw_next);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a740564..be3685c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -471,12 +471,12 @@ static int ehci_init(struct usb_hcd *hcd)
 	 * from automatically advancing to the next td after short reads.
 	 */
 	ehci->async->qh_next.qh = NULL;
-	ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
-	ehci->async->hw_info1 = cpu_to_le32(QH_HEAD);
-	ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT);
+	ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
+	ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
+	ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
 	ehci->async->hw_qtd_next = EHCI_LIST_END;
 	ehci->async->qh_state = QH_STATE_LINKED;
-	ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma);
+	ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
 
 	/* clear interrupt enables, set irq latency */
 	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -940,6 +940,11 @@ MODULE_LICENSE ("GPL");
 #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_sb_driver
 #endif
 
+#ifdef CONFIG_440EPX
+#include "ehci-ppc-soc.c"
+#define	PLATFORM_DRIVER		ehci_ppc_soc_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER)
 #error "missing bus glue for ehci-hcd"
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index a8ba2e1..2d9ace5 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -35,7 +35,8 @@
 
 /* Allocate the key transfer structures from the previously allocated pool */
 
-static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
+static inline void ehci_qtd_init (struct ehci_hcd *ehci, struct ehci_qtd *qtd,
+				  dma_addr_t dma)
 {
 	memset (qtd, 0, sizeof *qtd);
 	qtd->qtd_dma = dma;
@@ -52,7 +53,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
 
 	qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
 	if (qtd != NULL) {
-		ehci_qtd_init (qtd, dma);
+		ehci_qtd_init (ehci, qtd, dma);
 	}
 	return qtd;
 }
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index e7fbbd0..a4f5e05 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -43,15 +43,15 @@
 /* fill a qtd, returning how much of the buffer we were able to queue up */
 
 static int
-qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
-		int token, int maxpacket)
+qtd_fill (struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf,
+	  size_t len, int token, int maxpacket)
 {
 	int	i, count;
 	u64	addr = buf;
 
 	/* one buffer entry per 4K ... first might be short or unaligned */
-	qtd->hw_buf [0] = cpu_to_le32 ((u32)addr);
-	qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32));
+	qtd->hw_buf [0] = cpu_to_hc32 (ehci, (u32)addr);
+	qtd->hw_buf_hi [0] = cpu_to_hc32 (ehci, (u32)(addr >> 32));
 	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
 	if (likely (len < count))		/* ... iff needed */
 		count = len;
@@ -62,8 +62,8 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
 		/* per-qtd limit: from 16K to 20K (best alignment) */
 		for (i = 1; count < len && i < 5; i++) {
 			addr = buf;
-			qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
-			qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
+			qtd->hw_buf [i] = cpu_to_hc32 (ehci, (u32)addr);
+			qtd->hw_buf_hi [i] = cpu_to_hc32 (ehci, (u32)(addr >> 32));
 			buf += 0x1000;
 			if ((count + 0x1000) < len)
 				count += 0x1000;
@@ -75,7 +75,7 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
 		if (count != len)
 			count -= (count % maxpacket);
 	}
-	qtd->hw_token = cpu_to_le32 ((count << 16) | token);
+	qtd->hw_token = cpu_to_hc32 (ehci, (count << 16) | token);
 	qtd->length = count;
 
 	return count;
@@ -89,7 +89,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 	/* writes to an active overlay are unsafe */
 	BUG_ON(qh->qh_state != QH_STATE_IDLE);
 
-	qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
+	qh->hw_qtd_next = QTD_NEXT (ehci, qtd->qtd_dma);
 	qh->hw_alt_next = EHCI_LIST_END;
 
 	/* Except for control endpoints, we make hardware maintain data
@@ -97,20 +97,20 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 	 * and set the pseudo-toggle in udev. Only usb_clear_halt() will
 	 * ever clear it.
 	 */
-	if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) {
+	if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
 		unsigned	is_out, epnum;
 
-		is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
-		epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
+		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+		epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
 		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
-			qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
+			qh->hw_token &= ~cpu_to_hc32 (ehci, QTD_TOGGLE);
 			usb_settoggle (qh->dev, epnum, is_out, 1);
 		}
 	}
 
 	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
 	wmb ();
-	qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
+	qh->hw_token &= cpu_to_hc32 (ehci, QTD_TOGGLE | QTD_STS_PING);
 }
 
 /* if it weren't for a common silicon quirk (writing the dummy into the qh
@@ -128,7 +128,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		qtd = list_entry (qh->qtd_list.next,
 				struct ehci_qtd, qtd_list);
 		/* first qtd may already be partially processed */
-		if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current)
+		if (cpu_to_hc32 (ehci, qtd->qtd_dma) == qh->hw_current)
 			qtd = NULL;
 	}
 
@@ -222,7 +222,7 @@ __acquires(ehci->lock)
 		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
 
 		/* S-mask in a QH means it's an interrupt urb */
-		if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
+		if ((qh->hw_info2 & cpu_to_hc32 (ehci, QH_SMASK)) != 0) {
 
 			/* ... update hc-wide periodic stats (for usbfs) */
 			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -277,7 +277,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
  * Chases up to qh->hw_current.  Returns number of completions called,
  * indicating how much "real" work we did.
  */
-#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
+#define HALT_BIT cpu_to_hc32(ehci, QTD_STS_HALT)
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
@@ -330,7 +330,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 		/* hardware copies qtd out of qh overlay */
 		rmb ();
-		token = le32_to_cpu (qtd->hw_token);
+		token = hc32_to_cpu (ehci, qtd->hw_token);
 
 		/* always clean up qtds the hc de-activated */
 		if ((token & QTD_STS_ACTIVE) == 0) {
@@ -374,9 +374,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 			/* token in overlay may be most current */
 			if (state == QH_STATE_IDLE
-					&& cpu_to_le32 (qtd->qtd_dma)
+					&& cpu_to_hc32 (ehci, qtd->qtd_dma)
 						== qh->hw_current)
-				token = le32_to_cpu (qh->hw_token);
+				token = hc32_to_cpu (ehci, qh->hw_token);
 
 			/* force halt for unlinked or blocked qh, so we'll
 			 * patch the qh later and so that completions can't
@@ -428,7 +428,7 @@ halt:
 			/* should be rare for periodic transfers,
 			 * except maybe high bandwidth ...
 			 */
-			if ((__constant_cpu_to_le32 (QH_SMASK)
+			if ((cpu_to_hc32 (ehci, QH_SMASK)
 					& qh->hw_info2) != 0) {
 				intr_deschedule (ehci, qh);
 				(void) qh_schedule (ehci, qh);
@@ -502,7 +502,7 @@ qh_urb_transaction (
 	is_input = usb_pipein (urb->pipe);
 	if (usb_pipecontrol (urb->pipe)) {
 		/* SETUP pid */
-		qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
+		qtd_fill (ehci, qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
 			token | (2 /* "setup" */ << 8), 8);
 
 		/* ... and always at least one more pid */
@@ -512,7 +512,7 @@ qh_urb_transaction (
 		if (unlikely (!qtd))
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+		qtd_prev->hw_next = QTD_NEXT (ehci, qtd->qtd_dma);
 		list_add_tail (&qtd->qtd_list, head);
 
 		/* for zero length DATA stages, STATUS is always IN */
@@ -539,7 +539,7 @@ qh_urb_transaction (
 	for (;;) {
 		int this_qtd_len;
 
-		this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket);
+		this_qtd_len = qtd_fill (ehci, qtd, buf, len, token, maxpacket);
 		len -= this_qtd_len;
 		buf += this_qtd_len;
 		if (is_input)
@@ -557,7 +557,7 @@ qh_urb_transaction (
 		if (unlikely (!qtd))
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+		qtd_prev->hw_next = QTD_NEXT (ehci, qtd->qtd_dma);
 		list_add_tail (&qtd->qtd_list, head);
 	}
 
@@ -590,17 +590,17 @@ qh_urb_transaction (
 			if (unlikely (!qtd))
 				goto cleanup;
 			qtd->urb = urb;
-			qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+			qtd_prev->hw_next = QTD_NEXT (ehci, qtd->qtd_dma);
 			list_add_tail (&qtd->qtd_list, head);
 
 			/* never any data in such packets */
-			qtd_fill (qtd, 0, 0, token, 0);
+			qtd_fill (ehci, qtd, 0, 0, token, 0);
 		}
 	}
 
 	/* by default, enable interrupt on urb completion */
 	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
-		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
+		qtd->hw_token |= cpu_to_hc32 (ehci, QTD_IOC);
 	return head;
 
 cleanup:
@@ -769,8 +769,8 @@ done:
 
 	/* init as live, toggle clear, advance to dummy */
 	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_info1 = cpu_to_le32 (info1);
-	qh->hw_info2 = cpu_to_le32 (info2);
+	qh->hw_info1 = cpu_to_hc32 (ehci, info1);
+	qh->hw_info2 = cpu_to_hc32 (ehci, info2);
 	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
 	qh_refresh (ehci, qh);
 	return qh;
@@ -782,7 +782,7 @@ done:
 
 static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	__le32		dma = QH_NEXT (qh->qh_dma);
+	__hc32		dma = QH_NEXT (ehci, qh->qh_dma);
 	struct ehci_qh	*head;
 
 	/* (re)start the async schedule? */
@@ -820,7 +820,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 /*-------------------------------------------------------------------------*/
 
-#define	QH_ADDR_MASK	__constant_cpu_to_le32(0x7f)
+#define	QH_ADDR_MASK	cpu_to_hc32(ehci, 0x7f)
 
 /*
  * For control/bulk/interrupt, return QH with these TDs appended.
@@ -867,7 +867,7 @@ static struct ehci_qh *qh_append_tds (
 		if (likely (qtd != NULL)) {
 			struct ehci_qtd		*dummy;
 			dma_addr_t		dma;
-			__le32			token;
+			__hc32			token;
 
 			/* to avoid racing the HC, use the dummy td instead of
 			 * the first td of our list (becomes new dummy).  both
@@ -887,14 +887,14 @@ static struct ehci_qh *qh_append_tds (
 			list_add (&dummy->qtd_list, qtd_list);
 			__list_splice (qtd_list, qh->qtd_list.prev);
 
-			ehci_qtd_init (qtd, qtd->qtd_dma);
+			ehci_qtd_init (ehci, qtd, qtd->qtd_dma);
 			qh->dummy = qtd;
 
 			/* hc must see the new dummy at list end */
 			dma = qtd->qtd_dma;
 			qtd = list_entry (qh->qtd_list.prev,
 					struct ehci_qtd, qtd_list);
-			qtd->hw_next = QTD_NEXT (dma);
+			qtd->hw_next = QTD_NEXT (ehci, dma);
 
 			/* let the hc process these next qtds */
 			wmb ();
@@ -970,7 +970,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 
 	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
 
-	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
+	// qh->hw_next = cpu_to_hc32 (qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_next.qh = NULL;
 	qh_put (qh);			// refcount from reclaim
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 7b5ae71..8805e25 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -44,9 +44,10 @@ static int ehci_get_frame (struct usb_hcd *hcd);
  * @tag: hardware tag for type of this record
  */
 static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
+periodic_next_shadow (struct ehci_hcd *ehci, union ehci_shadow *periodic,
+		      __hc32 tag)
 {
-	switch (tag) {
+	switch (hc32_to_cpu(ehci, tag)) {
 	case Q_TYPE_QH:
 		return &periodic->qh->qh_next;
 	case Q_TYPE_FSTN:
@@ -63,12 +64,12 @@ periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
 static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 {
 	union ehci_shadow	*prev_p = &ehci->pshadow [frame];
-	__le32			*hw_p = &ehci->periodic [frame];
+	__hc32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	here = *prev_p;
 
 	/* find predecessor of "ptr"; hw and shadow lists are in sync */
 	while (here.ptr && here.ptr != ptr) {
-		prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
+		prev_p = periodic_next_shadow (ehci, prev_p, Q_NEXT_TYPE (*hw_p));
 		hw_p = here.hw_next;
 		here = *prev_p;
 	}
@@ -79,7 +80,7 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 	/* update shadow and hardware lists ... the old "next" pointers
 	 * from ptr may still be in use, the caller updates them.
 	 */
-	*prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+	*prev_p = *periodic_next_shadow (ehci, &here, Q_NEXT_TYPE (*hw_p));
 	*hw_p = *here.hw_next;
 }
 
@@ -87,18 +88,18 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 static unsigned short
 periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 {
-	__le32			*hw_p = &ehci->periodic [frame];
+	__hc32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	*q = &ehci->pshadow [frame];
 	unsigned		usecs = 0;
 
 	while (q->ptr) {
-		switch (Q_NEXT_TYPE (*hw_p)) {
+		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE (*hw_p))) {
 		case Q_TYPE_QH:
 			/* is it in the S-mask? */
-			if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
+			if (q->qh->hw_info2 & cpu_to_hc32 (ehci, 1 << uframe))
 				usecs += q->qh->usecs;
 			/* ... or C-mask? */
-			if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
+			if (q->qh->hw_info2 & cpu_to_hc32 (ehci, 1 << (8 + uframe)))
 				usecs += q->qh->c_usecs;
 			hw_p = &q->qh->hw_next;
 			q = &q->qh->qh_next;
@@ -121,9 +122,9 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 			break;
 		case Q_TYPE_SITD:
 			/* is it in the S-mask?  (count SPLIT, DATA) */
-			if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
+			if (q->sitd->hw_uframe & cpu_to_hc32 (ehci, 1 << uframe)) {
 				if (q->sitd->hw_fullspeed_ep &
-						__constant_cpu_to_le32 (1<<31))
+						cpu_to_hc32 (ehci, 1<<31))
 					usecs += q->sitd->stream->usecs;
 				else	/* worst case for OUT start-split */
 					usecs += HS_USECS_ISO (188);
@@ -131,7 +132,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 
 			/* ... C-mask?  (count CSPLIT, DATA) */
 			if (q->sitd->hw_uframe &
-					cpu_to_le32 (1 << (8 + uframe))) {
+					cpu_to_hc32 (ehci, 1 << (8 + uframe))) {
 				/* worst case for IN complete-split */
 				usecs += q->sitd->stream->c_usecs;
 			}
@@ -173,9 +174,9 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
  * will cause a transfer in "B-frame" uframe 0.  "B-frames" lag
  * "H-frames" by 1 uframe.  See the EHCI spec sec 4.5 and figure 4.7.
  */
-static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask)
+static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
 {
-	unsigned char smask = QH_SMASK & le32_to_cpu(mask);
+	unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask);
 	if (!smask) {
 		ehci_err(ehci, "invalid empty smask!\n");
 		/* uframe 7 can't have bw so this will indicate failure */
@@ -217,14 +218,14 @@ periodic_tt_usecs (
 	unsigned short tt_usecs[8]
 )
 {
-	__le32			*hw_p = &ehci->periodic [frame];
+	__hc32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	*q = &ehci->pshadow [frame];
 	unsigned char		uf;
 
 	memset(tt_usecs, 0, 16);
 
 	while (q->ptr) {
-		switch (Q_NEXT_TYPE(*hw_p)) {
+		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(*hw_p))) {
 		case Q_TYPE_ITD:
 			hw_p = &q->itd->hw_next;
 			q = &q->itd->itd_next;
@@ -368,12 +369,12 @@ static int tt_no_collision (
 	 */
 	for (; frame < ehci->periodic_size; frame += period) {
 		union ehci_shadow	here;
-		__le32			type;
+		__hc32			type;
 
 		here = ehci->pshadow [frame];
 		type = Q_NEXT_TYPE (ehci->periodic [frame]);
 		while (here.ptr) {
-			switch (type) {
+			switch (hc32_to_cpu(ehci, type)) {
 			case Q_TYPE_ITD:
 				type = Q_NEXT_TYPE (here.itd->hw_next);
 				here = here.itd->itd_next;
@@ -382,7 +383,7 @@ static int tt_no_collision (
 				if (same_tt (dev, here.qh->dev)) {
 					u32		mask;
 
-					mask = le32_to_cpu (here.qh->hw_info2);
+					mask = hc32_to_cpu (ehci, here.qh->hw_info2);
 					/* "knows" no gap is needed */
 					mask |= mask >> 8;
 					if (mask & uf_mask)
@@ -395,7 +396,7 @@ static int tt_no_collision (
 				if (same_tt (dev, here.sitd->urb->dev)) {
 					u16		mask;
 
-					mask = le32_to_cpu (here.sitd
+					mask = hc32_to_cpu (ehci, here.sitd
 								->hw_uframe);
 					/* FIXME assumes no gap for IN! */
 					mask |= mask >> 8;
@@ -487,7 +488,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	dev_dbg (&qh->dev->dev,
 		"link qh%d-%04x/%p start %d [%d/%d us]\n",
-		period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+		period, hc32_to_cpup (ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
 		qh, qh->start, qh->usecs, qh->c_usecs);
 
 	/* high bandwidth, or otherwise every microframe */
@@ -496,16 +497,16 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	for (i = qh->start; i < ehci->periodic_size; i += period) {
 		union ehci_shadow	*prev = &ehci->pshadow [i];
-		__le32			*hw_p = &ehci->periodic [i];
+		__hc32			*hw_p = &ehci->periodic [i];
 		union ehci_shadow	here = *prev;
-		__le32			type = 0;
+		__hc32			type = 0;
 
 		/* skip the iso nodes at list head */
 		while (here.ptr) {
 			type = Q_NEXT_TYPE (*hw_p);
-			if (type == Q_TYPE_QH)
+			if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
 				break;
-			prev = periodic_next_shadow (prev, type);
+			prev = periodic_next_shadow (ehci, prev, type);
 			hw_p = &here.qh->hw_next;
 			here = *prev;
 		}
@@ -527,7 +528,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 				qh->hw_next = *hw_p;
 			wmb ();
 			prev->qh = qh;
-			*hw_p = QH_NEXT (qh->qh_dma);
+			*hw_p = QH_NEXT (ehci, qh->qh_dma);
 		}
 	}
 	qh->qh_state = QH_STATE_LINKED;
@@ -555,7 +556,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	//   and this qh is active in the current uframe
 	//   (and overlay token SplitXstate is false?)
 	// THEN
-	//   qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */);
+	//   qh->hw_info1 |= __constant_cpu_to_hc32 (1 << 7 /* "ignore" */);
 
 	/* high bandwidth, or otherwise part of every microframe */
 	if ((period = qh->period) == 0)
@@ -572,7 +573,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	dev_dbg (&qh->dev->dev,
 		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
 		qh->period,
-		le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+		hc32_to_cpup (ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
 		qh, qh->start, qh->usecs, qh->c_usecs);
 
 	/* qh->qh_next still "live" to HC */
@@ -598,7 +599,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 	 * active high speed queues may need bigger delays...
 	 */
 	if (list_empty (&qh->qtd_list)
-			|| (__constant_cpu_to_le32 (QH_CMASK)
+			|| (cpu_to_hc32 (ehci, QH_CMASK)
 					& qh->hw_info2) != 0)
 		wait = 2;
 	else
@@ -663,7 +664,7 @@ static int check_intr_schedule (
 	unsigned		frame,
 	unsigned		uframe,
 	const struct ehci_qh	*qh,
-	__le32			*c_maskp
+	__hc32			*c_maskp
 )
 {
 	int		retval = -ENOSPC;
@@ -695,7 +696,7 @@ static int check_intr_schedule (
 
 		retval = 0;
 
-		*c_maskp = cpu_to_le32 (mask << 8);
+		*c_maskp = cpu_to_hc32 (ehci, mask << 8);
 	}
 #else
 	/* Make sure this tt's buffer is also available for CSPLITs.
@@ -706,7 +707,7 @@ static int check_intr_schedule (
 	 * one smart pass...
 	 */
 	mask = 0x03 << (uframe + qh->gap_uf);
-	*c_maskp = cpu_to_le32 (mask << 8);
+	*c_maskp = cpu_to_hc32 (ehci, mask << 8);
 
 	mask |= 1 << uframe;
 	if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
@@ -730,7 +731,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	int		status;
 	unsigned	uframe;
-	__le32		c_mask;
+	__hc32		c_mask;
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 
 	qh_refresh(ehci, qh);
@@ -739,7 +740,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	/* reuse the previous schedule slots, if we can */
 	if (frame < qh->period) {
-		uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+		uframe = ffs (hc32_to_cpup (ehci, &qh->hw_info2) & QH_SMASK);
 		status = check_intr_schedule (ehci, frame, --uframe,
 				qh, &c_mask);
 	} else {
@@ -775,10 +776,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
+		qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
 		qh->hw_info2 |= qh->period
-			? cpu_to_le32 (1 << uframe)
-			: __constant_cpu_to_le32 (QH_SMASK);
+			? cpu_to_hc32 (ehci, 1 << uframe)
+			: cpu_to_hc32 (ehci, QH_SMASK);
 		qh->hw_info2 |= c_mask;
 	} else
 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
@@ -898,9 +899,9 @@ iso_stream_init (
 		buf1 |= maxp;
 		maxp *= multi;
 
-		stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum);
-		stream->buf1 = cpu_to_le32 (buf1);
-		stream->buf2 = cpu_to_le32 (multi);
+		stream->buf0 = cpu_to_hc32 (ehci, (epnum << 8) | dev->devnum);
+		stream->buf1 = cpu_to_hc32 (ehci, buf1);
+		stream->buf2 = cpu_to_hc32 (ehci, multi);
 
 		/* usbfs wants to report the average usecs per frame tied up
 		 * when transfers on this endpoint are scheduled ...
@@ -943,7 +944,7 @@ iso_stream_init (
 		bandwidth /= 1 << (interval + 2);
 
 		/* stream->splits gets created from raw_mask later */
-		stream->address = cpu_to_le32 (addr);
+		stream->address = cpu_to_hc32 (ehci, addr);
 	}
 	stream->bandwidth = bandwidth;
 
@@ -1078,6 +1079,7 @@ iso_sched_alloc (unsigned packets, gfp_t mem_flags)
 
 static inline void
 itd_sched_init (
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_sched	*iso_sched,
 	struct ehci_iso_stream	*stream,
 	struct urb		*urb
@@ -1107,7 +1109,7 @@ itd_sched_init (
 				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
 			trans |= EHCI_ITD_IOC;
 		trans |= length << 16;
-		uframe->transaction = cpu_to_le32 (trans);
+		uframe->transaction = cpu_to_hc32 (ehci, trans);
 
 		/* might need to cross a buffer page within a uframe */
 		uframe->bufp = (buf & ~(u64)0x0fff);
@@ -1149,7 +1151,7 @@ itd_urb_transaction (
 	if (unlikely (sched == NULL))
 		return -ENOMEM;
 
-	itd_sched_init (sched, stream, urb);
+	itd_sched_init (ehci, sched, stream, urb);
 
 	if (urb->interval < 8)
 		num_itds = 1 + (sched->span + 7) / 8;
@@ -1294,7 +1296,7 @@ sitd_slot_ok (
 		uframe += period_uframes;
 	} while (uframe < mod);
 
-	stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7));
+	stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
 	return 1;
 }
 
@@ -1415,7 +1417,8 @@ ready:
 /*-------------------------------------------------------------------------*/
 
 static inline void
-itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
+itd_init (struct ehci_hcd *ehci, struct ehci_iso_stream *stream,
+	  struct ehci_itd *itd)
 {
 	int i;
 
@@ -1433,6 +1436,7 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
 
 static inline void
 itd_patch (
+	struct ehci_hcd		*ehci,
 	struct ehci_itd		*itd,
 	struct ehci_iso_sched	*iso_sched,
 	unsigned		index,
@@ -1448,16 +1452,16 @@ itd_patch (
 	itd->index [uframe] = index;
 
 	itd->hw_transaction [uframe] = uf->transaction;
-	itd->hw_transaction [uframe] |= cpu_to_le32 (pg << 12);
-	itd->hw_bufp [pg] |= cpu_to_le32 (uf->bufp & ~(u32)0);
-	itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));
+	itd->hw_transaction [uframe] |= cpu_to_hc32 (ehci, pg << 12);
+	itd->hw_bufp [pg] |= cpu_to_hc32 (ehci, uf->bufp & ~(u32)0);
+	itd->hw_bufp_hi [pg] |= cpu_to_hc32 (ehci, (u32)(uf->bufp >> 32));
 
 	/* iso_frame_desc[].offset must be strictly increasing */
 	if (unlikely (uf->cross)) {
 		u64	bufp = uf->bufp + 4096;
 		itd->pg = ++pg;
-		itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);
-		itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(bufp >> 32));
+		itd->hw_bufp [pg] |= cpu_to_hc32 (ehci, bufp & ~(u32)0);
+		itd->hw_bufp_hi [pg] |= cpu_to_hc32 (ehci, (u32)(bufp >> 32));
 	}
 }
 
@@ -1470,7 +1474,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
 	ehci->pshadow [frame].itd = itd;
 	itd->frame = frame;
 	wmb ();
-	ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
+	ehci->periodic [frame] = cpu_to_hc32 (ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
 /* fit urb's itds into the selected schedule slot; activate as needed */
@@ -1515,14 +1519,14 @@ itd_link_urb (
 			list_move_tail (&itd->itd_list, &stream->td_list);
 			itd->stream = iso_stream_get (stream);
 			itd->urb = usb_get_urb (urb);
-			itd_init (stream, itd);
+			itd_init (ehci, stream, itd);
 		}
 
 		uframe = next_uframe & 0x07;
 		frame = next_uframe >> 3;
 
 		itd->usecs [uframe] = stream->usecs;
-		itd_patch (itd, iso_sched, packet, uframe);
+		itd_patch (ehci, itd, iso_sched, packet, uframe);
 
 		next_uframe += stream->interval;
 		stream->depth += stream->interval;
@@ -1570,7 +1574,7 @@ itd_complete (
 		urb_index = itd->index[uframe];
 		desc = &urb->iso_frame_desc [urb_index];
 
-		t = le32_to_cpup (&itd->hw_transaction [uframe]);
+		t = hc32_to_cpup (ehci, &itd->hw_transaction [uframe]);
 		itd->hw_transaction [uframe] = 0;
 		stream->depth -= stream->interval;
 
@@ -1701,6 +1705,7 @@ done:
 
 static inline void
 sitd_sched_init (
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_sched	*iso_sched,
 	struct ehci_iso_stream	*stream,
 	struct urb		*urb
@@ -1729,7 +1734,7 @@ sitd_sched_init (
 				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
 			trans |= SITD_IOC;
 		trans |= length << 16;
-		packet->transaction = cpu_to_le32 (trans);
+		packet->transaction = cpu_to_hc32 (ehci, trans);
 
 		/* might need to cross a buffer page within a td */
 		packet->bufp = buf;
@@ -1765,7 +1770,7 @@ sitd_urb_transaction (
 	if (iso_sched == NULL)
 		return -ENOMEM;
 
-	sitd_sched_init (iso_sched, stream, urb);
+	sitd_sched_init (ehci, iso_sched, stream, urb);
 
 	/* allocate/init sITDs */
 	spin_lock_irqsave (&ehci->lock, flags);
@@ -1818,6 +1823,7 @@ sitd_urb_transaction (
 
 static inline void
 sitd_patch (
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_stream	*stream,
 	struct ehci_sitd	*sitd,
 	struct ehci_iso_sched	*iso_sched,
@@ -1834,13 +1840,13 @@ sitd_patch (
 	sitd->hw_backpointer = EHCI_LIST_END;
 
 	bufp = uf->bufp;
-	sitd->hw_buf [0] = cpu_to_le32 (bufp);
-	sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
+	sitd->hw_buf [0] = cpu_to_hc32 (ehci, bufp);
+	sitd->hw_buf_hi [0] = cpu_to_hc32 (ehci, bufp >> 32);
 
-	sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
+	sitd->hw_buf [1] = cpu_to_hc32 (ehci, uf->buf1);
 	if (uf->cross)
 		bufp += 4096;
-	sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
+	sitd->hw_buf_hi [1] = cpu_to_hc32 (ehci, bufp >> 32);
 	sitd->index = index;
 }
 
@@ -1853,7 +1859,7 @@ sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
 	ehci->pshadow [frame].sitd = sitd;
 	sitd->frame = frame;
 	wmb ();
-	ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD;
+	ehci->periodic [frame] = cpu_to_hc32 (ehci, sitd->sitd_dma | Q_TYPE_SITD);
 }
 
 /* fit urb's sitds into the selected schedule slot; activate as needed */
@@ -1881,7 +1887,7 @@ sitd_link_urb (
 			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 			(next_uframe >> 3) % ehci->periodic_size,
-			stream->interval, le32_to_cpu (stream->splits));
+			stream->interval, hc32_to_cpu (ehci, stream->splits));
 		stream->start = jiffies;
 	}
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1902,7 +1908,7 @@ sitd_link_urb (
 		sitd->stream = iso_stream_get (stream);
 		sitd->urb = usb_get_urb (urb);
 
-		sitd_patch (stream, sitd, sched, packet);
+		sitd_patch (ehci, stream, sitd, sched, packet);
 		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
 				sitd);
 
@@ -1940,7 +1946,7 @@ sitd_complete (
 
 	urb_index = sitd->index;
 	desc = &urb->iso_frame_desc [urb_index];
-	t = le32_to_cpup (&sitd->hw_results);
+	t = hc32_to_cpup (ehci, &sitd->hw_results);
 
 	/* report transfer status */
 	if (t & SITD_ERRS) {
@@ -2095,7 +2101,7 @@ scan_periodic (struct ehci_hcd *ehci)
 
 	for (;;) {
 		union ehci_shadow	q, *q_p;
-		__le32			type, *hw_p;
+		__hc32			type, *hw_p;
 		unsigned		uframes;
 
 		/* don't scan past the live uframe */
@@ -2122,7 +2128,7 @@ restart:
 			int			live;
 
 			live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
-			switch (type) {
+			switch (hc32_to_cpu(ehci, type)) {
 			case Q_TYPE_QH:
 				/* handle any completions */
 				temp.qh = qh_get (q.qh);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 46fa57a..0e0bbfa 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -21,6 +21,14 @@
 
 /* definitions used for the EHCI driver */
 
+/*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN), depending on the
+ * host controller implementation.
+ */
+typedef __u32 __bitwise __hc32;
+typedef __u16 __bitwise __hc16;
+
 /* statistics can be kept for for tuning/monitoring */
 struct ehci_stats {
 	/* irq usage */
@@ -64,7 +72,7 @@ struct ehci_hcd {			/* one per controller */
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
 	unsigned		periodic_size;
-	__le32			*periodic;	/* hw periodic table */
+	__hc32			*periodic;	/* hw periodic table */
 	dma_addr_t		periodic_dma;
 	unsigned		i_thresh;	/* uframes HC might cache */
 
@@ -97,6 +105,7 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		no_selective_suspend:1;
 	unsigned		has_fsl_port_bug:1; /* FreeScale */
 	unsigned		big_endian_mmio:1;
+	unsigned		big_endian_desc:1;
 
 	u8			sbrn;		/* packed release number */
 
@@ -303,7 +312,7 @@ struct ehci_dbg_port {
 
 /*-------------------------------------------------------------------------*/
 
-#define	QTD_NEXT(dma)	cpu_to_le32((u32)dma)
+#define	QTD_NEXT(ehci, dma)	cpu_to_hc32(ehci, (u32)dma)
 
 /*
  * EHCI Specification 0.95 Section 3.5
@@ -315,9 +324,9 @@ struct ehci_dbg_port {
  */
 struct ehci_qtd {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;	  /* see EHCI 3.5.1 */
-	__le32			hw_alt_next;      /* see EHCI 3.5.2 */
-	__le32			hw_token;         /* see EHCI 3.5.3 */
+	__hc32			hw_next;	  /* see EHCI 3.5.1 */
+	__hc32			hw_alt_next;      /* see EHCI 3.5.2 */
+	__hc32			hw_token;         /* see EHCI 3.5.3 */
 #define	QTD_TOGGLE	(1 << 31)	/* data toggle */
 #define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
 #define	QTD_IOC		(1 << 15)	/* interrupt on complete */
@@ -331,8 +340,8 @@ struct ehci_qtd {
 #define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
 #define	QTD_STS_STS	(1 << 1)	/* split transaction state */
 #define	QTD_STS_PING	(1 << 0)	/* issue PING? */
-	__le32			hw_buf [5];        /* see EHCI 3.5.4 */
-	__le32			hw_buf_hi [5];        /* Appendix B */
+	__hc32			hw_buf [5];        /* see EHCI 3.5.4 */
+	__hc32			hw_buf_hi [5];        /* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		qtd_dma;		/* qtd address */
@@ -342,26 +351,34 @@ struct ehci_qtd {
 } __attribute__ ((aligned (32)));
 
 /* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
+#define QTD_MASK cpu_to_hc32 (ehci, ~0x1f)
 
 #define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
 
 /*-------------------------------------------------------------------------*/
 
 /* type tag from {qh,itd,sitd,fstn}->hw_next */
-#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_hc32 (ehci, 3 << 1))
 
+/*
+ * Now the following defines are not converted using the
+ * __constant_cpu_to_le32() macro anymore, since we have to support
+ * "dynamic" switching between be and le support, so that the driver
+ * can be used on one system with a be SoC EHCI controller and a
+ * le PCI EHCI controller for example.
+ * Instead the case() input is converted now.
+ */
 /* values for that type tag */
-#define Q_TYPE_ITD	__constant_cpu_to_le32 (0 << 1)
-#define Q_TYPE_QH	__constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD	__constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN	__constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_ITD	(0 << 1)
+#define Q_TYPE_QH	(1 << 1)
+#define Q_TYPE_SITD	(2 << 1)
+#define Q_TYPE_FSTN	(3 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
-#define	QH_NEXT(dma)	(cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
+#define	QH_NEXT(ehci, dma)	(cpu_to_hc32(ehci, ((u32)dma)&~0x01f)|Q_TYPE_QH)
 
 /* for periodic/async schedules and qtd lists, mark end of list */
-#define	EHCI_LIST_END	__constant_cpu_to_le32(1) /* "null pointer" to hw */
+#define	EHCI_LIST_END	cpu_to_hc32(ehci, 1) /* "null pointer" to hw */
 
 /*
  * Entries in periodic shadow table are pointers to one of four kinds
@@ -376,7 +393,7 @@ union ehci_shadow {
 	struct ehci_itd		*itd;		/* Q_TYPE_ITD */
 	struct ehci_sitd	*sitd;		/* Q_TYPE_SITD */
 	struct ehci_fstn	*fstn;		/* Q_TYPE_FSTN */
-	__le32			*hw_next;	/* (all types) */
+	__hc32			*hw_next;	/* (all types) */
 	void			*ptr;
 };
 
@@ -392,23 +409,23 @@ union ehci_shadow {
 
 struct ehci_qh {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;	 /* see EHCI 3.6.1 */
-	__le32			hw_info1;        /* see EHCI 3.6.2 */
+	__hc32			hw_next;	 /* see EHCI 3.6.1 */
+	__hc32			hw_info1;        /* see EHCI 3.6.2 */
 #define	QH_HEAD		0x00008000
-	__le32			hw_info2;        /* see EHCI 3.6.2 */
+	__hc32			hw_info2;        /* see EHCI 3.6.2 */
 #define	QH_SMASK	0x000000ff
 #define	QH_CMASK	0x0000ff00
 #define	QH_HUBADDR	0x007f0000
 #define	QH_HUBPORT	0x3f800000
 #define	QH_MULT		0xc0000000
-	__le32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
+	__hc32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
 
 	/* qtd overlay (hardware parts of a struct ehci_qtd) */
-	__le32			hw_qtd_next;
-	__le32			hw_alt_next;
-	__le32			hw_token;
-	__le32			hw_buf [5];
-	__le32			hw_buf_hi [5];
+	__hc32			hw_qtd_next;
+	__hc32			hw_alt_next;
+	__hc32			hw_token;
+	__hc32			hw_buf [5];
+	__hc32			hw_buf_hi [5];
 
 	/* the rest is HCD-private */
 	dma_addr_t		qh_dma;		/* address of qh */
@@ -445,7 +462,7 @@ struct ehci_qh {
 struct ehci_iso_packet {
 	/* These will be copied to iTD when scheduling */
 	u64			bufp;		/* itd->hw_bufp{,_hi}[pg] |= */
-	__le32			transaction;	/* itd->hw_transaction[i] |= */
+	__hc32			transaction;	/* itd->hw_transaction[i] |= */
 	u8			cross;		/* buf crosses pages */
 	/* for full speed OUT splits */
 	u32			buf1;
@@ -467,8 +484,8 @@ struct ehci_iso_sched {
  */
 struct ehci_iso_stream {
 	/* first two fields match QH, but info1 == 0 */
-	__le32			hw_next;
-	__le32			hw_info1;
+	__hc32			hw_next;
+	__hc32			hw_info1;
 
 	u32			refcount;
 	u8			bEndpointAddress;
@@ -483,7 +500,7 @@ struct ehci_iso_stream {
 	unsigned long		start;		/* jiffies */
 	unsigned long		rescheduled;
 	int			next_uframe;
-	__le32			splits;
+	__hc32			splits;
 
 	/* the rest is derived from the endpoint descriptor,
 	 * trusting urb->interval == f(epdesc->bInterval) and
@@ -497,12 +514,12 @@ struct ehci_iso_stream {
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
-	__le32			buf0;
-	__le32			buf1;
-	__le32			buf2;
+	__hc32			buf0;
+	__hc32			buf1;
+	__hc32			buf2;
 
 	/* this is used to initialize sITD's tt info */
-	__le32			address;
+	__hc32			address;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -515,8 +532,8 @@ struct ehci_iso_stream {
  */
 struct ehci_itd {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;           /* see EHCI 3.3.1 */
-	__le32			hw_transaction [8]; /* see EHCI 3.3.2 */
+	__hc32			hw_next;           /* see EHCI 3.3.1 */
+	__hc32			hw_transaction [8]; /* see EHCI 3.3.2 */
 #define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
 #define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
 #define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
@@ -524,10 +541,10 @@ struct ehci_itd {
 #define	EHCI_ITD_LENGTH(tok)	(((tok)>>16) & 0x0fff)
 #define	EHCI_ITD_IOC		(1 << 15)	/* interrupt on complete */
 
-#define ITD_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
+#define ITD_ACTIVE	cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE)
 
-	__le32			hw_bufp [7];	/* see EHCI 3.3.3 */
-	__le32			hw_bufp_hi [7];	/* Appendix B */
+	__hc32			hw_bufp [7];	/* see EHCI 3.3.3 */
+	__hc32			hw_bufp_hi [7];	/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		itd_dma;	/* for this itd */
@@ -554,11 +571,11 @@ struct ehci_itd {
  */
 struct ehci_sitd {
 	/* first part defined by EHCI spec */
-	__le32			hw_next;
+	__hc32			hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	__le32			hw_fullspeed_ep;	/* EHCI table 3-9 */
-	__le32			hw_uframe;		/* EHCI table 3-10 */
-	__le32			hw_results;		/* EHCI table 3-11 */
+	__hc32			hw_fullspeed_ep;	/* EHCI table 3-9 */
+	__hc32			hw_uframe;		/* EHCI table 3-10 */
+	__hc32			hw_results;		/* EHCI table 3-11 */
 #define	SITD_IOC	(1 << 31)	/* interrupt on completion */
 #define	SITD_PAGE	(1 << 30)	/* buffer 0/1 */
 #define	SITD_LENGTH(x)	(0x3ff & ((x)>>16))
@@ -570,11 +587,11 @@ struct ehci_sitd {
 #define	SITD_STS_MMF	(1 << 2)	/* incomplete split transaction */
 #define	SITD_STS_STS	(1 << 1)	/* split transaction state */
 
-#define SITD_ACTIVE	__constant_cpu_to_le32(SITD_STS_ACTIVE)
+#define SITD_ACTIVE	cpu_to_hc32(ehci, SITD_STS_ACTIVE)
 
-	__le32			hw_buf [2];		/* EHCI table 3-12 */
-	__le32			hw_backpointer;		/* EHCI table 3-13 */
-	__le32			hw_buf_hi [2];		/* Appendix B */
+	__hc32			hw_buf [2];		/* EHCI table 3-12 */
+	__hc32			hw_backpointer;		/* EHCI table 3-13 */
+	__hc32			hw_buf_hi [2];		/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		sitd_dma;
@@ -599,8 +616,8 @@ struct ehci_sitd {
  * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
  */
 struct ehci_fstn {
-	__le32			hw_next;	/* any periodic q entry */
-	__le32			hw_prev;	/* qh or EHCI_LIST_END */
+	__hc32			hw_next;	/* any periodic q entry */
+	__hc32			hw_prev;	/* qh or EHCI_LIST_END */
 
 	/* the rest is HCD-private */
 	dma_addr_t		fstn_dma;
@@ -672,6 +689,19 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 #define ehci_big_endian_mmio(e)		0
 #endif
 
+/*
+ * Big-endian read/write functions are arch-specific.
+ * Other arches can be added if/when they're needed.
+ *
+ * REVISIT: arch/powerpc now has readl/writel_be, so the
+ * definition below can die once the 4xx support is
+ * finally ported over.
+ */
+#if defined(CONFIG_PPC)
+#define readl_be(addr)		in_be32((__force unsigned *)addr)
+#define writel_be(val, addr)	out_be32((__force unsigned *)addr, val)
+#endif
+
 static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
 				       __u32 __iomem * regs)
 {
@@ -696,6 +726,39 @@ static inline void ehci_writel (const struct ehci_hcd *ehci,
 #endif
 }
 
+/*
+ * The AMCC 440EPx not only implements it's EHCI registers in big-endian
+ * format, but also all data structures (descriptors).
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+#define ehci_big_endian_desc(e)		((e)->big_endian_desc)
+#else
+#define ehci_big_endian_desc(e)		0
+#endif
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+	return ehci_big_endian_desc(ehci) ?
+		(__force __hc32)cpu_to_be32(x) :
+		(__force __hc32)cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+	return ehci_big_endian_desc(ehci) ?
+		be32_to_cpu((__force __be32)x) :
+		le32_to_cpu((__force __le32)x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+	return ehci_big_endian_desc(ehci) ?
+		be32_to_cpup((__force __be32 *)x) :
+		le32_to_cpup((__force __le32 *)x);
+}
+
 /*-------------------------------------------------------------------------*/
 
 #ifndef DEBUG

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.