[PATCH v5 0/2] gpio: add generic gpio cascade

From: Mauri Sandberg
Date: Mon Jun 21 2021 - 13:25:41 EST


Hello all,

Thank you for your review comments so far. Here comes new attempt at the gpio
multiplexer driver. There are quite a lot of changes if you look at the diff
based on the v4. Functionality is still the same, though. Only renaming,
refactoring and some more documentation.

What was done
- rename 'gpio-mux-input' -> 'gpio-cascade' in sources
- bindings were changed to reflect the renaming
- refactoring here and there, renaming variables
- documentation was made simpler and more verbose

Drew: I chose to drop the Reviewed-by and Tested-by tags because, even though
mostly renaming, bindings were changed too and that affects functionality. If
you have the time, could you please have another look?

Linus: I hope the changes to the documentation were what you had in mind.

Rob: I fixed a couple of errors that you bot detected but one is due to missing
schema file (gpio-mux) and adding that is not in the scope of this work.

Andy: I dropped the Reported-by tag the bot had instructed me to add.

Thanks,
Mauri

diff between v4 and v5

1: 496558967cd8 ! 1: 83defaf33475 dt-bindings: gpio-mux-input: add documentation
@@ Metadata
Author: Mauri Sandberg <maukka@xxxxxxxxxxxx>

## Commit message ##
- dt-bindings: gpio-mux-input: add documentation
+ dt-bindings: gpio-cascade: add documentation

- Add documentation for a general GPIO multiplexer.
+ Add documentation for a general GPIO cascade. It allows building
+ one-to-many cascades of GPIO lines using multiplexer to choose
+ the cascaded line.

Signed-off-by: Mauri Sandberg <maukka@xxxxxxxxxxxx>
- Tested-by: Drew Fustini <drew@xxxxxxxxxxxxxxx>
- Reviewed-by: Drew Fustini <drew@xxxxxxxxxxxxxxx>
---
+ v4 -> v5:
+ - renamed gpio-mux-input -> gpio-cascade
+ - changed vague term 'pin' to 'upstream line'
+ - added more verbose description for the module
+ - added missing 'mux-controls' entry
+ - dropped Tested-by and Reviewed-by due to changes in bindings
v3 -> v4:
- Changed author email
- Included Tested-by and Reviewed-by from Drew
v2 -> v3: added a complete example on dual 4-way multiplexer
v1 -> v2: added a little bit more text in the binding documenation

