aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/da8xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/da8xx.c')
-rw-r--r--drivers/usb/musb/da8xx.c170
1 files changed, 153 insertions, 17 deletions
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 84427bebbf62..69a0da3c8f09 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -29,6 +29,8 @@
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 <mach/da8xx.h> 35#include <mach/da8xx.h>
34#include <mach/usb.h> 36#include <mach/usb.h>
@@ -78,6 +80,12 @@
78 80
79#define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) 81#define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG)
80 82
83struct da8xx_glue {
84 struct device *dev;
85 struct platform_device *musb;
86 struct clk *clk;
87};
88
81/* 89/*
82 * REVISIT (PM): we should be able to keep the PHY in low power mode most 90 * REVISIT (PM): we should be able to keep the PHY in low power mode most
83 * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 91 * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0
@@ -131,9 +139,9 @@ static inline void phy_off(void)
131 */ 139 */
132 140
133/** 141/**
134 * musb_platform_enable - enable interrupts 142 * da8xx_musb_enable - enable interrupts
135 */ 143 */
136void musb_platform_enable(struct musb *musb) 144static void da8xx_musb_enable(struct musb *musb)
137{ 145{
138 void __iomem *reg_base = musb->ctrl_base; 146 void __iomem *reg_base = musb->ctrl_base;
139 u32 mask; 147 u32 mask;
@@ -151,9 +159,9 @@ void musb_platform_enable(struct musb *musb)
151} 159}
152 160
153/** 161/**
154 * musb_platform_disable - disable HDRC and flush interrupts 162 * da8xx_musb_disable - disable HDRC and flush interrupts
155 */ 163 */
156void musb_platform_disable(struct musb *musb) 164static void da8xx_musb_disable(struct musb *musb)
157{ 165{
158 void __iomem *reg_base = musb->ctrl_base; 166 void __iomem *reg_base = musb->ctrl_base;
159 167
@@ -170,7 +178,7 @@ void musb_platform_disable(struct musb *musb)
170#define portstate(stmt) 178#define portstate(stmt)
171#endif 179#endif
172 180
173static void da8xx_set_vbus(struct musb *musb, int is_on) 181static void da8xx_musb_set_vbus(struct musb *musb, int is_on)
174{ 182{
175 WARN_ON(is_on && is_peripheral_active(musb)); 183 WARN_ON(is_on && is_peripheral_active(musb));
176} 184}
@@ -252,7 +260,7 @@ static void otg_timer(unsigned long _musb)
252 spin_unlock_irqrestore(&musb->lock, flags); 260 spin_unlock_irqrestore(&musb->lock, flags);
253} 261}
254 262
255void musb_platform_try_idle(struct musb *musb, unsigned long timeout) 263static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
256{ 264{
257 static unsigned long last_timer; 265 static unsigned long last_timer;
258 266
@@ -282,7 +290,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
282 mod_timer(&otg_workaround, timeout); 290 mod_timer(&otg_workaround, timeout);
283} 291}
284 292
285static irqreturn_t da8xx_interrupt(int irq, void *hci) 293static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
286{ 294{
287 struct musb *musb = hci; 295 struct musb *musb = hci;
288 void __iomem *reg_base = musb->ctrl_base; 296 void __iomem *reg_base = musb->ctrl_base;
@@ -380,7 +388,7 @@ static irqreturn_t da8xx_interrupt(int irq, void *hci)
380 return ret; 388 return ret;
381} 389}
382 390
383int musb_platform_set_mode(struct musb *musb, u8 musb_mode) 391static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode)
384{ 392{
385 u32 cfgchip2 = __raw_readl(CFGCHIP2); 393 u32 cfgchip2 = __raw_readl(CFGCHIP2);
386 394
@@ -409,15 +417,13 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
409 return 0; 417 return 0;
410} 418}
411 419
412int __init musb_platform_init(struct musb *musb, void *board_data) 420static int da8xx_musb_init(struct musb *musb)
413{ 421{
414 void __iomem *reg_base = musb->ctrl_base; 422 void __iomem *reg_base = musb->ctrl_base;
415 u32 rev; 423 u32 rev;
416 424
417 musb->mregs += DA8XX_MENTOR_CORE_OFFSET; 425 musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
418 426
419 clk_enable(musb->clock);
420
421 /* Returns zero if e.g. not clocked */ 427 /* Returns zero if e.g. not clocked */
422 rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); 428 rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
423 if (!rev) 429 if (!rev)
@@ -431,8 +437,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
431 if (is_host_enabled(musb)) 437 if (is_host_enabled(musb))
432 setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); 438 setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
433 439
434 musb->board_set_vbus = da8xx_set_vbus;
435
436 /* Reset the controller */ 440 /* Reset the controller */
437 musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); 441 musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
438 442
@@ -446,14 +450,13 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
446 rev, __raw_readl(CFGCHIP2), 450 rev, __raw_readl(CFGCHIP2),
447 musb_readb(reg_base, DA8XX_USB_CTRL_REG)); 451 musb_readb(reg_base, DA8XX_USB_CTRL_REG));
448 452
449 musb->isr = da8xx_interrupt; 453 musb->isr = da8xx_musb_interrupt;
450 return 0; 454 return 0;
451fail: 455fail:
452 clk_disable(musb->clock);
453 return -ENODEV; 456 return -ENODEV;
454} 457}
455 458
456int musb_platform_exit(struct musb *musb) 459static int da8xx_musb_exit(struct musb *musb)
457{ 460{
458 if (is_host_enabled(musb)) 461 if (is_host_enabled(musb))
459 del_timer_sync(&otg_workaround); 462 del_timer_sync(&otg_workaround);
@@ -463,7 +466,140 @@ int musb_platform_exit(struct musb *musb)
463 otg_put_transceiver(musb->xceiv); 466 otg_put_transceiver(musb->xceiv);
464 usb_nop_xceiv_unregister(); 467 usb_nop_xceiv_unregister();
465 468
466 clk_disable(musb->clock); 469 return 0;
470}
471
472static const struct musb_platform_ops da8xx_ops = {
473 .init = da8xx_musb_init,
474 .exit = da8xx_musb_exit,
475
476 .enable = da8xx_musb_enable,
477 .disable = da8xx_musb_disable,
478
479 .set_mode = da8xx_musb_set_mode,
480 .try_idle = da8xx_musb_try_idle,
481
482 .set_vbus = da8xx_musb_set_vbus,
483};
484
485static u64 da8xx_dmamask = DMA_BIT_MASK(32);
486
487static int __init da8xx_probe(struct platform_device *pdev)
488{
489 struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
490 struct platform_device *musb;
491 struct da8xx_glue *glue;
492
493 struct clk *clk;
494
495 int ret = -ENOMEM;
496
497 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
498 if (!glue) {
499 dev_err(&pdev->dev, "failed to allocate glue context\n");
500 goto err0;
501 }
502
503 musb = platform_device_alloc("musb-hdrc", -1);
504 if (!musb) {
505 dev_err(&pdev->dev, "failed to allocate musb device\n");
506 goto err1;
507 }
508
509 clk = clk_get(&pdev->dev, "usb20");
510 if (IS_ERR(clk)) {
511 dev_err(&pdev->dev, "failed to get clock\n");
512 ret = PTR_ERR(clk);
513 goto err2;
514 }
515
516 ret = clk_enable(clk);
517 if (ret) {
518 dev_err(&pdev->dev, "failed to enable clock\n");
519 goto err3;
520 }
521
522 musb->dev.parent = &pdev->dev;
523 musb->dev.dma_mask = &da8xx_dmamask;
524 musb->dev.coherent_dma_mask = da8xx_dmamask;
525
526 glue->dev = &pdev->dev;
527 glue->musb = musb;
528 glue->clk = clk;
529
530 pdata->platform_ops = &da8xx_ops;
531
532 platform_set_drvdata(pdev, glue);
533
534 ret = platform_device_add_resources(musb, pdev->resource,
535 pdev->num_resources);
536 if (ret) {
537 dev_err(&pdev->dev, "failed to add resources\n");
538 goto err4;
539 }
540
541 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
542 if (ret) {
543 dev_err(&pdev->dev, "failed to add platform_data\n");
544 goto err4;
545 }
546
547 ret = platform_device_add(musb);
548 if (ret) {
549 dev_err(&pdev->dev, "failed to register musb device\n");
550 goto err4;
551 }
552
553 return 0;
554
555err4:
556 clk_disable(clk);
557
558err3:
559 clk_put(clk);
560
561err2:
562 platform_device_put(musb);
563
564err1:
565 kfree(glue);
566
567err0:
568 return ret;
569}
570
571static int __exit da8xx_remove(struct platform_device *pdev)
572{
573 struct da8xx_glue *glue = platform_get_drvdata(pdev);
574
575 platform_device_del(glue->musb);
576 platform_device_put(glue->musb);
577 clk_disable(glue->clk);
578 clk_put(glue->clk);
579 kfree(glue);
467 580
468 return 0; 581 return 0;
469} 582}
583
584static struct platform_driver da8xx_driver = {
585 .remove = __exit_p(da8xx_remove),
586 .driver = {
587 .name = "musb-da8xx",
588 },
589};
590
591MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");
592MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");
593MODULE_LICENSE("GPL v2");
594
595static int __init da8xx_init(void)
596{
597 return platform_driver_probe(&da8xx_driver, da8xx_probe);
598}
599subsys_initcall(da8xx_init);
600
601static void __exit da8xx_exit(void)
602{
603 platform_driver_unregister(&da8xx_driver);
604}
605module_exit(da8xx_exit);