* [RFC uL PATCH 1/2] dt-bindings: mux-controller: ti: add binding for event mux router
2026-03-13 6:04 [RFC uL PATCH 0/2] Add TI's event mux router driver and build Rahul Sharma
@ 2026-03-13 6:04 ` Rahul Sharma
2026-03-13 6:04 ` [RFC uL PATCH 2/2] mux-controller: ti: add driver " Rahul Sharma
2026-03-13 6:35 ` [RFC uL PATCH 0/2] Add TI's event mux router driver and build Sharma, Rahul
2 siblings, 0 replies; 4+ messages in thread
From: Rahul Sharma @ 2026-03-13 6:04 UTC (permalink / raw)
To: peda, robh, krzk+dt, conor+dt
Cc: devicetree, vigneshr, r-sharma3, linux-kernel
Add binding for the event mux router of TI's K3 based SoC AM62L.
The TI K3 mux routers which route the GPIO input events or Time-Sync
events b/w peripherals instead of routing to a CPU.
Refer Section 10.2 and 10.2.1 of https://www.ti.com/lit/pdf/sprujb4
Signed-off-by: Rahul Sharma <r-sharma3@ti.com>
---
.../mux/ti,am62l-event-mux-router.yaml | 79 +++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mux/ti,am62l-event-mux-router.yaml
diff --git a/Documentation/devicetree/bindings/mux/ti,am62l-event-mux-router.yaml b/Documentation/devicetree/bindings/mux/ti,am62l-event-mux-router.yaml
new file mode 100644
index 000000000000..5401b0542eff
--- /dev/null
+++ b/Documentation/devicetree/bindings/mux/ti,am62l-event-mux-router.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mux/ti,am62l-event-mux-router.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI Event Multiplexer on K3 SoCs
+
+maintainers:
+ - Rahul Sharma <r-sharma3@ti.com>
+
+description:
+ The TI K3 mux routers routes the GPIO input events or Time
+ Sync events between peripherals instead of routing to a CPU.
+
+allOf:
+ - $ref: mux-controller.yaml#
+
+properties:
+ compatible:
+ const: ti,am62l-event-mux-router
+
+ reg:
+ description: Register base address and size.
+ maxItems: 1
+
+ '#mux-control-cells':
+ const: 1
+ description:
+ Number of cells in a mux control specifier. This should be 1.
+ The cell specifies which mux control to use (0-based index).
+
+ ti,reg-mask-val:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ items:
+ items:
+ - description: Register offset (relative to reg base)
+ - description: Bit mask for the mux control bits
+ - description: Value to write when mux is active (state 1)
+ minItems: 1
+ description: |
+ Array of triplets specifying register offset, mask, and value for each
+ mux control. Each triplet contains:
+ - register offset (relative to reg base or syscon)
+ - bit mask for the mux control bits
+ - value to write when mux is active (state 1)
+
+ idle-states:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: |
+ Idle state for each mux control. Each entry corresponds to a mux control:
+ - 0: clear masked bits when idle, also refers to inactive state
+ - 1: set configured value when idle, also refers to active state
+ - MUX_IDLE_AS_IS (-1): keep current state when idle
+
+required:
+ - compatible
+ - reg
+ - '#mux-control-cells'
+ - ti,reg-mask-val
+ - idle-states
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/mux/mux.h>
+
+ // Example 1: TI AM62L GPIO Mux Router
+ mux-controller@a00000 {
+ compatible = "ti,am62l-event-mux-router";
+ reg = <0xa00000 0x400>;
+ #mux-control-cells = <1>;
+
+ /* Mux Register addresses: 0xa00004 + (J × 4) */
+ /* GPIO0_40 -> BCDMA trigger 15 */
+ ti,reg-mask-val = <0x40 0x000ff 0x00028>;
+ idle-states = <0>;
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [RFC uL PATCH 2/2] mux-controller: ti: add driver for event mux router
2026-03-13 6:04 [RFC uL PATCH 0/2] Add TI's event mux router driver and build Rahul Sharma
2026-03-13 6:04 ` [RFC uL PATCH 1/2] dt-bindings: mux-controller: ti: add binding for event mux router Rahul Sharma
@ 2026-03-13 6:04 ` Rahul Sharma
2026-03-13 6:35 ` [RFC uL PATCH 0/2] Add TI's event mux router driver and build Sharma, Rahul
2 siblings, 0 replies; 4+ messages in thread
From: Rahul Sharma @ 2026-03-13 6:04 UTC (permalink / raw)
To: peda, robh, krzk+dt, conor+dt
Cc: devicetree, vigneshr, r-sharma3, linux-kernel
The driver supports event muxing routers like gpio mux router and timesync
router. This driver is adaptation of original reg-mux driver, along with
changes specific to support TI's mux router.
The idle states this driver supports are only 2 which active(represented
by 1 in dt-node) and in-active(represented by 0 in dt-node).
Signed-off-by: Rahul Sharma <r-sharma3@ti.com>
---
drivers/mux/Kconfig | 15 +++
drivers/mux/Makefile | 2 +
drivers/mux/ti-k3-event-mux.c | 235 ++++++++++++++++++++++++++++++++++
3 files changed, 252 insertions(+)
create mode 100644 drivers/mux/ti-k3-event-mux.c
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index c68132e38138..ad3af2724d28 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -59,4 +59,19 @@ config MUX_MMIO
To compile the driver as a module, choose M here: the module will
be called mux-mmio.
+config MUX_TI_K3_EVENT_ROUTER
+ tristate "TI Event Mux Router using MMIO registers"
+ depends on OF && (REGMAP_MMIO || COMPILE_TEST)
+ help
+ This is extension of MMIO mux for timesync router and gpiomux
+ routers on TI K3 SoCs. This driver supports the 3-field format for
+ mux control: <register-offset mask value>.
+
+ The driver allows configuration of hardware mux routers using
+ memory-mapped registers. It's based on the mmio-mux driver but
+ supports the extended 3-field format for more precise control.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-ti-k3-event.
+
endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 6e9fa47daf56..f3f367de84da 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -8,9 +8,11 @@ mux-adg792a-objs := adg792a.o
mux-adgs1408-objs := adgs1408.o
mux-gpio-objs := gpio.o
mux-mmio-objs := mmio.o
+mux-ti-k3-event-objs := ti-k3-event-mux.o
obj-$(CONFIG_MULTIPLEXER) += mux-core.o
obj-$(CONFIG_MUX_ADG792A) += mux-adg792a.o
obj-$(CONFIG_MUX_ADGS1408) += mux-adgs1408.o
obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
+obj-$(CONFIG_MUX_TI_K3_EVENT_ROUTER) += mux-ti-k3-event.o
diff --git a/drivers/mux/ti-k3-event-mux.c b/drivers/mux/ti-k3-event-mux.c
new file mode 100644
index 000000000000..2469500d1b48
--- /dev/null
+++ b/drivers/mux/ti-k3-event-mux.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MMIO register bit-field controlled multiplexer driver
+ *
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com
+ *
+ * Based on drivers/mux/mmio.c by Philipp Zabel <kernel@pengutronix.de>
+ * Modified to support 3-field format: reg-offset, mask & value
+ *
+ * Author: Rahul Sharma <r-sharma3@ti.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mux/driver.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+#define MUX_ENABLE_INTR BIT(16)
+
+struct mux_ti_k3_event {
+ struct regmap *regmap;
+ u32 reg;
+ u32 mask;
+ u32 value;
+};
+
+struct mux_ti_k3_event_chip {
+ struct mux_chip *mux_chip;
+ struct mux_ti_k3_event *fields;
+ int num_fields;
+ u32 *saved_states;
+};
+
+static int mux_ti_k3_event_suspend(struct device *dev)
+{
+ struct mux_ti_k3_event_chip *chip = dev_get_drvdata(dev);
+ int i, ret;
+
+ if (!chip->saved_states) {
+ chip->saved_states = devm_kcalloc(dev, chip->num_fields,
+ sizeof(u32), GFP_KERNEL);
+ if (!chip->saved_states)
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < chip->num_fields; i++) {
+ struct mux_ti_k3_event *field = &chip->fields[i];
+
+ ret = regmap_read(field->regmap, field->reg,
+ &chip->saved_states[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mux_ti_k3_event_resume(struct device *dev)
+{
+ struct mux_ti_k3_event_chip *chip = dev_get_drvdata(dev);
+ int i, ret;
+
+ if (!chip->saved_states)
+ return 0;
+
+ for (i = 0; i < chip->num_fields; i++) {
+ struct mux_ti_k3_event *field = &chip->fields[i];
+
+ ret = regmap_write(field->regmap, field->reg,
+ chip->saved_states[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(mux_ti_k3_event_pm_ops,
+ mux_ti_k3_event_suspend,
+ mux_ti_k3_event_resume);
+
+/*
+ * State behavior:
+ * - state 0: Clears the mask bits in the target register (inactive state)
+ * - state 1: Sets both the value bits and enable bit (bit 16) in the register
+ */
+static int mux_ti_k3_event_set(struct mux_control *mux, int state)
+{
+ struct mux_ti_k3_event *fields = mux_chip_priv(mux->chip);
+ struct mux_ti_k3_event *field = &fields[mux_control_get_index(mux)];
+
+ if (!state)
+ return regmap_update_bits(field->regmap, field->reg, field->mask, 0);
+
+ return regmap_update_bits(field->regmap, field->reg, field->mask | MUX_ENABLE_INTR,
+ field->value | MUX_ENABLE_INTR);
+}
+
+static const struct mux_control_ops mux_ti_k3_event_ops = {
+ .set = mux_ti_k3_event_set,
+};
+
+static const struct regmap_config mux_ti_k3_event_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int mux_ti_k3_event_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct mux_ti_k3_event_chip *chip;
+ struct mux_ti_k3_event *fields;
+ struct mux_chip *mux_chip;
+ struct regmap *regmap;
+ void __iomem *base;
+ int num_fields;
+ int ret;
+ int i;
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base)) {
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get base address\n");
+ } else {
+ regmap = devm_regmap_init_mmio(dev, base, &mux_ti_k3_event_regmap_cfg);
+ }
+ if (IS_ERR(regmap)) {
+ iounmap(base);
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to get regmap\n");
+ }
+
+ ret = of_property_count_u32_elems(np, "ti,reg-mask-val");
+ if (!ret || ret % 3) {
+ ret = -EINVAL;
+ dev_err(dev, "ti,reg-mask-val property missing or invalid: %d\n",
+ ret);
+ return ret;
+ }
+
+ num_fields = ret / 3;
+ mux_chip = devm_mux_chip_alloc(dev, num_fields, num_fields *
+ sizeof(*fields));
+ if (IS_ERR(mux_chip))
+ return PTR_ERR(mux_chip);
+
+ fields = mux_chip_priv(mux_chip);
+ chip->mux_chip = mux_chip;
+ chip->fields = fields;
+ chip->num_fields = num_fields;
+
+ platform_set_drvdata(pdev, chip);
+
+ for (i = 0; i < num_fields; i++) {
+ struct mux_control *mux = &mux_chip->mux[i];
+ s32 idle_state = MUX_IDLE_AS_IS;
+ u32 reg, mask, value;
+
+ ret = of_property_read_u32_index(np, "ti,reg-mask-val",
+ 3 * i, ®);
+ if (!ret)
+ ret = of_property_read_u32_index(np, "ti,reg-mask-val",
+ 3 * i + 1, &mask);
+ if (!ret)
+ ret = of_property_read_u32_index(np, "ti,reg-mask-val",
+ 3 * i + 2, &value);
+ if (ret < 0) {
+ dev_err(dev, "field %d: failed to read ti,reg-mask-val property: %d\n",
+ i, ret);
+ return ret;
+ }
+
+ /* Validate that value bits are within mask */
+ if (value & ~mask) {
+ dev_err(dev, "field %d: value 0x%x has bits outside mask 0x%x\n",
+ i, value, mask);
+ return -EINVAL;
+ }
+
+ fields[i].regmap = regmap;
+ fields[i].reg = reg;
+ fields[i].mask = mask;
+ fields[i].value = value;
+
+ /* This driver supports binary mux (2 states: 0 and active) */
+ mux->states = 2;
+
+ of_property_read_u32_index(np, "idle-states", i,
+ (u32 *)&idle_state);
+ if (idle_state != MUX_IDLE_AS_IS) {
+ if (idle_state < 0 || idle_state >= mux->states) {
+ dev_err(dev, "field: %d: out of range idle state %d\n",
+ i, idle_state);
+ return -EINVAL;
+ }
+
+ mux->idle_state = idle_state;
+ }
+ }
+
+ mux_chip->ops = &mux_ti_k3_event_ops;
+
+ return devm_mux_chip_register(dev, mux_chip);
+}
+
+static const struct of_device_id mux_ti_k3_event_dt_ids[] = {
+ { .compatible = "ti,am62l-event-mux-router", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_ti_k3_event_dt_ids);
+
+static struct platform_driver mux_ti_k3_event_driver = {
+ .driver = {
+ .name = "ti-k3-event-mux",
+ .of_match_table = mux_ti_k3_event_dt_ids,
+ .pm = &mux_ti_k3_event_pm_ops,
+ },
+ .probe = mux_ti_k3_event_probe,
+};
+module_platform_driver(mux_ti_k3_event_driver);
+
+MODULE_DESCRIPTION("TI K3 Bit-field Controlled Event Multiplexer driver");
+MODULE_AUTHOR("Rahul Sharma <r-sharma3@ti.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread