diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 3 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 20 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mv.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mxc.c | 8 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 331 | ||||
-rw-r--r-- | drivers/usb/host/ehci-orion.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-s5p.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sh.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-timer.c | 61 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap3.c | 24 |
12 files changed, 222 insertions, 257 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c59a1126926..2f682219e25 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -155,8 +155,9 @@ config USB_EHCI_MXC Variation of ARC USB block used in some Freescale chips. config USB_EHCI_HCD_OMAP - bool "EHCI support for OMAP3 and later chips" + tristate "EHCI support for OMAP3 and later chips" depends on USB_EHCI_HCD && ARCH_OMAP + select NOP_USB_XCEIV default y ---help--- Enables support for the on-chip EHCI controller on diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 001fbff2fde..56de4106c8b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o +obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 416a6dce5e1..0c3314c4136 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -757,7 +757,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* remote wakeup [4.3.1] */ if (status & STS_PCD) { unsigned i = HCS_N_PORTS (ehci->hcs_params); - u32 ppcd = 0; + u32 ppcd = ~0; /* kick root hub later */ pcd_status = status; @@ -774,7 +774,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) int pstatus; /* leverage per-port change bits feature */ - if (ehci->has_ppcd && !(ppcd & (1 << i))) + if (!(ppcd & (1 << i))) continue; pstatus = ehci_readl(ehci, &ehci->regs->port_status[i]); @@ -1251,11 +1251,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_sh_driver #endif -#ifdef CONFIG_USB_EHCI_HCD_OMAP -#include "ehci-omap.c" -#define PLATFORM_DRIVER ehci_hcd_omap_driver -#endif - #ifdef CONFIG_PPC_PS3 #include "ehci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver @@ -1345,6 +1340,7 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ + !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \ !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 7d06e77f6c4..7b04ca96b58 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) while (i--) { temp = ehci_readl(ehci, &ehci->regs->port_status [i]); if (test_bit(i, &resume_needed)) { - temp &= ~(PORT_RWC_BITS | PORT_RESUME); + temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME); ehci_writel(ehci, temp, &ehci->regs->port_status [i]); ehci_vdbg (ehci, "resumed port %d\n", i + 1); } @@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) u32 mask; int ports, i, retval = 1; unsigned long flags; - u32 ppcd = 0; + u32 ppcd = ~0; /* init status to no-changes */ buf [0] = 0; @@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) for (i = 0; i < ports; i++) { /* leverage per-port change bits feature */ - if (ehci->has_ppcd && !(ppcd & (1 << i))) - continue; - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); + if (ppcd & (1 << i)) + temp = ehci_readl(ehci, &ehci->regs->port_status[i]); + else + temp = 0; /* * Return status information even for ports with OWNER set. @@ -870,10 +871,9 @@ static int ehci_hub_control ( usb_hcd_end_port_resume(&hcd->self, wIndex); /* stop resume signaling */ - temp = ehci_readl(ehci, status_reg); - ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_RESUME), - status_reg); + temp &= ~(PORT_RWC_BITS | + PORT_SUSPEND | PORT_RESUME); + ehci_writel(ehci, temp, status_reg); clear_bit(wIndex, &ehci->resuming_ports); retval = handshake(ehci, status_reg, PORT_RESUME, 0, 2000 /* 2msec */); @@ -883,7 +883,7 @@ static int ehci_hub_control ( wIndex + 1, retval); goto error; } - temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); + temp = ehci_readl(ehci, status_reg); } } diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 3065809546b..5cd9f96ed92 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -225,7 +225,7 @@ static int mv_ehci_probe(struct platform_device *pdev) (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset); hcd->rsrc_start = r->start; - hcd->rsrc_len = r->end - r->start + 1; + hcd->rsrc_len = resource_size(r); hcd->regs = ehci_mv->op_regs; hcd->irq = platform_get_irq(pdev, 0); diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index e9301fb97ea..a38c8c8e5b0 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -28,11 +28,7 @@ #include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/hcd.h> - #include <linux/platform_data/usb-ehci-mxc.h> - -#include <asm/mach-types.h> - #include "ehci.h" #define DRIVER_DESC "Freescale On-Chip EHCI Host driver" @@ -61,8 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct ehci_hcd *ehci; - dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); - if (!pdata) { dev_err(dev, "No platform data given, bailing out.\n"); return -EINVAL; @@ -178,7 +172,7 @@ err_alloc: return ret; } -static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) +static int ehci_mxc_drv_remove(struct platform_device *pdev) { struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; struct usb_hcd *hcd = platform_get_drvdata(pdev); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 0555ee42d7c..5de3e43ded5 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -4,10 +4,11 @@ * Bus Glue for the EHCI controllers in OMAP3/4 * Tested on several OMAP3 boards, and OMAP4 Pandaboard * - * Copyright (C) 2007-2011 Texas Instruments, Inc. + * Copyright (C) 2007-2013 Texas Instruments, Inc. * Author: Vikram Pandita <vikram.pandita@ti.com> * Author: Anand Gadiyar <gadiyar@ti.com> * Author: Keshava Munegowda <keshava_mgowda@ti.com> + * Author: Roger Quadros <rogerq@ti.com> * * Copyright (C) 2009 Nokia Corporation * Contact: Felipe Balbi <felipe.balbi@nokia.com> @@ -28,21 +29,23 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * TODO (last updated Feb 27, 2010): - * - add kernel-doc - * - enable AUTOIDLE - * - add suspend/resume - * - add HSIC and TLL support - * - convert to use hwmod and runtime PM */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/usb/ulpi.h> -#include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> #include <linux/gpio.h> #include <linux/clk.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/of.h> +#include <linux/dma-mapping.h> + +#include "ehci.h" #include <linux/platform_data/usb-omap.h> @@ -57,10 +60,16 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 -/*-------------------------------------------------------------------------*/ +#define DRIVER_DESC "OMAP-EHCI Host Controller driver" + +static const char hcd_name[] = "ehci-omap"; -static const struct hc_driver ehci_omap_hc_driver; +/*-------------------------------------------------------------------------*/ +struct omap_hcd { + struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */ + int nports; +}; static inline void ehci_write(void __iomem *base, u32 reg, u32 val) { @@ -72,99 +81,16 @@ static inline u32 ehci_read(void __iomem *base, u32 reg) return __raw_readl(base + reg); } +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ -static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - unsigned reg = 0; - - reg = ULPI_FUNC_CTRL_RESET - /* FUNCTION_CTRL_SET register */ - | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) - /* Write */ - | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) - /* PORTn */ - | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) - /* start ULPI access*/ - | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); - - ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); - - /* Wait for ULPI access completion */ - while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) - & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_dbg(hcd->self.controller, - "phy reset operation timed out\n"); - break; - } - } -} - -static int omap_ehci_init(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int rc; - struct usbhs_omap_platform_data *pdata; - - pdata = hcd->self.controller->platform_data; - - /* Hold PHYs in reset while initializing EHCI controller */ - if (pdata->phy_reset) { - if (gpio_is_valid(pdata->reset_gpio_port[0])) - gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); - - if (gpio_is_valid(pdata->reset_gpio_port[1])) - gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); - - /* 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(hcd, 0); - if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) - omap_ehci_soft_phy_reset(hcd, 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); - } - - return rc; -} +static struct hc_driver __read_mostly ehci_omap_hc_driver; -static void disable_put_regulator( - struct usbhs_omap_platform_data *pdata) -{ - int i; - - for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { - if (pdata->regulator[i]) { - regulator_disable(pdata->regulator[i]); - regulator_put(pdata->regulator[i]); - } - } -} +static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { + .extra_priv_size = sizeof(struct omap_hcd), +}; -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ +static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32); /** * ehci_hcd_omap_probe - initialize TI-based HCDs @@ -175,15 +101,15 @@ static void disable_put_regulator( */ static int ehci_hcd_omap_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct usbhs_omap_platform_data *pdata = dev->platform_data; - struct resource *res; - struct usb_hcd *hcd; - void __iomem *regs; - int ret = -ENODEV; - int irq; - int i; - char supply[7]; + struct device *dev = &pdev->dev; + struct usbhs_omap_platform_data *pdata = dev->platform_data; + struct resource *res; + struct usb_hcd *hcd; + void __iomem *regs; + int ret = -ENODEV; + int irq; + int i; + struct omap_hcd *omap; if (usb_disabled()) return -ENODEV; @@ -193,52 +119,74 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) return -ENODEV; } - irq = platform_get_irq_byname(pdev, "ehci-irq"); - if (irq < 0) { - dev_err(dev, "EHCI irq failed\n"); - return -ENODEV; + /* For DT boot, get platform data from parent. i.e. usbhshost */ + if (dev->of_node) { + pdata = dev->parent->platform_data; + dev->platform_data = pdata; } - res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "ehci"); - if (!res) { - dev_err(dev, "UHH EHCI get resource failed\n"); + if (!pdata) { + dev_err(dev, "Missing platform data\n"); return -ENODEV; } - regs = ioremap(res->start, resource_size(res)); - if (!regs) { - dev_err(dev, "UHH EHCI ioremap failed\n"); - return -ENOMEM; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "EHCI irq failed\n"); + return -ENODEV; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &omap_ehci_dma_mask; + hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, dev_name(dev)); if (!hcd) { - dev_err(dev, "failed to create hcd with err %d\n", ret); - ret = -ENOMEM; - goto err_io; + dev_err(dev, "Failed to create HCD\n"); + return -ENOMEM; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = regs; - - /* get ehci regulator and enable */ - for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { - if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { - pdata->regulator[i] = NULL; - continue; - } - snprintf(supply, sizeof(supply), "hsusb%d", i); - pdata->regulator[i] = regulator_get(dev, supply); - if (IS_ERR(pdata->regulator[i])) { - pdata->regulator[i] = NULL; - dev_dbg(dev, - "failed to get ehci port%d regulator\n", i); - } else { - regulator_enable(pdata->regulator[i]); + hcd_to_ehci(hcd)->caps = regs; + + omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; + omap->nports = pdata->nports; + + platform_set_drvdata(pdev, hcd); + + /* get the PHY devices if needed */ + for (i = 0 ; i < omap->nports ; i++) { + struct usb_phy *phy; + + /* get the PHY device */ + if (dev->of_node) + phy = devm_usb_get_phy_by_phandle(dev, "phys", i); + else + phy = devm_usb_get_phy_dev(dev, i); + if (IS_ERR(phy) || !phy) { + /* Don't bail out if PHY is not absolutely necessary */ + if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) + continue; + + ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV; + dev_err(dev, "Can't get PHY device for port %d: %d\n", + i, ret); + goto err_phy; } + + omap->phy[i] = phy; } pm_runtime_enable(dev); @@ -262,16 +210,34 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) goto err_pm_runtime; } + /* + * Bring PHYs out of reset. + * Even though HSIC mode is a PHY-less mode, the reset + * line exists between the chips and can be modelled + * as a PHY device for reset control. + */ + for (i = 0; i < omap->nports; i++) { + if (!omap->phy[i]) + continue; + + usb_phy_init(omap->phy[i]); + /* bring PHY out of suspend */ + usb_phy_set_suspend(omap->phy[i], 0); + } return 0; err_pm_runtime: - disable_put_regulator(pdata); pm_runtime_put_sync(dev); + +err_phy: + for (i = 0; i < omap->nports; i++) { + if (omap->phy[i]) + usb_phy_shutdown(omap->phy[i]); + } + usb_put_hcd(hcd); -err_io: - iounmap(regs); return ret; } @@ -286,14 +252,19 @@ err_io: */ static int ehci_hcd_omap_remove(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; + int i; usb_remove_hcd(hcd); - disable_put_regulator(dev->platform_data); - iounmap(hcd->regs); - usb_put_hcd(hcd); + for (i = 0; i < omap->nports; i++) { + if (omap->phy[i]) + usb_phy_shutdown(omap->phy[i]); + } + + usb_put_hcd(hcd); pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -308,6 +279,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev) hcd->driver->shutdown(hcd); } +static const struct of_device_id omap_ehci_dt_ids[] = { + { .compatible = "ti,ehci-omap" }, + { } +}; + +MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); + static struct platform_driver ehci_hcd_omap_driver = { .probe = ehci_hcd_omap_probe, .remove = ehci_hcd_omap_remove, @@ -315,56 +293,35 @@ static struct platform_driver ehci_hcd_omap_driver = { /*.suspend = ehci_hcd_omap_suspend, */ /*.resume = ehci_hcd_omap_resume, */ .driver = { - .name = "ehci-omap", + .name = hcd_name, + .of_match_table = of_match_ptr(omap_ehci_dt_ids), } }; /*-------------------------------------------------------------------------*/ -static const struct hc_driver ehci_omap_hc_driver = { - .description = hcd_name, - .product_desc = "OMAP-EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = omap_ehci_init, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, +static int __init ehci_omap_init(void) +{ + if (usb_disabled()) + return -ENODEV; - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, + pr_info("%s: " DRIVER_DESC "\n", hcd_name); - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, + ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); + return platform_driver_register(&ehci_hcd_omap_driver); +} +module_init(ehci_omap_init); - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; +static void __exit ehci_omap_cleanup(void) +{ + platform_driver_unregister(&ehci_hcd_omap_driver); +} +module_exit(ehci_omap_cleanup); MODULE_ALIAS("platform:ehci-omap"); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); +MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 914a3ecfb5d..38c45fb3357 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -305,7 +305,7 @@ err1: return err; } -static int __exit ehci_orion_drv_remove(struct platform_device *pdev) +static int ehci_orion_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct clk *clk; @@ -333,7 +333,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids); static struct platform_driver ehci_orion_driver = { .probe = ehci_orion_drv_probe, - .remove = __exit_p(ehci_orion_drv_remove), + .remove = ehci_orion_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "orion-ehci", diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 20ebf6a8b7f..738490e6d42 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -92,20 +92,21 @@ static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci) static void s5p_setup_vbus_gpio(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int err; int gpio; - if (!pdev->dev.of_node) + if (!dev->of_node) return; - gpio = of_get_named_gpio(pdev->dev.of_node, - "samsung,vbus-gpio", 0); + gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0); if (!gpio_is_valid(gpio)) return; - err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio"); + err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH, + "ehci_vbus_gpio"); if (err) - dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio); + dev_err(dev, "can't request ehci vbus gpio %d", gpio); } static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32); diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 3565a300f40..e30e3967202 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -170,7 +170,7 @@ fail_create_hcd: return ret; } -static int __exit ehci_hcd_sh_remove(struct platform_device *pdev) +static int ehci_hcd_sh_remove(struct platform_device *pdev) { struct ehci_sh_priv *priv = platform_get_drvdata(pdev); struct usb_hcd *hcd = priv->hcd; @@ -196,7 +196,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev) static struct platform_driver ehci_hcd_sh_driver = { .probe = ehci_hcd_sh_probe, - .remove = __exit_p(ehci_hcd_sh_remove), + .remove = ehci_hcd_sh_remove .shutdown = ehci_hcd_sh_shutdown, .driver = { .name = "sh_ehci", diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index c3fa1305f83..e7363332887 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci) if (want != actual) { - /* Poll again later, but give up after about 20 ms */ - if (ehci->ASS_poll_count++ < 20) { + /* Poll again later, but give up after about 2-4 ms */ + if (ehci->ASS_poll_count++ < 2) { ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); return; } @@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci) if (want != actual) { - /* Poll again later, but give up after about 20 ms */ - if (ehci->PSS_poll_count++ < 20) { + /* Poll again later, but give up after about 2-4 ms */ + if (ehci->PSS_poll_count++ < 2) { ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); return; } @@ -295,8 +295,7 @@ static void end_free_itds(struct ehci_hcd *ehci) /* Handle lost (or very late) IAA interrupts */ static void ehci_iaa_watchdog(struct ehci_hcd *ehci) { - if (ehci->rh_state != EHCI_RH_RUNNING) - return; + u32 cmd, status; /* * Lost IAA irqs wedge things badly; seen first with a vt8235. @@ -304,34 +303,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci) * (a) SMP races against real IAA firing and retriggering, and * (b) clean HC shutdown, when IAA watchdog was pending. */ - if (1) { - u32 cmd, status; - - /* If we get here, IAA is *REALLY* late. It's barely - * conceivable that the system is so busy that CMD_IAAD - * is still legitimately set, so let's be sure it's - * clear before we read STS_IAA. (The HC should clear - * CMD_IAAD when it sets STS_IAA.) - */ - cmd = ehci_readl(ehci, &ehci->regs->command); - - /* - * If IAA is set here it either legitimately triggered - * after the watchdog timer expired (_way_ late, so we'll - * still count it as lost) ... or a silicon erratum: - * - VIA seems to set IAA without triggering the IRQ; - * - IAAD potentially cleared without setting IAA. - */ - status = ehci_readl(ehci, &ehci->regs->status); - if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { - COUNT(ehci->stats.lost_iaa); - ehci_writel(ehci, STS_IAA, &ehci->regs->status); - } + if (ehci->rh_state != EHCI_RH_RUNNING) + return; - ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n", - status, cmd); - end_unlink_async(ehci); + /* If we get here, IAA is *REALLY* late. It's barely + * conceivable that the system is so busy that CMD_IAAD + * is still legitimately set, so let's be sure it's + * clear before we read STS_IAA. (The HC should clear + * CMD_IAAD when it sets STS_IAA.) + */ + cmd = ehci_readl(ehci, &ehci->regs->command); + + /* + * If IAA is set here it either legitimately triggered + * after the watchdog timer expired (_way_ late, so we'll + * still count it as lost) ... or a silicon erratum: + * - VIA seems to set IAA without triggering the IRQ; + * - IAAD potentially cleared without setting IAA. + */ + status = ehci_readl(ehci, &ehci->regs->status); + if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { + COUNT(ehci->stats.lost_iaa); + ehci_writel(ehci, STS_IAA, &ehci->regs->status); } + + ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); + end_unlink_async(ehci); } diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index eb35d963023..ddfc31427bc 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -31,6 +31,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/dma-mapping.h> /*-------------------------------------------------------------------------*/ @@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = { /*-------------------------------------------------------------------------*/ +static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32); + /* * configure so an HC device and id are always provided * always called with process context; sleeping is OK @@ -141,14 +145,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) return -ENODEV; } - irq = platform_get_irq_byname(pdev, "ohci-irq"); + irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "OHCI irq failed\n"); return -ENODEV; } - res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "ohci"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "UHH OHCI get resource failed\n"); return -ENOMEM; @@ -160,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) return -ENOMEM; } + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &omap_ohci_dma_mask; hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev, dev_name(dev)); @@ -229,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev) hcd->driver->shutdown(hcd); } +static const struct of_device_id omap_ohci_dt_ids[] = { + { .compatible = "ti,ohci-omap3" }, + { } +}; + +MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids); + static struct platform_driver ohci_hcd_omap3_driver = { .probe = ohci_hcd_omap3_probe, .remove = ohci_hcd_omap3_remove, .shutdown = ohci_hcd_omap3_shutdown, .driver = { .name = "ohci-omap3", + .of_match_table = of_match_ptr(omap_ohci_dt_ids), }, }; |