EHCI: centralize controller initialization
authorAlan Stern <stern@rowland.harvard.edu>
Mon, 9 Jul 2012 19:55:14 +0000 (15:55 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 Jul 2012 20:35:05 +0000 (13:35 -0700)
This patch (as1564c) converts the EHCI platform drivers to use the
central ehci_setup() routine for generic controller initialization
rather than each having its own idiosyncratic approach.

The major point of difficulty lies in ehci-pci's many vendor- and
device-specific workarounds.  Some of them have to be applied before
calling ehci_setup() and some after, which necessitates a fair amount
of code motion.  The other platform drivers require much smaller
changes.

One point not addressed by the patch is whether ports should be
powered on or off following initialization.  The different drivers
appear to handle this pretty much at random.  In fact it shouldn't
matter, because the hub driver turns on power to all ports when it
binds to the root hub.  Straightening that out will be left for
another day.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24 files changed:
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-cns3xxx.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-grlib.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-ixp4xx.c
drivers/usb/host/ehci-mv.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-xls.c

index cf14c95..a47e2cf 100644 (file)
@@ -53,30 +53,15 @@ static void atmel_stop_ehci(struct platform_device *pdev)
 static int ehci_atmel_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval = 0;
+       int retval;
 
        /* registers start at offset 0x0 */
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs +
-               HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
 
-       /* data structure init */
-       retval = ehci_init(hcd);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
-       ehci->sbrn = 0x20;
-
-       ehci_reset(ehci);
        ehci_port_power(ehci, 0);
 
        return retval;
index 182d395..cba10d6 100644 (file)
@@ -20,10 +20,12 @@ extern int usb_disabled(void);
 static int au1xxx_ehci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret = ehci_init(hcd);
+       int ret;
+
+       ehci->caps = hcd->regs;
+       ret = ehci_setup(hcd);
 
        ehci->need_io_watchdog = 0;
-       ehci_reset(ehci);
        return ret;
 }
 
@@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
-       struct ehci_hcd *ehci;
        struct resource *res;
        int ret;
 
@@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
                goto err3;
        }
 
-       ehci = hcd_to_ehci(hcd);
-       ehci->caps = hcd->regs;
-       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);
-
        ret = usb_add_hcd(hcd, pdev->resource[1].start,
                          IRQF_SHARED);
        if (ret == 0) {
index 6536abd..caaa3e5 100644 (file)
@@ -33,14 +33,10 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd)
        }
 
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs
-               + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
        hcd->has_tt = 0;
-       ehci_reset(ehci);
 
