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)
struct ohci_regs __iomem *regs = controller->regs;
u32 temp;
temp = ohci_readl (&regs->revision) & 0xff;
temp = ohci_readl (controller, &regs->revision) & 0xff;
ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x10) ? "with" : "NO");
temp = ohci_readl (&regs->control);
temp = ohci_readl (controller, &regs->control);
ohci_dbg_sw (controller, next, size,
"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
temp,
......@@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
temp & OHCI_CTRL_CBSR
);
temp = ohci_readl (&regs->cmdstatus);
temp = ohci_readl (controller, &regs->cmdstatus);
ohci_dbg_sw (controller, next, size,
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
(temp & OHCI_SOC) >> 16,
......@@ -166,26 +166,33 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
);
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_readl (&regs->intrenable), next, size);
ohci_readl (controller, &regs->intrenable),
next, size);
// intrdisable always same as intrenable
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",
ohci_readl (&regs->ed_controlhead), next, size);
ohci_readl (controller, &regs->ed_controlhead),
next, size);
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",
ohci_readl (&regs->ed_bulkhead), next, size);
ohci_readl (controller, &regs->ed_bulkhead),
next, size);
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",
ohci_readl (&regs->donehead), next, size);
ohci_readl (controller, &regs->donehead), 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)
ohci_dump_status (controller, NULL, NULL);
if (controller->hcca)
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);
}
......@@ -279,13 +286,13 @@ static const char data1 [] = "DATA1";
static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
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",
label, td,
(tmp & TD_DONE) ? " (DONE)" : "",
td->urb, td->index,
le32_to_cpup (&td->hwNextTD));
hc32_to_cpup (ohci, &td->hwNextTD));
if ((tmp & TD_ISO) == 0) {
const char *toggle, *pid;
u32 cbp, be;
......@@ -306,8 +313,8 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
TD_CC_GET(tmp), /* EC, */ toggle,
(tmp & TD_DI) >> 21, pid,
(tmp & TD_R) ? "R" : "");
cbp = le32_to_cpup (&td->hwCBP);
be = le32_to_cpup (&td->hwBE);
cbp = hc32_to_cpup (ohci, &td->hwCBP);
be = hc32_to_cpup (ohci, &td->hwBE);
ohci_dbg (ohci, " cbp %08x be %08x (len %d)\n", cbp, be,
cbp ? (be + 1 - cbp) : 0);
} else {
......@@ -318,10 +325,10 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
(tmp & TD_DI) >> 21,
tmp & 0x0000ffff);
ohci_dbg (ohci, " bp0 %08x be %08x\n",
le32_to_cpup (&td->hwCBP) & ~0x0fff,
le32_to_cpup (&td->hwBE));
hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff,
hc32_to_cpup (ohci, &td->hwBE));
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;
ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i,
psw, cc,
......@@ -336,13 +343,13 @@ static void __attribute__((unused))
ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
const struct ed *ed, int verbose)
{
u32 tmp = le32_to_cpu (ed->hwINFO);
u32 tmp = hc32_to_cpu (ohci, ed->hwINFO);
char *type = "";
ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
label,
ed, ed->state, edstring (ed->type),
le32_to_cpup (&ed->hwNextED));
hc32_to_cpup (ohci, &ed->hwNextED));
switch (tmp & (ED_IN|ED_OUT)) {
case ED_OUT: type = "-OUT"; break;
case ED_IN: type = "-IN"; break;
......@@ -358,12 +365,12 @@ ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
0x000f & (tmp >> 7),
type,
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",
tmp,
(tmp & ED_C) ? data1 : data0,
(tmp & ED_H) ? " HALT" : "",
le32_to_cpup (&ed->hwTailP),
hc32_to_cpup (ohci, &ed->hwTailP),
verbose ? "" : " (not listing)");
if (verbose) {
struct list_head *tmp;
......@@ -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 */
while (ed) {
u32 info = le32_to_cpu (ed->hwINFO);
u32 headp = le32_to_cpu (ed->hwHeadP);
struct list_head *entry;
struct td *td;
u32 info = hc32_to_cpu (ohci, ed->hwINFO);
u32 headp = hc32_to_cpu (ohci, ed->hwHeadP);
struct list_head *entry;
struct td *td;
temp = scnprintf (buf, size,
"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)
u32 cbp, be;
td = list_entry (entry, struct td, td_list);
info = le32_to_cpup (&td->hwINFO);
cbp = le32_to_cpup (&td->hwCBP);
be = le32_to_cpup (&td->hwBE);
info = hc32_to_cpup (ohci, &td->hwINFO);
cbp = hc32_to_cpup (ohci, &td->hwCBP);
be = hc32_to_cpup (ohci, &td->hwBE);
temp = scnprintf (buf, size,
"\n\ttd %p %s %d cc=%x urb %p (%08x)",
td,
......@@ -535,7 +542,7 @@ show_periodic (struct class_device *class_dev, char *buf)
/* show more info the first time around */
if (temp == seen_count) {
u32 info = le32_to_cpu (ed->hwINFO);
u32 info = hc32_to_cpu (ohci, ed->hwINFO);
struct list_head *entry;
unsigned qlen = 0;
......@@ -555,8 +562,9 @@ show_periodic (struct class_device *class_dev, char *buf)
0x03ff & (info >> 16),
info,
(info & ED_SKIP) ? " K" : "",
(ed->hwHeadP & cpu_to_le32(ED_H)) ?
" H" : "");
(ed->hwHeadP &
cpu_to_hc32(ohci, ED_H)) ?
" H" : "");
size -= temp;
next += temp;
......@@ -628,10 +636,10 @@ show_registers (struct class_device *class_dev, char *buf)
/* hcca */
if (ohci->hcca)
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 */
rdata = ohci_readl (&regs->fminterval);
rdata = ohci_readl (ohci, &regs->fminterval);
temp = scnprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
rdata, (rdata >> 31) ? "FIT " : "",
......@@ -639,20 +647,20 @@ show_registers (struct class_device *class_dev, char *buf)
size -= 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",
rdata, (rdata >> 31) ? "FRT " : "",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = ohci_readl (&regs->periodicstart);
rdata = ohci_readl (ohci, &regs->periodicstart);
temp = scnprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = ohci_readl (&regs->lsthresh);
rdata = ohci_readl (ohci, &regs->lsthresh);
temp = scnprintf (next, size, "lsthresh 0x%04x\n",
rdata & 0x3fff);
size -= temp;
......
......@@ -260,7 +260,7 @@ static int ohci_urb_enqueue (
if (retval < 0)
goto fail0;
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 */
frame += max_t (u16, 8, ed->interval);
......@@ -403,14 +403,14 @@ static int ohci_get_frame (struct usb_hcd *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)
{
ohci->hc_control = ohci_readl (&ohci->regs->control);
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
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)
#ifndef IR_DISABLE
/* 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");
/* this timeout is arbitrary. we make it long, so systems
......@@ -439,9 +440,9 @@ static int ohci_init (struct ohci_hcd *ohci)
*/
temp = 500; /* arbitrary: five seconds */
writel (OHCI_INTR_OC, &ohci->regs->intrenable);
writel (OHCI_OCR, &ohci->regs->cmdstatus);
while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
ohci_writel (ohci, OHCI_INTR_OC, &ohci->regs->intrenable);
ohci_writel (ohci, OHCI_OCR, &ohci->regs->cmdstatus);
while (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_IR) {
msleep (10);
if (--temp == 0) {
ohci_err (ohci, "USB HC TakeOver failed!\n");
......@@ -453,9 +454,9 @@ static int ohci_init (struct ohci_hcd *ohci)
#endif
/* Disable HC interrupts */
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
// flush the writes
(void) ohci_readl (&ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
if (ohci->hcca)
return 0;
......@@ -491,7 +492,7 @@ static int ohci_run (struct ohci_hcd *ohci)
/* boot firmware should have set this up (5.1.1.3.1) */
if (first) {
temp = ohci_readl (&ohci->regs->fminterval);
temp = ohci_readl (ohci, &ohci->regs->fminterval);
ohci->fminterval = temp & 0x3fff;
if (ohci->fminterval != FI)
ohci_dbg (ohci, "fminterval delta %d\n",
......@@ -504,7 +505,7 @@ static int ohci_run (struct ohci_hcd *ohci)
* saved if boot firmware (BIOS/SMM/...) told us it's connected
* (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",
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
ohci->hc_control);
......@@ -530,20 +531,20 @@ static int ohci_run (struct ohci_hcd *ohci)
temp = 50 /* msec wait */;
break;
}
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
// flush the writes
(void) ohci_readl (&ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
msleep(temp);
if (power_switching) {
unsigned ports = roothub_a (ohci) & RH_A_NDP;
/* power down each port */
for (temp = 0; temp < ports; temp++)
writel (RH_PS_LSDA,
ohci_writel (ohci, RH_PS_LSDA,
&ohci->regs->roothub.portstatus [temp]);
}
// flush those writes
(void) ohci_readl (&ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
/* 2msec timelimit here means no irqs/preempt */
......@@ -551,9 +552,9 @@ static int ohci_run (struct ohci_hcd *ohci)
retry:
/* 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 */
while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
while ((ohci_readl (ohci, &ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
if (--temp == 0) {
spin_unlock_irq (&ohci->lock);
ohci_err (ohci, "USB HC reset timed out!\n");
......@@ -572,27 +573,27 @@ static int ohci_run (struct ohci_hcd *ohci)
* easily be a longstanding bug in chip init on Linux.
*/
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
(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
* The lists are empty now. */
writel (0, &ohci->regs->ed_controlhead);
writel (0, &ohci->regs->ed_bulkhead);
ohci_writel (ohci, 0, &ohci->regs->ed_controlhead);
ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead);
/* 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);
/* some OHCI implementations are finicky about how they init.
* bogus values here mean not even enumeration could work.
*/
if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|| !ohci_readl (&ohci->regs->periodicstart)) {
if ((ohci_readl (ohci, &ohci->regs->fminterval) & 0x3fff0000) == 0
|| !ohci_readl (ohci, &ohci->regs->periodicstart)) {
if (!(ohci->flags & OHCI_QUIRK_INITRESET)) {
ohci->flags |= OHCI_QUIRK_INITRESET;
ohci_dbg (ohci, "enabling initreset quirk\n");
......@@ -600,24 +601,24 @@ static int ohci_run (struct ohci_hcd *ohci)
}
spin_unlock_irq (&ohci->lock);
ohci_err (ohci, "init err (%08x %04x)\n",
ohci_readl (&ohci->regs->fminterval),
ohci_readl (&ohci->regs->periodicstart));
ohci_readl (ohci, &ohci->regs->fminterval),
ohci_readl (ohci, &ohci->regs->periodicstart));
return -EOVERFLOW;
}
/* start controller operations */
ohci->hc_control &= OHCI_CTRL_RWC;
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;
/* 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 */
mask = OHCI_INTR_INIT;
writel (mask, &ohci->regs->intrstatus);
writel (mask, &ohci->regs->intrenable);
ohci_writel (ohci, mask, &ohci->regs->intrstatus);
ohci_writel (ohci, mask, &ohci->regs->intrenable);
/* handle root hub init quirks ... */
temp = roothub_a (ohci);
......@@ -638,11 +639,12 @@ static int ohci_run (struct ohci_hcd *ohci)
*/
temp |= RH_A_NPS;
}
writel (temp, &ohci->regs->roothub.a);
writel (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
ohci_writel (ohci, temp, &ohci->regs->roothub.a);
ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);
ohci_writel (ohci, power_switching ? RH_B_PPCM : 0,
&ohci->regs->roothub.b);
// flush those writes
(void) ohci_readl (&ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
spin_unlock_irq (&ohci->lock);
......@@ -665,7 +667,7 @@ static int ohci_run (struct ohci_hcd *ohci)
if (!udev) {
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
return -ENOMEM;
}
......@@ -674,7 +676,7 @@ static int ohci_run (struct ohci_hcd *ohci)
usb_put_dev (udev);
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
return -ENODEV;
}
if (ohci->power_budget)
......@@ -697,17 +699,18 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
/* we can eliminate a (slow) ohci_readl()
if _only_ WDH caused this irq */
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;
/* 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);
ohci_dbg (ohci, "device removed!\n");
return IRQ_HANDLED;
/* 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;
}
......@@ -727,12 +730,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ints & OHCI_INTR_WDH) {
if (HCD_IS_RUNNING(hcd->state))
writel (OHCI_INTR_WDH, &regs->intrdisable);
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
spin_lock (&ohci->lock);
dl_done_list (ohci, ptregs);
spin_unlock (&ohci->lock);
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 */
......@@ -742,18 +745,17 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
*/
spin_lock (&ohci->lock);
if (ohci->ed_rm_list)
finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca),
ptregs);
finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
&& HCD_IS_RUNNING(ohci->hcd.state))
writel (OHCI_INTR_SF, &regs->intrdisable);
ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
if (HCD_IS_RUNNING(ohci->hcd.state)) {
writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable);
ohci_writel (ohci, ints, &regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
(void) ohci_readl (&ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
}
return IRQ_HANDLED;
......@@ -773,7 +775,7 @@ static void ohci_stop (struct usb_hcd *hcd)
flush_scheduled_work();
ohci_usb_reset (ohci);
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
remove_debug_files (ohci);
ohci_mem_cleanup (ohci);
......@@ -815,7 +817,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
switch (ed->state) {
case ED_OPER:
ed->state = ED_UNLINK;
ed->hwINFO |= cpu_to_le32(ED_DEQUEUE);
ed->hwINFO |= cpu_to_hc32(ohci, ED_DEQUEUE);
ed_deschedule (ohci, ed);
ed->ed_next = ohci->ed_rm_list;
......@@ -859,7 +861,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
*/
i = roothub_a (ohci) & RH_A_NDP;
while (i--)
writel (RH_PS_PSS,
ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [temp]);
ohci_dbg (ohci, "restart complete\n");
ohci->hcd.state = USB_STATE_RUNNING;
......
......@@ -58,14 +58,14 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
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) {
case OHCI_USB_RESUME:
ohci_dbg (ohci, "resume/suspend?\n");
ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_RESET;
writel (ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
/* FALL THROUGH */
case OHCI_USB_RESET:
status = -EBUSY;
......@@ -83,9 +83,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
int limit;
ohci->hc_control &= ~OHCI_SCHED_ENABLES;
writel (ohci->hc_control, &ohci->regs->control);
ohci->hc_control = ohci_readl (&ohci->regs->control);
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);
/* sched disables take effect on the next frame,
* then the last WDH could take 6+ msec
......@@ -95,15 +95,17 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
while (limit > 0) {
udelay (250);
limit =- 250;
if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
if (ohci_readl (ohci, &ohci->regs->intrstatus)
& OHCI_INTR_SF)
break;
}
dl_done_list (ohci, NULL);
mdelay (7);
}
dl_done_list (ohci, NULL);
finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), NULL);
writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
&ohci->regs->intrstatus);
/* maybe resume can wake root hub */
if (ohci->hcd.remote_wakeup)
......@@ -114,8 +116,8 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
/* Suspend hub */
ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_SUSPEND;
writel (ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
/* no resumes until devices finish suspending */
ohci->next_statechange = jiffies + msecs_to_jiffies (5);
......@@ -153,7 +155,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
return -EAGAIN;
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)) {
/* this can happen after suspend-to-disk */
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
......@@ -163,8 +165,8 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
case OHCI_USB_SUSPEND:
ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
ohci->hc_control |= OHCI_USB_RESUME;
writel (ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
ohci_dbg (ohci, "resume root hub\n");
break;
case OHCI_USB_RESUME:
......@@ -191,19 +193,21 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp = roothub_a (ohci) & RH_A_NDP;
enables = 0;
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 */
if (!(stat & RH_PS_PSS))
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 */
ohci->hcd.state = USB_STATE_RESUMING;
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;
if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n");
......@@ -211,32 +215,33 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
}
/* disable old schedule state, reinit from scratch */
writel (0, &ohci->regs->ed_controlhead);
writel (0, &ohci->regs->ed_controlcurrent);
writel (0, &ohci->regs->ed_bulkhead);
writel (0, &ohci->regs->ed_bulkcurrent);
writel (0, &ohci->regs->ed_periodcurrent);
writel ((u32) ohci->hcca_dma, &ohci->regs->hcca);
ohci_writel (ohci, 0, &ohci->regs->ed_controlhead);
ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent);
ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead);
ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent);
ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent);
ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);
periodic_reinit (ohci);
/* 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)
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
&ohci->regs->intrstatus);
/* Then re-enable operations */
writel (OHCI_USB_OPER, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
msleep (3);
temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
if (ohci->hcd.can_wakeup)
temp |= OHCI_CTRL_RWC;
ohci->hc_control = temp;
writel (temp, &ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
ohci_writel (ohci, temp, &ohci->regs->control);
(void) ohci_readl (ohci, &ohci->regs->control);
/* TRSMRCY */
msleep (10);
......@@ -251,13 +256,14 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp = 0;
if (!ohci->ed_rm_list) {
if (ohci->ed_controltail) {
writel (find_head (ohci->ed_controltail)->dma,
&ohci->regs->ed_controlhead);
ohci_writel (ohci,
find_head (ohci->ed_controltail)->dma,
&ohci->regs->ed_controlhead);
enables |= OHCI_CTRL_CLE;
temp |= OHCI_CLF;
}
if (ohci->ed_bulktail) {
writel (find_head (ohci->ed_bulktail)->dma,
ohci_writel (ohci, find_head (ohci->ed_bulktail)->dma,
&ohci->regs->ed_bulkhead);
enables |= OHCI_CTRL_BLE;
temp |= OHCI_BLF;
......@@ -269,10 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if (enables) {
ohci_dbg (ohci, "restarting schedules ... %08x\n", enables);
ohci->hc_control |= enables;
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
if (temp)
writel (temp, &ohci->regs->cmdstatus);
(void) ohci_readl (&ohci->regs->control);
ohci_writel (ohci, temp, &ohci->regs->cmdstatus);
(void) ohci_readl (ohci, &ohci->regs->control);
}
ohci->hcd.state = USB_STATE_RUNNING;
......@@ -313,8 +319,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (ports > MAX_ROOT_PORTS) {
if (!HCD_IS_RUNNING(ohci->hcd.state))
return -ESHUTDOWN;
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP);
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
return 0;
}
......@@ -403,7 +409,7 @@ ohci_hub_descriptor (
temp |= 0x0010;
else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */
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 */
rh = roothub_b (ohci);
......@@ -429,12 +435,12 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
port--;
/* 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))
return -ENODEV;
/* 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;
}
......@@ -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 temp;
u16 now = readl(&ohci->regs->fmnumber);
u16 now = ohci_readl(ohci, &ohci->regs->fmnumber);
u16 reset_done = now + PORT_RESET_MSEC;
/* 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)
do {
/* spin until any current reset finishes */
for (;;) {
temp = ohci_readl (portstat);
temp = ohci_readl (ohci, portstat);
if (!(temp & RH_PS_PRS))
break;
udelay (500);
......@@ -490,12 +496,12 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
if (!(temp & RH_PS_CCS))
break;
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 */
writel (RH_PS_PRS, portstat);
ohci_writel (ohci, RH_PS_PRS, portstat);
msleep(PORT_RESET_HW_MSEC);
now = readl(&ohci->regs->fmnumber);
now = ohci_readl(ohci, &ohci->regs->fmnumber);
} while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */
}
......@@ -517,7 +523,8 @@ static int ohci_hub_control (
case ClearHubFeature:
switch (wValue) {
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:
break;
default:
......@@ -560,8 +567,9 @@ static int ohci_hub_control (
default:
goto error;
}
writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
// ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
ohci_writel (ohci, temp,
&ohci->regs->roothub.portstatus [wIndex]);
// ohci_readl (ohci, &ohci->regs->roothub.portstatus [wIndex]);
break;
case GetHubDescriptor:
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
......@@ -604,11 +612,11 @@ static int ohci_hub_control (
start_hnp(ohci);
else
#endif
writel (RH_PS_PSS,
ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_POWER:
writel (RH_PS_PPS,
ohci_writel (ohci, RH_PS_PPS,
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_RESET:
......
......@@ -99,7 +99,7 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
if (td) {
/* in case hc fetches it, make it look dead */
memset (td, 0, sizeof *td);
td->hwNextTD = cpu_to_le32 (dma);
td->hwNextTD = cpu_to_hc32 (hc, dma);
td->td_dma = dma;
/* hashed in td_fill */
}
......@@ -115,7 +115,7 @@ td_free (struct ohci_hcd *hc, struct td *td)
prev = &(*prev)->td_hash;
if (*prev)
*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);
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)
if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0
&& hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0) {
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)
unsigned i;
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);
for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
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;
/* sorting each branch by period (slow before fast)
......@@ -156,7 +156,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
ed->hwNextED = *prev_p;
wmb ();
*prev = ed;
*prev_p = cpu_to_le32(ed->dma);
*prev_p = cpu_to_hc32(ohci, ed->dma);
wmb();
}
ohci->load [i] += ed->load;
......@@ -193,17 +193,20 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
case PIPE_CONTROL:
if (ohci->ed_controltail == NULL) {
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 {
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;
if (!ohci->ed_controltail && !ohci->ed_rm_list) {
wmb();
ohci->hc_control |= OHCI_CTRL_CLE;
writel (0, &ohci->regs->ed_controlcurrent);
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent);
ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
}
ohci->ed_controltail = ed;
break;
......@@ -211,17 +214,19 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
case PIPE_BULK:
if (ohci->ed_bulktail == NULL) {
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 {
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;
if (!ohci->ed_bulktail && !ohci->ed_rm_list) {
wmb();
ohci->hc_control |= OHCI_CTRL_BLE;
writel (0, &ohci->regs->ed_bulkcurrent);
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent);
ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
}
ohci->ed_bulktail = ed;
break;
......@@ -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) {
struct ed *temp;
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) {
prev_p = &temp->hwNextED;
......@@ -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;
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);
}
......@@ -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)
{
ed->hwINFO |= cpu_to_le32 (ED_SKIP);
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
ed->state = ED_UNLINK;
......@@ -320,10 +325,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (ed->ed_prev == NULL) {
if (!ed->hwNextED) {
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
} else
writel (le32_to_cpup (&ed->hwNextED),
ohci_writel (ohci,
hc32_to_cpup (ohci, &ed->hwNextED),
&ohci->regs->ed_controlhead);
} else {
ed->ed_prev->ed_next = ed->ed_next;
......@@ -344,10 +351,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (ed->ed_prev == NULL) {
if (!ed->hwNextED) {
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
} else
writel (le32_to_cpup (&ed->hwNextED),
ohci_writel (ohci,
hc32_to_cpup (ohci, &ed->hwNextED),
&ohci->regs->ed_bulkhead);
} else {
ed->ed_prev->ed_next = ed->ed_next;
......@@ -416,7 +425,7 @@ static struct ed *ed_get (
goto done;
}
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->state = ED_IDLE;
ed->type = type;
......@@ -450,7 +459,7 @@ static struct ed *ed_get (
/ 1000;
}
}
ed->hwINFO = cpu_to_le32(info);
ed->hwINFO = cpu_to_hc32(ohci, info);
}
done:
......@@ -468,7 +477,7 @@ static struct ed *ed_get (
*/
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);
/* rm_list is just singly linked, for simplicity */
......@@ -477,17 +486,17 @@ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
ohci->ed_rm_list = ed;
/* enable SOF interrupt */
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
// 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
* indicates when the HC isn't looking at it, so concurrent unlinks
* behave. frame_no wraps every 2^16 msec, and changes right before
* 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,
if (!len)
data = 0;
td->hwINFO = cpu_to_le32 (info);
td->hwINFO = cpu_to_hc32 (ohci, info);
if (is_iso) {
td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
td->hwPSW [0] = cpu_to_hc16 (ohci, (data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff;
} else {
td->hwCBP = cpu_to_le32 (data);
td->hwCBP = cpu_to_hc32 (ohci, data);
}
if (data)
td->hwBE = cpu_to_le32 (data + len - 1);
td->hwBE = cpu_to_hc32 (ohci, data + len - 1);
else
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 */
list_add_tail (&td->td_list, &td->ed->td_list);
......@@ -592,7 +601,7 @@ static void td_submit_urb (
if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
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;
......@@ -641,7 +650,7 @@ static void td_submit_urb (
/* maybe kickstart bulk list */
if (urb_priv->ed->type == PIPE_BULK) {
wmb ();
writel (OHCI_BLF, &ohci->regs->cmdstatus);
ohci_writel (ohci, OHCI_BLF, &ohci->regs->cmdstatus);
}
break;
......@@ -663,7 +672,7 @@ static void td_submit_urb (
td_fill (ohci, info, data, 0, urb, cnt++);
/* maybe kickstart control list */
wmb ();
writel (OHCI_CLF, &ohci->regs->cmdstatus);
ohci_writel (ohci, OHCI_CLF, &ohci->regs->cmdstatus);
break;
/* ISO has no retransmit, so no toggle; and it uses special TDs.
......@@ -692,7 +701,7 @@ static void td_submit_urb (
if (periodic) {
wmb ();
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);
......@@ -707,14 +716,14 @@ static void td_submit_urb (
*/
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;
list_del (&td->td_list);
/* ISO ... drivers see per-TD length/status */
if (tdINFO & TD_ISO) {
u16 tdPSW = le16_to_cpu (td->hwPSW [0]);
u16 tdPSW = hc16_to_cpu (ohci, td->hwPSW [0]);
int dlen = 0;
/* 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)
*/
} else {
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);
......@@ -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;
else
urb->actual_length +=
le32_to_cpup (&td->hwCBP)
hc32_to_cpup (ohci, &td->hwCBP)
- td->data_dma;
}
......@@ -788,14 +797,14 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
struct urb *urb = td->urb;
struct ed *ed = td->ed;
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
* 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 ();
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',
* 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)
*/
while (tmp != &ed->td_list) {
struct td *next;
__le32 info;
__hc32 info;
next = list_entry (tmp, struct td, td_list);
tmp = next->td_list.next;
......@@ -819,8 +828,8 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
* and clear ED_SKIP.
*/
info = next->hwINFO;
info |= cpu_to_le32 (TD_DONE);
info &= ~cpu_to_le32 (TD_CC);
info |= cpu_to_hc32 (ohci, TD_DONE);
info &= ~cpu_to_hc32 (ohci, TD_CC);
next->hwINFO = info;
next->next_dl_td = rev;
......@@ -848,7 +857,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
urb, urb->dev->devpath,
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out",
le32_to_cpu (td->hwINFO),
hc32_to_cpu (ohci, td->hwINFO),
cc, cc_to_error [cc]);
}
......@@ -864,7 +873,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
struct td *td_rev = 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;
wmb();
......@@ -880,20 +889,20 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
break;
}
td->hwINFO |= cpu_to_le32 (TD_DONE);
cc = TD_CC_GET (le32_to_cpup (&td->hwINFO));
td->hwINFO |= cpu_to_hc32 (ohci, TD_DONE);
cc = TD_CC_GET (hc32_to_cpup (ohci, &td->hwINFO));
/* Non-iso endpoints can halt on error; un-halt,
* and dequeue any other TDs from this urb.
* No other TD could have caused the halt.
*/
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->next_dl_td = td_rev;
td_rev = td;
td_dma = le32_to_cpup (&td->hwNextTD);
td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
}
return td_rev;
}
......@@ -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) {
struct list_head *entry, *tmp;
int completed, modified;
__le32 *prev;
__hc32 *prev;
/* only take off EDs that the HC isn't using, accounting for
* 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)
td = list_entry (ed->td_list.next, struct td,
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 */
if (td->td_dma != head)
......@@ -959,7 +969,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
struct td *td;
struct urb *urb;
urb_priv_t *urb_priv;
__le32 savebits;
__hc32 savebits;
td = list_entry (entry, struct td, td_list);
urb = td->urb;
......@@ -971,7 +981,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
}
/* patch pointer hc uses */
savebits = *prev & ~cpu_to_le32 (TD_MASK);
savebits = *prev & ~cpu_to_hc32 (ohci, TD_MASK);
*prev = td->hwNextTD | savebits;
/* HC may have partly processed this TD */
......@@ -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->state = ED_IDLE;
ed->hwHeadP &= ~cpu_to_le32(ED_H);
ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
ed->hwNextED = 0;
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 */
if (!list_empty (&ed->td_list)) {
......@@ -1014,24 +1024,27 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
command |= OHCI_CLF;
if (!(ohci->hc_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) {
command |= OHCI_BLF;
if (!(ohci->hc_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 */
if (control) {
ohci->hc_control |= control;
writel (ohci->hc_control, &ohci->regs->control);
ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
}
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)
start_ed_unlink (ohci, ed);
/* ... reenabling halted EDs only after fault cleanup */
} else if ((ed->hwINFO & cpu_to_le32 (ED_SKIP | ED_DEQUEUE))
== cpu_to_le32 (ED_SKIP)) {
} else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
== cpu_to_hc32 (ohci, ED_SKIP)) {
td = list_entry (ed->td_list.next, struct td, td_list);
if (!(td->hwINFO & cpu_to_le32 (TD_DONE))) {
ed->hwINFO &= ~cpu_to_le32 (ED_SKIP);
if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
/* ... hc may need waking-up */
switch (ed->type) {
case PIPE_CONTROL:
writel (OHCI_CLF,
ohci_writel (ohci, OHCI_CLF,
&ohci->regs->cmdstatus);
break;
case PIPE_BULK:
writel (OHCI_BLF,
ohci_writel (ohci, OHCI_BLF,
&ohci->regs->cmdstatus);
break;
}
......
......@@ -6,6 +6,14 @@
*
* 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
......@@ -15,8 +23,8 @@
* both EHCI and UHCI call similar structures a "QH".
*/
struct ed {
/* first fields are hardware-specified, le32 */
__le32 hwINFO; /* endpoint config bitmap */
/* first fields are hardware-specified */
__hc32 hwINFO; /* endpoint config bitmap */
/* info bits defined by hcd */
#define ED_DEQUEUE (1 << 27)
/* info bits defined by the hardware */
......@@ -25,11 +33,11 @@ struct ed {
#define ED_LOWSPEED (1 << 13)
#define ED_OUT (0x01 << 11)
#define ED_IN (0x02 << 11)
__le32 hwTailP; /* tail of TD list */
__le32 hwHeadP; /* head of TD list (hc r/w) */
__hc32 hwTailP; /* tail of TD list */
__hc32 hwHeadP; /* head of TD list (hc r/w) */
#define ED_C (0x02) /* toggle carry */
#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 */
dma_addr_t dma; /* addr of ED */
......@@ -69,8 +77,8 @@ struct ed {
* and 4.3.2 (iso)
*/
struct td {
/* first fields are hardware-specified, le32 */
__le32 hwINFO; /* transfer info bitmask */
/* first fields are hardware-specified */
__hc32 hwINFO; /* transfer info bitmask */
/* hwINFO bits for both general and iso tds: */
#define TD_CC 0xf0000000 /* condition code */
......@@ -99,13 +107,13 @@ struct td {
/* (no hwINFO #defines yet for iso tds) */
__le32 hwCBP; /* Current Buffer Pointer (or 0) */
__le32 hwNextTD; /* Next TD Pointer */
__le32 hwBE; /* Memory Buffer End Pointer */
__hc32 hwCBP; /* Current Buffer Pointer (or 0) */
__hc32 hwNextTD; /* Next TD Pointer */
__hc32 hwBE; /* Memory Buffer End Pointer */
/* PSW is only for ISO */
#define MAXPSW 1 /* hardware allows 8 */
__le16 hwPSW [MAXPSW];
__hc16 hwPSW [MAXPSW];
/* rest are purely for the driver's use */
__u8 index;
......@@ -170,20 +178,20 @@ static const int cc_to_error [16] = {
*/
struct ohci_hcca {
#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.
* Since some processors can't do 16 bit bus accesses,
* portable access must be a 32 bit byteswapped access.
*/
__le32 frame_no; /* current frame number */
#define OHCI_FRAME_NO(hccap) ((u16)le32_to_cpup(&(hccap)->frame_no))
__le32 done_head; /* info returned for an interrupt */
__hc32 frame_no; /* current frame number */
__hc32 done_head; /* info returned for an interrupt */
u8 reserved_for_hc [116];
u8 what [4]; /* spec only identifies 252 bytes :) */
} __attribute__ ((aligned(256)));
#define ohci_frame_no(ohci) ((u16)hc32_to_cpup(ohci,&(ohci)->hcca->frame_no))
/*
* This is the structure of the OHCI controller's memory mapped I/O region.
......@@ -192,36 +200,36 @@ struct ohci_hcca {
*/
struct ohci_regs {
/* control and status registers (section 7.1) */
__u32 revision;
__u32 control;
__u32 cmdstatus;
__u32 intrstatus;
__u32 intrenable;
__u32 intrdisable;
__hc32 revision;
__hc32 control;
__hc32 cmdstatus;
__hc32 intrstatus;
__hc32 intrenable;
__hc32 intrdisable;
/* memory pointers (section 7.2) */
__u32 hcca;
__u32 ed_periodcurrent;
__u32 ed_controlhead;
__u32 ed_controlcurrent;
__u32 ed_bulkhead;
__u32 ed_bulkcurrent;
__u32 donehead;
__hc32 hcca;
__hc32 ed_periodcurrent;
__hc32 ed_controlhead;
__hc32 ed_controlcurrent;
__hc32 ed_bulkhead;
__hc32 ed_bulkcurrent;
__hc32 donehead;
/* frame counters (section 7.3) */
__u32 fminterval;
__u32 fmremaining;
__u32 fmnumber;
__u32 periodicstart;
__u32 lsthresh;
__hc32 fminterval;
__hc32 fmremaining;
__hc32 fmnumber;
__hc32 periodicstart;
__hc32 lsthresh;
/* Root hub ports (section 7.4) */
struct ohci_roothub_regs {
__u32 a;
__u32 b;
__u32 status;
__hc32 a;
__hc32 b;
__hc32 status;
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */
__u32 portstatus [MAX_ROOT_PORTS];
__hc32 portstatus [MAX_ROOT_PORTS];
} roothub;
/* and optional "legacy support" registers (appendix B) at 0x0100 */
......@@ -392,6 +400,7 @@ struct ohci_hcd {
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */
#define OHCI_BIG_ENDIAN 0x08 /* big endian HC */
// there are also chip quirks/bugs in init logic
};
......@@ -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
#define STUB_DEBUG_FILES
#endif /* DEBUG */
......@@ -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
/* Marc Singer: at the time this code was written, the LH7A404
* had a problem reading the USB host registers. This
* implementation of the ohci_readl function performs the read
* 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;
return *(volatile unsigned int*) regs;
*(volatile __force unsigned int*) regs;
return *(volatile __force unsigned int*) regs;
}
#else
/* Standard version of ohci_readl uses standard, platform
* 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
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.
* The erratum (#4) description is incorrect. AMD's workaround waits
* till some bits (mostly reserved) are clear; ok for all revs.
*/
#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) \
disable (hc); \
else if (hc->flags & OHCI_QUIRK_AMD756) \
while (temp & mask) \
temp = ohci_readl (&hc->regs->roothub.register); \
temp = ohci_readl (hc, &hc->regs->roothub.register); \
temp; })
static u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); }
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)
{ 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)
{ 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