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