-       retval = ehci_init(hcd);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
index 74914de..ab52db6 100644 (file)
@@ -348,29 +348,13 @@ 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, ehci_readl(ehci, &ehci->caps->hc_capbase));
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
        hcd->has_tt = 1;
 
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       /* data structure init */
-       retval = ehci_init(hcd);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
-       ehci->sbrn = 0x20;
-
-       ehci_reset(ehci);
-
        if (of_device_is_compatible(dev->parent->of_node,
                                    "fsl,mpc5121-usb2-dr")) {
                /*
index fdfd8c5..22ca45c 100644 (file)
@@ -40,18 +40,13 @@ static int ehci_grlib_setup(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int             retval;
 
-       retval = ehci_halt(ehci);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       ehci->sbrn = 0x20;
        ehci_port_power(ehci, 1);
 
-       return ehci_reset(ehci);
+       return retval;
 }
 
 
@@ -164,12 +159,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
                ehci->big_endian_capbase = 1;
        }
 
-       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);
-
        rv = usb_add_hcd(hcd, irq, 0);
        if (rv)
                goto err_ehci;
index e6823a0..f9a783b 100644 (file)
@@ -808,7 +808,7 @@ static int ehci_run (struct usb_hcd *hcd)
        return 0;
 }
 
-static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
+static int ehci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
@@ -832,6 +832,9 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
        if (retval)
                return retval;
 
+       if (ehci_is_TDI(ehci))
+               tdi_reset(ehci);
+
        ehci_reset(ehci);
 
        return 0;
index c4460f3..488d401 100644 (file)
@@ -22,14 +22,10 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
        ehci->big_endian_mmio = 1;
 
        ehci->caps = hcd->regs + 0x100;
-       ehci->regs = hcd->regs + 0x100
-               + 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_reset(ehci);
 
-       retval = ehci_init(hcd);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
index 0e8c168..f6df1cc 100644 (file)
@@ -77,7 +77,6 @@ static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
 
 static int mv_ehci_reset(struct usb_hcd *hcd)
 {
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        struct device *dev = hcd->self.controller;
        struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev);
        int retval;
@@ -87,25 +86,13 @@ static int mv_ehci_reset(struct usb_hcd *hcd)
                return -ENODEV;
        }
 
-       /*
-        * data structure init
-        */
-       retval = ehci_init(hcd);
-       if (retval) {
-               dev_err(dev, "ehci_init failed %d\n", retval);
-               return retval;
-       }
-
        hcd->has_tt = 1;
-       ehci->sbrn = 0x20;
 
-       retval = ehci_reset(ehci);
-       if (retval) {
-               dev_err(dev, "ehci_reset failed %d\n", retval);
-               return retval;
-       }
+       retval = ehci_setup(hcd);
+       if (retval)
+               dev_err(dev, "ehci_setup failed %d\n", retval);
 
-       return 0;
+       return retval;
 }
 
 static const struct hc_driver mv_ehci_hc_driver = {
@@ -248,8 +235,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
 
        ehci = hcd_to_ehci(hcd);
        ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
-       ehci->regs = (struct ehci_regs *) ehci_mv->op_regs;
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
        ehci_mv->mode = pdata->mode;
        if (ehci_mv->mode == MV_USB_MODE_OTG) {
index c778ffe..3420137 100644 (file)
@@ -42,27 +42,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
 
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
        hcd->has_tt = 1;
 
-       retval = ehci_halt(ehci);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
-       /* data structure init */
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       ehci->sbrn = 0x20;
-
-       ehci_reset(ehci);
-
        ehci_port_power(ehci, 0);
        return 0;
 }
index c010488..ba26957 100644 (file)
@@ -56,7 +56,7 @@ static const struct hc_driver ehci_octeon_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset                  = ehci_init,
+       .reset                  = ehci_setup,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
@@ -150,12 +150,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
 #endif
 
        ehci->caps = hcd->regs;
-       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);
-
-       ehci_reset(ehci);
 
        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (ret) {
index 6e15fc8..6133d93 100644 (file)
@@ -145,6 +145,56 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
        }
 }
 
+static int omap_ehci_init(struct usb_hcd *hcd)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
+       int                     rc;
+       struct ehci_hcd_omap_platform_data      *pdata;
+
+       pdata = hcd->self.controller->platform_data;
+       if (pdata->phy_reset) {
+               if (gpio_is_valid(pdata->reset_gpio_port[0]))
+                       gpio_request_one(pdata->reset_gpio_port[0],
+                                        GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+
+               if (gpio_is_valid(pdata->reset_gpio_port[1]))
+                       gpio_request_one(pdata->reset_gpio_port[1],
+                                        GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+
+               /* Hold the PHY in RESET for enough time till DIR is high */
+               udelay(10);
+       }
+
+       /* Soft reset the PHY using PHY reset command over ULPI */
+       if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
+               omap_ehci_soft_phy_reset(pdev, 0);
+       if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
+               omap_ehci_soft_phy_reset(pdev, 1);
+
+       /* we know this is the memory we want, no need to ioremap again */
+       ehci->caps = hcd->regs;
+
+       rc = ehci_setup(hcd);
+
+       if (pdata->phy_reset) {
+               /* Hold the PHY in RESET for enough time till
+                * PHY is settled and ready
+                */
+               udelay(10);
+
+               if (gpio_is_valid(pdata->reset_gpio_port[0]))
+                       gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
+
+               if (gpio_is_valid(pdata->reset_gpio_port[1]))
+                       gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
+       }
+
+       /* root ports should always stay powered */
+       ehci_port_power(ehci, 1);
+
+       return rc;
+}
+
 static int omap_ehci_hub_control(
        struct usb_hcd  *hcd,
        u16             typeReq,
@@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        struct resource                         *res;
        struct usb_hcd                          *hcd;
        void __iomem                            *regs;
-       struct ehci_hcd                         *omap_ehci;
        int                                     ret = -ENODEV;
        int                                     irq;
        int                                     i;
@@ -281,19 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                }
        }
 
