]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/usb/host/ohci-exynos.c
usb: ehci/ohci-exynos: Fix PHY getting sequence
[karo-tx-linux.git] / drivers / usb / host / ohci-exynos.c
1 /*
2  * SAMSUNG EXYNOS USB HOST OHCI Controller
3  *
4  * Copyright (C) 2011 Samsung Electronics Co.Ltd
5  * Author: Jingoo Han <jg1.han@samsung.com>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  *
12  */
13
14 #include <linux/clk.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/io.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <linux/phy/phy.h>
22 #include <linux/usb/phy.h>
23 #include <linux/usb/samsung_usb_phy.h>
24 #include <linux/usb.h>
25 #include <linux/usb/hcd.h>
26 #include <linux/usb/otg.h>
27
28 #include "ohci.h"
29
30 #define DRIVER_DESC "OHCI EXYNOS driver"
31
32 static const char hcd_name[] = "ohci-exynos";
33 static struct hc_driver __read_mostly exynos_ohci_hc_driver;
34
35 #define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
36
37 #define PHY_NUMBER 3
38
39 struct exynos_ohci_hcd {
40         struct clk *clk;
41         struct usb_phy *phy;
42         struct usb_otg *otg;
43         struct phy *phy_g[PHY_NUMBER];
44 };
45
46 static 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         /*
55          * Getting generic phy:
56          * We are keeping both types of phys as a part of transiting OHCI
57          * to generic phy framework, so as to maintain backward compatibilty
58          * with old DTB too.
59          * We fallback to older USB-PHYs when we fail to get generic PHYs.
60          */
61         for_each_available_child_of_node(dev->of_node, child) {
62                 ret = of_property_read_u32(child, "reg", &phy_number);
63                 if (ret) {
64                         dev_err(dev, "Failed to parse device tree\n");
65                         of_node_put(child);
66                         return ret;
67                 }
68
69                 if (phy_number >= PHY_NUMBER) {
70                         dev_err(dev, "Invalid number of PHYs\n");
71                         of_node_put(child);
72                         return -EINVAL;
73                 }
74
75                 phy = devm_of_phy_get(dev, child, NULL);
76                 of_node_put(child);
77                 if (IS_ERR(phy))
78                         /* Lets fallback to older USB-PHYs */
79                         goto usb_phy_old;
80                 exynos_ohci->phy_g[phy_number] = phy;
81                 /* Make the older PHYs unavailable */
82                 exynos_ohci->phy = ERR_PTR(-ENXIO);
83         }
84
85         return 0;
86
87 usb_phy_old:
88         exynos_ohci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
89         if (IS_ERR(exynos_ohci->phy)) {
90                 ret = PTR_ERR(exynos_ohci->phy);
91                 if (ret != -ENXIO && ret != -ENODEV) {
92                         dev_err(dev, "no usb2 phy configured\n");
93                         return ret;
94                 }
95                 dev_dbg(dev, "Failed to get usb2 phy\n");
96         } else {
97                 exynos_ohci->otg = exynos_ohci->phy->otg;
98         }
99
100         return ret;
101 }
102
103 static int exynos_ohci_phy_enable(struct device *dev)
104 {
105         struct usb_hcd *hcd = dev_get_drvdata(dev);
106         struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
107         int i;
108         int ret = 0;
109
110         if (!IS_ERR(exynos_ohci->phy))
111                 return usb_phy_init(exynos_ohci->phy);
112
113         for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
114                 if (!IS_ERR(exynos_ohci->phy_g[i]))
115                         ret = phy_power_on(exynos_ohci->phy_g[i]);
116         if (ret)
117                 for (i--; i >= 0; i--)
118                         if (!IS_ERR(exynos_ohci->phy_g[i]))
119                                 phy_power_off(exynos_ohci->phy_g[i]);
120
121         return ret;
122 }
123
124 static void exynos_ohci_phy_disable(struct device *dev)
125 {
126         struct usb_hcd *hcd = dev_get_drvdata(dev);
127         struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
128         int i;
129
130         if (!IS_ERR(exynos_ohci->phy)) {
131                 usb_phy_shutdown(exynos_ohci->phy);
132                 return;
133         }
134
135         for (i = 0; i < PHY_NUMBER; i++)
136                 if (!IS_ERR(exynos_ohci->phy_g[i]))
137                         phy_power_off(exynos_ohci->phy_g[i]);
138 }
139
140 static int exynos_ohci_probe(struct platform_device *pdev)
141 {
142         struct exynos_ohci_hcd *exynos_ohci;
143         struct usb_hcd *hcd;
144         struct resource *res;
145         int irq;
146         int err;
147
148         /*
149          * Right now device-tree probed devices don't get dma_mask set.
150          * Since shared usb code relies on it, set it here for now.
151          * Once we move to full device tree support this will vanish off.
152          */
153         err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
154         if (err)
155                 return err;
156
157         hcd = usb_create_hcd(&exynos_ohci_hc_driver,
158                                 &pdev->dev, dev_name(&pdev->dev));
159         if (!hcd) {
160                 dev_err(&pdev->dev, "Unable to create HCD\n");
161                 return -ENOMEM;
162         }
163
164         exynos_ohci = to_exynos_ohci(hcd);
165
166         if (of_device_is_compatible(pdev->dev.of_node,
167                                         "samsung,exynos5440-ohci"))
168                 goto skip_phy;
169
170         err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
171         if (err)
172                 goto fail_clk;
173
174 skip_phy:
175         exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
176
177         if (IS_ERR(exynos_ohci->clk)) {
178                 dev_err(&pdev->dev, "Failed to get usbhost clock\n");
179                 err = PTR_ERR(exynos_ohci->clk);
180                 goto fail_clk;
181         }
182
183         err = clk_prepare_enable(exynos_ohci->clk);
184         if (err)
185                 goto fail_clk;
186
187         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
188         if (!res) {
189                 dev_err(&pdev->dev, "Failed to get I/O memory\n");
190                 err = -ENXIO;
191                 goto fail_io;
192         }
193
194         hcd->rsrc_start = res->start;
195         hcd->rsrc_len = resource_size(res);
196         hcd->regs = devm_ioremap_resource(&pdev->dev, res);
197         if (IS_ERR(hcd->regs)) {
198                 err = PTR_ERR(hcd->regs);
199                 goto fail_io;
200         }
201
202         irq = platform_get_irq(pdev, 0);
203         if (!irq) {
204                 dev_err(&pdev->dev, "Failed to get IRQ\n");
205                 err = -ENODEV;
206                 goto fail_io;
207         }
208
209         if (exynos_ohci->otg)
210                 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
211
212         platform_set_drvdata(pdev, hcd);
213
214         err = exynos_ohci_phy_enable(&pdev->dev);
215         if (err) {
216                 dev_err(&pdev->dev, "Failed to enable USB phy\n");
217                 goto fail_io;
218         }
219
220         err = usb_add_hcd(hcd, irq, IRQF_SHARED);
221         if (err) {
222                 dev_err(&pdev->dev, "Failed to add USB HCD\n");
223                 goto fail_add_hcd;
224         }
225         device_wakeup_enable(hcd->self.controller);
226         return 0;
227
228 fail_add_hcd:
229         exynos_ohci_phy_disable(&pdev->dev);
230 fail_io:
231         clk_disable_unprepare(exynos_ohci->clk);
232 fail_clk:
233         usb_put_hcd(hcd);
234         return err;
235 }
236
237 static int exynos_ohci_remove(struct platform_device *pdev)
238 {
239         struct usb_hcd *hcd = platform_get_drvdata(pdev);
240         struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
241
242         usb_remove_hcd(hcd);
243
244         if (exynos_ohci->otg)
245                 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
246
247         exynos_ohci_phy_disable(&pdev->dev);
248
249         clk_disable_unprepare(exynos_ohci->clk);
250
251         usb_put_hcd(hcd);
252
253         return 0;
254 }
255
256 static void exynos_ohci_shutdown(struct platform_device *pdev)
257 {
258         struct usb_hcd *hcd = platform_get_drvdata(pdev);
259
260         if (hcd->driver->shutdown)
261                 hcd->driver->shutdown(hcd);
262 }
263
264 #ifdef CONFIG_PM
265 static int exynos_ohci_suspend(struct device *dev)
266 {
267         struct usb_hcd *hcd = dev_get_drvdata(dev);
268         struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
269         bool do_wakeup = device_may_wakeup(dev);
270         int rc = ohci_suspend(hcd, do_wakeup);
271
272         if (rc)
273                 return rc;
274
275         if (exynos_ohci->otg)
276                 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
277
278         exynos_ohci_phy_disable(dev);
279
280         clk_disable_unprepare(exynos_ohci->clk);
281
282         return 0;
283 }
284
285 static int exynos_ohci_resume(struct device *dev)
286 {
287         struct usb_hcd *hcd                     = dev_get_drvdata(dev);
288         struct exynos_ohci_hcd *exynos_ohci     = to_exynos_ohci(hcd);
289         int ret;
290
291         clk_prepare_enable(exynos_ohci->clk);
292
293         if (exynos_ohci->otg)
294                 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
295
296         ret = exynos_ohci_phy_enable(dev);
297         if (ret) {
298                 dev_err(dev, "Failed to enable USB phy\n");
299                 clk_disable_unprepare(exynos_ohci->clk);
300                 return ret;
301         }
302
303         ohci_resume(hcd, false);
304
305         return 0;
306 }
307 #else
308 #define exynos_ohci_suspend     NULL
309 #define exynos_ohci_resume      NULL
310 #endif
311
312 static const struct ohci_driver_overrides exynos_overrides __initconst = {
313         .extra_priv_size =      sizeof(struct exynos_ohci_hcd),
314 };
315
316 static const struct dev_pm_ops exynos_ohci_pm_ops = {
317         .suspend        = exynos_ohci_suspend,
318         .resume         = exynos_ohci_resume,
319 };
320
321 #ifdef CONFIG_OF
322 static const struct of_device_id exynos_ohci_match[] = {
323         { .compatible = "samsung,exynos4210-ohci" },
324         { .compatible = "samsung,exynos5440-ohci" },
325         {},
326 };
327 MODULE_DEVICE_TABLE(of, exynos_ohci_match);
328 #endif
329
330 static struct platform_driver exynos_ohci_driver = {
331         .probe          = exynos_ohci_probe,
332         .remove         = exynos_ohci_remove,
333         .shutdown       = exynos_ohci_shutdown,
334         .driver = {
335                 .name   = "exynos-ohci",
336                 .owner  = THIS_MODULE,
337                 .pm     = &exynos_ohci_pm_ops,
338                 .of_match_table = of_match_ptr(exynos_ohci_match),
339         }
340 };
341 static int __init ohci_exynos_init(void)
342 {
343         if (usb_disabled())
344                 return -ENODEV;
345
346         pr_info("%s: " DRIVER_DESC "\n", hcd_name);
347         ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides);
348         return platform_driver_register(&exynos_ohci_driver);
349 }
350 module_init(ohci_exynos_init);
351
352 static void __exit ohci_exynos_cleanup(void)
353 {
354         platform_driver_unregister(&exynos_ohci_driver);
355 }
356 module_exit(ohci_exynos_cleanup);
357
358 MODULE_ALIAS("platform:exynos-ohci");
359 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
360 MODULE_LICENSE("GPL v2");