Commit ed3361ff authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: ohci, hooks for big-endian registers

This is the second of the patches from Dale Farnsworth to
support OHCI implementations that use big-endian byte sex
for registers ... all register accesses changed, that's why
it's so large.  (It also includes part of an update from
his third patch, so that it compiles/runs by itself.)

This patch adds support to the OHCI code for big-endian controllers,
maintaining the existing little-endian support.  This is done using
the following transforms:

        ohci_readl(p)   --> ohci_readl(ohci, p)
	writel(v, p)    --> ohci_writel(ohci, v, p)

	cpu_to_le16(v)  --> cpu_to_hc16(ohci, v)
	cpu_to_le16p(v) --> cpu_to_hc16p(ohci, v)
	cpu_to_le32(v)  --> cpu_to_hc32(ohci, v)
	cpu_to_le32p(v) --> cpu_to_hc32p(ohci, v)

	le16_to_cpu(v) --> hc16_to_cpu(ohci, v)
	le16_to_cpup(v) --> hc16_to_cpup(ohci, v)
	le32_to_cpu(v) --> hc32_to_cpu(ohci, v)
	le32_to_cpup(v) --> hc32_to_cpup(ohci, v)

	OHCI_FRAME_NO(ohci->hcca) --> ohci_frame_no(ohci)

