xref: /linux/drivers/usb/dwc3/dwc3-apple.c (revision f5e9d31e79c1ce8ba948ecac74d75e9c8d2f0c87)
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_phy_set_mode(struct dwc3_apple * appledwc,enum phy_mode mode)221 static void dwc3_apple_phy_set_mode(struct dwc3_apple *appledwc, enum phy_mode mode)
222 {
223 	lockdep_assert_held(&appledwc->lock);
224 
225 	/*
226 	 * This platform requires SUSPHY to be enabled here already in order to properly configure
227 	 * the PHY and switch dwc3's PIPE interface to USB3 PHY.
228 	 */
229 	dwc3_enable_susphy(&appledwc->dwc, true);
230 	phy_set_mode(appledwc->dwc.usb2_generic_phy[0], mode);
231 	phy_set_mode(appledwc->dwc.usb3_generic_phy[0], mode);
232 }
233 
dwc3_apple_init(struct dwc3_apple * appledwc,enum dwc3_apple_state state)234 static int dwc3_apple_init(struct dwc3_apple *appledwc, enum dwc3_apple_state state)
235 {
236 	int ret, ret_reset;
237 
238 	lockdep_assert_held(&appledwc->lock);
239 
240 	ret = reset_control_deassert(appledwc->reset);
241 	if (ret) {
242 		dev_err(appledwc->dev, "Failed to deassert reset, err=%d\n", ret);
243 		return ret;
244 	}
245 
246 	ret = dwc3_apple_core_init(appledwc);
247 	if (ret)
248 		goto reset_assert;
249 
250 	/*
251 	 * Now that the core is initialized and already went through dwc3_core_soft_reset we can
252 	 * configure some unknown Apple-specific settings and then bring up xhci or gadget mode.
253 	 */
254 	dwc3_apple_setup_cio(appledwc);
255 
256 	switch (state) {
257 	case DWC3_APPLE_HOST:
258 		appledwc->dwc.dr_mode = USB_DR_MODE_HOST;
259 		dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_HOST);
260 		dwc3_apple_phy_set_mode(appledwc, PHY_MODE_USB_HOST);
261 		ret = dwc3_host_init(&appledwc->dwc);
262 		if (ret) {
263 			dev_err(appledwc->dev, "Failed to initialize host, ret=%d\n", ret);
264 			goto core_exit;
265 		}
266 
267 		break;
268 	case DWC3_APPLE_DEVICE:
269 		appledwc->dwc.dr_mode = USB_DR_MODE_PERIPHERAL;
270 		dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_DEVICE);
271 		dwc3_apple_phy_set_mode(appledwc, PHY_MODE_USB_DEVICE);
272 		ret = dwc3_gadget_init(&appledwc->dwc);
273 		if (ret) {
274 			dev_err(appledwc->dev, "Failed to initialize gadget, ret=%d\n", ret);
275 			goto core_exit;
276 		}
277 		break;
278 	default:
279 		/* Unreachable unless there's a bug in this driver */
280 		WARN_ON_ONCE(1);
281 		ret = -EINVAL;
282 		goto core_exit;
283 	}
284 
285 	appledwc->state = state;
286 	return 0;
287 
288 core_exit:
289 	dwc3_core_exit(&appledwc->dwc);
290 reset_assert:
291 	ret_reset = reset_control_assert(appledwc->reset);
292 	if (ret_reset)
293 		dev_warn(appledwc->dev, "Failed to assert reset, err=%d\n", ret_reset);
294 
295 	return ret;
296 }
297 
dwc3_apple_exit(struct dwc3_apple * appledwc)298 static int dwc3_apple_exit(struct dwc3_apple *appledwc)
299 {
300 	int ret = 0;
301 
302 	lockdep_assert_held(&appledwc->lock);
303 
304 	switch (appledwc->state) {
305 	case DWC3_APPLE_PROBE_PENDING:
306 	case DWC3_APPLE_NO_CABLE:
307 		/* Nothing to do if we're already off */
308 		return 0;
309 	case DWC3_APPLE_DEVICE:
310 		dwc3_gadget_exit(&appledwc->dwc);
311 		break;
312 	case DWC3_APPLE_HOST:
313 		dwc3_host_exit(&appledwc->dwc);
314 		break;
315 	}
316 
317 	/*
318 	 * This platform requires SUSPHY to be enabled in order to properly power down the PHY
319 	 * and switch dwc3's PIPE interface back to a dummy PHY (i.e. no USB3 support and USB2 via
320 	 * a different PHY connected through ULPI).
321 	 */
322 	dwc3_enable_susphy(&appledwc->dwc, true);
323 	dwc3_core_exit(&appledwc->dwc);
324 	appledwc->state = DWC3_APPLE_NO_CABLE;
325 
326 	ret = reset_control_assert(appledwc->reset);
327 	if (ret) {
328 		dev_err(appledwc->dev, "Failed to assert reset, err=%d\n", ret);
329 		return ret;
330 	}
331 
332 	return 0;
333 }
334 
dwc3_usb_role_switch_set(struct usb_role_switch * sw,enum usb_role role)335 static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
336 {
337 	struct dwc3_apple *appledwc = usb_role_switch_get_drvdata(sw);
338 	int ret;
339 
340 	guard(mutex)(&appledwc->lock);
341 
342 	/*
343 	 * We need to tear all of dwc3 down and re-initialize it every time a cable is
344 	 * connected or disconnected or when the mode changes. See the documentation for enum
345 	 * dwc3_apple_state for details.
346 	 */
347 	ret = dwc3_apple_exit(appledwc);
348 	if (ret)
349 		return ret;
350 
351 	switch (role) {
352 	case USB_ROLE_NONE:
353 		/* Nothing to do if no cable is connected */
354 		return 0;
355 	case USB_ROLE_HOST:
356 		return dwc3_apple_init(appledwc, DWC3_APPLE_HOST);
357 	case USB_ROLE_DEVICE:
358 		return dwc3_apple_init(appledwc, DWC3_APPLE_DEVICE);
359 	default:
360 		dev_err(appledwc->dev, "Invalid target role: %d\n", role);
361 		return -EINVAL;
362 	}
363 }
364 
dwc3_usb_role_switch_get(struct usb_role_switch * sw)365 static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw)
366 {
367 	struct dwc3_apple *appledwc = usb_role_switch_get_drvdata(sw);
368 
369 	guard(mutex)(&appledwc->lock);
370 
371 	switch (appledwc->state) {
372 	case DWC3_APPLE_HOST:
373 		return USB_ROLE_HOST;
374 	case DWC3_APPLE_DEVICE:
375 		return USB_ROLE_DEVICE;
376 	case DWC3_APPLE_NO_CABLE:
377 	case DWC3_APPLE_PROBE_PENDING:
378 		return USB_ROLE_NONE;
379 	default:
380 		/* Unreachable unless there's a bug in this driver */
381 		dev_err(appledwc->dev, "Invalid internal state: %d\n", appledwc->state);
382 		return USB_ROLE_NONE;
383 	}
384 }
385 
dwc3_apple_setup_role_switch(struct dwc3_apple * appledwc)386 static int dwc3_apple_setup_role_switch(struct dwc3_apple *appledwc)
387 {
388 	struct usb_role_switch_desc dwc3_role_switch = { NULL };
389 
390 	dwc3_role_switch.fwnode = dev_fwnode(appledwc->dev);
391 	dwc3_role_switch.set = dwc3_usb_role_switch_set;
392 	dwc3_role_switch.get = dwc3_usb_role_switch_get;
393 	dwc3_role_switch.driver_data = appledwc;
394 	appledwc->role_sw = usb_role_switch_register(appledwc->dev, &dwc3_role_switch);
395 	if (IS_ERR(appledwc->role_sw))
396 		return PTR_ERR(appledwc->role_sw);
397 
398 	return 0;
399 }
400 
dwc3_apple_probe(struct platform_device * pdev)401 static int dwc3_apple_probe(struct platform_device *pdev)
402 {
403 	struct device *dev = &pdev->dev;
404 	struct dwc3_apple *appledwc;
405 	int ret;
406 
407 	appledwc = devm_kzalloc(&pdev->dev, sizeof(*appledwc), GFP_KERNEL);
408 	if (!appledwc)
409 		return -ENOMEM;
410 
411 	appledwc->dev = &pdev->dev;
412 	mutex_init(&appledwc->lock);
413 
414 	appledwc->reset = devm_reset_control_get_exclusive(dev, NULL);
415 	if (IS_ERR(appledwc->reset))
416 		return dev_err_probe(&pdev->dev, PTR_ERR(appledwc->reset),
417 				     "Failed to get reset control\n");
418 
419 	ret = reset_control_assert(appledwc->reset);
420 	if (ret) {
421 		dev_err(&pdev->dev, "Failed to assert reset, err=%d\n", ret);
422 		return ret;
423 	}
424 
425 	appledwc->mmio_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dwc3-core");
426 	if (!appledwc->mmio_resource) {
427 		dev_err(dev, "Failed to get DWC3 MMIO\n");
428 		return -EINVAL;
429 	}
430 
431 	appledwc->apple_regs = devm_platform_ioremap_resource_byname(pdev, "dwc3-apple");
432 	if (IS_ERR(appledwc->apple_regs))
433 		return dev_err_probe(dev, PTR_ERR(appledwc->apple_regs),
434 				     "Failed to map Apple-specific MMIO\n");
435 
436 	/*
437 	 * On this platform, DWC3 can only be brought up after parts of the PHY have been
438 	 * initialized with knowledge of the target mode and cable orientation from typec_set_mux.
439 	 * Since this has not happened here we cannot setup DWC3 yet and instead defer this until
440 	 * the first cable is connected. See the documentation for enum dwc3_apple_state for
441 	 * details.
442 	 */
443 	appledwc->state = DWC3_APPLE_PROBE_PENDING;
444 	ret = dwc3_apple_setup_role_switch(appledwc);
445 	if (ret)
446 		return dev_err_probe(&pdev->dev, ret, "Failed to setup role switch\n");
447 
448 	return 0;
449 }
450 
dwc3_apple_remove(struct platform_device * pdev)451 static void dwc3_apple_remove(struct platform_device *pdev)
452 {
453 	struct dwc3 *dwc = platform_get_drvdata(pdev);
454 	struct dwc3_apple *appledwc = to_dwc3_apple(dwc);
455 
456 	guard(mutex)(&appledwc->lock);
457 
458 	usb_role_switch_unregister(appledwc->role_sw);
459 
460 	/*
461 	 * If we're still in DWC3_APPLE_PROBE_PENDING we never got any cable connected event and
462 	 * dwc3_core_probe was never called and there's hence no need to call dwc3_core_remove.
463 	 * dwc3_apple_exit can be called unconditionally because it checks the state itself.
464 	 */
465 	dwc3_apple_exit(appledwc);
466 	if (appledwc->state != DWC3_APPLE_PROBE_PENDING)
467 		dwc3_core_remove(&appledwc->dwc);
468 }
469 
470 static const struct of_device_id dwc3_apple_of_match[] = {
471 	{ .compatible = "apple,t8103-dwc3" },
472 	{}
473 };
474 MODULE_DEVICE_TABLE(of, dwc3_apple_of_match);
475 
476 static struct platform_driver dwc3_apple_driver = {
477 	.probe		= dwc3_apple_probe,
478 	.remove		= dwc3_apple_remove,
479 	.driver		= {
480 		.name	= "dwc3-apple",
481 		.of_match_table	= dwc3_apple_of_match,
482 	},
483 };
484 
485 module_platform_driver(dwc3_apple_driver);
486 
487 MODULE_LICENSE("GPL");
488 MODULE_AUTHOR("Sven Peter <sven@kernel.org>");
489 MODULE_DESCRIPTION("DesignWare DWC3 Apple Silicon Glue Driver");
490