-       if (pdata->phy_reset) {
-               if (gpio_is_valid(pdata->reset_gpio_port[0]))
-                       gpio_request_one(pdata->reset_gpio_port[0],
-                                        GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
-
-               if (gpio_is_valid(pdata->reset_gpio_port[1]))
-                       gpio_request_one(pdata->reset_gpio_port[1],
-                                        GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
-
-               /* Hold the PHY in RESET for enough time till DIR is high */
-               udelay(10);
-       }
-
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
 
@@ -309,50 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        ehci_write(regs, EHCI_INSNREG04,
                                EHCI_INSNREG04_DISABLE_UNSUSPEND);
 
-       /* Soft reset the PHY using PHY reset command over ULPI */
-       if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
-               omap_ehci_soft_phy_reset(pdev, 0);
-       if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
-               omap_ehci_soft_phy_reset(pdev, 1);
-
-       omap_ehci = hcd_to_ehci(hcd);
-       omap_ehci->sbrn = 0x20;
-
-       /* 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(ehci, readl(&omap_ehci->caps->hc_capbase));
-
-       dbg_hcs_params(omap_ehci, "reset");
-       dbg_hcc_params(omap_ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
-
-       ehci_reset(omap_ehci);
-
-       if (pdata->phy_reset) {
-               /* Hold the PHY in RESET for enough time till
-                * PHY is settled and ready
-                */
-               udelay(10);
-
-               if (gpio_is_valid(pdata->reset_gpio_port[0]))
-                       gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
-
-               if (gpio_is_valid(pdata->reset_gpio_port[1]))
-                       gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
-       }
-
        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (ret) {
                dev_err(dev, "failed to add hcd with err %d\n", ret);
                goto err_pm_runtime;
        }
 
-       /* root ports should always stay powered */
-       ehci_port_power(omap_ehci, 1);
-
        /* get clocks */
        utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
        if (IS_ERR(utmi_p1_fck)) {
@@ -512,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset                  = ehci_init,
+       .reset                  = omap_ehci_init,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
index 82de107..3e41123 100644 (file)
@@ -106,21 +106,10 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
 
-       hcd->has_tt = 1;
-
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       /*
-        * data structure init
-        */
-       retval = ehci_init(hcd);
+       retval = ehci_setup(ehci);
        if (retval)
                return retval;
 
-       ehci_reset(ehci);
-
        ehci_port_power(ehci, 0);
 
        return retval;
@@ -261,11 +250,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, ehci_readl(ehci, &ehci->caps->hc_capbase));
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
        hcd->has_tt = 1;
-       ehci->sbrn = 0x20;
 
        /*
         * (Re-)program MBUS remapping windows if we are asked to.
index 6e767bc..21e5f96 100644 (file)
@@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        u32                     temp;
        int                     retval;
 
+       ehci->caps = hcd->regs;
+
+       /*
+        * ehci_init() causes memory for DMA transfers to be
+        * allocated.  Thus, any vendor-specific workarounds based on
+        * limiting the type of memory used for DMA transfers must
+        * happen before ehci_setup() is called.
+        *
+        * Most other workarounds can be done either before or after
+        * init and reset; they are located here too.
+        */
        switch (pdev->vendor) {
        case PCI_VENDOR_ID_TOSHIBA_2:
                /* celleb's companion chip */
@@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 #endif
                }
                break;
-       }
-
-       ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs +
-               HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-        /* ehci_init() causes memory for DMA transfers to be
-         * allocated.  Thus, any vendor-specific workarounds based on
-         * limiting the type of memory used for DMA transfers must
-         * happen before ehci_init() is called. */
-       switch (pdev->vendor) {
        case PCI_VENDOR_ID_NVIDIA:
                /* NVidia reports that certain chips don't handle
                 * QH, ITD, or SITD addresses above 2GB.  (But TD,
@@ -95,61 +92,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                                ehci_warn(ehci, "can't enable NVidia "
                                        "workaround for >2GB RAM\n");
                        break;
-               }
-               break;
-       }
 
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) ||
-           (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) {
-               /* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
-                * read/write memory space which does not belong to it when
-                * there is NULL pointer with T-bit set to 1 in the frame list
-                * table. To avoid the issue, the frame list link pointer
-                * should always contain a valid pointer to a inactive qh.
+               /* Some NForce2 chips have problems with selective suspend;
+                * fixed in newer silicon.
                 */
-               ehci->use_dummy_qh = 1;
-               ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI "
-                               "dummy qh workaround\n");
-       }
-
-       /* data structure init */
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       switch (pdev->vendor) {
-       case PCI_VENDOR_ID_NEC:
-               ehci->need_io_watchdog = 0;
+               case 0x0068:
+                       if (pdev->revision < 0xa4)
+                               ehci->no_selective_suspend = 1;
+                       break;
+               }
                break;
        case PCI_VENDOR_ID_INTEL:
-               ehci->need_io_watchdog = 0;
                ehci->fs_i_thresh = 1;
                if (pdev->device == 0x27cc) {
                        ehci->broken_periodic = 1;
                        ehci_info(ehci, "using broken periodic workaround\n");
                }
-               if (pdev->device == 0x0806 || pdev->device == 0x0811
-                               || pdev->device == 0x0829) {
-                       ehci_info(ehci, "disable lpm for langwell/penwell\n");
-                       ehci->has_lpm = 0;
-               }
-               if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) {
+               if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
                        hcd->has_tt = 1;
-                       tdi_reset(ehci);
-               }
                break;
        case PCI_VENDOR_ID_TDI:
-               if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+               if (pdev->device == PCI_DEVICE_ID_TDI_EHCI)
                        hcd->has_tt = 1;
-                       tdi_reset(ehci);
-               }
                break;
        case PCI_VENDOR_ID_AMD:
                /* AMD PLL quirk */
@@ -161,28 +125,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                        retval = -EIO;
                        goto done;
                }
-               break;
-       case PCI_VENDOR_ID_NVIDIA:
-               switch (pdev->device) {
-               /* Some NForce2 chips have problems with selective suspend;
-                * fixed in newer silicon.
-                */
-               case 0x0068:
-                       if (pdev->revision < 0xa4)
-                               ehci->no_selective_suspend = 1;
-                       break;
 
-               /* MCP89 chips on the MacBookAir3,1 give EPROTO when
-                * fetching device descriptors unless LPM is disabled.
-                * There are also intermittent problems enumerating
-                * devices with PPCD enabled.
+               /*
+                * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
+                * read/write memory space which does not belong to it when
+                * there is NULL pointer with T-bit set to 1 in the frame list
+                * table. To avoid the issue, the frame list link pointer
+                * should always contain a valid pointer to a inactive qh.
                 */
-               case 0x0d9d:
-                       ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
-                       ehci->has_lpm = 0;
-                       ehci->has_ppcd = 0;
-                       ehci->command &= ~CMD_PPCEE;
-                       break;
+               if (pdev->device == 0x7808) {
+                       ehci->use_dummy_qh = 1;
+                       ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
                }
                break;
        case PCI_VENDOR_ID_VIA:
@@ -203,6 +156,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                /* AMD PLL quirk */
                if (usb_amd_find_chipset_info())
                        ehci->amd_pll_fix = 1;
+
+               /*
+                * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
+                * read/write memory space which does not belong to it when
+                * there is NULL pointer with T-bit set to 1 in the frame list
+                * table. To avoid the issue, the frame list link pointer
+                * should always contain a valid pointer to a inactive qh.
+                */
+               if (pdev->device == 0x4396) {
+                       ehci->use_dummy_qh = 1;
+                       ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
+               }
                /* SB600 and old version of SB700 have a bug in EHCI controller,
                 * which causes usb devices lose response in some cases.
                 */
@@ -231,6 +196,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        }
 