There's no runtime penalty except for systems configured to handle
both byteorders at the same time.
Signed-off-by: default avatarDale Farnsworth <dale@farnsworth.org>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent c13db862
...@@ -134,13 +134,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ...@@ -134,13 +134,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
struct ohci_regs __iomem *regs = controller->regs; struct ohci_regs __iomem *regs = controller->regs;
u32 temp; u32 temp;
temp = ohci_readl (&regs->revision) & 0xff; temp = ohci_readl (controller, &regs->revision) & 0xff;
ohci_dbg_sw (controller, next, size, ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n", "OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f), 0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x10) ? "with" : "NO"); (temp & 0x10) ? "with" : "NO");
temp = ohci_readl (&regs->control); temp = ohci_readl (controller, &regs->control);
ohci_dbg_sw (controller, next, size, ohci_dbg_sw (controller, next, size,
"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
temp, temp,
...@@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ...@@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
temp & OHCI_CTRL_CBSR temp & OHCI_CTRL_CBSR
); );
temp = ohci_readl (&regs->cmdstatus); temp = ohci_readl (controller, &regs->cmdstatus);
ohci_dbg_sw (controller, next, size, ohci_dbg_sw (controller, next, size,
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp, "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
(temp & OHCI_SOC) >> 16, (temp & OHCI_SOC) >> 16,
...@@ -166,26 +166,33 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ...@@ -166,26 +166,33 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
); );
ohci_dump_intr_mask (controller, "intrstatus", ohci_dump_intr_mask (controller, "intrstatus",
ohci_readl (&regs->intrstatus), next, size); ohci_readl (controller, &regs->intrstatus),
next, size);
ohci_dump_intr_mask (controller, "intrenable", ohci_dump_intr_mask (controller, "intrenable",
ohci_readl (&regs->intrenable), next, size); ohci_readl (controller, &regs->intrenable),
next, size);
// intrdisable always same as intrenable // intrdisable always same as intrenable
maybe_print_eds (controller, "ed_periodcurrent", maybe_print_eds (controller, "ed_periodcurrent",
ohci_readl (&regs->ed_periodcurrent), next, size); ohci_readl (controller, &regs->ed_periodcurrent),
next, size);
maybe_print_eds (controller, "ed_controlhead", maybe_print_eds (controller, "ed_controlhead",
ohci_readl (&regs->ed_controlhead), next, size); ohci_readl (controller, &regs->ed_controlhead),
next, size);
maybe_print_eds (controller, "ed_controlcurrent", maybe_print_eds (controller, "ed_controlcurrent",
ohci_readl (&regs->ed_controlcurrent), next, size); ohci_readl (controller, &regs->ed_controlcurrent),
next, size);
maybe_print_eds (controller, "ed_bulkhead", maybe_print_eds (controller, "ed_bulkhead",
ohci_readl (&regs->ed_bulkhead), next, size); ohci_readl (controller, &regs->ed_bulkhead),
next, size);
maybe_print_eds (controller, "ed_bulkcurrent", maybe_print_eds (controller, "ed_bulkcurrent",
ohci_readl (&regs->ed_bulkcurrent), next, size); ohci_readl (controller, &regs->ed_bulkcurrent),
next, size);
maybe_print_eds (controller, "donehead", maybe_print_eds (controller, "donehead",
ohci_readl (&regs->donehead), next, size); ohci_readl (controller, &regs->donehead), next, size);
} }
#define dbg_port_sw(hc,num,value,next,size) \ #define dbg_port_sw(hc,num,value,next,size) \
...@@ -269,7 +276,7 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose) ...@@ -269,7 +276,7 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose)
ohci_dump_status (controller, NULL, NULL); ohci_dump_status (controller, NULL, NULL);
if (controller->hcca) if (controller->hcca)
ohci_dbg (controller, ohci_dbg (controller,
"hcca frame #%04x\n", OHCI_FRAME_NO(controller->hcca)); "hcca frame #%04x\n", ohci_frame_no(controller));
ohci_dump_roothub (controller, 1, NULL, NULL); ohci_dump_roothub (controller, 1, NULL, NULL);
} }
...@@ -279,13 +286,13 @@ static const char data1 [] = "DATA1"; ...@@ -279,13 +286,13 @@ static const char data1 [] = "DATA1";
static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
const struct td *td) const struct td *td)
{ {
u32 tmp = le32_to_cpup (&td->hwINFO); u32 tmp = hc32_to_cpup (ohci, &td->hwINFO);
ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x\n", ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x\n",
label, td, label, td,
(tmp & TD_DONE) ? " (DONE)" : "", (tmp & TD_DONE) ? " (DONE)" : "",
td->urb, td->index, td->urb, td->index,
le32_to_cpup (&td->hwNextTD)); hc32_to_cpup (ohci, &td->hwNextTD));
if ((tmp & TD_ISO) == 0) { if ((tmp & TD_ISO) == 0) {
const char *toggle, *pid; const char *toggle, *pid;
u32 cbp, be; u32 cbp, be;
...@@ -306,8 +313,8 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, ...@@ -306,8 +313,8 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
TD_CC_GET(tmp), /* EC, */ toggle, TD_CC_GET(tmp), /* EC, */ toggle,
(tmp & TD_DI) >> 21, pid, (tmp & TD_DI) >> 21, pid,
(tmp & TD_R) ? "R" : ""); (tmp & TD_R) ? "R" : "");
cbp = le32_to_cpup (&td->hwCBP); cbp = hc32_to_cpup (ohci, &td->hwCBP);
be = le32_to_cpup (&td->hwBE); be = hc32_to_cpup (ohci, &td->hwBE);
ohci_dbg (ohci, " cbp %08x be %08x (len %d)\n", cbp, be, ohci_dbg (ohci, " cbp %08x be %08x (len %d)\n", cbp, be,
cbp ? (be + 1 - cbp) : 0); cbp ? (be + 1 - cbp) : 0);
} else { } else {
...@@ -318,10 +325,10 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, ...@@ -318,10 +325,10 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
(tmp & TD_DI) >> 21, (tmp & TD_DI) >> 21,
tmp & 0x0000ffff); tmp & 0x0000ffff);
ohci_dbg (ohci, " bp0 %08x be %08x\n", ohci_dbg (ohci, " bp0 %08x be %08x\n",
le32_to_cpup (&td->hwCBP) & ~0x0fff, hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff,
le32_to_cpup (&td->hwBE)); hc32_to_cpup (ohci, &td->hwBE));
for (i = 0; i < MAXPSW; i++) { for (i = 0; i < MAXPSW; i++) {
u16 psw = le16_to_cpup (&td->hwPSW [i]); u16 psw = hc16_to_cpup (ohci, &td->hwPSW [i]);
int cc = (psw >> 12) & 0x0f; int cc = (psw >> 12) & 0x0f;
ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i, ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i,
psw, cc, psw, cc,
...@@ -336,13 +343,13 @@ static void __attribute__((unused)) ...@@ -336,13 +343,13 @@ static void __attribute__((unused))
ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
const struct ed *ed, int verbose) const struct ed *ed, int verbose)
{ {
u32 tmp = le32_to_cpu (ed->hwINFO); u32 tmp = hc32_to_cpu (ohci, ed->hwINFO);
char *type = ""; char *type = "";
ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n", ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
label, label,
ed, ed->state, edstring (ed->type), ed, ed->state, edstring (ed->type),
le32_to_cpup (&ed->hwNextED)); hc32_to_cpup (ohci, &ed->hwNextED));
switch (tmp & (ED_IN|ED_OUT)) { switch (tmp & (ED_IN|ED_OUT)) {
case ED_OUT: type = "-OUT"; break; case ED_OUT: type = "-OUT"; break;
case ED_IN: type = "-IN"; break; case ED_IN: type = "-IN"; break;
...@@ -358,12 +365,12 @@ ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, ...@@ -358,12 +365,12 @@ ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
0x000f & (tmp >> 7), 0x000f & (tmp >> 7),
type, type,
0x007f & tmp); 0x007f & tmp);
tmp = le32_to_cpup (&ed->hwHeadP); tmp = hc32_to_cpup (ohci, &ed->hwHeadP);
ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s\n", ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s\n",
tmp, tmp,
(tmp & ED_C) ? data1 : data0, (tmp & ED_C) ? data1 : data0,
(tmp & ED_H) ? " HALT" : "", (tmp & ED_H) ? " HALT" : "",
le32_to_cpup (&ed->hwTailP), hc32_to_cpup (ohci, &ed->hwTailP),
verbose ? "" : " (not listing)"); verbose ? "" : " (not listing)");
if (verbose) { if (verbose) {
struct list_head *tmp; struct list_head *tmp;
...@@ -409,10 +416,10 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) ...@@ -409,10 +416,10 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
/* dump a snapshot of the bulk or control schedule */ /* dump a snapshot of the bulk or control schedule */
while (ed) { while (ed) {
u32 info = le32_to_cpu (ed->hwINFO); u32 info = hc32_to_cpu (ohci, ed->hwINFO);
u32 headp = le32_to_cpu (ed->hwHeadP); u32 headp = hc32_to_cpu (ohci, ed->hwHeadP);
struct list_head *entry; struct list_head *entry;
struct td *td; struct td *td;
temp = scnprintf (buf, size, temp = scnprintf (buf, size,
"ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s", "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
...@@ -433,9 +440,9 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) ...@@ -433,9 +440,9 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
u32 cbp, be; u32 cbp, be;
td = list_entry (entry, struct td, td_list); td = list_entry (entry, struct td, td_list);
info = le32_to_cpup (&td->hwINFO); info = hc32_to_cpup (ohci, &td->hwINFO);
cbp = le32_to_cpup (&td->hwCBP); cbp = hc32_to_cpup (ohci, &td->hwCBP);
be = le32_to_cpup (&td->hwBE); be = hc32_to_cpup (ohci, &td->hwBE);
temp = scnprintf (buf, size, temp = scnprintf (buf, size,
"\n\ttd %p %s %d cc=%x urb %p (%08x)", "\n\ttd %p %s %d cc=%x urb %p (%08x)",
td, td,
...@@ -535,7 +542,7 @@ show_periodic (struct class_device *class_dev, char *buf) ...@@ -535,7 +542,7 @@ show_periodic (struct class_device *class_dev, char *buf)
/* show more info the first time around */ /* show more info the first time around */
if (temp == seen_count) { if (temp == seen_count) {
u32 info = le32_to_cpu (ed->hwINFO); u32 info = hc32_to_cpu (ohci, ed->hwINFO);
struct list_head *entry; struct list_head *entry;
unsigned qlen = 0; unsigned qlen = 0;
...@@ -555,8 +562,9 @@ show_periodic (struct class_device *class_dev, char *buf) ...@@ -555,8 +562,9 @@ show_periodic (struct class_device *class_dev, char *buf)
0x03ff & (info >> 16), 0x03ff & (info >> 16),
info, info,
(info & ED_SKIP) ? " K" : "", (info & ED_SKIP) ? " K" : "",
(ed->hwHeadP & cpu_to_le32(ED_H)) ? (ed->hwHeadP &
" H" : ""); cpu_to_hc32(ohci, ED_H)) ?
" H" : "");
size -= temp; size -= temp;
next += temp; next += temp;
...@@ -628,10 +636,10 @@ show_registers (struct class_device *class_dev, char *buf) ...@@ -628,10 +636,10 @@ show_registers (struct class_device *class_dev, char *buf)
/* hcca */ /* hcca */
if (ohci->hcca) if (ohci->hcca)
ohci_dbg_sw (ohci, &next, &size, ohci_dbg_sw (ohci, &next, &size,
"hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca)); "hcca frame 0x%04x\n", ohci_frame_no(ohci));
/* other registers mostly affect frame timings */ /* other registers mostly affect frame timings */
rdata = ohci_readl (&regs->fminterval); rdata = ohci_readl (ohci, &regs->fminterval);
temp = scnprintf (next, size, temp = scnprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
rdata, (rdata >> 31) ? "FIT " : "", rdata, (rdata >> 31) ? "FIT " : "",
...@@ -639,20 +647,20 @@ show_registers (struct class_device *class_dev, char *buf) ...@@ -639,20 +647,20 @@ show_registers (struct class_device *class_dev, char *buf)
size -= temp; size -= temp;
next += temp; next += temp;
rdata = ohci_readl (&regs->fmremaining); rdata = ohci_readl (ohci, &regs->fmremaining);
temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
rdata, (rdata >> 31) ? "FRT " : "", rdata, (rdata >> 31) ? "FRT " : "",
rdata & 0x3fff); rdata & 0x3fff);
size -= temp; size -= temp;
next += temp; next += temp;
rdata = ohci_readl (&regs->periodicstart); rdata = ohci_readl (ohci, &regs->periodicstart);
temp = scnprintf (next, size, "periodicstart 0x%04x\n", temp = scnprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff); rdata & 0x3fff);
size -= temp; size -= temp;
next += temp; next += temp;
rdata = ohci_readl (&regs->lsthresh); rdata = ohci_readl (ohci, &regs->lsthresh);
temp = scnprintf (next, size, "lsthresh 0x%04x\n", temp = scnprintf (next, size, "lsthresh 0x%04x\n",
rdata & 0x3fff); rdata & 0x3fff);
size -= temp; size -= temp;
......
...@@ -260,7 +260,7 @@ static int ohci_urb_enqueue ( ...@@ -260,7 +260,7 @@ static int ohci_urb_enqueue (
if (retval < 0) if (retval < 0)
goto fail0; goto fail0;
if (ed->type == PIPE_ISOCHRONOUS) { if (ed->type == PIPE_ISOCHRONOUS) {
u16 frame = OHCI_FRAME_NO(ohci->hcca); u16 frame = ohci_frame_no(ohci);
/* delay a few frames before the first TD */ /* delay a few frames before the first TD */
frame += max_t (u16, 8, ed->interval); frame += max_t (u16, 8, ed->interval);
...@@ -403,14 +403,14 @@ static int ohci_get_frame (struct usb_hcd *hcd) ...@@ -403,14 +403,14 @@ static int ohci_get_frame (struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
return OHCI_FRAME_NO(ohci->hcca); return ohci_frame_no(ohci);
} }
static void ohci_usb_reset (struct ohci_hcd *ohci) static void ohci_usb_reset (struct ohci_hcd *ohci)
{ {
ohci->hc_control = ohci_readl (&ohci->regs->control); ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control &= OHCI_CTRL_RWC;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
} }
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
...@@ -430,7 +430,8 @@ static int ohci_init (struct ohci_hcd *ohci) ...@@ -430,7 +430,8 @@ static int ohci_init (struct ohci_hcd *ohci)
#ifndef IR_DISABLE #ifndef IR_DISABLE
/* SMM owns the HC? not for long! */ /* SMM owns the HC? not for long! */
if (!no_handshake && ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { if (!no_handshake && ohci_readl (ohci,
&ohci->regs->control) & OHCI_CTRL_IR) {
ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n"); ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
/* this timeout is arbitrary. we make it long, so systems /* this timeout is arbitrary. we make it long, so systems
...@@ -439,9 +440,9 @@ static int ohci_init (struct ohci_hcd *ohci) ...@@ -439,9 +440,9 @@ static int ohci_init (struct ohci_hcd *ohci)
*/ */
temp = 500; /* arbitrary: five seconds */ temp = 500; /* arbitrary: five seconds */
writel (OHCI_INTR_OC, &ohci->regs->intrenable); ohci_writel (ohci, OHCI_INTR_OC, &ohci->regs->intrenable);
writel (OHCI_OCR, &ohci->regs->cmdstatus); ohci_writel (ohci, OHCI_OCR, &ohci->regs->cmdstatus);
while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { while (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_IR) {
msleep (10); msleep (10);
if (--temp == 0) { if (--temp == 0) {
ohci_err (ohci, "USB HC TakeOver failed!\n"); ohci_err (ohci, "USB HC TakeOver failed!\n");
...@@ -453,9 +454,9 @@ static int ohci_init (struct ohci_hcd *ohci) ...@@ -453,9 +454,9 @@ static int ohci_init (struct ohci_hcd *ohci)
#endif #endif
/* Disable HC interrupts */ /* Disable HC interrupts */
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
// flush the writes // flush the writes
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
if (ohci->hcca) if (ohci->hcca)
return 0; return 0;
...@@ -491,7 +492,7 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -491,7 +492,7 @@ static int ohci_run (struct ohci_hcd *ohci)
/* boot firmware should have set this up (5.1.1.3.1) */ /* boot firmware should have set this up (5.1.1.3.1) */
if (first) { if (first) {
temp = ohci_readl (&ohci->regs->fminterval); temp = ohci_readl (ohci, &ohci->regs->fminterval);
ohci->fminterval = temp & 0x3fff; ohci->fminterval = temp & 0x3fff;
if (ohci->fminterval != FI) if (ohci->fminterval != FI)
ohci_dbg (ohci, "fminterval delta %d\n", ohci_dbg (ohci, "fminterval delta %d\n",
...@@ -504,7 +505,7 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -504,7 +505,7 @@ static int ohci_run (struct ohci_hcd *ohci)
* saved if boot firmware (BIOS/SMM/...) told us it's connected * saved if boot firmware (BIOS/SMM/...) told us it's connected
* (for OHCI integrated on mainboard, it normally is) * (for OHCI integrated on mainboard, it normally is)
*/ */
ohci->hc_control = ohci_readl (&ohci->regs->control); ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n",
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
ohci->hc_control); ohci->hc_control);
...@@ -530,20 +531,20 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -530,20 +531,20 @@ static int ohci_run (struct ohci_hcd *ohci)
temp = 50 /* msec wait */; temp = 50 /* msec wait */;
break; break;
} }
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
// flush the writes // flush the writes
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
msleep(temp); msleep(temp);
if (power_switching) { if (power_switching) {
unsigned ports = roothub_a (ohci) & RH_A_NDP; unsigned ports = roothub_a (ohci) & RH_A_NDP;
/* power down each port */ /* power down each port */
for (temp = 0; temp < ports; temp++) for (temp = 0; temp < ports; temp++)
writel (RH_PS_LSDA, ohci_writel (ohci, RH_PS_LSDA,
&ohci->regs->roothub.portstatus [temp]); &ohci->regs->roothub.portstatus [temp]);
} }
// flush those writes // flush those writes
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
/* 2msec timelimit here means no irqs/preempt */ /* 2msec timelimit here means no irqs/preempt */
...@@ -551,9 +552,9 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -551,9 +552,9 @@ static int ohci_run (struct ohci_hcd *ohci)
retry: retry:
/* HC Reset requires max 10 us delay */ /* HC Reset requires max 10 us delay */
writel (OHCI_HCR, &ohci->regs->cmdstatus); ohci_writel (ohci, OHCI_HCR, &ohci->regs->cmdstatus);
temp = 30; /* ... allow extra time */ temp = 30; /* ... allow extra time */
while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { while ((ohci_readl (ohci, &ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
if (--temp == 0) { if (--temp == 0) {
spin_unlock_irq (&ohci->lock); spin_unlock_irq (&ohci->lock);
ohci_err (ohci, "USB HC reset timed out!\n"); ohci_err (ohci, "USB HC reset timed out!\n");
...@@ -572,27 +573,27 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -572,27 +573,27 @@ static int ohci_run (struct ohci_hcd *ohci)
* easily be a longstanding bug in chip init on Linux. * easily be a longstanding bug in chip init on Linux.
*/ */
if (ohci->flags & OHCI_QUIRK_INITRESET) { if (ohci->flags & OHCI_QUIRK_INITRESET) {
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
// flush those writes // flush those writes
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
} }
writel (ohci->fminterval, &ohci->regs->fminterval); ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval);
/* Tell the controller where the control and bulk lists are /* Tell the controller where the control and bulk lists are
* The lists are empty now. */ * The lists are empty now. */
writel (0, &ohci->regs->ed_controlhead); ohci_writel (ohci, 0, &ohci->regs->ed_controlhead);
writel (0, &ohci->regs->ed_bulkhead); ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead);
/* a reset clears this */ /* a reset clears this */
writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);
periodic_reinit (ohci); periodic_reinit (ohci);
/* some OHCI implementations are finicky about how they init. /* some OHCI implementations are finicky about how they init.
* bogus values here mean not even enumeration could work. * bogus values here mean not even enumeration could work.
*/ */
if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 if ((ohci_readl (ohci, &ohci->regs->fminterval) & 0x3fff0000) == 0
|| !ohci_readl (&ohci->regs->periodicstart)) { || !ohci_readl (ohci, &ohci->regs->periodicstart)) {
if (!(ohci->flags & OHCI_QUIRK_INITRESET)) { if (!(ohci->flags & OHCI_QUIRK_INITRESET)) {
ohci->flags |= OHCI_QUIRK_INITRESET; ohci->flags |= OHCI_QUIRK_INITRESET;
ohci_dbg (ohci, "enabling initreset quirk\n"); ohci_dbg (ohci, "enabling initreset quirk\n");
...@@ -600,24 +601,24 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -600,24 +601,24 @@ static int ohci_run (struct ohci_hcd *ohci)
} }
spin_unlock_irq (&ohci->lock); spin_unlock_irq (&ohci->lock);
ohci_err (ohci, "init err (%08x %04x)\n", ohci_err (ohci, "init err (%08x %04x)\n",
ohci_readl (&ohci->regs->fminterval), ohci_readl (ohci, &ohci->regs->fminterval),
ohci_readl (&ohci->regs->periodicstart)); ohci_readl (ohci, &ohci->regs->periodicstart));
return -EOVERFLOW; return -EOVERFLOW;
} }
/* start controller operations */ /* start controller operations */
ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control &= OHCI_CTRL_RWC;
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
ohci->hcd.state = USB_STATE_RUNNING; ohci->hcd.state = USB_STATE_RUNNING;
/* wake on ConnectStatusChange, matching external hubs */ /* wake on ConnectStatusChange, matching external hubs */
writel (RH_HS_DRWE, &ohci->regs->roothub.status); ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
/* Choose the interrupts we care about now, others later on demand */ /* Choose the interrupts we care about now, others later on demand */
mask = OHCI_INTR_INIT; mask = OHCI_INTR_INIT;
writel (mask, &ohci->regs->intrstatus); ohci_writel (ohci, mask, &ohci->regs->intrstatus);
writel (mask, &ohci->regs->intrenable); ohci_writel (ohci, mask, &ohci->regs->intrenable);
/* handle root hub init quirks ... */ /* handle root hub init quirks ... */
temp = roothub_a (ohci); temp = roothub_a (ohci);
...@@ -638,11 +639,12 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -638,11 +639,12 @@ static int ohci_run (struct ohci_hcd *ohci)
*/ */
temp |= RH_A_NPS; temp |= RH_A_NPS;
} }
writel (temp, &ohci->regs->roothub.a); ohci_writel (ohci, temp, &ohci->regs->roothub.a);
writel (RH_HS_LPSC, &ohci->regs->roothub.status); ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);
writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b); ohci_writel (ohci, power_switching ? RH_B_PPCM : 0,
&ohci->regs->roothub.b);
// flush those writes // flush those writes
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
spin_unlock_irq (&ohci->lock); spin_unlock_irq (&ohci->lock);
...@@ -665,7 +667,7 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -665,7 +667,7 @@ static int ohci_run (struct ohci_hcd *ohci)
if (!udev) { if (!udev) {
disable (ohci); disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
return -ENOMEM; return -ENOMEM;
} }
...@@ -674,7 +676,7 @@ static int ohci_run (struct ohci_hcd *ohci) ...@@ -674,7 +676,7 @@ static int ohci_run (struct ohci_hcd *ohci)
usb_put_dev (udev); usb_put_dev (udev);
disable (ohci); disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
return -ENODEV; return -ENODEV;
} }
if (ohci->power_budget) if (ohci->power_budget)
...@@ -697,17 +699,18 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -697,17 +699,18 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
/* we can eliminate a (slow) ohci_readl() /* we can eliminate a (slow) ohci_readl()
if _only_ WDH caused this irq */ if _only_ WDH caused this irq */
if ((ohci->hcca->done_head != 0) if ((ohci->hcca->done_head != 0)
&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head)
& 0x01)) {
ints = OHCI_INTR_WDH; ints = OHCI_INTR_WDH;
/* cardbus/... hardware gone before remove() */ /* cardbus/... hardware gone before remove() */
} else if ((ints = ohci_readl (&regs->intrstatus)) == ~(u32)0) { } else if ((ints = ohci_readl (ohci, &regs->intrstatus)) == ~(u32)0) {
disable (ohci); disable (ohci);
ohci_dbg (ohci, "device removed!\n"); ohci_dbg (ohci, "device removed!\n");
return IRQ_HANDLED; return IRQ_HANDLED;
/* interrupt for some other device? */ /* interrupt for some other device? */
} else if ((ints &= ohci_readl (&regs->intrenable)) == 0) { } else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -727,12 +730,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -727,12 +730,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ints & OHCI_INTR_WDH) { if (ints & OHCI_INTR_WDH) {
if (HCD_IS_RUNNING(hcd->state)) if (HCD_IS_RUNNING(hcd->state))
writel (OHCI_INTR_WDH, &regs->intrdisable); ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
spin_lock (&ohci->lock); spin_lock (&ohci->lock);
dl_done_list (ohci, ptregs); dl_done_list (ohci, ptregs);
spin_unlock (&ohci->lock); spin_unlock (&ohci->lock);
if (HCD_IS_RUNNING(hcd->state)) if (HCD_IS_RUNNING(hcd->state))
writel (OHCI_INTR_WDH, &regs->intrenable); ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
} }
/* could track INTR_SO to reduce available PCI/... bandwidth */ /* could track INTR_SO to reduce available PCI/... bandwidth */
...@@ -742,18 +745,17 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -742,18 +745,17 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
*/ */
spin_lock (&ohci->lock); spin_lock (&ohci->lock);
if (ohci->ed_rm_list) if (ohci->ed_rm_list)
finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
&& HCD_IS_RUNNING(ohci->hcd.state)) && HCD_IS_RUNNING(ohci->hcd.state))
writel (OHCI_INTR_SF, &regs->intrdisable); ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock); spin_unlock (&ohci->lock);
if (HCD_IS_RUNNING(ohci->hcd.state)) { if (HCD_IS_RUNNING(ohci->hcd.state)) {
writel (ints, &regs->intrstatus); ohci_writel (ohci, ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable); ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes // flush those writes
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -773,7 +775,7 @@ static void ohci_stop (struct usb_hcd *hcd) ...@@ -773,7 +775,7 @@ static void ohci_stop (struct usb_hcd *hcd)
flush_scheduled_work(); flush_scheduled_work();
ohci_usb_reset (ohci); ohci_usb_reset (ohci);
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
remove_debug_files (ohci); remove_debug_files (ohci);
ohci_mem_cleanup (ohci); ohci_mem_cleanup (ohci);
...@@ -815,7 +817,7 @@ static int ohci_restart (struct ohci_hcd *ohci) ...@@ -815,7 +817,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
switch (ed->state) { switch (ed->state) {
case ED_OPER: case ED_OPER:
ed->state = ED_UNLINK; ed->state = ED_UNLINK;
ed->hwINFO |= cpu_to_le32(ED_DEQUEUE); ed->hwINFO |= cpu_to_hc32(ohci, ED_DEQUEUE);
ed_deschedule (ohci, ed); ed_deschedule (ohci, ed);
ed->ed_next = ohci->ed_rm_list; ed->ed_next = ohci->ed_rm_list;
...@@ -859,7 +861,7 @@ static int ohci_restart (struct ohci_hcd *ohci) ...@@ -859,7 +861,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
*/ */
i = roothub_a (ohci) & RH_A_NDP; i = roothub_a (ohci) & RH_A_NDP;
while (i--) while (i--)
writel (RH_PS_PSS, ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [temp]); &ohci->regs->roothub.portstatus [temp]);
ohci_dbg (ohci, "restart complete\n"); ohci_dbg (ohci, "restart complete\n");
ohci->hcd.state = USB_STATE_RUNNING; ohci->hcd.state = USB_STATE_RUNNING;
......
...@@ -58,14 +58,14 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -58,14 +58,14 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
spin_lock_irq (&ohci->lock); spin_lock_irq (&ohci->lock);
ohci->hc_control = ohci_readl (&ohci->regs->control); ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
switch (ohci->hc_control & OHCI_CTRL_HCFS) { switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
ohci_dbg (ohci, "resume/suspend?\n"); ohci_dbg (ohci, "resume/suspend?\n");
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_RESET; ohci->hc_control |= OHCI_USB_RESET;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
/* FALL THROUGH */ /* FALL THROUGH */
case OHCI_USB_RESET: case OHCI_USB_RESET:
status = -EBUSY; status = -EBUSY;
...@@ -83,9 +83,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -83,9 +83,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
int limit; int limit;
ohci->hc_control &= ~OHCI_SCHED_ENABLES; ohci->hc_control &= ~OHCI_SCHED_ENABLES;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
ohci->hc_control = ohci_readl (&ohci->regs->control); ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);
/* sched disables take effect on the next frame, /* sched disables take effect on the next frame,
* then the last WDH could take 6+ msec * then the last WDH could take 6+ msec
...@@ -95,15 +95,17 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -95,15 +95,17 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
while (limit > 0) { while (limit > 0) {
udelay (250); udelay (250);
limit =- 250; limit =- 250;
if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) if (ohci_readl (ohci, &ohci->regs->intrstatus)
& OHCI_INTR_SF)
break; break;
} }
dl_done_list (ohci, NULL); dl_done_list (ohci, NULL);
mdelay (7); mdelay (7);
} }
dl_done_list (ohci, NULL); dl_done_list (ohci, NULL);
finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), NULL); finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
&ohci->regs->intrstatus);
/* maybe resume can wake root hub */ /* maybe resume can wake root hub */
if (ohci->hcd.remote_wakeup) if (ohci->hcd.remote_wakeup)
...@@ -114,8 +116,8 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -114,8 +116,8 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
/* Suspend hub */ /* Suspend hub */
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_SUSPEND; ohci->hc_control |= OHCI_USB_SUSPEND;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
/* no resumes until devices finish suspending */ /* no resumes until devices finish suspending */
ohci->next_statechange = jiffies + msecs_to_jiffies (5); ohci->next_statechange = jiffies + msecs_to_jiffies (5);
...@@ -153,7 +155,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -153,7 +155,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
return -EAGAIN; return -EAGAIN;
spin_lock_irq (&ohci->lock); spin_lock_irq (&ohci->lock);
ohci->hc_control = ohci_readl (&ohci->regs->control); ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
/* this can happen after suspend-to-disk */ /* this can happen after suspend-to-disk */
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
...@@ -163,8 +165,8 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -163,8 +165,8 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
case OHCI_USB_SUSPEND: case OHCI_USB_SUSPEND:
ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES); ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
ohci->hc_control |= OHCI_USB_RESUME; ohci->hc_control |= OHCI_USB_RESUME;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
ohci_dbg (ohci, "resume root hub\n"); ohci_dbg (ohci, "resume root hub\n");
break; break;
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
...@@ -191,19 +193,21 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -191,19 +193,21 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp = roothub_a (ohci) & RH_A_NDP; temp = roothub_a (ohci) & RH_A_NDP;
enables = 0; enables = 0;
while (temp--) { while (temp--) {
u32 stat = ohci_readl (&ohci->regs->roothub.portstatus [temp]); u32 stat = ohci_readl (ohci,
&ohci->regs->roothub.portstatus [temp]);
/* force global, not selective, resume */ /* force global, not selective, resume */
if (!(stat & RH_PS_PSS)) if (!(stat & RH_PS_PSS))
continue; continue;
writel (RH_PS_POCI, &ohci->regs->roothub.portstatus [temp]); ohci_writel (ohci, RH_PS_POCI,
&ohci->regs->roothub.portstatus [temp]);
} }
/* Some controllers (lucent) need extra-long delays */ /* Some controllers (lucent) need extra-long delays */
ohci->hcd.state = USB_STATE_RESUMING; ohci->hcd.state = USB_STATE_RESUMING;
mdelay (20 /* usb 11.5.1.10 */ + 15); mdelay (20 /* usb 11.5.1.10 */ + 15);
temp = ohci_readl (&ohci->regs->control); temp = ohci_readl (ohci, &ohci->regs->control);
temp &= OHCI_CTRL_HCFS; temp &= OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) { if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n"); ohci_err (ohci, "controller won't resume\n");
...@@ -211,32 +215,33 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -211,32 +215,33 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
} }
/* disable old schedule state, reinit from scratch */ /* disable old schedule state, reinit from scratch */
writel (0, &ohci->regs->ed_controlhead); ohci_writel (ohci, 0, &ohci->regs->ed_controlhead);
writel (0, &ohci->regs->ed_controlcurrent); ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent);
writel (0, &ohci->regs->ed_bulkhead); ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead);
writel (0, &ohci->regs->ed_bulkcurrent); ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent);
writel (0, &ohci->regs->ed_periodcurrent); ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent);
writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);
periodic_reinit (ohci); periodic_reinit (ohci);
/* interrupts might have been disabled */ /* interrupts might have been disabled */
writel (OHCI_INTR_INIT, &ohci->regs->intrenable); ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
if (ohci->ed_rm_list) if (ohci->ed_rm_list)
writel (OHCI_INTR_SF, &ohci->regs->intrenable); ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
&ohci->regs->intrstatus);
/* Then re-enable operations */ /* Then re-enable operations */
writel (OHCI_USB_OPER, &ohci->regs->control); ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
msleep (3); msleep (3);
temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
if (ohci->hcd.can_wakeup) if (ohci->hcd.can_wakeup)
temp |= OHCI_CTRL_RWC; temp |= OHCI_CTRL_RWC;
ohci->hc_control = temp; ohci->hc_control = temp;
writel (temp, &ohci->regs->control); ohci_writel (ohci, temp, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
/* TRSMRCY */ /* TRSMRCY */
msleep (10); msleep (10);
...@@ -251,13 +256,14 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -251,13 +256,14 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp = 0; temp = 0;
if (!ohci->ed_rm_list) { if (!ohci->ed_rm_list) {
if (ohci->ed_controltail) { if (ohci->ed_controltail) {
writel (find_head (ohci->ed_controltail)->dma, ohci_writel (ohci,
&ohci->regs->ed_controlhead); find_head (ohci->ed_controltail)->dma,
&ohci->regs->ed_controlhead);
enables |= OHCI_CTRL_CLE; enables |= OHCI_CTRL_CLE;
temp |= OHCI_CLF; temp |= OHCI_CLF;
} }
if (ohci->ed_bulktail) { if (ohci->ed_bulktail) {
writel (find_head (ohci->ed_bulktail)->dma, ohci_writel (ohci, find_head (ohci->ed_bulktail)->dma,
&ohci->regs->ed_bulkhead); &ohci->regs->ed_bulkhead);
enables |= OHCI_CTRL_BLE; enables |= OHCI_CTRL_BLE;
temp |= OHCI_BLF; temp |= OHCI_BLF;
...@@ -269,10 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -269,10 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if (enables) { if (enables) {
ohci_dbg (ohci, "restarting schedules ... %08x\n", enables); ohci_dbg (ohci, "restarting schedules ... %08x\n", enables);
ohci->hc_control |= enables; ohci->hc_control |= enables;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
if (temp) if (temp)
writel (temp, &ohci->regs->cmdstatus); ohci_writel (ohci, temp, &ohci->regs->cmdstatus);
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
} }
ohci->hcd.state = USB_STATE_RUNNING; ohci->hcd.state = USB_STATE_RUNNING;
...@@ -313,8 +319,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) ...@@ -313,8 +319,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (ports > MAX_ROOT_PORTS) { if (ports > MAX_ROOT_PORTS) {
if (!HCD_IS_RUNNING(ohci->hcd.state)) if (!HCD_IS_RUNNING(ohci->hcd.state))
return -ESHUTDOWN; return -ESHUTDOWN;
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP); ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */ /* retry later; "should not happen" */
return 0; return 0;
} }
...@@ -403,7 +409,7 @@ ohci_hub_descriptor ( ...@@ -403,7 +409,7 @@ ohci_hub_descriptor (
temp |= 0x0010; temp |= 0x0010;
else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */ else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */
temp |= 0x0008; temp |= 0x0008;
desc->wHubCharacteristics = cpu_to_le16 (temp); desc->wHubCharacteristics = cpu_to_hc16 (ohci, temp);
/* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
rh = roothub_b (ohci); rh = roothub_b (ohci);
...@@ -429,12 +435,12 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port) ...@@ -429,12 +435,12 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
port--; port--;
/* start port reset before HNP protocol times out */ /* start port reset before HNP protocol times out */
status = ohci_readl(&ohci->regs->roothub.portstatus [port]); status = ohci_readl(ohci, &ohci->regs->roothub.portstatus [port]);
if (!(status & RH_PS_CCS)) if (!(status & RH_PS_CCS))
return -ENODEV; return -ENODEV;
/* khubd will finish the reset later */ /* khubd will finish the reset later */
writel(RH_PS_PRS, &ohci->regs->roothub.portstatus [port]); ohci_writel(ohci, RH_PS_PRS, &ohci->regs->roothub.portstatus [port]);
return 0; return 0;
} }
...@@ -471,7 +477,7 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) ...@@ -471,7 +477,7 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
{ {
u32 __iomem *portstat = &ohci->regs->roothub.portstatus [port]; u32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp; u32 temp;
u16 now = readl(&ohci->regs->fmnumber); u16 now = ohci_readl(ohci, &ohci->regs->fmnumber);
u16 reset_done = now + PORT_RESET_MSEC; u16 reset_done = now + PORT_RESET_MSEC;
/* build a "continuous enough" reset signal, with up to /* build a "continuous enough" reset signal, with up to
...@@ -481,7 +487,7 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) ...@@ -481,7 +487,7 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
do { do {
/* spin until any current reset finishes */ /* spin until any current reset finishes */
for (;;) { for (;;) {
temp = ohci_readl (portstat); temp = ohci_readl (ohci, portstat);
if (!(temp & RH_PS_PRS)) if (!(temp & RH_PS_PRS))
break; break;
udelay (500); udelay (500);
...@@ -490,12 +496,12 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) ...@@ -490,12 +496,12 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
if (!(temp & RH_PS_CCS)) if (!(temp & RH_PS_CCS))
break; break;
if (temp & RH_PS_PRSC) if (temp & RH_PS_PRSC)
writel (RH_PS_PRSC, portstat); ohci_writel (ohci, RH_PS_PRSC, portstat);
/* start the next reset, sleep till it's probably done */ /* start the next reset, sleep till it's probably done */
writel (RH_PS_PRS, portstat); ohci_writel (ohci, RH_PS_PRS, portstat);
msleep(PORT_RESET_HW_MSEC); msleep(PORT_RESET_HW_MSEC);
now = readl(&ohci->regs->fmnumber); now = ohci_readl(ohci, &ohci->regs->fmnumber);
} while (tick_before(now, reset_done)); } while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */ /* caller synchronizes using PRSC */
} }
...@@ -517,7 +523,8 @@ static int ohci_hub_control ( ...@@ -517,7 +523,8 @@ static int ohci_hub_control (
case ClearHubFeature: case ClearHubFeature:
switch (wValue) { switch (wValue) {
case C_HUB_OVER_CURRENT: case C_HUB_OVER_CURRENT:
writel (RH_HS_OCIC, &ohci->regs->roothub.status); ohci_writel (ohci, RH_HS_OCIC,
&ohci->regs->roothub.status);
case C_HUB_LOCAL_POWER: case C_HUB_LOCAL_POWER:
break; break;
default: default:
...@@ -560,8 +567,9 @@ static int ohci_hub_control ( ...@@ -560,8 +567,9 @@ static int ohci_hub_control (
default: default:
goto error; goto error;
} }
writel (temp, &ohci->regs->roothub.portstatus [wIndex]); ohci_writel (ohci, temp,
// ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); &ohci->regs->roothub.portstatus [wIndex]);
// ohci_readl (ohci, &ohci->regs->roothub.portstatus [wIndex]);
break; break;
case GetHubDescriptor: case GetHubDescriptor:
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
...@@ -604,11 +612,11 @@ static int ohci_hub_control ( ...@@ -604,11 +612,11 @@ static int ohci_hub_control (
start_hnp(ohci); start_hnp(ohci);
else else
#endif #endif
writel (RH_PS_PSS, ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [wIndex]); &ohci->regs->roothub.portstatus [wIndex]);
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
writel (RH_PS_PPS, ohci_writel (ohci, RH_PS_PPS,
&ohci->regs->roothub.portstatus [wIndex]); &ohci->regs->roothub.portstatus [wIndex]);
break; break;
case USB_PORT_FEAT_RESET: case USB_PORT_FEAT_RESET:
......
...@@ -99,7 +99,7 @@ td_alloc (struct ohci_hcd *hc, int mem_flags) ...@@ -99,7 +99,7 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
if (td) { if (td) {
/* in case hc fetches it, make it look dead */ /* in case hc fetches it, make it look dead */
memset (td, 0, sizeof *td); memset (td, 0, sizeof *td);
td->hwNextTD = cpu_to_le32 (dma); td->hwNextTD = cpu_to_hc32 (hc, dma);
td->td_dma = dma; td->td_dma = dma;
/* hashed in td_fill */ /* hashed in td_fill */
} }
...@@ -115,7 +115,7 @@ td_free (struct ohci_hcd *hc, struct td *td) ...@@ -115,7 +115,7 @@ td_free (struct ohci_hcd *hc, struct td *td)
prev = &(*prev)->td_hash; prev = &(*prev)->td_hash;
if (*prev) if (*prev)
*prev = td->td_hash; *prev = td->td_hash;
else if ((td->hwINFO & cpu_to_le32(TD_DONE)) != 0) else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
ohci_dbg (hc, "no hash for td %p\n", td); ohci_dbg (hc, "no hash for td %p\n", td);
dma_pool_free (hc->td_cache, td, td->td_dma); dma_pool_free (hc->td_cache, td, td->td_dma);
} }
......
...@@ -78,7 +78,7 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) ...@@ -78,7 +78,7 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0 if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0
&& hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0) { && hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0) {
ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE); ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
} }
} }
...@@ -131,12 +131,12 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) ...@@ -131,12 +131,12 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
unsigned i; unsigned i;
ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n", ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n",
(ed->hwINFO & cpu_to_le32 (ED_ISO)) ? "iso " : "", (ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "",
ed, ed->branch, ed->load, ed->interval); ed, ed->branch, ed->load, ed->interval);
for (i = ed->branch; i < NUM_INTS; i += ed->interval) { for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
struct ed **prev = &ohci->periodic [i]; struct ed **prev = &ohci->periodic [i];
__le32 *prev_p = &ohci->hcca->int_table [i]; __hc32 *prev_p = &ohci->hcca->int_table [i];
struct ed *here = *prev; struct ed *here = *prev;
/* sorting each branch by period (slow before fast) /* sorting each branch by period (slow before fast)
...@@ -156,7 +156,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) ...@@ -156,7 +156,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
ed->hwNextED = *prev_p; ed->hwNextED = *prev_p;
wmb (); wmb ();
*prev = ed; *prev = ed;
*prev_p = cpu_to_le32(ed->dma); *prev_p = cpu_to_hc32(ohci, ed->dma);
wmb(); wmb();
} }
ohci->load [i] += ed->load; ohci->load [i] += ed->load;
...@@ -193,17 +193,20 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -193,17 +193,20 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
case PIPE_CONTROL: case PIPE_CONTROL:
if (ohci->ed_controltail == NULL) { if (ohci->ed_controltail == NULL) {
WARN_ON (ohci->hc_control & OHCI_CTRL_CLE); WARN_ON (ohci->hc_control & OHCI_CTRL_CLE);
writel (ed->dma, &ohci->regs->ed_controlhead); ohci_writel (ohci, ed->dma,
&ohci->regs->ed_controlhead);
} else { } else {
ohci->ed_controltail->ed_next = ed; ohci->ed_controltail->ed_next = ed;
ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); ohci->ed_controltail->hwNextED = cpu_to_hc32 (ohci,
ed->dma);
} }
ed->ed_prev = ohci->ed_controltail; ed->ed_prev = ohci->ed_controltail;
if (!ohci->ed_controltail && !ohci->ed_rm_list) { if (!ohci->ed_controltail && !ohci->ed_rm_list) {
wmb(); wmb();
ohci->hc_control |= OHCI_CTRL_CLE; ohci->hc_control |= OHCI_CTRL_CLE;
writel (0, &ohci->regs->ed_controlcurrent); ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent);
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
} }
ohci->ed_controltail = ed; ohci->ed_controltail = ed;
break; break;
...@@ -211,17 +214,19 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -211,17 +214,19 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
case PIPE_BULK: case PIPE_BULK:
if (ohci->ed_bulktail == NULL) { if (ohci->ed_bulktail == NULL) {
WARN_ON (ohci->hc_control & OHCI_CTRL_BLE); WARN_ON (ohci->hc_control & OHCI_CTRL_BLE);
writel (ed->dma, &ohci->regs->ed_bulkhead); ohci_writel (ohci, ed->dma, &ohci->regs->ed_bulkhead);
} else { } else {
ohci->ed_bulktail->ed_next = ed; ohci->ed_bulktail->ed_next = ed;
ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); ohci->ed_bulktail->hwNextED = cpu_to_hc32 (ohci,
ed->dma);
} }
ed->ed_prev = ohci->ed_bulktail; ed->ed_prev = ohci->ed_bulktail;
if (!ohci->ed_bulktail && !ohci->ed_rm_list) { if (!ohci->ed_bulktail && !ohci->ed_rm_list) {
wmb(); wmb();
ohci->hc_control |= OHCI_CTRL_BLE; ohci->hc_control |= OHCI_CTRL_BLE;
writel (0, &ohci->regs->ed_bulkcurrent); ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent);
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
} }
ohci->ed_bulktail = ed; ohci->ed_bulktail = ed;
break; break;
...@@ -257,7 +262,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -257,7 +262,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
for (i = ed->branch; i < NUM_INTS; i += ed->interval) { for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
struct ed *temp; struct ed *temp;
struct ed **prev = &ohci->periodic [i]; struct ed **prev = &ohci->periodic [i];
__le32 *prev_p = &ohci->hcca->int_table [i]; __hc32 *prev_p = &ohci->hcca->int_table [i];
while (*prev && (temp = *prev) != ed) { while (*prev && (temp = *prev) != ed) {
prev_p = &temp->hwNextED; prev_p = &temp->hwNextED;
...@@ -272,7 +277,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -272,7 +277,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval; hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval;
ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
(ed->hwINFO & cpu_to_le32 (ED_ISO)) ? "iso " : "", (ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "",
ed, ed->branch, ed->load, ed->interval); ed, ed->branch, ed->load, ed->interval);
} }
...@@ -300,7 +305,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -300,7 +305,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
*/ */
static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
{ {
ed->hwINFO |= cpu_to_le32 (ED_SKIP); ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb (); wmb ();
ed->state = ED_UNLINK; ed->state = ED_UNLINK;
...@@ -320,10 +325,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -320,10 +325,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (ed->ed_prev == NULL) { if (ed->ed_prev == NULL) {
if (!ed->hwNextED) { if (!ed->hwNextED) {
ohci->hc_control &= ~OHCI_CTRL_CLE; ohci->hc_control &= ~OHCI_CTRL_CLE;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
// a ohci_readl() later syncs CLE with the HC // a ohci_readl() later syncs CLE with the HC
} else } else
writel (le32_to_cpup (&ed->hwNextED), ohci_writel (ohci,
hc32_to_cpup (ohci, &ed->hwNextED),
&ohci->regs->ed_controlhead); &ohci->regs->ed_controlhead);
} else { } else {
ed->ed_prev->ed_next = ed->ed_next; ed->ed_prev->ed_next = ed->ed_next;
...@@ -344,10 +351,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -344,10 +351,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (ed->ed_prev == NULL) { if (ed->ed_prev == NULL) {
if (!ed->hwNextED) { if (!ed->hwNextED) {
ohci->hc_control &= ~OHCI_CTRL_BLE; ohci->hc_control &= ~OHCI_CTRL_BLE;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
// a ohci_readl() later syncs BLE with the HC // a ohci_readl() later syncs BLE with the HC
} else } else
writel (le32_to_cpup (&ed->hwNextED), ohci_writel (ohci,
hc32_to_cpup (ohci, &ed->hwNextED),
&ohci->regs->ed_bulkhead); &ohci->regs->ed_bulkhead);
} else { } else {
ed->ed_prev->ed_next = ed->ed_next; ed->ed_prev->ed_next = ed->ed_next;
...@@ -416,7 +425,7 @@ static struct ed *ed_get ( ...@@ -416,7 +425,7 @@ static struct ed *ed_get (
goto done; goto done;
} }
ed->dummy = td; ed->dummy = td;
ed->hwTailP = cpu_to_le32 (td->td_dma); ed->hwTailP = cpu_to_hc32 (ohci, td->td_dma);
ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */
ed->state = ED_IDLE; ed->state = ED_IDLE;
ed->type = type; ed->type = type;
...@@ -450,7 +459,7 @@ static struct ed *ed_get ( ...@@ -450,7 +459,7 @@ static struct ed *ed_get (
/ 1000; / 1000;
} }
} }
ed->hwINFO = cpu_to_le32(info); ed->hwINFO = cpu_to_hc32(ohci, info);
} }
done: done:
...@@ -468,7 +477,7 @@ static struct ed *ed_get ( ...@@ -468,7 +477,7 @@ static struct ed *ed_get (
*/ */
static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
{ {
ed->hwINFO |= cpu_to_le32 (ED_DEQUEUE); ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE);
ed_deschedule (ohci, ed); ed_deschedule (ohci, ed);
/* rm_list is just singly linked, for simplicity */ /* rm_list is just singly linked, for simplicity */
...@@ -477,17 +486,17 @@ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -477,17 +486,17 @@ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
ohci->ed_rm_list = ed; ohci->ed_rm_list = ed;
/* enable SOF interrupt */ /* enable SOF interrupt */
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);
writel (OHCI_INTR_SF, &ohci->regs->intrenable); ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
// flush those writes, and get latest HCCA contents // flush those writes, and get latest HCCA contents
(void) ohci_readl (&ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
/* SF interrupt might get delayed; record the frame counter value that /* SF interrupt might get delayed; record the frame counter value that
* indicates when the HC isn't looking at it, so concurrent unlinks * indicates when the HC isn't looking at it, so concurrent unlinks
* behave. frame_no wraps every 2^16 msec, and changes right before * behave. frame_no wraps every 2^16 msec, and changes right before
* SF is triggered. * SF is triggered.
*/ */
ed->tick = OHCI_FRAME_NO(ohci->hcca) + 1; ed->tick = ohci_frame_no(ohci) + 1;
} }
...@@ -539,19 +548,19 @@ td_fill (struct ohci_hcd *ohci, u32 info, ...@@ -539,19 +548,19 @@ td_fill (struct ohci_hcd *ohci, u32 info,
if (!len) if (!len)
data = 0; data = 0;
td->hwINFO = cpu_to_le32 (info); td->hwINFO = cpu_to_hc32 (ohci, info);
if (is_iso) { if (is_iso) {
td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); td->hwPSW [0] = cpu_to_hc16 (ohci, (data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff; td->ed->last_iso = info & 0xffff;
} else { } else {
td->hwCBP = cpu_to_le32 (data); td->hwCBP = cpu_to_hc32 (ohci, data);
} }
if (data) if (data)
td->hwBE = cpu_to_le32 (data + len - 1); td->hwBE = cpu_to_hc32 (ohci, data + len - 1);
else else
td->hwBE = 0; td->hwBE = 0;
td->hwNextTD = cpu_to_le32 (td_pt->td_dma); td->hwNextTD = cpu_to_hc32 (ohci, td_pt->td_dma);
/* append to queue */ /* append to queue */
list_add_tail (&td->td_list, &td->ed->td_list); list_add_tail (&td->td_list, &td->ed->td_list);
...@@ -592,7 +601,7 @@ static void td_submit_urb ( ...@@ -592,7 +601,7 @@ static void td_submit_urb (
if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
is_out, 1); is_out, 1);
urb_priv->ed->hwHeadP &= ~cpu_to_le32 (ED_C); urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
} }
urb_priv->td_cnt = 0; urb_priv->td_cnt = 0;
...@@ -641,7 +650,7 @@ static void td_submit_urb ( ...@@ -641,7 +650,7 @@ static void td_submit_urb (
/* maybe kickstart bulk list */ /* maybe kickstart bulk list */
if (urb_priv->ed->type == PIPE_BULK) { if (urb_priv->ed->type == PIPE_BULK) {
wmb (); wmb ();
writel (OHCI_BLF, &ohci->regs->cmdstatus); ohci_writel (ohci, OHCI_BLF, &ohci->regs->cmdstatus);
} }
break; break;
...@@ -663,7 +672,7 @@ static void td_submit_urb ( ...@@ -663,7 +672,7 @@ static void td_submit_urb (
td_fill (ohci, info, data, 0, urb, cnt++); td_fill (ohci, info, data, 0, urb, cnt++);
/* maybe kickstart control list */ /* maybe kickstart control list */
wmb (); wmb ();
writel (OHCI_CLF, &ohci->regs->cmdstatus); ohci_writel (ohci, OHCI_CLF, &ohci->regs->cmdstatus);
break; break;
/* ISO has no retransmit, so no toggle; and it uses special TDs. /* ISO has no retransmit, so no toggle; and it uses special TDs.
...@@ -692,7 +701,7 @@ static void td_submit_urb ( ...@@ -692,7 +701,7 @@ static void td_submit_urb (
if (periodic) { if (periodic) {
wmb (); wmb ();
ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE; ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
} }
// ASSERT (urb_priv->length == cnt); // ASSERT (urb_priv->length == cnt);
...@@ -707,14 +716,14 @@ static void td_submit_urb ( ...@@ -707,14 +716,14 @@ static void td_submit_urb (
*/ */
static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
{ {
u32 tdINFO = le32_to_cpup (&td->hwINFO); u32 tdINFO = hc32_to_cpup (ohci, &td->hwINFO);
int cc = 0; int cc = 0;
list_del (&td->td_list); list_del (&td->td_list);
/* ISO ... drivers see per-TD length/status */ /* ISO ... drivers see per-TD length/status */
if (tdINFO & TD_ISO) { if (tdINFO & TD_ISO) {
u16 tdPSW = le16_to_cpu (td->hwPSW [0]); u16 tdPSW = hc16_to_cpu (ohci, td->hwPSW [0]);
int dlen = 0; int dlen = 0;
/* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */ /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */
...@@ -746,7 +755,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) ...@@ -746,7 +755,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
*/ */
} else { } else {
int type = usb_pipetype (urb->pipe); int type = usb_pipetype (urb->pipe);
u32 tdBE = le32_to_cpup (&td->hwBE); u32 tdBE = hc32_to_cpup (ohci, &td->hwBE);
cc = TD_CC_GET (tdINFO); cc = TD_CC_GET (tdINFO);
...@@ -767,7 +776,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) ...@@ -767,7 +776,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
urb->actual_length += tdBE - td->data_dma + 1; urb->actual_length += tdBE - td->data_dma + 1;
else else
urb->actual_length += urb->actual_length +=
le32_to_cpup (&td->hwCBP) hc32_to_cpup (ohci, &td->hwCBP)
- td->data_dma; - td->data_dma;
} }
...@@ -788,14 +797,14 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) ...@@ -788,14 +797,14 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
struct urb *urb = td->urb; struct urb *urb = td->urb;
struct ed *ed = td->ed; struct ed *ed = td->ed;
struct list_head *tmp = td->td_list.next; struct list_head *tmp = td->td_list.next;
__le32 toggle = ed->hwHeadP & cpu_to_le32 (ED_C); __hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C);
/* clear ed halt; this is the td that caused it, but keep it inactive /* clear ed halt; this is the td that caused it, but keep it inactive
* until its urb->complete() has a chance to clean up. * until its urb->complete() has a chance to clean up.
*/ */
ed->hwINFO |= cpu_to_le32 (ED_SKIP); ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb (); wmb ();
ed->hwHeadP &= ~cpu_to_le32 (ED_H); ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
/* put any later tds from this urb onto the donelist, after 'td', /* put any later tds from this urb onto the donelist, after 'td',
* order won't matter here: no errors, and nothing was transferred. * order won't matter here: no errors, and nothing was transferred.
...@@ -803,7 +812,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) ...@@ -803,7 +812,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
*/ */
while (tmp != &ed->td_list) { while (tmp != &ed->td_list) {
struct td *next; struct td *next;
__le32 info; __hc32 info;
next = list_entry (tmp, struct td, td_list); next = list_entry (tmp, struct td, td_list);
tmp = next->td_list.next; tmp = next->td_list.next;
...@@ -819,8 +828,8 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) ...@@ -819,8 +828,8 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
* and clear ED_SKIP. * and clear ED_SKIP.
*/ */
info = next->hwINFO; info = next->hwINFO;
info |= cpu_to_le32 (TD_DONE); info |= cpu_to_hc32 (ohci, TD_DONE);
info &= ~cpu_to_le32 (TD_CC); info &= ~cpu_to_hc32 (ohci, TD_CC);
next->hwINFO = info; next->hwINFO = info;
next->next_dl_td = rev; next->next_dl_td = rev;
...@@ -848,7 +857,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) ...@@ -848,7 +857,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
urb, urb->dev->devpath, urb, urb->dev->devpath,
usb_pipeendpoint (urb->pipe), usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out", usb_pipein (urb->pipe) ? "in" : "out",
le32_to_cpu (td->hwINFO), hc32_to_cpu (ohci, td->hwINFO),
cc, cc_to_error [cc]); cc, cc_to_error [cc]);
} }
...@@ -864,7 +873,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -864,7 +873,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
struct td *td_rev = NULL; struct td *td_rev = NULL;
struct td *td = NULL; struct td *td = NULL;
td_dma = le32_to_cpup (&ohci->hcca->done_head); td_dma = hc32_to_cpup (ohci, &ohci->hcca->done_head);
ohci->hcca->done_head = 0; ohci->hcca->done_head = 0;
wmb(); wmb();
...@@ -880,20 +889,20 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -880,20 +889,20 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
break; break;
} }
td->hwINFO |= cpu_to_le32 (TD_DONE); td->hwINFO |= cpu_to_hc32 (ohci, TD_DONE);
cc = TD_CC_GET (le32_to_cpup (&td->hwINFO)); cc = TD_CC_GET (hc32_to_cpup (ohci, &td->hwINFO));
/* Non-iso endpoints can halt on error; un-halt, /* Non-iso endpoints can halt on error; un-halt,
* and dequeue any other TDs from this urb. * and dequeue any other TDs from this urb.
* No other TD could have caused the halt. * No other TD could have caused the halt.
*/ */
if (cc != TD_CC_NOERROR if (cc != TD_CC_NOERROR
&& (td->ed->hwHeadP & cpu_to_le32 (ED_H))) && (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
td_rev = ed_halted (ohci, td, cc, td_rev); td_rev = ed_halted (ohci, td, cc, td_rev);
td->next_dl_td = td_rev; td->next_dl_td = td_rev;
td_rev = td; td_rev = td;
td_dma = le32_to_cpup (&td->hwNextTD); td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
} }
return td_rev; return td_rev;
} }
...@@ -910,7 +919,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -910,7 +919,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) { for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) {
struct list_head *entry, *tmp; struct list_head *entry, *tmp;
int completed, modified; int completed, modified;
__le32 *prev; __hc32 *prev;
/* only take off EDs that the HC isn't using, accounting for /* only take off EDs that the HC isn't using, accounting for
* frame counter wraps and EDs with partially retired TDs * frame counter wraps and EDs with partially retired TDs
...@@ -928,7 +937,8 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -928,7 +937,8 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
td = list_entry (ed->td_list.next, struct td, td = list_entry (ed->td_list.next, struct td,
td_list); td_list);
head = le32_to_cpu (ed->hwHeadP) & TD_MASK; head = hc32_to_cpu (ohci, ed->hwHeadP) &
TD_MASK;
/* INTR_WDH may need to clean up first */ /* INTR_WDH may need to clean up first */
if (td->td_dma != head) if (td->td_dma != head)
...@@ -959,7 +969,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -959,7 +969,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
struct td *td; struct td *td;
struct urb *urb; struct urb *urb;
urb_priv_t *urb_priv; urb_priv_t *urb_priv;
__le32 savebits; __hc32 savebits;
td = list_entry (entry, struct td, td_list); td = list_entry (entry, struct td, td_list);
urb = td->urb; urb = td->urb;
...@@ -971,7 +981,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -971,7 +981,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
} }
/* patch pointer hc uses */ /* patch pointer hc uses */
savebits = *prev & ~cpu_to_le32 (TD_MASK); savebits = *prev & ~cpu_to_hc32 (ohci, TD_MASK);
*prev = td->hwNextTD | savebits; *prev = td->hwNextTD | savebits;
/* HC may have partly processed this TD */ /* HC may have partly processed this TD */
...@@ -989,10 +999,10 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -989,10 +999,10 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
/* ED's now officially unlinked, hc doesn't see */ /* ED's now officially unlinked, hc doesn't see */
ed->state = ED_IDLE; ed->state = ED_IDLE;
ed->hwHeadP &= ~cpu_to_le32(ED_H); ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
ed->hwNextED = 0; ed->hwNextED = 0;
wmb (); wmb ();
ed->hwINFO &= ~cpu_to_le32 (ED_SKIP | ED_DEQUEUE); ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE);
/* but if there's work queued, reschedule */ /* but if there's work queued, reschedule */
if (!list_empty (&ed->td_list)) { if (!list_empty (&ed->td_list)) {
...@@ -1014,24 +1024,27 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -1014,24 +1024,27 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
command |= OHCI_CLF; command |= OHCI_CLF;
if (!(ohci->hc_control & OHCI_CTRL_CLE)) { if (!(ohci->hc_control & OHCI_CTRL_CLE)) {
control |= OHCI_CTRL_CLE; control |= OHCI_CTRL_CLE;
writel (0, &ohci->regs->ed_controlcurrent); ohci_writel (ohci, 0,
&ohci->regs->ed_controlcurrent);
} }
} }
if (ohci->ed_bulktail) { if (ohci->ed_bulktail) {
command |= OHCI_BLF; command |= OHCI_BLF;
if (!(ohci->hc_control & OHCI_CTRL_BLE)) { if (!(ohci->hc_control & OHCI_CTRL_BLE)) {
control |= OHCI_CTRL_BLE; control |= OHCI_CTRL_BLE;
writel (0, &ohci->regs->ed_bulkcurrent); ohci_writel (ohci, 0,
&ohci->regs->ed_bulkcurrent);
} }
} }
/* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
if (control) { if (control) {
ohci->hc_control |= control; ohci->hc_control |= control;
writel (ohci->hc_control, &ohci->regs->control); ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
} }
if (command) if (command)
writel (command, &ohci->regs->cmdstatus); ohci_writel (ohci, command, &ohci->regs->cmdstatus);
} }
} }
...@@ -1071,19 +1084,19 @@ dl_done_list (struct ohci_hcd *ohci, struct pt_regs *regs) ...@@ -1071,19 +1084,19 @@ dl_done_list (struct ohci_hcd *ohci, struct pt_regs *regs)
start_ed_unlink (ohci, ed); start_ed_unlink (ohci, ed);
/* ... reenabling halted EDs only after fault cleanup */ /* ... reenabling halted EDs only after fault cleanup */
} else if ((ed->hwINFO & cpu_to_le32 (ED_SKIP | ED_DEQUEUE)) } else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
== cpu_to_le32 (ED_SKIP)) { == cpu_to_hc32 (ohci, ED_SKIP)) {
td = list_entry (ed->td_list.next, struct td, td_list); td = list_entry (ed->td_list.next, struct td, td_list);
if (!(td->hwINFO & cpu_to_le32 (TD_DONE))) { if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
ed->hwINFO &= ~cpu_to_le32 (ED_SKIP); ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
/* ... hc may need waking-up */ /* ... hc may need waking-up */
switch (ed->type) { switch (ed->type) {
case PIPE_CONTROL: case PIPE_CONTROL:
writel (OHCI_CLF, ohci_writel (ohci, OHCI_CLF,
&ohci->regs->cmdstatus); &ohci->regs->cmdstatus);
break; break;
case PIPE_BULK: case PIPE_BULK:
writel (OHCI_BLF, ohci_writel (ohci, OHCI_BLF,
&ohci->regs->cmdstatus); &ohci->regs->cmdstatus);
break; break;
} }
......
...@@ -6,6 +6,14 @@ ...@@ -6,6 +6,14 @@
* *
* This file is licenced under the GPL. * This file is licenced under the GPL.
*/ */
/*
* __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
* __leXX (normally) or __beXX (given OHCI_BIG_ENDIAN), depending on the
* host controller implementation.
*/
typedef __u32 __bitwise __hc32;
typedef __u16 __bitwise __hc16;
/* /*
* OHCI Endpoint Descriptor (ED) ... holds TD queue * OHCI Endpoint Descriptor (ED) ... holds TD queue
...@@ -15,8 +23,8 @@ ...@@ -15,8 +23,8 @@
* both EHCI and UHCI call similar structures a "QH". * both EHCI and UHCI call similar structures a "QH".
*/ */
struct ed { struct ed {
/* first fields are hardware-specified, le32 */ /* first fields are hardware-specified */
__le32 hwINFO; /* endpoint config bitmap */ __hc32 hwINFO; /* endpoint config bitmap */
/* info bits defined by hcd */ /* info bits defined by hcd */
#define ED_DEQUEUE (1 << 27) #define ED_DEQUEUE (1 << 27)
/* info bits defined by the hardware */ /* info bits defined by the hardware */
...@@ -25,11 +33,11 @@ struct ed { ...@@ -25,11 +33,11 @@ struct ed {
#define ED_LOWSPEED (1 << 13) #define ED_LOWSPEED (1 << 13)
#define ED_OUT (0x01 << 11) #define ED_OUT (0x01 << 11)
#define ED_IN (0x02 << 11) #define ED_IN (0x02 << 11)
__le32 hwTailP; /* tail of TD list */ __hc32 hwTailP; /* tail of TD list */
__le32 hwHeadP; /* head of TD list (hc r/w) */ __hc32 hwHeadP; /* head of TD list (hc r/w) */
#define ED_C (0x02) /* toggle carry */ #define ED_C (0x02) /* toggle carry */
#define ED_H (0x01) /* halted */ #define ED_H (0x01) /* halted */
__le32 hwNextED; /* next ED in list */ __hc32 hwNextED; /* next ED in list */
/* rest are purely for the driver's use */ /* rest are purely for the driver's use */
dma_addr_t dma; /* addr of ED */ dma_addr_t dma; /* addr of ED */
...@@ -69,8 +77,8 @@ struct ed { ...@@ -69,8 +77,8 @@ struct ed {
* and 4.3.2 (iso) * and 4.3.2 (iso)
*/ */
struct td { struct td {
/* first fields are hardware-specified, le32 */ /* first fields are hardware-specified */
__le32 hwINFO; /* transfer info bitmask */ __hc32 hwINFO; /* transfer info bitmask */
/* hwINFO bits for both general and iso tds: */ /* hwINFO bits for both general and iso tds: */
#define TD_CC 0xf0000000 /* condition code */ #define TD_CC 0xf0000000 /* condition code */
...@@ -99,13 +107,13 @@ struct td { ...@@ -99,13 +107,13 @@ struct td {
/* (no hwINFO #defines yet for iso tds) */ /* (no hwINFO #defines yet for iso tds) */
__le32 hwCBP; /* Current Buffer Pointer (or 0) */ __hc32 hwCBP; /* Current Buffer Pointer (or 0) */
__le32 hwNextTD; /* Next TD Pointer */ __hc32 hwNextTD; /* Next TD Pointer */
__le32 hwBE; /* Memory Buffer End Pointer */ __hc32 hwBE; /* Memory Buffer End Pointer */
/* PSW is only for ISO */ /* PSW is only for ISO */
#define MAXPSW 1 /* hardware allows 8 */ #define MAXPSW 1 /* hardware allows 8 */
__le16 hwPSW [MAXPSW]; __hc16 hwPSW [MAXPSW];
/* rest are purely for the driver's use */ /* rest are purely for the driver's use */
__u8 index; __u8 index;
...@@ -170,20 +178,20 @@ static const int cc_to_error [16] = { ...@@ -170,20 +178,20 @@ static const int cc_to_error [16] = {
*/ */
struct ohci_hcca { struct ohci_hcca {
#define NUM_INTS 32 #define NUM_INTS 32
__le32 int_table [NUM_INTS]; /* periodic schedule */ __hc32 int_table [NUM_INTS]; /* periodic schedule */
/* /*
* OHCI defines u16 frame_no, followed by u16 zero pad. * OHCI defines u16 frame_no, followed by u16 zero pad.
* Since some processors can't do 16 bit bus accesses, * 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 bit byteswapped access.
*/ */
__le32 frame_no; /* current frame number */ __hc32 frame_no; /* current frame number */
#define OHCI_FRAME_NO(hccap) ((u16)le32_to_cpup(&(hccap)->frame_no)) __hc32 done_head; /* info returned for an interrupt */
__le32 done_head; /* info returned for an interrupt */
u8 reserved_for_hc [116]; u8 reserved_for_hc [116];
u8 what [4]; /* spec only identifies 252 bytes :) */ u8 what [4]; /* spec only identifies 252 bytes :) */
} __attribute__ ((aligned(256))); } __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. * This is the structure of the OHCI controller's memory mapped I/O region.
...@@ -192,36 +200,36 @@ struct ohci_hcca { ...@@ -192,36 +200,36 @@ struct ohci_hcca {
*/ */
struct ohci_regs { struct ohci_regs {
/* control and status registers (section 7.1) */ /* control and status registers (section 7.1) */
__u32 revision; __hc32 revision;
__u32 control; __hc32 control;
__u32 cmdstatus; __hc32 cmdstatus;
__u32 intrstatus; __hc32 intrstatus;
__u32 intrenable; __hc32 intrenable;
__u32 intrdisable; __hc32 intrdisable;
/* memory pointers (section 7.2) */ /* memory pointers (section 7.2) */
__u32 hcca; __hc32 hcca;
__u32 ed_periodcurrent; __hc32 ed_periodcurrent;
__u32 ed_controlhead; __hc32 ed_controlhead;
__u32 ed_controlcurrent; __hc32 ed_controlcurrent;
__u32 ed_bulkhead; __hc32 ed_bulkhead;
__u32 ed_bulkcurrent; __hc32 ed_bulkcurrent;
__u32 donehead; __hc32 donehead;
/* frame counters (section 7.3) */ /* frame counters (section 7.3) */
__u32 fminterval; __hc32 fminterval;
__u32 fmremaining; __hc32 fmremaining;
__u32 fmnumber; __hc32 fmnumber;
__u32 periodicstart; __hc32 periodicstart;
__u32 lsthresh; __hc32 lsthresh;
/* Root hub ports (section 7.4) */ /* Root hub ports (section 7.4) */
struct ohci_roothub_regs { struct ohci_roothub_regs {
__u32 a; __hc32 a;
__u32 b; __hc32 b;
__u32 status; __hc32 status;
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */ #define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */
__u32 portstatus [MAX_ROOT_PORTS]; __hc32 portstatus [MAX_ROOT_PORTS];
} roothub; } roothub;
/* and optional "legacy support" registers (appendix B) at 0x0100 */ /* and optional "legacy support" registers (appendix B) at 0x0100 */
...@@ -392,6 +400,7 @@ struct ohci_hcd { ...@@ -392,6 +400,7 @@ struct ohci_hcd {
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ #define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */
#define OHCI_BIG_ENDIAN 0x08 /* big endian HC */
// there are also chip quirks/bugs in init logic // there are also chip quirks/bugs in init logic
}; };
...@@ -400,24 +409,6 @@ struct ohci_hcd { ...@@ -400,24 +409,6 @@ struct ohci_hcd {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static inline void disable (struct ohci_hcd *ohci)
{
ohci->hcd.state = USB_STATE_HALT;
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
#define LSTHRESH 0x628 /* lowspeed bit threshold */
static inline void periodic_reinit (struct ohci_hcd *ohci)
{
u32 fi = ohci->fminterval & 0x0ffff;
writel (((9 * fi) / 10) & 0x3fff, &ohci->regs->periodicstart);
}
/*-------------------------------------------------------------------------*/
#ifndef DEBUG #ifndef DEBUG
#define STUB_DEBUG_FILES #define STUB_DEBUG_FILES
#endif /* DEBUG */ #endif /* DEBUG */
...@@ -439,44 +430,162 @@ static inline void periodic_reinit (struct ohci_hcd *ohci) ...@@ -439,44 +430,162 @@ static inline void periodic_reinit (struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/*
* While most USB host controllers implement their registers and
* in-memory communication descriptors in little-endian format,
* a minority (notably the IBM STB04XXX and the Motorola MPC5200
* processors) 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_OHCI_BIG_ENDIAN
#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN
#define big_endian(ohci) (ohci->flags & OHCI_BIG_ENDIAN) /* either */
#else
#define big_endian(ohci) 1 /* only big endian */
#endif
/*
* 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 ohci_readl (const struct ohci_hcd *ohci,
__hc32 __iomem * regs)
{
return big_endian(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) :
writel (val, (__force u32 *)regs);
}
#else /* !CONFIG_USB_OHCI_BIG_ENDIAN */
#define big_endian(ohci) 0 /* only little endian */
#ifdef CONFIG_ARCH_LH7A404 #ifdef CONFIG_ARCH_LH7A404
/* Marc Singer: at the time this code was written, the LH7A404 /* Marc Singer: at the time this code was written, the LH7A404
* had a problem reading the USB host registers. This * had a problem reading the USB host registers. This
* implementation of the ohci_readl function performs the read * implementation of the ohci_readl function performs the read
* twice as a work-around. * twice as a work-around.
*/ */
static inline unsigned int ohci_readl (void* regs) static inline unsigned int
ohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs)
{ {
*(volatile unsigned int*) regs; *(volatile __force unsigned int*) regs;
return *(volatile unsigned int*) regs; return *(volatile __force unsigned int*) regs;
} }
#else #else
/* Standard version of ohci_readl uses standard, platform /* Standard version of ohci_readl uses standard, platform
* specific implementation. */ * specific implementation. */
static inline unsigned int ohci_readl (void __iomem * regs) static inline unsigned int
ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs)
{ {
return readl (regs); return readl ((__force u32 *)regs);
} }
#endif #endif
static inline void ohci_writel (const struct ohci_hcd *ohci,
const unsigned int val, __hc32 __iomem *regs)
{
writel (val, (__force u32 *)regs);
}
#endif /* !CONFIG_USB_OHCI_BIG_ENDIAN */
/*-------------------------------------------------------------------------*/
/* cpu to ohci */
static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x)
{
return big_endian(ohci) ? cpu_to_be16(x) : cpu_to_le16(x);
}
static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x)
{
return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x);
}
static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x)
{
return big_endian(ohci) ? cpu_to_be32(x) : cpu_to_le32(x);
}
static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x)
{
return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x);
}
/* ohci to cpu */
static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x)
{
return big_endian(ohci) ? be16_to_cpu(x) : le16_to_cpu(x);
}
static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x)
{
return big_endian(ohci) ? be16_to_cpup(x) : le16_to_cpup(x);
}
static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x)
{
return big_endian(ohci) ? be32_to_cpu(x) : le32_to_cpu(x);
}
static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
{
return big_endian(ohci) ? be32_to_cpup(x) : le32_to_cpup(x);
}
/*-------------------------------------------------------------------------*/
static inline void disable (struct ohci_hcd *ohci)
{
ohci->hcd.state = USB_STATE_HALT;
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
#define LSTHRESH 0x628 /* lowspeed bit threshold */
static inline void periodic_reinit (struct ohci_hcd *ohci)
{
u32 fi = ohci->fminterval & 0x0ffff;
ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff,
&ohci->regs->periodicstart);
}
/* AMD-756 (D2 rev) reports corrupt register contents in some cases. /* AMD-756 (D2 rev) reports corrupt register contents in some cases.
* The erratum (#4) description is incorrect. AMD's workaround waits * The erratum (#4) description is incorrect. AMD's workaround waits
* till some bits (mostly reserved) are clear; ok for all revs. * till some bits (mostly reserved) are clear; ok for all revs.
*/ */
#define read_roothub(hc, register, mask) ({ \ #define read_roothub(hc, register, mask) ({ \
u32 temp = ohci_readl (&hc->regs->roothub.register); \ u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \
if (temp == -1) \ if (temp == -1) \
disable (hc); \ disable (hc); \
else if (hc->flags & OHCI_QUIRK_AMD756) \ else if (hc->flags & OHCI_QUIRK_AMD756) \
while (temp & mask) \ while (temp & mask) \
temp = ohci_readl (&hc->regs->roothub.register); \ temp = ohci_readl (hc, &hc->regs->roothub.register); \
temp; }) temp; })
static u32 roothub_a (struct ohci_hcd *hc) static u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); } { return read_roothub (hc, a, 0xfc0fe000); }
static inline u32 roothub_b (struct ohci_hcd *hc) static inline u32 roothub_b (struct ohci_hcd *hc)
{ return ohci_readl (&hc->regs->roothub.b); } { return ohci_readl (hc, &hc->regs->roothub.b); }
static inline u32 roothub_status (struct ohci_hcd *hc) static inline u32 roothub_status (struct ohci_hcd *hc)
{ return ohci_readl (&hc->regs->roothub.status); } { return ohci_readl (hc, &hc->regs->roothub.status); }
static u32 roothub_portstatus (struct ohci_hcd *hc, int i) static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); } { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment