[PATCH V3 4/4] USB: UHCI: Support big endian GRUSBHC HC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for big endian GRUSBHC UHCI controllers.
The HCD bus glue will probe the register interface to determine
the endianness of the controller.

Tested on GR-LEON4-ITX board which has a controller with little endian
interface and on custom LEON3 board with a BE controller.

Signed-off-by: Jan Andersson <jan@xxxxxxxxxxx>
---
Changes for V3:
* Updated added comment
* Fixed number of zeros in example after comment from Sergei Shtylyov
Changes for V2:
Updated added comment in uhci-grlib.c
Assign uhci->big_endian_mmio instead of function pointers
---
 drivers/usb/host/Kconfig      |    6 ++++--
 drivers/usb/host/uhci-grlib.c |   16 ++++++++++++++++
 drivers/usb/host/uhci-hcd.h   |   11 ++++++++++-
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 5844248..ab085f1 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -418,11 +418,13 @@ config USB_UHCI_SUPPORT_NON_PCI_HC
 
 config USB_UHCI_BIG_ENDIAN_MMIO
 	bool
-	depends on USB_UHCI_SUPPORT_NON_PCI_HC
+	depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
+	default y
 
 config USB_UHCI_BIG_ENDIAN_DESC
 	bool
-	depends on USB_UHCI_SUPPORT_NON_PCI_HC
+	depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
+	default y
 
 config USB_FHCI_HCD
 	tristate "Freescale QE USB Host Controller support"
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index b1addd6..6519b84 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -25,6 +25,22 @@ static int uhci_grlib_init(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
+	/* Probe to see if we have a big or little endian controller. Bit 7
+	 * of PORTSC is always 1 and 15:13 are always zero, so we have:
+	 *
+	 * 1------- 000----- -------- 000----- => Little endian mode HC
+	 * 000----- 1------- 000----- -------- => Big endian mode HC
+	 *
+	 * We also need to take into account that readl will byte swap.
+	 *
+	 * If we detect a big endian register interface we also assume that
+	 * the controller uses big endian descriptors.
+	 */
+	if (!(uhci_readl(uhci, USBPORTSC1) & 0x80)) {
+		uhci->big_endian_mmio = 1;
+		uhci->big_endian_desc = 1;
+	}
+
 	uhci->rh_numports = uhci_count_ports(hcd);
 
 	/* Set up pointers to to generic functions */
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 7af2b70..72b963b 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -545,9 +545,18 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
 #ifdef CONFIG_USB_UHCI_BIG_ENDIAN_MMIO
 /* Support (non-PCI) big endian host controllers */
 #define uhci_big_endian_mmio(u)		((u)->big_endian_mmio)
+/* Arch-specific big endian read/write functions */
+#if defined(CONFIG_SPARC_LEON)
+#define readl_be(addr)		__raw_readl(addr)
+#define writel_be(val, addr)	__raw_writel(val, addr)
+#define readw_be(addr)		__raw_readw(addr)
+#define writew_be(val, addr)	__raw_writew(val, addr)
+#define readb_be(addr)		__raw_readb(addr)
+#define writeb_be(val, addr)	__raw_writeb(val, addr)
+#endif  /* CONFIG_SPARC_LEON */
 #else
 #define uhci_big_endian_mmio(u)		0
-#endif
+#endif /* CONFIG_USB_UHCI_BIG_ENDIAN_MMIO */
 
 static inline u32 uhci_readl(const struct uhci_hcd *uhci, int reg)
 {
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux