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