From: Sven Peter <sven@kernel.org>
To: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Felipe Balbi <balbi@kernel.org>, Janne Grunau <j@jannau.net>,
Alyssa Rosenzweig <alyssa@rosenzweig.io>,
Neal Gompa <neal@gompa.dev>, Vinod Koul <vkoul@kernel.org>,
Kishon Vijay Abraham I <kishon@kernel.org>,
Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Philipp Zabel <p.zabel@pengutronix.de>,
"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"asahi@lists.linux.dev" <asahi@lists.linux.dev>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
"linux-phy@lists.infradead.org" <linux-phy@lists.infradead.org>
Subject: Re: [PATCH RFC 04/22] usb: dwc3: apple: Reset dwc3 during role switches
Date: Sun, 24 Aug 2025 17:24:06 +0200 [thread overview]
Message-ID: <bc4fa511-5dc5-4844-8206-eb55783647e8@kernel.org> (raw)
In-Reply-To: <20250821232547.qzplkafogsacnbti@synopsys.com>
On 22.08.25 01:25, Thinh Nguyen wrote:
> On Thu, Aug 21, 2025, Sven Peter wrote:
>> As mad as it sounds, the dwc3 controller present on the Apple M1 must be
>> reset and reinitialized whenever a device is unplugged from the root
>> port or when the PHY mode is changed.
>>
>> This is required for at least the following reasons:
>>
>> - The USB2 D+/D- lines are connected through a stateful eUSB2 repeater
>> which in turn is controlled by a variant of the TI TPS6598x USB PD
>> chip. When the USB PD controller detects a hotplug event it resets
>> the eUSB2 repeater. Afterwards, no new device is recognized before
>> the DWC3 core and PHY are reset as well because the eUSB2 repeater
>> and the PHY/dwc3 block disagree about the current state.
>>
>> - It's possible to completely break the dwc3 controller by switching
>> it to device mode and unplugging the cable at just the wrong time.
>> If this happens dwc3 behaves as if no device is connected.
>> CORESOFTRESET will also never clear after it has been set. The only
>> workaround is to trigger a hard reset of the entire dwc3 core with
>> its external reset line.
>>
>> - Whenever the PHY mode is changed (to e.g. transition to DisplayPort
>> alternate mode or USB4) dwc3 has to be shutdown and reinitialized.
>> Otherwise the Type-C port will not be usable until the entire SoC
>> has been reset.
>>
>> All of this can be easily worked around by respecting transitions to
>> USB_ROLE_NONE and making sure the external reset line is asserted when
>> switching roles. We additionally have to ensure that the PHY is
>> suspended during init.
>>
>> Signed-off-by: Sven Peter <sven@kernel.org>
>> ---
>> drivers/usb/dwc3/core.c | 61 +++++++++++++++++++++++++++++++++++++++++++++---
[...]
>
>> + dwc3_core_exit(dwc);
>> + }
>> +
>> + if (desired_dr_role) {
>> + ret = dwc3_core_init_for_resume(dwc);
>
> The dwc3_core_init_for_resume() is for PM, reusing this with its
> current name is confusing.
Ack, I was going to clean this up later and wanted to get feedback on
this entire approach first. Won't be used anymore when moving to a
glue.h based approach anyway.
>
>> + if (ret) {
>> + dev_err(dwc->dev,
>> + "failed to reinitialize core\n");
>> + goto out;
>> + }
>> + } else {
>> + goto out;
>> + }
>> + }
>> +
>> /*
>> * When current_dr_role is not set, there's no role switching.
>> * Only perform GCTL.CoreSoftReset when there's DRD role switching.
>> */
>> - if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
>> + if (dwc->role_switch_reset_quirk ||
>
> Don't override the use of GCTL.CoreSoftReset with this quirk. Not all
> controller versions should use GCTL.CoreSoftReset, the new controller
> version don't even have it. What version is this vendor using?
>
> I'm concern how this condition is needed...
This is actually a leftover from the first attempts at making this work.
I didn't know about the external reset line back then and had to
soft-reset it here because it would not see new devices otherwise IIRC.
Since we're going through a hard-reset now anyway this can be dropped
and this entire commit will disappear in favor of a glue.h based driver
anyway.
>
>> + (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
>> DWC3_VER_IS_PRIOR(DWC31, 190A)) &&
>> - desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) {
>> + desired_dr_role != DWC3_GCTL_PRTCAP_OTG))) {
>> reg = dwc3_readl(dwc->regs, DWC3_GCTL);
>> reg |= DWC3_GCTL_CORESOFTRESET;
>> dwc3_writel(dwc->regs, DWC3_GCTL, reg);
>> @@ -1372,6 +1394,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
>> if (ret)
>> goto err_exit_phy;
>>
>> + if (dwc->role_switch_reset_quirk)
>> + dwc3_enable_susphy(dwc, true);
>> +
>
> Why do you need to enable susphy here?
The only place we actually need it is when we shut down the Type-C PHY
due some what I assume is some hardware quirk, i.e. just before
dwc3_core_exit.
The PHY will otherwise not be able to acquire some hardware lock (which
they call PIPEHANDLER lock in debug strings) to switch from e.g. USB3
PHY to a dummy PHY for USB2 only. It then can't shut down cleanly
anymore and will get stuck in a weird state where the port refuses to
work until I reset everything.
Originally it was added because we just undid some commit where susphy
handling was made unconditional IIRC.
I'll move this to the glue driver with a comment explaining why it's
required.
>
>> dwc3_core_setup_global_control(dwc);
[...]
>> + if (dev->of_node) {
>> + if (of_device_is_compatible(dev->of_node, "apple,t8103-dwc3")) {
>> + if (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) ||
>> + !IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
>> + dev_err(dev,
>> + "Apple DWC3 requires role switch support.\n"
>> + );
>> + ret = -EINVAL;
>> + goto err_put_psy;
>> + }
>> +
>> + dwc->dr_mode = USB_DR_MODE_OTG;
>> + dwc->role_switch_reset_quirk = true;
>
> Put this in your glue driver or device tree.
Ack.
>
>> + }
>> + }
[...]
>> +
>> + if (dwc->role_switch_reset_quirk && !dwc->current_dr_role)
>> + role = USB_ROLE_NONE;
>
> Don't return USB_ROLE_NONE on role_switch get. The USB_ROLE_NONE is the
> default role. The role_switch get() should return exactly which role the
> controller is currently in, and the driver can figure that out.
Ack, will also happen from inside the glue driver now.
Sven
WARNING: multiple messages have this Message-ID (diff)
From: Sven Peter <sven@kernel.org>
To: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Felipe Balbi <balbi@kernel.org>, Janne Grunau <j@jannau.net>,
Alyssa Rosenzweig <alyssa@rosenzweig.io>,
Neal Gompa <neal@gompa.dev>, Vinod Koul <vkoul@kernel.org>,
Kishon Vijay Abraham I <kishon@kernel.org>,
Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Philipp Zabel <p.zabel@pengutronix.de>,
"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"asahi@lists.linux.dev" <asahi@lists.linux.dev>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
"linux-phy@lists.infradead.org" <linux-phy@lists.infradead.org>
Subject: Re: [PATCH RFC 04/22] usb: dwc3: apple: Reset dwc3 during role switches
Date: Sun, 24 Aug 2025 17:24:06 +0200 [thread overview]
Message-ID: <bc4fa511-5dc5-4844-8206-eb55783647e8@kernel.org> (raw)
In-Reply-To: <20250821232547.qzplkafogsacnbti@synopsys.com>
On 22.08.25 01:25, Thinh Nguyen wrote:
> On Thu, Aug 21, 2025, Sven Peter wrote:
>> As mad as it sounds, the dwc3 controller present on the Apple M1 must be
>> reset and reinitialized whenever a device is unplugged from the root
>> port or when the PHY mode is changed.
>>
>> This is required for at least the following reasons:
>>
>> - The USB2 D+/D- lines are connected through a stateful eUSB2 repeater
>> which in turn is controlled by a variant of the TI TPS6598x USB PD
>> chip. When the USB PD controller detects a hotplug event it resets
>> the eUSB2 repeater. Afterwards, no new device is recognized before
>> the DWC3 core and PHY are reset as well because the eUSB2 repeater
>> and the PHY/dwc3 block disagree about the current state.
>>
>> - It's possible to completely break the dwc3 controller by switching
>> it to device mode and unplugging the cable at just the wrong time.
>> If this happens dwc3 behaves as if no device is connected.
>> CORESOFTRESET will also never clear after it has been set. The only
>> workaround is to trigger a hard reset of the entire dwc3 core with
>> its external reset line.
>>
>> - Whenever the PHY mode is changed (to e.g. transition to DisplayPort
>> alternate mode or USB4) dwc3 has to be shutdown and reinitialized.
>> Otherwise the Type-C port will not be usable until the entire SoC
>> has been reset.
>>
>> All of this can be easily worked around by respecting transitions to
>> USB_ROLE_NONE and making sure the external reset line is asserted when
>> switching roles. We additionally have to ensure that the PHY is
>> suspended during init.
>>
>> Signed-off-by: Sven Peter <sven@kernel.org>
>> ---
>> drivers/usb/dwc3/core.c | 61 +++++++++++++++++++++++++++++++++++++++++++++---
[...]
>
>> + dwc3_core_exit(dwc);
>> + }
>> +
>> + if (desired_dr_role) {
>> + ret = dwc3_core_init_for_resume(dwc);
>
> The dwc3_core_init_for_resume() is for PM, reusing this with its
> current name is confusing.
Ack, I was going to clean this up later and wanted to get feedback on
this entire approach first. Won't be used anymore when moving to a
glue.h based approach anyway.
>
>> + if (ret) {
>> + dev_err(dwc->dev,
>> + "failed to reinitialize core\n");
>> + goto out;
>> + }
>> + } else {
>> + goto out;
>> + }
>> + }
>> +
>> /*
>> * When current_dr_role is not set, there's no role switching.
>> * Only perform GCTL.CoreSoftReset when there's DRD role switching.
>> */
>> - if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
>> + if (dwc->role_switch_reset_quirk ||
>
> Don't override the use of GCTL.CoreSoftReset with this quirk. Not all
> controller versions should use GCTL.CoreSoftReset, the new controller
> version don't even have it. What version is this vendor using?
>
> I'm concern how this condition is needed...
This is actually a leftover from the first attempts at making this work.
I didn't know about the external reset line back then and had to
soft-reset it here because it would not see new devices otherwise IIRC.
Since we're going through a hard-reset now anyway this can be dropped
and this entire commit will disappear in favor of a glue.h based driver
anyway.
>
>> + (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
>> DWC3_VER_IS_PRIOR(DWC31, 190A)) &&
>> - desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) {
>> + desired_dr_role != DWC3_GCTL_PRTCAP_OTG))) {
>> reg = dwc3_readl(dwc->regs, DWC3_GCTL);
>> reg |= DWC3_GCTL_CORESOFTRESET;
>> dwc3_writel(dwc->regs, DWC3_GCTL, reg);
>> @@ -1372,6 +1394,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
>> if (ret)
>> goto err_exit_phy;
>>
>> + if (dwc->role_switch_reset_quirk)
>> + dwc3_enable_susphy(dwc, true);
>> +
>
> Why do you need to enable susphy here?
The only place we actually need it is when we shut down the Type-C PHY
due some what I assume is some hardware quirk, i.e. just before
dwc3_core_exit.
The PHY will otherwise not be able to acquire some hardware lock (which
they call PIPEHANDLER lock in debug strings) to switch from e.g. USB3
PHY to a dummy PHY for USB2 only. It then can't shut down cleanly
anymore and will get stuck in a weird state where the port refuses to
work until I reset everything.
Originally it was added because we just undid some commit where susphy
handling was made unconditional IIRC.
I'll move this to the glue driver with a comment explaining why it's
required.
>
>> dwc3_core_setup_global_control(dwc);
[...]
>> + if (dev->of_node) {
>> + if (of_device_is_compatible(dev->of_node, "apple,t8103-dwc3")) {
>> + if (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) ||
>> + !IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
>> + dev_err(dev,
>> + "Apple DWC3 requires role switch support.\n"
>> + );
>> + ret = -EINVAL;
>> + goto err_put_psy;
>> + }
>> +
>> + dwc->dr_mode = USB_DR_MODE_OTG;
>> + dwc->role_switch_reset_quirk = true;
>
> Put this in your glue driver or device tree.
Ack.
>
>> + }
>> + }
[...]
>> +
>> + if (dwc->role_switch_reset_quirk && !dwc->current_dr_role)
>> + role = USB_ROLE_NONE;
>
> Don't return USB_ROLE_NONE on role_switch get. The USB_ROLE_NONE is the
> default role. The role_switch get() should return exactly which role the
> controller is currently in, and the driver can figure that out.
Ack, will also happen from inside the glue driver now.
Sven
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
next prev parent reply other threads:[~2025-08-24 15:24 UTC|newest]
Thread overview: 108+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-21 15:38 [PATCH RFC 00/22] Apple Silicon USB3 support Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 15:38 ` [PATCH RFC 01/22] dt-bindings: usb: snps,dwc3: Allow multiple iommus Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 22:39 ` Rob Herring (Arm)
2025-08-21 22:39 ` Rob Herring (Arm)
2025-08-22 7:22 ` Krzysztof Kozlowski
2025-08-22 7:22 ` Krzysztof Kozlowski
2025-08-24 8:31 ` Krzysztof Kozlowski
2025-08-24 8:31 ` Krzysztof Kozlowski
2025-08-27 16:07 ` Sven Peter
2025-08-27 16:07 ` Sven Peter
2025-08-28 6:54 ` Krzysztof Kozlowski
2025-08-28 6:54 ` Krzysztof Kozlowski
2025-08-21 15:38 ` [PATCH RFC 02/22] dt-bindings: usb: Add Apple dwc3 Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 22:39 ` Rob Herring (Arm)
2025-08-21 22:39 ` Rob Herring (Arm)
2025-08-22 7:24 ` Krzysztof Kozlowski
2025-08-22 7:24 ` Krzysztof Kozlowski
2025-08-24 15:30 ` Sven Peter
2025-08-24 15:30 ` Sven Peter
2025-08-21 15:38 ` [PATCH RFC 03/22] dt-bindings: phy: Add Apple Type-C PHY Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 16:33 ` Janne Grunau
2025-08-21 16:33 ` Janne Grunau
2025-08-21 23:00 ` Rob Herring
2025-08-21 23:00 ` Rob Herring
2025-08-24 15:33 ` Sven Peter
2025-08-24 15:33 ` Sven Peter
2025-08-21 22:39 ` Rob Herring (Arm)
2025-08-21 22:39 ` Rob Herring (Arm)
2025-08-21 15:38 ` [PATCH RFC 04/22] usb: dwc3: apple: Reset dwc3 during role switches Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 23:25 ` Thinh Nguyen
2025-08-21 23:25 ` Thinh Nguyen
2025-08-24 13:18 ` Janne Grunau
2025-08-24 13:18 ` Janne Grunau
2025-08-28 23:07 ` Thinh Nguyen
2025-08-28 23:07 ` Thinh Nguyen
2025-08-24 15:24 ` Sven Peter [this message]
2025-08-24 15:24 ` Sven Peter
2025-08-28 23:14 ` Thinh Nguyen
2025-08-28 23:14 ` Thinh Nguyen
2025-08-21 15:38 ` [PATCH RFC 05/22] usb: dwc3: apple: Do not use host-vbus-glitches workaround Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 22:28 ` Thinh Nguyen
2025-08-21 22:28 ` Thinh Nguyen
2025-08-23 11:42 ` Sven Peter
2025-08-23 11:42 ` Sven Peter
2025-08-28 23:06 ` Thinh Nguyen
2025-08-28 23:06 ` Thinh Nguyen
2025-08-21 15:38 ` [PATCH RFC 06/22] usb: dwc3: apple: Use synchronous role switch for apple Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 15:38 ` [PATCH RFC 07/22] usb: dwc3: apple: Adjust vendor-specific registers during init Sven Peter
2025-08-21 15:38 ` Sven Peter
2025-08-21 22:18 ` Thinh Nguyen
2025-08-21 22:18 ` Thinh Nguyen
2025-08-23 9:32 ` Sven Peter
2025-08-23 9:32 ` Sven Peter
2025-08-28 22:51 ` Thinh Nguyen
2025-08-28 22:51 ` Thinh Nguyen
2025-08-21 15:39 ` [PATCH RFC 08/22] usb: typec: tipd: Clear interrupts first Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-29 9:37 ` Heikki Krogerus
2025-08-29 9:37 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 09/22] usb: typec: tipd: Move initial irq mask to tipd_data Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-09-05 11:03 ` Heikki Krogerus
2025-09-05 11:03 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 10/22] usb: typec: tipd: Move switch_power_state " Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-09-05 11:09 ` Heikki Krogerus
2025-09-05 11:09 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 11/22] usb: typec: tipd: Trace data status for CD321x correctly Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-09-05 11:11 ` Heikki Krogerus
2025-09-05 11:11 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 12/22] usb: typec: tipd: Add cd321x struct with separate size Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-09-05 11:15 ` Heikki Krogerus
2025-09-05 11:15 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 13/22] usb: typec: tipd: Read USB4, Thunderbolt and DisplayPort status for cd321x Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 16:46 ` Janne Grunau
2025-08-21 16:46 ` Janne Grunau
2025-08-21 15:39 ` [PATCH RFC 14/22] usb: typec: tipd: Register DisplayPort and Thunderbolt altmodes " Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-09-05 11:20 ` Heikki Krogerus
2025-09-05 11:20 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 15/22] usb: typec: tipd: Update partner identity when power status was updated Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-09-05 11:40 ` Heikki Krogerus
2025-09-05 11:40 ` Heikki Krogerus
2025-08-21 15:39 ` [PATCH RFC 16/22] usb: typec: tipd: Use read_power_status function in probe Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 15:39 ` [PATCH RFC 17/22] usb: typec: tipd: Read data status in probe and cache its value Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 15:39 ` [PATCH RFC 18/22] usb: typec: mux: Introduce data_role to mux state Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 15:39 ` [PATCH RFC 19/22] usb: typec: tipd: Handle mode transitions for CD321x Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 15:39 ` [PATCH RFC 20/22] soc: apple: Add hardware tunable support Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 15:39 ` [PATCH RFC 21/22] phy: apple: Add Apple Type-C PHY Sven Peter
2025-08-21 15:39 ` Sven Peter
2025-08-21 15:39 ` [PATCH RFC 22/22] arm64: dts: apple: t8103: Add Apple Type-C PHY and dwc3 nodes Sven Peter
2025-08-21 15:39 ` Sven Peter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bc4fa511-5dc5-4844-8206-eb55783647e8@kernel.org \
--to=sven@kernel.org \
--cc=Thinh.Nguyen@synopsys.com \
--cc=alyssa@rosenzweig.io \
--cc=asahi@lists.linux.dev \
--cc=balbi@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=heikki.krogerus@linux.intel.com \
--cc=j@jannau.net \
--cc=kishon@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux-usb@vger.kernel.org \
--cc=neal@gompa.dev \
--cc=p.zabel@pengutronix.de \
--cc=robh@kernel.org \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.