1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
2 | /* |
3 | * platform.c - DesignWare HS OTG Controller platform driver |
4 | * |
5 | * Copyright (C) Matthijs Kooijman <matthijs@stdin.nl> |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/clk.h> |
12 | #include <linux/device.h> |
13 | #include <linux/dma-mapping.h> |
14 | #include <linux/of.h> |
15 | #include <linux/mutex.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/phy/phy.h> |
18 | #include <linux/platform_data/s3c-hsotg.h> |
19 | #include <linux/reset.h> |
20 | |
21 | #include <linux/usb/of.h> |
22 | |
23 | #include "core.h" |
24 | #include "hcd.h" |
25 | #include "debug.h" |
26 | |
27 | static const char dwc2_driver_name[] = "dwc2" ; |
28 | |
29 | /* |
30 | * Check the dr_mode against the module configuration and hardware |
31 | * capabilities. |
32 | * |
33 | * The hardware, module, and dr_mode, can each be set to host, device, |
34 | * or otg. Check that all these values are compatible and adjust the |
35 | * value of dr_mode if possible. |
36 | * |
37 | * actual |
38 | * HW MOD dr_mode dr_mode |
39 | * ------------------------------ |
40 | * HST HST any : HST |
41 | * HST DEV any : --- |
42 | * HST OTG any : HST |
43 | * |
44 | * DEV HST any : --- |
45 | * DEV DEV any : DEV |
46 | * DEV OTG any : DEV |
47 | * |
48 | * OTG HST any : HST |
49 | * OTG DEV any : DEV |
50 | * OTG OTG any : dr_mode |
51 | */ |
52 | static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg) |
53 | { |
54 | enum usb_dr_mode mode; |
55 | |
56 | hsotg->dr_mode = usb_get_dr_mode(dev: hsotg->dev); |
57 | if (hsotg->dr_mode == USB_DR_MODE_UNKNOWN) |
58 | hsotg->dr_mode = USB_DR_MODE_OTG; |
59 | |
60 | mode = hsotg->dr_mode; |
61 | |
62 | if (dwc2_hw_is_device(hsotg)) { |
63 | if (IS_ENABLED(CONFIG_USB_DWC2_HOST)) { |
64 | dev_err(hsotg->dev, |
65 | "Controller does not support host mode.\n" ); |
66 | return -EINVAL; |
67 | } |
68 | mode = USB_DR_MODE_PERIPHERAL; |
69 | } else if (dwc2_hw_is_host(hsotg)) { |
70 | if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL)) { |
71 | dev_err(hsotg->dev, |
72 | "Controller does not support device mode.\n" ); |
73 | return -EINVAL; |
74 | } |
75 | mode = USB_DR_MODE_HOST; |
76 | } else { |
77 | if (IS_ENABLED(CONFIG_USB_DWC2_HOST)) |
78 | mode = USB_DR_MODE_HOST; |
79 | else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL)) |
80 | mode = USB_DR_MODE_PERIPHERAL; |
81 | } |
82 | |
83 | if (mode != hsotg->dr_mode) { |
84 | dev_warn(hsotg->dev, |
85 | "Configuration mismatch. dr_mode forced to %s\n" , |
86 | mode == USB_DR_MODE_HOST ? "host" : "device" ); |
87 | |
88 | hsotg->dr_mode = mode; |
89 | } |
90 | |
91 | return 0; |
92 | } |
93 | |
94 | static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) |
95 | { |
96 | struct platform_device *pdev = to_platform_device(hsotg->dev); |
97 | int ret; |
98 | |
99 | ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), |
100 | consumers: hsotg->supplies); |
101 | if (ret) |
102 | return ret; |
103 | |
104 | if (hsotg->utmi_clk) { |
105 | ret = clk_prepare_enable(clk: hsotg->utmi_clk); |
106 | if (ret) |
107 | goto err_dis_reg; |
108 | } |
109 | |
110 | if (hsotg->clk) { |
111 | ret = clk_prepare_enable(clk: hsotg->clk); |
112 | if (ret) |
113 | goto err_dis_utmi_clk; |
114 | } |
115 | |
116 | if (hsotg->uphy) { |
117 | ret = usb_phy_init(x: hsotg->uphy); |
118 | } else if (hsotg->plat && hsotg->plat->phy_init) { |
119 | ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); |
120 | } else { |
121 | ret = phy_init(phy: hsotg->phy); |
122 | if (ret == 0) { |
123 | ret = phy_power_on(phy: hsotg->phy); |
124 | if (ret) |
125 | phy_exit(phy: hsotg->phy); |
126 | } |
127 | } |
128 | |
129 | if (ret) |
130 | goto err_dis_clk; |
131 | |
132 | return 0; |
133 | |
134 | err_dis_clk: |
135 | if (hsotg->clk) |
136 | clk_disable_unprepare(clk: hsotg->clk); |
137 | |
138 | err_dis_utmi_clk: |
139 | if (hsotg->utmi_clk) |
140 | clk_disable_unprepare(clk: hsotg->utmi_clk); |
141 | |
142 | err_dis_reg: |
143 | regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), consumers: hsotg->supplies); |
144 | |
145 | return ret; |
146 | } |
147 | |
148 | /** |
149 | * dwc2_lowlevel_hw_enable - enable platform lowlevel hw resources |
150 | * @hsotg: The driver state |
151 | * |
152 | * A wrapper for platform code responsible for controlling |
153 | * low-level USB platform resources (phy, clock, regulators) |
154 | */ |
155 | int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) |
156 | { |
157 | int ret = __dwc2_lowlevel_hw_enable(hsotg); |
158 | |
159 | if (ret == 0) |
160 | hsotg->ll_hw_enabled = true; |
161 | return ret; |
162 | } |
163 | |
164 | static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) |
165 | { |
166 | struct platform_device *pdev = to_platform_device(hsotg->dev); |
167 | int ret = 0; |
168 | |
169 | if (hsotg->uphy) { |
170 | usb_phy_shutdown(x: hsotg->uphy); |
171 | } else if (hsotg->plat && hsotg->plat->phy_exit) { |
172 | ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); |
173 | } else { |
174 | ret = phy_power_off(phy: hsotg->phy); |
175 | if (ret == 0) |
176 | ret = phy_exit(phy: hsotg->phy); |
177 | } |
178 | if (ret) |
179 | return ret; |
180 | |
181 | if (hsotg->clk) |
182 | clk_disable_unprepare(clk: hsotg->clk); |
183 | |
184 | if (hsotg->utmi_clk) |
185 | clk_disable_unprepare(clk: hsotg->utmi_clk); |
186 | |
187 | return regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), consumers: hsotg->supplies); |
188 | } |
189 | |
190 | /** |
191 | * dwc2_lowlevel_hw_disable - disable platform lowlevel hw resources |
192 | * @hsotg: The driver state |
193 | * |
194 | * A wrapper for platform code responsible for controlling |
195 | * low-level USB platform resources (phy, clock, regulators) |
196 | */ |
197 | int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) |
198 | { |
199 | int ret = __dwc2_lowlevel_hw_disable(hsotg); |
200 | |
201 | if (ret == 0) |
202 | hsotg->ll_hw_enabled = false; |
203 | return ret; |
204 | } |
205 | |
206 | static void dwc2_reset_control_assert(void *data) |
207 | { |
208 | reset_control_assert(rstc: data); |
209 | } |
210 | |
211 | static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) |
212 | { |
213 | int i, ret; |
214 | |
215 | hsotg->reset = devm_reset_control_get_optional(dev: hsotg->dev, id: "dwc2" ); |
216 | if (IS_ERR(ptr: hsotg->reset)) |
217 | return dev_err_probe(dev: hsotg->dev, err: PTR_ERR(ptr: hsotg->reset), |
218 | fmt: "error getting reset control\n" ); |
219 | |
220 | reset_control_deassert(rstc: hsotg->reset); |
221 | ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, |
222 | hsotg->reset); |
223 | if (ret) |
224 | return ret; |
225 | |
226 | hsotg->reset_ecc = devm_reset_control_get_optional(dev: hsotg->dev, id: "dwc2-ecc" ); |
227 | if (IS_ERR(ptr: hsotg->reset_ecc)) |
228 | return dev_err_probe(dev: hsotg->dev, err: PTR_ERR(ptr: hsotg->reset_ecc), |
229 | fmt: "error getting reset control for ecc\n" ); |
230 | |
231 | reset_control_deassert(rstc: hsotg->reset_ecc); |
232 | ret = devm_add_action_or_reset(hsotg->dev, dwc2_reset_control_assert, |
233 | hsotg->reset_ecc); |
234 | if (ret) |
235 | return ret; |
236 | |
237 | /* |
238 | * Attempt to find a generic PHY, then look for an old style |
239 | * USB PHY and then fall back to pdata |
240 | */ |
241 | hsotg->phy = devm_phy_get(dev: hsotg->dev, string: "usb2-phy" ); |
242 | if (IS_ERR(ptr: hsotg->phy)) { |
243 | ret = PTR_ERR(ptr: hsotg->phy); |
244 | switch (ret) { |
245 | case -ENODEV: |
246 | case -ENOSYS: |
247 | hsotg->phy = NULL; |
248 | break; |
249 | default: |
250 | return dev_err_probe(dev: hsotg->dev, err: ret, fmt: "error getting phy\n" ); |
251 | } |
252 | } |
253 | |
254 | if (!hsotg->phy) { |
255 | hsotg->uphy = devm_usb_get_phy(dev: hsotg->dev, type: USB_PHY_TYPE_USB2); |
256 | if (IS_ERR(ptr: hsotg->uphy)) { |
257 | ret = PTR_ERR(ptr: hsotg->uphy); |
258 | switch (ret) { |
259 | case -ENODEV: |
260 | case -ENXIO: |
261 | hsotg->uphy = NULL; |
262 | break; |
263 | default: |
264 | return dev_err_probe(dev: hsotg->dev, err: ret, fmt: "error getting usb phy\n" ); |
265 | } |
266 | } |
267 | } |
268 | |
269 | hsotg->plat = dev_get_platdata(dev: hsotg->dev); |
270 | |
271 | /* Clock */ |
272 | hsotg->clk = devm_clk_get_optional(dev: hsotg->dev, id: "otg" ); |
273 | if (IS_ERR(ptr: hsotg->clk)) |
274 | return dev_err_probe(dev: hsotg->dev, err: PTR_ERR(ptr: hsotg->clk), fmt: "cannot get otg clock\n" ); |
275 | |
276 | hsotg->utmi_clk = devm_clk_get_optional(dev: hsotg->dev, id: "utmi" ); |
277 | if (IS_ERR(ptr: hsotg->utmi_clk)) |
278 | return dev_err_probe(dev: hsotg->dev, err: PTR_ERR(ptr: hsotg->utmi_clk), |
279 | fmt: "cannot get utmi clock\n" ); |
280 | |
281 | /* Regulators */ |
282 | for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) |
283 | hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i]; |
284 | |
285 | ret = devm_regulator_bulk_get(dev: hsotg->dev, ARRAY_SIZE(hsotg->supplies), |
286 | consumers: hsotg->supplies); |
287 | if (ret) |
288 | return dev_err_probe(dev: hsotg->dev, err: ret, fmt: "failed to request supplies\n" ); |
289 | |
290 | return 0; |
291 | } |
292 | |
293 | /** |
294 | * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the |
295 | * DWC_otg driver |
296 | * |
297 | * @dev: Platform device |
298 | * |
299 | * This routine is called, for example, when the rmmod command is executed. The |
300 | * device may or may not be electrically present. If it is present, the driver |
301 | * stops device processing. Any resources used on behalf of this device are |
302 | * freed. |
303 | */ |
304 | static void dwc2_driver_remove(struct platform_device *dev) |
305 | { |
306 | struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev: dev); |
307 | struct dwc2_gregs_backup *gr; |
308 | int ret = 0; |
309 | |
310 | gr = &hsotg->gr_backup; |
311 | |
312 | /* Exit Hibernation when driver is removed. */ |
313 | if (hsotg->hibernated) { |
314 | if (gr->gotgctl & GOTGCTL_CURMODE_HOST) |
315 | ret = dwc2_exit_hibernation(hsotg, rem_wakeup: 0, reset: 0, is_host: 1); |
316 | else |
317 | ret = dwc2_exit_hibernation(hsotg, rem_wakeup: 0, reset: 0, is_host: 0); |
318 | |
319 | if (ret) |
320 | dev_err(hsotg->dev, |
321 | "exit hibernation failed.\n" ); |
322 | } |
323 | |
324 | /* Exit Partial Power Down when driver is removed. */ |
325 | if (hsotg->in_ppd) { |
326 | ret = dwc2_exit_partial_power_down(hsotg, rem_wakeup: 0, restore: true); |
327 | if (ret) |
328 | dev_err(hsotg->dev, |
329 | "exit partial_power_down failed\n" ); |
330 | } |
331 | |
332 | /* Exit clock gating when driver is removed. */ |
333 | if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && |
334 | hsotg->bus_suspended) { |
335 | if (dwc2_is_device_mode(hsotg)) |
336 | dwc2_gadget_exit_clock_gating(hsotg, rem_wakeup: 0); |
337 | else |
338 | dwc2_host_exit_clock_gating(hsotg, rem_wakeup: 0); |
339 | } |
340 | |
341 | dwc2_debugfs_exit(hsotg); |
342 | if (hsotg->hcd_enabled) |
343 | dwc2_hcd_remove(hsotg); |
344 | if (hsotg->gadget_enabled) |
345 | dwc2_hsotg_remove(hsotg); |
346 | |
347 | dwc2_drd_exit(hsotg); |
348 | |
349 | if (hsotg->params.activate_stm_id_vb_detection) |
350 | regulator_disable(regulator: hsotg->usb33d); |
351 | |
352 | if (hsotg->ll_hw_enabled) |
353 | dwc2_lowlevel_hw_disable(hsotg); |
354 | } |
355 | |
356 | /** |
357 | * dwc2_driver_shutdown() - Called on device shutdown |
358 | * |
359 | * @dev: Platform device |
360 | * |
361 | * In specific conditions (involving usb hubs) dwc2 devices can create a |
362 | * lot of interrupts, even to the point of overwhelming devices running |
363 | * at low frequencies. Some devices need to do special clock handling |
364 | * at shutdown-time which may bring the system clock below the threshold |
365 | * of being able to handle the dwc2 interrupts. Disabling dwc2-irqs |
366 | * prevents reboots/poweroffs from getting stuck in such cases. |
367 | */ |
368 | static void dwc2_driver_shutdown(struct platform_device *dev) |
369 | { |
370 | struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev: dev); |
371 | |
372 | dwc2_disable_global_interrupts(hcd: hsotg); |
373 | synchronize_irq(irq: hsotg->irq); |
374 | } |
375 | |
376 | /** |
377 | * dwc2_check_core_endianness() - Returns true if core and AHB have |
378 | * opposite endianness. |
379 | * @hsotg: Programming view of the DWC_otg controller. |
380 | */ |
381 | static bool dwc2_check_core_endianness(struct dwc2_hsotg *hsotg) |
382 | { |
383 | u32 snpsid; |
384 | |
385 | snpsid = ioread32(hsotg->regs + GSNPSID); |
386 | if ((snpsid & GSNPSID_ID_MASK) == DWC2_OTG_ID || |
387 | (snpsid & GSNPSID_ID_MASK) == DWC2_FS_IOT_ID || |
388 | (snpsid & GSNPSID_ID_MASK) == DWC2_HS_IOT_ID) |
389 | return false; |
390 | return true; |
391 | } |
392 | |
393 | /** |
394 | * dwc2_check_core_version() - Check core version |
395 | * |
396 | * @hsotg: Programming view of the DWC_otg controller |
397 | * |
398 | */ |
399 | int dwc2_check_core_version(struct dwc2_hsotg *hsotg) |
400 | { |
401 | struct dwc2_hw_params *hw = &hsotg->hw_params; |
402 | |
403 | /* |
404 | * Attempt to ensure this device is really a DWC_otg Controller. |
405 | * Read and verify the GSNPSID register contents. The value should be |
406 | * 0x45f4xxxx, 0x5531xxxx or 0x5532xxxx |
407 | */ |
408 | |
409 | hw->snpsid = dwc2_readl(hsotg, GSNPSID); |
410 | if ((hw->snpsid & GSNPSID_ID_MASK) != DWC2_OTG_ID && |
411 | (hw->snpsid & GSNPSID_ID_MASK) != DWC2_FS_IOT_ID && |
412 | (hw->snpsid & GSNPSID_ID_MASK) != DWC2_HS_IOT_ID) { |
413 | dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n" , |
414 | hw->snpsid); |
415 | return -ENODEV; |
416 | } |
417 | |
418 | dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x (snpsid=%x)\n" , |
419 | hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf, |
420 | hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid); |
421 | return 0; |
422 | } |
423 | |
424 | /** |
425 | * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg |
426 | * driver |
427 | * |
428 | * @dev: Platform device |
429 | * |
430 | * This routine creates the driver components required to control the device |
431 | * (core, HCD, and PCD) and initializes the device. The driver components are |
432 | * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved |
433 | * in the device private data. This allows the driver to access the dwc2_hsotg |
434 | * structure on subsequent calls to driver methods for this device. |
435 | */ |
436 | static int dwc2_driver_probe(struct platform_device *dev) |
437 | { |
438 | struct dwc2_hsotg *hsotg; |
439 | struct resource *res; |
440 | int retval; |
441 | |
442 | hsotg = devm_kzalloc(dev: &dev->dev, size: sizeof(*hsotg), GFP_KERNEL); |
443 | if (!hsotg) |
444 | return -ENOMEM; |
445 | |
446 | hsotg->dev = &dev->dev; |
447 | |
448 | /* |
449 | * Use reasonable defaults so platforms don't have to provide these. |
450 | */ |
451 | if (!dev->dev.dma_mask) |
452 | dev->dev.dma_mask = &dev->dev.coherent_dma_mask; |
453 | retval = dma_set_coherent_mask(dev: &dev->dev, DMA_BIT_MASK(32)); |
454 | if (retval) { |
455 | dev_err(&dev->dev, "can't set coherent DMA mask: %d\n" , retval); |
456 | return retval; |
457 | } |
458 | |
459 | hsotg->regs = devm_platform_get_and_ioremap_resource(pdev: dev, index: 0, res: &res); |
460 | if (IS_ERR(ptr: hsotg->regs)) |
461 | return PTR_ERR(ptr: hsotg->regs); |
462 | |
463 | dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n" , |
464 | (unsigned long)res->start, hsotg->regs); |
465 | |
466 | retval = dwc2_lowlevel_hw_init(hsotg); |
467 | if (retval) |
468 | return retval; |
469 | |
470 | spin_lock_init(&hsotg->lock); |
471 | |
472 | hsotg->irq = platform_get_irq(dev, 0); |
473 | if (hsotg->irq < 0) |
474 | return hsotg->irq; |
475 | |
476 | dev_dbg(hsotg->dev, "registering common handler for irq%d\n" , |
477 | hsotg->irq); |
478 | retval = devm_request_irq(dev: hsotg->dev, irq: hsotg->irq, |
479 | handler: dwc2_handle_common_intr, IRQF_SHARED, |
480 | devname: dev_name(dev: hsotg->dev), dev_id: hsotg); |
481 | if (retval) |
482 | return retval; |
483 | |
484 | hsotg->vbus_supply = devm_regulator_get_optional(dev: hsotg->dev, id: "vbus" ); |
485 | if (IS_ERR(ptr: hsotg->vbus_supply)) { |
486 | retval = PTR_ERR(ptr: hsotg->vbus_supply); |
487 | hsotg->vbus_supply = NULL; |
488 | if (retval != -ENODEV) |
489 | return retval; |
490 | } |
491 | |
492 | retval = dwc2_lowlevel_hw_enable(hsotg); |
493 | if (retval) |
494 | return retval; |
495 | |
496 | hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg); |
497 | |
498 | retval = dwc2_get_dr_mode(hsotg); |
499 | if (retval) |
500 | goto error; |
501 | |
502 | hsotg->need_phy_for_wake = |
503 | of_property_read_bool(np: dev->dev.of_node, |
504 | propname: "snps,need-phy-for-wake" ); |
505 | |
506 | /* |
507 | * Before performing any core related operations |
508 | * check core version. |
509 | */ |
510 | retval = dwc2_check_core_version(hsotg); |
511 | if (retval) |
512 | goto error; |
513 | |
514 | /* |
515 | * Reset before dwc2_get_hwparams() then it could get power-on real |
516 | * reset value form registers. |
517 | */ |
518 | retval = dwc2_core_reset(hsotg, skip_wait: false); |
519 | if (retval) |
520 | goto error; |
521 | |
522 | /* Detect config values from hardware */ |
523 | retval = dwc2_get_hwparams(hsotg); |
524 | if (retval) |
525 | goto error; |
526 | |
527 | /* |
528 | * For OTG cores, set the force mode bits to reflect the value |
529 | * of dr_mode. Force mode bits should not be touched at any |
530 | * other time after this. |
531 | */ |
532 | dwc2_force_dr_mode(hsotg); |
533 | |
534 | retval = dwc2_init_params(hsotg); |
535 | if (retval) |
536 | goto error; |
537 | |
538 | if (hsotg->params.activate_stm_id_vb_detection) { |
539 | u32 ggpio; |
540 | |
541 | hsotg->usb33d = devm_regulator_get(dev: hsotg->dev, id: "usb33d" ); |
542 | if (IS_ERR(ptr: hsotg->usb33d)) { |
543 | retval = PTR_ERR(ptr: hsotg->usb33d); |
544 | dev_err_probe(dev: hsotg->dev, err: retval, fmt: "failed to request usb33d supply\n" ); |
545 | goto error; |
546 | } |
547 | retval = regulator_enable(regulator: hsotg->usb33d); |
548 | if (retval) { |
549 | dev_err_probe(dev: hsotg->dev, err: retval, fmt: "failed to enable usb33d supply\n" ); |
550 | goto error; |
551 | } |
552 | |
553 | ggpio = dwc2_readl(hsotg, GGPIO); |
554 | ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; |
555 | ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; |
556 | dwc2_writel(hsotg, value: ggpio, GGPIO); |
557 | |
558 | /* ID/VBUS detection startup time */ |
559 | usleep_range(min: 5000, max: 7000); |
560 | } |
561 | |
562 | retval = dwc2_drd_init(hsotg); |
563 | if (retval) { |
564 | dev_err_probe(dev: hsotg->dev, err: retval, fmt: "failed to initialize dual-role\n" ); |
565 | goto error_init; |
566 | } |
567 | |
568 | if (hsotg->dr_mode != USB_DR_MODE_HOST) { |
569 | retval = dwc2_gadget_init(hsotg); |
570 | if (retval) |
571 | goto error_drd; |
572 | hsotg->gadget_enabled = 1; |
573 | } |
574 | |
575 | /* |
576 | * If we need PHY for wakeup we must be wakeup capable. |
577 | * When we have a device that can wake without the PHY we |
578 | * can adjust this condition. |
579 | */ |
580 | if (hsotg->need_phy_for_wake) |
581 | device_set_wakeup_capable(dev: &dev->dev, capable: true); |
582 | |
583 | hsotg->reset_phy_on_wake = |
584 | of_property_read_bool(np: dev->dev.of_node, |
585 | propname: "snps,reset-phy-on-wake" ); |
586 | if (hsotg->reset_phy_on_wake && !hsotg->phy) { |
587 | dev_warn(hsotg->dev, |
588 | "Quirk reset-phy-on-wake only supports generic PHYs\n" ); |
589 | hsotg->reset_phy_on_wake = false; |
590 | } |
591 | |
592 | if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { |
593 | retval = dwc2_hcd_init(hsotg); |
594 | if (retval) { |
595 | if (hsotg->gadget_enabled) |
596 | dwc2_hsotg_remove(hsotg); |
597 | goto error_drd; |
598 | } |
599 | hsotg->hcd_enabled = 1; |
600 | } |
601 | |
602 | platform_set_drvdata(pdev: dev, data: hsotg); |
603 | hsotg->hibernated = 0; |
604 | |
605 | dwc2_debugfs_init(hsotg); |
606 | |
607 | /* Gadget code manages lowlevel hw on its own */ |
608 | if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) |
609 | dwc2_lowlevel_hw_disable(hsotg); |
610 | |
611 | #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ |
612 | IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) |
613 | /* Postponed adding a new gadget to the udc class driver list */ |
614 | if (hsotg->gadget_enabled) { |
615 | retval = usb_add_gadget_udc(parent: hsotg->dev, gadget: &hsotg->gadget); |
616 | if (retval) { |
617 | hsotg->gadget.udc = NULL; |
618 | dwc2_hsotg_remove(hsotg); |
619 | goto error_debugfs; |
620 | } |
621 | } |
622 | #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ |
623 | return 0; |
624 | |
625 | #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ |
626 | IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) |
627 | error_debugfs: |
628 | dwc2_debugfs_exit(hsotg); |
629 | if (hsotg->hcd_enabled) |
630 | dwc2_hcd_remove(hsotg); |
631 | #endif |
632 | error_drd: |
633 | dwc2_drd_exit(hsotg); |
634 | |
635 | error_init: |
636 | if (hsotg->params.activate_stm_id_vb_detection) |
637 | regulator_disable(regulator: hsotg->usb33d); |
638 | error: |
639 | if (hsotg->ll_hw_enabled) |
640 | dwc2_lowlevel_hw_disable(hsotg); |
641 | return retval; |
642 | } |
643 | |
644 | static int __maybe_unused dwc2_suspend(struct device *dev) |
645 | { |
646 | struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); |
647 | bool is_device_mode = dwc2_is_device_mode(hsotg: dwc2); |
648 | int ret = 0; |
649 | |
650 | if (is_device_mode) |
651 | dwc2_hsotg_suspend(dwc2); |
652 | |
653 | dwc2_drd_suspend(hsotg: dwc2); |
654 | |
655 | if (dwc2->params.activate_stm_id_vb_detection) { |
656 | unsigned long flags; |
657 | u32 ggpio, gotgctl; |
658 | |
659 | /* |
660 | * Need to force the mode to the current mode to avoid Mode |
661 | * Mismatch Interrupt when ID detection will be disabled. |
662 | */ |
663 | dwc2_force_mode(hsotg: dwc2, host: !is_device_mode); |
664 | |
665 | spin_lock_irqsave(&dwc2->lock, flags); |
666 | gotgctl = dwc2_readl(hsotg: dwc2, GOTGCTL); |
667 | /* bypass debounce filter, enable overrides */ |
668 | gotgctl |= GOTGCTL_DBNCE_FLTR_BYPASS; |
669 | gotgctl |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN; |
670 | /* Force A / B session if needed */ |
671 | if (gotgctl & GOTGCTL_ASESVLD) |
672 | gotgctl |= GOTGCTL_AVALOVAL; |
673 | if (gotgctl & GOTGCTL_BSESVLD) |
674 | gotgctl |= GOTGCTL_BVALOVAL; |
675 | dwc2_writel(hsotg: dwc2, value: gotgctl, GOTGCTL); |
676 | spin_unlock_irqrestore(lock: &dwc2->lock, flags); |
677 | |
678 | ggpio = dwc2_readl(hsotg: dwc2, GGPIO); |
679 | ggpio &= ~GGPIO_STM32_OTG_GCCFG_IDEN; |
680 | ggpio &= ~GGPIO_STM32_OTG_GCCFG_VBDEN; |
681 | dwc2_writel(hsotg: dwc2, value: ggpio, GGPIO); |
682 | |
683 | regulator_disable(regulator: dwc2->usb33d); |
684 | } |
685 | |
686 | if (dwc2->ll_hw_enabled && |
687 | (is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) { |
688 | ret = __dwc2_lowlevel_hw_disable(hsotg: dwc2); |
689 | dwc2->phy_off_for_suspend = true; |
690 | } |
691 | |
692 | return ret; |
693 | } |
694 | |
695 | static int __maybe_unused dwc2_resume(struct device *dev) |
696 | { |
697 | struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); |
698 | int ret = 0; |
699 | |
700 | if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) { |
701 | ret = __dwc2_lowlevel_hw_enable(hsotg: dwc2); |
702 | if (ret) |
703 | return ret; |
704 | } |
705 | dwc2->phy_off_for_suspend = false; |
706 | |
707 | if (dwc2->params.activate_stm_id_vb_detection) { |
708 | unsigned long flags; |
709 | u32 ggpio, gotgctl; |
710 | |
711 | ret = regulator_enable(regulator: dwc2->usb33d); |
712 | if (ret) |
713 | return ret; |
714 | |
715 | ggpio = dwc2_readl(hsotg: dwc2, GGPIO); |
716 | ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; |
717 | ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; |
718 | dwc2_writel(hsotg: dwc2, value: ggpio, GGPIO); |
719 | |
720 | /* ID/VBUS detection startup time */ |
721 | usleep_range(min: 5000, max: 7000); |
722 | |
723 | spin_lock_irqsave(&dwc2->lock, flags); |
724 | gotgctl = dwc2_readl(hsotg: dwc2, GOTGCTL); |
725 | gotgctl &= ~GOTGCTL_DBNCE_FLTR_BYPASS; |
726 | gotgctl &= ~(GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | |
727 | GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL); |
728 | dwc2_writel(hsotg: dwc2, value: gotgctl, GOTGCTL); |
729 | spin_unlock_irqrestore(lock: &dwc2->lock, flags); |
730 | } |
731 | |
732 | if (!dwc2->role_sw) { |
733 | /* Need to restore FORCEDEVMODE/FORCEHOSTMODE */ |
734 | dwc2_force_dr_mode(hsotg: dwc2); |
735 | } else { |
736 | dwc2_drd_resume(hsotg: dwc2); |
737 | } |
738 | |
739 | if (dwc2_is_device_mode(hsotg: dwc2)) |
740 | ret = dwc2_hsotg_resume(dwc2); |
741 | |
742 | return ret; |
743 | } |
744 | |
745 | static const struct dev_pm_ops dwc2_dev_pm_ops = { |
746 | SET_SYSTEM_SLEEP_PM_OPS(dwc2_suspend, dwc2_resume) |
747 | }; |
748 | |
749 | static struct platform_driver dwc2_platform_driver = { |
750 | .driver = { |
751 | .name = dwc2_driver_name, |
752 | .of_match_table = dwc2_of_match_table, |
753 | .acpi_match_table = ACPI_PTR(dwc2_acpi_match), |
754 | .pm = &dwc2_dev_pm_ops, |
755 | }, |
756 | .probe = dwc2_driver_probe, |
757 | .remove_new = dwc2_driver_remove, |
758 | .shutdown = dwc2_driver_shutdown, |
759 | }; |
760 | |
761 | module_platform_driver(dwc2_platform_driver); |
762 | |