* [PATCH v2 0/2] usb: typec: Find a Type-C partner after a warm reboot on the Orange Pi 5
@ 2026-11-12 8:23 Arun Iyengar via B4 Relay
2026-11-12 8:23 ` [PATCH v2 1/2] usb: typec: tcpm: Don't cut a pending state delay short on a re-queue Arun Iyengar via B4 Relay
2026-11-12 8:23 ` [PATCH v2 2/2] usb: typec: fusb302: Toggle with the default Rp current Arun Iyengar via B4 Relay
0 siblings, 2 replies; 5+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-12 8:23 UTC (permalink / raw)
To: Badhri Jagan Sridharan, Heikki Krogerus, Greg Kroah-Hartman,
Guenter Roeck, Heiko Stuebner
Cc: linux-usb, linux-kernel, linux-arm-kernel, linux-rockchip,
Arun Iyengar, stable
After a warm reboot, an Orange Pi 5 (RK3588S, FUSB302) often did not
see a Genesys Logic based USB-C to DisplayPort cable that stayed
plugged in: tcpm toggled in SRC_UNATTACHED, the FUSB302 raised no
interrupt at all, and only a replug at the board brought DisplayPort
back. Two changes in this series and one device tree change fix it:
1. tcpm: tcpm_init() sets two states back to back with the port lock
held, so the state machine work is queued twice, and the second
run applies the PORT_RESET -> PORT_RESET_WAIT_OFF transition at
once: tErrorRecovery (100 ms) took 6 us. A pending delay is now
re-armed for the time left. This is generic, with Fixes: and
Cc: stable.
2. fusb302: toggle with the default Rp current. The FUSB302 found
the cable within seconds when it toggled with the default current
(after another device was detached), never while it toggled with
Rp 3.0A. Once toggling stops on a sink, the driver switches to the
configured Rp current before it reports the attach, so the sink
sees that level from the start, as before.
The device tree change, "arm64: dts: rockchip: Mark the Orange Pi 5/5B
Type-C port self-powered" (patch 3 of v1), now goes separately to the
Rockchip tree: the port's VBUS comes from vcc5v0_sys and the board
runs from a separate power input, so tcpm opens CC during error
recovery and the partner sees a real detach at boot. It does not
depend on this series to build, but without patch 1 the open-CC period
at boot is cut short.
Testing, on an Orange Pi 5 with 7.3-based kernels: before, after a
warm reboot the cable was not detected (0 FUSB302 interrupts since
boot) until it was replugged at the board. With the three v1 patches it
was detected on 4/4 boots, the first one starting from that stuck
state, with DP connected 1-2 s after boot; the three were tested
together, not one at a time. The patches have been in every kernel I
have run since; in a later run of 30 reboots with a USB-C DisplayPort
monitor, the partner was attached on 30/30 boots, and the tcpm log of
every boot shows CC opened in PORT_RESET and 100-112 ms spent there
before PORT_RESET_WAIT_OFF. Not tested: other TCPCs (patch 1 is
generic, patch 2 only changes fusb302), and the Orange Pi 5B (same
dtsi).
v2 was tested on the same board with a kernel carrying exactly the v2
changes: on 16/16 warm reboots the partner was attached and DP alt mode
configured, CC was open in PORT_RESET for 100 ms each time, there were
no kernel warnings, and the FUSB302 HOST_CUR field matched the Rp level
of tcpm's last set_cc() on every boot. Three role changes (dual -> sink
-> dual) with the monitor attached each re-attached the partner and DP.
This is a PD port, so the non-PD path that the v2 change to patch 2 is
about was not exercised.
W=1 arm64 builds of drivers/usb/typec at every patch,
and checkpatch --strict are clean.
This series was developed with Claude (Anthropic) as a coding
assistant: it wrote the code and the commit messages, and I reviewed
and tested every change as described above.
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
Changes in v2:
- Patch 2: switch to the requested Rp current when toggling stops on a
sink, before the attach is reported; tcpm does not set it again on
every path (ports without PD) (Sashiko). Fixes: tag added (Sashiko)
- Patch 1 unchanged. Sashiko's pre-existing tcpm_unregister_port()
race is fixed separately:
https://lore.kernel.org/all/20261112-tcpm-unregister-timers-v1-1-7230fda5612b@gmail.com/
- Patch 3 (Orange Pi 5/5B DTS) split out; it goes to the Rockchip
tree on its own
- Link to v1: https://patch.msgid.link/20261110-tcpm-attach-reboot-v1-0-7657cc1e2dca@gmail.com
---
Arun Iyengar (2):
usb: typec: tcpm: Don't cut a pending state delay short on a re-queue
usb: typec: fusb302: Toggle with the default Rp current
drivers/usb/typec/tcpm/fusb302.c | 21 +++++++++++++++++++--
drivers/usb/typec/tcpm/tcpm.c | 12 ++++++++++++
2 files changed, 31 insertions(+), 2 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261110-tcpm-attach-reboot-d93d5f36403b
Best regards,
--
Arun Iyengar <aiyengar1990@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] usb: typec: tcpm: Don't cut a pending state delay short on a re-queue
2026-11-12 8:23 [PATCH v2 0/2] usb: typec: Find a Type-C partner after a warm reboot on the Orange Pi 5 Arun Iyengar via B4 Relay
@ 2026-11-12 8:23 ` Arun Iyengar via B4 Relay
2026-11-12 8:36 ` sashiko-bot
2026-11-12 8:23 ` [PATCH v2 2/2] usb: typec: fusb302: Toggle with the default Rp current Arun Iyengar via B4 Relay
1 sibling, 1 reply; 5+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-12 8:23 UTC (permalink / raw)
To: Badhri Jagan Sridharan, Heikki Krogerus, Greg Kroah-Hartman,
Guenter Roeck, Heiko Stuebner
Cc: linux-usb, linux-kernel, linux-arm-kernel, linux-rockchip,
Arun Iyengar, stable
From: Arun Iyengar <aiyengar1990@gmail.com>
tcpm_state_machine_work() applies port->delayed_state as soon as it
runs, assuming it only runs when the state machine timer fired. The
work can also run because it was queued for another reason while it was
already running.
This happens at every port registration: tcpm_init() runs with the port
lock held and calls tcpm_set_state() twice with no delay (default state,
then PORT_RESET). The first call queues the work, which starts and
blocks on the lock; the second call queues it again. The first run
handles PORT_RESET and schedules PORT_RESET_WAIT_OFF after
PD_T_ERROR_RECOVERY; the second run then applies it at once. On an
Orange Pi 5 (FUSB302) the log shows the 100 ms ErrorRecovery taking
6 us:
pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms
state change PORT_RESET -> PORT_RESET_WAIT_OFF [delayed 100 ms]
so the "clean slate" that tcpm_init() asks for never happens.
If the delay has not expired yet, re-arm the timer for the time left
and return, as tcpm_send_queued_message() already does.
Fixes: 3ed8e1c2ac99 ("usb: typec: tcpm: Migrate workqueue to RT priority for processing events")
Cc: stable@vger.kernel.org
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
drivers/usb/typec/tcpm/tcpm.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index d721baef5210..0a19b7665555 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -6569,6 +6569,18 @@ static void tcpm_state_machine_work(struct kthread_work *work)
/* If we were queued due to a delayed state change, update it now */
if (port->delayed_state) {
+ /*
+ * The work may have been queued again for another reason
+ * while it was running, for instance by tcpm_init() at port
+ * registration, which sets two states in a row with the
+ * port lock held. Do not cut a pending delay short; re-arm
+ * the timer for the time that is left.
+ */
+ if (ktime_after(port->delayed_runtime, ktime_get())) {
+ hrtimer_start(&port->state_machine_timer,
+ port->delayed_runtime, HRTIMER_MODE_ABS);
+ goto done;
+ }
tcpm_log(port, "state change %s -> %s [delayed %ld ms]",
tcpm_states[port->state],
tcpm_states[port->delayed_state], port->delay_ms);
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] usb: typec: fusb302: Toggle with the default Rp current
2026-11-12 8:23 [PATCH v2 0/2] usb: typec: Find a Type-C partner after a warm reboot on the Orange Pi 5 Arun Iyengar via B4 Relay
2026-11-12 8:23 ` [PATCH v2 1/2] usb: typec: tcpm: Don't cut a pending state delay short on a re-queue Arun Iyengar via B4 Relay
@ 2026-11-12 8:23 ` Arun Iyengar via B4 Relay
2026-11-12 8:45 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-12 8:23 UTC (permalink / raw)
To: Badhri Jagan Sridharan, Heikki Krogerus, Greg Kroah-Hartman,
Guenter Roeck, Heiko Stuebner
Cc: linux-usb, linux-kernel, linux-arm-kernel, linux-rockchip,
Arun Iyengar
From: Arun Iyengar <aiyengar1990@gmail.com>
tcpm_start_toggling() programs the Rp current that tcpm asks for, which
is the current of the source PDO (Rp 3.0A on boards that can source
3A) when the port starts toggling from Unattached.SRC, and the default
current when it starts from Unattached.SNK after a detach.
A Genesys Logic based USB-C to DisplayPort cable connected to the
Orange Pi 5 is often not detected after a warm reboot: the FUSB302
toggle state machine raises no interrupt with it while it drives the
high Rp current, but finds it within seconds once toggling restarts
with the default current after another device was detached.
Toggle with the default current, and switch to the requested one when
toggling stops on a sink, before tcpm is told about the attach, so the
sink sees the configured level from the start of the connection as
before. tcpm does not set it again after attach on every path (not on
ports without PD, for instance). The Rd detection threshold used for
unplug detection follows the restored current.
The FUSB302B datasheet sets the toggle up the same way: under "Toggle
Functionality" the processor writes HOST_CUR for the default current
before it sets TOGGLE, and a HOST_CUR change after attach is applied to
the CC line immediately ("HOST_CUR Changed After Attach").
Fixes: c034a43e72dd ("staging: typec: Fairchild FUSB302 Type-c chip driver")
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
drivers/usb/typec/tcpm/fusb302.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 3319f6a2b0c9..44aa05fd4ba2 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -97,6 +97,7 @@ struct fusb302_chip {
/* chip status */
enum toggling_mode toggling_mode;
enum src_current_status src_current_status;
+ enum src_current_status toggling_src_current;
bool intr_togdone;
bool intr_bc_lvl;
bool intr_comp_chng;
@@ -942,10 +943,19 @@ static int tcpm_start_toggling(struct tcpc_dev *dev,
}
mutex_lock(&chip->lock);
- ret = fusb302_set_src_current(chip, cc_src_current[cc]);
+ /*
+ * Look for a partner with the default USB current advertisement.
+ * Some sinks (seen with a Genesys Logic based USB-C to DisplayPort
+ * cable) present an Rd that the FUSB302 toggle state machine does
+ * not detect while it drives the high (3.0 A) Rp current, so they
+ * are only found when toggling starts from the sink side. The
+ * requested current is restored when toggling finds a sink.
+ */
+ chip->toggling_src_current = cc_src_current[cc];
+ ret = fusb302_set_src_current(chip, SRC_CURRENT_DEFAULT);
if (ret < 0) {
fusb302_log(chip, "unable to set src current %s, ret=%d",
- typec_cc_status_name[cc], ret);
+ typec_cc_status_name[TYPEC_CC_RP_DEF], ret);
goto done;
}
ret = fusb302_set_toggling(chip, mode);
@@ -1357,6 +1367,13 @@ static int fusb302_handle_togdone_src(struct fusb302_chip *chip,
typec_cc_status_name[cc2]);
return fusb302_set_toggling(chip, toggling_mode);
}
+ /* advertise the requested Rp current now that a sink is attached */
+ ret = fusb302_set_src_current(chip, chip->toggling_src_current);
+ if (ret < 0) {
+ fusb302_log(chip, "cannot set src current, ret=%d", ret);
+ return ret;
+ }
+ rd_mda = rd_mda_value[chip->src_current_status];
/* set polarity and pull_up, pull_down */
ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, true, false);
if (ret < 0) {
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] usb: typec: tcpm: Don't cut a pending state delay short on a re-queue
2026-11-12 8:23 ` [PATCH v2 1/2] usb: typec: tcpm: Don't cut a pending state delay short on a re-queue Arun Iyengar via B4 Relay
@ 2026-11-12 8:36 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-12 8:36 UTC (permalink / raw)
To: Arun Iyengar; +Cc: linux-usb
> From: Arun Iyengar <aiyengar1990@gmail.com>
>
> tcpm_state_machine_work() applies port->delayed_state as soon as it
> runs, assuming it only runs when the state machine timer fired. The
> work can also run because it was queued for another reason while it was
> already running.
>
> This happens at every port registration: tcpm_init() runs with the port
> lock held and calls tcpm_set_state() twice with no delay (default state,
> then PORT_RESET). The first call queues the work, which starts and
> blocks on the lock; the second call queues it again. The first run
> handles PORT_RESET and schedules PORT_RESET_WAIT_OFF after
> PD_T_ERROR_RECOVERY; the second run then applies it at once. On an
> Orange Pi 5 (FUSB302) the log shows the 100 ms ErrorRecovery taking
> 6 us:
>
> pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms
> state change PORT_RESET -> PORT_RESET_WAIT_OFF [delayed 100 ms]
>
> so the "clean slate" that tcpm_init() asks for never happens.
>
> If the delay has not expired yet, re-arm the timer for the time left
> and return, as tcpm_send_queued_message() already does.
>
> Fixes: 3ed8e1c2ac99 ("usb: typec: tcpm: Migrate workqueue to RT priority for processing events")
> Cc: stable@vger.kernel.org
> Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112-tcpm-attach-reboot-v2-0-b4bc6ca83490@gmail.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] usb: typec: fusb302: Toggle with the default Rp current
2026-11-12 8:23 ` [PATCH v2 2/2] usb: typec: fusb302: Toggle with the default Rp current Arun Iyengar via B4 Relay
@ 2026-11-12 8:45 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-12 8:45 UTC (permalink / raw)
To: Arun Iyengar; +Cc: linux-usb
> From: Arun Iyengar <aiyengar1990@gmail.com>
>
> tcpm_start_toggling() programs the Rp current that tcpm asks for, which
> is the current of the source PDO (Rp 3.0A on boards that can source
> 3A) when the port starts toggling from Unattached.SRC, and the default
> current when it starts from Unattached.SNK after a detach.
>
> A Genesys Logic based USB-C to DisplayPort cable connected to the
> Orange Pi 5 is often not detected after a warm reboot: the FUSB302
> toggle state machine raises no interrupt with it while it drives the
> high Rp current, but finds it within seconds once toggling restarts
> with the default current after another device was detached.
>
> Toggle with the default current, and switch to the requested one when
> toggling stops on a sink, before tcpm is told about the attach, so the
> sink sees the configured level from the start of the connection as
> before. tcpm does not set it again after attach on every path (not on
> ports without PD, for instance). The Rd detection threshold used for
> unplug detection follows the restored current.
>
> The FUSB302B datasheet sets the toggle up the same way: under "Toggle
> Functionality" the processor writes HOST_CUR for the default current
> before it sets TOGGLE, and a HOST_CUR change after attach is applied to
> the CC line immediately ("HOST_CUR Changed After Attach").
>
> Fixes: c034a43e72dd ("staging: typec: Fairchild FUSB302 Type-c chip driver")
> Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112-tcpm-attach-reboot-v2-0-b4bc6ca83490@gmail.com?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-12 8:45 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 8:23 [PATCH v2 0/2] usb: typec: Find a Type-C partner after a warm reboot on the Orange Pi 5 Arun Iyengar via B4 Relay
2026-11-12 8:23 ` [PATCH v2 1/2] usb: typec: tcpm: Don't cut a pending state delay short on a re-queue Arun Iyengar via B4 Relay
2026-11-12 8:36 ` sashiko-bot
2026-11-12 8:23 ` [PATCH v2 2/2] usb: typec: fusb302: Toggle with the default Rp current Arun Iyengar via B4 Relay
2026-11-12 8:45 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox