From: Jacob Procee <sn125164@gmail.com>
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
Sven Peter <sven@kernel.org>, Janne Grunau <j@jannau.net>,
Jacob Procee <sn125164@gmail.com>
Subject: [PATCH] usb: typec: tipd: cd321x: replay the plug on resume
Date: Thu, 12 Nov 2026 12:30:05 +0100 [thread overview]
Message-ID: <20261112113005.16418-1-sn125164@gmail.com> (raw)
On Apple Silicon the Type-C PHY and the dwc3 controller behind a CD321x
port lose their state during s2idle while the plug stays connected, and
the CD321x does not raise an interrupt on resume. xhci notices the lost
state and re-initializes the host controller:
xhci-hcd xhci-hcd.0.auto: xHC error in resume, USBSTS 0x401, Reinit
usb usb1: root hub lost power or was reset
usb 1-1: USB disconnect, device number 2
but the PHY is only ever programmed from typec_mux_set(), so a device
left plugged in (here a FIDO2 security key) never comes back until it is
unplugged and plugged in again.
Re-initializing only dwc3 after resume does not work: tearing dwc3 down
also powers off the PHY, and nothing turns it back on, so xhci then
times out ("Host halt failed, -110", "can't setup: -110").
Instead, make cd321x replay the plug on resume when a partner was
connected: mark the plug as changed and queue the update work, which
then goes through the same sequence as a real replug (role none, mux
safe, mux back to the partner's mode, role back on). Queue it on
system_freezable_wq so it runs only after all devices have resumed.
Tested on a 14" MacBook Pro (M1 Pro, j314s) with a backport of this
change to the Asahi 7.3.3 kernel: a USB-C security key left plugged in
re-enumerates right after "PM: suspend exit", where it previously stayed
gone until replugged. Unplugging the device while the system is asleep
also works: after resume the role goes to none, nothing is brought back
up, and replugging it later enumerates normally. This mainline version
was build-tested only (W=1, checkpatch --strict clean).
Fixes: 82432bbfb9e8 ("usb: typec: tipd: Handle mode transitions for CD321x")
Assisted-by: LLM
Signed-off-by: Jacob Procee <sn125164@gmail.com>
---
checkpatch flags the Assisted-by tag (non-standard signature, 'LLM' is
not an email address); the format follows
Documentation/process/coding-assistants.rst.
drivers/usb/typec/tipd/core.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
index 02539378ffed..2ec380124532 100644
--- a/drivers/usb/typec/tipd/core.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -164,6 +164,7 @@ struct tipd_data {
bool (*read_power_status)(struct tps6598x *tps);
int (*reset)(struct tps6598x *tps);
int (*connect)(struct tps6598x *tps, u32 status);
+ void (*resume)(struct tps6598x *tps);
};
struct tps6598x {
@@ -911,6 +912,21 @@ static int cd321x_connect(struct tps6598x *tps, u32 status)
return 0;
}
+static void cd321x_resume(struct tps6598x *tps)
+{
+ struct cd321x *cd321x = container_of(tps, struct cd321x, tps);
+
+ guard(mutex)(&tps->lock);
+
+ if (IS_ERR_OR_NULL(tps->partner))
+ return;
+
+ cd321x->update_status.status_changed |= TPS_STATUS_PLUG_PRESENT;
+ cancel_delayed_work(&cd321x->update_work);
+ queue_delayed_work(system_freezable_wq, &cd321x->update_work,
+ msecs_to_jiffies(CD321X_DEBOUNCE_DELAY_MS));
+}
+
static irqreturn_t cd321x_interrupt(int irq, void *data)
{
struct tps6598x *tps = data;
@@ -2014,6 +2030,9 @@ static int __maybe_unused tps6598x_resume(struct device *dev)
queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
msecs_to_jiffies(POLL_INTERVAL));
+ if (tps->data->resume)
+ tps->data->resume(tps);
+
return 0;
}
@@ -2040,6 +2059,7 @@ static const struct tipd_data cd321x_data = {
.reset = cd321x_reset,
.switch_power_state = cd321x_switch_power_state,
.connect = cd321x_connect,
+ .resume = cd321x_resume,
};
static const struct tipd_data tps6598x_data = {
--
2.56.0
reply other threads:[~2026-11-12 11:31 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261112113005.16418-1-sn125164@gmail.com \
--to=sn125164@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=heikki.krogerus@linux.intel.com \
--cc=j@jannau.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=sven@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
all inboxes | Powered by JetHome®