154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* 24792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * ehci-omap.c - driver for USBHOST on OMAP3/4 processors 354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 44792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * Bus Glue for the EHCI controllers in OMAP3/4 54792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * Tested on several OMAP3 boards, and OMAP4 Pandaboard 654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 7dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros * Copyright (C) 2007-2013 Texas Instruments, Inc. 854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Author: Vikram Pandita <vikram.pandita@ti.com> 94792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * Author: Anand Gadiyar <gadiyar@ti.com> 1019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * Author: Keshava Munegowda <keshava_mgowda@ti.com> 11dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros * Author: Roger Quadros <rogerq@ti.com> 1254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 1354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Copyright (C) 2009 Nokia Corporation 1454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Contact: Felipe Balbi <felipe.balbi@nokia.com> 1554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 1654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers 1754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 1854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is free software; you can redistribute it and/or modify 1954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * it under the terms of the GNU General Public License as published by 2054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the Free Software Foundation; either version 2 of the License, or 2154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * (at your option) any later version. 2254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 2354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is distributed in the hope that it will be useful, 2454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * but WITHOUT ANY WARRANTY; without even the implied warranty of 2554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * GNU General Public License for more details. 2754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 2854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * You should have received a copy of the GNU General Public License 2954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * along with this program; if not, write to the Free Software 3054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 3154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 3254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 3354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 3454a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#include <linux/kernel.h> 3554a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#include <linux/module.h> 3654a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#include <linux/io.h> 3754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#include <linux/platform_device.h> 385a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 395aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta#include <linux/usb/ulpi.h> 406c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda#include <linux/pm_runtime.h> 411fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda#include <linux/gpio.h> 42354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar#include <linux/clk.h> 4354a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#include <linux/usb.h> 4454a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#include <linux/usb/hcd.h> 45a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros#include <linux/of.h> 46a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros#include <linux/dma-mapping.h> 4754a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern 4854a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#include "ehci.h" 4954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 50e8c4a7acc9ec0ee82feedcdc3c6d0ee44d67918aFelipe Balbi#include <linux/platform_data/usb-omap.h> 51e8c4a7acc9ec0ee82feedcdc3c6d0ee44d67918aFelipe Balbi 5254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* EHCI Register Set */ 53572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04 (0xA0) 54572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) 5554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI (0xA4) 5654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 5754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 5854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 5954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 6054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 6154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 6254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 6354a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern#define DRIVER_DESC "OMAP-EHCI Host Controller driver" 644792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar 6554a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternstatic const char hcd_name[] = "ehci-omap"; 6654a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern 6754a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern/*-------------------------------------------------------------------------*/ 684792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar 69dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadrosstruct omap_hcd { 70dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */ 71dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros int nports; 72dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros}; 73a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar 7419403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline void ehci_write(void __iomem *base, u32 reg, u32 val) 7554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 7654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi __raw_writel(val, base + reg); 7754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 7854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 7919403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline u32 ehci_read(void __iomem *base, u32 reg) 8054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 8154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return __raw_readl(base + reg); 8254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 8354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 8454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* configure so an HC device and id are always provided */ 8554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* always called with process context; sleeping is OK */ 8654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 8754a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternstatic struct hc_driver __read_mostly ehci_omap_hc_driver; 8854a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern 8954a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternstatic const struct ehci_driver_overrides ehci_omap_overrides __initdata = { 90dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros .extra_priv_size = sizeof(struct omap_hcd), 9154a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern}; 9254a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern 9354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/** 9454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_probe - initialize TI-based HCDs 9554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 9654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Allocates basic resources for this USB host controller, and 9754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * then invokes the start() method for the HCD associated with it 9854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * through the hotplug entry's driver_data. 9954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 10054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_probe(struct platform_device *pdev) 10154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 102dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct device *dev = &pdev->dev; 103d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev); 104dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct resource *res; 105dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct usb_hcd *hcd; 106dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros void __iomem *regs; 10722d9d8e8316d7f69046c8805ce9aa8d9c43d4e5bRussell King int ret; 108dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros int irq; 109dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros int i; 110dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct omap_hcd *omap; 11154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 11219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (usb_disabled()) 11319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 11454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 11519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (!dev->parent) { 11619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "Missing parent device\n"); 11719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 11854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 11954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 120a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros /* For DT boot, get platform data from parent. i.e. usbhshost */ 121a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros if (dev->of_node) { 122d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han pdata = dev_get_platdata(dev->parent); 123a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros dev->platform_data = pdata; 124a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros } 125a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros 126a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros if (!pdata) { 127a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros dev_err(dev, "Missing platform data\n"); 128a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros return -ENODEV; 129a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros } 130a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros 1313414211b914464113ba3cd19726e44b5e416087dRoger Quadros irq = platform_get_irq(pdev, 0); 13219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (irq < 0) { 13319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "EHCI irq failed\n"); 13419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 13519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda } 13654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 1373414211b914464113ba3cd19726e44b5e416087dRoger Quadros res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 13818c2bb1b8c1571f4c1fa33cc1f4525b282059455Roger Quadros regs = devm_ioremap_resource(dev, res); 13918c2bb1b8c1571f4c1fa33cc1f4525b282059455Roger Quadros if (IS_ERR(regs)) 14018c2bb1b8c1571f4c1fa33cc1f4525b282059455Roger Quadros return PTR_ERR(regs); 14154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 142a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros /* 143a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros * Right now device-tree probed devices don't get dma_mask set. 144a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros * Since shared usb code relies on it, set it here for now. 145a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros * Once we have dma capability bindings this can go away. 146a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros */ 147e1fd7341837238c6c5380c5073887d238f706cf0Russell King ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); 14822d9d8e8316d7f69046c8805ce9aa8d9c43d4e5bRussell King if (ret) 14922d9d8e8316d7f69046c8805ce9aa8d9c43d4e5bRussell King return ret; 150a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros 15122d9d8e8316d7f69046c8805ce9aa8d9c43d4e5bRussell King ret = -ENODEV; 15219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, 15319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_name(dev)); 15454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi if (!hcd) { 15518c2bb1b8c1571f4c1fa33cc1f4525b282059455Roger Quadros dev_err(dev, "Failed to create HCD\n"); 15618c2bb1b8c1571f4c1fa33cc1f4525b282059455Roger Quadros return -ENOMEM; 15754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 15854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 15954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi hcd->rsrc_start = res->start; 16054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi hcd->rsrc_len = resource_size(res); 16119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda hcd->regs = regs; 162413fd1e9aa3e0441e64ed4703ce1bba164e135c0Roger Quadros hcd_to_ehci(hcd)->caps = regs; 16354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 164dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; 165dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros omap->nports = pdata->nports; 166dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 167dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros platform_set_drvdata(pdev, hcd); 168dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 169dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros /* get the PHY devices if needed */ 170dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros for (i = 0 ; i < omap->nports ; i++) { 171dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct usb_phy *phy; 172dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 173dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros /* get the PHY device */ 174a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros if (dev->of_node) 175a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros phy = devm_usb_get_phy_by_phandle(dev, "phys", i); 176a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros else 177a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros phy = devm_usb_get_phy_dev(dev, i); 1782bef64b89ae315e7935067ce8db901783deaf857Roger Quadros if (IS_ERR(phy)) { 179a2f450ca88a394e282f09e5e16f9de60cd487f80Roger Quadros /* Don't bail out if PHY is not absolutely necessary */ 180a2f450ca88a394e282f09e5e16f9de60cd487f80Roger Quadros if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) 181a2f450ca88a394e282f09e5e16f9de60cd487f80Roger Quadros continue; 182a2f450ca88a394e282f09e5e16f9de60cd487f80Roger Quadros 1832bef64b89ae315e7935067ce8db901783deaf857Roger Quadros ret = PTR_ERR(phy); 184dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros dev_err(dev, "Can't get PHY device for port %d: %d\n", 185dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros i, ret); 186dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros goto err_phy; 187dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros } 188dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 189dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros omap->phy[i] = phy; 1904e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros 1914e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) { 1924e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros usb_phy_init(omap->phy[i]); 1934e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros /* bring PHY out of suspend */ 1944e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros usb_phy_set_suspend(omap->phy[i], 0); 1954e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros } 196dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros } 197dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 1986c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_enable(dev); 1996c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_get_sync(dev); 20054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 20119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda /* 20219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * An undocumented "feature" in the OMAP3 EHCI controller, 20319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * causes suspended ports to be taken out of suspend when 20419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * the USBCMD.Run/Stop bit is cleared (for example when 20519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * we do ehci_bus_suspend). 20619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * This breaks suspend-resume if the root-hub is allowed 20719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * to suspend. Writing 1 to this undocumented register bit 20819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * disables this feature and restores normal behavior. 20919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda */ 21019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda ehci_write(regs, EHCI_INSNREG04, 21119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda EHCI_INSNREG04_DISABLE_UNSUSPEND); 21254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 2133aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill ret = usb_add_hcd(hcd, irq, IRQF_SHARED); 2143aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill if (ret) { 2153aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill dev_err(dev, "failed to add hcd with err %d\n", ret); 216984e97483a143f95d861b7218161ae033df293abRuss Dill goto err_pm_runtime; 2173aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill } 2183c9740a117d40a74412775b5d3fe2b88a7635a0ePeter Chen device_wakeup_enable(hcd->self.controller); 2193aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill 22049f092198f4fd2c70847de7151d33df08929af51Roger Quadros /* 2214e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros * Bring PHYs out of reset for non PHY modes. 22249f092198f4fd2c70847de7151d33df08929af51Roger Quadros * Even though HSIC mode is a PHY-less mode, the reset 22349f092198f4fd2c70847de7151d33df08929af51Roger Quadros * line exists between the chips and can be modelled 22449f092198f4fd2c70847de7151d33df08929af51Roger Quadros * as a PHY device for reset control. 22549f092198f4fd2c70847de7151d33df08929af51Roger Quadros */ 22649f092198f4fd2c70847de7151d33df08929af51Roger Quadros for (i = 0; i < omap->nports; i++) { 2274e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros if (!omap->phy[i] || 2284e5c9e6fa2d232a0686d5fe45cd1508484048936Roger Quadros pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) 22949f092198f4fd2c70847de7151d33df08929af51Roger Quadros continue; 23049f092198f4fd2c70847de7151d33df08929af51Roger Quadros 23149f092198f4fd2c70847de7151d33df08929af51Roger Quadros usb_phy_init(omap->phy[i]); 23249f092198f4fd2c70847de7151d33df08929af51Roger Quadros /* bring PHY out of suspend */ 23349f092198f4fd2c70847de7151d33df08929af51Roger Quadros usb_phy_set_suspend(omap->phy[i], 0); 23449f092198f4fd2c70847de7151d33df08929af51Roger Quadros } 235354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar 23654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return 0; 23754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 238984e97483a143f95d861b7218161ae033df293abRuss Dillerr_pm_runtime: 2396c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_put_sync(dev); 240dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 241dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadroserr_phy: 242dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros for (i = 0; i < omap->nports; i++) { 243dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros if (omap->phy[i]) 244dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros usb_phy_shutdown(omap->phy[i]); 245dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros } 246dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 247984e97483a143f95d861b7218161ae033df293abRuss Dill usb_put_hcd(hcd); 24854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 24954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return ret; 25054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 25154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 25254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 25354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/** 25454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs 25554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * @pdev: USB Host Controller being removed 25654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 25754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking 25854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the HCD's stop() method. It is always called from a thread 25954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * context, normally "rmmod", "apmd", or something similar. 26054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 26154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_remove(struct platform_device *pdev) 26254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 263dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct device *dev = &pdev->dev; 264dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct usb_hcd *hcd = dev_get_drvdata(dev); 265dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; 266dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros int i; 26754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 26854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi usb_remove_hcd(hcd); 269354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar 270dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros for (i = 0; i < omap->nports; i++) { 271dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros if (omap->phy[i]) 272dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros usb_phy_shutdown(omap->phy[i]); 273dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros } 274dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros 275dcd64063fd917b5c79f99cae218e1df3ed1b62a2Roger Quadros usb_put_hcd(hcd); 2766c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_put_sync(dev); 2776c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_disable(dev); 2786c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda 27954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return 0; 28054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 28154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 282a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadrosstatic const struct of_device_id omap_ehci_dt_ids[] = { 283a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros { .compatible = "ti,ehci-omap" }, 284a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros { } 285a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros}; 286a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros 287a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger QuadrosMODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); 288a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger Quadros 28954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic struct platform_driver ehci_hcd_omap_driver = { 29054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .probe = ehci_hcd_omap_probe, 29154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .remove = ehci_hcd_omap_remove, 292aaf6b52d50f85ed792c9c8987f5169f3dce2adeaRoger Quadros .shutdown = usb_hcd_platform_shutdown, 29354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /*.suspend = ehci_hcd_omap_suspend, */ 29454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /*.resume = ehci_hcd_omap_resume, */ 29554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .driver = { 29654a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern .name = hcd_name, 297be4b08ccfbd0faa7f92398213b2d3783389dc358Sachin Kamat .of_match_table = omap_ehci_dt_ids, 29854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 29954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}; 30054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 30154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/ 30254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 30354a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternstatic int __init ehci_omap_init(void) 30454a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern{ 30554a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern if (usb_disabled()) 30654a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern return -ENODEV; 30754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 30854a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern pr_info("%s: " DRIVER_DESC "\n", hcd_name); 30954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 31054a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); 31154a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern return platform_driver_register(&ehci_hcd_omap_driver); 31254a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern} 31354a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternmodule_init(ehci_omap_init); 31454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 31554a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternstatic void __exit ehci_omap_cleanup(void) 31654a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern{ 31754a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern platform_driver_unregister(&ehci_hcd_omap_driver); 31854a419668b0f27b7982807fb2376d237e0a0ce05Alan Stern} 31954a419668b0f27b7982807fb2376d237e0a0ce05Alan Sternmodule_exit(ehci_omap_cleanup); 32054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 32104753523266629b1cd0518091da1658755787198Roger QuadrosMODULE_ALIAS("platform:ehci-omap"); 32254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Texas Instruments, Inc."); 32354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); 324a1ae0affee119e6deb937d157aa8b43319c1d6f3Roger QuadrosMODULE_AUTHOR("Roger Quadros <rogerq@ti.com>"); 32554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 32654a419668b0f27b7982807fb2376d237e0a0ce05Alan SternMODULE_DESCRIPTION(DRIVER_DESC); 32754a419668b0f27b7982807fb2376d237e0a0ce05Alan SternMODULE_LICENSE("GPL"); 328