mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 3/3] drivers: port Linux gpio-mux driver
Date: Mon, 14 Apr 2025 09:05:24 +0200	[thread overview]
Message-ID: <20250414070524.2784496-3-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20250414070524.2784496-1-a.fatoum@pengutronix.de>

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@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@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@axentia.se>");
+MODULE_LICENSE("GPL v2");
-- 
2.39.5




  parent reply	other threads:[~2025-04-14  7:06 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-14  7:05 [PATCH 1/3] base: class: add convenience helpers for iteration Ahmad Fatoum
2025-04-14  7:05 ` [PATCH 2/3] mux: port Linux multiplexer framework Ahmad Fatoum
2025-04-14  7:05 ` Ahmad Fatoum [this message]
2025-04-14 11:33 ` [PATCH 1/3] base: class: add convenience helpers for iteration Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250414070524.2784496-3-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox