USB: EHCI: Support controllers with big endian capability regs
authorJan Andersson <jan@gaisler.com>
Tue, 3 May 2011 18:11:57 +0000 (20:11 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 3 May 2011 18:43:21 +0000 (11:43 -0700)
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>
27 files changed:
drivers/usb/early/ehci-dbgp.c
drivers/usb/host/ehci-ath79.c
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-cns3xxx.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-ixp4xx.c
drivers/usb/host/ehci-msm.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-octeon.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-pmcmsp.c
drivers/usb/host/ehci-ppc-of.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ehci-sh.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci-vt8500.c
drivers/usb/host/ehci-w90x900.c
drivers/usb/host/ehci-xilinx-of.c
drivers/usb/host/ehci.h
include/linux/usb/ehci_def.h

index a6a350f..1fc8f12 100644 (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;
index 7ea23b5..98cc8a1 100644 (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:
index b2ed55c..a5a3ef1 100644 (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");
 
index a869e3c..40b0028 100644 (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);
 
index 708a05b..d41745c 100644 (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;
index 693c29b..40a844c 100644 (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"
index 623732a..f380bf9 100644 (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");
 
index 83b7d5f..8164ffa 100644 (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),
index 89b7c70..50e600d 100644 (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;
index 9ce1b0b..b5a0bf6 100644 (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");
 
index 25c8c10..0c058be 100644 (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]);
index a31a031..ff55757 100644 (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);
 
index 7e41a95..3c482dc 100644 (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");
index 281e094..395bdb0 100644 (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;
index d5eaea7..660b80a 100644 (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");
index a216864..cd69099 100644 (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");
 
index 1f09f25..8552db6 100644 (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);
index 1dee33b..64626a7 100644 (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");
index 0c18f28..321a033 100644 (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");
index 595f70f..86a95bb 100644 (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");
index 75c0087..dbf1e4e 100644 (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);
index 7359bcb..02b2bfd 100644 (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");
index 2016806..47d7496 100644 (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");
index 6bc3580..52a027a 100644 (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
index effc58d..a64d6d6 100644 (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);
index e9ba8e2..d0792f5 100644 (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
 
 /*
index 7879943..7cc95ee 100644 (file)
 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 */