aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergei Shtylyov <sergei.shtylyov@cogentembedded.com>2014-09-24 15:09:44 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-09-29 11:54:02 -0400
commit0043325495222139daa0696db736f67658dc7770 (patch)
treecaea5e87947d93bac906cbdb18bd7b78de202422
parent3d46e73dfdb840f460e5b06416965d132570ec33 (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>
-rw-r--r--drivers/usb/core/hcd.c42
-rw-r--r--include/linux/usb/hcd.h1
2 files changed, 41 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);
2790err_register_bus: 2814err_register_bus:
2791 hcd_buffer_destroy(hcd); 2815 hcd_buffer_destroy(hcd);
2792err_remove_phy: 2816err_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 }
2823err_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);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 788059a108e5..cd96a2bc3388 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -107,6 +107,7 @@ struct usb_hcd {
107 * other external phys should be software-transparent 107 * other external phys should be software-transparent
108 */ 108 */
109 struct usb_phy *usb_phy; 109 struct usb_phy *usb_phy;
110 struct phy *phy;
110 111
111 /* Flags that need to be manipulated atomically because they can 112 /* Flags that need to be manipulated atomically because they can
112 * change while the host controller is running. Always use 113 * change while the host controller is running. Always use