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));
}
/*-------------------------------------------------------------------------*/