summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci.h')
-rw-r--r--drivers/usb/host/ehci.h32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 74dbc6c8228f..5f28b74bb8d3 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -92,6 +92,7 @@ struct ehci_hcd { /* one per controller */
unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
+ unsigned big_endian_mmio:1;
u8 sbrn; /* packed release number */
@@ -651,6 +652,37 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
#define ehci_has_fsl_portno_bug(e) (0)
#endif
+/*
+ * While most USB host controllers implement their registers in
+ * little-endian format, a minority (celleb companion chip) implement
+ * them in big endian format.
+ *
+ * This attempts to support either format at compile time without a
+ * runtime penalty, or both formats with the additional overhead
+ * of checking a flag bit.
+ */
+
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+#define ehci_big_endian_mmio(e) ((e)->big_endian_mmio)
+#else
+#define ehci_big_endian_mmio(e) 0
+#endif
+
+static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
+ __u32 __iomem * regs)
+{
+ return ehci_big_endian_mmio(ehci) ?
+ readl_be((__force u32 *)regs) :
+ readl((__force u32 *)regs);
+}
+
+static inline void ehci_writel (const struct ehci_hcd *ehci,
+ const unsigned int val, __u32 __iomem *regs)
+{
+ ehci_big_endian_mmio(ehci) ?
+ writel_be(val, (__force u32 *)regs) :
+ writel(val, (__force u32 *)regs);
+}
/*-------------------------------------------------------------------------*/