aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-exynos.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ohci-exynos.c')
-rw-r--r--drivers/usb/host/ohci-exynos.c118
1 files changed, 102 insertions, 16 deletions
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 05f00e3098fc..32f2ff1e93ce 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -18,6 +18,7 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/phy/phy.h>
21#include <linux/usb/phy.h> 22#include <linux/usb/phy.h>
22#include <linux/usb/samsung_usb_phy.h> 23#include <linux/usb/samsung_usb_phy.h>
23#include <linux/usb.h> 24#include <linux/usb.h>
@@ -33,28 +34,110 @@ static struct hc_driver __read_mostly exynos_ohci_hc_driver;
33 34
34#define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv) 35#define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
35 36
37#define PHY_NUMBER 3
38
36struct exynos_ohci_hcd { 39struct exynos_ohci_hcd {
37 struct clk *clk; 40 struct clk *clk;
38 struct usb_phy *phy; 41 struct usb_phy *phy;
39 struct usb_otg *otg; 42 struct usb_otg *otg;
43 struct phy *phy_g[PHY_NUMBER];
40}; 44};
41 45
42static void exynos_ohci_phy_enable(struct device *dev) 46static int exynos_ohci_get_phy(struct device *dev,
47 struct exynos_ohci_hcd *exynos_ohci)
48{
49 struct device_node *child;
50 struct phy *phy;
51 int phy_number;
52 int ret = 0;
53
54 exynos_ohci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
55 if (IS_ERR(exynos_ohci->phy)) {
56 ret = PTR_ERR(exynos_ohci->phy);
57 if (ret != -ENXIO && ret != -ENODEV) {
58 dev_err(dev, "no usb2 phy configured\n");
59 return ret;
60 }
61 dev_dbg(dev, "Failed to get usb2 phy\n");
62 } else {
63 exynos_ohci->otg = exynos_ohci->phy->otg;
64 }
65
66 /*
67 * Getting generic phy:
68 * We are keeping both types of phys as a part of transiting OHCI
69 * to generic phy framework, so as to maintain backward compatibilty
70 * with old DTB.
71 * If there are existing devices using DTB files built from them,
72 * to remove the support for old bindings in this driver,
73 * we need to make sure that such devices have their DTBs
74 * updated to ones built from new DTS.
75 */
76 for_each_available_child_of_node(dev->of_node, child) {
77 ret = of_property_read_u32(child, "reg", &phy_number);
78 if (ret) {
79 dev_err(dev, "Failed to parse device tree\n");
80 of_node_put(child);
81 return ret;
82 }
83
84 if (phy_number >= PHY_NUMBER) {
85 dev_err(dev, "Invalid number of PHYs\n");
86 of_node_put(child);
87 return -EINVAL;
88 }
89
90 phy = devm_of_phy_get(dev, child, 0);
91 of_node_put(child);
92 if (IS_ERR(phy)) {
93 ret = PTR_ERR(phy);
94 if (ret != -ENOSYS && ret != -ENODEV) {
95 dev_err(dev, "no usb2 phy configured\n");
96 return ret;
97 }
98 dev_dbg(dev, "Failed to get usb2 phy\n");
99 }
100 exynos_ohci->phy_g[phy_number] = phy;
101 }
102
103 return ret;
104}
105
106static int exynos_ohci_phy_enable(struct device *dev)
43{ 107{
44 struct usb_hcd *hcd = dev_get_drvdata(dev); 108 struct usb_hcd *hcd = dev_get_drvdata(dev);
45 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 109 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
110 int i;
111 int ret = 0;
112
113 if (!IS_ERR(exynos_ohci->phy))
114 return usb_phy_init(exynos_ohci->phy);
46 115
47 if (exynos_ohci->phy) 116 for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
48 usb_phy_init(exynos_ohci->phy); 117 if (!IS_ERR(exynos_ohci->phy_g[i]))
118 ret = phy_power_on(exynos_ohci->phy_g[i]);
119 if (ret)
120 for (i--; i >= 0; i--)
121 if (!IS_ERR(exynos_ohci->phy_g[i]))
122 phy_power_off(exynos_ohci->phy_g[i]);
123
124 return ret;
49} 125}
50 126
51static void exynos_ohci_phy_disable(struct device *dev) 127static void exynos_ohci_phy_disable(struct device *dev)
52{ 128{
53 struct usb_hcd *hcd = dev_get_drvdata(dev); 129 struct usb_hcd *hcd = dev_get_drvdata(dev);
54 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 130 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
131 int i;
55 132
56 if (exynos_ohci->phy) 133 if (!IS_ERR(exynos_ohci->phy)) {
57 usb_phy_shutdown(exynos_ohci->phy); 134 usb_phy_shutdown(exynos_ohci->phy);
135 return;
136 }
137
138 for (i = 0; i < PHY_NUMBER; i++)
139 if (!IS_ERR(exynos_ohci->phy_g[i]))
140 phy_power_off(exynos_ohci->phy_g[i]);
58} 141}
59 142
60static int exynos_ohci_probe(struct platform_device *pdev) 143static int exynos_ohci_probe(struct platform_device *pdev)
@@ -62,7 +145,6 @@ static int exynos_ohci_probe(struct platform_device *pdev)
62 struct exynos_ohci_hcd *exynos_ohci; 145 struct exynos_ohci_hcd *exynos_ohci;
63 struct usb_hcd *hcd; 146 struct usb_hcd *hcd;
64 struct resource *res; 147 struct resource *res;
65 struct usb_phy *phy;
66 int irq; 148 int irq;
67 int err; 149 int err;
68 150
@@ -88,15 +170,9 @@ static int exynos_ohci_probe(struct platform_device *pdev)
88 "samsung,exynos5440-ohci")) 170 "samsung,exynos5440-ohci"))
89 goto skip_phy; 171 goto skip_phy;
90 172
91 phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 173 err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
92 if (IS_ERR(phy)) { 174 if (err)
93 usb_put_hcd(hcd); 175 goto fail_clk;
94 dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
95 return -EPROBE_DEFER;
96 } else {
97 exynos_ohci->phy = phy;
98 exynos_ohci->otg = phy->otg;
99 }
100 176
101skip_phy: 177skip_phy:
102 exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); 178 exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
@@ -139,7 +215,11 @@ skip_phy:
139 215
140 platform_set_drvdata(pdev, hcd); 216 platform_set_drvdata(pdev, hcd);
141 217
142 exynos_ohci_phy_enable(&pdev->dev); 218 err = exynos_ohci_phy_enable(&pdev->dev);
219 if (err) {
220 dev_err(&pdev->dev, "Failed to enable USB phy\n");
221 goto fail_io;
222 }
143 223
144 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 224 err = usb_add_hcd(hcd, irq, IRQF_SHARED);
145 if (err) { 225 if (err) {
@@ -210,13 +290,19 @@ static int exynos_ohci_resume(struct device *dev)
210{ 290{
211 struct usb_hcd *hcd = dev_get_drvdata(dev); 291 struct usb_hcd *hcd = dev_get_drvdata(dev);
212 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 292 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
293 int ret;
213 294
214 clk_prepare_enable(exynos_ohci->clk); 295 clk_prepare_enable(exynos_ohci->clk);
215 296
216 if (exynos_ohci->otg) 297 if (exynos_ohci->otg)
217 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); 298 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
218 299
219 exynos_ohci_phy_enable(dev); 300 ret = exynos_ohci_phy_enable(dev);
301 if (ret) {
302 dev_err(dev, "Failed to enable USB phy\n");
303 clk_disable_unprepare(exynos_ohci->clk);
304 return ret;
305 }
220 306
221 ohci_resume(hcd, false); 307 ohci_resume(hcd, false);
222 308