USB: EHCI: Support controllers with big endian capability regs

The two first HC capability registers (CAPLENGTH and HCIVERSION)
are defined as one 8-bit and one 16-bit register. Most HC
implementations have selected to treat these registers as part
of a 32-bit register, giving the same layout for both big and
small endian systems.

This patch adds a new quirk, big_endian_capbase, to support
controllers with big endian register interfaces that treat
HCIVERSION and CAPLENGTH as individual registers.

Signed-off-by: Jan Andersson <jan@gaisler.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Jan Andersson 2011-05-03 20:11:57 +02:00 committed by Greg Kroah-Hartman
parent 2ce2c3ac88
commit c430131a02
27 changed files with 48 additions and 30 deletions

View file

@ -102,6 +102,9 @@ static struct kgdb_io kgdbdbgp_io_ops;
#define dbgp_kgdb_mode (0)
#endif
/* Local version of HC_LENGTH macro as ehci struct is not available here */
#define EARLY_HC_LENGTH(p) (0x00ff & (p)) /* bits 7 : 0 */
/*
* USB Packet IDs (PIDs)
*/
@ -892,7 +895,7 @@ int __init early_dbgp_init(char *s)
dbgp_printk("ehci_bar: %p\n", ehci_bar);
ehci_caps = ehci_bar;
ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase));
ehci_regs = ehci_bar + EARLY_HC_LENGTH(readl(&ehci_caps->hc_capbase));
ehci_debug = ehci_bar + offset;
ehci_dev.bus = bus;
ehci_dev.slot = slot;

View file

@ -44,6 +44,7 @@ static int ehci_ath79_init(struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct platform_device *pdev = to_platform_device(hcd->self.controller);
const struct platform_device_id *id;
int hclength;
int ret;
id = platform_get_device_id(pdev);
@ -52,21 +53,20 @@ static int ehci_ath79_init(struct usb_hcd *hcd)
return -EINVAL;
}
hclength = HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
switch (id->driver_data) {
case EHCI_ATH79_IP_V1:
ehci->has_synopsys_hc_bug = 1;
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->regs = hcd->regs + hclength;
break;
case EHCI_ATH79_IP_V2:
hcd->has_tt = 1;
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->regs = hcd->regs + 0x100 + hclength;
break;
default:

View file

@ -56,7 +56,7 @@ static int ehci_atmel_setup(struct usb_hcd *hcd)
/* registers start at offset 0x0 */
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -175,7 +175,8 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
ehci->regs = hcd->regs +
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = readl(&ehci->caps->hcs_params);

View file

@ -34,7 +34,7 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd)
ehci->caps = hcd->regs;
ehci->regs = hcd->regs
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 0;

View file

@ -726,7 +726,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
}
/* Capability Registers */
i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
i = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
temp = scnprintf (next, size,
"bus %s, device %s\n"
"%s\n"

View file

@ -324,7 +324,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -739,7 +739,7 @@ static int ehci_run (struct usb_hcd *hcd)
up_write(&ehci_cf_port_reset_rwsem);
ehci->last_periodic_enable = ktime_get_real();
temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci_info (ehci,
"USB %x.%x started, EHCI %x.%02x%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),

View file

@ -23,7 +23,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 1;

View file

@ -41,7 +41,7 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
ehci->caps = USB_CAPLENGTH;
ehci->regs = USB_CAPLENGTH +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -208,7 +208,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
/* set up the PORTSCx register */
ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);

View file

@ -151,7 +151,7 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

View file

@ -188,7 +188,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
/* we know this is the memory we want, no need to ioremap again */
omap_ehci->caps = hcd->regs;
omap_ehci->regs = hcd->regs
+ HC_LENGTH(readl(&omap_ehci->caps->hc_capbase));
+ HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase));
dbg_hcs_params(omap_ehci, "reset");
dbg_hcc_params(omap_ehci, "reset");

View file

@ -251,7 +251,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 1;
ehci->sbrn = 0x20;

View file

@ -70,7 +70,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -83,7 +83,7 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -179,7 +179,7 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

View file

@ -29,7 +29,7 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
ehci->big_endian_mmio = 1;
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");

View file

@ -126,7 +126,8 @@ static int s5p_ehci_probe(struct platform_device *pdev)
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
ehci->regs = hcd->regs +
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -23,7 +23,7 @@ static int ehci_sh_reset(struct usb_hcd *hcd)
int ret;
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");

View file

@ -38,7 +38,7 @@ static int ehci_spear_setup(struct usb_hcd *hcd)
/* registers start at offset 0x0 */
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
&ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

View file

@ -400,7 +400,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(readl(&ehci->caps->hc_capbase));
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -121,7 +121,8 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev)
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
ehci->regs = hcd->regs +
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");

View file

@ -57,7 +57,7 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
/* enable PHY 0,1,the regs only apply to w90p910
* 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of

View file

@ -220,7 +220,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
*/
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

View file

@ -128,6 +128,7 @@ struct ehci_hcd { /* one per controller */
unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned big_endian_mmio:1;
unsigned big_endian_desc:1;
unsigned big_endian_capbase:1;
unsigned has_amcc_usb23:1;
unsigned need_io_watchdog:1;
unsigned broken_periodic:1;
@ -605,12 +606,18 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
* 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.
*
* ehci_big_endian_capbase is a special quirk for controllers that
* implement the HC capability registers as separate registers and not
* as fields of a 32-bit register.
*/
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
#define ehci_big_endian_mmio(e) ((e)->big_endian_mmio)
#define ehci_big_endian_capbase(e) ((e)->big_endian_capbase)
#else
#define ehci_big_endian_mmio(e) 0
#define ehci_big_endian_capbase(e) 0
#endif
/*

View file

@ -25,10 +25,15 @@
struct ehci_caps {
/* these fields are specified as 8 and 16 bit registers,
* but some hosts can't perform 8 or 16 bit PCI accesses.
* some hosts treat caplength and hciversion as parts of a 32-bit
* register, others treat them as two separate registers, this
* affects the memory map for big endian controllers.
*/
u32 hc_capbase;
#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */
#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */
#define HC_LENGTH(ehci, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \
(ehci_big_endian_capbase(ehci) ? 24 : 0)))
#define HC_VERSION(ehci, p) (0xffff&((p) >> /* bits 31:16 / offset 02h */ \
(ehci_big_endian_capbase(ehci) ? 0 : 16)))
u32 hcs_params; /* HCSPARAMS - offset 0x4 */
#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */
#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */