[PATCH 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>
---
 drivers/usb/host/Kconfig      |    6 ++++--
 drivers/usb/host/uhci-grlib.c |   36 +++++++++++++++++++++++++++++-------
 drivers/usb/host/uhci-hcd.h   |   13 ++++++++++++-
 3 files changed, 45 insertions(+), 10 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 004c65a..e32230a 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -25,13 +25,35 @@ static int uhci_grlib_init(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-	/* Assign function pointers that will be used for register accesses */
-	uhci->ureadl = uhci_mmio_readl;
-	uhci->uwritel = uhci_mmio_writel;
-	uhci->ureadw = uhci_mmio_readw;
-	uhci->uwritew = uhci_mmio_writew;
-	uhci->ureadb = uhci_mmio_readb;
-	uhci->uwriteb = uhci_mmio_writeb;
+	/* Assign function pointers that will be used for register accesses.
+	 * 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------- 00------ -------- 00------ => Little endian mode HC
+	 * 00------ -------- 00------ 1------- => 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_mmio_readl(uhci, USBPORTSC1) & 0x80) {
+		uhci->ureadl = uhci_mmio_readl;
+		uhci->uwritel = uhci_mmio_writel;
+		uhci->ureadw = uhci_mmio_readw;
+		uhci->uwritew = uhci_mmio_writew;
+		uhci->ureadb = uhci_mmio_readb;
+		uhci->uwriteb = uhci_mmio_writeb;
+	} else {
+		uhci->ureadl = uhci_mmio_readl_be;
+		uhci->uwritel = uhci_mmio_writel_be;
+		uhci->ureadw = uhci_mmio_readw_be;
+		uhci->uwritew = uhci_mmio_writew_be;
+		uhci->ureadb = uhci_mmio_readb_be;
+		uhci->uwriteb = uhci_mmio_writeb_be;
+
+		uhci->big_endian_desc = 1;
+	}
 
 	uhci->rh_numports = uhci_count_ports(hcd);
 
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 50aa4a8..be6290a 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -635,7 +635,7 @@ static void uhci_pciio_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
 #endif /* defined(CONFIG_PCI) */
 
 #if defined(CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC)
-/* Functions for memory mapped I/O */
+/* Functions for (little endian) memory mapped I/O */
 static u32 uhci_mmio_readl(const struct uhci_hcd *uhci, int reg)
 {
 	return readl(uhci->regs + reg);
@@ -669,6 +669,17 @@ static void uhci_mmio_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
 
 #if defined(CONFIG_USB_UHCI_BIG_ENDIAN_MMIO)
 /* Functions for big endian memory mapped I/O */
+
+/* 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
+
 static u32 uhci_mmio_readl_be(const struct uhci_hcd *uhci, int reg)
 {
 	return readl_be(uhci->regs + 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