diff options
author | Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> | 2014-09-24 15:09:44 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-29 11:54:02 -0400 |
commit | 0043325495222139daa0696db736f67658dc7770 (patch) | |
tree | caea5e87947d93bac906cbdb18bd7b78de202422 /drivers | |
parent | 3d46e73dfdb840f460e5b06416965d132570ec33 (diff) |
usb: hcd: add generic PHY support
Add the generic PHY support, analogous to the USB PHY support. Intended it to be
used with the PCI EHCI/OHCI drivers and the xHCI platform driver.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/hcd.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 2c56252b9ff8..b84fb141e122 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/pm_runtime.h> | 42 | #include <linux/pm_runtime.h> |
43 | #include <linux/types.h> | 43 | #include <linux/types.h> |
44 | 44 | ||
45 | #include <linux/phy/phy.h> | ||
45 | #include <linux/usb.h> | 46 | #include <linux/usb.h> |
46 | #include <linux/usb/hcd.h> | 47 | #include <linux/usb/hcd.h> |
47 | #include <linux/usb/phy.h> | 48 | #include <linux/usb/phy.h> |
@@ -2647,6 +2648,29 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2647 | } | 2648 | } |
2648 | } | 2649 | } |
2649 | 2650 | ||
2651 | if (IS_ENABLED(CONFIG_GENERIC_PHY)) { | ||
2652 | struct phy *phy = phy_get(hcd->self.controller, "usb"); | ||
2653 | |||
2654 | if (IS_ERR(phy)) { | ||
2655 | retval = PTR_ERR(phy); | ||
2656 | if (retval == -EPROBE_DEFER) | ||
2657 | goto err_phy; | ||
2658 | } else { | ||
2659 | retval = phy_init(phy); | ||
2660 | if (retval) { | ||
2661 | phy_put(phy); | ||
2662 | goto err_phy; | ||
2663 | } | ||
2664 | retval = phy_power_on(phy); | ||
2665 | if (retval) { | ||
2666 | phy_exit(phy); | ||
2667 | phy_put(phy); | ||
2668 | goto err_phy; | ||
2669 | } | ||
2670 | hcd->phy = phy; | ||
2671 | } | ||
2672 | } | ||
2673 | |||
2650 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); | 2674 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); |
2651 | 2675 | ||
2652 | /* Keep old behaviour if authorized_default is not in [0, 1]. */ | 2676 | /* Keep old behaviour if authorized_default is not in [0, 1]. */ |
@@ -2662,7 +2686,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2662 | */ | 2686 | */ |
2663 | if ((retval = hcd_buffer_create(hcd)) != 0) { | 2687 | if ((retval = hcd_buffer_create(hcd)) != 0) { |
2664 | dev_dbg(hcd->self.controller, "pool alloc failed\n"); | 2688 | dev_dbg(hcd->self.controller, "pool alloc failed\n"); |
2665 | goto err_remove_phy; | 2689 | goto err_create_buf; |
2666 | } | 2690 | } |
2667 | 2691 | ||
2668 | if ((retval = usb_register_bus(&hcd->self)) < 0) | 2692 | if ((retval = usb_register_bus(&hcd->self)) < 0) |
@@ -2789,7 +2813,14 @@ err_allocate_root_hub: | |||
2789 | usb_deregister_bus(&hcd->self); | 2813 | usb_deregister_bus(&hcd->self); |
2790 | err_register_bus: | 2814 | err_register_bus: |
2791 | hcd_buffer_destroy(hcd); | 2815 | hcd_buffer_destroy(hcd); |
2792 | err_remove_phy: | 2816 | err_create_buf: |
2817 | if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->phy) { | ||
2818 | phy_power_off(hcd->phy); | ||
2819 | phy_exit(hcd->phy); | ||
2820 | phy_put(hcd->phy); | ||
2821 | hcd->phy = NULL; | ||
2822 | } | ||
2823 | err_phy: | ||
2793 | if (hcd->remove_phy && hcd->usb_phy) { | 2824 | if (hcd->remove_phy && hcd->usb_phy) { |
2794 | usb_phy_shutdown(hcd->usb_phy); | 2825 | usb_phy_shutdown(hcd->usb_phy); |
2795 | usb_put_phy(hcd->usb_phy); | 2826 | usb_put_phy(hcd->usb_phy); |
@@ -2866,6 +2897,13 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
2866 | 2897 | ||
2867 | usb_deregister_bus(&hcd->self); | 2898 | usb_deregister_bus(&hcd->self); |
2868 | hcd_buffer_destroy(hcd); | 2899 | hcd_buffer_destroy(hcd); |
2900 | |||
2901 | if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->phy) { | ||
2902 | phy_power_off(hcd->phy); | ||
2903 | phy_exit(hcd->phy); | ||
2904 | phy_put(hcd->phy); | ||
2905 | hcd->phy = NULL; | ||
2906 | } | ||
2869 | if (hcd->remove_phy && hcd->usb_phy) { | 2907 | if (hcd->remove_phy && hcd->usb_phy) { |
2870 | usb_phy_shutdown(hcd->usb_phy); | 2908 | usb_phy_shutdown(hcd->usb_phy); |
2871 | usb_put_phy(hcd->usb_phy); | 2909 | usb_put_phy(hcd->usb_phy); |