Skip to content

Commit

Permalink
kernel: 5.10: backport gpio-cascade and related symbols
Browse files Browse the repository at this point in the history
The patch is under review at [1].

Signed-off-by: Mauri Sandberg <maukka@ext.kapsi.fi>

[1] http://patchwork.ozlabs.org/project/linux-gpio/patch/20211026191506.3099-3-maukka@ext.kapsi.fi/
  • Loading branch information
msandber authored and ynezz committed Feb 19, 2022
1 parent ce7264a commit 966de48
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 0 deletions.
6 changes: 6 additions & 0 deletions target/linux/generic/config-5.10
Expand Up @@ -2085,6 +2085,7 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512
# CONFIG_GPIO_BCM_KONA is not set
# CONFIG_GPIO_BT8XX is not set
# CONFIG_GPIO_CADENCE is not set
# CONFIG_GPIO_CASCADE is not set
# CONFIG_GPIO_CDEV is not set
# CONFIG_GPIO_CDEV_V1 is not set
# CONFIG_GPIO_CS5535 is not set
Expand Down Expand Up @@ -3679,8 +3680,13 @@ CONFIG_MTD_SPLIT_SUPPORT=y
# CONFIG_MTD_NAND_MTK_BMT is not set
# CONFIG_MTK_MMC is not set
# CONFIG_MTK_MMSYS is not set
# CONFIG_MULTIPLEXER is not set
CONFIG_MULTIUSER=y
# CONFIG_MUTEX_SPIN_ON_OWNER is not set
# CONFIG_MUX_ADG792A is not set
# CONFIG_MUX_ADGS1408 is not set
# CONFIG_MUX_GPIO is not set
# CONFIG_MUX_MMIO is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_MVMDIO is not set
# CONFIG_MVNETA_BM is not set
Expand Down
@@ -0,0 +1,232 @@
From fc23ea48ba52c24f201fe5ca0132ee1a3de5a70a Mon Sep 17 00:00:00 2001
From: Mauri Sandberg <maukka@ext.kapsi.fi>
Date: Thu, 25 Mar 2021 11:48:05 +0200
Subject: [PATCH 2/2] gpio: gpio-cascade: add generic GPIO cascade

Adds support for 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 conveyed to the selected cascaded line or, vice versa, the status
of the cascaded line can be conveyed to the upstream line.

A multiplexer 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.

Signed-off-by: Mauri Sandberg <maukka@ext.kapsi.fi>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
v7 -> v8:
- rearrange members in struct gpio_cascade
- cosmetic changes in file header and in one function declaration
- added Reviewed-by tags by Linus and Andy
v6 -> v7:
- In Kconfig add info about module name
- adhere to new convention that allows lines longer than 80 chars
- use dev_probe_err with upstream gpio line too
- refactor for cleaner exit of probe function.
v5 -> v6:
- In Kconfig, remove dependency to OF_GPIO and select only MULTIPLEXER
- refactor code preferring one-liners
- clean up prints, removing them from success-path.
- don't explicitly set gpio_chip.of_node as it's done in the GPIO library
- use devm_gpiochip_add_data instead of gpiochip_add
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
v2 -> v3:
- use managed device resources
- update Kconfig description
v1 -> v2:
- removed .owner from platform_driver as per test bot's instruction
- added MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE
- added gpio_mux_input_get_direction as it's recommended for all chips
- removed because this is input only chip: gpio_mux_input_set_value
- removed because they are not needed for input/output only chips:
gpio_mux_input_direction_input
gpio_mux_input_direction_output
- fixed typo in an error message
- added info message about successful registration
- removed can_sleep flag as this does not sleep while getting GPIO value
like I2C or SPI do
- Updated description in Kconfig
---
drivers/gpio/Kconfig | 15 +++++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-cascade.c | 117 ++++++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+)
create mode 100644 drivers/gpio/gpio-cascade.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 37a6f77c86fe..e69457144459 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1694,4 +1694,19 @@ config GPIO_VIRTIO

endmenu

+comment "Other GPIO expanders"
+
+config GPIO_CASCADE
+ tristate "General GPIO cascade"
+ select MULTIPLEXER
+ help
+ Say yes here to enable support for generic GPIO cascade.
+
+ 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.
+
+ To build the driver as a module choose 'm' and the resulting module
+ will be called 'gpio-cascade'.
+
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 71ee9fc2ff83..e8945456e7ea 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -45,6 +45,7 @@ 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
diff --git a/drivers/gpio/gpio-cascade.c b/drivers/gpio/gpio-cascade.c
new file mode 100644
index 000000000000..5cbda882d79a
--- /dev/null
+++ b/drivers/gpio/gpio-cascade.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * A generic GPIO cascade driver
+ *
+ * Copyright (C) 2021 Mauri Sandberg <maukka@ext.kapsi.fi>
+ *
+ * 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 multiplexer 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 open drain constructions.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mux/consumer.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+
+struct gpio_cascade {
+ struct gpio_chip gpio_chip;
+ struct device *parent;
+ struct mux_control *mux_control;
+ struct gpio_desc *upstream_line;
+};
+
+static struct gpio_cascade *chip_to_cascade(struct gpio_chip *gc)
+{
+ return container_of(gc, struct gpio_cascade, gpio_chip);
+}
+
+static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset)
+{
+ struct gpio_cascade *cas = chip_to_cascade(gc);
+ int ret;
+
+ ret = mux_control_select(cas->mux_control, offset);
+ if (ret)
+ return ret;
+
+ ret = gpiod_get_value(cas->upstream_line);
+ mux_control_deselect(cas->mux_control);
+ return ret;
+}
+
+static int gpio_cascade_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct gpio_cascade *cas;
+ struct mux_control *mc;
+ struct gpio_desc *upstream;
+ struct gpio_chip *gc;
+
+ cas = devm_kzalloc(dev, sizeof(*cas), GFP_KERNEL);
+ if (!cas)
+ return -ENOMEM;
+
+ mc = devm_mux_control_get(dev, NULL);
+ if (IS_ERR(mc))
+ return dev_err_probe(dev, PTR_ERR(mc), "unable to get mux-control\n");
+
+ cas->mux_control = mc;
+ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN);
+ if (IS_ERR(upstream))
+ return dev_err_probe(dev, PTR_ERR(upstream), "unable to claim upstream GPIO line\n");
+
+ cas->upstream_line = upstream;
+ cas->parent = dev;
+
+ 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(cas->parent);
+ gc->parent = cas->parent;
+ gc->owner = THIS_MODULE;
+
+ platform_set_drvdata(pdev, cas);
+ return devm_gpiochip_add_data(dev, &cas->gpio_chip, NULL);
+}
+
+static const struct of_device_id gpio_cascade_id[] = {
+ { .compatible = "gpio-cascade" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, gpio_cascade_id);
+
+static struct platform_driver gpio_cascade_driver = {
+ .driver = {
+ .name = "gpio-cascade",
+ .of_match_table = gpio_cascade_id,
+ },
+ .probe = gpio_cascade_probe,
+};
+module_platform_driver(gpio_cascade_driver);
+
+MODULE_AUTHOR("Mauri Sandberg <maukka@ext.kapsi.fi>");
+MODULE_DESCRIPTION("Generic GPIO cascade");
+MODULE_LICENSE("GPL");
--
2.25.1

0 comments on commit 966de48

Please sign in to comment.