usb: host: ehci-tegra: Use devm_ioremap_resource instead of devm_ioremap
[deliverable/linux.git] / drivers / usb / host / ohci-exynos.c
CommitLineData
62194244
JH
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>
50a97e05
MG
15#include <linux/dma-mapping.h>
16#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
d5138930 19#include <linux/of.h>
62194244 20#include <linux/platform_device.h>
7d28e54b 21#include <linux/phy/phy.h>
ed993bf1 22#include <linux/usb/phy.h>
b506eebc 23#include <linux/usb/samsung_usb_phy.h>
50a97e05
MG
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
32static const char hcd_name[] = "ohci-exynos";
33static 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)
62194244 36
7d28e54b
VG
37#define PHY_NUMBER 3
38
62194244 39struct exynos_ohci_hcd {
62194244 40 struct clk *clk;
ed993bf1
VG
41 struct usb_phy *phy;
42 struct usb_otg *otg;
7d28e54b 43 struct phy *phy_g[PHY_NUMBER];
62194244
JH
44};
45
7d28e54b
VG
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)
ed993bf1 107{
54969ed6 108 struct usb_hcd *hcd = dev_get_drvdata(dev);
50a97e05 109 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
7d28e54b
VG
110 int i;
111 int ret = 0;
112
113 if (!IS_ERR(exynos_ohci->phy))
114 return usb_phy_init(exynos_ohci->phy);
ed993bf1 115
7d28e54b
VG
116 for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
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;
ed993bf1
VG
125}
126
54969ed6 127static void exynos_ohci_phy_disable(struct device *dev)
ed993bf1 128{
54969ed6 129 struct usb_hcd *hcd = dev_get_drvdata(dev);
50a97e05 130 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
7d28e54b 131 int i;
ed993bf1 132
7d28e54b 133 if (!IS_ERR(exynos_ohci->phy)) {
ed993bf1 134 usb_phy_shutdown(exynos_ohci->phy);
7d28e54b
VG
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]);
ed993bf1
VG
141}
142
41ac7b3a 143static int exynos_ohci_probe(struct platform_device *pdev)
62194244 144{
62194244
JH
145 struct exynos_ohci_hcd *exynos_ohci;
146 struct usb_hcd *hcd;
62194244
JH
147 struct resource *res;
148 int irq;
149 int err;
150
d5138930
VG
151 /*
152 * Right now device-tree probed devices don't get dma_mask set.
153 * Since shared usb code relies on it, set it here for now.
154 * Once we move to full device tree support this will vanish off.
155 */
e1fd7341 156 err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
22d9d8e8
RK
157 if (err)
158 return err;
d5138930 159
50a97e05
MG
160 hcd = usb_create_hcd(&exynos_ohci_hc_driver,
161 &pdev->dev, dev_name(&pdev->dev));
162 if (!hcd) {
163 dev_err(&pdev->dev, "Unable to create HCD\n");
62194244 164 return -ENOMEM;
50a97e05
MG
165 }
166
167 exynos_ohci = to_exynos_ohci(hcd);
62194244 168
2871782a
TA
169 if (of_device_is_compatible(pdev->dev.of_node,
170 "samsung,exynos5440-ohci"))
171 goto skip_phy;
172
7d28e54b
VG
173 err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
174 if (err)
175 goto fail_clk;
ed993bf1 176
2871782a 177skip_phy:
60d80adb 178 exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
62194244
JH
179
180 if (IS_ERR(exynos_ohci->clk)) {
181 dev_err(&pdev->dev, "Failed to get usbhost clock\n");
182 err = PTR_ERR(exynos_ohci->clk);
183 goto fail_clk;
184 }
185
c05c946c 186 err = clk_prepare_enable(exynos_ohci->clk);
62194244 187 if (err)
60d80adb 188 goto fail_clk;
62194244
JH
189
190 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
191 if (!res) {
192 dev_err(&pdev->dev, "Failed to get I/O memory\n");
193 err = -ENXIO;
194 goto fail_io;
195 }
196
197 hcd->rsrc_start = res->start;
198 hcd->rsrc_len = resource_size(res);
390a0a78 199 hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len);
62194244
JH
200 if (!hcd->regs) {
201 dev_err(&pdev->dev, "Failed to remap I/O memory\n");
202 err = -ENOMEM;
203 goto fail_io;
204 }
205
206 irq = platform_get_irq(pdev, 0);
207 if (!irq) {
208 dev_err(&pdev->dev, "Failed to get IRQ\n");
209 err = -ENODEV;
390a0a78 210 goto fail_io;
62194244
JH
211 }
212
ed993bf1 213 if (exynos_ohci->otg)
50a97e05 214 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
ed993bf1 215
50a97e05 216 platform_set_drvdata(pdev, hcd);
62194244 217
7d28e54b
VG
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 }
62194244
JH
223
224 err = usb_add_hcd(hcd, irq, IRQF_SHARED);
225 if (err) {
226 dev_err(&pdev->dev, "Failed to add USB HCD\n");
ed993bf1 227 goto fail_add_hcd;
62194244 228 }
3c9740a1 229 device_wakeup_enable(hcd->self.controller);
62194244
JH
230 return 0;
231
ed993bf1 232fail_add_hcd:
54969ed6 233 exynos_ohci_phy_disable(&pdev->dev);
62194244 234fail_io:
c05c946c 235 clk_disable_unprepare(exynos_ohci->clk);
62194244
JH
236fail_clk:
237 usb_put_hcd(hcd);
62194244
JH
238 return err;
239}
240
fb4e98ab 241static int exynos_ohci_remove(struct platform_device *pdev)
62194244 242{
50a97e05
MG
243 struct usb_hcd *hcd = platform_get_drvdata(pdev);
244 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
62194244
JH
245
246 usb_remove_hcd(hcd);
247
ed993bf1 248 if (exynos_ohci->otg)
50a97e05 249 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
ed993bf1 250
54969ed6 251 exynos_ohci_phy_disable(&pdev->dev);
62194244 252
c05c946c 253 clk_disable_unprepare(exynos_ohci->clk);
62194244
JH
254
255 usb_put_hcd(hcd);
62194244
JH
256
257 return 0;
258}
259
260static void exynos_ohci_shutdown(struct platform_device *pdev)
261{
50a97e05 262 struct usb_hcd *hcd = platform_get_drvdata(pdev);
62194244
JH
263
264 if (hcd->driver->shutdown)
265 hcd->driver->shutdown(hcd);
266}
267
268#ifdef CONFIG_PM
269static int exynos_ohci_suspend(struct device *dev)
270{
50a97e05
MG
271 struct usb_hcd *hcd = dev_get_drvdata(dev);
272 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
14982e31 273 bool do_wakeup = device_may_wakeup(dev);
14982e31 274 int rc = ohci_suspend(hcd, do_wakeup);
62194244 275
14982e31
MG
276 if (rc)
277 return rc;
066ba8e0 278
ed993bf1 279 if (exynos_ohci->otg)
50a97e05 280 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
ed993bf1 281
54969ed6 282 exynos_ohci_phy_disable(dev);
e864abed 283
c05c946c 284 clk_disable_unprepare(exynos_ohci->clk);
e864abed 285
14982e31 286 return 0;
62194244
JH
287}
288
289static int exynos_ohci_resume(struct device *dev)
290{
50a97e05
MG
291 struct usb_hcd *hcd = dev_get_drvdata(dev);
292 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
7d28e54b 293 int ret;
62194244 294
c05c946c 295 clk_prepare_enable(exynos_ohci->clk);
e864abed 296
ed993bf1 297 if (exynos_ohci->otg)
50a97e05 298 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
ed993bf1 299
7d28e54b
VG
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 }
62194244 306
cfa49b4b 307 ohci_resume(hcd, false);
62194244
JH
308
309 return 0;
310}
311#else
312#define exynos_ohci_suspend NULL
313#define exynos_ohci_resume NULL
314#endif
315
50a97e05
MG
316static const struct ohci_driver_overrides exynos_overrides __initconst = {
317 .extra_priv_size = sizeof(struct exynos_ohci_hcd),
318};
319
62194244
JH
320static const struct dev_pm_ops exynos_ohci_pm_ops = {
321 .suspend = exynos_ohci_suspend,
322 .resume = exynos_ohci_resume,
323};
324
d5138930
VG
325#ifdef CONFIG_OF
326static const struct of_device_id exynos_ohci_match[] = {
6e247777 327 { .compatible = "samsung,exynos4210-ohci" },
2871782a 328 { .compatible = "samsung,exynos5440-ohci" },
d5138930
VG
329 {},
330};
331MODULE_DEVICE_TABLE(of, exynos_ohci_match);
332#endif
333
62194244
JH
334static struct platform_driver exynos_ohci_driver = {
335 .probe = exynos_ohci_probe,
7690417d 336 .remove = exynos_ohci_remove,
62194244
JH
337 .shutdown = exynos_ohci_shutdown,
338 .driver = {
339 .name = "exynos-ohci",
340 .owner = THIS_MODULE,
341 .pm = &exynos_ohci_pm_ops,
d5138930 342 .of_match_table = of_match_ptr(exynos_ohci_match),
62194244
JH
343 }
344};
50a97e05
MG
345static int __init ohci_exynos_init(void)
346{
347 if (usb_disabled())
348 return -ENODEV;
349
350 pr_info("%s: " DRIVER_DESC "\n", hcd_name);
351 ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides);
352 return platform_driver_register(&exynos_ohci_driver);
353}
354module_init(ohci_exynos_init);
355
356static void __exit ohci_exynos_cleanup(void)
357{
358 platform_driver_unregister(&exynos_ohci_driver);
359}
360module_exit(ohci_exynos_cleanup);
62194244
JH
361
362MODULE_ALIAS("platform:exynos-ohci");
363MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
50a97e05 364MODULE_LICENSE("GPL v2");
This page took 0.196102 seconds and 5 git commands to generate.