diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 13:05:06 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 13:05:06 -0500 |
commit | 36facadd9ea98f8415d0dbb63e0763b7ee9d3911 (patch) | |
tree | 99dea00b332ed852f2b0a4923b581dd723f03634 /drivers/usb/musb/davinci.c | |
parent | 2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff) | |
parent | 0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff) |
Merge branch 'usb-next' into musb-merge
* usb-next: (132 commits)
USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path
USB: uas: Ensure we only bind to a UAS interface
USB: uas: Rename sense pipe and sense urb to status pipe and status urb
USB: uas: Use kzalloc instead of kmalloc
USB: uas: Fix up the Sense IU
usb: musb: core: kill unneeded #include's
DA8xx: assign name to MUSB IRQ resource
usb: gadget: g_ncm added
usb: gadget: f_ncm.c added
usb: gadget: u_ether: prepare for NCM
usb: pch_udc: Fix setup transfers with data out
usb: pch_udc: Fix compile error, warnings and checkpatch warnings
usb: add ab8500 usb transceiver driver
USB: gadget: Implement runtime PM for MSM bus glue driver
USB: gadget: Implement runtime PM for ci13xxx gadget
USB: gadget: Add USB controller driver for MSM SoC
USB: gadget: Introduce ci13xxx_udc_driver struct
USB: gadget: Initialize ci13xxx gadget device's coherent DMA mask
USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc
USB: gadget: Separate out PCI bus code from ci13xxx_udc
...
Diffstat (limited to 'drivers/usb/musb/davinci.c')
-rw-r--r-- | drivers/usb/musb/davinci.c | 174 |
1 files changed, 154 insertions, 20 deletions
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 6e67629f50cc..e6de097fb7e8 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 | ||
@@ -259,7 +267,7 @@ static void otg_timer(unsigned long _musb) | |||
259 | spin_unlock_irqrestore(&musb->lock, flags); | 267 | spin_unlock_irqrestore(&musb->lock, flags); |
260 | } | 268 | } |
261 | 269 | ||
262 | static irqreturn_t davinci_interrupt(int irq, void *__hci) | 270 | static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) |
263 | { | 271 | { |
264 | unsigned long flags; | 272 | unsigned long flags; |
265 | irqreturn_t retval = IRQ_NONE; | 273 | irqreturn_t retval = IRQ_NONE; |
@@ -345,7 +353,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
345 | /* NOTE: this must complete poweron within 100 msec | 353 | /* NOTE: this must complete poweron within 100 msec |
346 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. | 354 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. |
347 | */ | 355 | */ |
348 | davinci_source_power(musb, drvvbus, 0); | 356 | davinci_musb_source_power(musb, drvvbus, 0); |
349 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", | 357 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", |
350 | drvvbus ? "on" : "off", | 358 | drvvbus ? "on" : "off", |
351 | otg_state_string(musb), | 359 | otg_state_string(musb), |
@@ -370,13 +378,13 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
370 | return retval; | 378 | return retval; |
371 | } | 379 | } |
372 | 380 | ||
373 | int musb_platform_set_mode(struct musb *musb, u8 mode) | 381 | static int davinci_musb_set_mode(struct musb *musb, u8 mode) |
374 | { | 382 | { |
375 | /* EVM can't do this (right?) */ | 383 | /* EVM can't do this (right?) */ |
376 | return -EIO; | 384 | return -EIO; |
377 | } | 385 | } |
378 | 386 | ||
379 | int __init musb_platform_init(struct musb *musb, void *board_data) | 387 | static int davinci_musb_init(struct musb *musb) |
380 | { | 388 | { |
381 | void __iomem *tibase = musb->ctrl_base; | 389 | void __iomem *tibase = musb->ctrl_base; |
382 | u32 revision; | 390 | u32 revision; |
@@ -388,8 +396,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
388 | 396 | ||
389 | musb->mregs += DAVINCI_BASE_OFFSET; | 397 | musb->mregs += DAVINCI_BASE_OFFSET; |
390 | 398 | ||
391 | clk_enable(musb->clock); | ||
392 | |||
393 | /* returns zero if e.g. not clocked */ | 399 | /* returns zero if e.g. not clocked */ |
394 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); | 400 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); |
395 | if (revision == 0) | 401 | if (revision == 0) |
@@ -398,8 +404,7 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
398 | if (is_host_enabled(musb)) | 404 | if (is_host_enabled(musb)) |
399 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | 405 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); |
400 | 406 | ||
401 | musb->board_set_vbus = davinci_set_vbus; | 407 | davinci_musb_source_power(musb, 0, 1); |
402 | davinci_source_power(musb, 0, 1); | ||
403 | 408 | ||
404 | /* dm355 EVM swaps D+/D- for signal integrity, and | 409 | /* dm355 EVM swaps D+/D- for signal integrity, and |
405 | * is clocked from the main 24 MHz crystal. | 410 | * is clocked from the main 24 MHz crystal. |
@@ -440,18 +445,16 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
440 | revision, __raw_readl(USB_PHY_CTRL), | 445 | revision, __raw_readl(USB_PHY_CTRL), |
441 | musb_readb(tibase, DAVINCI_USB_CTRL_REG)); | 446 | musb_readb(tibase, DAVINCI_USB_CTRL_REG)); |
442 | 447 | ||
443 | musb->isr = davinci_interrupt; | 448 | musb->isr = davinci_musb_interrupt; |
444 | return 0; | 449 | return 0; |
445 | 450 | ||
446 | fail: | 451 | fail: |
447 | clk_disable(musb->clock); | ||
448 | |||
449 | otg_put_transceiver(musb->xceiv); | 452 | otg_put_transceiver(musb->xceiv); |
450 | usb_nop_xceiv_unregister(); | 453 | usb_nop_xceiv_unregister(); |
451 | return -ENODEV; | 454 | return -ENODEV; |
452 | } | 455 | } |
453 | 456 | ||
454 | int musb_platform_exit(struct musb *musb) | 457 | static int davinci_musb_exit(struct musb *musb) |
455 | { | 458 | { |
456 | if (is_host_enabled(musb)) | 459 | if (is_host_enabled(musb)) |
457 | del_timer_sync(&otg_workaround); | 460 | del_timer_sync(&otg_workaround); |
@@ -465,7 +468,7 @@ int musb_platform_exit(struct musb *musb) | |||
465 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | 468 | __raw_writel(deepsleep, DM355_DEEPSLEEP); |
466 | } | 469 | } |
467 | 470 | ||
468 | davinci_source_power(musb, 0 /*off*/, 1); | 471 | davinci_musb_source_power(musb, 0 /*off*/, 1); |
469 | 472 | ||
470 | /* delay, to avoid problems with module reload */ | 473 | /* delay, to avoid problems with module reload */ |
471 | if (is_host_enabled(musb) && musb->xceiv->default_a) { | 474 | if (is_host_enabled(musb) && musb->xceiv->default_a) { |
@@ -495,10 +498,141 @@ int musb_platform_exit(struct musb *musb) | |||
495 | 498 | ||
496 | phy_off(); | 499 | phy_off(); |
497 | 500 | ||
498 | clk_disable(musb->clock); | ||
499 | |||
500 | otg_put_transceiver(musb->xceiv); | 501 | otg_put_transceiver(musb->xceiv); |
501 | usb_nop_xceiv_unregister(); | 502 | usb_nop_xceiv_unregister(); |
502 | 503 | ||
503 | return 0; | 504 | return 0; |
504 | } | 505 | } |
506 | |||
507 | static const struct musb_platform_ops davinci_ops = { | ||
508 | .init = davinci_musb_init, | ||
509 | .exit = davinci_musb_exit, | ||
510 | |||
511 | .enable = davinci_musb_enable, | ||
512 | .disable = davinci_musb_disable, | ||
513 | |||
514 | .set_mode = davinci_musb_set_mode, | ||
515 | |||
516 | .set_vbus = davinci_musb_set_vbus, | ||
517 | }; | ||
518 | |||
519 | static u64 davinci_dmamask = DMA_BIT_MASK(32); | ||
520 | |||
521 | static int __init davinci_probe(struct platform_device *pdev) | ||
522 | { | ||
523 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
524 | struct platform_device *musb; | ||
525 | struct davinci_glue *glue; | ||
526 | struct clk *clk; | ||
527 | |||
528 | int ret = -ENOMEM; | ||
529 | |||
530 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
531 | if (!glue) { | ||
532 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
533 | goto err0; | ||
534 | } | ||
535 | |||
536 | musb = platform_device_alloc("musb-hdrc", -1); | ||
537 | if (!musb) { | ||
538 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
539 | goto err1; | ||
540 | } | ||
541 | |||
542 | clk = clk_get(&pdev->dev, "usb"); | ||
543 | if (IS_ERR(clk)) { | ||
544 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
545 | ret = PTR_ERR(clk); | ||
546 | goto err2; | ||
547 | } | ||
548 | |||
549 | ret = clk_enable(clk); | ||
550 | if (ret) { | ||
551 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
552 | goto err3; | ||
553 | } | ||
554 | |||
555 | musb->dev.parent = &pdev->dev; | ||
556 | musb->dev.dma_mask = &davinci_dmamask; | ||
557 | musb->dev.coherent_dma_mask = davinci_dmamask; | ||
558 | |||
559 | glue->dev = &pdev->dev; | ||
560 | glue->musb = musb; | ||
561 | glue->clk = clk; | ||
562 | |||
563 | pdata->platform_ops = &davinci_ops; | ||
564 | |||
565 | platform_set_drvdata(pdev, glue); | ||
566 | |||
567 | ret = platform_device_add_resources(musb, pdev->resource, | ||
568 | pdev->num_resources); | ||
569 | if (ret) { | ||
570 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
571 | goto err4; | ||
572 | } | ||
573 | |||
574 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
575 | if (ret) { | ||
576 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
577 | goto err4; | ||
578 | } | ||
579 | |||
580 | ret = platform_device_add(musb); | ||
581 | if (ret) { | ||
582 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
583 | goto err4; | ||
584 | } | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | err4: | ||
589 | clk_disable(clk); | ||
590 | |||
591 | err3: | ||
592 | clk_put(clk); | ||
593 | |||
594 | err2: | ||
595 | platform_device_put(musb); | ||
596 | |||
597 | err1: | ||
598 | kfree(glue); | ||
599 | |||
600 | err0: | ||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | static int __exit davinci_remove(struct platform_device *pdev) | ||
605 | { | ||
606 | struct davinci_glue *glue = platform_get_drvdata(pdev); | ||
607 | |||
608 | platform_device_del(glue->musb); | ||
609 | platform_device_put(glue->musb); | ||
610 | clk_disable(glue->clk); | ||
611 | clk_put(glue->clk); | ||
612 | kfree(glue); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static struct platform_driver davinci_driver = { | ||
618 | .remove = __exit_p(davinci_remove), | ||
619 | .driver = { | ||
620 | .name = "musb-davinci", | ||
621 | }, | ||
622 | }; | ||
623 | |||
624 | MODULE_DESCRIPTION("DaVinci MUSB Glue Layer"); | ||
625 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | ||
626 | MODULE_LICENSE("GPL v2"); | ||
627 | |||
628 | static int __init davinci_init(void) | ||
629 | { | ||
630 | return platform_driver_probe(&davinci_driver, davinci_probe); | ||
631 | } | ||
632 | subsys_initcall(davinci_init); | ||
633 | |||
634 | static void __exit davinci_exit(void) | ||
635 | { | ||
636 | platform_driver_unregister(&davinci_driver); | ||
637 | } | ||
638 | module_exit(davinci_exit); | ||