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;
......
This diff is collapsed.
This diff is collapsed.
......@@ -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);
}
......
This diff is collapsed.
This diff is collapsed.
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