[PATCH v2] mux: gpio-mux: add support for 4:1 2-channels mux

From: Andrea Tomassetti

Date: Wed May 06 2026 - 08:36:50 EST


Some gpio multiplexers, like TMUX1209, offer differential 4:1
or dual 4:1 single-ended channels. No binding changes are needed
because the DT binding already supports #mux-control-cells
with values 0 and 1. So, similarly to what was already done by the
adg792a driver, the gpio-mux driver has to take into account
the #mux-control-cells property and allocate as many controllers as
advised by it.

As an example, in the DTS you can now define:

tmux1209: mux-controller {
compatible = "gpio-mux";
#mux-control-cells = <1>;

mux-gpios = <&gpio_expander 01 GPIO_ACTIVE_HIGH>,
<&gpio_expander 02 GPIO_ACTIVE_HIGH>;
};

And use it like this:

adcmux30: adcmux30 {
compatible = "io-channel-mux";
io-channels = <&adc1 4>;
io-channel-names = "parent";
#io-channel-cells = <1>;
mux-controls = <&tmux1209 0>;

channels = "S1A", "S2A", "S3A", "S4A";
};

adcmux31: adcmux31 {
compatible = "io-channel-mux";
io-channels = <&adc1 5>;
io-channel-names = "parent";
#io-channel-cells = <1>;
mux-controls = <&tmux1209 1>;

channels = "S1B", "S2B", "S3B", "S4B";
};

Signed-off-by: Andrea Tomassetti <andrea.tomassetti@xxxxxxxxxxx>
Reviewed-by: Linus Walleij <linusw@xxxxxxxxxx>
---
v2: Address feedback from Linus Walleij
- reword commit message by making clear that patching the binding
is not needed
- make clear from error message that binding only allows 0 or 1
- fix two other locations where `mux` was accessed

drivers/mux/gpio.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/mux/gpio.c b/drivers/mux/gpio.c
index 4cc3202c58f3..ab3ed5247d2c 100644
--- a/drivers/mux/gpio.c
+++ b/drivers/mux/gpio.c
@@ -52,12 +52,23 @@ static int mux_gpio_probe(struct platform_device *pdev)
int pins;
s32 idle_state;
int ret;
+ u32 cells;
+ int i;

pins = gpiod_count(dev, "mux");
if (pins < 0)
return pins;

- mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio));
+ ret = device_property_read_u32(dev, "#mux-control-cells", &cells);
+ if (ret < 0)
+ cells = 0;
+
+ if (cells >= 2) {
+ dev_err(dev, "invalid control-cells %u, must be 0 or 1\n", cells);
+ return -EINVAL;
+ }
+
+ mux_chip = devm_mux_chip_alloc(dev, cells + 1, sizeof(*mux_gpio));
if (IS_ERR(mux_chip))
return PTR_ERR(mux_chip);

@@ -69,7 +80,9 @@ static int mux_gpio_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(mux_gpio->gpios),
"failed to get gpios\n");
WARN_ON(pins != mux_gpio->gpios->ndescs);
- mux_chip->mux->states = BIT(pins);
+
+ for (i = 0; i < mux_chip->controllers; ++i)
+ mux_chip->mux[i].states = BIT(pins);

ret = device_property_read_u32(dev, "idle-state", (u32 *)&idle_state);
if (ret >= 0 && idle_state != MUX_IDLE_AS_IS) {
@@ -78,7 +91,8 @@ static int mux_gpio_probe(struct platform_device *pdev)
return -EINVAL;
}

- mux_chip->mux->idle_state = idle_state;
+ for (i = 0; i < mux_chip->controllers; ++i)
+ mux_chip->mux[i].idle_state = idle_state;
}

ret = devm_regulator_get_enable_optional(dev, "mux");
@@ -89,8 +103,8 @@ static int mux_gpio_probe(struct platform_device *pdev)
if (ret < 0)
return ret;

- dev_info(dev, "%u-way mux-controller registered\n",
- mux_chip->mux->states);
+ dev_info(dev, "%u-way mux-controller registered, %u controllers\n",
+ mux_chip->mux->states, mux_chip->controllers);

return 0;
}

base-commit: 74fe02ce122a6103f207d29fafc8b3a53de6abaf
--
2.51.2