kernel: 5.10: backport gpio-cascade and related symbols
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/
This commit is contained in:
		 Mauri Sandberg
					Mauri Sandberg
				
			
				
					committed by
					
						 Petr Štetiar
						Petr Štetiar
					
				
			
			
				
	
			
			
			 Petr Štetiar
						Petr Štetiar
					
				
			
						parent
						
							ce7264a6e0
						
					
				
				
					commit
					966de48813
				
			| @@ -2085,6 +2085,7 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 | |||||||
| # CONFIG_GPIO_BCM_KONA is not set | # CONFIG_GPIO_BCM_KONA is not set | ||||||
| # CONFIG_GPIO_BT8XX is not set | # CONFIG_GPIO_BT8XX is not set | ||||||
| # CONFIG_GPIO_CADENCE is not set | # CONFIG_GPIO_CADENCE is not set | ||||||
|  | # CONFIG_GPIO_CASCADE is not set | ||||||
| # CONFIG_GPIO_CDEV is not set | # CONFIG_GPIO_CDEV is not set | ||||||
| # CONFIG_GPIO_CDEV_V1 is not set | # CONFIG_GPIO_CDEV_V1 is not set | ||||||
| # CONFIG_GPIO_CS5535 is not set | # CONFIG_GPIO_CS5535 is not set | ||||||
| @@ -3679,8 +3680,13 @@ CONFIG_MTD_SPLIT_SUPPORT=y | |||||||
| # CONFIG_MTD_NAND_MTK_BMT is not set | # CONFIG_MTD_NAND_MTK_BMT is not set | ||||||
| # CONFIG_MTK_MMC is not set | # CONFIG_MTK_MMC is not set | ||||||
| # CONFIG_MTK_MMSYS is not set | # CONFIG_MTK_MMSYS is not set | ||||||
|  | # CONFIG_MULTIPLEXER is not set | ||||||
| CONFIG_MULTIUSER=y | CONFIG_MULTIUSER=y | ||||||
| # CONFIG_MUTEX_SPIN_ON_OWNER is not set | # 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_MV643XX_ETH is not set | ||||||
| # CONFIG_MVMDIO is not set | # CONFIG_MVMDIO is not set | ||||||
| # CONFIG_MVNETA_BM is not set | # CONFIG_MVNETA_BM is not set | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user