1 /*
2 * drivers/usb/host/ohci-sunxi.c
3 * (C) Copyright 2010-2015
4 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
5 * yangnaitian, 2011-5-24, create this file
6 * javen, 2011-6-26, add suspend and resume
7 * javen, 2011-7-18, move clock and power operations out from driver
8 *
9 * OHCI Driver
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 */
17
18 #include <linux/platform_device.h>
19 #include <linux/signal.h>
20 #include <linux/time.h>
21 #include <linux/timer.h>
22 #include <linux/clk.h>
23 #include <linux/notifier.h>
24 #include <linux/suspend.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/phy/phy.h>
28 #include <linux/usb.h>
29 #include <linux/usb/hcd.h>
30 #include "ohci.h"
31 #include "sunxi-hci.h"
32
33 #define DRIVER_DESC "OHCI SUNXI driver"
34
35 #define SUNXI_OHCI_NAME "sunxi-ohci"
36 static const char ohci_name[] = SUNXI_OHCI_NAME;
37
38 #if IS_ENABLED(CONFIG_USB_SUNXI_OHCI0)
39 #define SUNXI_OHCI0_OF_MATCH "allwinner,sunxi-ohci0"
40 #else
41 #define SUNXI_OHCI0_OF_MATCH "null"
42 #endif
43
44 #if IS_ENABLED(CONFIG_USB_SUNXI_OHCI1)
45 #define SUNXI_OHCI1_OF_MATCH "allwinner,sunxi-ohci1"
46 #else
47 #define SUNXI_OHCI1_OF_MATCH "null"
48 #endif
49
50 #if IS_ENABLED(CONFIG_USB_SUNXI_OHCI2)
51 #define SUNXI_OHCI2_OF_MATCH "allwinner,sunxi-ohci2"
52 #else
53 #define SUNXI_OHCI2_OF_MATCH "null"
54 #endif
55
56 #if IS_ENABLED(CONFIG_USB_SUNXI_OHCI3)
57 #define SUNXI_OHCI3_OF_MATCH "allwinner,sunxi-ohci3"
58 #else
59 #define SUNXI_OHCI3_OF_MATCH "null"
60 #endif
61
62 static struct sunxi_hci_hcd *g_sunxi_ohci[4];
63 static u32 ohci_first_probe[4] = {1, 1, 1, 1};
64 static u32 ohci_enable[4] = {1, 1, 1, 1};
65 static atomic_t ohci_in_standby;
66
67 #if IS_ENABLED(CONFIG_PM)
68 static void sunxi_ohci_resume_work(struct work_struct *work);
69 #endif
70
71 int sunxi_usb_disable_ohci(__u32 usbc_no);
72 int sunxi_usb_enable_ohci(__u32 usbc_no);
73
ohci_enable_show(struct device * dev,struct device_attribute * attr,char * buf)74 static ssize_t ohci_enable_show(struct device *dev,
75 struct device_attribute *attr, char *buf)
76 {
77 struct sunxi_hci_hcd *sunxi_ohci = NULL;
78
79 if (dev == NULL) {
80 DMSG_PANIC("ERR: Argment is invalid\n");
81 return 0;
82 }
83
84 sunxi_ohci = dev->platform_data;
85 if (sunxi_ohci == NULL) {
86 DMSG_PANIC("ERR: sw_ohci is null\n");
87 return 0;
88 }
89
90 return sprintf(buf, "ohci:%d,probe:%u\n",
91 sunxi_ohci->usbc_no, sunxi_ohci->probe);
92 }
93
ohci_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)94 static ssize_t ohci_enable_store(struct device *dev,
95 struct device_attribute *attr,
96 const char *buf, size_t count)
97 {
98 struct sunxi_hci_hcd *sunxi_ohci = NULL;
99 int value = 0;
100 int err;
101
102 if (dev == NULL) {
103 DMSG_PANIC("ERR: Argment is invalid\n");
104 return 0;
105 }
106
107 sunxi_ohci = dev->platform_data;
108 if (sunxi_ohci == NULL) {
109 DMSG_PANIC("ERR: sw_ohci is null\n");
110 return 0;
111 }
112
113 ohci_first_probe[sunxi_ohci->usbc_no] = 0;
114
115 err = kstrtoint(buf, 10, &value);
116 if (err != 0)
117 return -EINVAL;
118 if (value == 1) {
119 ohci_enable[sunxi_ohci->usbc_no] = 0;
120 sunxi_usb_enable_ohci(sunxi_ohci->usbc_no);
121
122 if (sunxi_ohci->usbc_no == HCI0_USBC_NO)
123 sunxi_set_host_vbus(sunxi_ohci, 1);
124
125 } else if (value == 0) {
126 ohci_enable[sunxi_ohci->usbc_no] = 1;
127 sunxi_usb_disable_ohci(sunxi_ohci->usbc_no);
128 ohci_enable[sunxi_ohci->usbc_no] = 0;
129 } else {
130 DMSG_INFO("unknown value (%d)\n", value);
131 }
132
133 return count;
134 }
135
136 static DEVICE_ATTR(ohci_enable, 0644, ohci_enable_show, ohci_enable_store);
137
open_ohci_clock(struct sunxi_hci_hcd * sunxi_ohci)138 static int open_ohci_clock(struct sunxi_hci_hcd *sunxi_ohci)
139 {
140 return sunxi_ohci->open_clock(sunxi_ohci, 1);
141 }
142
close_ohci_clock(struct sunxi_hci_hcd * sunxi_ohci)143 static int close_ohci_clock(struct sunxi_hci_hcd *sunxi_ohci)
144 {
145 return sunxi_ohci->close_clock(sunxi_ohci, 1);
146 }
147
sunxi_ohci_set_vbus(struct sunxi_hci_hcd * sunxi_ohci,int is_on)148 static void sunxi_ohci_set_vbus(struct sunxi_hci_hcd *sunxi_ohci, int is_on)
149 {
150 sunxi_ohci->set_power(sunxi_ohci, is_on);
151 }
152
sunxi_ohci_set_passby(struct sunxi_hci_hcd * sunxi_ohci,int is_on)153 static void sunxi_ohci_set_passby(struct sunxi_hci_hcd *sunxi_ohci, int is_on)
154 {
155 sunxi_ohci->usb_passby(sunxi_ohci, is_on);
156 }
157
sunxi_start_ohci(struct sunxi_hci_hcd * sunxi_ohci)158 static void sunxi_start_ohci(struct sunxi_hci_hcd *sunxi_ohci)
159 {
160 open_ohci_clock(sunxi_ohci);
161 sunxi_ohci_set_passby(sunxi_ohci, 1);
162 sunxi_ohci_set_vbus(sunxi_ohci, 1);
163 }
164
sunxi_stop_ohci(struct sunxi_hci_hcd * sunxi_ohci)165 static void sunxi_stop_ohci(struct sunxi_hci_hcd *sunxi_ohci)
166 {
167 sunxi_ohci_set_vbus(sunxi_ohci, 0);
168 sunxi_ohci_set_passby(sunxi_ohci, 0);
169 close_ohci_clock(sunxi_ohci);
170 }
171
sunxi_ohci_pm_notify(struct notifier_block * nb,unsigned long mode,void * _unused)172 static int sunxi_ohci_pm_notify(struct notifier_block *nb,
173 unsigned long mode, void *_unused)
174 {
175 switch (mode) {
176 case PM_HIBERNATION_PREPARE:
177 case PM_RESTORE_PREPARE:
178 case PM_SUSPEND_PREPARE:
179 atomic_set(&ohci_in_standby, 1);
180 break;
181 case PM_POST_HIBERNATION:
182 case PM_POST_RESTORE:
183 case PM_POST_SUSPEND:
184 atomic_set(&ohci_in_standby, 0);
185 sunxi_hci_standby_completion(SUNXI_USB_OHCI);
186 break;
187 default:
188 break;
189 }
190
191 return 0;
192 }
193
194 static struct notifier_block sunxi_ohci_pm_nb = {
195 .notifier_call = sunxi_ohci_pm_notify,
196 };
197
198 static struct hc_driver sunxi_ohci_hc_driver;
199
sunxi_insmod_ohci(struct platform_device * pdev)200 static int sunxi_insmod_ohci(struct platform_device *pdev)
201 {
202 int ret;
203 struct usb_hcd *hcd = NULL;
204 struct sunxi_hci_hcd *sunxi_ohci = NULL;
205 struct device *dev = NULL;
206
207 if (pdev == NULL) {
208 DMSG_PANIC("ERR: Argment is invaild\n");
209 return -1;
210 }
211
212 /* if usb is disabled, can not probe */
213 if (usb_disabled()) {
214 DMSG_PANIC("ERR: usb hcd is disabled\n");
215 return -ENODEV;
216 }
217
218 sunxi_ohci = pdev->dev.platform_data;
219 if (!sunxi_ohci) {
220 DMSG_PANIC("ERR: sunxi_ohci is null\n");
221 ret = -ENOMEM;
222 goto ERR1;
223 }
224
225 sunxi_ohci->pdev = pdev;
226 g_sunxi_ohci[sunxi_ohci->usbc_no] = sunxi_ohci;
227
228 DMSG_INFO("[%s%d]: probe, pdev->name: %s, sunxi_ohci: 0x%px\n",
229 ohci_name, sunxi_ohci->usbc_no, pdev->name, sunxi_ohci);
230
231 sunxi_ohci->ohci_base = sunxi_ohci->usb_vbase +
232 SUNXI_USB_OHCI_BASE_OFFSET;
233
234 sunxi_ohci->ohci_reg_length = SUNXI_USB_OHCI_LEN;
235
236 /* not init ohci, when driver probe */
237 if (sunxi_ohci->usbc_no == HCI0_USBC_NO) {
238 if (sunxi_ohci->port_type != USB_PORT_TYPE_HOST) {
239 if (ohci_first_probe[sunxi_ohci->usbc_no]) {
240 ohci_first_probe[sunxi_ohci->usbc_no] = 0;
241 DMSG_INFO("[%s%d]: Not init ohci0\n",
242 ohci_name, sunxi_ohci->usbc_no);
243 return 0;
244 }
245 }
246 }
247
248 /* creat a usb_hcd for the ohci controller */
249 hcd = usb_create_hcd(&sunxi_ohci_hc_driver, &pdev->dev, ohci_name);
250 if (!hcd) {
251 DMSG_PANIC("ERR: usb_ohci_create_hcd failed\n");
252 ret = -ENOMEM;
253 goto ERR2;
254 }
255
256 hcd->rsrc_start = sunxi_ohci->usb_base_res->start;
257 hcd->rsrc_len = SUNXI_USB_OHCI_LEN;
258 hcd->regs = sunxi_ohci->ohci_base;
259 sunxi_ohci->hcd = hcd;
260
261 dev = &pdev->dev;
262 sunxi_ohci->supply = regulator_get(dev, "drvvbus");
263
264 if (IS_ERR(sunxi_ohci->supply)) {
265 DMSG_PANIC("%s()%d WARN: get supply failed\n", __func__, __LINE__);
266 sunxi_ohci->supply = NULL;
267 }
268
269 sunxi_ohci->hci_regulator = regulator_get(dev, "hci");
270 if (IS_ERR(sunxi_ohci->hci_regulator)) {
271 DMSG_PANIC("%s()%d WARN: get hci regulator failed\n", __func__, __LINE__);
272 sunxi_ohci->hci_regulator = NULL;
273 }
274 /* ochi start to work */
275 sunxi_start_ohci(sunxi_ohci);
276
277 ret = usb_add_hcd(hcd, sunxi_ohci->irq_no, IRQF_SHARED);
278 if (ret != 0) {
279 DMSG_PANIC("ERR: usb_add_hcd failed\n");
280 ret = -ENOMEM;
281 goto ERR3;
282 }
283
284 device_wakeup_enable(hcd->self.controller);
285 platform_set_drvdata(pdev, hcd);
286
287 #ifndef USB_SYNC_SUSPEND
288 device_enable_async_suspend(&pdev->dev);
289 #endif
290
291 #if IS_ENABLED(CONFIG_PM)
292 if (!sunxi_ohci->wakeup_suspend)
293 INIT_WORK(&sunxi_ohci->resume_work, sunxi_ohci_resume_work);
294 #endif
295
296 sunxi_ohci->probe = 1;
297
298 return 0;
299
300 ERR3:
301 sunxi_stop_ohci(sunxi_ohci);
302 usb_put_hcd(hcd);
303
304 ERR2:
305 sunxi_ohci->hcd = NULL;
306
307 ERR1:
308 return ret;
309 }
310
sunxi_rmmod_ohci(struct platform_device * pdev)311 static int sunxi_rmmod_ohci(struct platform_device *pdev)
312 {
313 struct usb_hcd *hcd = NULL;
314 struct sunxi_hci_hcd *sunxi_ohci = NULL;
315 unsigned long time_left;
316
317 if (pdev == NULL) {
318 DMSG_PANIC("ERR: Argment is invalid\n");
319 return -1;
320 }
321
322 hcd = platform_get_drvdata(pdev);
323 if (hcd == NULL) {
324 DMSG_PANIC("ERR: hcd is null\n");
325 return -1;
326 }
327
328 sunxi_ohci = pdev->dev.platform_data;
329 if (sunxi_ohci == NULL) {
330 DMSG_PANIC("ERR: sunxi_ohci is null\n");
331 return -1;
332 }
333
334 if (atomic_read(&ohci_in_standby)) {
335 reinit_completion(&sunxi_ohci->standby_complete);
336 DMSG_INFO("INFO: sunxi_ohci disable, waiting until standby finish\n");
337 time_left = wait_for_completion_timeout(&sunxi_ohci->standby_complete,
338 msecs_to_jiffies(STANDBY_TIMEOUT));
339 if (time_left)
340 DMSG_INFO("INFO: sunxi_ohci disable time_left = %lu\n", time_left);
341 else
342 DMSG_PANIC("ERR: sunxi_ohci waiting standby failed, go on disable\n");
343
344 }
345
346 sunxi_ohci->probe = 0;
347
348 #ifndef USB_SYNC_SUSPEND
349 device_disable_async_suspend(&pdev->dev);
350 #endif
351
352 device_wakeup_disable(hcd->self.controller);
353
354 DMSG_INFO("[%s%d]: remove, pdev->name: %s, sunxi_ohci: 0x%px\n",
355 ohci_name, sunxi_ohci->usbc_no, pdev->name, sunxi_ohci);
356 usb_remove_hcd(hcd);
357
358 #if IS_ENABLED(CONFIG_PM)
359 if (!sunxi_ohci->wakeup_suspend)
360 if (!IS_ERR_OR_NULL(&sunxi_ohci->resume_work))
361 cancel_work_sync(&sunxi_ohci->resume_work);
362 #endif
363
364 sunxi_stop_ohci(sunxi_ohci);
365
366 usb_put_hcd(hcd);
367
368 if (sunxi_ohci->supply)
369 regulator_put(sunxi_ohci->supply);
370
371 sunxi_ohci->hcd = NULL;
372
373 return 0;
374 }
375
sunxi_ohci_hcd_probe(struct platform_device * pdev)376 static int sunxi_ohci_hcd_probe(struct platform_device *pdev)
377 {
378 int ret = 0;
379 #if defined(CONFIG_ARCH_SUN50IW10)
380 int val = 0;
381 #endif
382 struct sunxi_hci_hcd *sunxi_ohci = NULL;
383
384 if (pdev == NULL) {
385 DMSG_PANIC("ERR: %s, Argment is invalid\n", __func__);
386 return -1;
387 }
388
389 /* if usb is disabled, can not probe */
390 if (usb_disabled()) {
391 DMSG_PANIC("ERR: usb hcd is disabled\n");
392 return -ENODEV;
393 }
394
395 ret = init_sunxi_hci(pdev, SUNXI_USB_OHCI);
396 if (ret != 0) {
397 dev_err(&pdev->dev, "init_sunxi_hci is fail\n");
398 return -1;
399 }
400
401 sunxi_insmod_ohci(pdev);
402
403 sunxi_ohci = pdev->dev.platform_data;
404 if (sunxi_ohci == NULL) {
405 DMSG_PANIC("ERR: %s, sunxi_ohci is null\n", __func__);
406 return -1;
407 }
408
409 if (sunxi_ohci->usbc_no == HCI0_USBC_NO) {
410 ret = register_pm_notifier(&sunxi_ohci_pm_nb);
411 if (ret) {
412 DMSG_PANIC("ERR: %s, can not register suspend notifier\n", __func__);
413 return -1;
414 }
415 }
416
417 init_completion(&sunxi_ohci->standby_complete);
418
419 /* keep common circuit configuration when usb0 enable only*/
420 #if defined(CONFIG_ARCH_SUN50IW10)
421 if (sunxi_ohci->usbc_no == HCI0_USBC_NO) {
422 val = readl(sunxi_ohci->usb_ccmu_config + 0x0A8C);
423 val |= (SUNXI_CCMU_USBEHCI1_GATING_OFFSET
424 | SUNXI_CCMU_USBEHCI1_RST_OFFSET);
425 writel(val, sunxi_ohci->usb_ccmu_config + 0x0A8C);
426
427 val = readl(sunxi_ohci->usb_ccmu_config + 0x0A74);
428 val |= (SUNXI_CCMU_SCLK_GATING_USBPHY1_OFFSET
429 | SUNXI_CCMU_USBPHY1_RST_OFFSET
430 | SUNXI_CCMU_SCLK_GATING_OHCI1_OFFSET);
431 writel(val, sunxi_ohci->usb_ccmu_config + 0x0A74);
432
433 /*phy reg, offset:0x10 bit3 set 0, enable siddq*/
434 val = USBC_Readl(sunxi_ohci->usb_common_phy_config
435 + SUNXI_HCI_PHY_CTRL);
436 val &= ~(0x1 << SUNXI_HCI_PHY_CTRL_SIDDQ);
437 USBC_Writel(val, sunxi_ohci->usb_common_phy_config
438 + SUNXI_HCI_PHY_CTRL);
439 }
440 #endif
441
442 if (ohci_enable[sunxi_ohci->usbc_no]) {
443 device_create_file(&pdev->dev, &dev_attr_ohci_enable);
444 ohci_enable[sunxi_ohci->usbc_no] = 0;
445 }
446
447 return 0;
448 }
449
sunxi_ohci_hcd_remove(struct platform_device * pdev)450 static int sunxi_ohci_hcd_remove(struct platform_device *pdev)
451 {
452 struct sunxi_hci_hcd *sunxi_ohci = NULL;
453 int ret = 0;
454 #if defined(CONFIG_ARCH_SUN50IW10)
455 int val = 0;
456 #endif
457
458 if (pdev == NULL) {
459 DMSG_PANIC("ERR: %s, Argment is invalid\n", __func__);
460 return -1;
461 }
462
463 sunxi_ohci = pdev->dev.platform_data;
464 if (sunxi_ohci == NULL) {
465 DMSG_PANIC("ERR: %s, sunxi_ohci is null\n", __func__);
466 return -1;
467 }
468
469 if (ohci_enable[sunxi_ohci->usbc_no] == 0)
470 device_remove_file(&pdev->dev, &dev_attr_ohci_enable);
471
472 /* reset common circuit configuration*/
473 #if defined(CONFIG_ARCH_SUN50IW10)
474 if (sunxi_ohci->usbc_no == HCI0_USBC_NO) {
475 val = readl(sunxi_ohci->usb_ccmu_config + 0x0A8C);
476 val &= ~(SUNXI_CCMU_USBEHCI1_GATING_OFFSET
477 | SUNXI_CCMU_USBEHCI1_RST_OFFSET);
478 writel(val, sunxi_ohci->usb_ccmu_config + 0x0A8C);
479
480 val = readl(sunxi_ohci->usb_ccmu_config + 0x0A74);
481 val &= ~(SUNXI_CCMU_SCLK_GATING_USBPHY1_OFFSET
482 | SUNXI_CCMU_USBPHY1_RST_OFFSET
483 | SUNXI_CCMU_SCLK_GATING_OHCI1_OFFSET);
484 writel(val, sunxi_ohci->usb_ccmu_config + 0x0A74);
485
486 /*phy reg, offset:0x10 bit3 set 0, enable siddq*/
487 val = USBC_Readl(sunxi_ohci->usb_common_phy_config
488 + SUNXI_HCI_PHY_CTRL);
489 val |= (0x1 << SUNXI_HCI_PHY_CTRL_SIDDQ);
490 USBC_Writel(val, sunxi_ohci->usb_common_phy_config
491 + SUNXI_HCI_PHY_CTRL);
492 }
493 #endif
494
495 if (sunxi_ohci->usbc_no == HCI0_USBC_NO)
496 unregister_pm_notifier(&sunxi_ohci_pm_nb);
497
498 if (sunxi_ohci->probe == 1) {
499 ret = sunxi_rmmod_ohci(pdev);
500 if (ret == 0)
501 exit_sunxi_hci(sunxi_ohci);
502
503
504 return ret;
505 } else
506 return 0;
507 }
508
sunxi_ohci_hcd_shutdown(struct platform_device * pdev)509 static void sunxi_ohci_hcd_shutdown(struct platform_device *pdev)
510 {
511 struct sunxi_hci_hcd *sunxi_ohci = NULL;
512
513 sunxi_ohci = pdev->dev.platform_data;
514 if (sunxi_ohci == NULL) {
515 DMSG_PANIC("ERR: %s sunxi_ohci is null\n", __func__);
516 return;
517 }
518
519 if (sunxi_ohci->probe == 0) {
520 DMSG_INFO("%s, %s is disable, need not shutdown\n",
521 __func__, sunxi_ohci->hci_name);
522 return;
523 }
524
525 DMSG_INFO("[%s]: ohci shutdown start\n", sunxi_ohci->hci_name);
526
527 usb_hcd_platform_shutdown(pdev);
528
529 /**
530 * disable usb otg INTUSBE, to solve usb0 device mode
531 * catch audio udev on reboot system is fail.
532 */
533 if (sunxi_ohci->usbc_no == 0) {
534 if (sunxi_ohci->otg_vbase) {
535 writel(0, (sunxi_ohci->otg_vbase
536 + SUNXI_USBC_REG_INTUSBE));
537 }
538 }
539 sunxi_ohci_set_vbus(sunxi_ohci, 0);
540 DMSG_INFO("[%s]: ohci shutdown end\n", sunxi_ohci->hci_name);
541 }
542
543 #if IS_ENABLED(CONFIG_PM)
544
sunxi_ohci_hcd_suspend(struct device * dev)545 static int sunxi_ohci_hcd_suspend(struct device *dev)
546 {
547 struct sunxi_hci_hcd *sunxi_ohci = NULL;
548 struct usb_hcd *hcd = NULL;
549 struct ohci_hcd *ohci = NULL;
550 int val = 0;
551
552 if (dev == NULL) {
553 DMSG_PANIC("ERR: Argment is invalid\n");
554 return 0;
555 }
556
557 hcd = dev_get_drvdata(dev);
558 if (hcd == NULL) {
559 DMSG_PANIC("ERR: hcd is null\n");
560 return 0;
561 }
562
563 sunxi_ohci = dev->platform_data;
564 if (sunxi_ohci == NULL) {
565 DMSG_PANIC("ERR: sunxi_ohci is null\n");
566 return 0;
567 }
568
569 if (sunxi_ohci->no_suspend) {
570 DMSG_INFO("[%s]:ohci is being enable, stop system suspend\n",
571 sunxi_ohci->hci_name);
572 return -1;
573 }
574
575 if (sunxi_ohci->probe == 0) {
576 DMSG_INFO("[%s]: is disable, can not suspend\n",
577 sunxi_ohci->hci_name);
578 return 0;
579 }
580
581 ohci = hcd_to_ohci(hcd);
582 if (ohci == NULL) {
583 DMSG_PANIC("ERR: ohci is null\n");
584 return 0;
585 }
586
587 if (sunxi_ohci->wakeup_suspend == USB_STANDBY) {
588 DMSG_INFO("[%s] usb suspend\n", sunxi_ohci->hci_name);
589 disable_irq(sunxi_ohci->irq_no);
590 val = ohci_readl(ohci, &ohci->regs->control);
591 val |= OHCI_CTRL_RWE;
592 ohci_writel(ohci, val, &ohci->regs->control);
593
594 val = ohci_readl(ohci, &ohci->regs->intrenable);
595 val |= OHCI_INTR_RD;
596 val |= OHCI_INTR_MIE;
597 ohci_writel(ohci, val, &ohci->regs->intrenable);
598
599 #if IS_ENABLED(SUNXI_USB_STANDBY_LOW_POW_MODE)
600 val = ohci_readl(ohci, &ohci->regs->control);
601 val |= OHCI_USB_SUSPEND;
602 ohci_writel(ohci, val, &ohci->regs->control);
603 #endif
604 enter_usb_standby(sunxi_ohci);
605
606 if (sunxi_ohci->clk_usbohci12m && sunxi_ohci->clk_losc)
607 clk_set_parent(sunxi_ohci->clk_usbohci12m,
608 sunxi_ohci->clk_losc);
609 } else {
610 DMSG_INFO("[%s]super suspend\n", sunxi_ohci->hci_name);
611
612 /**
613 * Root hub was already suspended. Disable irq emission and
614 * mark HW unaccessible, bail out if RH has been resumed. Use
615 * the spinlock to properly synchronize with possible pending
616 * RH suspend or resume activity.
617 *
618 * This is still racy as hcd->state is manipulated outside of
619 * any locks =P But that will be a different fix.
620 */
621 ohci_suspend(hcd, device_may_wakeup(dev));
622
623 cancel_work_sync(&sunxi_ohci->resume_work);
624 sunxi_stop_ohci(sunxi_ohci);
625
626 }
627
628 return 0;
629 }
630
sunxi_ohci_resume_work(struct work_struct * work)631 static void sunxi_ohci_resume_work(struct work_struct *work)
632 {
633 struct sunxi_hci_hcd *sunxi_ohci = NULL;
634
635 sunxi_ohci = container_of(work, struct sunxi_hci_hcd, resume_work);
636
637 sunxi_ohci_set_vbus(sunxi_ohci, 1);
638 }
639
sunxi_ohci_hcd_resume(struct device * dev)640 static int sunxi_ohci_hcd_resume(struct device *dev)
641 {
642 struct sunxi_hci_hcd *sunxi_ohci = NULL;
643 struct usb_hcd *hcd = NULL;
644 struct ohci_hcd *ohci = NULL;
645 int __maybe_unused val = 0;
646
647 if (dev == NULL) {
648 DMSG_PANIC("ERR: Argment is invalid\n");
649 return 0;
650 }
651
652 hcd = dev_get_drvdata(dev);
653 if (hcd == NULL) {
654 DMSG_PANIC("ERR: hcd is null\n");
655 return 0;
656 }
657
658 sunxi_ohci = dev->platform_data;
659 if (sunxi_ohci == NULL) {
660 DMSG_PANIC("ERR: sunxi_ohci is null\n");
661 return 0;
662 }
663
664 if (sunxi_ohci->probe == 0) {
665 DMSG_INFO("[%s]: is disable, can not resume\n",
666 sunxi_ohci->hci_name);
667 return 0;
668 }
669
670 ohci = hcd_to_ohci(hcd);
671 if (ohci == NULL) {
672 DMSG_PANIC("ERR: ohci is null\n");
673 return 0;
674 }
675
676 if (sunxi_ohci->wakeup_suspend == USB_STANDBY) {
677 DMSG_INFO("[%s]usb resume\n", sunxi_ohci->hci_name);
678
679 if (sunxi_ohci->clk_usbohci12m && sunxi_ohci->clk_hoscx2)
680 clk_set_parent(sunxi_ohci->clk_usbohci12m,
681 sunxi_ohci->clk_hoscx2);
682
683 exit_usb_standby(sunxi_ohci);
684 #if IS_ENABLED(SUNXI_USB_STANDBY_LOW_POW_MODE)
685 val = ohci_readl(ohci, &ohci->regs->control);
686 val &= ~(OHCI_USB_SUSPEND);
687 val |= OHCI_USB_RESUME;
688 ohci_writel(ohci, val, &ohci->regs->control);
689 #endif
690 enable_irq(sunxi_ohci->irq_no);
691 } else {
692 DMSG_INFO("[%s]super resume\n", sunxi_ohci->hci_name);
693 open_ohci_clock(sunxi_ohci);
694 sunxi_ohci_set_passby(sunxi_ohci, 1);
695 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
696 ohci_resume(hcd, false);
697
698 #if defined(CONFIG_ARCH_SUN50IW10)
699 if (sunxi_ohci->usbc_no == HCI0_USBC_NO) {
700 /*phy reg, offset:0x10 bit3 set 0, enable siddq*/
701 val = USBC_Readl(sunxi_ohci->usb_common_phy_config
702 + SUNXI_HCI_PHY_CTRL);
703 val &= ~(0x1 << SUNXI_HCI_PHY_CTRL_SIDDQ);
704 USBC_Writel(val, sunxi_ohci->usb_common_phy_config
705 + SUNXI_HCI_PHY_CTRL);
706 }
707 #endif
708
709 schedule_work(&sunxi_ohci->resume_work);
710 }
711
712 return 0;
713 }
714
715 static const struct dev_pm_ops sunxi_ohci_pmops = {
716 .suspend = sunxi_ohci_hcd_suspend,
717 .resume = sunxi_ohci_hcd_resume,
718 };
719
720 #define SUNXI_OHCI_PMOPS (&sunxi_ohci_pmops)
721
722 #else
723
724 #define SUNXI_OHCI_PMOPS NULL
725
726 #endif
727
728 static const struct of_device_id sunxi_ohci_match[] = {
729 {.compatible = SUNXI_OHCI0_OF_MATCH, },
730 {.compatible = SUNXI_OHCI1_OF_MATCH, },
731 {.compatible = SUNXI_OHCI2_OF_MATCH, },
732 {.compatible = SUNXI_OHCI3_OF_MATCH, },
733 {},
734 };
735 MODULE_DEVICE_TABLE(of, sunxi_ohci_match);
736
737
738 static struct platform_driver sunxi_ohci_hcd_driver = {
739 .probe = sunxi_ohci_hcd_probe,
740 .remove = sunxi_ohci_hcd_remove,
741 .shutdown = sunxi_ohci_hcd_shutdown,
742 .driver = {
743 .name = ohci_name,
744 .owner = THIS_MODULE,
745 .pm = SUNXI_OHCI_PMOPS,
746 .of_match_table = sunxi_ohci_match,
747 },
748 };
749
sunxi_usb_disable_ohci(__u32 usbc_no)750 int sunxi_usb_disable_ohci(__u32 usbc_no)
751 {
752 struct sunxi_hci_hcd *sunxi_ohci = NULL;
753
754 sunxi_ohci = g_sunxi_ohci[usbc_no];
755 if (sunxi_ohci == NULL) {
756 DMSG_PANIC("ERR: sunxi_ohci is null\n");
757 return -1;
758 }
759
760 if (sunxi_ohci->probe == 0) {
761 DMSG_PANIC("ERR: sunxi_ohci is disable, can not disable again\n");
762 return -1;
763 }
764
765 sunxi_ohci->probe = 0;
766
767 DMSG_INFO("[%s]: sunxi_usb_disable_ohci\n", sunxi_ohci->hci_name);
768
769 sunxi_rmmod_ohci(sunxi_ohci->pdev);
770
771 return 0;
772 }
773 EXPORT_SYMBOL(sunxi_usb_disable_ohci);
774
sunxi_usb_enable_ohci(__u32 usbc_no)775 int sunxi_usb_enable_ohci(__u32 usbc_no)
776 {
777 struct sunxi_hci_hcd *sunxi_ohci = NULL;
778 #if defined(CONFIG_ARCH_SUN50IW10)
779 int val;
780 #endif
781
782 sunxi_ohci = g_sunxi_ohci[usbc_no];
783 if (sunxi_ohci == NULL) {
784 DMSG_PANIC("ERR: sunxi_ohci is null\n");
785 return -1;
786 }
787
788 if (sunxi_ohci->probe == 1) {
789 DMSG_PANIC("ERR: sunxi_ohci is already enable, can not enable again\n");
790 return -1;
791 }
792
793 sunxi_ohci->no_suspend = 1;
794
795 DMSG_INFO("[%s]: sunxi_usb_enable_ohci\n", sunxi_ohci->hci_name);
796
797 #if defined(CONFIG_ARCH_SUN50IW10)
798 if (sunxi_ohci->usbc_no == HCI0_USBC_NO) {
799 /*phy reg, offset:0x10 bit3 set 0, enable siddq*/
800 val = USBC_Readl(sunxi_ohci->usb_common_phy_config
801 + SUNXI_HCI_PHY_CTRL);
802 val &= ~(0x1 << SUNXI_HCI_PHY_CTRL_SIDDQ);
803 USBC_Writel(val, sunxi_ohci->usb_common_phy_config
804 + SUNXI_HCI_PHY_CTRL);
805 }
806 #endif
807
808 sunxi_insmod_ohci(sunxi_ohci->pdev);
809
810 sunxi_ohci->no_suspend = 0;
811
812 return 0;
813 }
814 EXPORT_SYMBOL(sunxi_usb_enable_ohci);
815
sunxi_ohci_hcd_init(void)816 static int __init sunxi_ohci_hcd_init(void)
817 {
818 if (usb_disabled()) {
819 DMSG_ERR(KERN_ERR "%s nousb\n", ohci_name);
820 return -ENODEV;
821 }
822
823 DMSG_INFO(KERN_INFO "%s: " DRIVER_DESC "\n", ohci_name);
824 ohci_init_driver(&sunxi_ohci_hc_driver, NULL);
825 return platform_driver_register(&sunxi_ohci_hcd_driver);
826 }
827 module_init(sunxi_ohci_hcd_init);
828
sunxi_ohci_hcd_cleanup(void)829 static void __exit sunxi_ohci_hcd_cleanup(void)
830 {
831 platform_driver_unregister(&sunxi_ohci_hcd_driver);
832 }
833 module_exit(sunxi_ohci_hcd_cleanup);
834
835 MODULE_DESCRIPTION(DRIVER_DESC);
836 MODULE_LICENSE("GPL v2");
837 MODULE_ALIAS("platform:" SUNXI_OHCI_NAME);
838 MODULE_AUTHOR("javen");
839 MODULE_VERSION("1.0.9");
840