+       retval = ehci_setup(hcd);
+       if (retval)
+               return retval;
+
+       /* These workarounds need to be applied after ehci_setup() */
+       switch (pdev->vendor) {
+       case PCI_VENDOR_ID_NEC:
+               ehci->need_io_watchdog = 0;
+               break;
+       case PCI_VENDOR_ID_INTEL:
+               ehci->need_io_watchdog = 0;
+               if (pdev->device == 0x0806 || pdev->device == 0x0811
+                               || pdev->device == 0x0829) {
+                       ehci_info(ehci, "disable lpm for langwell/penwell\n");
+                       ehci->has_lpm = 0;
+               }
+               break;
+       case PCI_VENDOR_ID_NVIDIA:
+               switch (pdev->device) {
+               /* MCP89 chips on the MacBookAir3,1 give EPROTO when
+                * fetching device descriptors unless LPM is disabled.
+                * There are also intermittent problems enumerating
+                * devices with PPCD enabled.
+                */
+               case 0x0d9d:
+                       ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
+                       ehci->has_lpm = 0;
+                       ehci->has_ppcd = 0;
+                       ehci->command &= ~CMD_PPCEE;
+                       break;
+               }
+               break;
+       }
+
        /* optional debug port, normally in the first BAR */
        temp = pci_find_capability(pdev, 0x0a);
        if (temp) {
@@ -238,7 +237,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                temp >>= 16;
                if ((temp & (3 << 13)) == (1 << 13)) {
                        temp &= 0x1fff;
-                       ehci->debug = ehci_to_hcd(ehci)->regs + temp;
+                       ehci->debug = hcd->regs + temp;
                        temp = ehci_readl(ehci, &ehci->debug->control);
                        ehci_info(ehci, "debug port %d%s\n",
                                HCS_DEBUG_PORT(ehci->hcs_params),
@@ -250,8 +249,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                }
        }
 
-       ehci_reset(ehci);
-
        /* at least the Genesys GL880S needs fixup here */
        temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
        temp &= 0x0f;
@@ -275,10 +272,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        }
 
        /* Serial Bus Release Number is at PCI 0x60 offset */
-       pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
        if (pdev->vendor == PCI_VENDOR_ID_STMICRO
            && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
-               ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
+               ;       /* ConneXT has no sbrn register */
+       else
+               pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
 
        /* Keep this around for a while just in case some EHCI
         * implementation uses legacy PCI PM support.  This test
index e8d54de..087aee2 100644 (file)
@@ -78,27 +78,14 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        int                     retval;
+
        ehci->big_endian_mmio = 1;
        ehci->big_endian_desc = 1;
 
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs +
-               HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
        hcd->has_tt = 1;
 
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       ehci_reset(ehci);
-
-       /* data structure init */
-       retval = ehci_init(hcd);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
index 41d11fe..bbbe89d 100644 (file)
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
-/* called during probe() after chip reset completes */
-static int ehci_ppc_of_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int             retval;
-
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       ehci->sbrn = 0x20;
-       return ehci_reset(ehci);
-}
-
 
 static const struct hc_driver ehci_ppc_of_hc_driver = {
        .description            = hcd_name,
@@ -50,7 +32,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset                  = ehci_ppc_of_setup,
+       .reset                  = ehci_setup,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
@@ -178,11 +160,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
                ehci->big_endian_desc = 1;
 
        ehci->caps = hcd->regs;
-       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);
 
        if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
                rv = ppc44x_enable_bmt(dn);
index a20e496..45a356e 100644 (file)
@@ -55,28 +55,12 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
        ehci->big_endian_mmio = 1;
-
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
-               &ehci->caps->hc_capbase));
-
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-       result = ehci_halt(ehci);
 
+       result = ehci_setup(hcd);
        if (result)
                return result;
 
-       result = ehci_init(hcd);
-
-       if (result)
-               return result;
-
-       ehci_reset(ehci);
-
        ps3_ehci_setup_insnreg(ehci);
 
        return result;
index c7e0936..13c179f 100644 (file)
@@ -40,7 +40,7 @@ static const struct hc_driver s5p_ehci_hc_driver = {
        .irq                    = ehci_irq,
        .flags                  = HCD_MEMORY | HCD_USB2,
 
-       .reset                  = ehci_init,
+       .reset                  = ehci_setup,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
@@ -134,20 +134,10 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 
        ehci = hcd_to_ehci(hcd);
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs +
-               HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
 
        /* DMA burst Enable */
        writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
 
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = readl(&ehci->caps->hcs_params);
-
-       ehci_reset(ehci);
-
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err) {
                dev_err(&pdev->dev, "Failed to add USB HCD\n");
index e7cb392..b3f1e36 100644 (file)
@@ -24,25 +24,11 @@ static int ehci_sh_reset(struct usb_hcd *hcd)
        int ret;
 
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
-               &ehci->caps->hc_capbase));
 
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-       ret = ehci_halt(ehci);
-       if (unlikely(ret))
-               return ret;
-
-       ret = ehci_init(hcd);
+       ret = ehci_setup(hcd);
        if (unlikely(ret))
                return ret;
 
-       ehci->sbrn = 0x20;
-
-       ehci_reset(ehci);
        ehci_port_power(ehci, 0);
 
        return ret;
index 7ed533e..c718a06 100644 (file)
@@ -41,19 +41,11 @@ 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, ehci_readl(ehci,
-                               &ehci->caps->hc_capbase));
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
 
-       retval = ehci_init(hcd);
+       retval = ehci_setup(hcd);
        if (retval)
                return retval;
 
-       ehci_reset(ehci);
        ehci_port_power(ehci, 0);
 
        return retval;
index 477ecfa..f7f3ce3 100644 (file)
@@ -281,30 +281,14 @@ 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(ehci, readl(&ehci->caps->hc_capbase));
-
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = readl(&ehci->caps->hcs_params);
 
        /* switch to host mode */
        hcd->has_tt = 1;
-       ehci_reset(ehci);
 
-       retval = ehci_halt(ehci);
+       retval = ehci_setup(ehci);
        if (retval)
                return retval;
 
-       /* data structure init */
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       ehci->sbrn = 0x20;
-
        ehci_port_power(ehci, 1);
        return retval;
 }
index c1eda73..4d147c4 100644 (file)
@@ -48,7 +48,7 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset                  = ehci_init,
+       .reset                  = ehci_setup,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
@@ -121,18 +121,6 @@ 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(ehci, readl(&ehci->caps->hc_capbase));
-
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = readl(&ehci->caps->hcs_params);
-
-       ehci_port_power(ehci, 1);
-
-       ehci_reset(ehci);
 
        ret = usb_add_hcd(hcd, pdev->resource[1].start,
                          IRQF_SHARED);
index 3d2e26c..ec59808 100644 (file)
@@ -71,21 +71,14 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
        val |= ENPHY;
        __raw_writel(val, ehci->regs+PHY1_CTR);
 
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-       ehci->sbrn = 0x20;
-
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                goto err4;
 
-       ehci_reset(ehci);
-
        retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval != 0)
                goto err4;
 
-       ehci_writel(ehci, 1, &ehci->regs->configured_flag);
-
        return retval;
 err4:
        iounmap(hcd->regs);
@@ -120,7 +113,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset = ehci_init,
+       .reset = ehci_setup,
        .start = ehci_run,
 
        .stop = ehci_stop,
index e9713d5..39f24fa 100644 (file)
 #include <linux/of_address.h>
 
 /**
- * ehci_xilinx_of_setup - Initialize the device for ehci_reset()
- * @hcd:       Pointer to the usb_hcd device to which the host controller bound
- *
- * called during probe() after chip reset completes.
- */
-static int ehci_xilinx_of_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int             retval;
-
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       ehci->sbrn = 0x20;
-
-       return ehci_reset(ehci);
-}
-
-/**
  * ehci_xilinx_port_handed_over - hand the port out if failed to enable it
  * @hcd:       Pointer to the usb_hcd device to which the host controller bound
  * @portnum:Port number to which the device is attached.
@@ -107,7 +83,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset                  = ehci_xilinx_of_setup,
+       .reset                  = ehci_setup,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
@@ -219,11 +195,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
        /* Debug registers are at the first 0x100 region
         */
        ehci->caps = hcd->regs + 0x100;
-       ehci->regs = hcd->regs + 0x100 +
-               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);
 
        rv = usb_add_hcd(hcd, irq, 0);
        if (rv == 0)
index 72f0819..99c353a 100644 (file)
 
 static int ehci_xls_setup(struct usb_hcd *hcd)
 {
-       int     retval;
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs +
-               HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-       dbg_hcs_params(ehci, "reset");
-       dbg_hcc_params(ehci, "reset");
 
-       /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
-       retval = ehci_halt(ehci);
-       if (retval)
-               return retval;
-
-       /* data structure init */
-       retval = ehci_init(hcd);
-       if (retval)
-               return retval;
-
-       ehci_reset(ehci);
-
-       return retval;
+       return ehci_setup(ehci);
 }
 
 int ehci_xls_probe_internal(const struct hc_driver *driver,