diff options
Diffstat (limited to 'drivers/usb/musb/musb_dsps.c')
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 141 |
1 files changed, 83 insertions, 58 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index ff5f112053d2..9a975aa0dee2 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -124,8 +124,44 @@ struct dsps_glue { | |||
124 | const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ | 124 | const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ |
125 | struct timer_list timer[2]; /* otg_workaround timer */ | 125 | struct timer_list timer[2]; /* otg_workaround timer */ |
126 | unsigned long last_timer[2]; /* last timer data for each instance */ | 126 | unsigned long last_timer[2]; /* last timer data for each instance */ |
127 | u32 __iomem *usb_ctrl[2]; | ||
127 | }; | 128 | }; |
128 | 129 | ||
130 | #define DSPS_AM33XX_CONTROL_MODULE_PHYS_0 0x44e10620 | ||
131 | #define DSPS_AM33XX_CONTROL_MODULE_PHYS_1 0x44e10628 | ||
132 | |||
133 | static const resource_size_t dsps_control_module_phys[] = { | ||
134 | DSPS_AM33XX_CONTROL_MODULE_PHYS_0, | ||
135 | DSPS_AM33XX_CONTROL_MODULE_PHYS_1, | ||
136 | }; | ||
137 | |||
138 | /** | ||
139 | * musb_dsps_phy_control - phy on/off | ||
140 | * @glue: struct dsps_glue * | ||
141 | * @id: musb instance | ||
142 | * @on: flag for phy to be switched on or off | ||
143 | * | ||
144 | * This is to enable the PHY using usb_ctrl register in system control | ||
145 | * module space. | ||
146 | * | ||
147 | * XXX: This function will be removed once we have a seperate driver for | ||
148 | * control module | ||
149 | */ | ||
150 | static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on) | ||
151 | { | ||
152 | u32 usbphycfg; | ||
153 | |||
154 | usbphycfg = readl(glue->usb_ctrl[id]); | ||
155 | |||
156 | if (on) { | ||
157 | usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN); | ||
158 | usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN; | ||
159 | } else { | ||
160 | usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; | ||
161 | } | ||
162 | |||
163 | writel(usbphycfg, glue->usb_ctrl[id]); | ||
164 | } | ||
129 | /** | 165 | /** |
130 | * dsps_musb_enable - enable interrupts | 166 | * dsps_musb_enable - enable interrupts |
131 | */ | 167 | */ |
@@ -296,7 +332,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
296 | * Also, DRVVBUS pulses for SRP (but not at 5V) ... | 332 | * Also, DRVVBUS pulses for SRP (but not at 5V) ... |
297 | */ | 333 | */ |
298 | if (usbintr & MUSB_INTR_BABBLE) | 334 | if (usbintr & MUSB_INTR_BABBLE) |
299 | pr_info("CAUTION: musb: Babble Interrupt Occured\n"); | 335 | pr_info("CAUTION: musb: Babble Interrupt Occurred\n"); |
300 | 336 | ||
301 | if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { | 337 | if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { |
302 | int drvvbus = dsps_readl(reg_base, wrp->status); | 338 | int drvvbus = dsps_readl(reg_base, wrp->status); |
@@ -365,11 +401,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
365 | static int dsps_musb_init(struct musb *musb) | 401 | static int dsps_musb_init(struct musb *musb) |
366 | { | 402 | { |
367 | struct device *dev = musb->controller; | 403 | struct device *dev = musb->controller; |
368 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
369 | struct platform_device *pdev = to_platform_device(dev); | 404 | struct platform_device *pdev = to_platform_device(dev); |
370 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 405 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
371 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 406 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
372 | struct omap_musb_board_data *data = plat->board_data; | ||
373 | void __iomem *reg_base = musb->ctrl_base; | 407 | void __iomem *reg_base = musb->ctrl_base; |
374 | u32 rev, val; | 408 | u32 rev, val; |
375 | int status; | 409 | int status; |
@@ -377,7 +411,8 @@ static int dsps_musb_init(struct musb *musb) | |||
377 | /* mentor core register starts at offset of 0x400 from musb base */ | 411 | /* mentor core register starts at offset of 0x400 from musb base */ |
378 | musb->mregs += wrp->musb_core_offset; | 412 | musb->mregs += wrp->musb_core_offset; |
379 | 413 | ||
380 | /* Get the NOP PHY */ | 414 | /* NOP driver needs change if supporting dual instance */ |
415 | usb_nop_xceiv_register(); | ||
381 | musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); | 416 | musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); |
382 | if (IS_ERR_OR_NULL(musb->xceiv)) | 417 | if (IS_ERR_OR_NULL(musb->xceiv)) |
383 | return -ENODEV; | 418 | return -ENODEV; |
@@ -395,8 +430,7 @@ static int dsps_musb_init(struct musb *musb) | |||
395 | dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); | 430 | dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); |
396 | 431 | ||
397 | /* Start the on-chip PHY and its PLL. */ | 432 | /* Start the on-chip PHY and its PLL. */ |
398 | if (data->set_phy_power) | 433 | musb_dsps_phy_control(glue, pdev->id, 1); |
399 | data->set_phy_power(1); | ||
400 | 434 | ||
401 | musb->isr = dsps_interrupt; | 435 | musb->isr = dsps_interrupt; |
402 | 436 | ||
@@ -418,16 +452,13 @@ err0: | |||
418 | static int dsps_musb_exit(struct musb *musb) | 452 | static int dsps_musb_exit(struct musb *musb) |
419 | { | 453 | { |
420 | struct device *dev = musb->controller; | 454 | struct device *dev = musb->controller; |
421 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
422 | struct omap_musb_board_data *data = plat->board_data; | ||
423 | struct platform_device *pdev = to_platform_device(dev); | 455 | struct platform_device *pdev = to_platform_device(dev); |
424 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 456 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
425 | 457 | ||
426 | del_timer_sync(&glue->timer[pdev->id]); | 458 | del_timer_sync(&glue->timer[pdev->id]); |
427 | 459 | ||
428 | /* Shutdown the on-chip PHY and its PLL. */ | 460 | /* Shutdown the on-chip PHY and its PLL. */ |
429 | if (data->set_phy_power) | 461 | musb_dsps_phy_control(glue, pdev->id, 0); |
430 | data->set_phy_power(0); | ||
431 | 462 | ||
432 | /* NOP driver needs change if supporting dual instance */ | 463 | /* NOP driver needs change if supporting dual instance */ |
433 | usb_put_phy(musb->xceiv); | 464 | usb_put_phy(musb->xceiv); |
@@ -448,7 +479,7 @@ static struct musb_platform_ops dsps_ops = { | |||
448 | 479 | ||
449 | static u64 musb_dmamask = DMA_BIT_MASK(32); | 480 | static u64 musb_dmamask = DMA_BIT_MASK(32); |
450 | 481 | ||
451 | static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) | 482 | static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) |
452 | { | 483 | { |
453 | struct device *dev = glue->dev; | 484 | struct device *dev = glue->dev; |
454 | struct platform_device *pdev = to_platform_device(dev); | 485 | struct platform_device *pdev = to_platform_device(dev); |
@@ -459,24 +490,33 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) | |||
459 | struct resource *res; | 490 | struct resource *res; |
460 | struct resource resources[2]; | 491 | struct resource resources[2]; |
461 | char res_name[11]; | 492 | char res_name[11]; |
462 | int ret, musbid; | 493 | int ret; |
463 | 494 | ||
464 | /* get memory resource */ | 495 | resources[0].start = dsps_control_module_phys[id]; |
465 | snprintf(res_name, sizeof(res_name), "musb%d", id); | 496 | resources[0].end = resources[0].start + SZ_4 - 1; |
466 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); | 497 | resources[0].flags = IORESOURCE_MEM; |
498 | |||
499 | glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources); | ||
500 | if (glue->usb_ctrl[id] == NULL) { | ||
501 | dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id); | ||
502 | ret = -ENODEV; | ||
503 | goto err0; | ||
504 | } | ||
505 | |||
506 | /* first resource is for usbss, so start index from 1 */ | ||
507 | res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1); | ||
467 | if (!res) { | 508 | if (!res) { |
468 | dev_err(dev, "%s get mem resource failed\n", res_name); | 509 | dev_err(dev, "failed to get memory for instance %d\n", id); |
469 | ret = -ENODEV; | 510 | ret = -ENODEV; |
470 | goto err0; | 511 | goto err0; |
471 | } | 512 | } |
472 | res->parent = NULL; | 513 | res->parent = NULL; |
473 | resources[0] = *res; | 514 | resources[0] = *res; |
474 | 515 | ||
475 | /* get irq resource */ | 516 | /* first resource is for usbss, so start index from 1 */ |
476 | snprintf(res_name, sizeof(res_name), "musb%d-irq", id); | 517 | res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1); |
477 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); | ||
478 | if (!res) { | 518 | if (!res) { |
479 | dev_err(dev, "%s get irq resource failed\n", res_name); | 519 | dev_err(dev, "failed to get irq for instance %d\n", id); |
480 | ret = -ENODEV; | 520 | ret = -ENODEV; |
481 | goto err0; | 521 | goto err0; |
482 | } | 522 | } |
@@ -484,22 +524,14 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) | |||
484 | resources[1] = *res; | 524 | resources[1] = *res; |
485 | resources[1].name = "mc"; | 525 | resources[1].name = "mc"; |
486 | 526 | ||
487 | /* get the musb id */ | ||
488 | musbid = musb_get_id(dev, GFP_KERNEL); | ||
489 | if (musbid < 0) { | ||
490 | dev_err(dev, "failed to allocate musb id\n"); | ||
491 | ret = -ENOMEM; | ||
492 | goto err0; | ||
493 | } | ||
494 | /* allocate the child platform device */ | 527 | /* allocate the child platform device */ |
495 | musb = platform_device_alloc("musb-hdrc", musbid); | 528 | musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); |
496 | if (!musb) { | 529 | if (!musb) { |
497 | dev_err(dev, "failed to allocate musb device\n"); | 530 | dev_err(dev, "failed to allocate musb device\n"); |
498 | ret = -ENOMEM; | 531 | ret = -ENOMEM; |
499 | goto err1; | 532 | goto err0; |
500 | } | 533 | } |
501 | 534 | ||
502 | musb->id = musbid; | ||
503 | musb->dev.parent = dev; | 535 | musb->dev.parent = dev; |
504 | musb->dev.dma_mask = &musb_dmamask; | 536 | musb->dev.dma_mask = &musb_dmamask; |
505 | musb->dev.coherent_dma_mask = musb_dmamask; | 537 | musb->dev.coherent_dma_mask = musb_dmamask; |
@@ -556,20 +588,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) | |||
556 | 588 | ||
557 | err2: | 589 | err2: |
558 | platform_device_put(musb); | 590 | platform_device_put(musb); |
559 | err1: | ||
560 | musb_put_id(dev, musbid); | ||
561 | err0: | 591 | err0: |
562 | return ret; | 592 | return ret; |
563 | } | 593 | } |
564 | 594 | ||
565 | static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id) | 595 | static int dsps_probe(struct platform_device *pdev) |
566 | { | ||
567 | musb_put_id(glue->dev, glue->musb[id]->id); | ||
568 | platform_device_del(glue->musb[id]); | ||
569 | platform_device_put(glue->musb[id]); | ||
570 | } | ||
571 | |||
572 | static int __devinit dsps_probe(struct platform_device *pdev) | ||
573 | { | 596 | { |
574 | struct device_node *np = pdev->dev.of_node; | 597 | struct device_node *np = pdev->dev.of_node; |
575 | const struct of_device_id *match; | 598 | const struct of_device_id *match; |
@@ -628,7 +651,7 @@ static int __devinit dsps_probe(struct platform_device *pdev) | |||
628 | dev_err(&pdev->dev, "failed to create child pdev\n"); | 651 | dev_err(&pdev->dev, "failed to create child pdev\n"); |
629 | /* release resources of previously created instances */ | 652 | /* release resources of previously created instances */ |
630 | for (i--; i >= 0 ; i--) | 653 | for (i--; i >= 0 ; i--) |
631 | dsps_delete_musb_pdev(glue, i); | 654 | platform_device_unregister(glue->musb[i]); |
632 | goto err3; | 655 | goto err3; |
633 | } | 656 | } |
634 | } | 657 | } |
@@ -645,7 +668,7 @@ err1: | |||
645 | err0: | 668 | err0: |
646 | return ret; | 669 | return ret; |
647 | } | 670 | } |
648 | static int __devexit dsps_remove(struct platform_device *pdev) | 671 | static int dsps_remove(struct platform_device *pdev) |
649 | { | 672 | { |
650 | struct dsps_glue *glue = platform_get_drvdata(pdev); | 673 | struct dsps_glue *glue = platform_get_drvdata(pdev); |
651 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 674 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
@@ -653,7 +676,7 @@ static int __devexit dsps_remove(struct platform_device *pdev) | |||
653 | 676 | ||
654 | /* delete the child platform device */ | 677 | /* delete the child platform device */ |
655 | for (i = 0; i < wrp->instances ; i++) | 678 | for (i = 0; i < wrp->instances ; i++) |
656 | dsps_delete_musb_pdev(glue, i); | 679 | platform_device_unregister(glue->musb[i]); |
657 | 680 | ||
658 | /* disable usbss clocks */ | 681 | /* disable usbss clocks */ |
659 | pm_runtime_put(&pdev->dev); | 682 | pm_runtime_put(&pdev->dev); |
@@ -666,24 +689,26 @@ static int __devexit dsps_remove(struct platform_device *pdev) | |||
666 | #ifdef CONFIG_PM_SLEEP | 689 | #ifdef CONFIG_PM_SLEEP |
667 | static int dsps_suspend(struct device *dev) | 690 | static int dsps_suspend(struct device *dev) |
668 | { | 691 | { |
669 | struct musb_hdrc_platform_data *plat = dev->platform_data; | 692 | struct platform_device *pdev = to_platform_device(dev->parent); |
670 | struct omap_musb_board_data *data = plat->board_data; | 693 | struct dsps_glue *glue = platform_get_drvdata(pdev); |
694 | const struct dsps_musb_wrapper *wrp = glue->wrp; | ||
695 | int i; | ||
671 | 696 | ||
672 | /* Shutdown the on-chip PHY and its PLL. */ | 697 | for (i = 0; i < wrp->instances; i++) |
673 | if (data->set_phy_power) | 698 | musb_dsps_phy_control(glue, i, 0); |
674 | data->set_phy_power(0); | ||
675 | 699 | ||
676 | return 0; | 700 | return 0; |
677 | } | 701 | } |
678 | 702 | ||
679 | static int dsps_resume(struct device *dev) | 703 | static int dsps_resume(struct device *dev) |
680 | { | 704 | { |
681 | struct musb_hdrc_platform_data *plat = dev->platform_data; | 705 | struct platform_device *pdev = to_platform_device(dev->parent); |
682 | struct omap_musb_board_data *data = plat->board_data; | 706 | struct dsps_glue *glue = platform_get_drvdata(pdev); |
707 | const struct dsps_musb_wrapper *wrp = glue->wrp; | ||
708 | int i; | ||
683 | 709 | ||
684 | /* Start the on-chip PHY and its PLL. */ | 710 | for (i = 0; i < wrp->instances; i++) |
685 | if (data->set_phy_power) | 711 | musb_dsps_phy_control(glue, i, 1); |
686 | data->set_phy_power(1); | ||
687 | 712 | ||
688 | return 0; | 713 | return 0; |
689 | } | 714 | } |
@@ -691,7 +716,7 @@ static int dsps_resume(struct device *dev) | |||
691 | 716 | ||
692 | static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); | 717 | static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); |
693 | 718 | ||
694 | static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { | 719 | static const struct dsps_musb_wrapper ti81xx_driver_data = { |
695 | .revision = 0x00, | 720 | .revision = 0x00, |
696 | .control = 0x14, | 721 | .control = 0x14, |
697 | .status = 0x18, | 722 | .status = 0x18, |
@@ -719,10 +744,10 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { | |||
719 | .rxep_bitmap = (0xfffe << 16), | 744 | .rxep_bitmap = (0xfffe << 16), |
720 | .musb_core_offset = 0x400, | 745 | .musb_core_offset = 0x400, |
721 | .poll_seconds = 2, | 746 | .poll_seconds = 2, |
722 | .instances = 2, | 747 | .instances = 1, |
723 | }; | 748 | }; |
724 | 749 | ||
725 | static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { | 750 | static const struct platform_device_id musb_dsps_id_table[] = { |
726 | { | 751 | { |
727 | .name = "musb-ti81xx", | 752 | .name = "musb-ti81xx", |
728 | .driver_data = (kernel_ulong_t) &ti81xx_driver_data, | 753 | .driver_data = (kernel_ulong_t) &ti81xx_driver_data, |
@@ -732,7 +757,7 @@ static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { | |||
732 | MODULE_DEVICE_TABLE(platform, musb_dsps_id_table); | 757 | MODULE_DEVICE_TABLE(platform, musb_dsps_id_table); |
733 | 758 | ||
734 | #ifdef CONFIG_OF | 759 | #ifdef CONFIG_OF |
735 | static const struct of_device_id musb_dsps_of_match[] __devinitconst = { | 760 | static const struct of_device_id musb_dsps_of_match[] = { |
736 | { .compatible = "ti,musb-am33xx", | 761 | { .compatible = "ti,musb-am33xx", |
737 | .data = (void *) &ti81xx_driver_data, }, | 762 | .data = (void *) &ti81xx_driver_data, }, |
738 | { }, | 763 | { }, |
@@ -742,7 +767,7 @@ MODULE_DEVICE_TABLE(of, musb_dsps_of_match); | |||
742 | 767 | ||
743 | static struct platform_driver dsps_usbss_driver = { | 768 | static struct platform_driver dsps_usbss_driver = { |
744 | .probe = dsps_probe, | 769 | .probe = dsps_probe, |
745 | .remove = __devexit_p(dsps_remove), | 770 | .remove = dsps_remove, |
746 | .driver = { | 771 | .driver = { |
747 | .name = "musb-dsps", | 772 | .name = "musb-dsps", |
748 | .pm = &dsps_pm_ops, | 773 | .pm = &dsps_pm_ops, |