From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ed1-f43.google.com (mail-ed1-f43.google.com [209.85.208.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3413368287 for ; Mon, 19 Jan 2026 13:18:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828727; cv=none; b=qQTFqdN1+tRbQNjRWZZnuLZ8OKxGLIGEQizvvGJCRZdrofvZ18J3sqBdyUKF1YwD9cXCExNp8cQPiPIobO6zzGE2oJgYscWMkhdCv5SI5X/+MKGd6OYYh7JkKtKPUGY60DLfdF581MEyV1/WlxkDyoiCoHhFwLp7s4IvUAEHiOs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828727; c=relaxed/simple; bh=V1jmUzlQs0mqeDEI06ZenpYXU3urQAv3hO+yVPpB20c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FgyAwx+SB67ZUQOuX3CKSJ43mrXbxgSeWuIl00yJdgUB9o25obsS5KQgAXniNnfpA+nvoyBNRGs/K/Tr96jcQwqZ+GUiLZ6BFhg+ngFjpMU64KyZVUlQgX5KH4RoJa4oFdNFo4fIvYuQg+KlSrndter2WKKJgM+gjY7mR/g30bY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=bFPvJrPL; arc=none smtp.client-ip=209.85.208.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="bFPvJrPL" Received: by mail-ed1-f43.google.com with SMTP id 4fb4d7f45d1cf-64c893f3a94so9256723a12.0 for ; Mon, 19 Jan 2026 05:18:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828722; x=1769433522; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cLqa5LSPMe82XqVLviPNjog13TrBNYmx2vAnL8Z9NGE=; b=bFPvJrPLR1mSUfB1JPSjU3Zm0EmWTrNGyJmdr8h/4bCNt3gO4VDRV3VASov/dyXePk O+9J/5tScCq30NK9yaK7pY0Lhf3JamA45WBguVudWzg6SFlK3roLpqEOsul1kDv77qtH wyl8Mb5q1p7brZawTOEB56UzGB1PgSyyOmnCc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828722; x=1769433522; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=cLqa5LSPMe82XqVLviPNjog13TrBNYmx2vAnL8Z9NGE=; b=RfRC741OIiTZrxvlz7pEzFwPkOqzSRZINFX8RMD1kwRESyKVCYwA1FlrZ7fghEzK0p eLE+b50h6+xBh9Ny/0fLtc1tADcHwa+oa2ktXgFMN4fHQ/kjSafGQaKJ8dYboU1mBm0u ZpeyIh08SW9QLk81+DukXUOFpoMUDL9ZA1KuUfX8gXnliaR4nHzTaOdPILtMaH4bPdh/ /dZpKzwQaXTC2cSw6UU06q6aJNOM+aq5HCwEThz9DeEwZygkCz/JRm/SNIZl8mKYPScN oUXBI8c8Ssd7YmPajSIus2HNjTpQ7GxiI1wRgu94poXgS8hOAQXUIXT8rqn/XNE7hQya ClfA== X-Forwarded-Encrypted: i=1; AJvYcCXuM1otOKC278CDqY+wNuKXqspYhzafTlpuB2/h8hvi1bBUuQxmWyhjbbXsDtEE0bpQfZhdmtm079X9HJo=@vger.kernel.org X-Gm-Message-State: AOJu0YzcNmxxMetLJTQwWlyavUmGLnCbYDvlN+3ebSfAjrpZR5wuqG7R 1taOfZ5bypuBFf8s1oosJUQuGFlNSzOAGH/b5GoocPkLBLsA7Q/6418JNwOZG75PKQ== X-Gm-Gg: AY/fxX6pTuZQKs8E/u8SYkEB+EXkhKJrSmA4Lh4WRpSEWPfpv2wFTkRf7D1R7Er+eDq ctAnuexC3KjWTeiagwmZ5KzdiS7YLYn8544b6N6YwsQj1c46sFwNsuRw5jYk1EU33KOB5ceQRn0 3QJzPrTi5725IPip1oKSoYGTua+hb7T+88JVUVOe5JLfqSDApdXSXsDJXArp2ePfhjoWr5PPS14 dPpL/Y6ta/pZ1GdRx2097cCevDsiLioIMPC2Uer0ig8+VslGBCGIMIhnhht3ZeTL3x37BHC9aDg X2mZk7irz7qi1GbDVjNalQrgjhhwUQTCTR+H4/rVipQAIFeSZl9LhaAs3EFgpKXIUkdDgwLr26S LfWYcM278CQoib2DB4KIPW6cprHKDPdZR/tmVSESk6ZEujhQ9JmHaX77FsiBSiwz4g15haLs+Zb X/s7fyAD5zkCOIs2jBnY7bGC4fLPSnPd2zXuQhXi9ukm7bAHKOgz1EAH2aEC6yBdcto8kfFJ4z+ krOhmJ1 X-Received: by 2002:a17:907:971e:b0:b7c:cc8d:14f4 with SMTP id a640c23a62f3a-b8777a09915mr1291724366b.4.1768828722003; Mon, 19 Jan 2026 05:18:42 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:41 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 1/7] usb: typec: Add mode_control field to port property Date: Mon, 19 Jan 2026 13:18:18 +0000 Message-ID: <20260119131824.2529334-2-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This new field in the port properties dictates whether the Platform Policy Manager (PPM) allows the OS Policy Manager (OPM) to change the currently active, negotiated alternate mode. Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus Reviewed-by: Benson Leung --- drivers/usb/typec/class.c | 9 ++++++--- drivers/usb/typec/class.h | 1 + include/linux/usb/typec.h | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index c4ff4310ff58a..0f12d6120511b 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -457,11 +457,13 @@ static umode_t typec_altmode_attr_is_visible(struct k= object *kobj, struct attribute *attr, int n) { struct typec_altmode *adev =3D to_typec_altmode(kobj_to_dev(kobj)); + struct typec_port *port =3D typec_altmode2port(adev); =20 if (attr =3D=3D &dev_attr_active.attr) - if (!is_typec_port(adev->dev.parent) && - (!adev->ops || !adev->ops->activate)) - return 0444; + if (!is_typec_port(adev->dev.parent)) { + if (!port->mode_control || !adev->ops || !adev->ops->activate) + return 0444; + } =20 return attr->mode; } @@ -2708,6 +2710,7 @@ struct typec_port *typec_register_port(struct device = *parent, } =20 port->pd =3D cap->pd; + port->mode_control =3D !cap->no_mode_control; =20 ret =3D device_add(&port->dev); if (ret) { diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h index db2fe96c48ff0..2e89a83c2eb70 100644 --- a/drivers/usb/typec/class.h +++ b/drivers/usb/typec/class.h @@ -62,6 +62,7 @@ struct typec_port { struct mutex partner_link_lock; =20 enum typec_orientation orientation; + bool mode_control; struct typec_switch *sw; struct typec_mux *mux; struct typec_retimer *retimer; diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index c6fd46902fce7..dbb259d885266 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -290,6 +290,7 @@ enum usb_pd_svdm_ver { * @prefer_role: Initial role preference (DRP ports). * @accessory: Supported Accessory Modes * @usb_capability: Supported USB Modes + * @no_mode_control: Ability to manage Alternate Modes * @fwnode: Optional fwnode of the port * @driver_data: Private pointer for driver specific info * @pd: Optional USB Power Delivery Support @@ -307,6 +308,7 @@ struct typec_capability { enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; unsigned int orientation_aware:1; u8 usb_capability; + bool no_mode_control; =20 struct fwnode_handle *fwnode; void *driver_data; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ed1-f48.google.com (mail-ed1-f48.google.com [209.85.208.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0769D2EC096 for ; Mon, 19 Jan 2026 13:18:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828727; cv=none; b=dyGpcNW64eCUBYHLS3Ze02bnzHxcn95qeAnWyVx4CxgVExiPhLMG+pUk/DKJqNKgdtntOUxq3pgr3vnC6vdSUcvWCmmItR8RxqbzOenLKcPuw3d3B5n5X7/92DuhMC4nAI0AiiTC39quDREzPjo4u9AVGTOBRBQAJ5prgL7MpgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828727; c=relaxed/simple; bh=aP2YFO92lDva0e1jN3T5U5hBf2PD7EyvHXkgrzxR9eA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iI8z0ry+R87g90rWKv6Rwowqs+Mwo90BvDPkYsOZao9cfR8xIMsi36DszsPq9gq0luMp1WHmEanr1dCGKCa3n5oauFXDAYfJFB4NRtF6Km6q+FWDblBk80+7n6nDJdq6FzKj8cWUSdXKcfyCR419koNx32EPVTizVNaoNj/b9Fo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Fa9z9URx; arc=none smtp.client-ip=209.85.208.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Fa9z9URx" Received: by mail-ed1-f48.google.com with SMTP id 4fb4d7f45d1cf-64b9b0b4d5dso8912625a12.1 for ; Mon, 19 Jan 2026 05:18:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828724; x=1769433524; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KHMLWRy5Z3mpMYGMUoVXUolvpCNuwJWbgQEgoyJgmAk=; b=Fa9z9URxBN1jC2DM2DnhmVQ1GBsz19w3IkeupgRbSS4QpfzH9o98RGe3j3V7sy49lJ JNg7vNH8epQsn537pCe4FC7gZtGY2cuxWjGavv6elfmoDe8NgOiOV+njEeMhjuy9wA1+ +/3d67JOucW+S1lfxOKryVjBjqhRM2E7xcuDo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828724; x=1769433524; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=KHMLWRy5Z3mpMYGMUoVXUolvpCNuwJWbgQEgoyJgmAk=; b=fFmpMTj/AsJyesAB5/cbI3z5k8UJZCNVKx2HNPiRiC695t01OFfAMQ9gpBqnHVVKM9 UHJ85to5VaFX+d/lb1bxDDbtK4kAdlw3WNgcJi6ECC4UQlt4z7MwdiophRaHDB+C0bef 7oW0Tjw3jQIxPJkwxR0r9jCOwNCQhaE3OWbx9xCE/5OvxvI0vLMnfd0OAEZLxWUyoaBN 398FZxoNVqDLgB/kRKi0HFp55CfJosyyBW7ZWQjaP6s46PANHJccTnZVu6955ogF/csj gKkw7Q3KZHDIm+BRsYX58cJoDQ7/Rzlvx35+Yfu+4PuHEigWykxUS5aZMD8+bxbEShvM 7aiw== X-Forwarded-Encrypted: i=1; AJvYcCViNQ/IuUFh0zBHkCFQf9z2Rnby6vSaMZiKHBcv/XodENHSX8MIMklDuJTv8hIHMZi2xvgTYOrHnxRvVek=@vger.kernel.org X-Gm-Message-State: AOJu0YxaL0x57hvW//diRBIafIXOJqw16OnObuC1uW2FARwHSBTOHMU6 wZBtPITRQnE7L3n1WxETw3YipkJvfML5pPsCDjEK976yWc/vF/ehoG8BaOiHouILBA== X-Gm-Gg: AY/fxX6Uck3H0/xOr1zL9gcYcYPk3nQ/yxW858am3x149xUZuXXKhAsbBdfnHOZX0KO WKd6cXX/WaH56f6buyVgQwUZI3PB9U+vLvfdJef3Zzhe5MBENJ0RcTUoTIUc5cxYPeBl7Vhz8Ht 8sHGipF9WDwrisnGqF1/tvNJWfgRBQ4nDe7IAvQkK0tDVX0/EnQjafkED3SHo/VTOkEI8UIcoYa N3PTbwLVrAcwXrjgwwcMMIIVvTJOHrAoVT9VZTbeuDl5peifuXjDYLWfL7JYv79c+2be+rI+dKN sVAW6wDVmWegE3WDlRyfgNXu1h2/0QaRoX6tumjNL2C0WTtPS7VaONlJj1QSyFOCN5q1+T6sPK8 I+UqgUKiM3XXiMyFpNIHf0fPTVc9X33rxgrJCNU8T/iRrN1v/tvEo2ao2M5MB0wGZsvovxgFSwT jepXPB7pvoOfPzbzSyKcu4KP9mxOA+CHcOq9mAKo08Cd8B/IMzmO9qmXHjIo0Dz8AOf6GVKIVGH kewoVs0 X-Received: by 2002:a17:907:9713:b0:b80:402e:6e77 with SMTP id a640c23a62f3a-b8796b9da5fmr999144466b.54.1768828724407; Mon, 19 Jan 2026 05:18:44 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:43 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 2/7] platform/chrome: cros_ec_typec: Set no_mode_control flag Date: Mon, 19 Jan 2026 13:18:19 +0000 Message-ID: <20260119131824.2529334-3-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This flag specifies that the Embedded Controller (EC) must receive explicit approval from the Application Processor (AP) before initiating Type-C alternate modes or USB4 mode. Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus Acked-by: Tzung-Bi Shih Reviewed-by: Benson Leung --- drivers/platform/chrome/cros_ec_typec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chr= ome/cros_ec_typec.c index b712bcff6fb26..c0806c562bb93 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -491,6 +491,7 @@ static int cros_typec_init_ports(struct cros_typec_data= *typec) =20 cap->driver_data =3D cros_port; cap->ops =3D &cros_typec_usb_mode_ops; + cap->no_mode_control =3D !typec->ap_driven_altmode; =20 cros_port->port =3D typec_register_port(dev, cap); if (IS_ERR(cros_port->port)) { --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A657435CB98 for ; Mon, 19 Jan 2026 13:18:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828736; cv=none; b=qM8kkjKTdVgMCsTgEciG+OL/Akvuo6PThDOhn3/RftKJ+A5MZaJNwQueMmle6MVTuzcDSdt6uwLkELUIW/qF29qpkfZ5B7/JsaP4V4VWhtf8/fYVPxVQ/ygTTivcff1pGzaX6levbjqcu0l3yjfbOb3XzXxB+NW9g1LOyIvxv5c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828736; c=relaxed/simple; bh=DfrSPWYURzwp3WwkWbtpXKx1iOauYrzcxYjkJqvZmck=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VpUuJ/JNKrJ/H83VV/4US97gB9uXdoT8p0erWxAN6OJiJAEyZ8XHl9r1MxZ7ms88TYEbdj13hLEZgsaCKfB7xlzoQcQ9FKuY42mWi1TBx2IG86t/IrwrITXXG0OMcgINdgsZnNnzp6d8baZCnvS0fgBaM0qITemBg2y7pCSehiE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=GHNGjgj8; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="GHNGjgj8" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-b86ed375d37so562685166b.3 for ; Mon, 19 Jan 2026 05:18:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828727; x=1769433527; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JVZyoDBgCg278jS1vSrSjkeNL7wqN0touFgdWqJTr8k=; b=GHNGjgj8w6I55uTlodXaKq9PAWxY95pp/P/hMEDToyZqTogEKzKxywzPsQbInR/L8M S7uPHghylTaNUGPt3ZB1nrxqoXFsKO/Y/fGNEnyXnCqZwtzsySG0RYaoDLLwDV1JEUpn btVhI+HJoJkFhKXpWaFQu+sDpa+edXDGWU9Hc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828727; x=1769433527; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=JVZyoDBgCg278jS1vSrSjkeNL7wqN0touFgdWqJTr8k=; b=UHZmhPO+q9KlLv82/fBh55ooIUDTy8KSS6U9uHGtu4nq6jK/dDPv0ORkNyxFQaMxM8 wEKGZi2kblILq8/PUfyFUbqIdb8HRTK3OZZsx6zkuHfP1WdKe6L0wzdi05bgDVhcdfdS 47mm1E2popfGjj2KHUW4Nn7HLCjNBKWDuBw9wiSeZFFVwzRW4N9oUM5WDbVn+h68+AZ8 IxhAwDr5OmR1X4OdtJwBSH6FcBanb0vHZY9r04ZUTrjcsMpnh366JCLAY8ZP5NdYoHMD A9n51BY1vRcMPzA8gHGvk4pUn5BVt968Q/mxsjBopy6teaK2Za7C9qLQrONBoy0BFA1y VmrQ== X-Forwarded-Encrypted: i=1; AJvYcCU1RZGRk73DkTgyuIIOVRQErB8xreN04tcA95Wxw79Yvw7SBoujHx/11TldO89T8iHwmD3fmhuH7NcOfCU=@vger.kernel.org X-Gm-Message-State: AOJu0YxVTwaNoOSNuRNcZaaASuJE6zw8KS+SZghxwzvuKwUJVqz0tdny 3dhvsVlHzCRr63pXwjOUnIdXONlNBs9HHAXDIcIp1nXUXVPFAf9legWlv4dVaysVEA== X-Gm-Gg: AY/fxX5x9A7bR38Lvuu/e3LFLp3mZupXmtt3asxjF3neUNS2MKxdtopXfdWQ6nCE6sq bMqLh1HN/74Ix1lGU+wR1BQ2vR8yo0gQ0W1Anp0HYMR2o4smYFA8LcIoToaKCKAtGotOQ5STod0 R6JJhdCu7//ehND3nfPf1ZN0i+FR+FQ9k0qAukj774q/96Wfyl4TmCFXYmdLtsmQEBKs+IRVheO hQxvWSfvgT4r3k2reZxWuCr6fRiC5JyJw4tzoGN9xG7mwutsYJcpcF5wdTFETtVhItRUKOw7TW1 WOKDhLV168yuq5CrzRnX4z47qTD87NZ6CEGwYSIZ6T70FSI8qAeIf0KA+tPHxEmlksW8afo9dYN qau8zkc5JKzboQOIjwUzgtkKuYorKXRz1u4G3XfhobLjW3fgfb4I4YeIV74SS8Ge8AWJSWhsxlG Nf9tSaNCdqOVJcgEaDDhourtlv8AVuEmaU+qTagDAXfoWEVGIaSkYKU1BGUW9j2WZhjJWP0IEIW +tAgadltvYzrZCtPZg= X-Received: by 2002:a17:906:7305:b0:b86:fd46:724 with SMTP id a640c23a62f3a-b8792d489b0mr1082509366b.13.1768828726748; Mon, 19 Jan 2026 05:18:46 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:46 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 3/7] usb: typec: Expose alternate mode priority via sysfs Date: Mon, 19 Jan 2026 13:18:20 +0000 Message-ID: <20260119131824.2529334-4-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch introduces a priority sysfs attribute to the USB Type-C alternate mode port interface. This new attribute allows user-space to configure the numeric priority of alternate modes managing their preferred order of operation. If a new priority value conflicts with an existing mode's priority, the priorities of the conflicting mode and all subsequent modes are automatically incremented to ensure uniqueness. Signed-off-by: Andrei Kuchynski Reviewed-by: Benson Leung Reviewed-by: Heikki Krogerus --- Changes in V5: - Clean up code style and alignment issues Documentation/ABI/testing/sysfs-class-typec | 11 +++ drivers/usb/typec/class.c | 90 ++++++++++++++++++++- include/linux/usb/typec_altmode.h | 1 + 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/AB= I/testing/sysfs-class-typec index 38e101c17a004..737b76828b509 100644 --- a/Documentation/ABI/testing/sysfs-class-typec +++ b/Documentation/ABI/testing/sysfs-class-typec @@ -162,6 +162,17 @@ Description: Lists the supported USB Modes. The defaul= t USB mode that is used - usb3 (USB 3.2) - usb4 (USB4) =20 +What: /sys/class/typec///priority +Date: July 2025 +Contact: Andrei Kuchynski +Description: + Displays and allows setting the priority for a specific alternate mode. + The priority is an integer in the range 0-255. A lower numerical value + indicates a higher priority (0 is the highest). + If the new value is already in use by another mode, the priority of the + conflicting mode and any subsequent modes will be incremented until they + are all unique. + USB Type-C partner devices (eg. /sys/class/typec/port0-partner/) =20 What: /sys/class/typec/-partner/accessory_mode diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 0f12d6120511b..a48c447125184 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -445,11 +445,88 @@ svid_show(struct device *dev, struct device_attribute= *attr, char *buf) } static DEVICE_ATTR_RO(svid); =20 +static int increment_duplicated_priority(struct device *dev, void *data) +{ + if (is_typec_port_altmode(dev)) { + struct typec_altmode **alt_target =3D (struct typec_altmode **)data; + struct typec_altmode *alt =3D to_typec_altmode(dev); + + if (alt !=3D *alt_target && alt->priority =3D=3D (*alt_target)->priority= ) { + alt->priority++; + *alt_target =3D alt; + return 1; + } + } + return 0; +} + +static int find_duplicated_priority(struct device *dev, void *data) +{ + if (is_typec_port_altmode(dev)) { + struct typec_altmode **alt_target =3D (struct typec_altmode **)data; + struct typec_altmode *alt =3D to_typec_altmode(dev); + + if (alt !=3D *alt_target && alt->priority =3D=3D (*alt_target)->priority) + return 1; + } + return 0; +} + +static int typec_mode_set_priority(struct typec_altmode *alt, const u8 pri= ority) +{ + struct typec_port *port =3D to_typec_port(alt->dev.parent); + const u8 old_priority =3D alt->priority; + int res =3D 1; + + alt->priority =3D priority; + while (res) { + res =3D device_for_each_child(&port->dev, &alt, find_duplicated_priority= ); + if (res) { + alt->priority++; + if (alt->priority =3D=3D 0) { + alt->priority =3D old_priority; + return -EOVERFLOW; + } + } + } + + res =3D 1; + alt->priority =3D priority; + while (res) + res =3D device_for_each_child(&port->dev, &alt, + increment_duplicated_priority); + + return 0; +} + +static ssize_t priority_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + u8 val; + int err =3D kstrtou8(buf, 10, &val); + + if (!err) + err =3D typec_mode_set_priority(to_typec_altmode(dev), val); + + if (!err) + return size; + return err; +} + +static ssize_t priority_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%u\n", to_typec_altmode(dev)->priority); +} +static DEVICE_ATTR_RW(priority); + static struct attribute *typec_altmode_attrs[] =3D { &dev_attr_active.attr, &dev_attr_mode.attr, &dev_attr_svid.attr, &dev_attr_vdo.attr, + &dev_attr_priority.attr, NULL }; =20 @@ -459,11 +536,15 @@ static umode_t typec_altmode_attr_is_visible(struct k= object *kobj, struct typec_altmode *adev =3D to_typec_altmode(kobj_to_dev(kobj)); struct typec_port *port =3D typec_altmode2port(adev); =20 - if (attr =3D=3D &dev_attr_active.attr) + if (attr =3D=3D &dev_attr_active.attr) { if (!is_typec_port(adev->dev.parent)) { if (!port->mode_control || !adev->ops || !adev->ops->activate) return 0444; } + } else if (attr =3D=3D &dev_attr_priority.attr) { + if (!is_typec_port(adev->dev.parent) || !port->mode_control) + return 0; + } =20 return attr->mode; } @@ -2498,6 +2579,7 @@ typec_port_register_altmode(struct typec_port *port, struct typec_altmode *adev; struct typec_mux *mux; struct typec_retimer *retimer; + int ret; =20 mux =3D typec_mux_get(&port->dev); if (IS_ERR(mux)) @@ -2516,6 +2598,12 @@ typec_port_register_altmode(struct typec_port *port, } else { to_altmode(adev)->mux =3D mux; to_altmode(adev)->retimer =3D retimer; + + ret =3D typec_mode_set_priority(adev, 0); + if (ret) { + typec_unregister_altmode(adev); + return ERR_PTR(ret); + } } =20 return adev; diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_al= tmode.h index 9197a4637a938..7e6c02d74b54f 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -36,6 +36,7 @@ struct typec_altmode { int mode; u32 vdo; unsigned int active:1; + u8 priority; =20 char *desc; const struct typec_altmode_ops *ops; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ej1-f47.google.com (mail-ej1-f47.google.com [209.85.218.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 142D8368271 for ; Mon, 19 Jan 2026 13:18:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828735; cv=none; b=r7cXs91GbYQYwoy2atdL31nySfpNeCqn8pgO9gcvSMBEHrDx98k+gZxF4mdp2NO8bZ15WqDxvgBJvKNg+EijRlVTFP2GdzQm57mu/pn7Z8FcowCvFR6oLWqWFu31ihkGCFcMmJzOteXsPqte/2cIBaTYqYK93uK5nmWnaZWfa8Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828735; c=relaxed/simple; bh=W5rVUeJ0ZYQc7VJJqv7IN5MlC5nYGPDBCCaodck9cLg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JD/qCSkCacdW+jEDMIt0qrWUzzlGvZ90DF+aLtseA/V/eEW5+DLM/7m8m3l4jaAcQbVGCgL4MaxaqmW58iHD3W92ToRo1E+qJjnHl+6FhMYKMq/gESB38NmvDjhsUN2NLSfUhCMTOuOmxYyyfip8hCbUZxge9OE9GRMPwtQF5as= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Epsk9GYk; arc=none smtp.client-ip=209.85.218.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Epsk9GYk" Received: by mail-ej1-f47.google.com with SMTP id a640c23a62f3a-b87f3c684a1so40651866b.0 for ; Mon, 19 Jan 2026 05:18:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828729; x=1769433529; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6Z12NdnfPArhakjxM92nLWa6k5fhcIcqz5sumyUrY3w=; b=Epsk9GYkvkXwJwGseMkCl4z3b7pX6KQMt9oaqUeWVCvTM5oANgO32qLDcVtmAisf1L Ktm7lDyr7oZPMi2dpCbyBav9Shc9AdAu4oEvTi3B4tGfIVlU/J48ehAR85kbP55U6zLa vnaWtDzd8KYCE2vJZC5VNFJxhL3dJvU9ZWvOI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828729; x=1769433529; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=6Z12NdnfPArhakjxM92nLWa6k5fhcIcqz5sumyUrY3w=; b=CbXVQpTE2UuPmnTplkNLgubp3JoaOqFT9NmisChHEv9JRFwT0G9Dttj63tn6yJz/J/ wLU4Je8/3RHgQ66b1YvkE8TNFJ8tveJC6hkRMwZNUB9AjPIiJO/Vg7HVzv8fILreAdmi 4zbJk9/D9TDXL+qgPYRqk6Ix5KjxtHYzUSnIYGnpvhegy5iElKa1QdRFCjSQsf9/QItX HFRQNRyvicIp+3tH45Y99u5OMhycM2sB1dJDs4ZfrcZhPhTLV+O0KJBl+fTjAOo/fnYH OCpIfsj7AX1i6XFCiBd/crkaZzf9gOGyIJLSIKuP7yqwyKDcqNxrqCvcsPMd9sjk4X1D ITVw== X-Forwarded-Encrypted: i=1; AJvYcCXqWouYn7VEfLdNE6gsXN5szpWjBhz1n8lHbRf/PtpzRQWh6Qir+7JR5EXvbQGAdwnm2+Rv277oahIqXlI=@vger.kernel.org X-Gm-Message-State: AOJu0Yy1siUwDF2u6bFL2BvwTXESgPF645m/Wm/+ZHEnJj1H+05XHkwQ qIZLOc/izCNv6KRhVuCeF1WUcjFWszSavfeNyl88rTOahY+sCMruMigXBjVOj5qxcA== X-Gm-Gg: AY/fxX5CTFXDPo0tXkbsipoFrLGMLbhiQbYJfBj3CCjhoM4R0nObaHZlXLsVfgh0kHZ dSkzZCpnjgJsznzVDeLBWoc7bn4eBIR6VCwOPghits930FBUUZZExN1PzVr4Q4wQy481RGRmoiI MywqNKQbsNdsMUIlE+D17y+TvhWe7IrW34keUM1PSsRjBCptCGVmLgDCfnaeQH0+JOxgpOYMrnL dA59CyaMRHXYtgOaUutMAysmteKHb4XiGz2D/3ihJAV6Jbf9R2Azeg49lS0gJ2fpnjm/sfN22// UOrRP0KcdA9a/uu8J2PHYk5OhgsFVLs2laJVGd/YcDVF+u7qHFVCiz8FNIz1U6G7IK5uQRhi8ER Z0sTkUq7s1W0CVIqsE0x2ngiMrkWO3NFVSV0mkGtOTlGlz/GEOaViJjCjSdawWXnWOdMWGl+mgf gTu+TJiarx+tiE0mtuV2iqAGi/PNXWsVduKofKlGXuJEgWPXfs3cNqniDVGL2izJEcJ4HqZ2Bd9 EvAQrba X-Received: by 2002:a17:906:4793:b0:b87:3809:6982 with SMTP id a640c23a62f3a-b8793254fe1mr1093930866b.57.1768828729213; Mon, 19 Jan 2026 05:18:49 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:48 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 4/7] usb: typec: Implement mode selection Date: Mon, 19 Jan 2026 13:18:21 +0000 Message-ID: <20260119131824.2529334-5-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The mode selection process is controlled by the following API functions, which allow to initiate and complete mode entry based on the priority of each mode: `typec_mode_selection_start` function compiles a priority list of supported Alternate Modes. `typec_altmode_state_update` function is invoked by the port driver to communicate the current mode of the Type-C connector. `typec_mode_selection_delete` function stops the currently running mode selection process and releases all associated system resources. `mode_selection_work_fn` task attempts to activate modes. The process stops on success; otherwise, it proceeds to the next mode after a timeout or error. Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus --- Changes in V5: - Adopt guard(mutex)(&sel->lock) in mode_selection_work_fn() - Use dev_err instead of dev_dbg, remove the error message when exiting the mode - Update typec_altmode_state_update() to only reschedule the mode_selection_work_fn task if it was successfully cancelled - Clean up code style and alignment issues drivers/usb/typec/Makefile | 2 +- drivers/usb/typec/class.h | 2 + drivers/usb/typec/mode_selection.c | 283 +++++++++++++++++++++++++++++ include/linux/usb/typec_altmode.h | 40 ++++ 4 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/typec/mode_selection.c diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index 7a368fea61bc9..8a6a1c663eb69 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TYPEC) +=3D typec.o -typec-y :=3D class.o mux.o bus.o pd.o retimer.o +typec-y :=3D class.o mux.o bus.o pd.o retimer.o mode_selection.o typec-$(CONFIG_ACPI) +=3D port-mapper.o obj-$(CONFIG_TYPEC) +=3D altmodes/ obj-$(CONFIG_TYPEC_TCPM) +=3D tcpm/ diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h index 2e89a83c2eb70..d3435936ee7c8 100644 --- a/drivers/usb/typec/class.h +++ b/drivers/usb/typec/class.h @@ -9,6 +9,7 @@ struct typec_mux; struct typec_switch; struct usb_device; +struct mode_selection; =20 struct typec_plug { struct device dev; @@ -39,6 +40,7 @@ struct typec_partner { u8 usb_capability; =20 struct usb_power_delivery *pd; + struct mode_selection *sel; =20 void (*attach)(struct typec_partner *partner, struct device *dev); void (*deattach)(struct typec_partner *partner, struct device *dev); diff --git a/drivers/usb/typec/mode_selection.c b/drivers/usb/typec/mode_se= lection.c new file mode 100644 index 0000000000000..a95b31e21b528 --- /dev/null +++ b/drivers/usb/typec/mode_selection.c @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2025 Google LLC. + */ + +#include +#include +#include +#include +#include +#include + +#include "class.h" + +/** + * struct mode_state - State tracking for a specific Type-C alternate mode + * @svid: Standard or Vendor ID of the Alternate Mode + * @priority: Mode priority + * @error: Outcome of the last attempt to enter the mode + * @list: List head to link this mode state into a prioritized list + */ +struct mode_state { + u16 svid; + u8 priority; + int error; + struct list_head list; +}; + +/** + * struct mode_selection - Manages the selection and state of Alternate Mo= des + * @mode_list: Prioritized list of available Alternate Modes + * @lock: Mutex to protect mode_list + * @work: Work structure + * @partner: Handle to the Type-C partner device + * @active_svid: svid of currently active mode + * @timeout: Timeout for a mode entry attempt, ms + * @delay: Delay between mode entry/exit attempts, ms + */ +struct mode_selection { + struct list_head mode_list; + /* Protects the mode_list*/ + struct mutex lock; + struct delayed_work work; + struct typec_partner *partner; + u16 active_svid; + unsigned int timeout; + unsigned int delay; +}; + +/** + * struct mode_order - Mode activation tracking + * @svid: Standard or Vendor ID of the Alternate Mode + * @enter: Flag indicating if the driver is currently attempting to enter = or + * exit the mode + * @result: Outcome of the attempt to activate the mode + */ +struct mode_order { + u16 svid; + int enter; + int result; +}; + +static int activate_altmode(struct device *dev, void *data) +{ + if (is_typec_partner_altmode(dev)) { + struct typec_altmode *alt =3D to_typec_altmode(dev); + struct mode_order *order =3D (struct mode_order *)data; + + if (order->svid =3D=3D alt->svid) { + if (alt->ops && alt->ops->activate) + order->result =3D alt->ops->activate(alt, order->enter); + else + order->result =3D -EOPNOTSUPP; + return 1; + } + } + return 0; +} + +static int mode_selection_activate(struct mode_selection *sel, + const u16 svid, const int enter) + + __must_hold(&sel->lock) +{ + struct mode_order order =3D {.svid =3D svid, .enter =3D enter, .result = =3D -ENODEV}; + + /* + * The port driver may acquire its internal mutex during alternate mode + * activation. Since this is the same mutex that may be held during the + * execution of typec_altmode_state_update(), it is crucial to release + * sel->mutex before activation to avoid potential deadlock. + * Note that sel->mode_list must remain invariant throughout this unlocked + * interval. + */ + mutex_unlock(&sel->lock); + device_for_each_child(&sel->partner->dev, &order, activate_altmode); + mutex_lock(&sel->lock); + + return order.result; +} + +static void mode_list_clean(struct mode_selection *sel) +{ + struct mode_state *ms, *tmp; + + list_for_each_entry_safe(ms, tmp, &sel->mode_list, list) { + list_del(&ms->list); + kfree(ms); + } +} + +/** + * mode_selection_work_fn() - Alternate mode activation task + * @work: work structure + * + * - If the Alternate Mode currently prioritized at the top of the list is= already + * active, the entire selection process is considered finished. + * - If a different Alternate Mode is currently active, the system must ex= it that + * active mode first before attempting any new entry. + * + * The function then checks the result of the attempt to entre the current= mode, + * stored in the `ms->error` field: + * - if the attempt FAILED, the mode is deactivated and removed from the l= ist. + * - `ms->error` value of 0 signifies that the mode has not yet been activ= ated. + * + * Once successfully activated, the task is scheduled for subsequent entry= after + * a timeout period. The alternate mode driver is expected to call back wi= th the + * actual mode entry result via `typec_altmode_state_update()`. + */ +static void mode_selection_work_fn(struct work_struct *work) +{ + struct mode_selection *sel =3D container_of(work, + struct mode_selection, work.work); + struct mode_state *ms; + unsigned int delay =3D sel->delay; + int result; + + guard(mutex)(&sel->lock); + + ms =3D list_first_entry_or_null(&sel->mode_list, struct mode_state, list); + if (!ms) + return; + + if (sel->active_svid =3D=3D ms->svid) { + dev_dbg(&sel->partner->dev, "%x altmode is active\n", ms->svid); + mode_list_clean(sel); + } else if (sel->active_svid !=3D 0) { + result =3D mode_selection_activate(sel, sel->active_svid, 0); + if (result) + mode_list_clean(sel); + else + sel->active_svid =3D 0; + } else if (ms->error) { + dev_err(&sel->partner->dev, "%x: entry error %pe\n", + ms->svid, ERR_PTR(ms->error)); + mode_selection_activate(sel, ms->svid, 0); + list_del(&ms->list); + kfree(ms); + } else { + result =3D mode_selection_activate(sel, ms->svid, 1); + if (result) { + dev_err(&sel->partner->dev, "%x: activation error %pe\n", + ms->svid, ERR_PTR(result)); + list_del(&ms->list); + kfree(ms); + } else { + delay =3D sel->timeout; + ms->error =3D -ETIMEDOUT; + } + } + + if (!list_empty(&sel->mode_list)) + schedule_delayed_work(&sel->work, msecs_to_jiffies(delay)); +} + +void typec_altmode_state_update(struct typec_partner *partner, const u16 s= vid, + const int error) +{ + struct mode_selection *sel =3D partner->sel; + struct mode_state *ms; + + if (sel) { + mutex_lock(&sel->lock); + ms =3D list_first_entry_or_null(&sel->mode_list, struct mode_state, list= ); + if (ms && ms->svid =3D=3D svid) { + ms->error =3D error; + if (cancel_delayed_work(&sel->work)) + schedule_delayed_work(&sel->work, 0); + } + if (!error) + sel->active_svid =3D svid; + else + sel->active_svid =3D 0; + mutex_unlock(&sel->lock); + } +} +EXPORT_SYMBOL_GPL(typec_altmode_state_update); + +static int compare_priorities(void *priv, + const struct list_head *a, const struct list_head *b) +{ + const struct mode_state *msa =3D container_of(a, struct mode_state, list); + const struct mode_state *msb =3D container_of(b, struct mode_state, list); + + if (msa->priority < msb->priority) + return -1; + return 1; +} + +static int altmode_add_to_list(struct device *dev, void *data) +{ + if (is_typec_partner_altmode(dev)) { + struct list_head *list =3D (struct list_head *)data; + struct typec_altmode *altmode =3D to_typec_altmode(dev); + const struct typec_altmode *pdev =3D typec_altmode_get_partner(altmode); + struct mode_state *ms; + + if (pdev && altmode->ops && altmode->ops->activate) { + ms =3D kzalloc(sizeof(*ms), GFP_KERNEL); + if (!ms) + return -ENOMEM; + ms->svid =3D pdev->svid; + ms->priority =3D pdev->priority; + INIT_LIST_HEAD(&ms->list); + list_add_tail(&ms->list, list); + } + } + return 0; +} + +int typec_mode_selection_start(struct typec_partner *partner, + const unsigned int delay, const unsigned int timeout) +{ + struct mode_selection *sel; + int ret; + + if (partner->usb_mode =3D=3D USB_MODE_USB4) + return -EBUSY; + + if (partner->sel) + return -EALREADY; + + sel =3D kzalloc(sizeof(*sel), GFP_KERNEL); + if (!sel) + return -ENOMEM; + + INIT_LIST_HEAD(&sel->mode_list); + + ret =3D device_for_each_child(&partner->dev, &sel->mode_list, + altmode_add_to_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 =3D partner; + sel->delay =3D delay; + sel->timeout =3D timeout; + mutex_init(&sel->lock); + INIT_DELAYED_WORK(&sel->work, mode_selection_work_fn); + schedule_delayed_work(&sel->work, msecs_to_jiffies(delay)); + partner->sel =3D sel; + + return 0; +} +EXPORT_SYMBOL_GPL(typec_mode_selection_start); + +void typec_mode_selection_delete(struct typec_partner *partner) +{ + struct mode_selection *sel =3D partner->sel; + + if (sel) { + partner->sel =3D NULL; + cancel_delayed_work_sync(&sel->work); + mode_list_clean(sel); + mutex_destroy(&sel->lock); + kfree(sel); + } +} +EXPORT_SYMBOL_GPL(typec_mode_selection_delete); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_al= tmode.h index 7e6c02d74b54f..70026f5f8f997 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -240,4 +240,44 @@ void typec_altmode_unregister_driver(struct typec_altm= ode_driver *drv); module_driver(__typec_altmode_driver, typec_altmode_register_driver, \ typec_altmode_unregister_driver) =20 +/** + * typec_mode_selection_start - Start an alternate mode selection process + * @partner: Handle to the Type-C partner device + * @delay: Delay between mode entry/exit attempts, ms + * @timeout: Timeout for a mode entry attempt, ms + * + * This function initiates the process of attempting to enter an Alternate= Mode + * supported by the connected Type-C partner. + * Returns 0 on success, or a negative error code on failure. + */ +int typec_mode_selection_start(struct typec_partner *partner, + const unsigned int delay, const unsigned int timeout); + +/** + * typec_altmode_state_update - Report the current status of an Alternate = Mode + * negotiation + * @partner: Handle to the Type-C partner device + * @svid: Standard or Vendor ID of the Alternate Mode. A value of 0 should= be + * passed if no mode is currently active + * @result: Result of the entry operation. This should be 0 on success, or= a + * negative error code if the negotiation failed + * + * This function should be called by an Alternate Mode driver to report the + * result of an asynchronous alternate mode entry request. It signals what= the + * current active SVID is (or 0 if none) and the success or failure status= of + * the last attempt. + */ +void typec_altmode_state_update(struct typec_partner *partner, const u16 s= vid, + const int result); + +/** + * typec_mode_selection_delete - Delete an alternate mode selection instan= ce + * @partner: Handle to the Type-C partner device. + * + * This function cancels a pending alternate mode selection request that w= as + * previously started with typec_mode_selection_start(). + * This is typically called when the partner disconnects. + */ +void typec_mode_selection_delete(struct typec_partner *partner); + #endif /* __USB_TYPEC_ALTMODE_H */ --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ed1-f66.google.com (mail-ed1-f66.google.com [209.85.208.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A5713368278 for ; Mon, 19 Jan 2026 13:18:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.66 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828735; cv=none; b=KqOIjoI7ejMiHf8uwik9g1l+UFhS55F3/3ehlgA3Dc99STyeC3Vm+lajTfc2Ce/QS3eHd5w9RewImN8QC34RFcy89D0NBoCkSFq9Gh8shSfBhwXS9A6Fe+RV6kA/d3qzngFfj1ms9kCH+VVDegIJujL0xDAH2kRYGDh9DD6sgPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828735; c=relaxed/simple; bh=PvMl78Egz6bmb1PsfFjOs6AkxoGFu1IQkxwSzJj0RZk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fCgYHOWbx9b2gIDnLkmeyqHFDPxFzKWEw0VCj4ovPFyAM0Kt0g66K+YuCidB5OQzaur/T7/+ZpVbvLQ85dx3JtYZzy+DpEbqwjFtLmYlWSgs4uxVl/ifcRYXtaCbmGbDn1VO1fBi1mIpisG55loWCU8RE+PHf83WFMuGTouwQXo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=McMA2foG; arc=none smtp.client-ip=209.85.208.66 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="McMA2foG" Received: by mail-ed1-f66.google.com with SMTP id 4fb4d7f45d1cf-64d4d8b3ad7so6892607a12.2 for ; Mon, 19 Jan 2026 05:18:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828732; x=1769433532; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dDnniPjMK/sJQN7VPW7dqxpb712evvAY2y6naw6LGNE=; b=McMA2foG3PfY/bLG2smlB9DVMu3pMOuRfZ8qXgtSFRM3nraOyDAvHG6b4Bm2S9I0vh v05Wapeh+mgyQ7HxvMywrlyUjm6mb55UqMVow0IO1CWeXfGDwHasGCUCBXno4sEeZjRI 5Oxh6XfZPpPf8+quO1H/BwcO57FgudR9cbKj8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828732; x=1769433532; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=dDnniPjMK/sJQN7VPW7dqxpb712evvAY2y6naw6LGNE=; b=u0/MGkfmacYnq3OTtOp4wlgndCyGTgjR1pAVci/oUHSNV2iF56dhroVB/6bi9dDQWP U/EjcRpPOFiqkb/IIkbuxgfK+OX50iFWa64H9UV/vX3WSFV6BQ9J6qXEiAAN3JpPwLiN +kfkMiX6QhipmcILWhJY/DldZxfWPu5kAm7QWOMZsRmV/O7lK00MgyOnFpAHNIV3/GpC 3mw33EYAyQ/XNiNq6IBrhUEiG+hbu2Lb1PvbALBliCiKLZBjpjMzI+bEoInw8qPtiEPC eC4mDr+9MtpI/2p76w4lW+UpK0TgKvNn5jcf2iZFxZUXLDoFZAKBuhfeRPlBGAGPaNjk yNUQ== X-Forwarded-Encrypted: i=1; AJvYcCVv+TDX3Te3pOUzcpPONe145cgdzXsMYpc3HNUYq9Kpt9xAE1EnYYnexKe6lNswGrGbYUMptspw7msSy4o=@vger.kernel.org X-Gm-Message-State: AOJu0YxeoMKRs7Cgj+QHz8lqjhXY/3pYn9dCPGIKrA1BE2Fk578Kgf4a D+NpOvL2pg60GTufD1RlEZOYiu0t10mHuFINYab+EtHczTo5CF2lyr7LnPIEqD8F7Q== X-Gm-Gg: AY/fxX5snz1RR6Y9L1kF1BsKm1wjFhGhsRHJHX3h/5NI5ef5zQzl2220N0VjnWV6HdI 8tNEJD/FEvHCYcBPD6Curzv+mjcoiCDCjvqIt76f9KBoG4aSj7qVDW6gxPJNCsxWJktf9E0gfri paALguqJvOruqmkBYJJaJFUcS6vqBERy4yLUFM83MZ1yQ3LWjsJngnpqBEyXgvOkaBgUHnZVpf4 18rIptjxwCRnerMTK2wWmg+ZBjkjimRPfe9WJQkhH+qMOMFRp0hcyGrFceNcbXY7PDOlgwkLU/0 z1LozrqXxe02fRp89JEddO0oaKIshIGPPuhnL/gs7E5VRX2adSj51p+RHvtvJSql+1Q1rVi+qWL hieNO1+OMPvVLXKAKgd4820E/MYHag5nSDqcdVZq6dzbcbLVFsCYkDRLCUp8aZjMYF8iMdFSgsi jJEmuKBYREPxH0UR7sav1oOhnlzZwuP4NvOcgk7xGoSB8qq039gPPLElsB/kF/PxZ1i2YDeWvXt hRQlfxy X-Received: by 2002:a17:907:d1f:b0:b77:2269:8df0 with SMTP id a640c23a62f3a-b8796a5a491mr862916266b.28.1768828731903; Mon, 19 Jan 2026 05:18:51 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:51 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 5/7] usb: typec: Introduce mode_selection bit Date: Mon, 19 Jan 2026 13:18:22 +0000 Message-ID: <20260119131824.2529334-6-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The port driver sets this bit for an alternate mode description to indicate support for the mode selection feature. Once set, individual Alt Mode drivers will no longer attempt to activate their respective modes within their probe functions. This prevents race conditions and non-prioritized activation. The bit is not set by default. If left unset, the system retains the current behavior where Alt Mode drivers manage their own activation logic. Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus --- drivers/usb/typec/altmodes/displayport.c | 6 ++++-- drivers/usb/typec/altmodes/thunderbolt.c | 2 +- drivers/usb/typec/class.c | 1 + include/linux/usb/typec.h | 1 + include/linux/usb/typec_altmode.h | 1 + 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/a= ltmodes/displayport.c index d96ab106a980b..d185688a16b13 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -804,8 +804,10 @@ int dp_altmode_probe(struct typec_altmode *alt) if (plug) typec_altmode_set_drvdata(plug, dp); =20 - dp->state =3D plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER; - schedule_work(&dp->work); + if (!alt->mode_selection) { + dp->state =3D plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER; + schedule_work(&dp->work); + } =20 return 0; } diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/a= ltmodes/thunderbolt.c index 6eadf7835f8f6..c4c5da6154da9 100644 --- a/drivers/usb/typec/altmodes/thunderbolt.c +++ b/drivers/usb/typec/altmodes/thunderbolt.c @@ -307,7 +307,7 @@ static int tbt_altmode_probe(struct typec_altmode *alt) typec_altmode_set_drvdata(alt, tbt); typec_altmode_set_ops(alt, &tbt_altmode_ops); =20 - if (tbt_ready(alt)) { + if (!alt->mode_selection && tbt_ready(alt)) { if (tbt->plug[TYPEC_PLUG_SOP_P]) tbt->state =3D TBT_STATE_SOP_P_ENTER; else if (tbt->plug[TYPEC_PLUG_SOP_PP]) diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index a48c447125184..dbba53f024977 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -655,6 +655,7 @@ typec_register_altmode(struct device *parent, alt->adev.svid =3D desc->svid; alt->adev.mode =3D desc->mode; alt->adev.vdo =3D desc->vdo; + alt->adev.mode_selection =3D desc->mode_selection; alt->roles =3D desc->roles; alt->id =3D id; =20 diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index dbb259d885266..d61ec38216fa9 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -155,6 +155,7 @@ struct typec_altmode_desc { /* Only used with ports */ enum typec_port_data roles; bool inactive; + bool mode_selection; }; =20 void typec_partner_set_pd_revision(struct typec_partner *partner, u16 pd_r= evision); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_al= tmode.h index 70026f5f8f997..0513d333b7977 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -37,6 +37,7 @@ struct typec_altmode { u32 vdo; unsigned int active:1; u8 priority; + bool mode_selection; =20 char *desc; const struct typec_altmode_ops *ops; --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ed1-f65.google.com (mail-ed1-f65.google.com [209.85.208.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7882936922C for ; Mon, 19 Jan 2026 13:18:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828743; cv=none; b=H6EBABk4hPyJ3WIdOuYIe/PMyLfxB/IsMuEpaEYQZB5nG3u+XlnF0dufUsilMZ6BPKppNuS3JZ/BAfFP316OBf5JzAGZzCO0AqBGU4f1PHCCvDUi83LV+APjG2PLY9lilVb9bl0Z0vkvDRVOIvrLARuvq5xjth92AIVa2bk94Dc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828743; c=relaxed/simple; bh=frUPC546TbZHzSgYQ2uN6oeGYjK8P6K8ZiFxPhwwtAs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I3PnYt8tHloDIMScH1igf3IOfriALPVzrPTGn8I0Ae2yjCTHATLgy5g87T+/2kjRrGX0HhvupEV8G6RgLk89Vqkp0wYP9DIGaAnNT4oStFA5tYMIW+69CmGbMSwJMxMpcV2tJTx2Hywdh3xSD7uIrY2biH8tXNZ2bdgcjomB+aw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=MsCwvsFc; arc=none smtp.client-ip=209.85.208.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="MsCwvsFc" Received: by mail-ed1-f65.google.com with SMTP id 4fb4d7f45d1cf-64d4d8b3ad7so6892714a12.2 for ; Mon, 19 Jan 2026 05:18:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828735; x=1769433535; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IjQjxmFvS2FQRrIuJW4DNjfu1H/SHcaCjJwkwuXOThw=; b=MsCwvsFcVSqCpzlTFgrm03I7WfjcEnpjhiqSTGwBfN2ULLFLZ6E9Or9rJh76zikmIC WZRJUUC+tDEnB5DL92wEniEnkBTcVkzcUmDoJTQ55bYnXO75tMrYKVGrT2x3V+UdJU87 XVEUrrcnt7/W12QTDvOkhHjFhVoRcjDewaKfI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828735; x=1769433535; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=IjQjxmFvS2FQRrIuJW4DNjfu1H/SHcaCjJwkwuXOThw=; b=E8iBdxgQmtt6qBggcx6ekF+bhs/Y63AmuOyFuotBakAgrycUNOBjhZ7aB2h/bP930R aDYh+Nk0838eoId+XVrDJehRMUBxt+pb4F8dHX720mYm0ZZ8yJFqAI9TB8uvVUyb5YcL WtAFax9/Hd2lcjTzB99HDMPhr1yJH2B+k4rNapnjPv1fwe6YcWY1QfnZ5pI+Xvu9UazX 2O2+XrL9+SRXegkojSgn2mo7uRBaWPyplG5ZQSLvP0F/heasWlAg+J76Sn85RH0Me91w TNqH0v3vZj+xokoV5z4TLK+lrhrO9uWsoc9UylYElUIqFSxUL4KCCqTSMKqY+8ydts4W 2d8w== X-Forwarded-Encrypted: i=1; AJvYcCXsP97knoXkdJYhsbS9rgTSOKcaKOdeRvxzx8GctWob9ZshLWHU2rw3MMfi2p5gKJ2w6nM/baPklYpuPDw=@vger.kernel.org X-Gm-Message-State: AOJu0YzE5gqwCSn88I42wvI+m0DSFZBu2V4A7MWZyEYyLEbEivq1fz08 XeF8NCCse+outdWe6J0ZxQA/pZVTzPLkfQ655SR9qaoBagoBjSrdD6a8/61jcN8MXw== X-Gm-Gg: AY/fxX4eThKzsH3a0NnbK6bCdsusAmV697bR+KwpIubXfYyaXz7XApbz30Rzp9g7Bkd hLNX49gX4GRiOwiF13DhaLMsFmM6Onbzxv7rN6olIeZhW//cARqt/3OzzmemVLX0NL6THx3CXM7 rtoza7io9CCTM0W6LaDWejQ1O48FVagtrWLd8HNRLHgVUVTEDnAVqj98Oh2FLOpZtN1JM2gtRMx gCS1i8RTtPb40mNlBfjN1/n8MblW6qdne2ad1wAJdWTcPuzMbLy/vbsWO5U8Er68pmtlPIb0w4n FR0HXsFMY2tBvUmckpWLeeXgH2R9MLFKZ6STZKDIytnVkYFR7/AZlYS5q3PdjFyKjaqq0dBcx+A CtG34i0XlcwDe3scjCQxiCmZmQscPM+dK/WYNcfllhcU7DvD1lFi+CK7DXt7wt86kJ9oEpHnNWn tT0kpr3lQhMdjWekuMa3K8XHWLHhZ2bksdxC+6DB2/oaZWC04goPhj/V0bD3f/ZyXqk6f59pJE0 uSUp+s0 X-Received: by 2002:a17:906:f584:b0:b73:278a:a499 with SMTP id a640c23a62f3a-b879690c3ccmr870116566b.15.1768828734746; Mon, 19 Jan 2026 05:18:54 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:54 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 6/7] usb: typec: ucsi: Support mode selection to activate altmodes Date: Mon, 19 Jan 2026 13:18:23 +0000 Message-ID: <20260119131824.2529334-7-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If the ucsi port driver supports modes selection, it should implement `add_partner_altmodes` and `remove_partner_altmodes` ucsi operations. With these operations the driver can manage the mode selection process. Once partner altmodes are registered, `add_partner_altmodes` is called to start the mode selection. When the partner is unregistered, `remove_partner_altmodes` is supposed to stop any ongoing processes and clean up the resources. `typec_altmode_state_update` informes mode selection about the current mode of the Type-C connector. Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus --- Changes in V5: - Use the no_mode_control field instead of con->ucsi->cap.features & UCSI_CAP_ALT_MODE_OVERRIDE - Squash previous V4 patches 3/8 and 7/8 into a single patch drivers/usb/typec/ucsi/ucsi.c | 12 ++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index a7b388dc7fa0f..251990475faa7 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -314,6 +314,7 @@ void ucsi_altmode_update_active(struct ucsi_connector *= con) { const struct typec_altmode *altmode =3D NULL; u64 command; + u16 svid =3D 0; int ret; u8 cur; int i; @@ -335,6 +336,10 @@ void ucsi_altmode_update_active(struct ucsi_connector = *con) for (i =3D 0; con->partner_altmode[i]; i++) typec_altmode_update_active(con->partner_altmode[i], con->partner_altmode[i] =3D=3D altmode); + + if (altmode) + svid =3D altmode->svid; + typec_altmode_state_update(con->partner, svid, 0); } =20 static int ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid) @@ -609,6 +614,8 @@ static int ucsi_register_altmodes(struct ucsi_connector= *con, u8 recipient) desc.vdo =3D alt[j].mid; desc.svid =3D alt[j].svid; desc.roles =3D TYPEC_PORT_DRD; + desc.mode_selection =3D con->ucsi->ops->add_partner_altmodes && + !con->typec_cap.no_mode_control; =20 ret =3D ucsi_register_altmode(con, &desc, recipient); if (ret) @@ -831,6 +838,8 @@ static int ucsi_check_altmodes(struct ucsi_connector *c= on) if (con->partner_altmode[0]) { num_partner_am =3D ucsi_get_num_altmode(con->partner_altmode); typec_partner_set_num_altmodes(con->partner, num_partner_am); + if (con->ucsi->ops->add_partner_altmodes) + con->ucsi->ops->add_partner_altmodes(con); ucsi_altmode_update_active(con); return 0; } else { @@ -1119,6 +1128,8 @@ static void ucsi_unregister_partner(struct ucsi_conne= ctor *con) return; =20 typec_set_mode(con->port, TYPEC_STATE_SAFE); + if (con->ucsi->ops->remove_partner_altmodes) + con->ucsi->ops->remove_partner_altmodes(con); =20 typec_partner_set_usb_power_delivery(con->partner, NULL); ucsi_unregister_partner_pdos(con); @@ -1659,6 +1670,7 @@ static int ucsi_register_port(struct ucsi *ucsi, stru= ct ucsi_connector *con) =20 cap->driver_data =3D con; cap->ops =3D &ucsi_ops; + cap->no_mode_control =3D !(con->ucsi->cap.features & UCSI_CAP_ALT_MODE_OV= ERRIDE); =20 if (ucsi->version >=3D UCSI_VERSION_2_0) con->typec_cap.orientation_aware =3D true; diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 410389ef173ab..4797b4aa1e35b 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -70,6 +70,8 @@ struct dentry; * @update_altmodes: Squashes duplicate DP altmodes * @update_connector: Update connector capabilities before registering * @connector_status: Updates connector status, called holding connector l= ock + * @add_partner_altmodes: Start mode selection + * @remove_partner_altmodes: Clean mode selection * * Read and write routines for UCSI interface. @sync_write must wait for t= he * Command Completion Event from the PPM before returning, and @async_writ= e must @@ -88,6 +90,8 @@ struct ucsi_operations { struct ucsi_altmode *updated); void (*update_connector)(struct ucsi_connector *con); void (*connector_status)(struct ucsi_connector *con); + void (*add_partner_altmodes)(struct ucsi_connector *con); + void (*remove_partner_altmodes)(struct ucsi_connector *con); }; =20 struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations = *ops); --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 15:25:04 2026 Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 000CE369985 for ; Mon, 19 Jan 2026 13:18:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828744; cv=none; b=Hjv2NqluyDnGITvFEWyqGwQQlp7kOJCWG5bGY+asrnYiF3MlQYzEi4S075hb7DV7N0msjSB96677dP+A6VK2cU6dROfuT51KP61A1TSwuxMEM74ucuuySxHnJEe5zgYRzvtNuFgx9DCTQi8qJ0BkUsnTBujt6242Qj0aJNc09sQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768828744; c=relaxed/simple; bh=zFB/wu9zF/WPehhEPtbWl8UOJvP9spgPqLlItDsGdnM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fHWNRhg7EXGl3huhILrVhn+dVXGoiamDXhZNGukmbMxCISz+FtUfpeC/ZOBMDqhzaZAih9YjefBmSVYb5dRLFmz6916/5RjdaUvgO+5KFcxtH8VQRmVf9lYfdN1s85nv9SxT77xLnXP+sSrChnL11cidY4MYvStO3S2qA4xqZw8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=bIGmewBI; arc=none smtp.client-ip=209.85.208.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="bIGmewBI" Received: by mail-ed1-f51.google.com with SMTP id 4fb4d7f45d1cf-64baaa754c6so6527983a12.3 for ; Mon, 19 Jan 2026 05:18:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1768828737; x=1769433537; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4Jj9JdVBqHdqB0HXN619HZiSF0v0HIUhhUTLIyvICbg=; b=bIGmewBIoAq+cT0Qhjb/uS492Db3u8Tp0aySa1K31MSvBb2Hh2KY+jm0afvZKLOvZL RCzWUzRFhtYiuamP+bLmf9+DpEZS68T31VQQdHgC3OF0+bG2yY2NI/lD5TrP3XPN05ju pJL+o+T03+h+9EjDNwqPIobfBvMAazWmaXELM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768828737; x=1769433537; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4Jj9JdVBqHdqB0HXN619HZiSF0v0HIUhhUTLIyvICbg=; b=vzdF380CjdVcgT0B1EyiHbokKTg7Hxex2d5I8nv5aZpv9W2wNzYbmWWnUaNLYNL6ZZ ePW0JzhSmvBrC+8+ANP2TD3uDeBSEY9aSDHi/4e8CxBIZS8EvoRZhw6ZyOTf/XP+xAE/ 935JwCiecVkaHe49vpQd+rESfpwJ7kjpXOy5Y0vVfARtSvCXkDc4ODq53lP6o1spqos2 OP3g0EEkFuYpKc5wvVHE2baQTEKlinoCRYxAwappsk4vAO6YlMIt/2agwtzpCxR1z0/0 8JAbfK80v4Vc2kXfZCUfenGpnahxNmrWN1PFsBDy+meL7/OT30qXbgasC+5QCZKzqCcP ikDA== X-Forwarded-Encrypted: i=1; AJvYcCXvg/CPH3wjqJfsgiaFvCEG04AQdohcouD7gmIz97Tyan6u3+YJSLqO4Yzv6o8vI2vNCU3oFrL2r+kv3PY=@vger.kernel.org X-Gm-Message-State: AOJu0YxvrWtnVwa6MDDUuYNCXh683RfoVOEbq8OlfdUEbwZLeyrlO0ps GVxWw6J/QDfY2C8oANNzRZmNtdpMnC4rThP6CBNYP7G+zMmeU5VIx3TCk8G7Ramygg== X-Gm-Gg: AY/fxX7zs7+Qse2JH7gPUmFVwSGFUca7NH8kD/aNqwsAgSnvKIKy73npVg7RDqyChW0 yaV3XHe1HNqH1GpXBUXVCWPIU5ralmONop0e8lJqO2SQr8cvu4NbphDxgpRrmIhaoMpsvYjzyfi ZePaC37Jy3GpiBR0uB7M958CyuDA6hihVSALEPlAIWfvSw7nKmVKicBCCLDWbF3yXAqH38J9yp5 udo/WoD2tTAefnTXxC0OP/GksVlJBp1Ivi/1vXfuywxFqPagJTpOj6OriLBPymRgRrSSpPKECMe gDg5Jf4LT+xkT95jNl/6Q/mD4E/+aw7jiD8Rwruia2zKgKzFlee2wNh3RwaFbMZ7HNY2Hq2ZWsG wdW8Kk845DL5Q9ubjjf/kiG4pbor1/O7P1MnTtb65JZSI0L/g3zHKleCcnfZsvgrl4weQP5/e9p 9mV2o4vFemMeCQJkGizckoT4Jx6RGD8UBiH234ozN8NMfAuwna0VzRQqp/51+oLMu3+k7fk0e6y AUQ3g88 X-Received: by 2002:a17:907:8692:b0:b87:6ce:1269 with SMTP id a640c23a62f3a-b8792de8e4cmr919137966b.19.1768828737282; Mon, 19 Jan 2026 05:18:57 -0800 (PST) Received: from akuchynski.c.googlers.com.com (150.230.32.34.bc.googleusercontent.com. [34.32.230.150]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9a14sm1078801866b.45.2026.01.19.05.18.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:18:56 -0800 (PST) From: Andrei Kuchynski To: Heikki Krogerus , Abhishek Pandit-Subedi , Benson Leung , Jameson Thies , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, chrome-platform@lists.linux.dev Cc: Tzung-Bi Shih , Guenter Roeck , Greg Kroah-Hartman , Dmitry Baryshkov , =?UTF-8?q?=C5=81ukasz=20Bartosik?= , Pooja Katiyar , Johan Hovold , Hsin-Te Yuan , Madhu M , Venkat Jayaraman , Andrei Kuchynski Subject: [PATCH v5 7/7] usb: typec: ucsi: Enforce mode selection for cros_ec_ucsi Date: Mon, 19 Jan 2026 13:18:24 +0000 Message-ID: <20260119131824.2529334-8-akuchynski@chromium.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog In-Reply-To: <20260119131824.2529334-1-akuchynski@chromium.org> References: <20260119131824.2529334-1-akuchynski@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- Changes in V5: - Use the no_mode_control field instead of con->ucsi->cap.features & UCSI_CAP_ALT_MODE_OVERRIDE drivers/usb/typec/ucsi/cros_ec_ucsi.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi= /cros_ec_ucsi.c index eed2a7d0ebc63..6bca2dce211cd 100644 --- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c +++ b/drivers/usb/typec/ucsi/cros_ec_ucsi.c @@ -16,6 +16,7 @@ #include #include #include +#include =20 #include "ucsi.h" =20 @@ -33,6 +34,11 @@ /* Number of times to attempt recovery from a write timeout before giving = up. */ #define WRITE_TMO_CTR_MAX 5 =20 +/* Delay between mode entry/exit attempts, ms */ +static const unsigned int mode_selection_delay =3D 1000; +/* Timeout for a mode entry attempt, ms */ +static const unsigned int mode_selection_timeout =3D 4000; + struct cros_ucsi_data { struct device *dev; struct ucsi *ucsi; @@ -134,6 +140,20 @@ static int cros_ucsi_sync_control(struct ucsi *ucsi, u= 64 cmd, u32 *cci, return ret; } =20 +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 =3D { .read_version =3D cros_ucsi_read_version, .read_cci =3D cros_ucsi_read_cci, @@ -141,6 +161,8 @@ static const struct ucsi_operations cros_ucsi_ops =3D { .read_message_in =3D cros_ucsi_read_message_in, .async_control =3D cros_ucsi_async_control, .sync_control =3D cros_ucsi_sync_control, + .add_partner_altmodes =3D cros_ucsi_add_partner_altmodes, + .remove_partner_altmodes =3D cros_ucsi_remove_partner_altmodes, }; =20 static void cros_ucsi_work(struct work_struct *work) --=20 2.52.0.457.g6b5491de43-goog