xref: /linux/drivers/usb/dwc3/dwc3-apple.c (revision af0bc3ac9a9e830cb52b718ecb237c4e76a466be)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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