- ## Documentation/devicetree/bindings/gpio/gpio-mux-input.yaml (new) ##
+ ## Documentation/devicetree/bindings/gpio/gpio-cascade.yaml (new) ##
@@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
-+$id: http://devicetree.org/schemas/gpio/gpio-mux-input.yaml#
++$id: http://devicetree.org/schemas/gpio/gpio-cascade.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
-+title: Generic GPIO input multiplexer
++title: Generic GPIO cascade
+
+maintainers:
+ - Mauri Sandberg <maukka@xxxxxxxxxxxx>
+
+description: |
-+ A generic GPIO based input multiplexer
++ A generic GPIO cascade
+
-+ This driver uses a mux-controller to drive the multiplexer and has a single
-+ output pin for reading the inputs to the mux.
++ This hardware construction cascades (multiplexes) several GPIO lines from
++ one-to-many using a software controlled multiplexer. The most common use
++ case is probably reading several inputs by switching the multiplexer over
++ several input lines, which in practice works well since input lines has
++ high impedance.
+
-+ For GPIO consumer documentation see gpio.txt.
++ Constructions with multiplexed outputs are also possible using open drain
++ electronics.
++
++ The number of cascaded GPIO lines is limited by the technology used to
++ switch over the cascaded lines. There are readily available dual/triple
++ 4-to-1 multiplexers, for example, and others.
++
++ Illustration (pins used to drive the multiplexer are omitted for clarity)
++
++ /|---- Cascaded GPIO line 0
++ Upstream | |---- Cascaded GPIO line 1
++ GPIO line ----+ | .
++ | | .
++ \|---- Cascaded GPIO line n
+
+properties:
+ compatible:
+ enum:
-+ - gpio-mux-input
++ - gpio-cascade
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ const: 2
+
-+ pin-gpios:
++ mux-controls:
++ minItems: 1
++ maxItems: 1
+ description: |
-+ The GPIO pin used as the output from the multiplexer
++ The mux controller that will be driving the GPIO cascade.
++
++ upstream-gpios:
++ description: |
++ The GPIO line used as the upstream line will convey the status to/from
++ cascaded GPIO lines. In an input mode, by using this line, it is
++ possible to read the status from selected cascaded GPIO line.
++
++ In an output mode the status of the upstream GPIO will be conveyed to
++ the selected cascaded GPIO line.
+
+required:
+ - compatible
+ - gpio-controller
+ - "#gpio-cells"
-+ - pin-gpios
++ - mux-controls
++ - upstream-gpios
+
+additionalProperties: false
+
@@ Documentation/devicetree/bindings/gpio/gpio-mux-input.yaml (new)
+ };
+
+ gpio2: key-mux1 {
-+ compatible = "gpio-mux-input";
++ compatible = "gpio-cascade";
+ mux-controls = <&mux>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
-+ // GPIOs used by this node, mux pin
-+ pin-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
++ // GPIOs used by this node, upstream pin
++ upstream-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
+ };
+
+ gpio3: key-mux2 {
-+ compatible = "gpio-mux-input";
++ compatible = "gpio-cascade";
+ mux-controls = <&mux>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
-+ // GPIOs used by this node, mux pin
-+ pin-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
++ // GPIOs used by this node, upstream pin
++ upstream-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
+ };
+
+...
2: 782e009ba54b ! 2: d1063611d6ac gpio: gpio-mux-input: add generic gpio input multiplexer
@@ Metadata
Author: Mauri Sandberg <maukka@xxxxxxxxxxxx>

## Commit message ##
- gpio: gpio-mux-input: add generic gpio input multiplexer
+ gpio: gpio-cascade: add generic GPIO cascade

- Adds support for a generic GPIO multiplexer. To drive the multiplexer a
- mux-controller is needed. The output pin of the multiplexer is a GPIO
- pin.
+ Adds support for a building cascades of GPIO lines. That is, it allows
+ setups when there is one upstream line and multiple cascaded lines, out
+ of which one can be chosen at a time. The status of the upstream line
+ can be conveyd to the selected cascaded line or, vice versa, the status
+ of the cascaded line can be conveyed to the upstream line.
+
+ A gpio-mux is being used to select, which cascaded GPIO line is being
+ used at any given time.
+
+ At the moment only input direction is supported. In future it should be
+ possible to add support for output direction, too.

- Reported-by: kernel test robot <lkp@xxxxxxxxx>
Signed-off-by: Mauri Sandberg <maukka@xxxxxxxxxxxx>
- Tested-by: Drew Fustini <drew@xxxxxxxxxxxxxxx>
- Reviewed-by: Drew Fustini <drew@xxxxxxxxxxxxxxx>
---
+ v4 -> v5:
+ - renamed gpio-mux-input -> gpio-cascade. refactored code accordingly
+ here and there and changed to use new bindings and compatible string
+ - ambigious and vague 'pin' was rename to 'upstream_line'
+ - dropped Tested-by and Reviewed-by due to changes in bindings
+ - dropped Reported-by suggested by an automatic bot as it was not really
+ appropriate to begin with
+ - functionally it's the same as v4
v3 -> v4:
- Changed author email
- Included Tested-by and Reviewed-by from Drew
@@ drivers/gpio/Kconfig: config GPIO_MOCKUP

+comment "Other GPIO expanders"
+
-+config GPIO_MUX_INPUT
-+ tristate "General GPIO input multiplexer"
++config GPIO_CASCADE
++ tristate "General GPIO cascade"
+ depends on OF_GPIO
+ select MULTIPLEXER
+ select MUX_GPIO
+ help
-+ Say yes here to enable support for generic GPIO input multiplexer.
++ Say yes here to enable support for generic GPIO cascade.
+
-+ This driver uses a mux-controller to drive the multiplexer and has a
-+ single output pin for reading the inputs to the mux. The driver can
-+ be used in situations when GPIO pins are used to select what
-+ multiplexer pin should be used for reading input and the output pin
-+ of the multiplexer is connected to a GPIO input pin.
++ This allows building one-to-many cascades of GPIO lines using
++ different types of multiplexers readily available. At the
++ moment only input lines are supported.
+
endif

