USB: UHCI: Add support for big endian descriptors

This patch adds support for universal host controllers that use
big endian descriptors. Support for BE descriptors requires a non-PCI
host controller. For kernels with PCI-only UHCI there should be no
change in behaviour.

This patch tries to replicate the technique used to support BE descriptors
in the EHCI HCD. Parts added to uhci-hcd.h are basically copy'n'paste from
ehci.h.

Signed-off-by: Jan Andersson <jan@gaisler.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 0deeab6..7af2b70 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -78,11 +78,11 @@
 #define   USBPORT1EN		0x01
 #define   USBPORT2EN		0x02
 
-#define UHCI_PTR_BITS		cpu_to_le32(0x000F)
-#define UHCI_PTR_TERM		cpu_to_le32(0x0001)
-#define UHCI_PTR_QH		cpu_to_le32(0x0002)
-#define UHCI_PTR_DEPTH		cpu_to_le32(0x0004)
-#define UHCI_PTR_BREADTH	cpu_to_le32(0x0000)
+#define UHCI_PTR_BITS(uhci)	cpu_to_hc32((uhci), 0x000F)
+#define UHCI_PTR_TERM(uhci)	cpu_to_hc32((uhci), 0x0001)
+#define UHCI_PTR_QH(uhci)	cpu_to_hc32((uhci), 0x0002)
+#define UHCI_PTR_DEPTH(uhci)	cpu_to_hc32((uhci), 0x0004)
+#define UHCI_PTR_BREADTH(uhci)	cpu_to_hc32((uhci), 0x0000)
 
 #define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
 #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
@@ -99,6 +99,22 @@
 
 
 /*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given UHCI_BIG_ENDIAN_DESC), depending on
+ * the host controller implementation.
+ *
+ * To facilitate the strongest possible byte-order checking from "sparse"
+ * and so on, we use __leXX unless that's not practical.
+ */
+#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_DESC
+typedef __u32 __bitwise __hc32;
+typedef __u16 __bitwise __hc16;
+#else
+#define __hc32	__le32
+#define __hc16	__le16
+#endif
+
+/*
  *	Queue Headers
  */
 
@@ -130,8 +146,8 @@
 
 struct uhci_qh {
 	/* Hardware fields */
-	__le32 link;			/* Next QH in the schedule */
-	__le32 element;			/* Queue element (TD) pointer */
+	__hc32 link;			/* Next QH in the schedule */
+	__hc32 element;			/* Queue element (TD) pointer */
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -170,7 +186,8 @@
  */
 #define qh_element(qh)		ACCESS_ONCE((qh)->element)
 
-#define LINK_TO_QH(qh)		(UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
+#define LINK_TO_QH(uhci, qh)	(UHCI_PTR_QH((uhci)) | \
+				cpu_to_hc32((uhci), (qh)->dma_handle))
 
 
 /*
@@ -207,7 +224,7 @@
 /*
  * for TD <info>: (a.k.a. Token)
  */
-#define td_token(td)		le32_to_cpu((td)->token)
+#define td_token(uhci, td)	hc32_to_cpu((uhci), (td)->token)
 #define TD_TOKEN_DEVADDR_SHIFT	8
 #define TD_TOKEN_TOGGLE_SHIFT	19
 #define TD_TOKEN_TOGGLE		(1 << 19)
@@ -240,10 +257,10 @@
  */
 struct uhci_td {
 	/* Hardware fields */
-	__le32 link;
-	__le32 status;
-	__le32 token;
-	__le32 buffer;
+	__hc32 link;
+	__hc32 status;
+	__hc32 token;
+	__hc32 buffer;
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -258,9 +275,10 @@
  * We need a special accessor for the control/status word because it is
  * subject to asynchronous updates by the controller.
  */
-#define td_status(td)		le32_to_cpu(ACCESS_ONCE((td)->status))
+#define td_status(uhci, td)		hc32_to_cpu((uhci), \
+						ACCESS_ONCE((td)->status))
 
-#define LINK_TO_TD(td)		(cpu_to_le32((td)->dma_handle))
+#define LINK_TO_TD(uhci, td)		(cpu_to_hc32((uhci), (td)->dma_handle))
 
 
 /*
@@ -383,7 +401,7 @@
 	spinlock_t lock;
 
 	dma_addr_t frame_dma_handle;	/* Hardware frame list */
-	__le32 *frame;
+	__hc32 *frame;
 	void **frame_cpu;		/* CPU's frame list */
 
 	enum uhci_rh_state rh_state;
@@ -412,6 +430,7 @@
 	unsigned int oc_low:1;			/* OverCurrent bit active low */
 	unsigned int wait_for_hp:1;		/* Wait for HP port reset */
 	unsigned int big_endian_mmio:1;		/* Big endian registers */
+	unsigned int big_endian_desc:1;		/* Big endian descriptors */
 
 	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
@@ -603,4 +622,43 @@
 }
 #endif /* CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC */
 
+/*
+ * The GRLIB GRUSBHC controller can use big endian format for its descriptors.
+ *
+ * UHCI controllers accessed through PCI work normally (little-endian
+ * everywhere), so we don't bother supporting a BE-only mode.
+ */
+#ifdef CONFIG_USB_UHCI_BIG_ENDIAN_DESC
+#define uhci_big_endian_desc(u)		((u)->big_endian_desc)
+
+/* cpu to uhci */
+static inline __hc32 cpu_to_hc32(const struct uhci_hcd *uhci, const u32 x)
+{
+	return uhci_big_endian_desc(uhci)
+		? (__force __hc32)cpu_to_be32(x)
+		: (__force __hc32)cpu_to_le32(x);
+}
+
+/* uhci to cpu */
+static inline u32 hc32_to_cpu(const struct uhci_hcd *uhci, const __hc32 x)
+{
+	return uhci_big_endian_desc(uhci)
+		? be32_to_cpu((__force __be32)x)
+		: le32_to_cpu((__force __le32)x);
+}
+
+#else
+/* cpu to uhci */
+static inline __hc32 cpu_to_hc32(const struct uhci_hcd *uhci, const u32 x)
+{
+	return cpu_to_le32(x);
+}
+
+/* uhci to cpu */
+static inline u32 hc32_to_cpu(const struct uhci_hcd *uhci, const __hc32 x)
+{
+	return le32_to_cpu(x);
+}
+#endif
+
 #endif