diff options
| author | Andrei Kuchynski <akuchynski@chromium.org> | 2026-01-19 13:18:24 +0000 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-01-23 17:18:01 +0100 |
| commit | ffbe78fdbbbdf774a92b47ac138bc1a0a7482096 (patch) | |
| tree | c24861eabae7b1ebee8985760e4fee4c544daf3e /drivers/usb | |
| parent | ab2588c040fe6e87e5b1ca5a0d005cc4df14aced (diff) | |
usb: typec: ucsi: Enforce mode selection for cros_ec_ucsi
The mode selection sequence is initiated by the driver after all partner
alternate modes have been successfully registered.
When a partner is disconnected, the driver also stops the mode selection
process and releases resources via `typec_mode_selection_delete`.
Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://patch.msgid.link/20260119131824.2529334-8-akuchynski@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/typec/ucsi/cros_ec_ucsi.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi.c index eed2a7d0ebc6..6bca2dce211c 100644 --- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c +++ b/drivers/usb/typec/ucsi/cros_ec_ucsi.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/wait.h> +#include <linux/usb/typec_altmode.h> #include "ucsi.h" @@ -33,6 +34,11 @@ /* Number of times to attempt recovery from a write timeout before giving up. */ #define WRITE_TMO_CTR_MAX 5 +/* Delay between mode entry/exit attempts, ms */ +static const unsigned int mode_selection_delay = 1000; +/* Timeout for a mode entry attempt, ms */ +static const unsigned int mode_selection_timeout = 4000; + struct cros_ucsi_data { struct device *dev; struct ucsi *ucsi; @@ -134,6 +140,20 @@ static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci, return ret; } +static void cros_ucsi_add_partner_altmodes(struct ucsi_connector *con) +{ + if (!con->typec_cap.no_mode_control) + typec_mode_selection_start(con->partner, + mode_selection_delay, + mode_selection_timeout); +} + +static void cros_ucsi_remove_partner_altmodes(struct ucsi_connector *con) +{ + if (!con->typec_cap.no_mode_control) + typec_mode_selection_delete(con->partner); +} + static const struct ucsi_operations cros_ucsi_ops = { .read_version = cros_ucsi_read_version, .read_cci = cros_ucsi_read_cci, @@ -141,6 +161,8 @@ static const struct ucsi_operations cros_ucsi_ops = { .read_message_in = cros_ucsi_read_message_in, .async_control = cros_ucsi_async_control, .sync_control = cros_ucsi_sync_control, + .add_partner_altmodes = cros_ucsi_add_partner_altmodes, + .remove_partner_altmodes = cros_ucsi_remove_partner_altmodes, }; static void cros_ucsi_work(struct work_struct *work) |
