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