diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-exynos.c | 129 |
1 files changed, 109 insertions, 20 deletions
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 4d763dc91f70..c7081c75de8a 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_gpio.h> | 21 | #include <linux/of_gpio.h> |
22 | #include <linux/phy/phy.h> | ||
22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
23 | #include <linux/usb/phy.h> | 24 | #include <linux/usb/phy.h> |
24 | #include <linux/usb/samsung_usb_phy.h> | 25 | #include <linux/usb/samsung_usb_phy.h> |
@@ -42,14 +43,104 @@ | |||
42 | static const char hcd_name[] = "ehci-exynos"; | 43 | static const char hcd_name[] = "ehci-exynos"; |
43 | static struct hc_driver __read_mostly exynos_ehci_hc_driver; | 44 | static struct hc_driver __read_mostly exynos_ehci_hc_driver; |
44 | 45 | ||
46 | #define PHY_NUMBER 3 | ||
47 | |||
45 | struct exynos_ehci_hcd { | 48 | struct exynos_ehci_hcd { |
46 | struct clk *clk; | 49 | struct clk *clk; |
47 | struct usb_phy *phy; | 50 | struct usb_phy *phy; |
48 | struct usb_otg *otg; | 51 | struct usb_otg *otg; |
52 | struct phy *phy_g[PHY_NUMBER]; | ||
49 | }; | 53 | }; |
50 | 54 | ||
51 | #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) | 55 | #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) |
52 | 56 | ||
57 | static int exynos_ehci_get_phy(struct device *dev, | ||
58 | struct exynos_ehci_hcd *exynos_ehci) | ||
59 | { | ||
60 | struct device_node *child; | ||
61 | struct phy *phy; | ||
62 | int phy_number; | ||
63 | int ret = 0; | ||
64 | |||
65 | exynos_ehci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); | ||
66 | if (IS_ERR(exynos_ehci->phy)) { | ||
67 | ret = PTR_ERR(exynos_ehci->phy); | ||
68 | if (ret != -ENXIO && ret != -ENODEV) { | ||
69 | dev_err(dev, "no usb2 phy configured\n"); | ||
70 | return ret; | ||
71 | } | ||
72 | dev_dbg(dev, "Failed to get usb2 phy\n"); | ||
73 | } else { | ||
74 | exynos_ehci->otg = exynos_ehci->phy->otg; | ||
75 | } | ||
76 | |||
77 | for_each_available_child_of_node(dev->of_node, child) { | ||
78 | ret = of_property_read_u32(child, "reg", &phy_number); | ||
79 | if (ret) { | ||
80 | dev_err(dev, "Failed to parse device tree\n"); | ||
81 | of_node_put(child); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | if (phy_number >= PHY_NUMBER) { | ||
86 | dev_err(dev, "Invalid number of PHYs\n"); | ||
87 | of_node_put(child); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | phy = devm_of_phy_get(dev, child, 0); | ||
92 | of_node_put(child); | ||
93 | if (IS_ERR(phy)) { | ||
94 | ret = PTR_ERR(phy); | ||
95 | if (ret != -ENOSYS && ret != -ENODEV) { | ||
96 | dev_err(dev, "no usb2 phy configured\n"); | ||
97 | return ret; | ||
98 | } | ||
99 | dev_dbg(dev, "Failed to get usb2 phy\n"); | ||
100 | } | ||
101 | exynos_ehci->phy_g[phy_number] = phy; | ||
102 | } | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static int exynos_ehci_phy_enable(struct device *dev) | ||
108 | { | ||
109 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
110 | struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); | ||
111 | int i; | ||
112 | int ret = 0; | ||
113 | |||
114 | if (!IS_ERR(exynos_ehci->phy)) | ||
115 | return usb_phy_init(exynos_ehci->phy); | ||
116 | |||
117 | for (i = 0; ret == 0 && i < PHY_NUMBER; i++) | ||
118 | if (!IS_ERR(exynos_ehci->phy_g[i])) | ||
119 | ret = phy_power_on(exynos_ehci->phy_g[i]); | ||
120 | if (ret) | ||
121 | for (i--; i >= 0; i--) | ||
122 | if (!IS_ERR(exynos_ehci->phy_g[i])) | ||
123 | phy_power_off(exynos_ehci->phy_g[i]); | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | static void exynos_ehci_phy_disable(struct device *dev) | ||
129 | { | ||
130 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
131 | struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); | ||
132 | int i; | ||
133 | |||
134 | if (!IS_ERR(exynos_ehci->phy)) { | ||
135 | usb_phy_shutdown(exynos_ehci->phy); | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | for (i = 0; i < PHY_NUMBER; i++) | ||
140 | if (!IS_ERR(exynos_ehci->phy_g[i])) | ||
141 | phy_power_off(exynos_ehci->phy_g[i]); | ||
142 | } | ||
143 | |||
53 | static void exynos_setup_vbus_gpio(struct device *dev) | 144 | static void exynos_setup_vbus_gpio(struct device *dev) |
54 | { | 145 | { |
55 | int err; | 146 | int err; |
@@ -74,7 +165,6 @@ static int exynos_ehci_probe(struct platform_device *pdev) | |||
74 | struct usb_hcd *hcd; | 165 | struct usb_hcd *hcd; |
75 | struct ehci_hcd *ehci; | 166 | struct ehci_hcd *ehci; |
76 | struct resource *res; | 167 | struct resource *res; |
77 | struct usb_phy *phy; | ||
78 | int irq; | 168 | int irq; |
79 | int err; | 169 | int err; |
80 | 170 | ||
@@ -101,15 +191,9 @@ static int exynos_ehci_probe(struct platform_device *pdev) | |||
101 | "samsung,exynos5440-ehci")) | 191 | "samsung,exynos5440-ehci")) |
102 | goto skip_phy; | 192 | goto skip_phy; |
103 | 193 | ||
104 | phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); | 194 | err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci); |
105 | if (IS_ERR(phy)) { | 195 | if (err) |
106 | usb_put_hcd(hcd); | 196 | goto fail_clk; |
107 | dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); | ||
108 | return -EPROBE_DEFER; | ||
109 | } else { | ||
110 | exynos_ehci->phy = phy; | ||
111 | exynos_ehci->otg = phy->otg; | ||
112 | } | ||
113 | 197 | ||
114 | skip_phy: | 198 | skip_phy: |
115 | 199 | ||
@@ -151,8 +235,11 @@ skip_phy: | |||
151 | if (exynos_ehci->otg) | 235 | if (exynos_ehci->otg) |
152 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); | 236 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); |
153 | 237 | ||
154 | if (exynos_ehci->phy) | 238 | err = exynos_ehci_phy_enable(&pdev->dev); |
155 | usb_phy_init(exynos_ehci->phy); | 239 | if (err) { |
240 | dev_err(&pdev->dev, "Failed to enable USB phy\n"); | ||
241 | goto fail_io; | ||
242 | } | ||
156 | 243 | ||
157 | ehci = hcd_to_ehci(hcd); | 244 | ehci = hcd_to_ehci(hcd); |
158 | ehci->caps = hcd->regs; | 245 | ehci->caps = hcd->regs; |
@@ -172,8 +259,7 @@ skip_phy: | |||
172 | return 0; | 259 | return 0; |
173 | 260 | ||
174 | fail_add_hcd: | 261 | fail_add_hcd: |
175 | if (exynos_ehci->phy) | 262 | exynos_ehci_phy_disable(&pdev->dev); |
176 | usb_phy_shutdown(exynos_ehci->phy); | ||
177 | fail_io: | 263 | fail_io: |
178 | clk_disable_unprepare(exynos_ehci->clk); | 264 | clk_disable_unprepare(exynos_ehci->clk); |
179 | fail_clk: | 265 | fail_clk: |
@@ -191,8 +277,7 @@ static int exynos_ehci_remove(struct platform_device *pdev) | |||
191 | if (exynos_ehci->otg) | 277 | if (exynos_ehci->otg) |
192 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); | 278 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); |
193 | 279 | ||
194 | if (exynos_ehci->phy) | 280 | exynos_ehci_phy_disable(&pdev->dev); |
195 | usb_phy_shutdown(exynos_ehci->phy); | ||
196 | 281 | ||
197 | clk_disable_unprepare(exynos_ehci->clk); | 282 | clk_disable_unprepare(exynos_ehci->clk); |
198 | 283 | ||
@@ -217,8 +302,7 @@ static int exynos_ehci_suspend(struct device *dev) | |||
217 | if (exynos_ehci->otg) | 302 | if (exynos_ehci->otg) |
218 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); | 303 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); |
219 | 304 | ||
220 | if (exynos_ehci->phy) | 305 | exynos_ehci_phy_disable(dev); |
221 | usb_phy_shutdown(exynos_ehci->phy); | ||
222 | 306 | ||
223 | clk_disable_unprepare(exynos_ehci->clk); | 307 | clk_disable_unprepare(exynos_ehci->clk); |
224 | 308 | ||
@@ -229,14 +313,19 @@ static int exynos_ehci_resume(struct device *dev) | |||
229 | { | 313 | { |
230 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 314 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
231 | struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); | 315 | struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); |
316 | int ret; | ||
232 | 317 | ||
233 | clk_prepare_enable(exynos_ehci->clk); | 318 | clk_prepare_enable(exynos_ehci->clk); |
234 | 319 | ||
235 | if (exynos_ehci->otg) | 320 | if (exynos_ehci->otg) |
236 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); | 321 | exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); |
237 | 322 | ||
238 | if (exynos_ehci->phy) | 323 | ret = exynos_ehci_phy_enable(dev); |
239 | usb_phy_init(exynos_ehci->phy); | 324 | if (ret) { |
325 | dev_err(dev, "Failed to enable USB phy\n"); | ||
326 | clk_disable_unprepare(exynos_ehci->clk); | ||
327 | return ret; | ||
328 | } | ||
240 | 329 | ||
241 | /* DMA burst Enable */ | 330 | /* DMA burst Enable */ |
242 | writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); | 331 | writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); |