1 /* 2 * Copyright (C) 2005-2007 by Texas Instruments 3 * Some code has been taken from tusb6010.c 4 * Copyrights for that are attributable to: 5 * Copyright (C) 2006 Nokia Corporation 6 * Tony Lindgren <tony@atomide.com> 7 * 8 * This file is part of the Inventra Controller Driver for Linux. 9 * 10 * SPDX-License-Identifier: GPL-2.0 11 */ 12 #ifndef __UBOOT__ 13 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/sched.h> 16 #include <linux/init.h> 17 #include <linux/list.h> 18 #include <linux/io.h> 19 #include <linux/platform_device.h> 20 #include <linux/dma-mapping.h> 21 #include <linux/pm_runtime.h> 22 #include <linux/err.h> 23 #include <linux/usb/musb-omap.h> 24 #else 25 #include <common.h> 26 #include <asm/omap_musb.h> 27 #include <twl4030.h> 28 #include "linux-compat.h" 29 #endif 30 31 #include "musb_core.h" 32 #include "omap2430.h" 33 34 #ifndef __UBOOT__ 35 struct omap2430_glue { 36 struct device *dev; 37 struct platform_device *musb; 38 enum omap_musb_vbus_id_status status; 39 struct work_struct omap_musb_mailbox_work; 40 }; 41 #define glue_to_musb(g) platform_get_drvdata(g->musb) 42 43 struct omap2430_glue *_glue; 44 45 static struct timer_list musb_idle_timer; 46 47 static void musb_do_idle(unsigned long _musb) 48 { 49 struct musb *musb = (void *)_musb; 50 unsigned long flags; 51 u8 power; 52 u8 devctl; 53 54 spin_lock_irqsave(&musb->lock, flags); 55 56 switch (musb->xceiv->state) { 57 case OTG_STATE_A_WAIT_BCON: 58 59 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 60 if (devctl & MUSB_DEVCTL_BDEVICE) { 61 musb->xceiv->state = OTG_STATE_B_IDLE; 62 MUSB_DEV_MODE(musb); 63 } else { 64 musb->xceiv->state = OTG_STATE_A_IDLE; 65 MUSB_HST_MODE(musb); 66 } 67 break; 68 case OTG_STATE_A_SUSPEND: 69 /* finish RESUME signaling? */ 70 if (musb->port1_status & MUSB_PORT_STAT_RESUME) { 71 power = musb_readb(musb->mregs, MUSB_POWER); 72 power &= ~MUSB_POWER_RESUME; 73 dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power); 74 musb_writeb(musb->mregs, MUSB_POWER, power); 75 musb->is_active = 1; 76 musb->port1_status &= ~(USB_PORT_STAT_SUSPEND 77 | MUSB_PORT_STAT_RESUME); 78 musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; 79 usb_hcd_poll_rh_status(musb_to_hcd(musb)); 80 /* NOTE: it might really be A_WAIT_BCON ... */ 81 musb->xceiv->state = OTG_STATE_A_HOST; 82 } 83 break; 84 case OTG_STATE_A_HOST: 85 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 86 if (devctl & MUSB_DEVCTL_BDEVICE) 87 musb->xceiv->state = OTG_STATE_B_IDLE; 88 else 89 musb->xceiv->state = OTG_STATE_A_WAIT_BCON; 90 default: 91 break; 92 } 93 spin_unlock_irqrestore(&musb->lock, flags); 94 } 95 96 97 static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) 98 { 99 unsigned long default_timeout = jiffies + msecs_to_jiffies(3); 100 static unsigned long last_timer; 101 102 if (timeout == 0) 103 timeout = default_timeout; 104 105 /* Never idle if active, or when VBUS timeout is not set as host */ 106 if (musb->is_active || ((musb->a_wait_bcon == 0) 107 && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { 108 dev_dbg(musb->controller, "%s active, deleting timer\n", 109 otg_state_string(musb->xceiv->state)); 110 del_timer(&musb_idle_timer); 111 last_timer = jiffies; 112 return; 113 } 114 115 if (time_after(last_timer, timeout)) { 116 if (!timer_pending(&musb_idle_timer)) 117 last_timer = timeout; 118 else { 119 dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n"); 120 return; 121 } 122 } 123 last_timer = timeout; 124 125 dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", 126 otg_state_string(musb->xceiv->state), 127 (unsigned long)jiffies_to_msecs(timeout - jiffies)); 128 mod_timer(&musb_idle_timer, timeout); 129 } 130 131 static void omap2430_musb_set_vbus(struct musb *musb, int is_on) 132 { 133 struct usb_otg *otg = musb->xceiv->otg; 134 u8 devctl; 135 unsigned long timeout = jiffies + msecs_to_jiffies(1000); 136 int ret = 1; 137 /* HDRC controls CPEN, but beware current surges during device 138 * connect. They can trigger transient overcurrent conditions 139 * that must be ignored. 140 */ 141 142 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 143 144 if (is_on) { 145 if (musb->xceiv->state == OTG_STATE_A_IDLE) { 146 /* start the session */ 147 devctl |= MUSB_DEVCTL_SESSION; 148 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); 149 /* 150 * Wait for the musb to set as A device to enable the 151 * VBUS 152 */ 153 while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { 154 155 cpu_relax(); 156 157 if (time_after(jiffies, timeout)) { 158 dev_err(musb->controller, 159 "configured as A device timeout"); 160 ret = -EINVAL; 161 break; 162 } 163 } 164 165 if (ret && otg->set_vbus) 166 otg_set_vbus(otg, 1); 167 } else { 168 musb->is_active = 1; 169 otg->default_a = 1; 170 musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; 171 devctl |= MUSB_DEVCTL_SESSION; 172 MUSB_HST_MODE(musb); 173 } 174 } else { 175 musb->is_active = 0; 176 177 /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and 178 * jumping right to B_IDLE... 179 */ 180 181 otg->default_a = 0; 182 musb->xceiv->state = OTG_STATE_B_IDLE; 183 devctl &= ~MUSB_DEVCTL_SESSION; 184 185 MUSB_DEV_MODE(musb); 186 } 187 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); 188 189 dev_dbg(musb->controller, "VBUS %s, devctl %02x " 190 /* otg %3x conf %08x prcm %08x */ "\n", 191 otg_state_string(musb->xceiv->state), 192 musb_readb(musb->mregs, MUSB_DEVCTL)); 193 } 194 195 static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode) 196 { 197 u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 198 199 devctl |= MUSB_DEVCTL_SESSION; 200 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); 201 202 return 0; 203 } 204 #endif 205 206 static inline void omap2430_low_level_exit(struct musb *musb) 207 { 208 u32 l; 209 210 /* in any role */ 211 l = musb_readl(musb->mregs, OTG_FORCESTDBY); 212 l |= ENABLEFORCE; /* enable MSTANDBY */ 213 musb_writel(musb->mregs, OTG_FORCESTDBY, l); 214 } 215 216 static inline void omap2430_low_level_init(struct musb *musb) 217 { 218 u32 l; 219 220 l = musb_readl(musb->mregs, OTG_FORCESTDBY); 221 l &= ~ENABLEFORCE; /* disable MSTANDBY */ 222 musb_writel(musb->mregs, OTG_FORCESTDBY, l); 223 } 224 225 #ifndef __UBOOT__ 226 void omap_musb_mailbox(enum omap_musb_vbus_id_status status) 227 { 228 struct omap2430_glue *glue = _glue; 229 struct musb *musb = glue_to_musb(glue); 230 231 glue->status = status; 232 if (!musb) { 233 dev_err(glue->dev, "musb core is not yet ready\n"); 234 return; 235 } 236 237 schedule_work(&glue->omap_musb_mailbox_work); 238 } 239 EXPORT_SYMBOL_GPL(omap_musb_mailbox); 240 241 static void omap_musb_set_mailbox(struct omap2430_glue *glue) 242 { 243 struct musb *musb = glue_to_musb(glue); 244 struct device *dev = musb->controller; 245 struct musb_hdrc_platform_data *pdata = dev->platform_data; 246 struct omap_musb_board_data *data = pdata->board_data; 247 struct usb_otg *otg = musb->xceiv->otg; 248 249 switch (glue->status) { 250 case OMAP_MUSB_ID_GROUND: 251 dev_dbg(dev, "ID GND\n"); 252 253 otg->default_a = true; 254 musb->xceiv->state = OTG_STATE_A_IDLE; 255 musb->xceiv->last_event = USB_EVENT_ID; 256 if (!is_otg_enabled(musb) || musb->gadget_driver) { 257 pm_runtime_get_sync(dev); 258 usb_phy_init(musb->xceiv); 259 omap2430_musb_set_vbus(musb, 1); 260 } 261 break; 262 263 case OMAP_MUSB_VBUS_VALID: 264 dev_dbg(dev, "VBUS Connect\n"); 265 266 otg->default_a = false; 267 musb->xceiv->state = OTG_STATE_B_IDLE; 268 musb->xceiv->last_event = USB_EVENT_VBUS; 269 if (musb->gadget_driver) 270 pm_runtime_get_sync(dev); 271 usb_phy_init(musb->xceiv); 272 break; 273 274 case OMAP_MUSB_ID_FLOAT: 275 case OMAP_MUSB_VBUS_OFF: 276 dev_dbg(dev, "VBUS Disconnect\n"); 277 278 musb->xceiv->last_event = USB_EVENT_NONE; 279 if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) 280 if (musb->gadget_driver) { 281 pm_runtime_mark_last_busy(dev); 282 pm_runtime_put_autosuspend(dev); 283 } 284 285 if (data->interface_type == MUSB_INTERFACE_UTMI) { 286 if (musb->xceiv->otg->set_vbus) 287 otg_set_vbus(musb->xceiv->otg, 0); 288 } 289 usb_phy_shutdown(musb->xceiv); 290 break; 291 default: 292 dev_dbg(dev, "ID float\n"); 293 } 294 } 295 296 297 static void omap_musb_mailbox_work(struct work_struct *mailbox_work) 298 { 299 struct omap2430_glue *glue = container_of(mailbox_work, 300 struct omap2430_glue, omap_musb_mailbox_work); 301 omap_musb_set_mailbox(glue); 302 } 303 #endif 304 305 static int omap2430_musb_init(struct musb *musb) 306 { 307 u32 l; 308 int status = 0; 309 unsigned long int start; 310 #ifndef __UBOOT__ 311 struct device *dev = musb->controller; 312 struct omap2430_glue *glue = dev_get_drvdata(dev->parent); 313 struct musb_hdrc_platform_data *plat = dev->platform_data; 314 struct omap_musb_board_data *data = plat->board_data; 315 #else 316 struct omap_musb_board_data *data = 317 (struct omap_musb_board_data *)musb->controller; 318 #endif 319 320 /* Reset the controller */ 321 musb_writel(musb->mregs, OTG_SYSCONFIG, SOFTRST); 322 323 start = get_timer(0); 324 325 while (1) { 326 l = musb_readl(musb->mregs, OTG_SYSCONFIG); 327 if ((l & SOFTRST) == 0) 328 break; 329 330 if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { 331 dev_err(musb->controller, "MUSB reset is taking too long\n"); 332 return -ENODEV; 333 } 334 } 335 336 #ifndef __UBOOT__ 337 /* We require some kind of external transceiver, hooked 338 * up through ULPI. TWL4030-family PMICs include one, 339 * which needs a driver, drivers aren't always needed. 340 */ 341 musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 342 if (IS_ERR_OR_NULL(musb->xceiv)) { 343 pr_err("HS USB OTG: no transceiver configured\n"); 344 return -ENODEV; 345 } 346 347 status = pm_runtime_get_sync(dev); 348 if (status < 0) { 349 dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); 350 goto err1; 351 } 352 #endif 353 354 l = musb_readl(musb->mregs, OTG_INTERFSEL); 355 356 if (data->interface_type == MUSB_INTERFACE_UTMI) { 357 /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ 358 l &= ~ULPI_12PIN; /* Disable ULPI */ 359 l |= UTMI_8BIT; /* Enable UTMI */ 360 } else { 361 l |= ULPI_12PIN; 362 } 363 364 musb_writel(musb->mregs, OTG_INTERFSEL, l); 365 366 pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " 367 "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", 368 musb_readl(musb->mregs, OTG_REVISION), 369 musb_readl(musb->mregs, OTG_SYSCONFIG), 370 musb_readl(musb->mregs, OTG_SYSSTATUS), 371 musb_readl(musb->mregs, OTG_INTERFSEL), 372 musb_readl(musb->mregs, OTG_SIMENABLE)); 373 374 #ifndef __UBOOT__ 375 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); 376 377 if (glue->status != OMAP_MUSB_UNKNOWN) 378 omap_musb_set_mailbox(glue); 379 380 pm_runtime_put_noidle(musb->controller); 381 #endif 382 return 0; 383 384 err1: 385 return status; 386 } 387 388 #ifndef __UBOOT__ 389 static void omap2430_musb_enable(struct musb *musb) 390 #else 391 static int omap2430_musb_enable(struct musb *musb) 392 #endif 393 { 394 #ifndef __UBOOT__ 395 u8 devctl; 396 unsigned long timeout = jiffies + msecs_to_jiffies(1000); 397 struct device *dev = musb->controller; 398 struct omap2430_glue *glue = dev_get_drvdata(dev->parent); 399 struct musb_hdrc_platform_data *pdata = dev->platform_data; 400 struct omap_musb_board_data *data = pdata->board_data; 401 402 switch (glue->status) { 403 404 case OMAP_MUSB_ID_GROUND: 405 usb_phy_init(musb->xceiv); 406 if (data->interface_type != MUSB_INTERFACE_UTMI) 407 break; 408 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 409 /* start the session */ 410 devctl |= MUSB_DEVCTL_SESSION; 411 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); 412 while (musb_readb(musb->mregs, MUSB_DEVCTL) & 413 MUSB_DEVCTL_BDEVICE) { 414 cpu_relax(); 415 416 if (time_after(jiffies, timeout)) { 417 dev_err(dev, "configured as A device timeout"); 418 break; 419 } 420 } 421 break; 422 423 case OMAP_MUSB_VBUS_VALID: 424 usb_phy_init(musb->xceiv); 425 break; 426 427 default: 428 break; 429 } 430 #else 431 #ifdef CONFIG_TWL4030_USB 432 if (twl4030_usb_ulpi_init()) { 433 serial_printf("ERROR: %s Could not initialize PHY\n", 434 __PRETTY_FUNCTION__); 435 } 436 #endif 437 return 0; 438 #endif 439 } 440 441 static void omap2430_musb_disable(struct musb *musb) 442 { 443 #ifndef __UBOOT__ 444 struct device *dev = musb->controller; 445 struct omap2430_glue *glue = dev_get_drvdata(dev->parent); 446 447 if (glue->status != OMAP_MUSB_UNKNOWN) 448 usb_phy_shutdown(musb->xceiv); 449 #endif 450 } 451 452 static int omap2430_musb_exit(struct musb *musb) 453 { 454 del_timer_sync(&musb_idle_timer); 455 456 omap2430_low_level_exit(musb); 457 458 return 0; 459 } 460 461 #ifndef __UBOOT__ 462 static const struct musb_platform_ops omap2430_ops = { 463 #else 464 const struct musb_platform_ops omap2430_ops = { 465 #endif 466 .init = omap2430_musb_init, 467 .exit = omap2430_musb_exit, 468 469 #ifndef __UBOOT__ 470 .set_mode = omap2430_musb_set_mode, 471 .try_idle = omap2430_musb_try_idle, 472 473 .set_vbus = omap2430_musb_set_vbus, 474 #endif 475 476 .enable = omap2430_musb_enable, 477 .disable = omap2430_musb_disable, 478 }; 479 480 #ifndef __UBOOT__ 481 static u64 omap2430_dmamask = DMA_BIT_MASK(32); 482 483 static int __devinit omap2430_probe(struct platform_device *pdev) 484 { 485 struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; 486 struct platform_device *musb; 487 struct omap2430_glue *glue; 488 int ret = -ENOMEM; 489 490 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); 491 if (!glue) { 492 dev_err(&pdev->dev, "failed to allocate glue context\n"); 493 goto err0; 494 } 495 496 musb = platform_device_alloc("musb-hdrc", -1); 497 if (!musb) { 498 dev_err(&pdev->dev, "failed to allocate musb device\n"); 499 goto err0; 500 } 501 502 musb->dev.parent = &pdev->dev; 503 musb->dev.dma_mask = &omap2430_dmamask; 504 musb->dev.coherent_dma_mask = omap2430_dmamask; 505 506 glue->dev = &pdev->dev; 507 glue->musb = musb; 508 glue->status = OMAP_MUSB_UNKNOWN; 509 510 pdata->platform_ops = &omap2430_ops; 511 512 platform_set_drvdata(pdev, glue); 513 514 /* 515 * REVISIT if we ever have two instances of the wrapper, we will be 516 * in big trouble 517 */ 518 _glue = glue; 519 520 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); 521 522 ret = platform_device_add_resources(musb, pdev->resource, 523 pdev->num_resources); 524 if (ret) { 525 dev_err(&pdev->dev, "failed to add resources\n"); 526 goto err1; 527 } 528 529 ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); 530 if (ret) { 531 dev_err(&pdev->dev, "failed to add platform_data\n"); 532 goto err1; 533 } 534 535 pm_runtime_enable(&pdev->dev); 536 537 ret = platform_device_add(musb); 538 if (ret) { 539 dev_err(&pdev->dev, "failed to register musb device\n"); 540 goto err1; 541 } 542 543 return 0; 544 545 err1: 546 platform_device_put(musb); 547 548 err0: 549 return ret; 550 } 551 552 static int __devexit omap2430_remove(struct platform_device *pdev) 553 { 554 struct omap2430_glue *glue = platform_get_drvdata(pdev); 555 556 cancel_work_sync(&glue->omap_musb_mailbox_work); 557 platform_device_del(glue->musb); 558 platform_device_put(glue->musb); 559 560 return 0; 561 } 562 563 #ifdef CONFIG_PM 564 565 static int omap2430_runtime_suspend(struct device *dev) 566 { 567 struct omap2430_glue *glue = dev_get_drvdata(dev); 568 struct musb *musb = glue_to_musb(glue); 569 570 if (musb) { 571 musb->context.otg_interfsel = musb_readl(musb->mregs, 572 OTG_INTERFSEL); 573 574 omap2430_low_level_exit(musb); 575 usb_phy_set_suspend(musb->xceiv, 1); 576 } 577 578 return 0; 579 } 580 581 static int omap2430_runtime_resume(struct device *dev) 582 { 583 struct omap2430_glue *glue = dev_get_drvdata(dev); 584 struct musb *musb = glue_to_musb(glue); 585 586 if (musb) { 587 omap2430_low_level_init(musb); 588 musb_writel(musb->mregs, OTG_INTERFSEL, 589 musb->context.otg_interfsel); 590 591 usb_phy_set_suspend(musb->xceiv, 0); 592 } 593 594 return 0; 595 } 596 597 static struct dev_pm_ops omap2430_pm_ops = { 598 .runtime_suspend = omap2430_runtime_suspend, 599 .runtime_resume = omap2430_runtime_resume, 600 }; 601 602 #define DEV_PM_OPS (&omap2430_pm_ops) 603 #else 604 #define DEV_PM_OPS NULL 605 #endif 606 607 static struct platform_driver omap2430_driver = { 608 .probe = omap2430_probe, 609 .remove = __devexit_p(omap2430_remove), 610 .driver = { 611 .name = "musb-omap2430", 612 .pm = DEV_PM_OPS, 613 }, 614 }; 615 616 MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer"); 617 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 618 MODULE_LICENSE("GPL v2"); 619 620 static int __init omap2430_init(void) 621 { 622 return platform_driver_register(&omap2430_driver); 623 } 624 subsys_initcall(omap2430_init); 625 626 static void __exit omap2430_exit(void) 627 { 628 platform_driver_unregister(&omap2430_driver); 629 } 630 module_exit(omap2430_exit); 631 #endif 632