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