1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Apple Silicon DWC3 Glue driver
4 * Copyright (C) The Asahi Linux Contributors
5 *
6 * Based on:
7 * - dwc3-qcom.c Copyright (c) 2018, The Linux Foundation. All rights reserved.
8 * - dwc3-of-simple.c Copyright (c) 2015 Texas Instruments Incorporated - https://www.ti.com
9 */
10
11 #include <linux/of.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/platform_device.h>
15 #include <linux/reset.h>
16
17 #include "glue.h"
18
19 /*
20 * This platform requires a very specific sequence of operations to bring up dwc3 and its USB3 PHY:
21 *
22 * 1) The PHY itself has to be brought up; for this we need to know the mode (USB3,
23 * USB3+DisplayPort, USB4, etc) and the lane orientation. This happens through typec_mux_set.
24 * 2) DWC3 has to be brought up but we must not touch the gadget area or start xhci yet.
25 * 3) The PHY bring-up has to be finalized and dwc3's PIPE interface has to be switched to the
26 * USB3 PHY, this is done inside phy_set_mode.
27 * 4) We can now initialize xhci or gadget mode.
28 *
29 * We can switch 1 and 2 but 3 has to happen after (1 and 2) and 4 has to happen after 3.
30 *
31 * And then to bring this all down again:
32 *
33 * 1) DWC3 has to exit host or gadget mode and must no longer touch those registers
34 * 2) The PHY has to switch dwc3's PIPE interface back to the dummy backend
35 * 3) The PHY itself can be shut down, this happens from typec_mux_set
36 *
37 * We also can't transition the PHY from one mode to another while dwc3 is up and running (this is
38 * slightly wrong, some transitions are possible, others aren't but because we have no documentation
39 * for this I'd rather play it safe).
40 *
41 * After both the PHY and dwc3 are initialized we will only ever see a single "new device connected"
42 * event. If we just keep them running only the first device plugged in will ever work. XHCI's port
43 * status register actually does show the correct state but no interrupt ever comes in. In gadget
44 * mode we don't even get a USBDisconnected event and everything looks like there's still something
45 * connected on the other end.
46 * This can be partially explained because the USB2 D+/D- lines are connected through a stateful
47 * eUSB2 repeater which in turn is controlled by a variant of the TI TPS6598x USB PD chip which
48 * resets the repeater out-of-band everytime the CC lines are (dis)connected. This then requires a
49 * PHY reset to make sure the PHY and the eUSB2 repeater state are synchronized again.
50 *
51 * And to make this all extra fun: If we get the order of some of this wrong either the port is just
52 * broken until a phy+dwc3 reset, or it's broken until a full SoC reset (likely because we can't
53 * reset some parts of the PHY), or some watchdog kicks in after a few seconds and forces a full SoC
54 * reset (mostly seen this with USB4/Thunderbolt but there's clearly some watchdog that hates
55 * invalid states).
56 *
57 * Hence there's really no good way to keep dwc3 fully up and running after we disconnect a cable
58 * because then we can't shut down the PHY anymore. And if we kept the PHY running in whatever mode
59 * it was until the next cable is connected we'd need to tear it all down and bring it back up again
60 * anyway to detect and use the next device.
61 *
62 * Instead, we just shut down everything when a cable is disconnected and transition to
63 * DWC3_APPLE_NO_CABLE.
64 * During initial probe we don't have any information about the connected cable and can't bring up
65 * the PHY properly and thus also can't fully bring up dwc3. Instead, we just keep everything off
66 * and defer the first dwc3 probe until we get the first cable connected event. Until then we stay
67 * in DWC3_APPLE_PROBE_PENDING.
68 * Once a cable is connected we then keep track of the controller mode here by transitioning to
69 * DWC3_APPLE_HOST or DWC3_APPLE_DEVICE.
70 */
71 enum dwc3_apple_state {
72 DWC3_APPLE_PROBE_PENDING, /* Before first cable connection, dwc3_core_probe not called */
73 DWC3_APPLE_NO_CABLE, /* No cable connected, dwc3 suspended after dwc3_core_exit */
74 DWC3_APPLE_HOST, /* Cable connected, dwc3 in host mode */
75 DWC3_APPLE_DEVICE, /* Cable connected, dwc3 in device mode */
76 };
77
78 /**
79 * struct dwc3_apple - Apple-specific DWC3 USB controller
80 * @dwc: Core DWC3 structure
81 * @dev: Pointer to the device structure
82 * @mmio_resource: Resource to be passed to dwc3_core_probe
83 * @apple_regs: Apple-specific DWC3 registers
84 * @reset: Reset control
85 * @role_sw: USB role switch
86 * @lock: Mutex for synchronizing access
87 * @state: Current state of the controller, see documentation for the enum for details
88 */
89 struct dwc3_apple {
90 struct dwc3 dwc;
91
92 struct device *dev;
93 struct resource *mmio_resource;
94 void __iomem *apple_regs;
95
96 struct reset_control *reset;
97 struct usb_role_switch *role_sw;
98
99 struct mutex lock;
100
101 enum dwc3_apple_state state;
102 };
103
104 #define to_dwc3_apple(d) container_of((d), struct dwc3_apple, dwc)
105
106 /*
107 * Apple Silicon dwc3 vendor-specific registers
108 *
109 * These registers were identified by tracing XNU's memory access patterns and correlating them with
110 * debug output over serial to determine their names. We don't exactly know what these do but
111 * without these USB3 devices sometimes don't work.
112 */
113 #define APPLE_DWC3_REGS_START 0xcd00
114 #define APPLE_DWC3_REGS_END 0xcdff
115
116 #define APPLE_DWC3_CIO_LFPS_OFFSET 0xcd38
117 #define APPLE_DWC3_CIO_LFPS_OFFSET_VALUE 0xf800f80
118
119 #define APPLE_DWC3_CIO_BW_NGT_OFFSET 0xcd3c
120 #define APPLE_DWC3_CIO_BW_NGT_OFFSET_VALUE 0xfc00fc0
121
122 #define APPLE_DWC3_CIO_LINK_TIMER 0xcd40
123 #define APPLE_DWC3_CIO_PENDING_HP_TIMER GENMASK(23, 16)
124 #define APPLE_DWC3_CIO_PENDING_HP_TIMER_VALUE 0x14
125 #define APPLE_DWC3_CIO_PM_LC_TIMER GENMASK(15, 8)
126 #define APPLE_DWC3_CIO_PM_LC_TIMER_VALUE 0xa
127 #define APPLE_DWC3_CIO_PM_ENTRY_TIMER GENMASK(7, 0)
128 #define APPLE_DWC3_CIO_PM_ENTRY_TIMER_VALUE 0x10
129
dwc3_apple_writel(struct dwc3_apple * appledwc,u32 offset,u32 value)130 static inline void dwc3_apple_writel(struct dwc3_apple *appledwc, u32 offset, u32 value)
131 {
132 writel(value, appledwc->apple_regs + offset - APPLE_DWC3_REGS_START);
133 }
134
dwc3_apple_readl(struct dwc3_apple * appledwc,u32 offset)135 static inline u32 dwc3_apple_readl(struct dwc3_apple *appledwc, u32 offset)
136 {
137 return readl(appledwc->apple_regs + offset - APPLE_DWC3_REGS_START);
138 }
139
dwc3_apple_mask(struct dwc3_apple * appledwc,u32 offset,u32 mask,u32 value)140 static inline void dwc3_apple_mask(struct dwc3_apple *appledwc, u32 offset, u32 mask, u32 value)
141 {
142 u32 reg;
143
144 reg = dwc3_apple_readl(appledwc, offset);
145 reg &= ~mask;
146 reg |= value;
147 dwc3_apple_writel(appledwc, offset, reg);
148 }
149
dwc3_apple_setup_cio(struct dwc3_apple * appledwc)150 static void dwc3_apple_setup_cio(struct dwc3_apple *appledwc)
151 {
152 dwc3_apple_writel(appledwc, APPLE_DWC3_CIO_LFPS_OFFSET, APPLE_DWC3_CIO_LFPS_OFFSET_VALUE);
153 dwc3_apple_writel(appledwc, APPLE_DWC3_CIO_BW_NGT_OFFSET,
154 APPLE_DWC3_CIO_BW_NGT_OFFSET_VALUE);
155 dwc3_apple_mask(appledwc, APPLE_DWC3_CIO_LINK_TIMER, APPLE_DWC3_CIO_PENDING_HP_TIMER,
156 FIELD_PREP(APPLE_DWC3_CIO_PENDING_HP_TIMER,
157 APPLE_DWC3_CIO_PENDING_HP_TIMER_VALUE));
158 dwc3_apple_mask(appledwc, APPLE_DWC3_CIO_LINK_TIMER, APPLE_DWC3_CIO_PM_LC_TIMER,
159 FIELD_PREP(APPLE_DWC3_CIO_PM_LC_TIMER, APPLE_DWC3_CIO_PM_LC_TIMER_VALUE));
160 dwc3_apple_mask(appledwc, APPLE_DWC3_CIO_LINK_TIMER, APPLE_DWC3_CIO_PM_ENTRY_TIMER,
161 FIELD_PREP(APPLE_DWC3_CIO_PM_ENTRY_TIMER,
162 APPLE_DWC3_CIO_PM_ENTRY_TIMER_VALUE));
163 }
164
dwc3_apple_set_ptrcap(struct dwc3_apple * appledwc,u32 mode)165 static void dwc3_apple_set_ptrcap(struct dwc3_apple *appledwc, u32 mode)
166 {
167 guard(spinlock_irqsave)(&appledwc->dwc.lock);
168 dwc3_set_prtcap(&appledwc->dwc, mode, false);
169 }
170
dwc3_apple_core_probe(struct dwc3_apple * appledwc)171 static int dwc3_apple_core_probe(struct dwc3_apple *appledwc)
172 {
173 struct dwc3_probe_data probe_data = {};
174 int ret;
175
176 lockdep_assert_held(&appledwc->lock);
177 WARN_ON_ONCE(appledwc->state != DWC3_APPLE_PROBE_PENDING);
178
179 appledwc->dwc.dev = appledwc->dev;
180 probe_data.dwc = &appledwc->dwc;
181 probe_data.res = appledwc->mmio_resource;
182 probe_data.ignore_clocks_and_resets = true;
183 probe_data.skip_core_init_mode = true;
184 probe_data.properties = DWC3_DEFAULT_PROPERTIES;
185
186 ret = dwc3_core_probe(&probe_data);
187 if (ret)
188 return ret;
189
190 appledwc->state = DWC3_APPLE_NO_CABLE;
191 return 0;
192 }
193
dwc3_apple_core_init(struct dwc3_apple * appledwc)194 static int dwc3_apple_core_init(struct dwc3_apple *appledwc)
195 {
196 int ret;
197
198 lockdep_assert_held(&appledwc->lock);
199
200 switch (appledwc->state) {
201 case DWC3_APPLE_PROBE_PENDING:
202 ret = dwc3_apple_core_probe(appledwc);
203 if (ret)
204 dev_err(appledwc->dev, "Failed to probe DWC3 Core, err=%d\n", ret);
205 break;
206 case DWC3_APPLE_NO_CABLE:
207 ret = dwc3_core_init(&appledwc->dwc);
208 if (ret)
209 dev_err(appledwc->dev, "Failed to initialize DWC3 Core, err=%d\n", ret);
210 break;
211 default:
212 /* Unreachable unless there's a bug in this driver */
213 WARN_ON_ONCE(1);
214 ret = -EINVAL;
215 break;
216 }
217
218 return ret;
219 }
220
dwc3_apple_init(struct dwc3_apple * appledwc,enum dwc3_apple_state state)221 static int dwc3_apple_init(struct dwc3_apple *appledwc, enum dwc3_apple_state state)
222 {
223 int ret, ret_reset;
224
225 lockdep_assert_held(&appledwc->lock);
226
227 /*
228 * The USB2 PHY on this platform must be configured for host or device mode while it is
229 * still powered off and before dwc3 tries to access it. Otherwise, the new configuration
230 * will sometimes only take affect after the *next* time dwc3 is brought up which causes
231 * the connected device to just not work.
232 * The USB3 PHY must be configured later after dwc3 has already been initialized.
233 */
234 switch (state) {
235 case DWC3_APPLE_HOST:
236 phy_set_mode(appledwc->dwc.usb2_generic_phy[0], PHY_MODE_USB_HOST);
237 break;
238 case DWC3_APPLE_DEVICE:
239 phy_set_mode(appledwc->dwc.usb2_generic_phy[0], PHY_MODE_USB_DEVICE);
240 break;
241 default:
242 /* Unreachable unless there's a bug in this driver */
243 return -EINVAL;
244 }
245
246 ret = reset_control_deassert(appledwc->reset);
247 if (ret) {
248 dev_err(appledwc->dev, "Failed to deassert reset, err=%d\n", ret);
249 return ret;
250 }
251
252 ret = dwc3_apple_core_init(appledwc);
253 if (ret)
254 goto reset_assert;
255
256 /*
257 * Now that the core is initialized and already went through dwc3_core_soft_reset we can
258 * configure some unknown Apple-specific settings and then bring up xhci or gadget mode.
259 */
260 dwc3_apple_setup_cio(appledwc);
261
262 switch (state) {
263 case DWC3_APPLE_HOST:
264 appledwc->dwc.dr_mode = USB_DR_MODE_HOST;
265 dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_HOST);
266 /*
267 * This platform requires SUSPHY to be enabled here already in order to properly
268 * configure the PHY and switch dwc3's PIPE interface to USB3 PHY. The USB2 PHY
269 * has already been configured to the correct mode earlier.
270 */
271 dwc3_enable_susphy(&appledwc->dwc, true);
272 phy_set_mode(appledwc->dwc.usb3_generic_phy[0], PHY_MODE_USB_HOST);
273 ret = dwc3_host_init(&appledwc->dwc);
274 if (ret) {
275 dev_err(appledwc->dev, "Failed to initialize host, ret=%d\n", ret);
276 goto core_exit;
277 }
278
279 break;
280 case DWC3_APPLE_DEVICE:
281 appledwc->dwc.dr_mode = USB_DR_MODE_PERIPHERAL;
282 dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_DEVICE);
283 /*
284 * This platform requires SUSPHY to be enabled here already in order to properly
285 * configure the PHY and switch dwc3's PIPE interface to USB3 PHY. The USB2 PHY
286 * has already been configured to the correct mode earlier.
287 */
288 dwc3_enable_susphy(&appledwc->dwc, true);
289 phy_set_mode(appledwc->dwc.usb3_generic_phy[0], PHY_MODE_USB_DEVICE);
290 ret = dwc3_gadget_init(&appledwc->dwc);
291 if (ret) {
292 dev_err(appledwc->dev, "Failed to initialize gadget, ret=%d\n", ret);
293 goto core_exit;
294 }
295 break;
296 default:
297 /* Unreachable unless there's a bug in this driver */
298 WARN_ON_ONCE(1);
299 ret = -EINVAL;
300 goto core_exit;
301 }
302
303 appledwc->state = state;
304 return 0;
305
306 core_exit:
307 dwc3_core_exit(&appledwc->dwc);
308 reset_assert:
309 ret_reset = reset_control_assert(appledwc->reset);
310 if (ret_reset)
311 dev_warn(appledwc->dev, "Failed to assert reset, err=%d\n", ret_reset);
312
313 return ret;
314 }
315
dwc3_apple_exit(struct dwc3_apple * appledwc)316 static int dwc3_apple_exit(struct dwc3_apple *appledwc)
317 {
318 int ret = 0;
319
320 lockdep_assert_held(&appledwc->lock);
321
322 switch (appledwc->state) {
323 case DWC3_APPLE_PROBE_PENDING:
324 case DWC3_APPLE_NO_CABLE:
325 /* Nothing to do if we're already off */
326 return 0;
327 case DWC3_APPLE_DEVICE:
328 dwc3_gadget_exit(&appledwc->dwc);
329 break;
330 case DWC3_APPLE_HOST:
331 dwc3_host_exit(&appledwc->dwc);
332 break;
333 }
334
335 /*
336 * This platform requires SUSPHY to be enabled in order to properly power down the PHY
337 * and switch dwc3's PIPE interface back to a dummy PHY (i.e. no USB3 support and USB2 via
338 * a different PHY connected through ULPI).
339 */
340 dwc3_enable_susphy(&appledwc->dwc, true);
341 dwc3_core_exit(&appledwc->dwc);
342 appledwc->state = DWC3_APPLE_NO_CABLE;
343
344 ret = reset_control_assert(appledwc->reset);
345 if (ret) {
346 dev_err(appledwc->dev, "Failed to assert reset, err=%d\n", ret);
347 return ret;
348 }
349
350 return 0;
351 }
352
dwc3_usb_role_switch_set(struct usb_role_switch * sw,enum usb_role role)353 static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
354 {
355 struct dwc3_apple *appledwc = usb_role_switch_get_drvdata(sw);
356 int ret;
357
358 guard(mutex)(&appledwc->lock);
359
360 /*
361 * Skip role switches if appledwc is already in the desired state. The
362 * USB-C port controller on M2 and M1/M2 Pro/Max/Ultra devices issues
363 * additional interrupts which results in usb_role_switch_set_role()
364 * calls with the current role.
365 * Ignore those calls here to ensure the USB-C port controller and
366 * appledwc are in a consistent state.
367 * This matches the behaviour in __dwc3_set_mode().
368 * Do no handle USB_ROLE_NONE for DWC3_APPLE_NO_CABLE and
369 * DWC3_APPLE_PROBE_PENDING since that is no-op anyway.
370 */
371 if (appledwc->state == DWC3_APPLE_HOST && role == USB_ROLE_HOST)
372 return 0;
373 if (appledwc->state == DWC3_APPLE_DEVICE && role == USB_ROLE_DEVICE)
374 return 0;
375
376 /*
377 * We need to tear all of dwc3 down and re-initialize it every time a cable is
378 * connected or disconnected or when the mode changes. See the documentation for enum
379 * dwc3_apple_state for details.
380 */
381 ret = dwc3_apple_exit(appledwc);
382 if (ret)
383 return ret;
384
385 switch (role) {
386 case USB_ROLE_NONE:
387 /* Nothing to do if no cable is connected */
388 return 0;
389 case USB_ROLE_HOST:
390 return dwc3_apple_init(appledwc, DWC3_APPLE_HOST);
391 case USB_ROLE_DEVICE:
392 return dwc3_apple_init(appledwc, DWC3_APPLE_DEVICE);
393 default:
394 dev_err(appledwc->dev, "Invalid target role: %d\n", role);
395 return -EINVAL;
396 }
397 }
398
dwc3_usb_role_switch_get(struct usb_role_switch * sw)399 static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw)
400 {
401 struct dwc3_apple *appledwc = usb_role_switch_get_drvdata(sw);
402
403 guard(mutex)(&appledwc->lock);
404
405 switch (appledwc->state) {
406 case DWC3_APPLE_HOST:
407 return USB_ROLE_HOST;
408 case DWC3_APPLE_DEVICE:
409 return USB_ROLE_DEVICE;
410 case DWC3_APPLE_NO_CABLE:
411 case DWC3_APPLE_PROBE_PENDING:
412 return USB_ROLE_NONE;
413 default:
414 /* Unreachable unless there's a bug in this driver */
415 dev_err(appledwc->dev, "Invalid internal state: %d\n", appledwc->state);
416 return USB_ROLE_NONE;
417 }
418 }
419
dwc3_apple_setup_role_switch(struct dwc3_apple * appledwc)420 static int dwc3_apple_setup_role_switch(struct dwc3_apple *appledwc)
421 {
422 struct usb_role_switch_desc dwc3_role_switch = { NULL };
423
424 dwc3_role_switch.fwnode = dev_fwnode(appledwc->dev);
425 dwc3_role_switch.set = dwc3_usb_role_switch_set;
426 dwc3_role_switch.get = dwc3_usb_role_switch_get;
427 dwc3_role_switch.driver_data = appledwc;
428 appledwc->role_sw = usb_role_switch_register(appledwc->dev, &dwc3_role_switch);
429 if (IS_ERR(appledwc->role_sw))
430 return PTR_ERR(appledwc->role_sw);
431
432 return 0;
433 }
434
dwc3_apple_probe(struct platform_device * pdev)435 static int dwc3_apple_probe(struct platform_device *pdev)
436 {
437 struct device *dev = &pdev->dev;
438 struct dwc3_apple *appledwc;
439 int ret;
440
441 appledwc = devm_kzalloc(&pdev->dev, sizeof(*appledwc), GFP_KERNEL);
442 if (!appledwc)
443 return -ENOMEM;
444
445 appledwc->dev = &pdev->dev;
446 mutex_init(&appledwc->lock);
447
448 appledwc->reset = devm_reset_control_get_exclusive(dev, NULL);
449 if (IS_ERR(appledwc->reset))
450 return dev_err_probe(&pdev->dev, PTR_ERR(appledwc->reset),
451 "Failed to get reset control\n");
452
453 ret = reset_control_assert(appledwc->reset);
454 if (ret) {
455 dev_err(&pdev->dev, "Failed to assert reset, err=%d\n", ret);
456 return ret;
457 }
458
459 appledwc->mmio_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dwc3-core");
460 if (!appledwc->mmio_resource) {
461 dev_err(dev, "Failed to get DWC3 MMIO\n");
462 return -EINVAL;
463 }
464
465 appledwc->apple_regs = devm_platform_ioremap_resource_byname(pdev, "dwc3-apple");
466 if (IS_ERR(appledwc->apple_regs))
467 return dev_err_probe(dev, PTR_ERR(appledwc->apple_regs),
468 "Failed to map Apple-specific MMIO\n");
469
470 /*
471 * On this platform, DWC3 can only be brought up after parts of the PHY have been
472 * initialized with knowledge of the target mode and cable orientation from typec_set_mux.
473 * Since this has not happened here we cannot setup DWC3 yet and instead defer this until
474 * the first cable is connected. See the documentation for enum dwc3_apple_state for
475 * details.
476 */
477 appledwc->state = DWC3_APPLE_PROBE_PENDING;
478 ret = dwc3_apple_setup_role_switch(appledwc);
479 if (ret)
480 return dev_err_probe(&pdev->dev, ret, "Failed to setup role switch\n");
481
482 return 0;
483 }
484
dwc3_apple_remove(struct platform_device * pdev)485 static void dwc3_apple_remove(struct platform_device *pdev)
486 {
487 struct dwc3 *dwc = platform_get_drvdata(pdev);
488 struct dwc3_apple *appledwc = to_dwc3_apple(dwc);
489
490 guard(mutex)(&appledwc->lock);
491
492 usb_role_switch_unregister(appledwc->role_sw);
493
494 /*
495 * If we're still in DWC3_APPLE_PROBE_PENDING we never got any cable connected event and
496 * dwc3_core_probe was never called and there's hence no need to call dwc3_core_remove.
497 * dwc3_apple_exit can be called unconditionally because it checks the state itself.
498 */
499 dwc3_apple_exit(appledwc);
500 if (appledwc->state != DWC3_APPLE_PROBE_PENDING)
501 dwc3_core_remove(&appledwc->dwc);
502 }
503
504 static const struct of_device_id dwc3_apple_of_match[] = {
505 { .compatible = "apple,t8103-dwc3" },
506 {}
507 };
508 MODULE_DEVICE_TABLE(of, dwc3_apple_of_match);
509
510 static struct platform_driver dwc3_apple_driver = {
511 .probe = dwc3_apple_probe,
512 .remove = dwc3_apple_remove,
513 .driver = {
514 .name = "dwc3-apple",
515 .of_match_table = dwc3_apple_of_match,
516 },
517 };
518
519 module_platform_driver(dwc3_apple_driver);
520
521 MODULE_LICENSE("GPL");
522 MODULE_AUTHOR("Sven Peter <sven@kernel.org>");
523 MODULE_DESCRIPTION("DesignWare DWC3 Apple Silicon Glue Driver");
524