Lines Matching +full:role +full:- +full:switch +full:- +full:default +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0
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
22 * 1) The PHY itself has to be brought up; for this we need to know the mode (USB3,
25 * 3) The PHY bring-up has to be finalized and dwc3's PIPE interface has to be switched to the
27 * 4) We can now initialize xhci or gadget mode.
29 * We can switch 1 and 2 but 3 has to happen after (1 and 2) and 4 has to happen after 3.
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
37 * We also can't transition the PHY from one mode to another while dwc3 is up and running (this is
44 * mode we don't even get a USBDisconnected event and everything looks like there's still something
46 * This can be partially explained because the USB2 D+/D- lines are connected through a stateful
48 * resets the repeater out-of-band everytime the CC lines are (dis)connected. This then requires a
58 * because then we can't shut down the PHY anymore. And if we kept the PHY running in whatever mode
68 * Once a cable is connected we then keep track of the controller mode here by transitioning to
74 DWC3_APPLE_HOST, /* Cable connected, dwc3 in host mode */
75 DWC3_APPLE_DEVICE, /* Cable connected, dwc3 in device mode */
79 * struct dwc3_apple - Apple-specific DWC3 USB controller
83 * @apple_regs: Apple-specific DWC3 registers
85 * @role_sw: USB role switch
107 * Apple Silicon dwc3 vendor-specific registers
132 writel(value, appledwc->apple_regs + offset - APPLE_DWC3_REGS_START); in dwc3_apple_writel()
137 return readl(appledwc->apple_regs + offset - APPLE_DWC3_REGS_START); in dwc3_apple_readl()
165 static void dwc3_apple_set_ptrcap(struct dwc3_apple *appledwc, u32 mode) in dwc3_apple_set_ptrcap() argument
167 guard(spinlock_irqsave)(&appledwc->dwc.lock); in dwc3_apple_set_ptrcap()
168 dwc3_set_prtcap(&appledwc->dwc, mode, false); in dwc3_apple_set_ptrcap()
176 lockdep_assert_held(&appledwc->lock); in dwc3_apple_core_probe()
177 WARN_ON_ONCE(appledwc->state != DWC3_APPLE_PROBE_PENDING); in dwc3_apple_core_probe()
179 appledwc->dwc.dev = appledwc->dev; in dwc3_apple_core_probe()
180 probe_data.dwc = &appledwc->dwc; in dwc3_apple_core_probe()
181 probe_data.res = appledwc->mmio_resource; in dwc3_apple_core_probe()
190 appledwc->state = DWC3_APPLE_NO_CABLE; in dwc3_apple_core_probe()
198 lockdep_assert_held(&appledwc->lock); in dwc3_apple_core_init()
200 switch (appledwc->state) { in dwc3_apple_core_init()
204 dev_err(appledwc->dev, "Failed to probe DWC3 Core, err=%d\n", ret); in dwc3_apple_core_init()
207 ret = dwc3_core_init(&appledwc->dwc); in dwc3_apple_core_init()
209 dev_err(appledwc->dev, "Failed to initialize DWC3 Core, err=%d\n", ret); in dwc3_apple_core_init()
211 default: in dwc3_apple_core_init()
214 ret = -EINVAL; in dwc3_apple_core_init()
221 static void dwc3_apple_phy_set_mode(struct dwc3_apple *appledwc, enum phy_mode mode) in dwc3_apple_phy_set_mode() argument
223 lockdep_assert_held(&appledwc->lock); in dwc3_apple_phy_set_mode()
227 * the PHY and switch dwc3's PIPE interface to USB3 PHY. in dwc3_apple_phy_set_mode()
229 dwc3_enable_susphy(&appledwc->dwc, true); in dwc3_apple_phy_set_mode()
230 phy_set_mode(appledwc->dwc.usb2_generic_phy[0], mode); in dwc3_apple_phy_set_mode()
231 phy_set_mode(appledwc->dwc.usb3_generic_phy[0], mode); in dwc3_apple_phy_set_mode()
238 lockdep_assert_held(&appledwc->lock); in dwc3_apple_init()
240 ret = reset_control_deassert(appledwc->reset); in dwc3_apple_init()
242 dev_err(appledwc->dev, "Failed to deassert reset, err=%d\n", ret); in dwc3_apple_init()
252 * configure some unknown Apple-specific settings and then bring up xhci or gadget mode. in dwc3_apple_init()
256 switch (state) { in dwc3_apple_init()
258 appledwc->dwc.dr_mode = USB_DR_MODE_HOST; in dwc3_apple_init()
261 ret = dwc3_host_init(&appledwc->dwc); in dwc3_apple_init()
263 dev_err(appledwc->dev, "Failed to initialize host, ret=%d\n", ret); in dwc3_apple_init()
269 appledwc->dwc.dr_mode = USB_DR_MODE_PERIPHERAL; in dwc3_apple_init()
272 ret = dwc3_gadget_init(&appledwc->dwc); in dwc3_apple_init()
274 dev_err(appledwc->dev, "Failed to initialize gadget, ret=%d\n", ret); in dwc3_apple_init()
278 default: in dwc3_apple_init()
281 ret = -EINVAL; in dwc3_apple_init()
285 appledwc->state = state; in dwc3_apple_init()
289 dwc3_core_exit(&appledwc->dwc); in dwc3_apple_init()
291 ret_reset = reset_control_assert(appledwc->reset); in dwc3_apple_init()
293 dev_warn(appledwc->dev, "Failed to assert reset, err=%d\n", ret_reset); in dwc3_apple_init()
302 lockdep_assert_held(&appledwc->lock); in dwc3_apple_exit()
304 switch (appledwc->state) { in dwc3_apple_exit()
310 dwc3_gadget_exit(&appledwc->dwc); in dwc3_apple_exit()
313 dwc3_host_exit(&appledwc->dwc); in dwc3_apple_exit()
319 * and switch dwc3's PIPE interface back to a dummy PHY (i.e. no USB3 support and USB2 via in dwc3_apple_exit()
322 dwc3_enable_susphy(&appledwc->dwc, true); in dwc3_apple_exit()
323 dwc3_core_exit(&appledwc->dwc); in dwc3_apple_exit()
324 appledwc->state = DWC3_APPLE_NO_CABLE; in dwc3_apple_exit()
326 ret = reset_control_assert(appledwc->reset); in dwc3_apple_exit()
328 dev_err(appledwc->dev, "Failed to assert reset, err=%d\n", ret); in dwc3_apple_exit()
335 static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role) in dwc3_usb_role_switch_set() argument
340 guard(mutex)(&appledwc->lock); in dwc3_usb_role_switch_set()
343 * We need to tear all of dwc3 down and re-initialize it every time a cable is in dwc3_usb_role_switch_set()
344 * connected or disconnected or when the mode changes. See the documentation for enum in dwc3_usb_role_switch_set()
351 switch (role) { in dwc3_usb_role_switch_set()
359 default: in dwc3_usb_role_switch_set()
360 dev_err(appledwc->dev, "Invalid target role: %d\n", role); in dwc3_usb_role_switch_set()
361 return -EINVAL; in dwc3_usb_role_switch_set()
369 guard(mutex)(&appledwc->lock); in dwc3_usb_role_switch_get()
371 switch (appledwc->state) { in dwc3_usb_role_switch_get()
379 default: in dwc3_usb_role_switch_get()
381 dev_err(appledwc->dev, "Invalid internal state: %d\n", appledwc->state); in dwc3_usb_role_switch_get()
390 dwc3_role_switch.fwnode = dev_fwnode(appledwc->dev); in dwc3_apple_setup_role_switch()
394 appledwc->role_sw = usb_role_switch_register(appledwc->dev, &dwc3_role_switch); in dwc3_apple_setup_role_switch()
395 if (IS_ERR(appledwc->role_sw)) in dwc3_apple_setup_role_switch()
396 return PTR_ERR(appledwc->role_sw); in dwc3_apple_setup_role_switch()
403 struct device *dev = &pdev->dev; in dwc3_apple_probe()
407 appledwc = devm_kzalloc(&pdev->dev, sizeof(*appledwc), GFP_KERNEL); in dwc3_apple_probe()
409 return -ENOMEM; in dwc3_apple_probe()
411 appledwc->dev = &pdev->dev; in dwc3_apple_probe()
412 mutex_init(&appledwc->lock); in dwc3_apple_probe()
414 appledwc->reset = devm_reset_control_get_exclusive(dev, NULL); in dwc3_apple_probe()
415 if (IS_ERR(appledwc->reset)) in dwc3_apple_probe()
416 return dev_err_probe(&pdev->dev, PTR_ERR(appledwc->reset), in dwc3_apple_probe()
419 ret = reset_control_assert(appledwc->reset); in dwc3_apple_probe()
421 dev_err(&pdev->dev, "Failed to assert reset, err=%d\n", ret); in dwc3_apple_probe()
425 appledwc->mmio_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dwc3-core"); in dwc3_apple_probe()
426 if (!appledwc->mmio_resource) { in dwc3_apple_probe()
428 return -EINVAL; in dwc3_apple_probe()
431 appledwc->apple_regs = devm_platform_ioremap_resource_byname(pdev, "dwc3-apple"); in dwc3_apple_probe()
432 if (IS_ERR(appledwc->apple_regs)) in dwc3_apple_probe()
433 return dev_err_probe(dev, PTR_ERR(appledwc->apple_regs), in dwc3_apple_probe()
434 "Failed to map Apple-specific MMIO\n"); in dwc3_apple_probe()
438 * initialized with knowledge of the target mode and cable orientation from typec_set_mux. in dwc3_apple_probe()
443 appledwc->state = DWC3_APPLE_PROBE_PENDING; in dwc3_apple_probe()
446 return dev_err_probe(&pdev->dev, ret, "Failed to setup role switch\n"); in dwc3_apple_probe()
456 guard(mutex)(&appledwc->lock); in dwc3_apple_remove()
458 usb_role_switch_unregister(appledwc->role_sw); in dwc3_apple_remove()
466 if (appledwc->state != DWC3_APPLE_PROBE_PENDING) in dwc3_apple_remove()
467 dwc3_core_remove(&appledwc->dwc); in dwc3_apple_remove()
471 { .compatible = "apple,t8103-dwc3" },
480 .name = "dwc3-apple",