usb: dwc3: rockchip: fix possible circular deadlock
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc3 / dwc3-rockchip-inno.c
1 /**
2  * dwc3-rockchip-inno.c - Rockchip DWC3 Specific Glue layer with INNO PHY
3  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4  *
5  * Authors: William Wu <william.wu@rock-chips.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 of
9  * the License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/slab.h>
20 #include <linux/platform_device.h>
21 #include <linux/dma-mapping.h>
22 #include <linux/clk.h>
23 #include <linux/clk-provider.h>
24 #include <linux/debugfs.h>
25 #include <linux/of.h>
26 #include <linux/of_platform.h>
27 #include <linux/pm_runtime.h>
28 #include <linux/usb.h>
29 #include <linux/usb/hcd.h>
30 #include <linux/notifier.h>
31 #include <linux/uaccess.h>
32 #include <linux/usb/phy.h>
33 #include <linux/usb/ch9.h>
34
35 #include "core.h"
36 #include "../host/xhci.h"
37
38 #define XHCI_TSTCTRL_MASK               (0xf << 28)
39 struct dwc3_rockchip {
40         struct device           *dev;
41         struct clk              **clks;
42         int                     num_clocks;
43         struct dwc3             *dwc;
44         struct dentry           *root;
45         struct usb_phy          *phy;
46         struct notifier_block   u3phy_nb;
47         struct work_struct      u3_work;
48         struct mutex            lock;
49 };
50
51 static int dwc3_rockchip_host_testmode_show(struct seq_file *s, void *unused)
52 {
53         struct dwc3_rockchip    *rockchip = s->private;
54         struct dwc3             *dwc = rockchip->dwc;
55         struct usb_hcd          *hcd  = dev_get_drvdata(&dwc->xhci->dev);
56         struct xhci_hcd         *xhci = hcd_to_xhci(hcd);
57         __le32 __iomem          **port_array;
58         u32                     reg;
59
60         if (rockchip->dwc->dr_mode == USB_DR_MODE_PERIPHERAL) {
61                 dev_warn(rockchip->dev, "USB HOST not support!\n");
62                 return 0;
63         }
64
65         if (hcd->state == HC_STATE_HALT) {
66                 dev_warn(rockchip->dev, "HOST is halted!\n");
67                 return 0;
68         }
69
70         port_array = xhci->usb2_ports;
71         reg = readl(port_array[0] + 1);
72         reg &= XHCI_TSTCTRL_MASK;
73         reg >>= 28;
74
75         switch (reg) {
76         case 0:
77                 seq_puts(s, "U2: no test\n");
78                 break;
79         case TEST_J:
80                 seq_puts(s, "U2: test_j\n");
81                 break;
82         case TEST_K:
83                 seq_puts(s, "U2: test_k\n");
84                 break;
85         case TEST_SE0_NAK:
86                 seq_puts(s, "U2: test_se0_nak\n");
87                 break;
88         case TEST_PACKET:
89                 seq_puts(s, "U2: test_packet\n");
90                 break;
91         case TEST_FORCE_EN:
92                 seq_puts(s, "U2: test_force_enable\n");
93                 break;
94         default:
95                 seq_printf(s, "U2: UNKNOWN %d\n", reg);
96         }
97
98         port_array = xhci->usb3_ports;
99         reg = readl(port_array[0]);
100         reg &= PORT_PLS_MASK;
101         if (reg == USB_SS_PORT_LS_COMP_MOD)
102                 seq_puts(s, "U3: compliance mode\n");
103         else
104                 seq_printf(s, "U3: UNKNOWN %d\n", reg >> 5);
105
106         return 0;
107 }
108
109 static int dwc3_rockchip_host_testmode_open(struct inode *inode,
110                                             struct file *file)
111 {
112         return single_open(file, dwc3_rockchip_host_testmode_show,
113                            inode->i_private);
114 }
115
116 /**
117  * dwc3_rockchip_set_test_mode - Enables USB2/USB3 HOST Test Modes
118  * @rockchip: pointer to our context structure
119  * @mode: the mode to set (U2: J, K SE0 NAK, Test_packet,
120  * Force Enable; U3: Compliance mode)
121  *
122  * This function will return 0 on success or -EINVAL if wrong Test
123  * Selector is passed.
124  */
125 static int dwc3_rockchip_set_test_mode(struct dwc3_rockchip *rockchip,
126                                        u32 mode)
127 {
128         struct dwc3     *dwc = rockchip->dwc;
129         struct usb_hcd  *hcd  = dev_get_drvdata(&dwc->xhci->dev);
130         struct xhci_hcd *xhci = hcd_to_xhci(hcd);
131         __le32 __iomem  **port_array;
132         int             ret;
133         u32             reg;
134
135         if (hcd->state == HC_STATE_HALT) {
136                 dev_err(rockchip->dev, "HOST is halted!\n");
137                 return -EINVAL;
138         }
139
140         switch (mode) {
141         case TEST_J:
142         case TEST_K:
143         case TEST_SE0_NAK:
144         case TEST_PACKET:
145         case TEST_FORCE_EN:
146                 port_array = xhci->usb2_ports;
147                 reg = readl(port_array[0] + 1);
148                 reg &= ~XHCI_TSTCTRL_MASK;
149                 reg |= mode << 28;
150                 writel(reg, port_array[0] + 1);
151                 break;
152         case USB_SS_PORT_LS_COMP_MOD:
153                 /*
154                  * Enable Inno U3 PHY to toggle CP test pattern
155                  * before set XHCI controller enter compliance mode.
156                  */
157                 ret = phy_cp_test(dwc->usb3_generic_phy);
158                 if (ret) {
159                         dev_err(rockchip->dev, "phy cp test fail!\n");
160                         return ret;
161                 }
162
163                 port_array = xhci->usb3_ports;
164                 xhci_set_link_state(xhci, port_array, 0, mode);
165                 break;
166         default:
167                 return -EINVAL;
168         }
169
170         dev_info(rockchip->dev, "set USB HOST test mode successfully!\n");
171
172         return 0;
173 }
174
175 static ssize_t dwc3_rockchip_host_testmode_write(struct file *file,
176                                                  const char __user *ubuf,
177                                                  size_t count, loff_t *ppos)
178 {
179         struct seq_file         *s = file->private_data;
180         struct dwc3_rockchip    *rockchip = s->private;
181         u32                     testmode = 0;
182         char                    buf[32];
183
184         if (rockchip->dwc->dr_mode == USB_DR_MODE_PERIPHERAL) {
185                 dev_warn(rockchip->dev, "USB HOST not support!\n");
186                 return -EINVAL;
187         }
188
189         if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
190                 return -EFAULT;
191
192         if (!strncmp(buf, "test_j", 6)) {
193                 testmode = TEST_J;
194         } else if (!strncmp(buf, "test_k", 6)) {
195                 testmode = TEST_K;
196         } else if (!strncmp(buf, "test_se0_nak", 12)) {
197                 testmode = TEST_SE0_NAK;
198         } else if (!strncmp(buf, "test_packet", 11)) {
199                 testmode = TEST_PACKET;
200         } else if (!strncmp(buf, "test_force_enable", 17)) {
201                 testmode = TEST_FORCE_EN;
202         } else if (!strncmp(buf, "test_u3", 7)) {
203                 testmode = USB_SS_PORT_LS_COMP_MOD;
204         } else {
205                 dev_warn(rockchip->dev, "Test cmd not support!\n");
206                 return -EINVAL;
207         }
208
209         dwc3_rockchip_set_test_mode(rockchip, testmode);
210
211         return count;
212 }
213
214 static const struct file_operations dwc3_host_testmode_fops = {
215         .open                   = dwc3_rockchip_host_testmode_open,
216         .write                  = dwc3_rockchip_host_testmode_write,
217         .read                   = seq_read,
218         .llseek                 = seq_lseek,
219         .release                = single_release,
220 };
221
222 static void dwc3_rockchip_debugfs_init(struct dwc3_rockchip *rockchip)
223 {
224         struct dentry   *root;
225         struct dentry   *file;
226
227         root = debugfs_create_dir(dev_name(rockchip->dev), NULL);
228         if (IS_ERR_OR_NULL(root)) {
229                 if (!root)
230                         dev_err(rockchip->dev, "Can't create debugfs root\n");
231                 return;
232         }
233         rockchip->root = root;
234
235         if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
236             IS_ENABLED(CONFIG_USB_DWC3_HOST)) {
237                 file = debugfs_create_file("host_testmode", S_IRUSR | S_IWUSR,
238                                            root, rockchip,
239                                            &dwc3_host_testmode_fops);
240                 if (!file)
241                         dev_dbg(rockchip->dev, "Can't create debugfs host_testmode\n");
242         }
243 }
244
245 static int u3phy_disconnect_det_notifier(struct notifier_block *nb,
246                                          unsigned long event, void *p)
247 {
248         struct dwc3_rockchip *rockchip =
249                 container_of(nb, struct dwc3_rockchip, u3phy_nb);
250
251         schedule_work(&rockchip->u3_work);
252
253         return NOTIFY_DONE;
254 }
255
256 static void u3phy_disconnect_det_work(struct work_struct *work)
257 {
258         struct dwc3_rockchip *rockchip =
259                 container_of(work, struct dwc3_rockchip, u3_work);
260         struct usb_hcd  *hcd = dev_get_drvdata(&rockchip->dwc->xhci->dev);
261         struct usb_hcd  *shared_hcd = hcd->shared_hcd;
262         struct xhci_hcd *xhci = hcd_to_xhci(hcd);
263         u32             count = 0;
264
265         mutex_lock(&rockchip->lock);
266
267         if (hcd->state != HC_STATE_HALT) {
268                 usb_remove_hcd(shared_hcd);
269                 usb_remove_hcd(hcd);
270         }
271
272         if (rockchip->phy)
273                 usb_phy_shutdown(rockchip->phy);
274
275         while (hcd->state != HC_STATE_HALT) {
276                 if (++count > 1000) {
277                         dev_err(rockchip->dev,
278                                 "wait for HCD remove 1s timeout!\n");
279                         break;
280                 }
281                 usleep_range(1000, 1100);
282         }
283
284         if (hcd->state == HC_STATE_HALT) {
285                 xhci->shared_hcd = shared_hcd;
286                 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
287                 usb_add_hcd(shared_hcd, hcd->irq, IRQF_SHARED);
288         }
289
290         if (rockchip->phy)
291                 usb_phy_init(rockchip->phy);
292
293         mutex_unlock(&rockchip->lock);
294 }
295
296 static int dwc3_rockchip_probe(struct platform_device *pdev)
297 {
298         struct dwc3_rockchip    *rockchip;
299         struct device           *dev = &pdev->dev;
300         struct device_node      *np = dev->of_node, *child;
301         struct platform_device  *child_pdev;
302
303         unsigned int            count;
304         int                     ret;
305         int                     i;
306
307         rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
308         if (!rockchip)
309                 return -ENOMEM;
310
311         child = of_get_child_by_name(np, "dwc3");
312         if (!child) {
313                 dev_err(dev, "failed to find dwc3 core node\n");
314                 return -ENODEV;
315         }
316
317         count = of_clk_get_parent_count(np);
318         if (!count)
319                 return -ENOENT;
320
321         rockchip->num_clocks = count;
322
323         rockchip->clks = devm_kcalloc(dev, rockchip->num_clocks,
324                         sizeof(struct clk *), GFP_KERNEL);
325         if (!rockchip->clks)
326                 return -ENOMEM;
327
328         platform_set_drvdata(pdev, rockchip);
329         rockchip->dev = dev;
330
331         for (i = 0; i < rockchip->num_clocks; i++) {
332                 struct clk      *clk;
333
334                 clk = of_clk_get(np, i);
335                 if (IS_ERR(clk)) {
336                         ret = PTR_ERR(clk);
337                         goto err0;
338                 }
339
340                 ret = clk_prepare_enable(clk);
341                 if (ret < 0) {
342                         clk_put(clk);
343                         goto err0;
344                 }
345
346                 rockchip->clks[i] = clk;
347         }
348
349         pm_runtime_set_active(dev);
350         pm_runtime_enable(dev);
351         ret = pm_runtime_get_sync(dev);
352         if (ret < 0) {
353                 dev_err(dev, "get_sync failed with err %d\n", ret);
354                 goto err1;
355         }
356
357         ret = of_platform_populate(np, NULL, NULL, dev);
358         if (ret)
359                 goto err1;
360
361         child_pdev = of_find_device_by_node(child);
362         if (!child_pdev) {
363                 dev_err(dev, "failed to find dwc3 core device\n");
364                 ret = -ENODEV;
365                 goto err2;
366         }
367
368         rockchip->dwc = platform_get_drvdata(child_pdev);
369         if (!rockchip->dwc || !rockchip->dwc->xhci) {
370                 dev_dbg(dev, "failed to get drvdata dwc3\n");
371                 ret = -EPROBE_DEFER;
372                 goto err2;
373         }
374
375         mutex_init(&rockchip->lock);
376
377         rockchip->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
378         if (rockchip->phy) {
379                 INIT_WORK(&rockchip->u3_work, u3phy_disconnect_det_work);
380                 rockchip->u3phy_nb.notifier_call =
381                         u3phy_disconnect_det_notifier;
382                 usb_register_notifier(rockchip->phy, &rockchip->u3phy_nb);
383         }
384
385         dwc3_rockchip_debugfs_init(rockchip);
386
387         return 0;
388
389 err2:
390         of_platform_depopulate(dev);
391 err1:
392         pm_runtime_put_sync(dev);
393         pm_runtime_disable(dev);
394 err0:
395         for (i = 0; i < rockchip->num_clocks && rockchip->clks[i]; i++) {
396                 if (!pm_runtime_status_suspended(dev))
397                         clk_disable(rockchip->clks[i]);
398                 clk_unprepare(rockchip->clks[i]);
399                 clk_put(rockchip->clks[i]);
400         }
401
402         return ret;
403 }
404
405 static int dwc3_rockchip_remove(struct platform_device *pdev)
406 {
407         struct dwc3_rockchip    *rockchip = platform_get_drvdata(pdev);
408         struct device           *dev = &pdev->dev;
409         int                     i;
410
411         of_platform_depopulate(dev);
412
413         debugfs_remove_recursive(rockchip->root);
414
415         pm_runtime_put_sync(dev);
416         pm_runtime_disable(dev);
417
418         for (i = 0; i < rockchip->num_clocks; i++) {
419                 if (!pm_runtime_status_suspended(dev))
420                         clk_disable(rockchip->clks[i]);
421                 clk_unprepare(rockchip->clks[i]);
422                 clk_put(rockchip->clks[i]);
423         }
424
425         return 0;
426 }
427
428 #ifdef CONFIG_PM
429 static int dwc3_rockchip_runtime_suspend(struct device *dev)
430 {
431         struct dwc3_rockchip    *rockchip = dev_get_drvdata(dev);
432         int                     i;
433
434         for (i = 0; i < rockchip->num_clocks; i++)
435                 clk_disable(rockchip->clks[i]);
436
437         return 0;
438 }
439
440 static int dwc3_rockchip_runtime_resume(struct device *dev)
441 {
442         struct dwc3_rockchip    *rockchip = dev_get_drvdata(dev);
443         int                     ret;
444         int                     i;
445
446         for (i = 0; i < rockchip->num_clocks; i++) {
447                 ret = clk_enable(rockchip->clks[i]);
448                 if (ret < 0) {
449                         while (--i >= 0)
450                                 clk_disable(rockchip->clks[i]);
451                         return ret;
452                 }
453         }
454
455         return 0;
456 }
457
458 static const struct dev_pm_ops dwc3_rockchip_dev_pm_ops = {
459         SET_RUNTIME_PM_OPS(dwc3_rockchip_runtime_suspend,
460                            dwc3_rockchip_runtime_resume, NULL)
461 };
462
463 #define DEV_PM_OPS      (&dwc3_rockchip_dev_pm_ops)
464 #else
465 #define DEV_PM_OPS      NULL
466 #endif /* CONFIG_PM */
467
468 static const struct of_device_id rockchip_dwc3_match[] = {
469         { .compatible = "rockchip,rk3328-dwc3" },
470         { /* Sentinel */ }
471 };
472 MODULE_DEVICE_TABLE(of, rockchip_dwc3_match);
473
474 static struct platform_driver dwc3_rockchip_driver = {
475         .probe          = dwc3_rockchip_probe,
476         .remove         = dwc3_rockchip_remove,
477         .driver         = {
478                 .name   = "rockchip-inno-dwc3",
479                 .pm     = DEV_PM_OPS,
480                 .of_match_table = rockchip_dwc3_match,
481         },
482 };
483
484 module_platform_driver(dwc3_rockchip_driver);
485
486 MODULE_ALIAS("platform:rockchip-inno-dwc3");
487 MODULE_AUTHOR("William Wu <william.wu@rock-chips.com>");
488 MODULE_LICENSE("GPL v2");
489 MODULE_DESCRIPTION("DesignWare USB3 rockchip-inno Glue Layer");