This patch introduces APIs to manage the priority of USB Type-C alternate modes. These APIs allow for setting and retrieving a priority number for each mode. 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 <akuchynski@xxxxxxxxxxxx> --- drivers/usb/typec/Makefile | 2 +- drivers/usb/typec/mode_selection.c | 38 ++++++++++++++++++++++++++++++ drivers/usb/typec/mode_selection.h | 6 +++++ include/linux/usb/typec_altmode.h | 1 + 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/typec/mode_selection.c create mode 100644 drivers/usb/typec/mode_selection.h diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index 7a368fea61bc..8a6a1c663eb6 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TYPEC) += typec.o -typec-y := class.o mux.o bus.o pd.o retimer.o +typec-y := class.o mux.o bus.o pd.o retimer.o mode_selection.o typec-$(CONFIG_ACPI) += port-mapper.o obj-$(CONFIG_TYPEC) += altmodes/ obj-$(CONFIG_TYPEC_TCPM) += tcpm/ diff --git a/drivers/usb/typec/mode_selection.c b/drivers/usb/typec/mode_selection.c new file mode 100644 index 000000000000..2179bf25f5d4 --- /dev/null +++ b/drivers/usb/typec/mode_selection.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2025 Google LLC. + */ + +#include "mode_selection.h" +#include "class.h" +#include "bus.h" + +static int increment_duplicated_priority(struct device *dev, void *data) +{ + struct typec_altmode **alt_target = (struct typec_altmode **)data; + + if (is_typec_altmode(dev)) { + struct typec_altmode *alt = to_typec_altmode(dev); + + if (alt != *alt_target && alt->priority == (*alt_target)->priority) { + alt->priority++; + *alt_target = alt; + return 1; + } + } + + return 0; +} + +void typec_mode_set_priority(struct typec_altmode *alt, + const unsigned int priority) +{ + struct typec_port *port = to_typec_port(alt->dev.parent); + int res = 1; + + alt->priority = priority; + + while (res) + res = device_for_each_child(&port->dev, &alt, + increment_duplicated_priority); +} diff --git a/drivers/usb/typec/mode_selection.h b/drivers/usb/typec/mode_selection.h new file mode 100644 index 000000000000..cbf5a37e6404 --- /dev/null +++ b/drivers/usb/typec/mode_selection.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/usb/typec_altmode.h> + +void typec_mode_set_priority(struct typec_altmode *alt, + const unsigned int priority); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h index b3c0866ea70f..571c6e00b54f 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -28,6 +28,7 @@ struct typec_altmode { int mode; u32 vdo; unsigned int active:1; + unsigned int priority; char *desc; const struct typec_altmode_ops *ops; -- 2.51.0.rc2.233.g662b1ed5c5-goog