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