1 /* 2 * ehci-omap.c - driver for USBHOST on OMAP3/4 processors 3 * 4 * Bus Glue for the EHCI controllers in OMAP3/4 5 * Tested on several OMAP3 boards, and OMAP4 Pandaboard 6 * 7 * Copyright (C) 2007-2011 Texas Instruments, Inc. 8 * Author: Vikram Pandita <vikram.pandita@ti.com> 9 * Author: Anand Gadiyar <gadiyar@ti.com> 10 * Author: Keshava Munegowda <keshava_mgowda@ti.com> 11 * 12 * Copyright (C) 2009 Nokia Corporation 13 * Contact: Felipe Balbi <felipe.balbi@nokia.com> 14 * 15 * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers 16 * 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU General Public License as published by 19 * the Free Software Foundation; either version 2 of the License, or 20 * (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30 * 31 * TODO (last updated Feb 27, 2010): 32 * - add kernel-doc 33 * - enable AUTOIDLE 34 * - add suspend/resume 35 * - add HSIC and TLL support 36 * - convert to use hwmod and runtime PM 37 */ 38 39 #include <linux/platform_device.h> 40 #include <linux/slab.h> 41 #include <linux/usb/ulpi.h> 42 #include <plat/usb.h> 43 #include <linux/regulator/consumer.h> 44 #include <linux/pm_runtime.h> 45 #include <linux/gpio.h> 46 47 /* EHCI Register Set */ 48 #define EHCI_INSNREG04 (0xA0) 49 #define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) 50 #define EHCI_INSNREG05_ULPI (0xA4) 51 #define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 52 #define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 53 #define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 54 #define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 55 #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 56 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 57 58 /*-------------------------------------------------------------------------*/ 59 60 static const struct hc_driver ehci_omap_hc_driver; 61 62 63 static inline void ehci_write(void __iomem *base, u32 reg, u32 val) 64 { 65 __raw_writel(val, base + reg); 66 } 67 68 static inline u32 ehci_read(void __iomem *base, u32 reg) 69 { 70 return __raw_readl(base + reg); 71 } 72 73 static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) 74 { 75 struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); 76 unsigned long timeout = jiffies + msecs_to_jiffies(1000); 77 unsigned reg = 0; 78 79 reg = ULPI_FUNC_CTRL_RESET 80 /* FUNCTION_CTRL_SET register */ 81 | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) 82 /* Write */ 83 | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) 84 /* PORTn */ 85 | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) 86 /* start ULPI access*/ 87 | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); 88 89 ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); 90 91 /* Wait for ULPI access completion */ 92 while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) 93 & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { 94 cpu_relax(); 95 96 if (time_after(jiffies, timeout)) { 97 dev_dbg(&pdev->dev, "phy reset operation timed out\n"); 98 break; 99 } 100 } 101 } 102 103 static void disable_put_regulator( 104 struct ehci_hcd_omap_platform_data *pdata) 105 { 106 int i; 107 108 for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { 109 if (pdata->regulator[i]) { 110 regulator_disable(pdata->regulator[i]); 111 regulator_put(pdata->regulator[i]); 112 } 113 } 114 } 115 116 /* configure so an HC device and id are always provided */ 117 /* always called with process context; sleeping is OK */ 118 119 /** 120 * ehci_hcd_omap_probe - initialize TI-based HCDs 121 * 122 * Allocates basic resources for this USB host controller, and 123 * then invokes the start() method for the HCD associated with it 124 * through the hotplug entry's driver_data. 125 */ 126 static int ehci_hcd_omap_probe(struct platform_device *pdev) 127 { 128 struct device *dev = &pdev->dev; 129 struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; 130 struct resource *res; 131 struct usb_hcd *hcd; 132 void __iomem *regs; 133 struct ehci_hcd *omap_ehci; 134 int ret = -ENODEV; 135 int irq; 136 int i; 137 char supply[7]; 138 139 if (usb_disabled()) 140 return -ENODEV; 141 142 if (!dev->parent) { 143 dev_err(dev, "Missing parent device\n"); 144 return -ENODEV; 145 } 146 147 irq = platform_get_irq_byname(pdev, "ehci-irq"); 148 if (irq < 0) { 149 dev_err(dev, "EHCI irq failed\n"); 150 return -ENODEV; 151 } 152 153 res = platform_get_resource_byname(pdev, 154 IORESOURCE_MEM, "ehci"); 155 if (!res) { 156 dev_err(dev, "UHH EHCI get resource failed\n"); 157 return -ENODEV; 158 } 159 160 regs = ioremap(res->start, resource_size(res)); 161 if (!regs) { 162 dev_err(dev, "UHH EHCI ioremap failed\n"); 163 return -ENOMEM; 164 } 165 166 hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, 167 dev_name(dev)); 168 if (!hcd) { 169 dev_err(dev, "failed to create hcd with err %d\n", ret); 170 ret = -ENOMEM; 171 goto err_io; 172 } 173 174 hcd->rsrc_start = res->start; 175 hcd->rsrc_len = resource_size(res); 176 hcd->regs = regs; 177 178 /* get ehci regulator and enable */ 179 for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { 180 if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { 181 pdata->regulator[i] = NULL; 182 continue; 183 } 184 snprintf(supply, sizeof(supply), "hsusb%d", i); 185 pdata->regulator[i] = regulator_get(dev, supply); 186 if (IS_ERR(pdata->regulator[i])) { 187 pdata->regulator[i] = NULL; 188 dev_dbg(dev, 189 "failed to get ehci port%d regulator\n", i); 190 } else { 191 regulator_enable(pdata->regulator[i]); 192 } 193 } 194 195 if (pdata->phy_reset) { 196 if (gpio_is_valid(pdata->reset_gpio_port[0])) 197 gpio_request_one(pdata->reset_gpio_port[0], 198 GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); 199 200 if (gpio_is_valid(pdata->reset_gpio_port[1])) 201 gpio_request_one(pdata->reset_gpio_port[1], 202 GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); 203 204 /* Hold the PHY in RESET for enough time till DIR is high */ 205 udelay(10); 206 } 207 208 pm_runtime_enable(dev); 209 pm_runtime_get_sync(dev); 210 211 /* 212 * An undocumented "feature" in the OMAP3 EHCI controller, 213 * causes suspended ports to be taken out of suspend when 214 * the USBCMD.Run/Stop bit is cleared (for example when 215 * we do ehci_bus_suspend). 216 * This breaks suspend-resume if the root-hub is allowed 217 * to suspend. Writing 1 to this undocumented register bit 218 * disables this feature and restores normal behavior. 219 */ 220 ehci_write(regs, EHCI_INSNREG04, 221 EHCI_INSNREG04_DISABLE_UNSUSPEND); 222 223 /* Soft reset the PHY using PHY reset command over ULPI */ 224 if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) 225 omap_ehci_soft_phy_reset(pdev, 0); 226 if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) 227 omap_ehci_soft_phy_reset(pdev, 1); 228 229 omap_ehci = hcd_to_ehci(hcd); 230 omap_ehci->sbrn = 0x20; 231 232 /* we know this is the memory we want, no need to ioremap again */ 233 omap_ehci->caps = hcd->regs; 234 omap_ehci->regs = hcd->regs 235 + HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase)); 236 237 dbg_hcs_params(omap_ehci, "reset"); 238 dbg_hcc_params(omap_ehci, "reset"); 239 240 /* cache this readonly data; minimize chip reads */ 241 omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); 242 243 ehci_reset(omap_ehci); 244 245 ret = usb_add_hcd(hcd, irq, IRQF_SHARED); 246 if (ret) { 247 dev_err(dev, "failed to add hcd with err %d\n", ret); 248 goto err_add_hcd; 249 } 250 251 /* root ports should always stay powered */ 252 ehci_port_power(omap_ehci, 1); 253 254 if (pdata->phy_reset) { 255 /* Hold the PHY in RESET for enough time till 256 * PHY is settled and ready 257 */ 258 udelay(10); 259 260 if (gpio_is_valid(pdata->reset_gpio_port[0])) 261 gpio_set_value(pdata->reset_gpio_port[0], 1); 262 263 if (gpio_is_valid(pdata->reset_gpio_port[1])) 264 gpio_set_value(pdata->reset_gpio_port[1], 1); 265 } 266 267 return 0; 268 269 err_add_hcd: 270 disable_put_regulator(pdata); 271 pm_runtime_put_sync(dev); 272 273 err_io: 274 iounmap(regs); 275 return ret; 276 } 277 278 279 /** 280 * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs 281 * @pdev: USB Host Controller being removed 282 * 283 * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking 284 * the HCD's stop() method. It is always called from a thread 285 * context, normally "rmmod", "apmd", or something similar. 286 */ 287 static int ehci_hcd_omap_remove(struct platform_device *pdev) 288 { 289 struct device *dev = &pdev->dev; 290 struct usb_hcd *hcd = dev_get_drvdata(dev); 291 struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; 292 293 usb_remove_hcd(hcd); 294 disable_put_regulator(dev->platform_data); 295 iounmap(hcd->regs); 296 usb_put_hcd(hcd); 297 pm_runtime_put_sync(dev); 298 pm_runtime_disable(dev); 299 300 if (pdata->phy_reset) { 301 if (gpio_is_valid(pdata->reset_gpio_port[0])) 302 gpio_free(pdata->reset_gpio_port[0]); 303 304 if (gpio_is_valid(pdata->reset_gpio_port[1])) 305 gpio_free(pdata->reset_gpio_port[1]); 306 } 307 return 0; 308 } 309 310 static void ehci_hcd_omap_shutdown(struct platform_device *pdev) 311 { 312 struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); 313 314 if (hcd->driver->shutdown) 315 hcd->driver->shutdown(hcd); 316 } 317 318 static struct platform_driver ehci_hcd_omap_driver = { 319 .probe = ehci_hcd_omap_probe, 320 .remove = ehci_hcd_omap_remove, 321 .shutdown = ehci_hcd_omap_shutdown, 322 /*.suspend = ehci_hcd_omap_suspend, */ 323 /*.resume = ehci_hcd_omap_resume, */ 324 .driver = { 325 .name = "ehci-omap", 326 } 327 }; 328 329 /*-------------------------------------------------------------------------*/ 330 331 static const struct hc_driver ehci_omap_hc_driver = { 332 .description = hcd_name, 333 .product_desc = "OMAP-EHCI Host Controller", 334 .hcd_priv_size = sizeof(struct ehci_hcd), 335 336 /* 337 * generic hardware linkage 338 */ 339 .irq = ehci_irq, 340 .flags = HCD_MEMORY | HCD_USB2, 341 342 /* 343 * basic lifecycle operations 344 */ 345 .reset = ehci_init, 346 .start = ehci_run, 347 .stop = ehci_stop, 348 .shutdown = ehci_shutdown, 349 350 /* 351 * managing i/o requests and associated device resources 352 */ 353 .urb_enqueue = ehci_urb_enqueue, 354 .urb_dequeue = ehci_urb_dequeue, 355 .endpoint_disable = ehci_endpoint_disable, 356 .endpoint_reset = ehci_endpoint_reset, 357 358 /* 359 * scheduling support 360 */ 361 .get_frame_number = ehci_get_frame, 362 363 /* 364 * root hub support 365 */ 366 .hub_status_data = ehci_hub_status_data, 367 .hub_control = ehci_hub_control, 368 .bus_suspend = ehci_bus_suspend, 369 .bus_resume = ehci_bus_resume, 370 371 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 372 }; 373 374 MODULE_ALIAS("platform:omap-ehci"); 375 MODULE_AUTHOR("Texas Instruments, Inc."); 376 MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); 377 378