Hi !
I'm sending this patch on behalf of Toshiba. This version of the patch
is mostly for comments, I'll forward a more "final" one as soon as I get
it from them, possibly addressing comments you guys might have.
The goal is to have that in 2.6.20 along with the support for the
platforms that need this (Toshiba Cell based "Celleb" platform, and a
soon-to-be-released-long-awaited other Cell one I can't talk about right
now :-)
The issue is that those have an EHCI/OHCI pair which has big endian
registers but little manipulates DMA data structures in little endian
form (some would say they are only half broken :-)
The OHCI change is trivial. The EHCI change is more invasive as EHCI
didn't have any support for big-endian cells so far, but it's also
pretty much on the trivial side of things, mostly replacing readl/writel
with ehci_readl/ehci_writel.
(Note that the CONFIG_PPC hack in there will go as by the time that
patch hits upstream, I'll expect powerpc to provide writel_be() and
real_be(), the patch is sitting on my disk and ready to go when the
merge window opens).
[Note to Kou Ishizaki-san: This is pretty much an extract from your
patch with only the generic changes slightly reworked to apply on
current -git]
Cheers,
Ben.
Index: linux-cell/drivers/usb/host/Kconfig
===================================================================
--- linux-cell.orig/drivers/usb/host/Kconfig 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/Kconfig 2006-11-05 17:31:44.000000000 +1100
@@ -67,6 +67,11 @@
If unsure, say N.
+config USB_EHCI_BIG_ENDIAN_MMIO
+ bool
+ depends on USB_EHCI_HCD
+ default n
+
config USB_ISP116X_HCD
tristate "ISP116X HCD support"
depends on USB
@@ -126,6 +131,11 @@
default n if STB03xxx || PPC_MPC52xx
default y
+config USB_OHCI_BIG_ENDIAN_MMIO
+ bool
+ depends on USB_OHCI_HCD
+ default n
+
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
depends on USB && PCI
Index: linux-cell/drivers/usb/host/ehci-dbg.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-dbg.c 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci-dbg.c 2006-11-05 17:31:44.000000000
+1100
@@ -43,7 +43,7 @@
*/
static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
{
- u32 params = readl (&ehci->caps->hcs_params);
+ u32 params = ehci_readl(ehci, &ehci->caps->hcs_params);
ehci_dbg (ehci,
"%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n",
@@ -87,7 +87,7 @@
* */
static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
{
- u32 params = readl (&ehci->caps->hcc_params);
+ u32 params = ehci_readl(ehci, &ehci->caps->hcc_params);
if (HCC_ISOC_CACHE (params)) {
ehci_dbg (ehci,
@@ -653,7 +653,7 @@
}
/* Capability Registers */
- i = HC_VERSION(readl (&ehci->caps->hc_capbase));
+ i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
temp = scnprintf (next, size,
"bus %s, device %s (driver " DRIVER_VERSION ")\n"
"%s\n"
@@ -673,7 +673,7 @@
unsigned count = 256/4;
pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
- offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
+ offset = HCC_EXT_CAPS (ehci_readl(ehci,
&ehci->caps->hcc_params));
while (offset && count--) {
pci_read_config_dword (pdev, offset, &cap);
switch (cap & 0xff) {
@@ -704,50 +704,50 @@
#endif
// FIXME interpret both types of params
- i = readl (&ehci->caps->hcs_params);
+ i = ehci_readl(ehci, &ehci->caps->hcs_params);
temp = scnprintf (next, size, "structural params 0x%08x\n", i);
size -= temp;
next += temp;
- i = readl (&ehci->caps->hcc_params);
+ i = ehci_readl(ehci, &ehci->caps->hcc_params);
temp = scnprintf (next, size, "capability params 0x%08x\n", i);
size -= temp;
next += temp;
/* Operational Registers */
temp = dbg_status_buf (scratch, sizeof scratch, label,
- readl (&ehci->regs->status));
+ ehci_readl(ehci, &ehci->regs->status));
temp = scnprintf (next, size, fmt, temp, scratch);
size -= temp;
next += temp;
temp = dbg_command_buf (scratch, sizeof scratch, label,
- readl (&ehci->regs->command));
+ ehci_readl(ehci, &ehci->regs->command));
temp = scnprintf (next, size, fmt, temp, scratch);
size -= temp;
next += temp;
temp = dbg_intr_buf (scratch, sizeof scratch, label,
- readl (&ehci->regs->intr_enable));
+ ehci_readl(ehci, &ehci->regs->intr_enable));
temp = scnprintf (next, size, fmt, temp, scratch);
size -= temp;
next += temp;
temp = scnprintf (next, size, "uframe %04x\n",
- readl (&ehci->regs->frame_index));
+ ehci_readl(ehci, &ehci->regs->frame_index));
size -= temp;
next += temp;
for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {
temp = dbg_port_buf (scratch, sizeof scratch, label, i,
- readl (&ehci->regs->port_status [i - 1]));
+ ehci_readl(ehci, &ehci->regs->port_status [i -
1]));
temp = scnprintf (next, size, fmt, temp, scratch);
size -= temp;
next += temp;
if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {
temp = scnprintf (next, size,
" debug control %08x\n",
- readl (&ehci->debug->control));
+ ehci_readl(ehci,
&ehci->debug->control));
size -= temp;
next += temp;
}
Index: linux-cell/drivers/usb/host/ehci-fsl.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-fsl.c 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci-fsl.c 2006-11-05 17:31:44.000000000
+1100
@@ -177,7 +177,7 @@
case FSL_USB2_PHY_NONE:
break;
}
- writel(portsc, &ehci->regs->port_status[port_offset]);
+ ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
}
static void mpc83xx_usb_setup(struct usb_hcd *hcd)
@@ -214,7 +214,7 @@
}
/* put controller in host mode. */
- writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+ ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
@@ -238,12 +238,12 @@
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
- HC_LENGTH(readl(&ehci->caps->hc_capbase));
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
/* cache this readonly data; minimize chip reads */
- ehci->hcs_params = readl(&ehci->caps->hcs_params);
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
retval = ehci_halt(ehci);
if (retval)
Index: linux-cell/drivers/usb/host/ehci-hcd.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-hcd.c 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci-hcd.c 2006-11-05 17:33:05.000000000
+1100
@@ -152,12 +152,12 @@
* before driver shutdown. But it also seems to be caused by bugs in cardbus
* bridge shutdown: shutting down the bridge before the devices using it.
*/
-static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec)
+static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, u32 mask, u32
done, int usec)
{
u32 result;
do {
- result = readl (ptr);
+ result = ehci_readl(ehci, ptr);
if (result == ~(u32)0) /* card removed */
return -ENODEV;
result &= mask;
@@ -172,18 +172,18 @@
/* force HC to halt state from unknown (EHCI spec section 2.3) */
static int ehci_halt (struct ehci_hcd *ehci)
{
- u32 temp = readl (&ehci->regs->status);
+ u32 temp = ehci_readl(ehci, &ehci->regs->status);
/* disable any irqs left enabled by previous code */
- writel (0, &ehci->regs->intr_enable);
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
if ((temp & STS_HALT) != 0)
return 0;
- temp = readl (&ehci->regs->command);
+ temp = ehci_readl(ehci, &ehci->regs->command);
temp &= ~CMD_RUN;
- writel (temp, &ehci->regs->command);
- return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
+ ehci_writel(ehci, temp, &ehci->regs->command);
+ return handshake (ehci, &ehci->regs->status, STS_HALT, STS_HALT, 16 *
125);
}
/* put TDI/ARC silicon into EHCI mode */
@@ -193,23 +193,23 @@
u32 tmp;
reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
- tmp = readl (reg_ptr);
+ tmp = ehci_readl(ehci, reg_ptr);
tmp |= 0x3;
- writel (tmp, reg_ptr);
+ ehci_writel(ehci, tmp, reg_ptr);
}
/* reset a non-running (STS_HALT == 1) controller */
static int ehci_reset (struct ehci_hcd *ehci)
{
int retval;
- u32 command = readl (&ehci->regs->command);
+ u32 command = ehci_readl(ehci, &ehci->regs->command);
command |= CMD_RESET;
dbg_cmd (ehci, "reset", command);
- writel (command, &ehci->regs->command);
+ ehci_writel(ehci, command, &ehci->regs->command);
ehci_to_hcd(ehci)->state = HC_STATE_HALT;
ehci->next_statechange = jiffies;
- retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+ retval = handshake (ehci, &ehci->regs->command, CMD_RESET, 0, 250 *
1000);
if (retval)
return retval;
@@ -231,21 +231,21 @@
#endif
/* wait for any schedule enables/disables to take effect */
- temp = readl (&ehci->regs->command) << 10;
+ temp = ehci_readl(ehci, &ehci->regs->command) << 10;
temp &= STS_ASS | STS_PSS;
- if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
+ if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
temp, 16 * 125) != 0) {
ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return;
}
/* then disable anything that's still active */
- temp = readl (&ehci->regs->command);
+ temp = ehci_readl(ehci, &ehci->regs->command);
temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
- writel (temp, &ehci->regs->command);
+ ehci_writel(ehci, temp, &ehci->regs->command);
/* hardware can take 16 microframes to turn off ... */
- if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
+ if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
0, 16 * 125) != 0) {
ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return;
@@ -272,11 +272,11 @@
/* lost IAA irqs wedge things badly; seen with a vt8235 */
if (ehci->reclaim) {
- u32 status = readl (&ehci->regs->status);
+ u32 status = ehci_readl (&ehci->regs->status);
if (status & STS_IAA) {
ehci_vdbg (ehci, "lost IAA\n");
COUNT (ehci->stats.lost_iaa);
- writel (STS_IAA, &ehci->regs->status);
+ ehci_writel (STS_IAA, &ehci->regs->status);
ehci->reclaim_ready = 1;
}
}
@@ -304,7 +304,7 @@
(void) ehci_halt (ehci);
/* make BIOS/etc use companion controller during reboot */
- writel (0, &ehci->regs->configured_flag);
+ ehci_writel (0, &ehci->regs->configured_flag);
}
static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -374,11 +374,11 @@
ehci_quiesce (ehci);
ehci_reset (ehci);
- writel (0, &ehci->regs->intr_enable);
+ ehci_writel (0, &ehci->regs->intr_enable);
spin_unlock_irq(&ehci->lock);
/* let companion controllers work when we aren't */
- writel (0, &ehci->regs->configured_flag);
+ ehci_writel (0, &ehci->regs->configured_flag);
remove_debug_files (ehci);
@@ -397,7 +397,7 @@
ehci->stats.complete, ehci->stats.unlink);
#endif
- dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
+ dbg_status (ehci, "ehci_stop completed", ehci_readl(ehci,
&ehci->regs->status));
}
/* one-time init, only for memory state */
@@ -423,7 +423,7 @@
return retval;
/* controllers may cache some of the periodic schedule ... */
- hcc_params = readl(&ehci->caps->hcc_params);
+ hcc_params = ehci_readl(&ehci->caps->hcc_params);
if (HCC_ISOC_CACHE(hcc_params)) // full frame cache
ehci->i_thresh = 8;
else // N microframes cached
@@ -496,8 +496,8 @@
ehci_mem_cleanup(ehci);
return retval;
}
- writel(ehci->periodic_dma, &ehci->regs->frame_list);
- writel((u32)ehci->async->qh_dma, &ehci->regs->async_next);
+ ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
+ ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
/*
* hcc_params controls whether ehci->regs->segment must (!!!)
@@ -511,9 +511,9 @@
* Scsi_Host.highmem_io, and so forth. It's readonly to all
* host side drivers though.
*/
- hcc_params = readl(&ehci->caps->hcc_params);
+ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
if (HCC_64BIT_ADDR(hcc_params)) {
- writel(0, &ehci->regs->segment);
+ ehci_writel(ehci, 0, &ehci->regs->segment);
#if 0
// this is deeply broken on almost all architectures
if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK))
@@ -526,7 +526,7 @@
// root hub will detect new devices (why?); NEC doesn't
ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
ehci->command |= CMD_RUN;
- writel (ehci->command, &ehci->regs->command);
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
dbg_cmd (ehci, "init", ehci->command);
/*
@@ -536,16 +536,16 @@
* and there's no companion controller unless maybe for USB OTG.)
*/
hcd->state = HC_STATE_RUNNING;
- writel (FLAG_CF, &ehci->regs->configured_flag);
- readl (&ehci->regs->command); /* unblock posted writes */
+ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
- temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
+ temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci_info (ehci,
"USB %x.%x started, EHCI %x.%02x, driver %s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
temp >> 8, temp & 0xff, DRIVER_VERSION);
- writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
+ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); /* Turn On
Interrupts */
/* GRR this is run-once init(), being done every time the HC starts.
* So long as they're part of class devices, we can't do it init()
@@ -566,7 +566,7 @@
spin_lock (&ehci->lock);
- status = readl (&ehci->regs->status);
+ status = ehci_readl(ehci, &ehci->regs->status);
/* e.g. cardbus physical eject */
if (status == ~(u32) 0) {
@@ -581,8 +581,8 @@
}
/* clear (just) interrupts */
- writel (status, &ehci->regs->status);
- readl (&ehci->regs->command); /* unblock posted write */
+ ehci_writel(ehci, status, &ehci->regs->status);
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */
bh = 0;
#ifdef EHCI_VERBOSE_DEBUG
@@ -613,12 +613,12 @@
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */
- status = readl (&ehci->regs->command);
+ status = ehci_readl(ehci, &ehci->regs->command);
if (!(status & CMD_RUN))
- writel (status | CMD_RUN, &ehci->regs->command);
+ ehci_writel(ehci, status | CMD_RUN,
&ehci->regs->command);
while (i--) {
- int pstatus = readl (&ehci->regs->port_status [i]);
+ int pstatus = ehci_readl(ehci, &ehci->regs->port_status
[i]);
if (pstatus & PORT_OWNER)
continue;
@@ -639,14 +639,14 @@
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
/* bogus "fatal" IRQs appear on some chips... why? */
- status = readl (&ehci->regs->status);
- dbg_cmd (ehci, "fatal", readl (&ehci->regs->command));
+ status = ehci_readl(ehci, &ehci->regs->status);
+ dbg_cmd (ehci, "fatal", ehci_readl(ehci, &ehci->regs->command));
dbg_status (ehci, "fatal", status);
if (status & STS_HALT) {
ehci_err (ehci, "fatal error\n");
dead:
ehci_reset (ehci);
- writel (0, &ehci->regs->configured_flag);
+ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
/* generic layer kills/unlinks all urbs, then
* uses ehci_stop to clean up the rest
*/
@@ -869,7 +869,7 @@
static int ehci_get_frame (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
+ return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) %
ehci->periodic_size;
}
/*-------------------------------------------------------------------------*/
Index: linux-cell/drivers/usb/host/ehci-hub.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-hub.c 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci-hub.c 2006-11-05 17:34:09.000000000
+1100
@@ -46,7 +46,7 @@
ehci_quiesce (ehci);
hcd->state = HC_STATE_QUIESCING;
}
- ehci->command = readl (&ehci->regs->command);
+ ehci->command = ehci_readl(ehci, &ehci->regs->command);
if (ehci->reclaim)
ehci->reclaim_ready = 1;
ehci_work(ehci);
@@ -54,7 +54,7 @@
/* suspend any active/unsuspended ports, maybe allow wakeup */
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
- u32 t1 = readl (reg) & ~PORT_RWC_BITS;
+ u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
@@ -67,7 +67,7 @@
if (t1 != t2) {
ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
port + 1, t1, t2);
- writel (t2, reg);
+ ehci_writel(ehci, t2, reg);
}
}
@@ -102,45 +102,45 @@
*/
/* re-init operational registers in case we lost power */
- if (readl (&ehci->regs->intr_enable) == 0) {
+ if (ehci_readl (&ehci->regs->intr_enable) == 0) {
/* at least some APM implementations will try to deliver
* IRQs right away, so delay them until we're ready.
*/
intr_enable = 1;
- writel (0, &ehci->regs->segment);
- writel (ehci->periodic_dma, &ehci->regs->frame_list);
- writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
+ ehci_writel (0, &ehci->regs->segment);
+ ehci_writel (ehci->periodic_dma, &ehci->regs->frame_list);
+ ehci_writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
} else
intr_enable = 0;
ehci_dbg(ehci, "resume root hub%s\n",
intr_enable ? " after power loss" : "");
/* restore CMD_RUN, framelist size, and irq threshold */
- writel (ehci->command, &ehci->regs->command);
+ ehci_writel (ehci->command, &ehci->regs->command);
/* take ports out of suspend */
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
- temp = readl (&ehci->regs->port_status [i]);
+ temp = ehci_readl (&ehci->regs->port_status [i]);
temp &= ~(PORT_RWC_BITS
| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
if (temp & PORT_SUSPEND) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
temp |= PORT_RESUME;
}
- writel (temp, &ehci->regs->port_status [i]);
+ ehci_writel (temp, &ehci->regs->port_status [i]);
}
i = HCS_N_PORTS (ehci->hcs_params);
mdelay (20);
while (i--) {
- temp = readl (&ehci->regs->port_status [i]);
+ temp = ehci_readl (&ehci->regs->port_status [i]);
if ((temp & PORT_SUSPEND) == 0)
continue;
temp &= ~(PORT_RWC_BITS | PORT_RESUME);
- writel (temp, &ehci->regs->port_status [i]);
+ ehci_writel (temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
- (void) readl (&ehci->regs->command);
+ (void) ehci_readl (&ehci->regs->command);
/* maybe re-activate the schedule(s) */
temp = 0;
@@ -150,7 +150,7 @@
temp |= CMD_PSE;
if (temp) {
ehci->command |= temp;
- writel (ehci->command, &ehci->regs->command);
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
}
ehci->next_statechange = jiffies + msecs_to_jiffies(5);
@@ -158,7 +158,7 @@
/* Now we can safely re-enable irqs */
if (intr_enable)
- writel (INTR_MASK, &ehci->regs->intr_enable);
+ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock);
return 0;
@@ -200,7 +200,7 @@
// what happens if HCS_N_CC(params) == 0 ?
port_status |= PORT_OWNER;
port_status &= ~PORT_RWC_BITS;
- writel (port_status, &ehci->regs->port_status [index]);
+ ehci_writel(ehci, port_status, &ehci->regs->port_status
[index]);
} else
ehci_dbg (ehci, "port %d high speed\n", index + 1);
@@ -238,13 +238,13 @@
/* port N changes (bit N)? */
spin_lock_irqsave (&ehci->lock, flags);
for (i = 0; i < ports; i++) {
- temp = readl (&ehci->regs->port_status [i]);
+ temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
if (temp & PORT_OWNER) {
/* don't report this in GetPortStatus */
if (temp & PORT_CSC) {
temp &= ~PORT_RWC_BITS;
temp |= PORT_CSC;
- writel (temp, &ehci->regs->port_status [i]);
+ ehci_writel(ehci, temp,
&ehci->regs->port_status [i]);
}
continue;
}
@@ -343,17 +343,17 @@
if (!wIndex || wIndex > ports)
goto error;
wIndex--;
- temp = readl (&ehci->regs->port_status [wIndex]);
+ temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
if (temp & PORT_OWNER)
break;
switch (wValue) {
case USB_PORT_FEAT_ENABLE:
- writel (temp & ~PORT_PE,
+ ehci_writel(ehci, temp & ~PORT_PE,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_ENABLE:
- writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
+ ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_SUSPEND:
@@ -366,7 +366,7 @@
goto error;
/* resume signaling for 20 msec */
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
- writel (temp | PORT_RESUME,
+ ehci_writel(ehci, temp | PORT_RESUME,
&ehci->regs->port_status [wIndex]);
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (20);
@@ -377,15 +377,15 @@
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
- writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
+ ehci_writel(ehci, temp & ~(PORT_RWC_BITS |
PORT_POWER),
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_CONNECTION:
- writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
+ ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
- writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
+ ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_C_RESET:
@@ -394,7 +394,7 @@
default:
goto error;
}
- readl (&ehci->regs->command); /* unblock posted write */
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted write
*/
break;
case GetHubDescriptor:
ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
@@ -410,7 +410,7 @@
goto error;
wIndex--;
status = 0;
- temp = readl (&ehci->regs->port_status [wIndex]);
+ temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
// wPortChange bits
if (temp & PORT_CSC)
@@ -428,10 +428,10 @@
ehci->reset_done [wIndex] = 0;
/* stop resume signaling */
- temp = readl (&ehci->regs->port_status [wIndex]);
- writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
+ temp = ehci_readl(ehci, &ehci->regs->port_status
[wIndex]);
+ ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESUME),
&ehci->regs->port_status [wIndex]);
- retval = handshake (
+ retval = handshake (ehci,
&ehci->regs->port_status [wIndex],
PORT_RESUME, 0, 2000 /* 2msec */);
if (retval != 0) {
@@ -450,12 +450,12 @@
ehci->reset_done [wIndex] = 0;
/* force reset to complete */
- writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
+ ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
&ehci->regs->port_status [wIndex]);
/* REVISIT: some hardware needs 550+ usec to clear
* this bit; seems too long to spin routinely...
*/
- retval = handshake (
+ retval = handshake (ehci,
&ehci->regs->port_status [wIndex],
PORT_RESET, 0, 750);
if (retval != 0) {
@@ -466,7 +466,7 @@
/* see what we found out */
temp = check_reset_complete (ehci, wIndex,
- readl (&ehci->regs->port_status [wIndex]));
+ ehci_readl(ehci, &ehci->regs->port_status
[wIndex]));
}
// don't show wPortStatus if it's owned by a companion hc
@@ -509,7 +509,7 @@
if (!wIndex || wIndex > ports)
goto error;
wIndex--;
- temp = readl (&ehci->regs->port_status [wIndex]);
+ temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
if (temp & PORT_OWNER)
break;
@@ -523,12 +523,12 @@
goto error;
if (device_may_wakeup(&hcd->self.root_hub->dev))
temp |= PORT_WAKE_BITS;
- writel (temp | PORT_SUSPEND,
+ ehci_writel(ehci, temp | PORT_SUSPEND,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params))
- writel (temp | PORT_POWER,
+ ehci_writel(ehci, temp | PORT_POWER,
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_RESET:
@@ -557,12 +557,12 @@
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (50);
}
- writel (temp, &ehci->regs->port_status [wIndex]);
+ ehci_writel(ehci, temp, &ehci->regs->port_status
[wIndex]);
break;
default:
goto error;
}
- readl (&ehci->regs->command); /* unblock posted writes */
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted
writes */
break;
default:
Index: linux-cell/drivers/usb/host/ehci-pci.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-pci.c 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci-pci.c 2006-11-05 17:31:44.000000000
+1100
@@ -38,7 +38,7 @@
if ((temp & (3 << 13)) == (1 << 13)) {
temp &= 0x1fff;
ehci->debug = ehci_to_hcd(ehci)->regs + temp;
- temp = readl(&ehci->debug->control);
+ temp = ehci_readl(ehci, &ehci->debug->control);
ehci_info(ehci, "debug port %d%s\n",
HCS_DEBUG_PORT(ehci->hcs_params),
(temp & DBGP_ENABLED)
@@ -71,8 +71,16 @@
u32 temp;
int retval;
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_TOSHIBA_2:
+ /* celleb's companion chip */
+ if (pdev->device == 0x01b5) {
+ ehci->big_endian_mmio = 1;
+ }
+ break;
+ }
ehci->caps = hcd->regs;
- ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
+ ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
@@ -101,7 +109,7 @@
}
/* cache this readonly data; minimize chip reads */
- ehci->hcs_params = readl(&ehci->caps->hcs_params);
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
retval = ehci_halt(ehci);
if (retval)
@@ -235,8 +243,8 @@
rc = -EINVAL;
goto bail;
}
- writel (0, &ehci->regs->intr_enable);
- (void)readl(&ehci->regs->intr_enable);
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ (void)ehci_readl(ehci, &ehci->regs->intr_enable);
/* make sure snapshot being resumed re-enumerates everything */
if (message.event == PM_EVENT_PRETHAW) {
@@ -270,7 +278,7 @@
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* If CF is clear, we lost PCI Vaux power and need to restart. */
- if (readl(&ehci->regs->configured_flag) != FLAG_CF)
+ if (ehci_readl(ehci, &ehci->regs->configured_flag) != FLAG_CF)
goto restart;
/* If any port is suspended (or owned by the companion),
@@ -280,7 +288,7 @@
for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
u32 status;
port--;
- status = readl(&ehci->regs->port_status [port]);
+ status = ehci_readl(ehci, &ehci->regs->port_status [port]);
if (!(status & PORT_POWER))
continue;
if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
Index: linux-cell/drivers/usb/host/ehci-q.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-q.c 2006-10-21 16:37:03.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci-q.c 2006-11-05 17:31:44.000000000
+1100
@@ -789,13 +789,13 @@
head = ehci->async;
timer_action_done (ehci, TIMER_ASYNC_OFF);
if (!head->qh_next.qh) {
- u32 cmd = readl (&ehci->regs->command);
+ u32 cmd = ehci_readl(ehci, &ehci->regs->command);
if (!(cmd & CMD_ASE)) {
/* in case a clear of CMD_ASE didn't take yet */
- (void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
+ (void) handshake (ehci, &ehci->regs->status, STS_ASS,
0, 150);
cmd |= CMD_ASE | CMD_RUN;
- writel (cmd, &ehci->regs->command);
+ ehci_writel(ehci, cmd, &ehci->regs->command);
ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
/* posted write need not be known to HC yet ... */
}
@@ -1007,7 +1007,7 @@
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
- int cmd = readl (&ehci->regs->command);
+ int cmd = ehci_readl(ehci, &ehci->regs->command);
struct ehci_qh *prev;
#ifdef DEBUG
@@ -1025,7 +1025,7 @@
if (ehci_to_hcd(ehci)->state != HC_STATE_HALT
&& !ehci->reclaim) {
/* ... and CMD_IAAD clear */
- writel (cmd & ~CMD_ASE, &ehci->regs->command);
+ ehci_writel(ehci, cmd & ~CMD_ASE, &ehci->regs->command);
wmb ();
// handshake later, if we need to
timer_action_done (ehci, TIMER_ASYNC_OFF);
@@ -1054,8 +1054,8 @@
ehci->reclaim_ready = 0;
cmd |= CMD_IAAD;
- writel (cmd, &ehci->regs->command);
- (void) readl (&ehci->regs->command);
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+ (void) ehci_readl(ehci, &ehci->regs->command);
timer_action (ehci, TIMER_IAA_WATCHDOG);
}
Index: linux-cell/drivers/usb/host/ehci-sched.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci-sched.c 2006-10-21
16:37:04.000000000 +1000
+++ linux-cell/drivers/usb/host/ehci-sched.c 2006-11-05 17:31:44.000000000
+1100
@@ -433,19 +433,19 @@
/* did clearing PSE did take effect yet?
* takes effect only at frame boundaries...
*/
- status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
+ status = handshake (ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return status;
}
- cmd = readl (&ehci->regs->command) | CMD_PSE;
- writel (cmd, &ehci->regs->command);
+ cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
/* posted write ... PSS happens later */
ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
/* make sure ehci_work scans these */
- ehci->next_uframe = readl (&ehci->regs->frame_index)
+ ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index)
% (ehci->periodic_size << 3);
return 0;
}
@@ -458,14 +458,14 @@
/* did setting PSE not take effect yet?
* takes effect only at frame boundaries...
*/
- status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
+ status = handshake (ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 *
125);
if (status != 0) {
ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return status;
}
- cmd = readl (&ehci->regs->command) & ~CMD_PSE;
- writel (cmd, &ehci->regs->command);
+ cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
/* posted write ... */
ehci->next_uframe = -1;
@@ -1336,7 +1336,7 @@
goto fail;
}
- now = readl (&ehci->regs->frame_index) % mod;
+ now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
/* when's the last uframe this urb could start? */
max = now + mod;
@@ -2088,7 +2088,7 @@
*/
now_uframe = ehci->next_uframe;
if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
- clock = readl (&ehci->regs->frame_index);
+ clock = ehci_readl(ehci, &ehci->regs->frame_index);
else
clock = now_uframe + mod - 1;
clock %= mod;
@@ -2213,7 +2213,7 @@
if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
break;
ehci->next_uframe = now_uframe;
- now = readl (&ehci->regs->frame_index) % mod;
+ now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
if (now_uframe == now)
break;
Index: linux-cell/drivers/usb/host/ehci.h
===================================================================
--- linux-cell.orig/drivers/usb/host/ehci.h 2006-10-21 16:37:04.000000000
+1000
+++ linux-cell/drivers/usb/host/ehci.h 2006-11-05 17:31:44.000000000 +1100
@@ -91,6 +91,7 @@
unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
+ unsigned big_endian_mmio:1; /* for celleb_scc */
u8 sbrn; /* packed release number */
@@ -653,6 +654,59 @@
/*-------------------------------------------------------------------------*/
+/*
+ * While most USB host controllers implement their registers in
+ * little-endian format, a minority (celleb companion chip) implement
+ * them in big endian format.
+ *
+ * This attempts to support either format at compile time without a
+ * runtime penalty, or both formats with the additional overhead
+ * of checking a flag bit.
+ */
+
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+
+#define ehci_big_endian(e) ((e)->big_endian_mmio)
+
+/*
+ * Big-endian read/write functions are arch-specific.
+ * Other arches can be added if/when they're needed.
+ */
+#if defined(CONFIG_PPC)
+#define readl_be(addr) in_be32((__force unsigned *)addr)
+#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)
+#endif
+
+static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
+ __u32 __iomem * regs)
+{
+ return ehci_big_endian(ehci) ? readl_be (regs) : readl ((__force u32
*)regs);
+}
+
+static inline void ehci_writel (const struct ehci_hcd *ehci,
+ const unsigned int val, __u32 __iomem *regs)
+{
+ ehci_big_endian(ehci) ? writel_be (val, regs) :
+ writel (val, (__force u32 *)regs);
+}
+
+#else /* !CONFIG_USB_EHCI_BIG_ENDIAN_MMIO */
+
+static inline unsigned int
+ehci_readl (const struct ehci_hcd *ehci, __u32 __iomem * regs)
+{
+ return readl(regs);
+}
+
+static inline void ehci_writel (const struct ehci_hcd *ehci,
+ const unsigned int val, __u32 __iomem *regs)
+{
+ writel (val, regs);
+}
+#endif /* !CONFIG_USB_EHCI_BIG_ENDIAN_MMIO */
+
+/*-------------------------------------------------------------------------*/
+
#ifndef DEBUG
#define STUB_DEBUG_FILES
#endif /* DEBUG */
Index: linux-cell/drivers/usb/host/ohci-pci.c
===================================================================
--- linux-cell.orig/drivers/usb/host/ohci-pci.c 2006-10-21 16:37:04.000000000
+1000
+++ linux-cell/drivers/usb/host/ohci-pci.c 2006-11-05 17:31:44.000000000
+1100
@@ -25,6 +25,22 @@
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+ if (hcd->self.controller) {
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ /* for TOSHIBA CELLEB
+ *
+ *
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_TOSHIBA_2
+ && pdev->device == 0x01b6) {
+ ohci->flags |= OHCI_BIG_ENDIAN_MMIO;
+ ohci_dbg (ohci,
+ "enabled OHCI_BIG_ENDIAN_MMIO\n");
+ }
+ }
+#endif
+
ohci_hcd_init (ohci);
return ohci_init (ohci);
}
Index: linux-cell/drivers/usb/host/ohci.h
===================================================================
--- linux-cell.orig/drivers/usb/host/ohci.h 2006-10-21 16:37:04.000000000
+1000
+++ linux-cell/drivers/usb/host/ohci.h 2006-11-05 17:31:44.000000000 +1100
@@ -396,6 +396,7 @@
#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi,
... */
#define OHCI_BIG_ENDIAN 0x08 /* big endian
HC */
#define OHCI_QUIRK_ZFMICRO 0x10 /* Compaq
ZFMicro chipset*/
+#define OHCI_BIG_ENDIAN_MMIO 0x20 /* big endian
HC for mmio only*/
// there are also chip quirks/bugs in init logic
};
@@ -452,6 +453,12 @@
#define big_endian(ohci) 1 /* only big endian */
#endif
+#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+#define big_endian_mmio(ohci) (big_endian(ohci)||((ohci)->flags &
OHCI_BIG_ENDIAN_MMIO))
+#else
+#define big_endian_mmio(ohci) big_endian(ohci)
+#endif
+
/*
* Big-endian read/write functions are arch-specific.
* Other arches can be added if/when they're needed.
@@ -464,13 +471,13 @@
static inline unsigned int ohci_readl (const struct ohci_hcd *ohci,
__hc32 __iomem * regs)
{
- return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs);
+ return big_endian_mmio(ohci) ? readl_be (regs) : readl ((__force u32
*)regs);
}
static inline void ohci_writel (const struct ohci_hcd *ohci,
const unsigned int val, __hc32 __iomem *regs)
{
- big_endian(ohci) ? writel_be (val, regs) :
+ big_endian_mmio(ohci) ? writel_be (val, regs) :
writel (val, (__force u32 *)regs);
}
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel