diff options
author | Peter Chen <peter.chen@freescale.com> | 2013-09-24 00:47:53 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-09-30 21:54:06 -0400 |
commit | 74475ede784d4a649592751e4d85bb8ff679e1e0 (patch) | |
tree | d29b65deb7bcdcf413b51ff6814814d0597fc053 /drivers/usb/chipidea | |
parent | df9b17f5868bdafd46cad18b08f1e70fa22b8854 (diff) |
usb: chipidea: move PHY operation to core
PHY operations are common, so move them to core.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r-- | drivers/usb/chipidea/core.c | 57 | ||||
-rw-r--r-- | drivers/usb/chipidea/udc.c | 39 |
2 files changed, 52 insertions, 44 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index c47a6b46dea3..b20286de1436 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -474,6 +474,33 @@ static void ci_get_otg_capable(struct ci_hdrc *ci) | |||
474 | } | 474 | } |
475 | } | 475 | } |
476 | 476 | ||
477 | static int ci_usb_phy_init(struct ci_hdrc *ci) | ||
478 | { | ||
479 | if (ci->platdata->phy) { | ||
480 | ci->transceiver = ci->platdata->phy; | ||
481 | return usb_phy_init(ci->transceiver); | ||
482 | } else { | ||
483 | ci->global_phy = true; | ||
484 | ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | ||
485 | if (IS_ERR(ci->transceiver)) | ||
486 | ci->transceiver = NULL; | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | static void ci_usb_phy_destroy(struct ci_hdrc *ci) | ||
493 | { | ||
494 | if (!ci->transceiver) | ||
495 | return; | ||
496 | |||
497 | otg_set_peripheral(ci->transceiver->otg, NULL); | ||
498 | if (ci->global_phy) | ||
499 | usb_put_phy(ci->transceiver); | ||
500 | else | ||
501 | usb_phy_shutdown(ci->transceiver); | ||
502 | } | ||
503 | |||
477 | static int ci_hdrc_probe(struct platform_device *pdev) | 504 | static int ci_hdrc_probe(struct platform_device *pdev) |
478 | { | 505 | { |
479 | struct device *dev = &pdev->dev; | 506 | struct device *dev = &pdev->dev; |
@@ -501,10 +528,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
501 | 528 | ||
502 | ci->dev = dev; | 529 | ci->dev = dev; |
503 | ci->platdata = dev->platform_data; | 530 | ci->platdata = dev->platform_data; |
504 | if (ci->platdata->phy) | ||
505 | ci->transceiver = ci->platdata->phy; | ||
506 | else | ||
507 | ci->global_phy = true; | ||
508 | 531 | ||
509 | ret = hw_device_init(ci, base); | 532 | ret = hw_device_init(ci, base); |
510 | if (ret < 0) { | 533 | if (ret < 0) { |
@@ -512,12 +535,19 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
512 | return -ENODEV; | 535 | return -ENODEV; |
513 | } | 536 | } |
514 | 537 | ||
538 | ret = ci_usb_phy_init(ci); | ||
539 | if (ret) { | ||
540 | dev_err(dev, "unable to init phy: %d\n", ret); | ||
541 | return ret; | ||
542 | } | ||
543 | |||
515 | ci->hw_bank.phys = res->start; | 544 | ci->hw_bank.phys = res->start; |
516 | 545 | ||
517 | ci->irq = platform_get_irq(pdev, 0); | 546 | ci->irq = platform_get_irq(pdev, 0); |
518 | if (ci->irq < 0) { | 547 | if (ci->irq < 0) { |
519 | dev_err(dev, "missing IRQ\n"); | 548 | dev_err(dev, "missing IRQ\n"); |
520 | return -ENODEV; | 549 | ret = -ENODEV; |
550 | goto destroy_phy; | ||
521 | } | 551 | } |
522 | 552 | ||
523 | ci_get_otg_capable(ci); | 553 | ci_get_otg_capable(ci); |
@@ -536,11 +566,23 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
536 | ret = ci_hdrc_gadget_init(ci); | 566 | ret = ci_hdrc_gadget_init(ci); |
537 | if (ret) | 567 | if (ret) |
538 | dev_info(dev, "doesn't support gadget\n"); | 568 | dev_info(dev, "doesn't support gadget\n"); |
569 | if (!ret && ci->transceiver) { | ||
570 | ret = otg_set_peripheral(ci->transceiver->otg, | ||
571 | &ci->gadget); | ||
572 | /* | ||
573 | * If we implement all USB functions using chipidea drivers, | ||
574 | * it doesn't need to call above API, meanwhile, if we only | ||
575 | * use gadget function, calling above API is useless. | ||
576 | */ | ||
577 | if (ret && ret != -ENOTSUPP) | ||
578 | goto destroy_phy; | ||
579 | } | ||
539 | } | 580 | } |
540 | 581 | ||
541 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { | 582 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { |
542 | dev_err(dev, "no supported roles\n"); | 583 | dev_err(dev, "no supported roles\n"); |
543 | return -ENODEV; | 584 | ret = -ENODEV; |
585 | goto destroy_phy; | ||
544 | } | 586 | } |
545 | 587 | ||
546 | if (ci->is_otg) { | 588 | if (ci->is_otg) { |
@@ -593,6 +635,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
593 | free_irq(ci->irq, ci); | 635 | free_irq(ci->irq, ci); |
594 | stop: | 636 | stop: |
595 | ci_role_destroy(ci); | 637 | ci_role_destroy(ci); |
638 | destroy_phy: | ||
639 | ci_usb_phy_destroy(ci); | ||
596 | 640 | ||
597 | return ret; | 641 | return ret; |
598 | } | 642 | } |
@@ -604,6 +648,7 @@ static int ci_hdrc_remove(struct platform_device *pdev) | |||
604 | dbg_remove_files(ci); | 648 | dbg_remove_files(ci); |
605 | free_irq(ci->irq, ci); | 649 | free_irq(ci->irq, ci); |
606 | ci_role_destroy(ci); | 650 | ci_role_destroy(ci); |
651 | ci_usb_phy_destroy(ci); | ||
607 | kfree(ci->hw_bank.regmap); | 652 | kfree(ci->hw_bank.regmap); |
608 | 653 | ||
609 | return 0; | 654 | return 0; |
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b157c95f7a36..2bb7d18ef2d5 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/usb/ch9.h> | 21 | #include <linux/usb/ch9.h> |
22 | #include <linux/usb/gadget.h> | 22 | #include <linux/usb/gadget.h> |
23 | #include <linux/usb/otg.h> | ||
24 | #include <linux/usb/chipidea.h> | 23 | #include <linux/usb/chipidea.h> |
25 | 24 | ||
26 | #include "ci.h" | 25 | #include "ci.h" |
@@ -1790,34 +1789,9 @@ static int udc_start(struct ci_hdrc *ci) | |||
1790 | 1789 | ||
1791 | ci->gadget.ep0 = &ci->ep0in->ep; | 1790 | ci->gadget.ep0 = &ci->ep0in->ep; |
1792 | 1791 | ||
1793 | if (ci->global_phy) { | ||
1794 | ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | ||
1795 | if (IS_ERR(ci->transceiver)) | ||
1796 | ci->transceiver = NULL; | ||
1797 | } | ||
1798 | |||
1799 | if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) { | ||
1800 | if (ci->transceiver == NULL) { | ||
1801 | retval = -ENODEV; | ||
1802 | goto destroy_eps; | ||
1803 | } | ||
1804 | } | ||
1805 | |||
1806 | if (ci->transceiver) { | ||
1807 | retval = otg_set_peripheral(ci->transceiver->otg, | ||
1808 | &ci->gadget); | ||
1809 | /* | ||
1810 | * If we implement all USB functions using chipidea drivers, | ||
1811 | * it doesn't need to call above API, meanwhile, if we only | ||
1812 | * use gadget function, calling above API is useless. | ||
1813 | */ | ||
1814 | if (retval && retval != -ENOTSUPP) | ||
1815 | goto put_transceiver; | ||
1816 | } | ||
1817 | |||
1818 | retval = usb_add_gadget_udc(dev, &ci->gadget); | 1792 | retval = usb_add_gadget_udc(dev, &ci->gadget); |
1819 | if (retval) | 1793 | if (retval) |
1820 | goto remove_trans; | 1794 | goto destroy_eps; |
1821 | 1795 | ||
1822 | pm_runtime_no_callbacks(&ci->gadget.dev); | 1796 | pm_runtime_no_callbacks(&ci->gadget.dev); |
1823 | pm_runtime_enable(&ci->gadget.dev); | 1797 | pm_runtime_enable(&ci->gadget.dev); |
@@ -1827,17 +1801,6 @@ static int udc_start(struct ci_hdrc *ci) | |||
1827 | 1801 | ||
1828 | return retval; | 1802 | return retval; |
1829 | 1803 | ||
1830 | remove_trans: | ||
1831 | if (ci->transceiver) { | ||
1832 | otg_set_peripheral(ci->transceiver->otg, NULL); | ||
1833 | if (ci->global_phy) | ||
1834 | usb_put_phy(ci->transceiver); | ||
1835 | } | ||
1836 | |||
1837 | dev_err(dev, "error = %i\n", retval); | ||
1838 | put_transceiver: | ||
1839 | if (ci->transceiver && ci->global_phy) | ||
1840 | usb_put_phy(ci->transceiver); | ||
1841 | destroy_eps: | 1804 | destroy_eps: |
1842 | destroy_eps(ci); | 1805 | destroy_eps(ci); |
1843 | free_pools: | 1806 | free_pools: |