ehci-omap.c revision 04753523266629b1cd0518091da1658755787198
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 * 719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * Copyright (C) 2007-2011 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> 1154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 1254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Copyright (C) 2009 Nokia Corporation 1354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Contact: Felipe Balbi <felipe.balbi@nokia.com> 1454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 1554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers 1654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 1754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is free software; you can redistribute it and/or modify 1854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * it under the terms of the GNU General Public License as published by 1954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the Free Software Foundation; either version 2 of the License, or 2054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * (at your option) any later version. 2154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 2254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is distributed in the hope that it will be useful, 2354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * but WITHOUT ANY WARRANTY; without even the implied warranty of 2454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * GNU General Public License for more details. 2654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 2754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * You should have received a copy of the GNU General Public License 2854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * along with this program; if not, write to the Free Software 2954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 3054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 3119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * TODO (last updated Feb 27, 2010): 3254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * - add kernel-doc 3354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * - enable AUTOIDLE 3454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * - add suspend/resume 354792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * - add HSIC and TLL support 364792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * - convert to use hwmod and runtime PM 3754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 3854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 3954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#include <linux/platform_device.h> 405a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 415aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta#include <linux/usb/ulpi.h> 426e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda#include <linux/regulator/consumer.h> 436c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda#include <linux/pm_runtime.h> 441fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda#include <linux/gpio.h> 45354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar#include <linux/clk.h> 4654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 47e8c4a7acc9ec0ee82feedcdc3c6d0ee44d67918aFelipe Balbi#include <linux/platform_data/usb-omap.h> 48e8c4a7acc9ec0ee82feedcdc3c6d0ee44d67918aFelipe Balbi 4954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* EHCI Register Set */ 50572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04 (0xA0) 51572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) 5254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI (0xA4) 5354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 5454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 5554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 5654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 5754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 5854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 5954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 6019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda/*-------------------------------------------------------------------------*/ 614792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar 6219403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic const struct hc_driver ehci_omap_hc_driver; 634792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar 64a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar 6519403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline void ehci_write(void __iomem *base, u32 reg, u32 val) 6654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 6754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi __raw_writel(val, base + reg); 6854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 6954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 7019403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline u32 ehci_read(void __iomem *base, u32 reg) 7154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 7254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return __raw_readl(base + reg); 7354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 7454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 75354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar 76ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Leistatic void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) 775aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta{ 785aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta unsigned long timeout = jiffies + msecs_to_jiffies(1000); 795aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta unsigned reg = 0; 805aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta 815aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta reg = ULPI_FUNC_CTRL_RESET 825aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta /* FUNCTION_CTRL_SET register */ 835aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) 845aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta /* Write */ 855aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) 865aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta /* PORTn */ 875aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) 885aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta /* start ULPI access*/ 895aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); 905aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta 9119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); 925aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta 935aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta /* Wait for ULPI access completion */ 9419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) 955aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { 965aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta cpu_relax(); 975aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta 985aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta if (time_after(jiffies, timeout)) { 99ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei dev_dbg(hcd->self.controller, 100ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei "phy reset operation timed out\n"); 1015aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta break; 1025aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta } 1035aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta } 1045aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta} 1055aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta 1061a49e2ac9651df7349867a5cf44e2c83de1046afAlan Sternstatic int omap_ehci_init(struct usb_hcd *hcd) 1071a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern{ 1081a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern struct ehci_hcd *ehci = hcd_to_ehci(hcd); 1091a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern int rc; 1101a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern struct ehci_hcd_omap_platform_data *pdata; 1111a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1121a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern pdata = hcd->self.controller->platform_data; 1133e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds 1143e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds /* Hold PHYs in reset while initializing EHCI controller */ 1151a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (pdata->phy_reset) { 1161a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (gpio_is_valid(pdata->reset_gpio_port[0])) 1173e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); 1181a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1191a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (gpio_is_valid(pdata->reset_gpio_port[1])) 1203e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); 1211a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1221a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern /* Hold the PHY in RESET for enough time till DIR is high */ 1231a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern udelay(10); 1241a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern } 1251a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1261a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern /* Soft reset the PHY using PHY reset command over ULPI */ 1271a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) 128ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei omap_ehci_soft_phy_reset(hcd, 0); 1291a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) 130ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei omap_ehci_soft_phy_reset(hcd, 1); 1311a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1321a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern /* we know this is the memory we want, no need to ioremap again */ 1331a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern ehci->caps = hcd->regs; 1341a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1351a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern rc = ehci_setup(hcd); 1361a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1371a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (pdata->phy_reset) { 1381a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern /* Hold the PHY in RESET for enough time till 1391a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern * PHY is settled and ready 1401a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern */ 1411a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern udelay(10); 1421a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1431a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (gpio_is_valid(pdata->reset_gpio_port[0])) 1441a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); 1451a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1461a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern if (gpio_is_valid(pdata->reset_gpio_port[1])) 1471a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); 1481a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern } 1491a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 1501a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern return rc; 1511a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern} 1521a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern 153d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Leistatic void disable_put_regulator( 154d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei struct ehci_hcd_omap_platform_data *pdata) 155d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei{ 156d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei int i; 157d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei 158d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { 159d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei if (pdata->regulator[i]) { 160d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei regulator_disable(pdata->regulator[i]); 161d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei regulator_put(pdata->regulator[i]); 162d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei } 163d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei } 164d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei} 16554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 16654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* configure so an HC device and id are always provided */ 16754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* always called with process context; sleeping is OK */ 16854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 16954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/** 17054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_probe - initialize TI-based HCDs 17154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 17254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Allocates basic resources for this USB host controller, and 17354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * then invokes the start() method for the HCD associated with it 17454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * through the hotplug entry's driver_data. 17554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 17654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_probe(struct platform_device *pdev) 17754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 17819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda struct device *dev = &pdev->dev; 17919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; 18019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda struct resource *res; 18119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda struct usb_hcd *hcd; 18219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda void __iomem *regs; 18319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda int ret = -ENODEV; 18419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda int irq; 1856e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda int i; 1866e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda char supply[7]; 18754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 18819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (usb_disabled()) 18919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 19054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 19119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (!dev->parent) { 19219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "Missing parent device\n"); 19319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 19454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 19554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 19619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda irq = platform_get_irq_byname(pdev, "ehci-irq"); 19719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (irq < 0) { 19819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "EHCI irq failed\n"); 19919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 20019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda } 20154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 20219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda res = platform_get_resource_byname(pdev, 20319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda IORESOURCE_MEM, "ehci"); 20419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (!res) { 20519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "UHH EHCI get resource failed\n"); 20619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENODEV; 20719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda } 20819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda 20919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda regs = ioremap(res->start, resource_size(res)); 21019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda if (!regs) { 21119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "UHH EHCI ioremap failed\n"); 21219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda return -ENOMEM; 21354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 21454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 21519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, 21619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_name(dev)); 21754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi if (!hcd) { 21819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda dev_err(dev, "failed to create hcd with err %d\n", ret); 21954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi ret = -ENOMEM; 22019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda goto err_io; 22154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 22254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 22354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi hcd->rsrc_start = res->start; 22454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi hcd->rsrc_len = resource_size(res); 22519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda hcd->regs = regs; 22654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 2276e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda /* get ehci regulator and enable */ 2286e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { 2296e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { 2306e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda pdata->regulator[i] = NULL; 2316e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda continue; 2326e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda } 2336e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda snprintf(supply, sizeof(supply), "hsusb%d", i); 2346e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda pdata->regulator[i] = regulator_get(dev, supply); 2356e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda if (IS_ERR(pdata->regulator[i])) { 2366e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda pdata->regulator[i] = NULL; 2376e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda dev_dbg(dev, 2386e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda "failed to get ehci port%d regulator\n", i); 2396e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda } else { 2406e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda regulator_enable(pdata->regulator[i]); 2416e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda } 2426e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda } 2436e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda 2446c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_enable(dev); 2456c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_get_sync(dev); 24654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 24719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda /* 24819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * An undocumented "feature" in the OMAP3 EHCI controller, 24919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * causes suspended ports to be taken out of suspend when 25019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * the USBCMD.Run/Stop bit is cleared (for example when 25119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * we do ehci_bus_suspend). 25219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * This breaks suspend-resume if the root-hub is allowed 25319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * to suspend. Writing 1 to this undocumented register bit 25419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * disables this feature and restores normal behavior. 25519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda */ 25619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda ehci_write(regs, EHCI_INSNREG04, 25719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda EHCI_INSNREG04_DISABLE_UNSUSPEND); 25854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 2593aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill ret = usb_add_hcd(hcd, irq, IRQF_SHARED); 2603aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill if (ret) { 2613aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill dev_err(dev, "failed to add hcd with err %d\n", ret); 262984e97483a143f95d861b7218161ae033df293abRuss Dill goto err_pm_runtime; 2633aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill } 2643aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill 265354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar 26654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return 0; 26754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 268984e97483a143f95d861b7218161ae033df293abRuss Dillerr_pm_runtime: 269d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei disable_put_regulator(pdata); 2706c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_put_sync(dev); 271984e97483a143f95d861b7218161ae033df293abRuss Dill usb_put_hcd(hcd); 27254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 27319403165c272cc4ed00c97973e7271714b009708Keshava Munegowdaerr_io: 274d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei iounmap(regs); 27554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return ret; 27654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 27754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 27854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 27954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/** 28054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs 28154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * @pdev: USB Host Controller being removed 28254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * 28354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking 28454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the HCD's stop() method. It is always called from a thread 28554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * context, normally "rmmod", "apmd", or something similar. 28654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 28754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_remove(struct platform_device *pdev) 28854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 2891fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda struct device *dev = &pdev->dev; 2901fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda struct usb_hcd *hcd = dev_get_drvdata(dev); 29154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 29254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi usb_remove_hcd(hcd); 293d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei disable_put_regulator(dev->platform_data); 294d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei iounmap(hcd->regs); 29554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi usb_put_hcd(hcd); 296354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar 2976c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_put_sync(dev); 2986c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda pm_runtime_disable(dev); 2996c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda 30054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi return 0; 30154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 30254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 30354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic void ehci_hcd_omap_shutdown(struct platform_device *pdev) 30454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{ 30519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); 30654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 30754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi if (hcd->driver->shutdown) 30854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi hcd->driver->shutdown(hcd); 30954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi} 31054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 31154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic struct platform_driver ehci_hcd_omap_driver = { 31254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .probe = ehci_hcd_omap_probe, 31354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .remove = ehci_hcd_omap_remove, 31454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .shutdown = ehci_hcd_omap_shutdown, 31554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /*.suspend = ehci_hcd_omap_suspend, */ 31654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /*.resume = ehci_hcd_omap_resume, */ 31754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .driver = { 31854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .name = "ehci-omap", 31954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi } 32054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}; 32154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 32254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/ 32354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 32454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic const struct hc_driver ehci_omap_hc_driver = { 32554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .description = hcd_name, 32654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .product_desc = "OMAP-EHCI Host Controller", 32754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .hcd_priv_size = sizeof(struct ehci_hcd), 32854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 32954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /* 33054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * generic hardware linkage 33154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 33254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .irq = ehci_irq, 33354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .flags = HCD_MEMORY | HCD_USB2, 33454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 33554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /* 33654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * basic lifecycle operations 33754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 3381a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern .reset = omap_ehci_init, 33954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .start = ehci_run, 34054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .stop = ehci_stop, 34154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .shutdown = ehci_shutdown, 34254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 34354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /* 34454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * managing i/o requests and associated device resources 34554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 34654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .urb_enqueue = ehci_urb_enqueue, 34754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .urb_dequeue = ehci_urb_dequeue, 34854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .endpoint_disable = ehci_endpoint_disable, 34954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .endpoint_reset = ehci_endpoint_reset, 35054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 35154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /* 35254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * scheduling support 35354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 35454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .get_frame_number = ehci_get_frame, 35554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 35654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi /* 35754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * root hub support 35854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */ 35954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .hub_status_data = ehci_hub_status_data, 360872c495dd0f9d1f48814a8ee80c2c7b3b7c3b4d9Keshava Munegowda .hub_control = ehci_hub_control, 36154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .bus_suspend = ehci_bus_suspend, 36254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .bus_resume = ehci_bus_resume, 36354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 36454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 36554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}; 36654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 36704753523266629b1cd0518091da1658755787198Roger QuadrosMODULE_ALIAS("platform:ehci-omap"); 36854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Texas Instruments, Inc."); 36954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); 37054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi 371