From: sashiko-bot@kernel.org
To: "Joonhoe Kim" <26rote@gmail.com>
Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH 2/3] usb: dwc3: qcom: Use the UTMI clock as PIPE clock in DisplayPort-only modes
Date: Mon, 02 Nov 2026 22:08:43 +0000 [thread overview]
Message-ID: <sashiko-outbox-194253@kernel.org> (raw)
In-Reply-To: <20261102215121.738-3-26rote@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] usb: dwc3: qcom: missing CONFIG_TYPEC handling in dwc3_qcom_mux_register()
- [High] usb: dwc3: qcom: UTMI clock stuck after DP-only exit in dwc3_qcom_mux_set()
--
commit 248cd44664911cc499b2fd0be17d977befe94173
Author: Joonhoe Kim <26rote@gmail.com>
usb: dwc3: qcom: Use the UTMI clock as PIPE clock in DisplayPort-only modes
This commit registers dwc3-qcom as a Type-C mode switch when the
"mode-switch" property is present and selects the UTMI clock as the PIPE
clock during DisplayPort-only pin assignments (C and E). It defers
switching back to the PHY PIPE clock until a role change notification
occurs after leaving the safe state.
> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
> index ac68b4218b56b..4919deae682d9 100644
> --- a/drivers/usb/dwc3/dwc3-qcom.c
> +++ b/drivers/usb/dwc3/dwc3-qcom.c
[ ... ]
> @@ -419,21 +429,77 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data)
> return IRQ_HANDLED;
> }
>
> -static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom)
> +static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom, bool utmi)
> {
> - /* Configure dwc3 to use UTMI clock as PIPE clock not present */
> dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
> PIPE_UTMI_CLK_DIS);
>
> usleep_range(100, 1000);
>
> - dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
> - PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW);
> + if (utmi)
> + dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
> + PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW);
> + else
> + dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
> + PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW);
>
> usleep_range(100, 1000);
>
> dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG,
> PIPE_UTMI_CLK_DIS);
> +
> + qcom->utmi_pipe_clk = utmi;
> +}
> +
> +static void dwc3_qcom_update_pipe_clk(struct dwc3_qcom *qcom)
> +{
> + if (qcom->ignore_pipe_clk || qcom->dp_only == qcom->utmi_pipe_clk)
> + return;
> +
> + dwc3_qcom_select_utmi_clk(qcom, qcom->dp_only);
> +}
> +
> +static int dwc3_qcom_mux_set(struct typec_mux_dev *mux,
> + struct typec_mux_state *state)
> +{
> + struct dwc3_qcom *qcom = typec_mux_get_drvdata(mux);
> +
> + guard(mutex)(&qcom->pipe_clk_lock);
> +
> + if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) {
> + qcom->dp_active = true;
> + qcom->dp_only = state->mode == TYPEC_DP_STATE_C ||
> + state->mode == TYPEC_DP_STATE_E;
> + } else if (state->mode == TYPEC_STATE_SAFE) {
> + qcom->dp_active = false;
> + } else if (!qcom->dp_active) {
> + qcom->dp_only = false;
> + }
> +
> + /* The PHY stops the PIPE clock right after this in DP-only mode */
> + if (!qcom->dp_only || pm_runtime_resume_and_get(qcom->dev))
> + return 0;
> +
> + dwc3_qcom_update_pipe_clk(qcom);
> + pm_runtime_put_autosuspend(qcom->dev);
> +
> + return 0;
> +}
[Severity: High]
Can the controller get stuck on the UTMI clock after leaving a
DisplayPort-only mode?
In dwc3_qcom_mux_set(), when qcom->dp_only transitions to false, the
function returns early at:
if (!qcom->dp_only || pm_runtime_resume_and_get(qcom->dev))
return 0;
Switching back to the PHY PIPE clock via dwc3_qcom_select_utmi_clk(qcom,
false) therefore relies entirely on a subsequent call to
dwc3_qcom_set_role_notifier() where next_role != qcom->current_role.
However, as noted in the commit message, role and mux notifications arrive
from different services in no fixed order. After unplugging a 4-lane DP
monitor (where TYPEC_STATE_SAFE sets qcom->dp_active = false while leaving
qcom->dp_only = true and qcom->utmi_pipe_clk = true), plugging in a USB 3.x
device or 2-lane DP + USB 3.x dock can deliver the role change first:
1. dwc3_qcom_set_role_notifier(USB_ROLE_HOST) runs while qcom->dp_only is
still true, so dwc3_qcom_update_pipe_clk() does nothing and
qcom->current_role becomes USB_ROLE_HOST.
2. dwc3_qcom_mux_set() runs next and sets qcom->dp_only = false (for
TYPEC_STATE_USB or TYPEC_DP_STATE_D), then returns early because
!qcom->dp_only is true.
3. Any subsequent role notification for USB_ROLE_HOST returns early at
if (qcom->current_role == next_role) in dwc3_qcom_set_role_notifier().
Similarly, if a dock reconfigures its DisplayPort pin assignment in-place
from 4-lane DP (TYPEC_DP_STATE_C or TYPEC_DP_STATE_E) to 2-lane DP + USB3
(TYPEC_DP_STATE_D or TYPEC_DP_STATE_F) without changing the USB role, or if
pmic_glink_altmode_sc8280xp_notify() coalesces MUX_CTRL_STATE_NO_CONN with
a subsequent USB3 state before its worker runs (leaving qcom->dp_active
true when TYPEC_STATE_USB arrives), qcom->utmi_pipe_clk will remain true
with PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW asserted in
QSCRATCH_GENERAL_CFG.
> +
> +static int dwc3_qcom_mux_register(struct dwc3_qcom *qcom)
> +{
> + struct typec_mux_desc desc = {};
> +
> + if (!device_property_present(qcom->dev, "mode-switch"))
> + return 0;
> +
> + desc.drvdata = qcom;
> + desc.fwnode = dev_fwnode(qcom->dev);
> + desc.set = dwc3_qcom_mux_set;
> +
> + qcom->mux = typec_mux_register(qcom->dev, &desc);
> +
> + return PTR_ERR_OR_ZERO(qcom->mux);
> +}
[Severity: High]
What happens here when CONFIG_USB_DWC3_QCOM=y and CONFIG_TYPEC=m, or when
CONFIG_TYPEC=n?
In drivers/usb/dwc3/Kconfig, USB_DWC3_QCOM does not depend on
TYPEC || !TYPEC, so built-in dwc3-qcom.o will fail to link against
typec_mux_register(), typec_mux_unregister(), and typec_mux_get_drvdata()
when CONFIG_TYPEC=m.
Additionally, when CONFIG_TYPEC=n, the stub for typec_mux_register() in
include/linux/usb/typec_mux.h returns ERR_PTR(-EOPNOTSUPP):
static inline struct typec_mux_dev *
typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
{
return ERR_PTR(-EOPNOTSUPP);
}
On a board with the "mode-switch" property in its device tree,
dwc3_qcom_mux_register() will return -EOPNOTSUPP to dwc3_qcom_probe() and
abort probing of the USB controller.
Should USB_DWC3_QCOM add a Kconfig dependency on TYPEC || !TYPEC (or
TYPEC || TYPEC=n, like PHY_QCOM_QMP_COMBO) and guard the mux registration
when CONFIG_TYPEC is disabled?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102215121.738-1-26rote@gmail.com?part=2
next prev parent reply other threads:[~2026-11-02 22:08 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 21:51 [PATCH 0/3] usb: dwc3: qcom: Keep USB 2.0 working in DisplayPort-only modes Joonhoe Kim
2026-11-02 21:51 ` [PATCH 1/3] dt-bindings: usb: qcom,snps-dwc3: Add mode-switch Joonhoe Kim
2026-11-02 21:51 ` [PATCH 2/3] usb: dwc3: qcom: Use the UTMI clock as PIPE clock in DisplayPort-only modes Joonhoe Kim
2026-11-02 22:08 ` sashiko-bot [this message]
2026-11-03 13:51 ` joonhoekim
2026-11-02 21:51 ` [PATCH 3/3] arm64: dts: qcom: kaanapali: Mark the USB controller as a Type-C mode switch Joonhoe Kim
2026-11-02 22:15 ` sashiko-bot
2026-11-03 13:51 ` joonhoekim
2026-11-03 9:51 ` Abel Vesa
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=sashiko-outbox-194253@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=26rote@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox