From: Xu Yang <xu.yang_2@nxp.com>
To: peter.chen@kernel.org, gregkh@linuxfoundation.org
Cc: jun.li@nxp.com, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org, imx@lists.linux.dev
Subject: [PATCH v2 2/3] usb: chipidea: core: allow ci_irq_handler() handle both ID and VBUS change
Date: Thu, 2 Apr 2026 15:14:56 +0800 [thread overview]
Message-ID: <20260402071457.2516021-2-xu.yang_2@nxp.com> (raw)
In-Reply-To: <20260402071457.2516021-1-xu.yang_2@nxp.com>
For USB role switch-triggered IRQ, ID and VBUS change come together, for
example when switching from host to device mode. ID indicate a role switch
and VBUS is required to determine whether the device controller can start
operating. Currently, ci_irq_handler() handles only a single event per
invocation. This can cause an issue where switching to device mode results
in the device controller not working at all. Allowing ci_irq_handler() to
handle both ID and VBUS change in one call resolves this issue.
Meanwhile, this change also affects the VBUS event handling logic.
Previously, if an ID event indicated host mode the VBUS IRQ will be
ignored as the device disable BSE when stop() is called. With the new
behavior, if ID and VBUS IRQ occur together and the target mode is host,
the VBUS event is queued and ci_handle_vbus_change() will call
usb_gadget_vbus_connect(), after which USBMODE is switched to device mode,
causing host mode to stop working. To prevent this, an additional check is
added to skip handling VBUS event when current role is not device mode.
Suggested-by: Peter Chen <peter.chen@kernel.org>
Fixes: e1b5d2bed67c ("usb: chipidea: core: handle usb role switch in a common way")
Cc: stable@vger.kernel.org
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v2:
- change ci_irq_handler() instead of assign id_event/b_sess_valid_event
as true and queue otg work directly
---
drivers/usb/chipidea/core.c | 45 +++++++++++++++++++------------------
drivers/usb/chipidea/otg.c | 3 +++
2 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 87be716dff3e..7cfabb04a4fb 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -544,30 +544,31 @@ static irqreturn_t ci_irq_handler(int irq, void *data)
if (ret == IRQ_HANDLED)
return ret;
}
- }
- /*
- * Handle id change interrupt, it indicates device/host function
- * switch.
- */
- if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) {
- ci->id_event = true;
- /* Clear ID change irq status */
- hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
- ci_otg_queue_work(ci);
- return IRQ_HANDLED;
- }
+ /*
+ * Handle id change interrupt, it indicates device/host function
+ * switch.
+ */
+ if ((otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) {
+ ci->id_event = true;
+ /* Clear ID change irq status */
+ hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
+ }
- /*
- * Handle vbus change interrupt, it indicates device connection
- * and disconnection events.
- */
- if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
- ci->b_sess_valid_event = true;
- /* Clear BSV irq */
- hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
- ci_otg_queue_work(ci);
- return IRQ_HANDLED;
+ /*
+ * Handle vbus change interrupt, it indicates device connection
+ * and disconnection events.
+ */
+ if ((otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
+ ci->b_sess_valid_event = true;
+ /* Clear BSV irq */
+ hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
+ }
+
+ if (ci->id_event || ci->b_sess_valid_event) {
+ ci_otg_queue_work(ci);
+ return IRQ_HANDLED;
+ }
}
/* Handle device/host interrupt */
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 647e98f4e351..def933b73a90 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -130,6 +130,9 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
void ci_handle_vbus_change(struct ci_hdrc *ci)
{
+ if (ci->role != CI_ROLE_GADGET)
+ return;
+
if (!ci->is_otg) {
if (ci->platdata->flags & CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS)
usb_gadget_vbus_connect(&ci->gadget);
--
2.34.1
next prev parent reply other threads:[~2026-04-02 7:12 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 7:14 [PATCH v2 1/3] usb: chipidea: core: refactor ci_usb_role_switch_set() Xu Yang
2026-04-02 7:14 ` Xu Yang [this message]
2026-04-08 5:39 ` [PATCH v2 2/3] usb: chipidea: core: allow ci_irq_handler() handle both ID and VBUS change Peter Chen (CIX)
2026-04-09 6:11 ` Xu Yang
2026-04-02 7:14 ` [PATCH v2 3/3] usb: chipidea: otg: not wait vbus drop if use role_switch Xu Yang
2026-04-08 5:24 ` [PATCH v2 1/3] usb: chipidea: core: refactor ci_usb_role_switch_set() Peter Chen (CIX)
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=20260402071457.2516021-2-xu.yang_2@nxp.com \
--to=xu.yang_2@nxp.com \
--cc=gregkh@linuxfoundation.org \
--cc=imx@lists.linux.dev \
--cc=jun.li@nxp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=peter.chen@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox