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 cf14c95a670040dce6f49159ec707c8df100df02..a47e2cffaaf84a752b709f7e812b85b1dbd4481a 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 182d3956590654d1f842c1c380f2418e812ab0b3..cba10d625a5d6430d8343717bb80b7cbd0f3ca9a 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 6536abdea6e6f117e0f5ea99968a069c96e35e62..caaa3e5be3347360d8a228838f26bb8e70d875f6 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 74914de8b9bf64ad9d758222bc1bc9075bc8aa78..ab52db684b63369f00aeab80d7c4fb380591b3a2 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 fdfd8c5b639b843d6170a7afed710e2d58ab18c8..22ca45c079a4223ed1cae600c83133881d327a99 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 e6823a0cf6426ff3deb76f12ca153f4144d82620..f9a783bfa1fe4de374e43c3dbadafa5595a9b5ef 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 c4460f3d009fdb6595e0566b19a70a6302f3fd10..488d401942e90c784e02d687087773324b178b8a 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 0e8c168ca24c1c88135841c7fddd492b3f69effd..f6df1ccc961775ac182ce32838c71360bce8611d 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 c778ffe4e4e528544e8f70007c851f521bd90675..34201372c85f57c799c13e4d8ceb7561629bb7e8 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 c0104882c72d9d63c1cb525e01d72ec3578c5bd9..ba26957abf462095d6d1d74d682aa31f3545a836 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 6e15fc87cf606ef0d8473b27dcfc967b52a416ff..6133d93808dca46be5169ffd518a0d128688dbe8 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 82de1073aa529ae105da5ac374face13e6b35bd2..3e411230953bda0939907d712a0eff0749f030d2 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 6e767bce0605bb4f4d28c3d46f3398c019b7d478..21e5f963f3316f82dac58ad9b522109bf5cdf691 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 e8d54de44acc679bc5622d4075e7a16276efac52..087aee2a904f0fecc9221702f400918367690648 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 41d11fe14252ad7963d9e08ca277822aa8c8ff9c..bbbe89dfd886b8ef250217cb18c25bc9eb0e0a74 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 a20e496eb479b62698c4a73aca8b95dad47d7ef6..45a356e9f138a45ca201a85c28a16811555f6970 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 c7e0936d4a7cffd717bdcee0e7e52183656ae8f3..13c179fb2ee2280a2b8ab9abe346d212c2b73149 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 e7cb3925abf8e0276dc4c119e8e03116d0ea48bd..b3f1e3650da0a455bcea891f231308270dd99a4b 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 7ed533e6cca8e2e695a1764ef99f813fccbd62ff..c718a065e154d675d634b48269160086148bfbe1 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 477ecfa05154e3fdecfe3bd951e8d65cf1c65da2..f7f3ce3275b89560e31bc97103a0776975e6d420 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 c1eda73916cdd7e189ffd380882317631d5b1367..4d147c4e33f5343802787d5db358b25fcfae0244 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 3d2e26cbb34cd564ace646f55f8f8e1fccee7cb5..ec598082c14b09476f7de3369f75b0d04b3a6a69 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 e9713d589e30d20c9a7c4d10b253e431592692b0..39f24fa37ebe9fff07c3f38087dbf6f04bedaaa8 100644 (file)
 #include <linux/of_platform.h>
 #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
@@ -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 72f08196f8cd7f08ae481a8ea3b0ff342e7cef38..99c353a85ae4a7c216eb47f398b856ef3e206a22 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,