## drivers/gpio/Makefile ##
-@@ drivers/gpio/Makefile: obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
- obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
- obj-$(CONFIG_GPIO_MSC313) += gpio-msc313.o
- obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
-+obj-$(CONFIG_GPIO_MUX_INPUT) += gpio-mux-input.o
- obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
- obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
- obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
+@@ drivers/gpio/Makefile: obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
+ obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
+ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
+ obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o
++obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o
+ obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
+ obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o
+ obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o

- ## drivers/gpio/gpio-mux-input.c (new) ##
+ ## drivers/gpio/gpio-cascade.c (new) ##
@@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
-+ * A generic GPIO input multiplexer driver
++ * A generic GPIO cascade driver
+ *
+ * Copyright (C) 2021 Mauri Sandberg <maukka@xxxxxxxxxxxx>
+ *
++ * This allows building cascades of GPIO lines in a manner illustrated
++ * below:
++ *
++ * /|---- Cascaded GPIO line 0
++ * Upstream | |---- Cascaded GPIO line 1
++ * GPIO line ----+ | .
++ * | | .
++ * \|---- Cascaded GPIO line n
++ *
++ * A gpio-mux is being used to select, which cascaded line is being
++ * addressed at any given time.
++ *
++ * At the moment only input mode is supported due to lack of means for
++ * testing output functionality. At least theoretically output should be
++ * possible with an open drain constructions.
+ */
+
+#include <linux/module.h>
@@ drivers/gpio/gpio-mux-input.c (new)
+#include <linux/platform_device.h>
+#include <linux/mux/consumer.h>
+
-+struct gpio_mux_input {
++struct gpio_cascade {
+ struct device *parent;
+ struct gpio_chip gpio_chip;
+ struct mux_control *mux_control;
-+ struct gpio_desc *mux_pin;
++ struct gpio_desc *upstream_line;
+};
+
-+static struct gpio_mux_input *gpio_to_mux(struct gpio_chip *gc)
++static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc)
+{
-+ return container_of(gc, struct gpio_mux_input, gpio_chip);
++ return container_of(gc, struct gpio_cascade, gpio_chip);
+}
+
-+static int gpio_mux_input_get_direction(struct gpio_chip *gc,
++static int gpio_cascade_get_direction(struct gpio_chip *gc,
+ unsigned int offset)
+{
+ return GPIO_LINE_DIRECTION_IN;
+}
+
-+static int gpio_mux_input_get_value(struct gpio_chip *gc, unsigned int offset)
++static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset)
+{
-+ struct gpio_mux_input *mux;
++ struct gpio_cascade *cas;
+ int ret;
+
-+ mux = gpio_to_mux(gc);
-+ ret = mux_control_select(mux->mux_control, offset);
++ cas = chip_to_cascade(gc);
++ ret = mux_control_select(cas->mux_control, offset);
+ if (ret)
+ return ret;
+
-+ ret = gpiod_get_value(mux->mux_pin);
-+ mux_control_deselect(mux->mux_control);
++ ret = gpiod_get_value(cas->upstream_line);
++ mux_control_deselect(cas->mux_control);
+ return ret;
+}
+
-+static int gpio_mux_input_probe(struct platform_device *pdev)
++static int gpio_cascade_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
-+ struct gpio_mux_input *mux;
++ struct gpio_cascade *cas;
+ struct mux_control *mc;
-+ struct gpio_desc *pin;
++ struct gpio_desc *upstream;
+ struct gpio_chip *gc;
+ int err;
+
-+ mux = devm_kzalloc(dev, sizeof(struct gpio_mux_input), GFP_KERNEL);
-+ if (mux == NULL)
++ cas = devm_kzalloc(dev, sizeof(struct gpio_cascade), GFP_KERNEL);
++ if (cas == NULL)
+ return -ENOMEM;
+
+ mc = devm_mux_control_get(dev, NULL);
@@ drivers/gpio/gpio-mux-input.c (new)
+ return err;
+ }
+
-+ mux->mux_control = mc;
-+ pin = devm_gpiod_get(dev, "pin", GPIOD_IN);
-+ if (IS_ERR(pin)) {
-+ err = (int) PTR_ERR(pin);
-+ dev_err(dev, "unable to claim output pin: %d\n", err);
++ cas->mux_control = mc;
++ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN);
++ if (IS_ERR(upstream)) {
++ err = (int) PTR_ERR(upstream);
++ dev_err(dev, "unable to claim upstream GPIO line: %d\n", err);
+ return err;
+ }
+
-+ mux->mux_pin = pin;
-+ mux->parent = dev;
++ cas->upstream_line = upstream;
++ cas->parent = dev;
+
-+ gc = &mux->gpio_chip;
-+ gc->get = gpio_mux_input_get_value;
-+ gc->get_direction = gpio_mux_input_get_direction;
++ gc = &cas->gpio_chip;
++ gc->get = gpio_cascade_get_value;
++ gc->get_direction = gpio_cascade_get_direction;
+
+ gc->base = -1;
+ gc->ngpio = mux_control_states(mc);
-+ gc->label = dev_name(mux->parent);
-+ gc->parent = mux->parent;
++ gc->label = dev_name(cas->parent);
++ gc->parent = cas->parent;
+ gc->owner = THIS_MODULE;
+ gc->of_node = np;
+
-+ err = gpiochip_add(&mux->gpio_chip);
++ err = gpiochip_add(&cas->gpio_chip);
+ if (err) {
+ dev_err(dev, "unable to add gpio chip, err=%d\n", err);
+ return err;
+ }
+
-+ platform_set_drvdata(pdev, mux);
-+ dev_info(dev, "registered %u input GPIOs\n", gc->ngpio);
++ platform_set_drvdata(pdev, cas);
++ dev_info(dev, "registered %u cascaded GPIO lines\n", gc->ngpio);
+ return 0;
+}
+
-+static const struct of_device_id gpio_mux_input_id[] = {
++static const struct of_device_id gpio_cascade_id[] = {
+ {
-+ .compatible = "gpio-mux-input",
++ .compatible = "gpio-cascade",
+ .data = NULL,
+ },
+ { /* sentinel */ }
+};
-+MODULE_DEVICE_TABLE(of, gpio_mux_input_id);
++MODULE_DEVICE_TABLE(of, gpio_cascade_id);
+
-+static struct platform_driver gpio_mux_input_driver = {
++static struct platform_driver gpio_cascade_driver = {
+ .driver = {
-+ .name = "gpio-mux-input",
-+ .of_match_table = gpio_mux_input_id,
++ .name = "gpio-cascade",
++ .of_match_table = gpio_cascade_id,
+ },
-+ .probe = gpio_mux_input_probe,
++ .probe = gpio_cascade_probe,
+};
-+module_platform_driver(gpio_mux_input_driver);
++module_platform_driver(gpio_cascade_driver);
+
+MODULE_AUTHOR("Mauri Sandberg <maukka@xxxxxxxxxxxx>");
-+MODULE_DESCRIPTION("Generic GPIO input multiplexer");
++MODULE_DESCRIPTION("Generic GPIO cascade");
+MODULE_LICENSE("GPL");

Mauri Sandberg (2):
dt-bindings: gpio-cascade: add documentation
gpio: gpio-cascade: add generic GPIO cascade

.../bindings/gpio/gpio-cascade.yaml | 103 +++++++++++++
drivers/gpio/Kconfig | 14 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-cascade.c | 139 ++++++++++++++++++
4 files changed, 257 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-cascade.yaml
create mode 100644 drivers/gpio/gpio-cascade.c


base-commit: 6d49b3a0f351925b5ea5047166c112b7590b918a
--
2.25.1