aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/am35x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/am35x.c')
-rw-r--r--drivers/usb/musb/am35x.c410
1 files changed, 270 insertions, 140 deletions
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index b0aabf3a606f..d5a3da37c90c 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -29,8 +29,9 @@
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/platform_device.h>
33#include <linux/dma-mapping.h>
32 34
33#include <plat/control.h>
34#include <plat/usb.h> 35#include <plat/usb.h>
35 36
36#include "musb_core.h" 37#include "musb_core.h"
@@ -80,51 +81,18 @@
80 81
81#define USB_MENTOR_CORE_OFFSET 0x400 82#define USB_MENTOR_CORE_OFFSET 0x400
82 83
83static inline void phy_on(void) 84struct am35x_glue {
84{ 85 struct device *dev;
85 unsigned long timeout = jiffies + msecs_to_jiffies(100); 86 struct platform_device *musb;
86 u32 devconf2; 87 struct clk *phy_clk;
87 88 struct clk *clk;
88 /* 89};
89 * Start the on-chip PHY and its PLL. 90#define glue_to_musb(g) platform_get_drvdata(g->musb)
90 */
91 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
92
93 devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
94 devconf2 |= CONF2_PHY_PLLON;
95
96 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
97
98 DBG(1, "Waiting for PHY clock good...\n");
99 while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
100 & CONF2_PHYCLKGD)) {
101 cpu_relax();
102
103 if (time_after(jiffies, timeout)) {
104 DBG(1, "musb PHY clock good timed out\n");
105 break;
106 }
107 }
108}
109
110static inline void phy_off(void)
111{
112 u32 devconf2;
113
114 /*
115 * Power down the on-chip PHY.
116 */
117 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
118
119 devconf2 &= ~CONF2_PHY_PLLON;
120 devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
121 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
122}
123 91
124/* 92/*
125 * musb_platform_enable - enable interrupts 93 * am35x_musb_enable - enable interrupts
126 */ 94 */
127void musb_platform_enable(struct musb *musb) 95static void am35x_musb_enable(struct musb *musb)
128{ 96{
129 void __iomem *reg_base = musb->ctrl_base; 97 void __iomem *reg_base = musb->ctrl_base;
130 u32 epmask; 98 u32 epmask;
@@ -143,9 +111,9 @@ void musb_platform_enable(struct musb *musb)
143} 111}
144 112
145/* 113/*
146 * musb_platform_disable - disable HDRC and flush interrupts 114 * am35x_musb_disable - disable HDRC and flush interrupts
147 */ 115 */
148void musb_platform_disable(struct musb *musb) 116static void am35x_musb_disable(struct musb *musb)
149{ 117{
150 void __iomem *reg_base = musb->ctrl_base; 118 void __iomem *reg_base = musb->ctrl_base;
151 119
@@ -162,7 +130,7 @@ void musb_platform_disable(struct musb *musb)
162#define portstate(stmt) 130#define portstate(stmt)
163#endif 131#endif
164 132
165static void am35x_set_vbus(struct musb *musb, int is_on) 133static void am35x_musb_set_vbus(struct musb *musb, int is_on)
166{ 134{
167 WARN_ON(is_on && is_peripheral_active(musb)); 135 WARN_ON(is_on && is_peripheral_active(musb));
168} 136}
@@ -221,7 +189,7 @@ static void otg_timer(unsigned long _musb)
221 spin_unlock_irqrestore(&musb->lock, flags); 189 spin_unlock_irqrestore(&musb->lock, flags);
222} 190}
223 191
224void musb_platform_try_idle(struct musb *musb, unsigned long timeout) 192static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
225{ 193{
226 static unsigned long last_timer; 194 static unsigned long last_timer;
227 195
@@ -251,13 +219,16 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
251 mod_timer(&otg_workaround, timeout); 219 mod_timer(&otg_workaround, timeout);
252} 220}
253 221
254static irqreturn_t am35x_interrupt(int irq, void *hci) 222static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
255{ 223{
256 struct musb *musb = hci; 224 struct musb *musb = hci;
257 void __iomem *reg_base = musb->ctrl_base; 225 void __iomem *reg_base = musb->ctrl_base;
226 struct device *dev = musb->controller;
227 struct musb_hdrc_platform_data *plat = dev->platform_data;
228 struct omap_musb_board_data *data = plat->board_data;
258 unsigned long flags; 229 unsigned long flags;
259 irqreturn_t ret = IRQ_NONE; 230 irqreturn_t ret = IRQ_NONE;
260 u32 epintr, usbintr, lvl_intr; 231 u32 epintr, usbintr;
261 232
262 spin_lock_irqsave(&musb->lock, flags); 233 spin_lock_irqsave(&musb->lock, flags);
263 234
@@ -346,9 +317,8 @@ eoi:
346 /* EOI needs to be written for the IRQ to be re-asserted. */ 317 /* EOI needs to be written for the IRQ to be re-asserted. */
347 if (ret == IRQ_HANDLED || epintr || usbintr) { 318 if (ret == IRQ_HANDLED || epintr || usbintr) {
348 /* clear level interrupt */ 319 /* clear level interrupt */
349 lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); 320 if (data->clear_irq)
350 lvl_intr |= AM35XX_USBOTGSS_INT_CLR; 321 data->clear_irq();
351 omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
352 /* write EOI */ 322 /* write EOI */
353 musb_writel(reg_base, USB_END_OF_INTR_REG, 0); 323 musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
354 } 324 }
@@ -362,137 +332,85 @@ eoi:
362 return ret; 332 return ret;
363} 333}
364 334
365int musb_platform_set_mode(struct musb *musb, u8 musb_mode) 335static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
366{ 336{
367 u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 337 struct device *dev = musb->controller;
338 struct musb_hdrc_platform_data *plat = dev->platform_data;
339 struct omap_musb_board_data *data = plat->board_data;
340 int retval = 0;
368 341
369 devconf2 &= ~CONF2_OTGMODE; 342 if (data->set_mode)
370 switch (musb_mode) { 343 data->set_mode(musb_mode);
371#ifdef CONFIG_USB_MUSB_HDRC_HCD 344 else
372 case MUSB_HOST: /* Force VBUS valid, ID = 0 */ 345 retval = -EIO;
373 devconf2 |= CONF2_FORCE_HOST;
374 break;
375#endif
376#ifdef CONFIG_USB_GADGET_MUSB_HDRC
377 case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
378 devconf2 |= CONF2_FORCE_DEVICE;
379 break;
380#endif
381#ifdef CONFIG_USB_MUSB_OTG
382 case MUSB_OTG: /* Don't override the VBUS/ID comparators */
383 devconf2 |= CONF2_NO_OVERRIDE;
384 break;
385#endif
386 default:
387 DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
388 }
389 346
390 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 347 return retval;
391 return 0;
392} 348}
393 349
394int __init musb_platform_init(struct musb *musb, void *board_data) 350static int am35x_musb_init(struct musb *musb)
395{ 351{
352 struct device *dev = musb->controller;
353 struct musb_hdrc_platform_data *plat = dev->platform_data;
354 struct omap_musb_board_data *data = plat->board_data;
396 void __iomem *reg_base = musb->ctrl_base; 355 void __iomem *reg_base = musb->ctrl_base;
397 u32 rev, lvl_intr, sw_reset; 356 u32 rev;
398 int status;
399 357
400 musb->mregs += USB_MENTOR_CORE_OFFSET; 358 musb->mregs += USB_MENTOR_CORE_OFFSET;
401 359
402 clk_enable(musb->clock);
403 DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock));
404
405 musb->phy_clock = clk_get(musb->controller, "fck");
406 if (IS_ERR(musb->phy_clock)) {
407 status = PTR_ERR(musb->phy_clock);
408 goto exit0;
409 }
410 clk_enable(musb->phy_clock);
411 DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock));
412
413 /* Returns zero if e.g. not clocked */ 360 /* Returns zero if e.g. not clocked */
414 rev = musb_readl(reg_base, USB_REVISION_REG); 361 rev = musb_readl(reg_base, USB_REVISION_REG);
415 if (!rev) { 362 if (!rev)
416 status = -ENODEV; 363 return -ENODEV;
417 goto exit1;
418 }
419 364
420 usb_nop_xceiv_register(); 365 usb_nop_xceiv_register();
421 musb->xceiv = otg_get_transceiver(); 366 musb->xceiv = otg_get_transceiver();
422 if (!musb->xceiv) { 367 if (!musb->xceiv)
423 status = -ENODEV; 368 return -ENODEV;
424 goto exit1;
425 }
426 369
427 if (is_host_enabled(musb)) 370 if (is_host_enabled(musb))
428 setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); 371 setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
429 372
430 musb->board_set_vbus = am35x_set_vbus; 373 /* Reset the musb */
431 374 if (data->reset)
432 /* Global reset */ 375 data->reset();
433 sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
434
435 sw_reset |= AM35XX_USBOTGSS_SW_RST;
436 omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
437
438 sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
439 omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
440 376
441 /* Reset the controller */ 377 /* Reset the controller */
442 musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); 378 musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
443 379
444 /* Start the on-chip PHY and its PLL. */ 380 /* Start the on-chip PHY and its PLL. */
445 phy_on(); 381 if (data->set_phy_power)
382 data->set_phy_power(1);
446 383
447 msleep(5); 384 msleep(5);
448 385
449 musb->isr = am35x_interrupt; 386 musb->isr = am35x_musb_interrupt;
450 387
451 /* clear level interrupt */ 388 /* clear level interrupt */
452 lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); 389 if (data->clear_irq)
453 lvl_intr |= AM35XX_USBOTGSS_INT_CLR; 390 data->clear_irq();
454 omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); 391
455 return 0; 392 return 0;
456exit1:
457 clk_disable(musb->phy_clock);
458 clk_put(musb->phy_clock);
459exit0:
460 clk_disable(musb->clock);
461 return status;
462} 393}
463 394
464int musb_platform_exit(struct musb *musb) 395static int am35x_musb_exit(struct musb *musb)
465{ 396{
397 struct device *dev = musb->controller;
398 struct musb_hdrc_platform_data *plat = dev->platform_data;
399 struct omap_musb_board_data *data = plat->board_data;
400
466 if (is_host_enabled(musb)) 401 if (is_host_enabled(musb))
467 del_timer_sync(&otg_workaround); 402 del_timer_sync(&otg_workaround);
468 403
469 phy_off(); 404 /* Shutdown the on-chip PHY and its PLL. */
405 if (data->set_phy_power)
406 data->set_phy_power(0);
470 407
471 otg_put_transceiver(musb->xceiv); 408 otg_put_transceiver(musb->xceiv);
472 usb_nop_xceiv_unregister(); 409 usb_nop_xceiv_unregister();
473 410
474 clk_disable(musb->clock);
475
476 clk_disable(musb->phy_clock);
477 clk_put(musb->phy_clock);
478
479 return 0; 411 return 0;
480} 412}
481 413
482#ifdef CONFIG_PM
483void musb_platform_save_context(struct musb *musb,
484 struct musb_context_registers *musb_context)
485{
486 phy_off();
487}
488
489void musb_platform_restore_context(struct musb *musb,
490 struct musb_context_registers *musb_context)
491{
492 phy_on();
493}
494#endif
495
496/* AM35x supports only 32bit read operation */ 414/* AM35x supports only 32bit read operation */
497void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) 415void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
498{ 416{
@@ -522,3 +440,215 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
522 memcpy(dst, &val, len); 440 memcpy(dst, &val, len);
523 } 441 }
524} 442}
443
444static const struct musb_platform_ops am35x_ops = {
445 .init = am35x_musb_init,
446 .exit = am35x_musb_exit,
447
448 .enable = am35x_musb_enable,
449 .disable = am35x_musb_disable,
450
451 .set_mode = am35x_musb_set_mode,
452 .try_idle = am35x_musb_try_idle,
453
454 .set_vbus = am35x_musb_set_vbus,
455};
456
457static u64 am35x_dmamask = DMA_BIT_MASK(32);
458
459static int __init am35x_probe(struct platform_device *pdev)
460{
461 struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
462 struct platform_device *musb;
463 struct am35x_glue *glue;
464
465 struct clk *phy_clk;
466 struct clk *clk;
467
468 int ret = -ENOMEM;
469
470 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
471 if (!glue) {
472 dev_err(&pdev->dev, "failed to allocate glue context\n");
473 goto err0;
474 }
475
476 musb = platform_device_alloc("musb-hdrc", -1);
477 if (!musb) {
478 dev_err(&pdev->dev, "failed to allocate musb device\n");
479 goto err1;
480 }
481
482 phy_clk = clk_get(&pdev->dev, "fck");
483 if (IS_ERR(phy_clk)) {
484 dev_err(&pdev->dev, "failed to get PHY clock\n");
485 ret = PTR_ERR(phy_clk);
486 goto err2;
487 }
488
489 clk = clk_get(&pdev->dev, "ick");
490 if (IS_ERR(clk)) {
491 dev_err(&pdev->dev, "failed to get clock\n");
492 ret = PTR_ERR(clk);
493 goto err3;
494 }
495
496 ret = clk_enable(phy_clk);
497 if (ret) {
498 dev_err(&pdev->dev, "failed to enable PHY clock\n");
499 goto err4;
500 }
501
502 ret = clk_enable(clk);
503 if (ret) {
504 dev_err(&pdev->dev, "failed to enable clock\n");
505 goto err5;
506 }
507
508 musb->dev.parent = &pdev->dev;
509 musb->dev.dma_mask = &am35x_dmamask;
510 musb->dev.coherent_dma_mask = am35x_dmamask;
511
512 glue->dev = &pdev->dev;
513 glue->musb = musb;
514 glue->phy_clk = phy_clk;
515 glue->clk = clk;
516
517 pdata->platform_ops = &am35x_ops;
518
519 platform_set_drvdata(pdev, glue);
520
521 ret = platform_device_add_resources(musb, pdev->resource,
522 pdev->num_resources);
523 if (ret) {
524 dev_err(&pdev->dev, "failed to add resources\n");
525 goto err6;
526 }
527
528 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
529 if (ret) {
530 dev_err(&pdev->dev, "failed to add platform_data\n");
531 goto err6;
532 }
533
534 ret = platform_device_add(musb);
535 if (ret) {
536 dev_err(&pdev->dev, "failed to register musb device\n");
537 goto err6;
538 }
539
540 return 0;
541
542err6:
543 clk_disable(clk);
544
545err5:
546 clk_disable(phy_clk);
547
548err4:
549 clk_put(clk);
550
551err3:
552 clk_put(phy_clk);
553
554err2:
555 platform_device_put(musb);
556
557err1:
558 kfree(glue);
559
560err0:
561 return ret;
562}
563
564static int __exit am35x_remove(struct platform_device *pdev)
565{
566 struct am35x_glue *glue = platform_get_drvdata(pdev);
567
568 platform_device_del(glue->musb);
569 platform_device_put(glue->musb);
570 clk_disable(glue->clk);
571 clk_disable(glue->phy_clk);
572 clk_put(glue->clk);
573 clk_put(glue->phy_clk);
574 kfree(glue);
575
576 return 0;
577}
578
579#ifdef CONFIG_PM
580static int am35x_suspend(struct device *dev)
581{
582 struct am35x_glue *glue = dev_get_drvdata(dev);
583 struct musb_hdrc_platform_data *plat = dev->platform_data;
584 struct omap_musb_board_data *data = plat->board_data;
585
586 /* Shutdown the on-chip PHY and its PLL. */
587 if (data->set_phy_power)
588 data->set_phy_power(0);
589
590 clk_disable(glue->phy_clk);
591 clk_disable(glue->clk);
592
593 return 0;
594}
595
596static int am35x_resume(struct device *dev)
597{
598 struct am35x_glue *glue = dev_get_drvdata(dev);
599 struct musb_hdrc_platform_data *plat = dev->platform_data;
600 struct omap_musb_board_data *data = plat->board_data;
601 int ret;
602
603 /* Start the on-chip PHY and its PLL. */
604 if (data->set_phy_power)
605 data->set_phy_power(1);
606
607 ret = clk_enable(glue->phy_clk);
608 if (ret) {
609 dev_err(dev, "failed to enable PHY clock\n");
610 return ret;
611 }
612
613 ret = clk_enable(glue->clk);
614 if (ret) {
615 dev_err(dev, "failed to enable clock\n");
616 return ret;
617 }
618
619 return 0;
620}
621
622static struct dev_pm_ops am35x_pm_ops = {
623 .suspend = am35x_suspend,
624 .resume = am35x_resume,
625};
626
627#define DEV_PM_OPS &am35x_pm_ops
628#else
629#define DEV_PM_OPS NULL
630#endif
631
632static struct platform_driver am35x_driver = {
633 .remove = __exit_p(am35x_remove),
634 .driver = {
635 .name = "musb-am35x",
636 .pm = DEV_PM_OPS,
637 },
638};
639
640MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
641MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
642MODULE_LICENSE("GPL v2");
643
644static int __init am35x_init(void)
645{
646 return platform_driver_probe(&am35x_driver, am35x_probe);
647}
648subsys_initcall(am35x_init);
649
650static void __exit am35x_exit(void)
651{
652 platform_driver_unregister(&am35x_driver);
653}
654module_exit(am35x_exit);