[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251201122604.1268071-3-akuchynski@chromium.org>
Date: Mon, 1 Dec 2025 12:25:58 +0000
From: Andrei Kuchynski <akuchynski@...omium.org>
To: Heikki Krogerus <heikki.krogerus@...ux.intel.com>,
Abhishek Pandit-Subedi <abhishekpandit@...omium.org>,
Benson Leung <bleung@...omium.org>,
Jameson Thies <jthies@...gle.com>,
Tzung-Bi Shih <tzungbi@...nel.org>,
linux-usb@...r.kernel.org,
chrome-platform@...ts.linux.dev
Cc: Guenter Roeck <groeck@...omium.org>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>,
"Christian A. Ehrhardt" <lk@...e.de>,
Abel Vesa <abel.vesa@...aro.org>,
Pooja Katiyar <pooja.katiyar@...el.com>,
Pavan Holla <pholla@...omium.org>,
Madhu M <madhu.m@...el.com>,
Venkat Jayaraman <venkat.jayaraman@...el.com>,
linux-kernel@...r.kernel.org,
Andrei Kuchynski <akuchynski@...omium.org>
Subject: [PATCH RFC 2/8] usb: typec: Integrate USB4 into the mode selection process
USB4 is defined as the most preferred mode and is placed at the top of the
mode priority list. This ensures that if the port and partner support USB4,
activation is attempted first.
Activation is handled via the `enter_usb_mode` function. System control
(enabling/disabling) over the mode is exposed through the `usb_capability`
sysfs port attribute.
Signed-off-by: Andrei Kuchynski <akuchynski@...omium.org>
---
drivers/usb/typec/mode_selection.c | 27 +++++++++++++++++++++++++--
include/linux/usb/typec_altmode.h | 2 ++
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/mode_selection.c b/drivers/usb/typec/mode_selection.c
index 1cf8a4dcd742..957e09813831 100644
--- a/drivers/usb/typec/mode_selection.c
+++ b/drivers/usb/typec/mode_selection.c
@@ -74,6 +74,7 @@ static int mode_selection_activate(struct mode_selection *sel,
__must_hold(&sel->lock)
{
+ struct typec_port *port = to_typec_port(sel->partner->dev.parent);
struct mode_order order = {.svid = svid, .enter = enter, .result = -ENODEV};
/*
@@ -85,7 +86,14 @@ static int mode_selection_activate(struct mode_selection *sel,
* interval.
*/
mutex_unlock(&sel->lock);
- device_for_each_child(&sel->partner->dev, &order, activate_altmode);
+ if (svid == USB_TYPEC_USB4_SID) {
+ if (port->ops && port->ops->enter_usb_mode)
+ order.result = port->ops->enter_usb_mode(port,
+ enter ? USB_MODE_USB4 : USB_MODE_USB3);
+ else
+ order.result = -EOPNOTSUPP;
+ } else
+ device_for_each_child(&sel->partner->dev, &order, activate_altmode);
mutex_lock(&sel->lock);
return order.result;
@@ -236,7 +244,9 @@ static int altmode_add_to_list(struct device *dev, void *data)
int typec_mode_selection_start(struct typec_partner *partner,
const unsigned int delay, const unsigned int timeout)
{
+ struct typec_port *port = to_typec_port(partner->dev.parent);
struct mode_selection *sel;
+ struct mode_state *ms;
int ret;
if (partner->sel)
@@ -251,13 +261,26 @@ int typec_mode_selection_start(struct typec_partner *partner,
ret = device_for_each_child(
&partner->dev, &sel->mode_list, altmode_add_to_list);
+ if (!ret) {
+ list_sort(NULL, &sel->mode_list, compare_priorities);
+
+ if (port->usb_mode == USB_MODE_USB4 &&
+ partner->usb_capability & USB_CAPABILITY_USB4 &&
+ port->ops && port->ops->enter_usb_mode) {
+ ms = create_mode_entry(USB_TYPEC_USB4_SID, 0);
+ if (!ms)
+ ret = -ENOMEM;
+ else
+ list_add(&ms->list, &sel->mode_list);
+ }
+ }
+
if (ret || list_empty(&sel->mode_list)) {
mode_list_clean(sel);
kfree(sel);
return ret;
}
- list_sort(NULL, &sel->mode_list, compare_priorities);
sel->partner = partner;
sel->delay = delay;
sel->timeout = timeout;
diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h
index a240d8264b92..faf72e4d6ceb 100644
--- a/include/linux/usb/typec_altmode.h
+++ b/include/linux/usb/typec_altmode.h
@@ -9,6 +9,8 @@
#define MODE_DISCOVERY_MAX 6
+#define USB_TYPEC_USB4_SID 0xFF00
+
struct typec_altmode_ops;
/**
--
2.52.0.158.g65b55ccf14-goog
Powered by blists - more mailing lists