diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/musb/davinci.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/musb/davinci.c')
-rw-r--r-- | drivers/usb/musb/davinci.c | 189 |
1 files changed, 163 insertions, 26 deletions
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 57624361c1de..2a2adf6492cd 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/dma-mapping.h> | ||
33 | 35 | ||
34 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
35 | #include <mach/memory.h> | 37 | #include <mach/memory.h> |
@@ -51,6 +53,12 @@ | |||
51 | #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) | 53 | #define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) |
52 | #define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) | 54 | #define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) |
53 | 55 | ||
56 | struct davinci_glue { | ||
57 | struct device *dev; | ||
58 | struct platform_device *musb; | ||
59 | struct clk *clk; | ||
60 | }; | ||
61 | |||
54 | /* REVISIT (PM) we should be able to keep the PHY in low power mode most | 62 | /* REVISIT (PM) we should be able to keep the PHY in low power mode most |
55 | * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 | 63 | * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 |
56 | * and, when in host mode, autosuspending idle root ports... PHYPLLON | 64 | * and, when in host mode, autosuspending idle root ports... PHYPLLON |
@@ -83,7 +91,7 @@ static inline void phy_off(void) | |||
83 | 91 | ||
84 | static int dma_off = 1; | 92 | static int dma_off = 1; |
85 | 93 | ||
86 | void musb_platform_enable(struct musb *musb) | 94 | static void davinci_musb_enable(struct musb *musb) |
87 | { | 95 | { |
88 | u32 tmp, old, val; | 96 | u32 tmp, old, val; |
89 | 97 | ||
@@ -116,7 +124,7 @@ void musb_platform_enable(struct musb *musb) | |||
116 | /* | 124 | /* |
117 | * Disable the HDRC and flush interrupts | 125 | * Disable the HDRC and flush interrupts |
118 | */ | 126 | */ |
119 | void musb_platform_disable(struct musb *musb) | 127 | static void davinci_musb_disable(struct musb *musb) |
120 | { | 128 | { |
121 | /* because we don't set CTRLR.UINT, "important" to: | 129 | /* because we don't set CTRLR.UINT, "important" to: |
122 | * - not read/write INTRUSB/INTRUSBE | 130 | * - not read/write INTRUSB/INTRUSBE |
@@ -167,7 +175,7 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) | |||
167 | 175 | ||
168 | #endif /* EVM */ | 176 | #endif /* EVM */ |
169 | 177 | ||
170 | static void davinci_source_power(struct musb *musb, int is_on, int immediate) | 178 | static void davinci_musb_source_power(struct musb *musb, int is_on, int immediate) |
171 | { | 179 | { |
172 | #ifdef CONFIG_MACH_DAVINCI_EVM | 180 | #ifdef CONFIG_MACH_DAVINCI_EVM |
173 | if (is_on) | 181 | if (is_on) |
@@ -190,10 +198,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) | |||
190 | #endif | 198 | #endif |
191 | } | 199 | } |
192 | 200 | ||
193 | static void davinci_set_vbus(struct musb *musb, int is_on) | 201 | static void davinci_musb_set_vbus(struct musb *musb, int is_on) |
194 | { | 202 | { |
195 | WARN_ON(is_on && is_peripheral_active(musb)); | 203 | WARN_ON(is_on && is_peripheral_active(musb)); |
196 | davinci_source_power(musb, is_on, 0); | 204 | davinci_musb_source_power(musb, is_on, 0); |
197 | } | 205 | } |
198 | 206 | ||
199 | 207 | ||
@@ -212,7 +220,8 @@ static void otg_timer(unsigned long _musb) | |||
212 | * status change events (from the transceiver) otherwise. | 220 | * status change events (from the transceiver) otherwise. |
213 | */ | 221 | */ |
214 | devctl = musb_readb(mregs, MUSB_DEVCTL); | 222 | devctl = musb_readb(mregs, MUSB_DEVCTL); |
215 | DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); | 223 | dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl, |
224 | otg_state_string(musb->xceiv->state)); | ||
216 | 225 | ||
217 | spin_lock_irqsave(&musb->lock, flags); | 226 | spin_lock_irqsave(&musb->lock, flags); |
218 | switch (musb->xceiv->state) { | 227 | switch (musb->xceiv->state) { |
@@ -259,7 +268,7 @@ static void otg_timer(unsigned long _musb) | |||
259 | spin_unlock_irqrestore(&musb->lock, flags); | 268 | spin_unlock_irqrestore(&musb->lock, flags); |
260 | } | 269 | } |
261 | 270 | ||
262 | static irqreturn_t davinci_interrupt(int irq, void *__hci) | 271 | static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) |
263 | { | 272 | { |
264 | unsigned long flags; | 273 | unsigned long flags; |
265 | irqreturn_t retval = IRQ_NONE; | 274 | irqreturn_t retval = IRQ_NONE; |
@@ -289,7 +298,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
289 | /* ack and handle non-CPPI interrupts */ | 298 | /* ack and handle non-CPPI interrupts */ |
290 | tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); | 299 | tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); |
291 | musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp); | 300 | musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp); |
292 | DBG(4, "IRQ %08x\n", tmp); | 301 | dev_dbg(musb->controller, "IRQ %08x\n", tmp); |
293 | 302 | ||
294 | musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK) | 303 | musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK) |
295 | >> DAVINCI_USB_RXINT_SHIFT; | 304 | >> DAVINCI_USB_RXINT_SHIFT; |
@@ -345,10 +354,10 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
345 | /* NOTE: this must complete poweron within 100 msec | 354 | /* NOTE: this must complete poweron within 100 msec |
346 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. | 355 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. |
347 | */ | 356 | */ |
348 | davinci_source_power(musb, drvvbus, 0); | 357 | davinci_musb_source_power(musb, drvvbus, 0); |
349 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", | 358 | dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", |
350 | drvvbus ? "on" : "off", | 359 | drvvbus ? "on" : "off", |
351 | otg_state_string(musb), | 360 | otg_state_string(musb->xceiv->state), |
352 | err ? " ERROR" : "", | 361 | err ? " ERROR" : "", |
353 | devctl); | 362 | devctl); |
354 | retval = IRQ_HANDLED; | 363 | retval = IRQ_HANDLED; |
@@ -370,13 +379,13 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
370 | return retval; | 379 | return retval; |
371 | } | 380 | } |
372 | 381 | ||
373 | int musb_platform_set_mode(struct musb *musb, u8 mode) | 382 | static int davinci_musb_set_mode(struct musb *musb, u8 mode) |
374 | { | 383 | { |
375 | /* EVM can't do this (right?) */ | 384 | /* EVM can't do this (right?) */ |
376 | return -EIO; | 385 | return -EIO; |
377 | } | 386 | } |
378 | 387 | ||
379 | int __init musb_platform_init(struct musb *musb, void *board_data) | 388 | static int davinci_musb_init(struct musb *musb) |
380 | { | 389 | { |
381 | void __iomem *tibase = musb->ctrl_base; | 390 | void __iomem *tibase = musb->ctrl_base; |
382 | u32 revision; | 391 | u32 revision; |
@@ -388,8 +397,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
388 | 397 | ||
389 | musb->mregs += DAVINCI_BASE_OFFSET; | 398 | musb->mregs += DAVINCI_BASE_OFFSET; |
390 | 399 | ||
391 | clk_enable(musb->clock); | ||
392 | |||
393 | /* returns zero if e.g. not clocked */ | 400 | /* returns zero if e.g. not clocked */ |
394 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); | 401 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); |
395 | if (revision == 0) | 402 | if (revision == 0) |
@@ -398,8 +405,7 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
398 | if (is_host_enabled(musb)) | 405 | if (is_host_enabled(musb)) |
399 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | 406 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); |
400 | 407 | ||
401 | musb->board_set_vbus = davinci_set_vbus; | 408 | davinci_musb_source_power(musb, 0, 1); |
402 | davinci_source_power(musb, 0, 1); | ||
403 | 409 | ||
404 | /* dm355 EVM swaps D+/D- for signal integrity, and | 410 | /* dm355 EVM swaps D+/D- for signal integrity, and |
405 | * is clocked from the main 24 MHz crystal. | 411 | * is clocked from the main 24 MHz crystal. |
@@ -440,17 +446,16 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
440 | revision, __raw_readl(USB_PHY_CTRL), | 446 | revision, __raw_readl(USB_PHY_CTRL), |
441 | musb_readb(tibase, DAVINCI_USB_CTRL_REG)); | 447 | musb_readb(tibase, DAVINCI_USB_CTRL_REG)); |
442 | 448 | ||
443 | musb->isr = davinci_interrupt; | 449 | musb->isr = davinci_musb_interrupt; |
444 | return 0; | 450 | return 0; |
445 | 451 | ||
446 | fail: | 452 | fail: |
447 | clk_disable(musb->clock); | 453 | otg_put_transceiver(musb->xceiv); |
448 | |||
449 | usb_nop_xceiv_unregister(); | 454 | usb_nop_xceiv_unregister(); |
450 | return -ENODEV; | 455 | return -ENODEV; |
451 | } | 456 | } |
452 | 457 | ||
453 | int musb_platform_exit(struct musb *musb) | 458 | static int davinci_musb_exit(struct musb *musb) |
454 | { | 459 | { |
455 | if (is_host_enabled(musb)) | 460 | if (is_host_enabled(musb)) |
456 | del_timer_sync(&otg_workaround); | 461 | del_timer_sync(&otg_workaround); |
@@ -464,7 +469,7 @@ int musb_platform_exit(struct musb *musb) | |||
464 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | 469 | __raw_writel(deepsleep, DM355_DEEPSLEEP); |
465 | } | 470 | } |
466 | 471 | ||
467 | davinci_source_power(musb, 0 /*off*/, 1); | 472 | davinci_musb_source_power(musb, 0 /*off*/, 1); |
468 | 473 | ||
469 | /* delay, to avoid problems with module reload */ | 474 | /* delay, to avoid problems with module reload */ |
470 | if (is_host_enabled(musb) && musb->xceiv->default_a) { | 475 | if (is_host_enabled(musb) && musb->xceiv->default_a) { |
@@ -480,7 +485,7 @@ int musb_platform_exit(struct musb *musb) | |||
480 | break; | 485 | break; |
481 | if ((devctl & MUSB_DEVCTL_VBUS) != warn) { | 486 | if ((devctl & MUSB_DEVCTL_VBUS) != warn) { |
482 | warn = devctl & MUSB_DEVCTL_VBUS; | 487 | warn = devctl & MUSB_DEVCTL_VBUS; |
483 | DBG(1, "VBUS %d\n", | 488 | dev_dbg(musb->controller, "VBUS %d\n", |
484 | warn >> MUSB_DEVCTL_VBUS_SHIFT); | 489 | warn >> MUSB_DEVCTL_VBUS_SHIFT); |
485 | } | 490 | } |
486 | msleep(1000); | 491 | msleep(1000); |
@@ -489,14 +494,146 @@ int musb_platform_exit(struct musb *musb) | |||
489 | 494 | ||
490 | /* in OTG mode, another host might be connected */ | 495 | /* in OTG mode, another host might be connected */ |
491 | if (devctl & MUSB_DEVCTL_VBUS) | 496 | if (devctl & MUSB_DEVCTL_VBUS) |
492 | DBG(1, "VBUS off timeout (devctl %02x)\n", devctl); | 497 | dev_dbg(musb->controller, "VBUS off timeout (devctl %02x)\n", devctl); |
493 | } | 498 | } |
494 | 499 | ||
495 | phy_off(); | 500 | phy_off(); |
496 | 501 | ||
497 | clk_disable(musb->clock); | 502 | otg_put_transceiver(musb->xceiv); |
498 | |||
499 | usb_nop_xceiv_unregister(); | 503 | usb_nop_xceiv_unregister(); |
500 | 504 | ||
501 | return 0; | 505 | return 0; |
502 | } | 506 | } |
507 | |||
508 | static const struct musb_platform_ops davinci_ops = { | ||
509 | .init = davinci_musb_init, | ||
510 | .exit = davinci_musb_exit, | ||
511 | |||
512 | .enable = davinci_musb_enable, | ||
513 | .disable = davinci_musb_disable, | ||
514 | |||
515 | .set_mode = davinci_musb_set_mode, | ||
516 | |||
517 | .set_vbus = davinci_musb_set_vbus, | ||
518 | }; | ||
519 | |||
520 | static u64 davinci_dmamask = DMA_BIT_MASK(32); | ||
521 | |||
522 | static int __init davinci_probe(struct platform_device *pdev) | ||
523 | { | ||
524 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
525 | struct platform_device *musb; | ||
526 | struct davinci_glue *glue; | ||
527 | struct clk *clk; | ||
528 | |||
529 | int ret = -ENOMEM; | ||
530 | |||
531 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
532 | if (!glue) { | ||
533 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
534 | goto err0; | ||
535 | } | ||
536 | |||
537 | musb = platform_device_alloc("musb-hdrc", -1); | ||
538 | if (!musb) { | ||
539 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
540 | goto err1; | ||
541 | } | ||
542 | |||
543 | clk = clk_get(&pdev->dev, "usb"); | ||
544 | if (IS_ERR(clk)) { | ||
545 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
546 | ret = PTR_ERR(clk); | ||
547 | goto err2; | ||
548 | } | ||
549 | |||
550 | ret = clk_enable(clk); | ||
551 | if (ret) { | ||
552 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
553 | goto err3; | ||
554 | } | ||
555 | |||
556 | musb->dev.parent = &pdev->dev; | ||
557 | musb->dev.dma_mask = &davinci_dmamask; | ||
558 | musb->dev.coherent_dma_mask = davinci_dmamask; | ||
559 | |||
560 | glue->dev = &pdev->dev; | ||
561 | glue->musb = musb; | ||
562 | glue->clk = clk; | ||
563 | |||
564 | pdata->platform_ops = &davinci_ops; | ||
565 | |||
566 | platform_set_drvdata(pdev, glue); | ||
567 | |||
568 | ret = platform_device_add_resources(musb, pdev->resource, | ||
569 | pdev->num_resources); | ||
570 | if (ret) { | ||
571 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
572 | goto err4; | ||
573 | } | ||
574 | |||
575 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
576 | if (ret) { | ||
577 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
578 | goto err4; | ||
579 | } | ||
580 | |||
581 | ret = platform_device_add(musb); | ||
582 | if (ret) { | ||
583 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
584 | goto err4; | ||
585 | } | ||
586 | |||
587 | return 0; | ||
588 | |||
589 | err4: | ||
590 | clk_disable(clk); | ||
591 | |||
592 | err3: | ||
593 | clk_put(clk); | ||
594 | |||
595 | err2: | ||
596 | platform_device_put(musb); | ||
597 | |||
598 | err1: | ||
599 | kfree(glue); | ||
600 | |||
601 | err0: | ||
602 | return ret; | ||
603 | } | ||
604 | |||
605 | static int __exit davinci_remove(struct platform_device *pdev) | ||
606 | { | ||
607 | struct davinci_glue *glue = platform_get_drvdata(pdev); | ||
608 | |||
609 | platform_device_del(glue->musb); | ||
610 | platform_device_put(glue->musb); | ||
611 | clk_disable(glue->clk); | ||
612 | clk_put(glue->clk); | ||
613 | kfree(glue); | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static struct platform_driver davinci_driver = { | ||
619 | .remove = __exit_p(davinci_remove), | ||
620 | .driver = { | ||
621 | .name = "musb-davinci", | ||
622 | }, | ||
623 | }; | ||
624 | |||
625 | MODULE_DESCRIPTION("DaVinci MUSB Glue Layer"); | ||
626 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | ||
627 | MODULE_LICENSE("GPL v2"); | ||
628 | |||
629 | static int __init davinci_init(void) | ||
630 | { | ||
631 | return platform_driver_probe(&davinci_driver, davinci_probe); | ||
632 | } | ||
633 | subsys_initcall(davinci_init); | ||
634 | |||
635 | static void __exit davinci_exit(void) | ||
636 | { | ||
637 | platform_driver_unregister(&davinci_driver); | ||
638 | } | ||
639 | module_exit(davinci_exit); | ||