[PATCH 3/3] drivers: port Linux gpio-mux driver
Ahmad Fatoum
a.fatoum at pengutronix.de
Mon Apr 14 00:05:24 PDT 2025
The driver builds a single multiplexer controller using a number
of gpio pins. For N pins, there will be 2^N possible multiplexer
states.
The GPIO pins can be connected (by the hardware) to several
multiplexers. Consumer drivers in turn can reference the mux in
the device tree to control it.
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
drivers/mux/Kconfig | 16 +++++++
drivers/mux/Makefile | 2 +
drivers/mux/gpio.c | 103 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 drivers/mux/gpio.c
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index 280e5527efbe..c68f1d4130ee 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -10,4 +10,20 @@ config MULTIPLEXER
menu "Multiplexer drivers"
depends on MULTIPLEXER
+config MUX_GPIO
+ tristate "GPIO-controlled Multiplexer"
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ GPIO-controlled Multiplexer controller.
+
+ The driver builds a single multiplexer controller using a number
+ of gpio pins. For N pins, there will be 2^N possible multiplexer
+ states. The GPIO pins can be connected (by the hardware) to several
+ multiplexers.
+
+ The barebox driver doesn't implement Linux' fastpath, which enables
+ atomically switching GPIOs in the same bank where possible.
+ This means that board code authors need to ensure that intermediate
+ states when switching some of the GPIOs don't break anything.
+
endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 3dfaf766fea7..22d285ed9d4b 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -4,5 +4,7 @@
#
mux-core-objs := core.o
+mux-gpio-objs := gpio.o
obj-$(CONFIG_MULTIPLEXER) += mux-core.o
+obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
diff --git a/drivers/mux/gpio.c b/drivers/mux/gpio.c
new file mode 100644
index 000000000000..4b8a744c2501
--- /dev/null
+++ b/drivers/mux/gpio.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GPIO-controlled multiplexer driver
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <peda at axentia.se>
+ */
+
+#include <linux/bitmap.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
+#include <module.h>
+#include <linux/mux/driver.h>
+#include <driver.h>
+#include <of.h>
+
+struct mux_gpio {
+ struct gpio_descs *gpios;
+};
+
+static int mux_gpio_set(struct mux_control *mux, int state)
+{
+ struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
+ DECLARE_BITMAP(values, BITS_PER_TYPE(state));
+ u32 value = state;
+
+ bitmap_from_arr32(values, &value, BITS_PER_TYPE(value));
+
+ gpiod_set_array_value(mux_gpio->gpios->ndescs,
+ mux_gpio->gpios->desc,
+ mux_gpio->gpios->info, values);
+
+ return 0;
+}
+
+static const struct mux_control_ops mux_gpio_ops = {
+ .set = mux_gpio_set,
+};
+
+static const struct of_device_id mux_gpio_dt_ids[] = {
+ { .compatible = "gpio-mux", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
+
+static int mux_gpio_probe(struct device *dev)
+{
+ struct mux_chip *mux_chip;
+ struct mux_gpio *mux_gpio;
+ int pins;
+ s32 idle_state;
+ int ret;
+
+ pins = gpiod_count(dev, "mux");
+ if (pins < 0)
+ return pins;
+
+ mux_chip = mux_chip_alloc(dev, 1, sizeof(*mux_gpio));
+ if (IS_ERR(mux_chip))
+ return PTR_ERR(mux_chip);
+
+ mux_gpio = mux_chip_priv(mux_chip);
+ mux_chip->ops = &mux_gpio_ops;
+
+ mux_gpio->gpios = gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
+ if (IS_ERR(mux_gpio->gpios))
+ 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);
+
+ ret = of_property_read_u32(dev->of_node, "idle-state", (u32 *)&idle_state);
+ if (ret >= 0 && idle_state != MUX_IDLE_AS_IS) {
+ if (idle_state < 0 || idle_state >= mux_chip->mux->states) {
+ dev_err(dev, "invalid idle-state %u\n", idle_state);
+ return -EINVAL;
+ }
+
+ mux_chip->mux->idle_state = idle_state;
+ }
+
+ ret = mux_chip_register(mux_chip);
+ if (ret < 0)
+ return ret;
+
+ dev_info(dev, "%u-way mux-controller registered\n",
+ mux_chip->mux->states);
+
+ return 0;
+}
+
+static struct driver mux_gpio_driver = {
+ .name = "gpio-mux",
+ .of_match_table = mux_gpio_dt_ids,
+ .probe = mux_gpio_probe,
+};
+coredevice_platform_driver(mux_gpio_driver);
+
+MODULE_DESCRIPTION("GPIO-controlled multiplexer driver");
+MODULE_AUTHOR("Peter Rosin <peda at axentia.se>");
+MODULE_LICENSE("GPL v2");
--
2.39.5
More information about the barebox
mailing list