This has the remaining OHCI core tweaks to support two PPC embedded SOC chips, which use non-standard byte order. The only core changes would affect ISO transfers; verified on some USB speakers.
Please merge. - Dave
These are the remaining OHCI core (and Kconfig) updates for big-endian support on STB03xxx and MPC52xx PPC chips. These are the first known implementations with big-endian register and memory layouts. - Two more in-memory fields, related to isochronous transfers have different behavior: HCCA frame number, and ISO TD status. - Kconfig gets new OHCI options, for big-endian and little-endian. The default is little-endian; those PPC platforms can support both the on-chip big-endian version, and little-endian PCI chips. Most of the related ohci core fixes have already been merged. Signed-off-by: Dale Farnsworth <[EMAIL PROTECTED]> Signed-off-by: David Brownell <[EMAIL PROTECTED]> --- 1.10/drivers/usb/host/Kconfig 2004-12-06 11:45:04 -07:00 +++ edited/drivers/usb/host/Kconfig 2005-01-25 12:00:29 -07:00 @@ -7,13 +7,18 @@ default y if ARM # SL-811 default PCI -# many non-PCI hcds implement OHCI +# many non-PCI SOC chips embed OHCI config USB_ARCH_HAS_OHCI boolean + # ARM: default y if SA1111 default y if ARCH_OMAP default y if ARCH_LH7A404 default y if PXA27x + # PPC: + default y if STB03xxx + default y if PPC_MPC52xx + # more: default PCI # @@ -83,6 +88,35 @@ To compile this driver as a module, choose M here: the module will be called ohci-hcd. + +config USB_OHCI_HCD_PPC_SOC + bool "OHCI support for on-chip PPC USB controller" + depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) + default y + select USB_OHCI_BIG_ENDIAN + ---help--- + Enables support for the USB controller on the MPC52xx or + STB03xxx processor chip. If unsure, say Y. + +config USB_OHCI_HCD_PCI + bool "OHCI support for PCI-bus USB controllers" + depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx) + default y + select USB_OHCI_LITTLE_ENDIAN + ---help--- + Enables support for PCI-bus plug-in USB controller cards. + If unsure, say Y. + +config USB_OHCI_BIG_ENDIAN + bool + depends on USB_OHCI_HCD + default n + +config USB_OHCI_LITTLE_ENDIAN + bool + depends on USB_OHCI_HCD + default n if STB03xxx || PPC_MPC52xx + default y config USB_UHCI_HCD tristate "UHCI HCD (most Intel and VIA) support" --- 1.37/drivers/usb/host/ohci-dbg.c 2004-12-18 08:22:52 -07:00 +++ edited/drivers/usb/host/ohci-dbg.c 2005-01-24 10:04:17 -07:00 @@ -328,7 +328,7 @@ hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff, hc32_to_cpup (ohci, &td->hwBE)); for (i = 0; i < MAXPSW; i++) { - u16 psw = hc16_to_cpup (ohci, &td->hwPSW [i]); + u16 psw = ohci_hwPSW (ohci, td, i); int cc = (psw >> 12) & 0x0f; ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i, psw, cc, --- 1.67/drivers/usb/host/ohci-q.c 2004-12-20 18:15:10 -07:00 +++ edited/drivers/usb/host/ohci-q.c 2005-01-24 10:04:17 -07:00 @@ -547,7 +547,8 @@ td->hwINFO = cpu_to_hc32 (ohci, info); if (is_iso) { td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000); - td->hwPSW [0] = cpu_to_hc16 (ohci, (data & 0x0FFF) | 0xE000); + *ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci, + (data & 0x0FFF) | 0xE000); td->ed->last_iso = info & 0xffff; } else { td->hwCBP = cpu_to_hc32 (ohci, data); @@ -719,10 +720,12 @@ /* ISO ... drivers see per-TD length/status */ if (tdINFO & TD_ISO) { - u16 tdPSW = hc16_to_cpu (ohci, td->hwPSW [0]); + u16 tdPSW = ohci_hwPSW (ohci, td, 0); int dlen = 0; - /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */ + /* NOTE: assumes FC in tdINFO == 0, and that + * only the first of 0..MAXPSW psws is used. + */ cc = (tdPSW >> 12) & 0xF; if (tdINFO & TD_CC) /* hc didn't touch? */ --- 1.37/drivers/usb/host/ohci.h 2004-12-18 08:22:52 -07:00 +++ edited/drivers/usb/host/ohci.h 2005-01-24 10:04:18 -07:00 @@ -111,8 +111,10 @@ __hc32 hwNextTD; /* Next TD Pointer */ __hc32 hwBE; /* Memory Buffer End Pointer */ - /* PSW is only for ISO */ -#define MAXPSW 1 /* hardware allows 8 */ + /* PSW is only for ISO. Only 1 PSW entry is used, but on + * big-endian PPC hardware that's the second entry. + */ +#define MAXPSW 2 __hc16 hwPSW [MAXPSW]; /* rest are purely for the driver's use */ @@ -183,7 +185,7 @@ /* * OHCI defines u16 frame_no, followed by u16 zero pad. * Since some processors can't do 16 bit bus accesses, - * portable access must be a 32 bit byteswapped access. + * portable access must be a 32 bits wide. */ __hc32 frame_no; /* current frame number */ __hc32 done_head; /* info returned for an interrupt */ @@ -191,8 +193,6 @@ u8 what [4]; /* spec only identifies 252 bytes :) */ } __attribute__ ((aligned(256))); -#define ohci_frame_no(ohci) ((u16)hc32_to_cpup(ohci,&(ohci)->hcca->frame_no)) - /* * This is the structure of the OHCI controller's memory mapped I/O region. * You must use readl() and writel() (in <asm/io.h>) to access these fields!! @@ -550,6 +550,44 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) { return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x); +} + +/*-------------------------------------------------------------------------*/ + +/* HCCA frame number is 16 bits, but is accessed as 32 bits since not all + * hardware handles 16 bit reads. That creates a different confusion on + * some big-endian SOC implementations. Same thing happens with PSW access. + */ + +#ifdef CONFIG_STB03xxx +#define OHCI_BE_FRAME_NO_SHIFT 16 +#else +#define OHCI_BE_FRAME_NO_SHIFT 0 +#endif + +static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) +{ + u32 tmp; + if (big_endian(ohci)) { + tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); + tmp >>= OHCI_BE_FRAME_NO_SHIFT; + } else + tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no); + + return (u16)tmp; +} + +static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci, + const struct td *td, int index) +{ + return (__hc16 *)(big_endian(ohci) ? + &td->hwPSW[index ^ 1] : &td->hwPSW[index]); +} + +static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci, + const struct td *td, int index) +{ + return hc16_to_cpup(ohci, ohci_hwPSWp(ohci, td, index)); } /*-------------------------------------------------------------------------*/