GNU Linux-libre 4.14.313-gnu1
[releases.git] / drivers / usb / chipidea / ci_hdrc_imx.c
1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  * Copyright (C) 2012 Marek Vasut <marex@denx.de>
4  * on behalf of DENX Software Engineering GmbH
5  *
6  * The code contained herein is licensed under the GNU General Public
7  * License. You may obtain a copy of the GNU General Public License
8  * Version 2 or later at the following locations:
9  *
10  * http://www.opensource.org/licenses/gpl-license.html
11  * http://www.gnu.org/copyleft/gpl.html
12  */
13
14 #include <linux/module.h>
15 #include <linux/of_platform.h>
16 #include <linux/of_gpio.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/dma-mapping.h>
20 #include <linux/usb/chipidea.h>
21 #include <linux/usb/of.h>
22 #include <linux/clk.h>
23
24 #include "ci.h"
25 #include "ci_hdrc_imx.h"
26
27 struct ci_hdrc_imx_platform_flag {
28         unsigned int flags;
29         bool runtime_pm;
30 };
31
32 static const struct ci_hdrc_imx_platform_flag imx23_usb_data = {
33         .flags = CI_HDRC_TURN_VBUS_EARLY_ON |
34                 CI_HDRC_DISABLE_STREAMING,
35 };
36
37 static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
38                 CI_HDRC_DISABLE_STREAMING,
39 };
40
41 static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
42         .flags = CI_HDRC_IMX28_WRITE_FIX |
43                 CI_HDRC_TURN_VBUS_EARLY_ON |
44                 CI_HDRC_DISABLE_STREAMING,
45 };
46
47 static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
48         .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
49                 CI_HDRC_TURN_VBUS_EARLY_ON |
50                 CI_HDRC_DISABLE_STREAMING,
51 };
52
53 static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
54         .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
55                 CI_HDRC_TURN_VBUS_EARLY_ON |
56                 CI_HDRC_DISABLE_HOST_STREAMING,
57 };
58
59 static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
60         .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
61                 CI_HDRC_TURN_VBUS_EARLY_ON |
62                 CI_HDRC_DISABLE_HOST_STREAMING,
63 };
64
65 static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = {
66         .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
67                 CI_HDRC_TURN_VBUS_EARLY_ON |
68                 CI_HDRC_DISABLE_DEVICE_STREAMING,
69 };
70
71 static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
72         .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
73 };
74
75 static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
76         { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
77         { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
78         { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
79         { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
80         { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
81         { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
82         { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
83         { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
84         { /* sentinel */ }
85 };
86 MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
87
88 struct ci_hdrc_imx_data {
89         struct usb_phy *phy;
90         struct platform_device *ci_pdev;
91         struct clk *clk;
92         struct imx_usbmisc_data *usbmisc_data;
93         bool supports_runtime_pm;
94         bool in_lpm;
95         /* SoC before i.mx6 (except imx23/imx28) needs three clks */
96         bool need_three_clks;
97         struct clk *clk_ipg;
98         struct clk *clk_ahb;
99         struct clk *clk_per;
100         /* --------------------------------- */
101 };
102
103 /* Common functions shared by usbmisc drivers */
104
105 static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
106 {
107         struct platform_device *misc_pdev;
108         struct device_node *np = dev->of_node;
109         struct of_phandle_args args;
110         struct imx_usbmisc_data *data;
111         int ret;
112
113         /*
114          * In case the fsl,usbmisc property is not present this device doesn't
115          * need usbmisc. Return NULL (which is no error here)
116          */
117         if (!of_get_property(np, "fsl,usbmisc", NULL))
118                 return NULL;
119
120         data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
121         if (!data)
122                 return ERR_PTR(-ENOMEM);
123
124         ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
125                                         0, &args);
126         if (ret) {
127                 dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
128                         ret);
129                 return ERR_PTR(ret);
130         }
131
132         data->index = args.args[0];
133
134         misc_pdev = of_find_device_by_node(args.np);
135         of_node_put(args.np);
136
137         if (!misc_pdev)
138                 return ERR_PTR(-EPROBE_DEFER);
139
140         if (!platform_get_drvdata(misc_pdev)) {
141                 put_device(&misc_pdev->dev);
142                 return ERR_PTR(-EPROBE_DEFER);
143         }
144         data->dev = &misc_pdev->dev;
145
146         if (of_find_property(np, "disable-over-current", NULL))
147                 data->disable_oc = 1;
148
149         if (of_find_property(np, "over-current-active-high", NULL))
150                 data->oc_polarity = 1;
151
152         if (of_find_property(np, "external-vbus-divider", NULL))
153                 data->evdo = 1;
154
155         if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
156                 data->ulpi = 1;
157
158         return data;
159 }
160
161 /* End of common functions shared by usbmisc drivers*/
162 static int imx_get_clks(struct device *dev)
163 {
164         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
165         int ret = 0;
166
167         data->clk_ipg = devm_clk_get(dev, "ipg");
168         if (IS_ERR(data->clk_ipg)) {
169                 /* If the platform only needs one clocks */
170                 data->clk = devm_clk_get(dev, NULL);
171                 if (IS_ERR(data->clk)) {
172                         ret = PTR_ERR(data->clk);
173                         dev_err(dev,
174                                 "Failed to get clks, err=%ld,%ld\n",
175                                 PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
176                         return ret;
177                 }
178                 return ret;
179         }
180
181         data->clk_ahb = devm_clk_get(dev, "ahb");
182         if (IS_ERR(data->clk_ahb)) {
183                 ret = PTR_ERR(data->clk_ahb);
184                 dev_err(dev,
185                         "Failed to get ahb clock, err=%d\n", ret);
186                 return ret;
187         }
188
189         data->clk_per = devm_clk_get(dev, "per");
190         if (IS_ERR(data->clk_per)) {
191                 ret = PTR_ERR(data->clk_per);
192                 dev_err(dev,
193                         "Failed to get per clock, err=%d\n", ret);
194                 return ret;
195         }
196
197         data->need_three_clks = true;
198         return ret;
199 }
200
201 static int imx_prepare_enable_clks(struct device *dev)
202 {
203         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
204         int ret = 0;
205
206         if (data->need_three_clks) {
207                 ret = clk_prepare_enable(data->clk_ipg);
208                 if (ret) {
209                         dev_err(dev,
210                                 "Failed to prepare/enable ipg clk, err=%d\n",
211                                 ret);
212                         return ret;
213                 }
214
215                 ret = clk_prepare_enable(data->clk_ahb);
216                 if (ret) {
217                         dev_err(dev,
218                                 "Failed to prepare/enable ahb clk, err=%d\n",
219                                 ret);
220                         clk_disable_unprepare(data->clk_ipg);
221                         return ret;
222                 }
223
224                 ret = clk_prepare_enable(data->clk_per);
225                 if (ret) {
226                         dev_err(dev,
227                                 "Failed to prepare/enable per clk, err=%d\n",
228                                 ret);
229                         clk_disable_unprepare(data->clk_ahb);
230                         clk_disable_unprepare(data->clk_ipg);
231                         return ret;
232                 }
233         } else {
234                 ret = clk_prepare_enable(data->clk);
235                 if (ret) {
236                         dev_err(dev,
237                                 "Failed to prepare/enable clk, err=%d\n",
238                                 ret);
239                         return ret;
240                 }
241         }
242
243         return ret;
244 }
245
246 static void imx_disable_unprepare_clks(struct device *dev)
247 {
248         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
249
250         if (data->need_three_clks) {
251                 clk_disable_unprepare(data->clk_per);
252                 clk_disable_unprepare(data->clk_ahb);
253                 clk_disable_unprepare(data->clk_ipg);
254         } else {
255                 clk_disable_unprepare(data->clk);
256         }
257 }
258
259 static int ci_hdrc_imx_probe(struct platform_device *pdev)
260 {
261         struct ci_hdrc_imx_data *data;
262         struct ci_hdrc_platform_data pdata = {
263                 .name           = dev_name(&pdev->dev),
264                 .capoffset      = DEF_CAPOFFSET,
265         };
266         int ret;
267         const struct of_device_id *of_id;
268         const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
269
270         of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
271         if (!of_id)
272                 return -ENODEV;
273
274         imx_platform_flag = of_id->data;
275
276         data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
277         if (!data)
278                 return -ENOMEM;
279
280         platform_set_drvdata(pdev, data);
281         data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
282         if (IS_ERR(data->usbmisc_data))
283                 return PTR_ERR(data->usbmisc_data);
284
285         ret = imx_get_clks(&pdev->dev);
286         if (ret)
287                 return ret;
288
289         ret = imx_prepare_enable_clks(&pdev->dev);
290         if (ret)
291                 return ret;
292
293         data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
294         if (IS_ERR(data->phy)) {
295                 ret = PTR_ERR(data->phy);
296                 /* Return -EINVAL if no usbphy is available */
297                 if (ret == -ENODEV)
298                         ret = -EINVAL;
299                 goto err_clk;
300         }
301
302         pdata.usb_phy = data->phy;
303         pdata.flags |= imx_platform_flag->flags;
304         if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
305                 data->supports_runtime_pm = true;
306
307         ret = imx_usbmisc_init(data->usbmisc_data);
308         if (ret) {
309                 dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret);
310                 goto err_clk;
311         }
312
313         data->ci_pdev = ci_hdrc_add_device(&pdev->dev,
314                                 pdev->resource, pdev->num_resources,
315                                 &pdata);
316         if (IS_ERR(data->ci_pdev)) {
317                 ret = PTR_ERR(data->ci_pdev);
318                 if (ret != -EPROBE_DEFER)
319                         dev_err(&pdev->dev,
320                                 "ci_hdrc_add_device failed, err=%d\n", ret);
321                 goto err_clk;
322         }
323
324         ret = imx_usbmisc_init_post(data->usbmisc_data);
325         if (ret) {
326                 dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret);
327                 goto disable_device;
328         }
329
330         if (data->supports_runtime_pm) {
331                 pm_runtime_set_active(&pdev->dev);
332                 pm_runtime_enable(&pdev->dev);
333         }
334
335         device_set_wakeup_capable(&pdev->dev, true);
336
337         return 0;
338
339 disable_device:
340         ci_hdrc_remove_device(data->ci_pdev);
341 err_clk:
342         imx_disable_unprepare_clks(&pdev->dev);
343         return ret;
344 }
345
346 static int ci_hdrc_imx_remove(struct platform_device *pdev)
347 {
348         struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev);
349
350         if (data->supports_runtime_pm) {
351                 pm_runtime_get_sync(&pdev->dev);
352                 pm_runtime_disable(&pdev->dev);
353                 pm_runtime_put_noidle(&pdev->dev);
354         }
355         ci_hdrc_remove_device(data->ci_pdev);
356         imx_disable_unprepare_clks(&pdev->dev);
357
358         return 0;
359 }
360
361 static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
362 {
363         ci_hdrc_imx_remove(pdev);
364 }
365
366 #ifdef CONFIG_PM
367 static int imx_controller_suspend(struct device *dev)
368 {
369         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
370
371         dev_dbg(dev, "at %s\n", __func__);
372
373         imx_disable_unprepare_clks(dev);
374         data->in_lpm = true;
375
376         return 0;
377 }
378
379 static int imx_controller_resume(struct device *dev)
380 {
381         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
382         int ret = 0;
383
384         dev_dbg(dev, "at %s\n", __func__);
385
386         if (!data->in_lpm) {
387                 WARN_ON(1);
388                 return 0;
389         }
390
391         ret = imx_prepare_enable_clks(dev);
392         if (ret)
393                 return ret;
394
395         data->in_lpm = false;
396
397         ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
398         if (ret) {
399                 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
400                 goto clk_disable;
401         }
402
403         return 0;
404
405 clk_disable:
406         imx_disable_unprepare_clks(dev);
407         return ret;
408 }
409
410 #ifdef CONFIG_PM_SLEEP
411 static int ci_hdrc_imx_suspend(struct device *dev)
412 {
413         int ret;
414
415         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
416
417         if (data->in_lpm)
418                 /* The core's suspend doesn't run */
419                 return 0;
420
421         if (device_may_wakeup(dev)) {
422                 ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
423                 if (ret) {
424                         dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n",
425                                         ret);
426                         return ret;
427                 }
428         }
429
430         return imx_controller_suspend(dev);
431 }
432
433 static int ci_hdrc_imx_resume(struct device *dev)
434 {
435         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
436         int ret;
437
438         ret = imx_controller_resume(dev);
439         if (!ret && data->supports_runtime_pm) {
440                 pm_runtime_disable(dev);
441                 pm_runtime_set_active(dev);
442                 pm_runtime_enable(dev);
443         }
444
445         return ret;
446 }
447 #endif /* CONFIG_PM_SLEEP */
448
449 static int ci_hdrc_imx_runtime_suspend(struct device *dev)
450 {
451         struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
452         int ret;
453
454         if (data->in_lpm) {
455                 WARN_ON(1);
456                 return 0;
457         }
458
459         ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
460         if (ret) {
461                 dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
462                 return ret;
463         }
464
465         return imx_controller_suspend(dev);
466 }
467
468 static int ci_hdrc_imx_runtime_resume(struct device *dev)
469 {
470         return imx_controller_resume(dev);
471 }
472
473 #endif /* CONFIG_PM */
474
475 static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
476         SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume)
477         SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend,
478                         ci_hdrc_imx_runtime_resume, NULL)
479 };
480 static struct platform_driver ci_hdrc_imx_driver = {
481         .probe = ci_hdrc_imx_probe,
482         .remove = ci_hdrc_imx_remove,
483         .shutdown = ci_hdrc_imx_shutdown,
484         .driver = {
485                 .name = "imx_usb",
486                 .of_match_table = ci_hdrc_imx_dt_ids,
487                 .pm = &ci_hdrc_imx_pm_ops,
488          },
489 };
490
491 module_platform_driver(ci_hdrc_imx_driver);
492
493 MODULE_ALIAS("platform:imx-usb");
494 MODULE_LICENSE("GPL v2");
495 MODULE_DESCRIPTION("CI HDRC i.MX USB binding");
496 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
497 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");