From db2056e21c666ec83d5ecbaf973fe5505405e8e0 Mon Sep 17 00:00:00 2001 From: Yinbo Zhu Date: Thu, 2 Mar 2023 16:17:10 +0800 Subject: dt-bindings: gpio: add loongson gpio Add the Loongson platform gpio binding with DT schema format using json-schema. Signed-off-by: Yinbo Zhu Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bartosz Golaszewski --- .../devicetree/bindings/gpio/loongson,ls-gpio.yaml | 126 +++++++++++++++++++++ MAINTAINERS | 6 + 2 files changed, 132 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml diff --git a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml new file mode 100644 index 000000000000..fb86e8ce6349 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/loongson,ls-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson GPIO controller. + +maintainers: + - Yinbo Zhu + +properties: + compatible: + enum: + - loongson,ls2k-gpio + - loongson,ls7a-gpio + + reg: + maxItems: 1 + + ngpios: + minimum: 1 + maximum: 64 + + "#gpio-cells": + const: 2 + + gpio-controller: true + + gpio-ranges: true + + interrupts: + minItems: 1 + maxItems: 64 + +required: + - compatible + - reg + - ngpios + - "#gpio-cells" + - gpio-controller + - gpio-ranges + - interrupts + +additionalProperties: false + +examples: + - | + #include + + gpio0: gpio@1fe00500 { + compatible = "loongson,ls2k-gpio"; + reg = <0x1fe00500 0x38>; + ngpios = <64>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pctrl 0 0 15>, + <&pctrl 16 16 15>, + <&pctrl 32 32 10>, + <&pctrl 44 44 20>; + interrupt-parent = <&liointc1>; + interrupts = <28 IRQ_TYPE_LEVEL_LOW>, + <29 IRQ_TYPE_LEVEL_LOW>, + <30 IRQ_TYPE_LEVEL_LOW>, + <30 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <26 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <>, + <>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>, + <27 IRQ_TYPE_LEVEL_LOW>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..adc828919771 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12116,6 +12116,12 @@ S: Maintained F: Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml F: drivers/pinctrl/pinctrl-loongson2.c +LOONGSON GPIO DRIVER +M: Yinbo Zhu +L: linux-gpio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml + LOONGSON-2 SOC SERIES CLOCK DRIVER M: Yinbo Zhu L: linux-clk@vger.kernel.org -- cgit From 7944d3b7fe86067509751473aa917fdfd662d92c Mon Sep 17 00:00:00 2001 From: Yinbo Zhu Date: Thu, 2 Mar 2023 16:17:11 +0800 Subject: gpio: loongson: add gpio driver support The Loongson platforms GPIO controller contains 60 GPIO pins in total, 4 of which are dedicated GPIO pins, and the remaining 56 are reused with other functions. Each GPIO can set input/output and has the interrupt capability. This driver added support for Loongson GPIO controller and support to use DTS or ACPI to descibe GPIO device resources. Signed-off-by: Jianmin Lv Signed-off-by: Hongchen Zhang Signed-off-by: Liu Peibao Signed-off-by: Juxin Gao Signed-off-by: Yinbo Zhu Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- MAINTAINERS | 1 + drivers/gpio/Kconfig | 12 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-loongson-64bit.c | 239 +++++++++++++++++++++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 drivers/gpio/gpio-loongson-64bit.c diff --git a/MAINTAINERS b/MAINTAINERS index adc828919771..ec309d7ff813 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12121,6 +12121,7 @@ M: Yinbo Zhu L: linux-gpio@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml +F: drivers/gpio/gpio-loongson-64bit.c LOONGSON-2 SOC SERIES CLOCK DRIVER M: Yinbo Zhu diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 13be729710f2..98114768c86a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -380,6 +380,18 @@ config GPIO_LOONGSON help Driver for GPIO functionality on Loongson-2F/3A/3B processors. +config GPIO_LOONGSON_64BIT + tristate "Loongson 64 bit GPIO support" + depends on LOONGARCH || COMPILE_TEST + select OF_GPIO + select GPIO_GENERIC + help + Say yes here to support the GPIO functionality of a number of + Loongson series of chips. The Loongson GPIO controller supports + up to 60 GPIOS in total, 4 of which are dedicated GPIO pins, and + the remaining 56 are reused with other functions, with edge or + level triggered interrupts. + config GPIO_LPC18XX tristate "NXP LPC18XX/43XX GPIO support" default y if ARCH_LPC18XX diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c048ba003367..73d1ec260c14 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o +obj-$(CONFIG_GPIO_LOONGSON_64BIT) += gpio-loongson-64bit.o obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o diff --git a/drivers/gpio/gpio-loongson-64bit.c b/drivers/gpio/gpio-loongson-64bit.c new file mode 100644 index 000000000000..20a68e5e66c1 --- /dev/null +++ b/drivers/gpio/gpio-loongson-64bit.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Loongson GPIO Support + * + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum loongson_gpio_mode { + BIT_CTRL_MODE, + BYTE_CTRL_MODE, +}; + +struct loongson_gpio_chip_data { + const char *label; + enum loongson_gpio_mode mode; + unsigned int conf_offset; + unsigned int out_offset; + unsigned int in_offset; +}; + +struct loongson_gpio_chip { + struct gpio_chip chip; + struct fwnode_handle *fwnode; + spinlock_t lock; + void __iomem *reg_base; + const struct loongson_gpio_chip_data *chip_data; +}; + +static inline struct loongson_gpio_chip *to_loongson_gpio_chip(struct gpio_chip *chip) +{ + return container_of(chip, struct loongson_gpio_chip, chip); +} + +static inline void loongson_commit_direction(struct loongson_gpio_chip *lgpio, unsigned int pin, + int input) +{ + u8 bval = input ? 1 : 0; + + writeb(bval, lgpio->reg_base + lgpio->chip_data->conf_offset + pin); +} + +static void loongson_commit_level(struct loongson_gpio_chip *lgpio, unsigned int pin, int high) +{ + u8 bval = high ? 1 : 0; + + writeb(bval, lgpio->reg_base + lgpio->chip_data->out_offset + pin); +} + +static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned int pin) +{ + unsigned long flags; + struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip); + + spin_lock_irqsave(&lgpio->lock, flags); + loongson_commit_direction(lgpio, pin, 1); + spin_unlock_irqrestore(&lgpio->lock, flags); + + return 0; +} + +static int loongson_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, int value) +{ + unsigned long flags; + struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip); + + spin_lock_irqsave(&lgpio->lock, flags); + loongson_commit_level(lgpio, pin, value); + loongson_commit_direction(lgpio, pin, 0); + spin_unlock_irqrestore(&lgpio->lock, flags); + + return 0; +} + +static int loongson_gpio_get(struct gpio_chip *chip, unsigned int pin) +{ + u8 bval; + int val; + struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip); + + bval = readb(lgpio->reg_base + lgpio->chip_data->in_offset + pin); + val = bval & 1; + + return val; +} + +static int loongson_gpio_get_direction(struct gpio_chip *chip, unsigned int pin) +{ + u8 bval; + struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip); + + bval = readb(lgpio->reg_base + lgpio->chip_data->conf_offset + pin); + if (bval & 1) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; +} + +static void loongson_gpio_set(struct gpio_chip *chip, unsigned int pin, int value) +{ + unsigned long flags; + struct loongson_gpio_chip *lgpio = to_loongson_gpio_chip(chip); + + spin_lock_irqsave(&lgpio->lock, flags); + loongson_commit_level(lgpio, pin, value); + spin_unlock_irqrestore(&lgpio->lock, flags); +} + +static int loongson_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct platform_device *pdev = to_platform_device(chip->parent); + + return platform_get_irq(pdev, offset); +} + +static int loongson_gpio_init(struct device *dev, struct loongson_gpio_chip *lgpio, + struct device_node *np, void __iomem *reg_base) +{ + int ret; + u32 ngpios; + + lgpio->reg_base = reg_base; + + if (lgpio->chip_data->mode == BIT_CTRL_MODE) { + ret = bgpio_init(&lgpio->chip, dev, 8, + lgpio->reg_base + lgpio->chip_data->in_offset, + lgpio->reg_base + lgpio->chip_data->out_offset, + NULL, NULL, + lgpio->reg_base + lgpio->chip_data->conf_offset, + 0); + if (ret) { + dev_err(dev, "unable to init generic GPIO\n"); + return ret; + } + } else { + lgpio->chip.direction_input = loongson_gpio_direction_input; + lgpio->chip.get = loongson_gpio_get; + lgpio->chip.get_direction = loongson_gpio_get_direction; + lgpio->chip.direction_output = loongson_gpio_direction_output; + lgpio->chip.set = loongson_gpio_set; + lgpio->chip.parent = dev; + spin_lock_init(&lgpio->lock); + } + + device_property_read_u32(dev, "ngpios", &ngpios); + + lgpio->chip.can_sleep = 0; + lgpio->chip.ngpio = ngpios; + lgpio->chip.label = lgpio->chip_data->label; + lgpio->chip.to_irq = loongson_gpio_to_irq; + + return devm_gpiochip_add_data(dev, &lgpio->chip, lgpio); +} + +static int loongson_gpio_probe(struct platform_device *pdev) +{ + void __iomem *reg_base; + struct loongson_gpio_chip *lgpio; + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + + lgpio = devm_kzalloc(dev, sizeof(*lgpio), GFP_KERNEL); + if (!lgpio) + return -ENOMEM; + + lgpio->chip_data = device_get_match_data(dev); + + reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + + return loongson_gpio_init(dev, lgpio, np, reg_base); +} + +static const struct loongson_gpio_chip_data loongson_gpio_ls2k_data = { + .label = "ls2k_gpio", + .mode = BIT_CTRL_MODE, + .conf_offset = 0x0, + .in_offset = 0x20, + .out_offset = 0x10, +}; + +static const struct loongson_gpio_chip_data loongson_gpio_ls7a_data = { + .label = "ls7a_gpio", + .mode = BYTE_CTRL_MODE, + .conf_offset = 0x800, + .in_offset = 0xa00, + .out_offset = 0x900, +}; + +static const struct of_device_id loongson_gpio_of_match[] = { + { + .compatible = "loongson,ls2k-gpio", + .data = &loongson_gpio_ls2k_data, + }, + { + .compatible = "loongson,ls7a-gpio", + .data = &loongson_gpio_ls7a_data, + }, + {} +}; +MODULE_DEVICE_TABLE(of, loongson_gpio_of_match); + +static const struct acpi_device_id loongson_gpio_acpi_match[] = { + { + .id = "LOON0002", + .driver_data = (kernel_ulong_t)&loongson_gpio_ls7a_data, + }, + {} +}; +MODULE_DEVICE_TABLE(acpi, loongson_gpio_acpi_match); + +static struct platform_driver loongson_gpio_driver = { + .driver = { + .name = "loongson-gpio", + .owner = THIS_MODULE, + .of_match_table = loongson_gpio_of_match, + .acpi_match_table = loongson_gpio_acpi_match, + }, + .probe = loongson_gpio_probe, +}; + +static int __init loongson_gpio_setup(void) +{ + return platform_driver_register(&loongson_gpio_driver); +} +postcore_initcall(loongson_gpio_setup); + +MODULE_DESCRIPTION("Loongson gpio driver"); +MODULE_LICENSE("GPL"); -- cgit From 68d94cca3b9d297aedf7321a823d0e72ce0f283f Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Fri, 24 Feb 2023 15:07:45 +0000 Subject: gpio: remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Cc: Luis Chamberlain Cc: linux-modules@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Hitomi Hasegawa Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Shawn Guo Cc: Sascha Hauer Cc: linux-gpio@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-imx-scu.c | 1 - drivers/gpio/gpio-mxs.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/gpio/gpio-imx-scu.c b/drivers/gpio/gpio-imx-scu.c index 17be21b8f3b7..e190bde5397d 100644 --- a/drivers/gpio/gpio-imx-scu.c +++ b/drivers/gpio/gpio-imx-scu.c @@ -136,4 +136,3 @@ subsys_initcall_sync(_imx_scu_gpio_init); MODULE_AUTHOR("Shenwei Wang "); MODULE_DESCRIPTION("NXP GPIO over IMX SCU API"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 7f59e5d936c2..390e619a2831 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -364,4 +364,3 @@ MODULE_AUTHOR("Freescale Semiconductor, " "Daniel Mack , " "Juergen Beisert "); MODULE_DESCRIPTION("Freescale MXS GPIO"); -MODULE_LICENSE("GPL"); -- cgit From b961b2aa2f64a828a77749b82989ba2968cdf344 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 8 Feb 2023 05:55:42 -0500 Subject: gpio: 104-dio-48e: Utilize mask_buf_def in handle_mask_sync() callback The mask_buf_def argument provides a mask of all the maskable lines. Utilize mask_buf_def rather than hardcode an "all_masked" mask. Signed-off-by: William Breathitt Gray Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-104-dio-48e.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index a3846faf3780..74e2721f2613 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -106,7 +106,6 @@ static int dio48e_handle_mask_sync(struct regmap *const map, const int index, { unsigned int *const irq_mask = irq_drv_data; const unsigned int prev_mask = *irq_mask; - const unsigned int all_masked = GENMASK(1, 0); int err; unsigned int val; @@ -118,7 +117,7 @@ static int dio48e_handle_mask_sync(struct regmap *const map, const int index, *irq_mask = mask_buf; /* if all previously masked, enable interrupts when unmasking */ - if (prev_mask == all_masked) { + if (prev_mask == mask_buf_def) { err = regmap_write(map, DIO48E_CLEAR_INTERRUPT, 0x00); if (err) return err; @@ -126,7 +125,7 @@ static int dio48e_handle_mask_sync(struct regmap *const map, const int index, } /* if all are currently masked, disable interrupts */ - if (mask_buf == all_masked) + if (mask_buf == mask_buf_def) return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val); return 0; -- cgit From 63de20ca24dd00074e2a3d6dc84c3067bba9e788 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 16 Feb 2023 10:19:09 +0100 Subject: gpio: pmic-eic-sprd: Move Kconfig to MFD expanders The Spreadtrum PMIC EIC interrupt controller is part of an MFD expander and should thus be in the MFD GPIO expander menu section with the rest. Move it. Cc: Cixi Geng Cc: Baolin Wang Signed-off-by: Linus Walleij Reviewed-by: Baolin Wang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 98114768c86a..5d0804d58c0a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -497,14 +497,6 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device. -config GPIO_PMIC_EIC_SPRD - tristate "Spreadtrum PMIC EIC support" - depends on MFD_SC27XX_PMIC || COMPILE_TEST - depends on OF_GPIO - select GPIOLIB_IRQCHIP - help - Say yes here to support Spreadtrum PMIC EIC device. - config GPIO_PXA bool "PXA GPIO support" depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST @@ -1323,6 +1315,14 @@ config GPIO_PALMAS Select this option to enable GPIO driver for the TI PALMAS series chip family. +config GPIO_PMIC_EIC_SPRD + tristate "Spreadtrum PMIC EIC support" + depends on MFD_SC27XX_PMIC || COMPILE_TEST + depends on OF_GPIO + select GPIOLIB_IRQCHIP + help + Say yes here to support Spreadtrum PMIC EIC device. + config GPIO_RC5T583 bool "RICOH RC5T583 GPIO" depends on MFD_RC5T583 -- cgit From db9da1959db3d1e0637af4339776b285bacb0c69 Mon Sep 17 00:00:00 2001 From: Trevor Woerner Date: Fri, 10 Feb 2023 22:06:45 -0500 Subject: dt-bindings: gpio.txt: expand gpio-line-names recommendations Provide more guidance to differentiate between recommendations for names of lines which are hard-wired to on-board devices, versus recommendations for names of lines which are connected to general-purpose pin headers. Signed-off-by: Trevor Woerner Acked-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- Documentation/devicetree/bindings/gpio/gpio.txt | 41 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 5663e71b751f..d82c32217fff 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -154,18 +154,35 @@ of the GPIOs that can't be used. Optionally, a GPIO controller may have a "gpio-line-names" property. This is an array of strings defining the names of the GPIO lines going out of the -GPIO controller. This name should be the most meaningful producer name -for the system, such as a rail name indicating the usage. Package names -such as pin name are discouraged: such lines have opaque names (since they -are by definition generic purpose) and such names are usually not very -helpful. For example "MMC-CD", "Red LED Vdd" and "ethernet reset" are -reasonable line names as they describe what the line is used for. "GPIO0" -is not a good name to give to a GPIO line. Placeholders are discouraged: -rather use the "" (blank string) if the use of the GPIO line is undefined -in your design. The names are assigned starting from line offset 0 from -left to right from the passed array. An incomplete array (where the number -of passed named are less than ngpios) will still be used up until the last -provided valid line index. +GPIO controller. + +For lines which are routed to on-board devices, this name should be +the most meaningful producer name for the system, such as a rail name +indicating the usage. Package names, such as a pin name, are discouraged: +such lines have opaque names (since they are by definition general-purpose) +and such names are usually not very helpful. For example "MMC-CD", "Red LED +Vdd" and "ethernet reset" are reasonable line names as they describe what +the line is used for. "GPIO0" is not a good name to give to a GPIO line +that is hard-wired to a specific device. + +However, in the case of lines that are routed to a general purpose header +(e.g. the Raspberry Pi 40-pin header), and therefore are not hard-wired to +specific devices, using a pin number or the names on the header is fine +provided these are real (preferably unique) names. Using an SoC's pad name +or package name, or names made up from kernel-internal software constructs, +are strongly discouraged. For example "pin8 [gpio14/uart0_txd]" is fine +if the board's documentation labels pin 8 as such. However "PortB_24" (an +example of a name from an SoC's reference manual) would not be desirable. + +In either case placeholders are discouraged: rather use the "" (blank +string) if the use of the GPIO line is undefined in your design. Ideally, +try to add comments to the dts file describing the naming the convention +you have chosen, and specifying from where the names are derived. + +The names are assigned starting from line offset 0, from left to right, +from the passed array. An incomplete array (where the number of passed +names is less than ngpios) will be used up until the last provided valid +line index. Example: -- cgit From 70e1114eb72591cdd493b44c6437f9e11cff81b8 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Fri, 17 Feb 2023 14:10:55 +0000 Subject: kbuild, gpio: remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Cc: Luis Chamberlain Cc: linux-modules@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Hitomi Hasegawa Cc: Manivannan Sadhasivam Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: linux-arm-kernel@lists.infradead.org Cc: linux-unisoc@lists.infradead.org Cc: linux-gpio@vger.kernel.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-rda.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-rda.c b/drivers/gpio/gpio-rda.c index 62ba18b3a602..ab4137de5889 100644 --- a/drivers/gpio/gpio-rda.c +++ b/drivers/gpio/gpio-rda.c @@ -286,4 +286,3 @@ module_platform_driver_probe(rda_gpio_driver, rda_gpio_probe); MODULE_DESCRIPTION("RDA Micro GPIO driver"); MODULE_AUTHOR("Manivannan Sadhasivam "); -MODULE_LICENSE("GPL v2"); -- cgit From 0d8b4049bb4792da225e2c908282bb9ed1024ac7 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 22 Feb 2023 12:14:53 +0000 Subject: kbuild, gpio: gpio-aspeed-sgpio: remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Cc: Luis Chamberlain Cc: linux-modules@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Hitomi Hasegawa Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Joel Stanley Cc: linux-gpio@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-aspeed@lists.ozlabs.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-aspeed-sgpio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c index 454cefbeecf0..ecc94bfded86 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -609,4 +609,3 @@ static struct platform_driver aspeed_sgpio_driver = { module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); MODULE_DESCRIPTION("Aspeed Serial GPIO Driver"); -MODULE_LICENSE("GPL"); -- cgit From d1143d50073cff1f6dcd4bf62a8eb3852770ae4d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Jan 2023 10:51:34 +0100 Subject: ARM: orion/gpio: Use the right include This is a GPIO driver so include and not the legacy header. Switch a single call to the legacy API and use as well. Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- arch/arm/plat-orion/gpio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 3ef9ecdd6343..595e9cb33c1d 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -312,7 +313,7 @@ int orion_gpio_led_blink_set(struct gpio_desc *desc, int state, case GPIO_LED_NO_BLINK_LOW: case GPIO_LED_NO_BLINK_HIGH: orion_gpio_set_blink(gpio, 0); - gpio_set_value(gpio, state); + gpiod_set_raw_value(desc, state); break; case GPIO_LED_BLINK: orion_gpio_set_blink(gpio, 1); -- cgit From 7a49bfde01961dac9efb734f031f3e77ce537f6d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Jan 2023 10:56:17 +0100 Subject: ARM: s3c64xx: Use the right include The file s3c64xx.c is including despite using no symbols from the file, however it needs it to implicitly bring in of_have_populated_dt() so include explicitly instead. Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- arch/arm/mach-s3c/s3c64xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c/s3c64xx.c b/arch/arm/mach-s3c/s3c64xx.c index e97bd59083a8..9f9717874d67 100644 --- a/arch/arm/mach-s3c/s3c64xx.c +++ b/arch/arm/mach-s3c/s3c64xx.c @@ -21,13 +21,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include -- cgit From 3b541b890ebe5c2914e0e0a2f0905b167afb3b75 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Jan 2023 10:44:01 +0100 Subject: hte: tegra-194: Use proper includes The test driver uses the gpiod consumer API so include the right header. This may cause a problem with struct of_device_id being implcitly pulled in by the legacy header so include explicitly as well. While at it, drop explicit moduleparam.h (it's included with module.h) and sort the headers. Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/hte/hte-tegra194-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hte/hte-tegra194-test.c b/drivers/hte/hte-tegra194-test.c index 5d776a185bd6..358d4a10c6a1 100644 --- a/drivers/hte/hte-tegra194-test.c +++ b/drivers/hte/hte-tegra194-test.c @@ -6,14 +6,14 @@ */ #include -#include -#include +#include +#include #include -#include -#include +#include +#include #include +#include #include -#include /* * This sample HTE GPIO test driver demonstrates HTE API usage by enabling -- cgit From 21d9526d13b5467b0a6532e5a8b0eb04c01ce326 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 3 Jul 2020 15:04:51 +0200 Subject: gpiolib: Make the legacy consumer-only The legacy header was an all-inclusive header used by drivers and consumers alike. After eliminating the last users of the driver defines, we can drop the inclusion of the header. Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- include/asm-generic/gpio.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 22cb8c9efc1d..1c910d124423 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -8,7 +8,6 @@ #ifdef CONFIG_GPIOLIB #include -#include #include /* -- cgit From ee5a66d87cddc77f8e727ca1d3f4dcbeefb3cb49 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Feb 2023 16:29:41 +0200 Subject: gpiolib: remove empty asm/gpio.h files The arm and sh versions of this file are identical to the generic versions and can just be removed. The drivers that actually use the sh3 specific version also include cpu/gpio.h directly, with the exception of magicpanelr2, which is easily fixed. This leaves coldfire as the only gpio driver that needs something custom for gpiolib. Reviewed-by: Geert Uytterhoeven Reviewed-by: Andy Shevchenko Acked-by: Bartosz Golaszewski Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko Reviewed-by: Vincenzo Palazzo --- arch/arm/Kconfig | 1 - arch/arm/include/asm/gpio.h | 21 ----------------- arch/sh/Kconfig | 1 - arch/sh/boards/board-magicpanelr2.c | 1 + arch/sh/include/asm/gpio.h | 45 ------------------------------------- 5 files changed, 1 insertion(+), 68 deletions(-) delete mode 100644 arch/arm/include/asm/gpio.h delete mode 100644 arch/sh/include/asm/gpio.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e24a9820e12f..1d1a603d964d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -24,7 +24,6 @@ config ARM select ARCH_HAS_SYNC_DMA_FOR_CPU select ARCH_HAS_TEARDOWN_DMA_OPS if MMU select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST - select ARCH_HAVE_CUSTOM_GPIO_H select ARCH_HAVE_NMI_SAFE_CMPXCHG if CPU_V7 || CPU_V7M || CPU_V6K select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_KEEP_MEMBLOCK diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h deleted file mode 100644 index 4ebbb58f06ea..000000000000 --- a/arch/arm/include/asm/gpio.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ARCH_ARM_GPIO_H -#define _ARCH_ARM_GPIO_H - -#include - -/* The trivial gpiolib dispatchers */ -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep - -/* - * Provide a default gpio_to_irq() which should satisfy every case. - * However, some platforms want to do this differently, so allow them - * to override it. - */ -#ifndef gpio_to_irq -#define gpio_to_irq __gpio_to_irq -#endif - -#endif /* _ARCH_ARM_GPIO_H */ diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 0665ac0add0b..ccb866750a88 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -4,7 +4,6 @@ config SUPERH select ARCH_32BIT_OFF_T select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM && MMU select ARCH_ENABLE_MEMORY_HOTREMOVE if SPARSEMEM && MMU - select ARCH_HAVE_CUSTOM_GPIO_H select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A) select ARCH_HAS_BINFMT_FLAT if !MMU select ARCH_HAS_CURRENT_STACK_POINTER diff --git a/arch/sh/boards/board-magicpanelr2.c b/arch/sh/boards/board-magicpanelr2.c index 56bd386ff3b0..75de893152af 100644 --- a/arch/sh/boards/board-magicpanelr2.c +++ b/arch/sh/boards/board-magicpanelr2.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* Dummy supplies, where voltage doesn't matter */ diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h deleted file mode 100644 index 588c1380e4cb..000000000000 --- a/arch/sh/include/asm/gpio.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * include/asm-sh/gpio.h - * - * Generic GPIO API and pinmux table support for SuperH. - * - * Copyright (c) 2008 Magnus Damm - */ -#ifndef __ASM_SH_GPIO_H -#define __ASM_SH_GPIO_H - -#include -#include - -#if defined(CONFIG_CPU_SH3) -#include -#endif - -#include - -#ifdef CONFIG_GPIOLIB - -static inline int gpio_get_value(unsigned gpio) -{ - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - __gpio_set_value(gpio, value); -} - -static inline int gpio_cansleep(unsigned gpio) -{ - return __gpio_cansleep(gpio); -} - -static inline int gpio_to_irq(unsigned gpio) -{ - return __gpio_to_irq(gpio); -} - -#endif /* CONFIG_GPIOLIB */ - -#endif /* __ASM_SH_GPIO_H */ -- cgit From 94d20f7d674d589e94aea77e2cbe37fc58541d04 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Feb 2023 16:29:42 +0200 Subject: gpiolib: coldfire: remove custom asm/gpio.h Now that coldfire is the only user of a custom asm/gpio.h, it seems better to remove this as well, and have the same interface everywhere. For the gpio_get_value()/gpio_set_value()/gpio_to_irq(), gpio_cansleep() functions, the custom version is only a micro-optimization to inline the function for constant GPIO numbers. However, in the coldfire defconfigs, I was unable to find a single instance where this micro-optimization was even used, and according to Geert the only user appears to be the QSPI chip that is disabled everywhere. The custom gpio_request_one() function is even less useful, as it is guarded by an #ifdef that is never true. Reviewed-by: Geert Uytterhoeven Reviewed-by: Andy Shevchenko Acked-by: Bartosz Golaszewski Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko --- arch/m68k/Kconfig.cpu | 1 - arch/m68k/include/asm/gpio.h | 95 -------------------------------------------- drivers/gpio/Kconfig | 8 ---- include/linux/gpio.h | 7 ---- 4 files changed, 111 deletions(-) delete mode 100644 arch/m68k/include/asm/gpio.h diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 9380f6e3bb66..96a0fb4f1af5 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -24,7 +24,6 @@ config M68KCLASSIC config COLDFIRE bool "Coldfire CPU family support" - select ARCH_HAVE_CUSTOM_GPIO_H select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_CAS select CPU_HAS_NO_MULDIV64 diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h deleted file mode 100644 index 5cfc0996ba94..000000000000 --- a/arch/m68k/include/asm/gpio.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Coldfire generic GPIO support - * - * (C) Copyright 2009, Steven King -*/ - -#ifndef coldfire_gpio_h -#define coldfire_gpio_h - -#include -#include -#include -#include -/* - * The Generic GPIO functions - * - * If the gpio is a compile time constant and is one of the Coldfire gpios, - * use the inline version, otherwise dispatch thru gpiolib. - */ - -static inline int gpio_get_value(unsigned gpio) -{ - if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) - return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio); - else - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) { - if (gpio < MCFGPIO_SCR_START) { - unsigned long flags; - MCFGPIO_PORTTYPE data; - - local_irq_save(flags); - data = mcfgpio_read(__mcfgpio_podr(gpio)); - if (value) - data |= mcfgpio_bit(gpio); - else - data &= ~mcfgpio_bit(gpio); - mcfgpio_write(data, __mcfgpio_podr(gpio)); - local_irq_restore(flags); - } else { - if (value) - mcfgpio_write(mcfgpio_bit(gpio), - MCFGPIO_SETR_PORT(gpio)); - else - mcfgpio_write(~mcfgpio_bit(gpio), - MCFGPIO_CLRR_PORT(gpio)); - } - } else - __gpio_set_value(gpio, value); -} - -static inline int gpio_to_irq(unsigned gpio) -{ -#if defined(MCFGPIO_IRQ_MIN) - if ((gpio >= MCFGPIO_IRQ_MIN) && (gpio < MCFGPIO_IRQ_MAX)) -#else - if (gpio < MCFGPIO_IRQ_MAX) -#endif - return gpio + MCFGPIO_IRQ_VECBASE; - else - return __gpio_to_irq(gpio); -} - -static inline int gpio_cansleep(unsigned gpio) -{ - return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio); -} - -#ifndef CONFIG_GPIOLIB -static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) -{ - int err; - - err = gpio_request(gpio, label); - if (err) - return err; - - if (flags & GPIOF_DIR_IN) - err = gpio_direction_input(gpio); - else - err = gpio_direction_output(gpio, - (flags & GPIOF_INIT_HIGH) ? 1 : 0); - - if (err) - gpio_free(gpio); - - return err; -} -#endif /* !CONFIG_GPIOLIB */ -#endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 13be729710f2..df82fb7eb0eb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -3,14 +3,6 @@ # GPIO infrastructure and drivers # -config ARCH_HAVE_CUSTOM_GPIO_H - bool - help - Selecting this config option from the architecture Kconfig allows - the architecture to provide a custom asm/gpio.h implementation - overriding the default implementations. New uses of this are - strongly discouraged. - menuconfig GPIOLIB bool "GPIO Support" help diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 85beb236c925..2b75017b3aad 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -54,11 +54,6 @@ struct gpio { }; #ifdef CONFIG_GPIOLIB - -#ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H -#include -#else - #include static inline int gpio_get_value(unsigned int gpio) @@ -81,8 +76,6 @@ static inline int gpio_to_irq(unsigned int gpio) return __gpio_to_irq(gpio); } -#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */ - /* CONFIG_GPIOLIB: bindings for managed devices that want to request gpios */ struct device; -- cgit From eccb7a00613c804ec7244676090bf6ee43a23da2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Feb 2023 17:37:22 +0200 Subject: gpiolib: remove asm-generic/gpio.h The asm-generic/gpio.h file is now always included when using gpiolib, so just move its contents into linux/gpio.h with a few minor simplifications. Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- MAINTAINERS | 1 - arch/m68k/include/asm/mcfgpio.h | 2 +- drivers/gpio/gpio-davinci.c | 2 - drivers/pinctrl/core.c | 1 - include/asm-generic/gpio.h | 146 ---------------------------------------- include/linux/gpio.h | 94 +++++++++++++++++++++++--- 6 files changed, 85 insertions(+), 161 deletions(-) delete mode 100644 include/asm-generic/gpio.h diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..ddf686c2e546 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8752,7 +8752,6 @@ F: Documentation/admin-guide/gpio/ F: Documentation/devicetree/bindings/gpio/ F: Documentation/driver-api/gpio/ F: drivers/gpio/ -F: include/asm-generic/gpio.h F: include/dt-bindings/gpio/ F: include/linux/gpio.h F: include/linux/gpio/ diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h index 27f32cc81da6..2cefe8445980 100644 --- a/arch/m68k/include/asm/mcfgpio.h +++ b/arch/m68k/include/asm/mcfgpio.h @@ -9,7 +9,7 @@ #define mcfgpio_h #ifdef CONFIG_GPIOLIB -#include +#include #else int __mcfgpio_get_value(unsigned gpio); diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 26b1f7465e09..7fc83057990a 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -24,8 +24,6 @@ #include #include -#include - #define MAX_REGS_BANKS 5 #define MAX_INT_PER_BANK 32 diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index d6e6c751255f..401886c81344 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -30,7 +30,6 @@ #ifdef CONFIG_GPIOLIB #include "../gpio/gpiolib.h" -#include #endif #include "core.h" diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h deleted file mode 100644 index 1c910d124423..000000000000 --- a/include/asm-generic/gpio.h +++ /dev/null @@ -1,146 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_GENERIC_GPIO_H -#define _ASM_GENERIC_GPIO_H - -#include -#include - -#ifdef CONFIG_GPIOLIB - -#include -#include - -/* - * Platforms may implement their GPIO interface with library code, - * at a small performance cost for non-inlined operations and some - * extra memory (for code and for per-GPIO table entries). - */ - -/* - * At the end we want all GPIOs to be dynamically allocated from 0. - * However, some legacy drivers still perform fixed allocation. - * Until they are all fixed, leave 0-512 space for them. - */ -#define GPIO_DYNAMIC_BASE 512 - -struct device; -struct gpio; -struct seq_file; -struct module; -struct device_node; -struct gpio_desc; - -/* Always use the library code for GPIO management calls, - * or when sleeping may be involved. - */ -extern int gpio_request(unsigned gpio, const char *label); -extern void gpio_free(unsigned gpio); - -static inline int gpio_direction_input(unsigned gpio) -{ - return gpiod_direction_input(gpio_to_desc(gpio)); -} -static inline int gpio_direction_output(unsigned gpio, int value) -{ - return gpiod_direction_output_raw(gpio_to_desc(gpio), value); -} - -static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) -{ - return gpiod_set_debounce(gpio_to_desc(gpio), debounce); -} - -static inline int gpio_get_value_cansleep(unsigned gpio) -{ - return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio)); -} -static inline void gpio_set_value_cansleep(unsigned gpio, int value) -{ - return gpiod_set_raw_value_cansleep(gpio_to_desc(gpio), value); -} - - -/* A platform's code may want to inline the I/O calls when - * the GPIO is constant and refers to some always-present controller, - * giving direct access to chip registers and tight bitbanging loops. - */ -static inline int __gpio_get_value(unsigned gpio) -{ - return gpiod_get_raw_value(gpio_to_desc(gpio)); -} -static inline void __gpio_set_value(unsigned gpio, int value) -{ - return gpiod_set_raw_value(gpio_to_desc(gpio), value); -} - -static inline int __gpio_cansleep(unsigned gpio) -{ - return gpiod_cansleep(gpio_to_desc(gpio)); -} - -static inline int __gpio_to_irq(unsigned gpio) -{ - return gpiod_to_irq(gpio_to_desc(gpio)); -} - -extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); -extern int gpio_request_array(const struct gpio *array, size_t num); -extern void gpio_free_array(const struct gpio *array, size_t num); - -/* - * A sysfs interface can be exported by individual drivers if they want, - * but more typically is configured entirely from userspace. - */ -static inline int gpio_export(unsigned gpio, bool direction_may_change) -{ - return gpiod_export(gpio_to_desc(gpio), direction_may_change); -} - -static inline void gpio_unexport(unsigned gpio) -{ - gpiod_unexport(gpio_to_desc(gpio)); -} - -#else /* !CONFIG_GPIOLIB */ - -#include - -/* platforms that don't directly support access to GPIOs through I2C, SPI, - * or other blocking infrastructure can use these wrappers. - */ - -static inline int gpio_cansleep(unsigned gpio) -{ - return 0; -} - -static inline int gpio_get_value_cansleep(unsigned gpio) -{ - might_sleep(); - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value_cansleep(unsigned gpio, int value) -{ - might_sleep(); - __gpio_set_value(gpio, value); -} - -#endif /* !CONFIG_GPIOLIB */ - -/* - * "valid" GPIO numbers are nonnegative and may be passed to - * setup routines like gpio_request(). only some valid numbers - * can successfully be requested and used. - * - * Invalid GPIO numbers are useful for indicating no-such-GPIO in - * platform data and other tables. - */ - -static inline bool gpio_is_valid(int number) -{ - /* only non-negative numbers are valid */ - return number >= 0; -} - -#endif /* _ASM_GENERIC_GPIO_H */ diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 2b75017b3aad..d5ce78e2bdd9 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -13,6 +13,7 @@ #define __LINUX_GPIO_H #include +#include /* see Documentation/driver-api/gpio/legacy.rst */ @@ -54,26 +55,100 @@ struct gpio { }; #ifdef CONFIG_GPIOLIB -#include -static inline int gpio_get_value(unsigned int gpio) +#include + +/* + * "valid" GPIO numbers are nonnegative and may be passed to + * setup routines like gpio_request(). Only some valid numbers + * can successfully be requested and used. + * + * Invalid GPIO numbers are useful for indicating no-such-GPIO in + * platform data and other tables. + */ +static inline bool gpio_is_valid(int number) +{ + /* only non-negative numbers are valid */ + return number >= 0; +} + +/* + * Platforms may implement their GPIO interface with library code, + * at a small performance cost for non-inlined operations and some + * extra memory (for code and for per-GPIO table entries). + */ + +/* + * At the end we want all GPIOs to be dynamically allocated from 0. + * However, some legacy drivers still perform fixed allocation. + * Until they are all fixed, leave 0-512 space for them. + */ +#define GPIO_DYNAMIC_BASE 512 + +/* Always use the library code for GPIO management calls, + * or when sleeping may be involved. + */ +int gpio_request(unsigned gpio, const char *label); +void gpio_free(unsigned gpio); + +static inline int gpio_direction_input(unsigned gpio) +{ + return gpiod_direction_input(gpio_to_desc(gpio)); +} +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return gpiod_direction_output_raw(gpio_to_desc(gpio), value); +} + +static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) +{ + return gpiod_set_debounce(gpio_to_desc(gpio), debounce); +} + +static inline int gpio_get_value_cansleep(unsigned gpio) +{ + return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio)); +} +static inline void gpio_set_value_cansleep(unsigned gpio, int value) { - return __gpio_get_value(gpio); + return gpiod_set_raw_value_cansleep(gpio_to_desc(gpio), value); } -static inline void gpio_set_value(unsigned int gpio, int value) +static inline int gpio_get_value(unsigned gpio) +{ + return gpiod_get_raw_value(gpio_to_desc(gpio)); +} +static inline void gpio_set_value(unsigned gpio, int value) { - __gpio_set_value(gpio, value); + return gpiod_set_raw_value(gpio_to_desc(gpio), value); } -static inline int gpio_cansleep(unsigned int gpio) +static inline int gpio_cansleep(unsigned gpio) { - return __gpio_cansleep(gpio); + return gpiod_cansleep(gpio_to_desc(gpio)); } -static inline int gpio_to_irq(unsigned int gpio) +static inline int gpio_to_irq(unsigned gpio) { - return __gpio_to_irq(gpio); + return gpiod_to_irq(gpio_to_desc(gpio)); +} + +int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); +int gpio_request_array(const struct gpio *array, size_t num); +void gpio_free_array(const struct gpio *array, size_t num); + +/* + * A sysfs interface can be exported by individual drivers if they want, + * but more typically is configured entirely from userspace. + */ +static inline int gpio_export(unsigned gpio, bool direction_may_change) +{ + return gpiod_export(gpio_to_desc(gpio), direction_may_change); +} + +static inline void gpio_unexport(unsigned gpio) +{ + gpiod_unexport(gpio_to_desc(gpio)); } /* CONFIG_GPIOLIB: bindings for managed devices that want to request gpios */ @@ -88,7 +163,6 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio, #include #include -#include struct device; struct gpio_chip; -- cgit From 0e685c3e7158d35626d6d76b9f859eae806d87fa Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Feb 2023 16:29:44 +0200 Subject: gpiolib: remove gpio_set_debounce() gpio_set_debounce() only has a single user, which is trivially converted to gpiod_set_debounce(). Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- Documentation/driver-api/gpio/legacy.rst | 2 -- Documentation/translations/zh_CN/driver-api/gpio/legacy.rst | 1 - Documentation/translations/zh_TW/gpio.txt | 1 - drivers/input/touchscreen/ads7846.c | 5 +++-- include/linux/gpio.h | 10 ---------- 5 files changed, 3 insertions(+), 16 deletions(-) diff --git a/Documentation/driver-api/gpio/legacy.rst b/Documentation/driver-api/gpio/legacy.rst index a0559d93efd1..e0306e78e34b 100644 --- a/Documentation/driver-api/gpio/legacy.rst +++ b/Documentation/driver-api/gpio/legacy.rst @@ -238,8 +238,6 @@ setup or driver probe/teardown code, so this is an easy constraint.):: ## gpio_free_array() gpio_free() - gpio_set_debounce() - Claiming and Releasing GPIOs diff --git a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst index 74fa473bb504..dee2a0517c1c 100644 --- a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst +++ b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst @@ -219,7 +219,6 @@ GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其 ## gpio_free_array() gpio_free() - gpio_set_debounce() diff --git a/Documentation/translations/zh_TW/gpio.txt b/Documentation/translations/zh_TW/gpio.txt index 1b986bbb0909..dc608358d90a 100644 --- a/Documentation/translations/zh_TW/gpio.txt +++ b/Documentation/translations/zh_TW/gpio.txt @@ -226,7 +226,6 @@ GPIO 值的命令需要等待其信息排到隊首才發送命令,再獲得其 ## gpio_free_array() gpio_free() - gpio_set_debounce() diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 17f11bce8113..bb1058b1e7fd 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1012,8 +1013,8 @@ static int ads7846_setup_pendown(struct spi_device *spi, ts->gpio_pendown = pdata->gpio_pendown; if (pdata->gpio_pendown_debounce) - gpio_set_debounce(pdata->gpio_pendown, - pdata->gpio_pendown_debounce); + gpiod_set_debounce(gpio_to_desc(ts->gpio_pendown), + pdata->gpio_pendown_debounce); } else { dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); return -EINVAL; diff --git a/include/linux/gpio.h b/include/linux/gpio.h index d5ce78e2bdd9..fc56733e8514 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -100,11 +100,6 @@ static inline int gpio_direction_output(unsigned gpio, int value) return gpiod_direction_output_raw(gpio_to_desc(gpio), value); } -static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) -{ - return gpiod_set_debounce(gpio_to_desc(gpio), debounce); -} - static inline int gpio_get_value_cansleep(unsigned gpio) { return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio)); @@ -214,11 +209,6 @@ static inline int gpio_direction_output(unsigned gpio, int value) return -ENOSYS; } -static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) -{ - return -ENOSYS; -} - static inline int gpio_get_value(unsigned gpio) { /* GPIO can never have been requested or set as {in,out}put */ -- cgit From d74e316633e49f44756c23997fa071979a939405 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Feb 2023 16:29:45 +0200 Subject: gpiolib: remove legacy gpio_export() There are only a handful of users of gpio_export() and related functions. As these are just wrappers around the modern gpiod_export() helper, remove the wrappers and open-code the gpio_to_desc in all callers to shrink the legacy API. Reviewed-by: Andy Shevchenko Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko --- Documentation/admin-guide/gpio/sysfs.rst | 2 +- Documentation/driver-api/gpio/legacy.rst | 21 ----------------- .../translations/zh_CN/driver-api/gpio/legacy.rst | 19 --------------- Documentation/translations/zh_TW/gpio.txt | 18 --------------- arch/arm/mach-omap2/pdata-quirks.c | 9 ++++---- arch/sh/boards/mach-ap325rxa/setup.c | 7 +++--- drivers/gpio/gpiolib-sysfs.c | 4 ++-- drivers/media/pci/sta2x11/sta2x11_vip.c | 10 +++++--- drivers/net/ieee802154/ca8210.c | 3 ++- include/linux/gpio.h | 27 ---------------------- 10 files changed, 21 insertions(+), 99 deletions(-) diff --git a/Documentation/admin-guide/gpio/sysfs.rst b/Documentation/admin-guide/gpio/sysfs.rst index ec09ffd983e7..35171d15f78d 100644 --- a/Documentation/admin-guide/gpio/sysfs.rst +++ b/Documentation/admin-guide/gpio/sysfs.rst @@ -145,7 +145,7 @@ requested using gpio_request():: /* export the GPIO to userspace */ int gpiod_export(struct gpio_desc *desc, bool direction_may_change); - /* reverse gpio_export() */ + /* reverse gpiod_export() */ void gpiod_unexport(struct gpio_desc *desc); /* create a sysfs link to an exported GPIO node */ diff --git a/Documentation/driver-api/gpio/legacy.rst b/Documentation/driver-api/gpio/legacy.rst index e0306e78e34b..78372853c6d4 100644 --- a/Documentation/driver-api/gpio/legacy.rst +++ b/Documentation/driver-api/gpio/legacy.rst @@ -714,27 +714,6 @@ gpiochip nodes (possibly in conjunction with schematics) to determine the correct GPIO number to use for a given signal. -Exporting from Kernel code --------------------------- -Kernel code can explicitly manage exports of GPIOs which have already been -requested using gpio_request():: - - /* export the GPIO to userspace */ - int gpio_export(unsigned gpio, bool direction_may_change); - - /* reverse gpio_export() */ - void gpio_unexport(); - -After a kernel driver requests a GPIO, it may only be made available in -the sysfs interface by gpio_export(). The driver can control whether the -signal direction may change. This helps drivers prevent userspace code -from accidentally clobbering important system state. - -This explicit exporting can help with debugging (by making some kinds -of experiments easier), or can provide an always-there interface that's -suitable for documenting as part of a board support package. - - API Reference ============= diff --git a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst index dee2a0517c1c..84ce2322fdba 100644 --- a/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst +++ b/Documentation/translations/zh_CN/driver-api/gpio/legacy.rst @@ -653,25 +653,6 @@ GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO 确定给定信号所用的 GPIO 编号。 -从内核代码中导出 ----------------- - -内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出:: - - /* 导出 GPIO 到用户空间 */ - int gpio_export(unsigned gpio, bool direction_may_change); - - /* gpio_export()的逆操作 */ - void gpio_unexport(); - -在一个内核驱动申请一个 GPIO 之后,它可以通过 gpio_export()使其在 sysfs -接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间 -破坏重要的系统状态。 - -这个明确的导出有助于(通过使某些实验更容易来)调试,也可以提供一个始终存在的接口, -与文档配合作为板级支持包的一部分。 - - API参考 ======= diff --git a/Documentation/translations/zh_TW/gpio.txt b/Documentation/translations/zh_TW/gpio.txt index dc608358d90a..62e560ffe628 100644 --- a/Documentation/translations/zh_TW/gpio.txt +++ b/Documentation/translations/zh_TW/gpio.txt @@ -614,21 +614,3 @@ GPIO 控制器的路徑類似 /sys/class/gpio/gpiochip42/ (對於從#42 GPIO 固定的,例如在擴展卡上的 GPIO會根據所使用的主板或所在堆疊架構中其他的板子而 有所不同。在這種情況下,你可能需要使用 gpiochip 節點(儘可能地結合電路圖)來 確定給定信號所用的 GPIO 編號。 - - -從內核代碼中導出 -------------- -內核代碼可以明確地管理那些已通過 gpio_request()申請的 GPIO 的導出: - - /* 導出 GPIO 到用戶空間 */ - int gpio_export(unsigned gpio, bool direction_may_change); - - /* gpio_export()的逆操作 */ - void gpio_unexport(); - -在一個內核驅動申請一個 GPIO 之後,它可以通過 gpio_export()使其在 sysfs -接口中可見。該驅動可以控制信號方向是否可修改。這有助於防止用戶空間代碼無意間 -破壞重要的系統狀態。 - -這個明確的導出有助於(通過使某些實驗更容易來)調試,也可以提供一個始終存在的接口, -與文檔配合作爲板級支持包的一部分。 diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index baba73fd6f11..04208cc52784 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -6,6 +6,7 @@ */ #include #include +#include #include #include #include @@ -108,7 +109,7 @@ static int omap3_sbc_t3730_twl_callback(struct device *dev, if (res) return res; - gpio_export(gpio, 0); + gpiod_export(gpio_to_desc(gpio), 0); return 0; } @@ -123,7 +124,7 @@ static void __init omap3_sbc_t3x_usb_hub_init(int gpio, char *hub_name) return; } - gpio_export(gpio, 0); + gpiod_export(gpio_to_desc(gpio), 0); udelay(10); gpio_set_value(gpio, 1); @@ -200,8 +201,8 @@ static void __init omap3_sbc_t3517_wifi_init(void) return; } - gpio_export(cm_t3517_wlan_gpios[0].gpio, 0); - gpio_export(cm_t3517_wlan_gpios[1].gpio, 0); + gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[0].gpio), 0); + gpiod_export(gpio_to_desc(cm_t3517_wlan_gpios[1].gpio), 0); msleep(100); gpio_set_value(cm_t3517_wlan_gpios[1].gpio, 0); diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index c77b5f00a66a..151792162152 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -411,16 +412,16 @@ static int __init ap325rxa_devices_setup(void) /* LD3 and LD4 LEDs */ gpio_request(GPIO_PTX5, NULL); /* RUN */ gpio_direction_output(GPIO_PTX5, 1); - gpio_export(GPIO_PTX5, 0); + gpiod_export(gpio_to_desc(GPIO_PTX5), 0); gpio_request(GPIO_PTX4, NULL); /* INDICATOR */ gpio_direction_output(GPIO_PTX4, 0); - gpio_export(GPIO_PTX4, 0); + gpiod_export(gpio_to_desc(GPIO_PTX4), 0); /* SW1 input */ gpio_request(GPIO_PTF7, NULL); /* MODE */ gpio_direction_input(GPIO_PTF7); - gpio_export(GPIO_PTF7, 0); + gpiod_export(gpio_to_desc(GPIO_PTF7), 0); /* LCDC */ gpio_request(GPIO_FN_LCDD15, NULL); diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index cd27bf173dec..6e4267944f80 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -491,7 +491,7 @@ static ssize_t unexport_store(struct class *class, goto done; desc = gpio_to_desc(gpio); - /* reject bogus commands (gpio_unexport ignores them) */ + /* reject bogus commands (gpiod_unexport() ignores them) */ if (!desc) { pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); return -EINVAL; @@ -790,7 +790,7 @@ static int __init gpiolib_sysfs_init(void) * early (e.g. before the class_register above was called). * * We run before arch_initcall() so chip->dev nodes can have - * registered, and so arch_initcall() can always gpio_export(). + * registered, and so arch_initcall() can always gpiod_export(). */ spin_lock_irqsave(&gpio_lock, flags); list_for_each_entry(gdev, &gpio_devices, list) { diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 8535e49a4c4f..e4cf9d63e926 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -889,6 +890,7 @@ static int sta2x11_vip_init_controls(struct sta2x11_vip *vip) static int vip_gpio_reserve(struct device *dev, int pin, int dir, const char *name) { + struct gpio_desc *desc = gpio_to_desc(pin); int ret = -ENODEV; if (!gpio_is_valid(pin)) @@ -900,7 +902,7 @@ static int vip_gpio_reserve(struct device *dev, int pin, int dir, return ret; } - ret = gpio_direction_output(pin, dir); + ret = gpiod_direction_output(desc, dir); if (ret) { dev_err(dev, "Failed to set direction for pin %d (%s)\n", pin, name); @@ -908,7 +910,7 @@ static int vip_gpio_reserve(struct device *dev, int pin, int dir, return ret; } - ret = gpio_export(pin, false); + ret = gpiod_export(desc, false); if (ret) { dev_err(dev, "Failed to export pin %d (%s)\n", pin, name); gpio_free(pin); @@ -928,8 +930,10 @@ static int vip_gpio_reserve(struct device *dev, int pin, int dir, static void vip_gpio_release(struct device *dev, int pin, const char *name) { if (gpio_is_valid(pin)) { + struct gpio_desc *desc = gpio_to_desc(pin); + dev_dbg(dev, "releasing pin %d (%s)\n", pin, name); - gpio_unexport(pin); + gpiod_unexport(desc); gpio_free(pin); } } diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index e1a569b99e4a..5c0be6a3ec5e 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -2853,7 +2854,7 @@ static int ca8210_interrupt_init(struct spi_device *spi) ); if (ret) { dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id); - gpio_unexport(pdata->gpio_irq); + gpiod_unexport(gpio_to_desc(pdata->gpio_irq)); gpio_free(pdata->gpio_irq); } diff --git a/include/linux/gpio.h b/include/linux/gpio.h index fc56733e8514..a86953696e47 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -132,20 +132,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); int gpio_request_array(const struct gpio *array, size_t num); void gpio_free_array(const struct gpio *array, size_t num); -/* - * A sysfs interface can be exported by individual drivers if they want, - * but more typically is configured entirely from userspace. - */ -static inline int gpio_export(unsigned gpio, bool direction_may_change) -{ - return gpiod_export(gpio_to_desc(gpio), direction_may_change); -} - -static inline void gpio_unexport(unsigned gpio) -{ - gpiod_unexport(gpio_to_desc(gpio)); -} - /* CONFIG_GPIOLIB: bindings for managed devices that want to request gpios */ struct device; @@ -242,19 +228,6 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) WARN_ON(1); } -static inline int gpio_export(unsigned gpio, bool direction_may_change) -{ - /* GPIO can never have been requested or set as {in,out}put */ - WARN_ON(1); - return -EINVAL; -} - -static inline void gpio_unexport(unsigned gpio) -{ - /* GPIO can never have been exported */ - WARN_ON(1); -} - static inline int gpio_to_irq(unsigned gpio) { /* GPIO can never have been requested or set as input */ -- cgit From a8e59744e16b9ae18fab773a0fd3b23cdf21ad75 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Feb 2023 17:41:47 +0200 Subject: gpiolib: split linux/gpio/driver.h out of linux/gpio.h Almost all gpio drivers include linux/gpio/driver.h, and other files should not rely on includes from this header. Remove the indirect include from here and include the correct headers directly from where they are used. Reviewed-by: Andy Shevchenko Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko Acked-by: Lee Jones --- arch/arm/mach-omap1/irq.c | 1 + arch/arm/mach-orion5x/board-rd88f5182.c | 1 + arch/arm/mach-sa1100/assabet.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c | 1 + include/linux/mfd/ucb1x00.h | 1 + 5 files changed, 5 insertions(+) diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 9ccc784fd614..bfc7ab010ae2 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-orion5x/board-rd88f5182.c b/arch/arm/mach-orion5x/board-rd88f5182.c index 596601367989..1c14e49a90a6 100644 --- a/arch/arm/mach-orion5x/board-rd88f5182.c +++ b/arch/arm/mach-orion5x/board-rd88f5182.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 2eba112f2ad8..d000c678b439 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c index 9540a05247c2..89c8829528c2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index 43bcf35afe27..ede237384723 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #define UCB_IO_DATA 0x00 -- cgit From a99cc66807d6c854a7f65f962766c530c91be149 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Feb 2023 16:29:47 +0200 Subject: gpiolib: split of_mm_gpio_chip out of linux/of_gpio.h This is a rarely used feature that has nothing to do with the client-side of_gpio.h. Split it out with a separate header file and Kconfig option so it can be removed on its own timeline aside from removing the of_gpio consumer interfaces. Reviewed-by: Andy Shevchenko Signed-off-by: Arnd Bergmann Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/44x/Kconfig | 1 + arch/powerpc/platforms/4xx/gpio.c | 2 +- arch/powerpc/platforms/8xx/Kconfig | 1 + arch/powerpc/platforms/8xx/cpm1.c | 2 +- arch/powerpc/platforms/Kconfig | 2 ++ arch/powerpc/sysdev/cpm_common.c | 2 +- drivers/gpio/Kconfig | 11 +++++++++ drivers/gpio/TODO | 15 ++++++++----- drivers/gpio/gpio-altera.c | 2 +- drivers/gpio/gpio-mm-lantiq.c | 2 +- drivers/gpio/gpio-mpc5200.c | 2 +- drivers/gpio/gpiolib-of.c | 3 +++ drivers/soc/fsl/qe/gpio.c | 2 +- include/linux/gpio/legacy-of-mm-gpiochip.h | 36 ++++++++++++++++++++++++++++++ include/linux/of_gpio.h | 21 ----------------- 15 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 include/linux/gpio/legacy-of-mm-gpiochip.h diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 25b80cd558f8..1624ebf95497 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -230,6 +230,7 @@ config PPC4xx_GPIO bool "PPC4xx GPIO support" depends on 44x select GPIOLIB + select OF_GPIO_MM_GPIOCHIP help Enable gpiolib support for ppc440 based boards diff --git a/arch/powerpc/platforms/4xx/gpio.c b/arch/powerpc/platforms/4xx/gpio.c index 49ee8d365852..e5f2319e5cbe 100644 --- a/arch/powerpc/platforms/4xx/gpio.c +++ b/arch/powerpc/platforms/4xx/gpio.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index 60cc5b537a98..a14d9d8997a4 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -101,6 +101,7 @@ comment "Generic MPC8xx Options" config 8xx_GPIO bool "GPIO API Support" select GPIOLIB + select OF_GPIO_MM_GPIOCHIP help Saying Y here will cause the ports on an MPC8xx processor to be used with the GPIO API. If you say N here, the kernel needs less memory. diff --git a/arch/powerpc/platforms/8xx/cpm1.c b/arch/powerpc/platforms/8xx/cpm1.c index bb38c8d8f8de..56ca14f77543 100644 --- a/arch/powerpc/platforms/8xx/cpm1.c +++ b/arch/powerpc/platforms/8xx/cpm1.c @@ -44,7 +44,7 @@ #include #ifdef CONFIG_8xx_GPIO -#include +#include #endif #define CPM_MAP_SIZE (0x4000) diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index d41dad227de8..8e4bbd19dec5 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -244,6 +244,7 @@ config QE_GPIO bool "QE GPIO support" depends on QUICC_ENGINE select GPIOLIB + select OF_GPIO_MM_GPIOCHIP help Say Y here if you're going to use hardware that connects to the QE GPIOs. @@ -254,6 +255,7 @@ config CPM2 select CPM select HAVE_PCI select GPIOLIB + select OF_GPIO_MM_GPIOCHIP help The CPM2 (Communications Processor Module) is a coprocessor on embedded CPUs made by Freescale. Selecting this option means that diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 7dc1960f8bdb..8234013a8772 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c @@ -31,7 +31,7 @@ #include #if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO) -#include +#include #endif static int __init cpm_init(void) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index df82fb7eb0eb..2b72a7a7084a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -39,6 +39,14 @@ config GPIOLIB_IRQCHIP select IRQ_DOMAIN bool +config OF_GPIO_MM_GPIOCHIP + bool + help + This adds support for the legacy 'struct of_mm_gpio_chip' interface + from PowerPC. Existing drivers using this interface need to select + this symbol, but new drivers should use the generic gpio-regmap + infrastructure instead. + config DEBUG_GPIO bool "Debug GPIO calls" depends on DEBUG_KERNEL @@ -131,6 +139,7 @@ config GPIO_ALTERA tristate "Altera GPIO" depends on OF_GPIO select GPIOLIB_IRQCHIP + select OF_GPIO_MM_GPIOCHIP help Say Y or M here to build support for the Altera PIO device. @@ -403,6 +412,7 @@ config GPIO_MENZ127 config GPIO_MM_LANTIQ bool "Lantiq Memory mapped GPIOs" depends on LANTIQ && SOC_XWAY + select OF_GPIO_MM_GPIOCHIP help This enables support for memory mapped GPIOs on the External Bus Unit (EBU) found on Lantiq SoCs. The GPIOs are output only as they are @@ -411,6 +421,7 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select OF_GPIO_MM_GPIOCHIP config GPIO_MPC8XXX bool "MPC512x/MPC8xxx/QorIQ GPIO support" diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO index 68ada1066941..189c3abe7e79 100644 --- a/drivers/gpio/TODO +++ b/drivers/gpio/TODO @@ -59,11 +59,6 @@ the device tree back-end. It is legacy and should not be used in new code. Work items: -- Get rid of struct of_mm_gpio_chip altogether: use the generic MMIO - GPIO for all current users (see below). Delete struct of_mm_gpio_chip, - to_of_mm_gpio_chip(), of_mm_gpiochip_add_data(), of_mm_gpiochip_remove() - from the kernel. - - Change all consumer drivers that #include to #include and stop doing custom parsing of the GPIO lines from the device tree. This can be tricky and often ivolves @@ -81,6 +76,16 @@ Work items: uses or instead. +Get rid of + +Work items: + +- Get rid of struct of_mm_gpio_chip altogether: use the generic MMIO + GPIO for all current users (see below). Delete struct of_mm_gpio_chip, + to_of_mm_gpio_chip(), of_mm_gpiochip_add_data(), of_mm_gpiochip_remove(), + CONFIG_OF_GPIO_MM_GPIOCHIP from the kernel. + + Get rid of This legacy header is a one stop shop for anything GPIO is closely tied diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index b59fae993626..99e137f8097e 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -7,7 +7,7 @@ #include #include #include -#include /* For of_mm_gpio_chip */ +#include #include #define ALTERA_GPIO_MAX_NGPIO 32 diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index 538e31fe8903..27ff84c5d162 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c index 000494e0c533..3b0bfff8c778 100644 --- a/drivers/gpio/gpio-mpc5200.c +++ b/drivers/gpio/gpio-mpc5200.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 266352b1a966..0f699af438b0 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -892,6 +892,8 @@ static int of_gpio_simple_xlate(struct gpio_chip *gc, return gpiospec->args[0]; } +#if IS_ENABLED(CONFIG_OF_GPIO_MM_GPIOCHIP) +#include /** * of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank) * @np: device node of the GPIO chip @@ -964,6 +966,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) kfree(gc->label); } EXPORT_SYMBOL_GPL(of_mm_gpiochip_remove); +#endif #ifdef CONFIG_PINCTRL static int of_gpiochip_add_pin_range(struct gpio_chip *chip) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 1c41eb49d5a7..3ef24ba0245b 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -13,7 +13,7 @@ #include #include #include -#include /* for of_mm_gpio_chip */ +#include #include #include #include diff --git a/include/linux/gpio/legacy-of-mm-gpiochip.h b/include/linux/gpio/legacy-of-mm-gpiochip.h new file mode 100644 index 000000000000..2e2bd3b19cc3 --- /dev/null +++ b/include/linux/gpio/legacy-of-mm-gpiochip.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * OF helpers for the old of_mm_gpio_chip, used on ppc32 and nios2, + * do not use in new code. + * + * Copyright (c) 2007-2008 MontaVista Software, Inc. + * + * Author: Anton Vorontsov + */ + +#ifndef __LINUX_GPIO_LEGACY_OF_MM_GPIO_CHIP_H +#define __LINUX_GPIO_LEGACY_OF_MM_GPIO_CHIP_H + +#include +#include + +/* + * OF GPIO chip for memory mapped banks + */ +struct of_mm_gpio_chip { + struct gpio_chip gc; + void (*save_regs)(struct of_mm_gpio_chip *mm_gc); + void __iomem *regs; +}; + +static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) +{ + return container_of(gc, struct of_mm_gpio_chip, gc); +} + +extern int of_mm_gpiochip_add_data(struct device_node *np, + struct of_mm_gpio_chip *mm_gc, + void *data); +extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); + +#endif /* __LINUX_GPIO_LEGACY_OF_MM_GPIO_CHIP_H */ diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 5d58b3b0a97e..d0f66a5e1b2a 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -19,30 +19,9 @@ struct device_node; #ifdef CONFIG_OF_GPIO -#include - -/* - * OF GPIO chip for memory mapped banks - */ -struct of_mm_gpio_chip { - struct gpio_chip gc; - void (*save_regs)(struct of_mm_gpio_chip *mm_gc); - void __iomem *regs; -}; - -static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) -{ - return container_of(gc, struct of_mm_gpio_chip, gc); -} - extern int of_get_named_gpio(const struct device_node *np, const char *list_name, int index); -extern int of_mm_gpiochip_add_data(struct device_node *np, - struct of_mm_gpio_chip *mm_gc, - void *data); -extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); - #else /* CONFIG_OF_GPIO */ #include -- cgit From 39ebbd52b73db8598e3399ba3ac9333902251975 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Feb 2023 16:29:48 +0200 Subject: gpio: aggregator: Add missing header(s) Do not imply that some of the generic headers may be always included. Instead, include explicitly what we are direct user of. While at it, drop unused linux/gpio.h and split out the GPIO group of headers. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/gpio/gpio-aggregator.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 6d17d262ad91..20a686f12df7 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -10,19 +10,20 @@ #include #include #include -#include -#include -#include -#include #include #include #include #include #include #include +#include #include #include +#include +#include +#include + #define AGGREGATOR_MAX_GPIOS 512 /* -- cgit From d74c0863fd4ecaeafde6a4bb290dcae90b12d942 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Feb 2023 16:29:48 +0200 Subject: gpio: reg: Add missing header(s) Do not imply that some of the generic headers may be always included. Instead, include explicitly what we are direct user of. While at it, split out the GPIO group of headers. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-reg.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c index d35169bde25a..73c7260d89c0 100644 --- a/drivers/gpio/gpio-reg.c +++ b/drivers/gpio/gpio-reg.c @@ -4,11 +4,19 @@ * * Copyright (C) 2016 Russell King */ -#include -#include +#include +#include +#include +#include +#include #include +#include #include #include +#include + +#include +#include struct gpio_reg { struct gpio_chip gc; -- cgit From e79098ac29a41526a50a83ea77306c634a74e904 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Feb 2023 16:29:48 +0200 Subject: gpio: regmap: Add missing header(s) Do not imply that some of the generic headers may be always included. Instead, include explicitly what we are direct user of. While at it, split out the GPIO group of headers. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-regmap.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index fca17d478984..c08c8e528867 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -5,11 +5,17 @@ * Copyright 2020 Michael Walle */ -#include -#include -#include +#include +#include +#include +#include #include #include +#include +#include + +#include +#include struct gpio_regmap { struct device *parent; -- cgit From 6cfd84c4f4f61905088b642a3ef1038ee627cd98 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Feb 2023 16:29:49 +0200 Subject: gpiolib: Drop unused forward declaration from driver.h There is no struct device_node pointers anywhere in the header, drop unused forward declaration. Signed-off-by: Andy Shevchenko --- include/linux/gpio/driver.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ccd8a512d854..262a84ce9bcb 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -16,7 +16,6 @@ struct gpio_desc; struct of_phandle_args; -struct device_node; struct seq_file; struct gpio_device; struct module; -- cgit From 91e5ae95a0af7d2db9e98e8f99436c02c304378b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Feb 2023 16:29:50 +0200 Subject: gpiolib: Deduplicate forward declarations in consumer.h The struct fwnode_handle pointer is used in both branches of ifdeffery, no need to have a copy of the same in each of them, just make it global. Signed-off-by: Andy Shevchenko --- include/linux/gpio/consumer.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 59cb20cfac3d..a7eb8aa1e54c 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -8,6 +8,7 @@ #include struct device; +struct fwnode_handle; struct gpio_desc; struct gpio_array; @@ -171,9 +172,6 @@ int gpiod_set_consumer_name(struct gpio_desc *desc, const char *name); struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); -/* Child properties interface */ -struct fwnode_handle; - struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode, const char *con_id, int index, enum gpiod_flags flags, @@ -546,9 +544,6 @@ static inline int desc_to_gpio(const struct gpio_desc *desc) return -EINVAL; } -/* Child properties interface */ -struct fwnode_handle; - static inline struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode, const char *con_id, int index, -- cgit From 5b1911976ccf83e892452afb0363500228b35d81 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Feb 2023 16:29:51 +0200 Subject: gpiolib: Group forward declarations in consumer.h For better maintenance group the forward declarations together. Signed-off-by: Andy Shevchenko --- include/linux/gpio/consumer.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index a7eb8aa1e54c..5432e5d5fbfb 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -7,6 +7,7 @@ #include #include +struct acpi_device; struct device; struct fwnode_handle; struct gpio_desc; @@ -602,8 +603,6 @@ struct acpi_gpio_mapping { unsigned int quirks; }; -struct acpi_device; - #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI) int acpi_dev_add_driver_gpios(struct acpi_device *adev, -- cgit From 380c7ba3923c6e471aff0f951a6cf42e8dec2c79 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 8 Feb 2023 19:07:28 +0200 Subject: gpiolib: Clean up headers There is a few things done: - include only the headers we are direct user of - when pointer is in use, provide a forward declaration - add missing headers - group generic headers and subsystem headers - sort each group alphabetically Signed-off-by: Andy Shevchenko --- drivers/gpio/gpiolib-acpi.c | 10 ++++++---- drivers/gpio/gpiolib-acpi.h | 1 - drivers/gpio/gpiolib-of.c | 6 ++++-- drivers/gpio/gpiolib-of.h | 1 - drivers/gpio/gpiolib-swnode.c | 5 +++-- drivers/gpio/gpiolib-sysfs.c | 21 ++++++++++++++++----- drivers/gpio/gpiolib.c | 9 ++++++--- include/linux/gpio.h | 10 ++++------ include/linux/gpio/consumer.h | 14 ++++++++++---- include/linux/gpio/driver.h | 30 +++++++++++++++++++++++------- 10 files changed, 72 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index d8a421ce26a8..0605399c84e7 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -7,17 +7,19 @@ * Mika Westerberg */ +#include #include #include -#include -#include -#include #include -#include #include +#include #include #include +#include +#include +#include + #include "gpiolib.h" #include "gpiolib-acpi.h" diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h index 90fd6b04f24d..0fcd7e14d7f9 100644 --- a/drivers/gpio/gpiolib-acpi.h +++ b/drivers/gpio/gpiolib-acpi.h @@ -9,7 +9,6 @@ #define GPIOLIB_ACPI_H #include -#include #include #include diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 0f699af438b0..1436cdb5fa26 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -10,14 +10,16 @@ #include #include #include -#include #include -#include +#include #include #include #include #include #include +#include + +#include #include #include "gpiolib.h" diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index e5bb065d82ef..6b3a5347c5d9 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -4,7 +4,6 @@ #define GPIOLIB_OF_H #include -#include #include #include diff --git a/drivers/gpio/gpiolib-swnode.c b/drivers/gpio/gpiolib-swnode.c index dd9ccac214d1..b5a6eaf3729b 100644 --- a/drivers/gpio/gpiolib-swnode.c +++ b/drivers/gpio/gpiolib-swnode.c @@ -6,13 +6,14 @@ */ #include #include -#include -#include #include #include #include #include +#include +#include + #include "gpiolib.h" #include "gpiolib-swnode.h" diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 6e4267944f80..c1cbf71329f0 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -1,18 +1,29 @@ // SPDX-License-Identifier: GPL-2.0 + +#include +#include #include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include #include +#include + #include #include -#include -#include -#include -#include #include "gpiolib.h" #include "gpiolib-sysfs.h" +struct kernfs_node; + #define GPIO_IRQF_TRIGGER_NONE 0 #define GPIO_IRQF_TRIGGER_FALLING BIT(0) #define GPIO_IRQF_TRIGGER_RISING BIT(1) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 19bd23044b01..700195a1faae 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -6,22 +6,25 @@ #include #include #include +#include #include #include -#include -#include -#include #include #include #include #include #include #include +#include #include #include #include #include +#include +#include +#include + #include #include "gpiolib-acpi.h" diff --git a/include/linux/gpio.h b/include/linux/gpio.h index a86953696e47..8528353e073b 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -12,9 +12,10 @@ #ifndef __LINUX_GPIO_H #define __LINUX_GPIO_H -#include #include +struct device; + /* see Documentation/driver-api/gpio/legacy.rst */ /* make these flag values available regardless of GPIO kconfig options */ @@ -134,19 +135,16 @@ void gpio_free_array(const struct gpio *array, size_t num); /* CONFIG_GPIOLIB: bindings for managed devices that want to request gpios */ -struct device; - int devm_gpio_request(struct device *dev, unsigned gpio, const char *label); int devm_gpio_request_one(struct device *dev, unsigned gpio, unsigned long flags, const char *label); #else /* ! CONFIG_GPIOLIB */ -#include #include -struct device; -struct gpio_chip; +#include +#include static inline bool gpio_is_valid(int number) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 5432e5d5fbfb..1c4385a00f88 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -3,15 +3,14 @@ #define __LINUX_GPIO_CONSUMER_H #include -#include -#include -#include +#include struct acpi_device; struct device; struct fwnode_handle; -struct gpio_desc; + struct gpio_array; +struct gpio_desc; /** * struct gpio_descs - Struct containing an array of descriptors that can be @@ -185,8 +184,11 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #else /* CONFIG_GPIOLIB */ +#include #include +#include + static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; @@ -616,6 +618,8 @@ struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char #else /* CONFIG_GPIOLIB && CONFIG_ACPI */ +#include + static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, const struct acpi_gpio_mapping *gpios) { @@ -647,6 +651,8 @@ void gpiod_unexport(struct gpio_desc *desc); #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ +#include + static inline int gpiod_export(struct gpio_desc *desc, bool direction_may_change) { diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 262a84ce9bcb..5c6db5533be6 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -2,27 +2,35 @@ #ifndef __LINUX_GPIO_DRIVER_H #define __LINUX_GPIO_DRIVER_H -#include -#include +#include #include #include +#include #include #include #include #include +#include #include +#ifdef CONFIG_GENERIC_MSI_IRQ #include +#endif -struct gpio_desc; +struct device; +struct irq_chip; +struct irq_data; +struct module; struct of_phandle_args; +struct pinctrl_dev; struct seq_file; -struct gpio_device; -struct module; -enum gpiod_flags; -enum gpio_lookup_flags; struct gpio_chip; +struct gpio_desc; +struct gpio_device; + +enum gpio_lookup_flags; +enum gpiod_flags; union gpio_irq_fwspec { struct irq_fwspec fwspec; @@ -679,6 +687,10 @@ bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc, int gpiochip_irqchip_add_domain(struct gpio_chip *gc, struct irq_domain *domain); #else + +#include +#include + static inline int gpiochip_irqchip_add_domain(struct gpio_chip *gc, struct irq_domain *domain) { @@ -756,6 +768,10 @@ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); #else /* CONFIG_GPIOLIB */ +#include + +#include + static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) { /* GPIO can never have been requested */ -- cgit From d2c19e89e03cced2417175f48586648ae88f7cbf Mon Sep 17 00:00:00 2001 From: Pandith N Date: Thu, 16 Feb 2023 18:53:54 +0530 Subject: gpio: tangier: Introduce Intel Tangier GPIO driver Intel Elkhart Lake and Merrifield platforms have same GPIO IP. Intel Tangier implements the common GPIO functionalities for both Elkhart Lake and Merrifield platforms. Signed-off-by: Pandith N Co-developed-by: Raag Jadav Signed-off-by: Raag Jadav Co-developed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- MAINTAINERS | 1 + drivers/gpio/Kconfig | 8 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-tangier.c | 536 ++++++++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpio-tangier.h | 107 +++++++++ 5 files changed, 653 insertions(+) create mode 100644 drivers/gpio/gpio-tangier.c create mode 100644 drivers/gpio/gpio-tangier.h diff --git a/MAINTAINERS b/MAINTAINERS index ddf686c2e546..1176ae6b6d4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10287,6 +10287,7 @@ F: drivers/gpio/gpio-ml-ioh.c F: drivers/gpio/gpio-pch.c F: drivers/gpio/gpio-sch.c F: drivers/gpio/gpio-sodaville.c +F: drivers/gpio/gpio-tangier.c INTEL GVT-g DRIVERS (Intel GPU Virtualization) M: Zhenyu Wang diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2b72a7a7084a..d9c27e733e01 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -619,6 +619,14 @@ config GPIO_SYSCON help Say yes here to support GPIO functionality though SYSCON driver. +config GPIO_TANGIER + tristate + select GPIOLIB_IRQCHIP + help + GPIO support for Intel Tangier and compatible platforms. + + If built as a module its name will be gpio-tangier. + config GPIO_TB10X bool select GPIO_GENERIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c048ba003367..d884abbf6156 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -145,6 +145,7 @@ obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o +obj-$(CONFIG_GPIO_TANGIER) += gpio-tangier.o obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_GPIO_TEGRA186) += gpio-tegra186.o diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c new file mode 100644 index 000000000000..e990781935ba --- /dev/null +++ b/drivers/gpio/gpio-tangier.c @@ -0,0 +1,536 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Intel Tangier GPIO driver + * + * Copyright (c) 2016, 2021, 2023 Intel Corporation. + * + * Authors: Andy Shevchenko + * Pandith N + * Raag Jadav + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gpio-tangier.h" + +#define GCCR 0x000 /* Controller configuration */ +#define GPLR 0x004 /* Pin level r/o */ +#define GPDR 0x01c /* Pin direction */ +#define GPSR 0x034 /* Pin set w/o */ +#define GPCR 0x04c /* Pin clear w/o */ +#define GRER 0x064 /* Rising edge detect */ +#define GFER 0x07c /* Falling edge detect */ +#define GFBR 0x094 /* Glitch filter bypass */ +#define GIMR 0x0ac /* Interrupt mask */ +#define GISR 0x0c4 /* Interrupt source */ +#define GITR 0x300 /* Input type */ +#define GLPR 0x318 /* Level input polarity */ + +/** + * struct tng_gpio_context - Context to be saved during suspend-resume + * @level: Pin level + * @gpdr: Pin direction + * @grer: Rising edge detect enable + * @gfer: Falling edge detect enable + * @gimr: Interrupt mask + * @gwmr: Wake mask + */ +struct tng_gpio_context { + u32 level; + u32 gpdr; + u32 grer; + u32 gfer; + u32 gimr; + u32 gwmr; +}; + +static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset, + unsigned int reg) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + u8 reg_offset = offset / 32; + + return priv->reg_base + reg + reg_offset * 4; +} + +static void __iomem *gpio_reg_and_bit(struct gpio_chip *chip, unsigned int offset, + unsigned int reg, u8 *bit) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + u8 reg_offset = offset / 32; + u8 shift = offset % 32; + + *bit = shift; + return priv->reg_base + reg + reg_offset * 4; +} + +static int tng_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + void __iomem *gplr; + u8 shift; + + gplr = gpio_reg_and_bit(chip, offset, GPLR, &shift); + + return !!(readl(gplr) & BIT(shift)); +} + +static void tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + unsigned long flags; + void __iomem *reg; + u8 shift; + + reg = gpio_reg_and_bit(chip, offset, value ? GPSR : GPCR, &shift); + + raw_spin_lock_irqsave(&priv->lock, flags); + + writel(BIT(shift), reg); + + raw_spin_unlock_irqrestore(&priv->lock, flags); +} + +static int tng_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + unsigned long flags; + void __iomem *gpdr; + u32 value; + u8 shift; + + gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift); + + raw_spin_lock_irqsave(&priv->lock, flags); + + value = readl(gpdr); + value &= ~BIT(shift); + writel(value, gpdr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int tng_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + unsigned long flags; + void __iomem *gpdr; + u8 shift; + + gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift); + tng_gpio_set(chip, offset, value); + + raw_spin_lock_irqsave(&priv->lock, flags); + + value = readl(gpdr); + value |= BIT(shift); + writel(value, gpdr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int tng_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + void __iomem *gpdr; + u8 shift; + + gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift); + + if (readl(gpdr) & BIT(shift)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int tng_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, + unsigned int debounce) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + unsigned long flags; + void __iomem *gfbr; + u32 value; + u8 shift; + + gfbr = gpio_reg_and_bit(chip, offset, GFBR, &shift); + + raw_spin_lock_irqsave(&priv->lock, flags); + + value = readl(gfbr); + if (debounce) + value &= ~BIT(shift); + else + value |= BIT(shift); + writel(value, gfbr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int tng_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + u32 debounce; + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + return gpiochip_generic_config(chip, offset, config); + case PIN_CONFIG_INPUT_DEBOUNCE: + debounce = pinconf_to_config_argument(config); + return tng_gpio_set_debounce(chip, offset, debounce); + default: + return -ENOTSUPP; + } +} + +static void tng_irq_ack(struct irq_data *d) +{ + struct tng_gpio *priv = irq_data_get_irq_chip_data(d); + irq_hw_number_t gpio = irqd_to_hwirq(d); + unsigned long flags; + void __iomem *gisr; + u8 shift; + + gisr = gpio_reg_and_bit(&priv->chip, gpio, GISR, &shift); + + raw_spin_lock_irqsave(&priv->lock, flags); + writel(BIT(shift), gisr); + raw_spin_unlock_irqrestore(&priv->lock, flags); +} + +static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask) +{ + unsigned long flags; + void __iomem *gimr; + u32 value; + u8 shift; + + gimr = gpio_reg_and_bit(&priv->chip, gpio, GIMR, &shift); + + raw_spin_lock_irqsave(&priv->lock, flags); + + value = readl(gimr); + if (unmask) + value |= BIT(shift); + else + value &= ~BIT(shift); + writel(value, gimr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); +} + +static void tng_irq_mask(struct irq_data *d) +{ + struct tng_gpio *priv = irq_data_get_irq_chip_data(d); + irq_hw_number_t gpio = irqd_to_hwirq(d); + + tng_irq_unmask_mask(priv, gpio, false); + gpiochip_disable_irq(&priv->chip, gpio); +} + +static void tng_irq_unmask(struct irq_data *d) +{ + struct tng_gpio *priv = irq_data_get_irq_chip_data(d); + irq_hw_number_t gpio = irqd_to_hwirq(d); + + gpiochip_enable_irq(&priv->chip, gpio); + tng_irq_unmask_mask(priv, gpio, true); +} + +static int tng_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct tng_gpio *priv = gpiochip_get_data(gc); + irq_hw_number_t gpio = irqd_to_hwirq(d); + void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER); + void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER); + void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR); + void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR); + u8 shift = gpio % 32; + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&priv->lock, flags); + + value = readl(grer); + if (type & IRQ_TYPE_EDGE_RISING) + value |= BIT(shift); + else + value &= ~BIT(shift); + writel(value, grer); + + value = readl(gfer); + if (type & IRQ_TYPE_EDGE_FALLING) + value |= BIT(shift); + else + value &= ~BIT(shift); + writel(value, gfer); + + /* + * To prevent glitches from triggering an unintended level interrupt, + * configure GLPR register first and then configure GITR. + */ + value = readl(glpr); + if (type & IRQ_TYPE_LEVEL_LOW) + value |= BIT(shift); + else + value &= ~BIT(shift); + writel(value, glpr); + + if (type & IRQ_TYPE_LEVEL_MASK) { + value = readl(gitr); + value |= BIT(shift); + writel(value, gitr); + + irq_set_handler_locked(d, handle_level_irq); + } else if (type & IRQ_TYPE_EDGE_BOTH) { + value = readl(gitr); + value &= ~BIT(shift); + writel(value, gitr); + + irq_set_handler_locked(d, handle_edge_irq); + } + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int tng_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct tng_gpio *priv = gpiochip_get_data(gc); + irq_hw_number_t gpio = irqd_to_hwirq(d); + void __iomem *gwmr = gpio_reg(&priv->chip, gpio, priv->wake_regs.gwmr); + void __iomem *gwsr = gpio_reg(&priv->chip, gpio, priv->wake_regs.gwsr); + u8 shift = gpio % 32; + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&priv->lock, flags); + + /* Clear the existing wake status */ + writel(BIT(shift), gwsr); + + value = readl(gwmr); + if (on) + value |= BIT(shift); + else + value &= ~BIT(shift); + writel(value, gwmr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + dev_dbg(priv->dev, "%s wake for gpio %lu\n", str_enable_disable(on), gpio); + return 0; +} + +static const struct irq_chip tng_irqchip = { + .name = "gpio-tangier", + .irq_ack = tng_irq_ack, + .irq_mask = tng_irq_mask, + .irq_unmask = tng_irq_unmask, + .irq_set_type = tng_irq_set_type, + .irq_set_wake = tng_irq_set_wake, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void tng_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct tng_gpio *priv = gpiochip_get_data(gc); + struct irq_chip *irqchip = irq_desc_get_chip(desc); + unsigned long base, gpio; + + chained_irq_enter(irqchip, desc); + + /* Check GPIO controller to check which pin triggered the interrupt */ + for (base = 0; base < priv->chip.ngpio; base += 32) { + void __iomem *gisr = gpio_reg(&priv->chip, base, GISR); + void __iomem *gimr = gpio_reg(&priv->chip, base, GIMR); + unsigned long pending, enabled; + + pending = readl(gisr); + enabled = readl(gimr); + + /* Only interrupts that are enabled */ + pending &= enabled; + + for_each_set_bit(gpio, &pending, 32) + generic_handle_domain_irq(gc->irq.domain, base + gpio); + } + + chained_irq_exit(irqchip, desc); +} + +static int tng_irq_init_hw(struct gpio_chip *chip) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + void __iomem *reg; + unsigned int base; + + for (base = 0; base < priv->chip.ngpio; base += 32) { + /* Clear the rising-edge detect register */ + reg = gpio_reg(&priv->chip, base, GRER); + writel(0, reg); + + /* Clear the falling-edge detect register */ + reg = gpio_reg(&priv->chip, base, GFER); + writel(0, reg); + } + + return 0; +} + +static int tng_gpio_add_pin_ranges(struct gpio_chip *chip) +{ + struct tng_gpio *priv = gpiochip_get_data(chip); + const struct tng_gpio_pinrange *range; + unsigned int i; + int ret; + + for (i = 0; i < priv->pin_info.nranges; i++) { + range = &priv->pin_info.pin_ranges[i]; + ret = gpiochip_add_pin_range(&priv->chip, + priv->pin_info.name, + range->gpio_base, + range->pin_base, + range->npins); + if (ret) { + dev_err(priv->dev, "failed to add GPIO pin range\n"); + return ret; + } + } + + return 0; +} + +int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio) +{ + const struct tng_gpio_info *info = &gpio->info; + struct gpio_irq_chip *girq; + int ret; + + gpio->ctx = devm_kcalloc(dev, DIV_ROUND_UP(info->ngpio, 32), sizeof(*gpio->ctx), GFP_KERNEL); + if (!gpio->ctx) + return -ENOMEM; + + gpio->chip.label = dev_name(dev); + gpio->chip.parent = dev; + gpio->chip.request = gpiochip_generic_request; + gpio->chip.free = gpiochip_generic_free; + gpio->chip.direction_input = tng_gpio_direction_input; + gpio->chip.direction_output = tng_gpio_direction_output; + gpio->chip.get = tng_gpio_get; + gpio->chip.set = tng_gpio_set; + gpio->chip.get_direction = tng_gpio_get_direction; + gpio->chip.set_config = tng_gpio_set_config; + gpio->chip.base = info->base; + gpio->chip.ngpio = info->ngpio; + gpio->chip.can_sleep = false; + gpio->chip.add_pin_ranges = tng_gpio_add_pin_ranges; + + raw_spin_lock_init(&gpio->lock); + + girq = &gpio->chip.irq; + gpio_irq_chip_set_chip(girq, &tng_irqchip); + girq->init_hw = tng_irq_init_hw; + girq->parent_handler = tng_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + + girq->parents[0] = gpio->irq; + girq->first = info->first; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + ret = devm_gpiochip_add_data(dev, &gpio->chip, gpio); + if (ret) + return dev_err_probe(dev, ret, "gpiochip_add error\n"); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(devm_tng_gpio_probe, GPIO_TANGIER); + +int tng_gpio_suspend(struct device *dev) +{ + struct tng_gpio *priv = dev_get_drvdata(dev); + struct tng_gpio_context *ctx = priv->ctx; + unsigned long flags; + unsigned int base; + + raw_spin_lock_irqsave(&priv->lock, flags); + + for (base = 0; base < priv->chip.ngpio; base += 32, ctx++) { + /* GPLR is RO, values read will be restored using GPSR */ + ctx->level = readl(gpio_reg(&priv->chip, base, GPLR)); + + ctx->gpdr = readl(gpio_reg(&priv->chip, base, GPDR)); + ctx->grer = readl(gpio_reg(&priv->chip, base, GRER)); + ctx->gfer = readl(gpio_reg(&priv->chip, base, GFER)); + ctx->gimr = readl(gpio_reg(&priv->chip, base, GIMR)); + + ctx->gwmr = readl(gpio_reg(&priv->chip, base, priv->wake_regs.gwmr)); + } + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(tng_gpio_suspend, GPIO_TANGIER); + +int tng_gpio_resume(struct device *dev) +{ + struct tng_gpio *priv = dev_get_drvdata(dev); + struct tng_gpio_context *ctx = priv->ctx; + unsigned long flags; + unsigned int base; + + raw_spin_lock_irqsave(&priv->lock, flags); + + for (base = 0; base < priv->chip.ngpio; base += 32, ctx++) { + /* GPLR is RO, values read will be restored using GPSR */ + writel(ctx->level, gpio_reg(&priv->chip, base, GPSR)); + + writel(ctx->gpdr, gpio_reg(&priv->chip, base, GPDR)); + writel(ctx->grer, gpio_reg(&priv->chip, base, GRER)); + writel(ctx->gfer, gpio_reg(&priv->chip, base, GFER)); + writel(ctx->gimr, gpio_reg(&priv->chip, base, GIMR)); + + writel(ctx->gwmr, gpio_reg(&priv->chip, base, priv->wake_regs.gwmr)); + } + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(tng_gpio_resume, GPIO_TANGIER); + +MODULE_AUTHOR("Andy Shevchenko "); +MODULE_AUTHOR("Pandith N "); +MODULE_AUTHOR("Raag Jadav "); +MODULE_DESCRIPTION("Intel Tangier GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-tangier.h b/drivers/gpio/gpio-tangier.h new file mode 100644 index 000000000000..dd3df3c3f5c6 --- /dev/null +++ b/drivers/gpio/gpio-tangier.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Intel Tangier GPIO functions + * + * Copyright (c) 2016, 2021, 2023 Intel Corporation. + * + * Authors: Andy Shevchenko + * Pandith N + * Raag Jadav + */ + +#ifndef _GPIO_TANGIER_H_ +#define _GPIO_TANGIER_H_ + +#include +#include +#include + +struct device; + +struct tng_gpio_context; + +/** + * struct tng_wake_regs - Platform specific wake registers + * @gwmr: Wake mask + * @gwsr: Wake source + * @gsir: Secure input + */ +struct tng_wake_regs { + u32 gwmr; + u32 gwsr; + u32 gsir; +}; + +/** + * struct tng_gpio_pinrange - Map pin numbers to gpio numbers + * @gpio_base: Starting GPIO number of this range + * @pin_base: Starting pin number of this range + * @npins: Number of pins in this range + */ +struct tng_gpio_pinrange { + unsigned int gpio_base; + unsigned int pin_base; + unsigned int npins; +}; + +#define GPIO_PINRANGE(gstart, gend, pstart) \ +(struct tng_gpio_pinrange) { \ + .gpio_base = (gstart), \ + .pin_base = (pstart), \ + .npins = (gend) - (gstart) + 1, \ + } + +/** + * struct tng_gpio_pin_info - Platform specific pinout information + * @pin_ranges: Pin to GPIO mapping + * @nranges: Number of pin ranges + * @name: Respective pinctrl device name + */ +struct tng_gpio_pin_info { + const struct tng_gpio_pinrange *pin_ranges; + unsigned int nranges; + const char *name; +}; + +/** + * struct tng_gpio_info - Platform specific GPIO and IRQ information + * @base: GPIO base to start numbering with + * @ngpio: Amount of GPIOs supported by the controller + * @first: First IRQ to start numbering with + */ +struct tng_gpio_info { + int base; + u16 ngpio; + unsigned int first; +}; + +/** + * struct tng_gpio - Platform specific private data + * @chip: Instance of the struct gpio_chip + * @reg_base: Base address of MMIO registers + * @irq: Interrupt for the GPIO device + * @lock: Synchronization lock to prevent I/O race conditions + * @dev: The GPIO device + * @ctx: Context to be saved during suspend-resume + * @wake_regs: Platform specific wake registers + * @pin_info: Platform specific pinout information + * @info: Platform specific GPIO and IRQ information + */ +struct tng_gpio { + struct gpio_chip chip; + void __iomem *reg_base; + int irq; + raw_spinlock_t lock; + struct device *dev; + struct tng_gpio_context *ctx; + struct tng_wake_regs wake_regs; + struct tng_gpio_pin_info pin_info; + struct tng_gpio_info info; +}; + +int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio); + +int tng_gpio_suspend(struct device *dev); +int tng_gpio_resume(struct device *dev); + +#endif /* _GPIO_TANGIER_H_ */ -- cgit From 34840be53410c29d67ffb304588a258fab785fd7 Mon Sep 17 00:00:00 2001 From: Pandith N Date: Thu, 16 Feb 2023 20:34:19 +0200 Subject: gpio: merrifield: Adapt to Intel Tangier GPIO driver Make use of Intel Tangier GPIO as a library driver for Merrifield. Signed-off-by: Pandith N Co-developed-by: Raag Jadav Signed-off-by: Raag Jadav Co-developed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- drivers/gpio/Kconfig | 4 +- drivers/gpio/gpio-merrifield.c | 440 +++-------------------------------------- drivers/gpio/gpio-tangier.h | 5 + 3 files changed, 34 insertions(+), 415 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d9c27e733e01..c769d29315e5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -624,6 +624,8 @@ config GPIO_TANGIER select GPIOLIB_IRQCHIP help GPIO support for Intel Tangier and compatible platforms. + Currently supported: + - Merrifield If built as a module its name will be gpio-tangier. @@ -1516,7 +1518,7 @@ config GPIO_BT8XX config GPIO_MERRIFIELD tristate "Intel Merrifield GPIO support" depends on X86_INTEL_MID - select GPIOLIB_IRQCHIP + select GPIO_TANGIER help Say Y here to support Intel Merrifield GPIO. diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 92ea8411050d..5c0b460fcd90 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -2,60 +2,25 @@ /* * Intel Merrifield SoC GPIO driver * - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016, 2023 Intel Corporation. * Author: Andy Shevchenko */ #include #include -#include -#include +#include +#include #include #include #include -#include -#include +#include -#define GCCR 0x000 /* controller configuration */ -#define GPLR 0x004 /* pin level r/o */ -#define GPDR 0x01c /* pin direction */ -#define GPSR 0x034 /* pin set w/o */ -#define GPCR 0x04c /* pin clear w/o */ -#define GRER 0x064 /* rising edge detect */ -#define GFER 0x07c /* falling edge detect */ -#define GFBR 0x094 /* glitch filter bypass */ -#define GIMR 0x0ac /* interrupt mask */ -#define GISR 0x0c4 /* interrupt source */ -#define GITR 0x300 /* input type */ -#define GLPR 0x318 /* level input polarity */ -#define GWMR 0x400 /* wake mask */ -#define GWSR 0x418 /* wake source */ -#define GSIR 0xc00 /* secure input */ +#include "gpio-tangier.h" /* Intel Merrifield has 192 GPIO pins */ #define MRFLD_NGPIO 192 -struct mrfld_gpio_pinrange { - unsigned int gpio_base; - unsigned int pin_base; - unsigned int npins; -}; - -#define GPIO_PINRANGE(gstart, gend, pstart) \ - { \ - .gpio_base = (gstart), \ - .pin_base = (pstart), \ - .npins = (gend) - (gstart) + 1, \ - } - -struct mrfld_gpio { - struct gpio_chip chip; - void __iomem *reg_base; - raw_spinlock_t lock; - struct device *dev; -}; - -static const struct mrfld_gpio_pinrange mrfld_gpio_ranges[] = { +static const struct tng_gpio_pinrange mrfld_gpio_ranges[] = { GPIO_PINRANGE(0, 11, 146), GPIO_PINRANGE(12, 13, 144), GPIO_PINRANGE(14, 15, 35), @@ -84,316 +49,7 @@ static const struct mrfld_gpio_pinrange mrfld_gpio_ranges[] = { GPIO_PINRANGE(190, 191, 178), }; -static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset, - unsigned int reg_type_offset) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - u8 reg = offset / 32; - - return priv->reg_base + reg_type_offset + reg * 4; -} - -static int mrfld_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - void __iomem *gplr = gpio_reg(chip, offset, GPLR); - - return !!(readl(gplr) & BIT(offset % 32)); -} - -static void mrfld_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - void __iomem *gpsr, *gpcr; - unsigned long flags; - - raw_spin_lock_irqsave(&priv->lock, flags); - - if (value) { - gpsr = gpio_reg(chip, offset, GPSR); - writel(BIT(offset % 32), gpsr); - } else { - gpcr = gpio_reg(chip, offset, GPCR); - writel(BIT(offset % 32), gpcr); - } - - raw_spin_unlock_irqrestore(&priv->lock, flags); -} - -static int mrfld_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&priv->lock, flags); - - value = readl(gpdr); - value &= ~BIT(offset % 32); - writel(value, gpdr); - - raw_spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static int mrfld_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - unsigned long flags; - - mrfld_gpio_set(chip, offset, value); - - raw_spin_lock_irqsave(&priv->lock, flags); - - value = readl(gpdr); - value |= BIT(offset % 32); - writel(value, gpdr); - - raw_spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) -{ - void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - - if (readl(gpdr) & BIT(offset % 32)) - return GPIO_LINE_DIRECTION_OUT; - - return GPIO_LINE_DIRECTION_IN; -} - -static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, - unsigned int debounce) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - void __iomem *gfbr = gpio_reg(chip, offset, GFBR); - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&priv->lock, flags); - - if (debounce) - value = readl(gfbr) & ~BIT(offset % 32); - else - value = readl(gfbr) | BIT(offset % 32); - writel(value, gfbr); - - raw_spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static int mrfld_gpio_set_config(struct gpio_chip *chip, unsigned int offset, - unsigned long config) -{ - u32 debounce; - - if ((pinconf_to_config_param(config) == PIN_CONFIG_BIAS_DISABLE) || - (pinconf_to_config_param(config) == PIN_CONFIG_BIAS_PULL_UP) || - (pinconf_to_config_param(config) == PIN_CONFIG_BIAS_PULL_DOWN)) - return gpiochip_generic_config(chip, offset, config); - - if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) - return -ENOTSUPP; - - debounce = pinconf_to_config_argument(config); - return mrfld_gpio_set_debounce(chip, offset, debounce); -} - -static void mrfld_irq_ack(struct irq_data *d) -{ - struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); - u32 gpio = irqd_to_hwirq(d); - void __iomem *gisr = gpio_reg(&priv->chip, gpio, GISR); - unsigned long flags; - - raw_spin_lock_irqsave(&priv->lock, flags); - - writel(BIT(gpio % 32), gisr); - - raw_spin_unlock_irqrestore(&priv->lock, flags); -} - -static void mrfld_irq_unmask_mask(struct mrfld_gpio *priv, u32 gpio, bool unmask) -{ - void __iomem *gimr = gpio_reg(&priv->chip, gpio, GIMR); - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&priv->lock, flags); - - if (unmask) - value = readl(gimr) | BIT(gpio % 32); - else - value = readl(gimr) & ~BIT(gpio % 32); - writel(value, gimr); - - raw_spin_unlock_irqrestore(&priv->lock, flags); -} - -static void mrfld_irq_mask(struct irq_data *d) -{ - struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); - u32 gpio = irqd_to_hwirq(d); - - mrfld_irq_unmask_mask(priv, gpio, false); - gpiochip_disable_irq(&priv->chip, gpio); -} - -static void mrfld_irq_unmask(struct irq_data *d) -{ - struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); - u32 gpio = irqd_to_hwirq(d); - - gpiochip_enable_irq(&priv->chip, gpio); - mrfld_irq_unmask_mask(priv, gpio, true); -} - -static int mrfld_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct mrfld_gpio *priv = gpiochip_get_data(gc); - u32 gpio = irqd_to_hwirq(d); - void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER); - void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER); - void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR); - void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR); - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&priv->lock, flags); - - if (type & IRQ_TYPE_EDGE_RISING) - value = readl(grer) | BIT(gpio % 32); - else - value = readl(grer) & ~BIT(gpio % 32); - writel(value, grer); - - if (type & IRQ_TYPE_EDGE_FALLING) - value = readl(gfer) | BIT(gpio % 32); - else - value = readl(gfer) & ~BIT(gpio % 32); - writel(value, gfer); - - /* - * To prevent glitches from triggering an unintended level interrupt, - * configure GLPR register first and then configure GITR. - */ - if (type & IRQ_TYPE_LEVEL_LOW) - value = readl(glpr) | BIT(gpio % 32); - else - value = readl(glpr) & ~BIT(gpio % 32); - writel(value, glpr); - - if (type & IRQ_TYPE_LEVEL_MASK) { - value = readl(gitr) | BIT(gpio % 32); - writel(value, gitr); - - irq_set_handler_locked(d, handle_level_irq); - } else if (type & IRQ_TYPE_EDGE_BOTH) { - value = readl(gitr) & ~BIT(gpio % 32); - writel(value, gitr); - - irq_set_handler_locked(d, handle_edge_irq); - } - - raw_spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static int mrfld_irq_set_wake(struct irq_data *d, unsigned int on) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct mrfld_gpio *priv = gpiochip_get_data(gc); - u32 gpio = irqd_to_hwirq(d); - void __iomem *gwmr = gpio_reg(&priv->chip, gpio, GWMR); - void __iomem *gwsr = gpio_reg(&priv->chip, gpio, GWSR); - unsigned long flags; - u32 value; - - raw_spin_lock_irqsave(&priv->lock, flags); - - /* Clear the existing wake status */ - writel(BIT(gpio % 32), gwsr); - - if (on) - value = readl(gwmr) | BIT(gpio % 32); - else - value = readl(gwmr) & ~BIT(gpio % 32); - writel(value, gwmr); - - raw_spin_unlock_irqrestore(&priv->lock, flags); - - dev_dbg(priv->dev, "%s wake for gpio %u\n", str_enable_disable(on), gpio); - return 0; -} - -static const struct irq_chip mrfld_irqchip = { - .name = "gpio-merrifield", - .irq_ack = mrfld_irq_ack, - .irq_mask = mrfld_irq_mask, - .irq_unmask = mrfld_irq_unmask, - .irq_set_type = mrfld_irq_set_type, - .irq_set_wake = mrfld_irq_set_wake, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, -}; - -static void mrfld_irq_handler(struct irq_desc *desc) -{ - struct gpio_chip *gc = irq_desc_get_handler_data(desc); - struct mrfld_gpio *priv = gpiochip_get_data(gc); - struct irq_chip *irqchip = irq_desc_get_chip(desc); - unsigned long base, gpio; - - chained_irq_enter(irqchip, desc); - - /* Check GPIO controller to check which pin triggered the interrupt */ - for (base = 0; base < priv->chip.ngpio; base += 32) { - void __iomem *gisr = gpio_reg(&priv->chip, base, GISR); - void __iomem *gimr = gpio_reg(&priv->chip, base, GIMR); - unsigned long pending, enabled; - - pending = readl(gisr); - enabled = readl(gimr); - - /* Only interrupts that are enabled */ - pending &= enabled; - - for_each_set_bit(gpio, &pending, 32) - generic_handle_domain_irq(gc->irq.domain, base + gpio); - } - - chained_irq_exit(irqchip, desc); -} - -static int mrfld_irq_init_hw(struct gpio_chip *chip) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - void __iomem *reg; - unsigned int base; - - for (base = 0; base < priv->chip.ngpio; base += 32) { - /* Clear the rising-edge detect register */ - reg = gpio_reg(&priv->chip, base, GRER); - writel(0, reg); - /* Clear the falling-edge detect register */ - reg = gpio_reg(&priv->chip, base, GFER); - writel(0, reg); - } - - return 0; -} - -static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) +static const char *mrfld_gpio_get_pinctrl_dev_name(struct tng_gpio *priv) { struct acpi_device *adev; const char *name; @@ -409,37 +65,10 @@ static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) return name; } -static int mrfld_gpio_add_pin_ranges(struct gpio_chip *chip) -{ - struct mrfld_gpio *priv = gpiochip_get_data(chip); - const struct mrfld_gpio_pinrange *range; - const char *pinctrl_dev_name; - unsigned int i; - int retval; - - pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv); - if (!pinctrl_dev_name) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { - range = &mrfld_gpio_ranges[i]; - retval = gpiochip_add_pin_range(&priv->chip, pinctrl_dev_name, - range->gpio_base, - range->pin_base, - range->npins); - if (retval) { - dev_err(priv->dev, "failed to add GPIO pin range\n"); - return retval; - } - } - - return 0; -} - static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct gpio_irq_chip *girq; - struct mrfld_gpio *priv; + struct device *dev = &pdev->dev; + struct tng_gpio *priv; u32 gpio_base, irq_base; void __iomem *base; int retval; @@ -469,46 +98,29 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id priv->dev = &pdev->dev; priv->reg_base = pcim_iomap_table(pdev)[0]; - priv->chip.label = dev_name(&pdev->dev); - priv->chip.parent = &pdev->dev; - priv->chip.request = gpiochip_generic_request; - priv->chip.free = gpiochip_generic_free; - priv->chip.direction_input = mrfld_gpio_direction_input; - priv->chip.direction_output = mrfld_gpio_direction_output; - priv->chip.get = mrfld_gpio_get; - priv->chip.set = mrfld_gpio_set; - priv->chip.get_direction = mrfld_gpio_get_direction; - priv->chip.set_config = mrfld_gpio_set_config; - priv->chip.base = gpio_base; - priv->chip.ngpio = MRFLD_NGPIO; - priv->chip.can_sleep = false; - priv->chip.add_pin_ranges = mrfld_gpio_add_pin_ranges; + priv->pin_info.pin_ranges = mrfld_gpio_ranges; + priv->pin_info.nranges = ARRAY_SIZE(mrfld_gpio_ranges); + priv->pin_info.name = mrfld_gpio_get_pinctrl_dev_name(priv); + if (!priv->pin_info.name) + return -ENOMEM; - raw_spin_lock_init(&priv->lock); + priv->info.base = gpio_base; + priv->info.ngpio = MRFLD_NGPIO; + priv->info.first = irq_base; retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); if (retval < 0) return retval; - girq = &priv->chip.irq; - gpio_irq_chip_set_chip(girq, &mrfld_irqchip); - girq->init_hw = mrfld_irq_init_hw; - girq->parent_handler = mrfld_irq_handler; - girq->num_parents = 1; - girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, - sizeof(*girq->parents), GFP_KERNEL); - if (!girq->parents) - return -ENOMEM; - girq->parents[0] = pci_irq_vector(pdev, 0); - girq->first = irq_base; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_bad_irq; + priv->irq = pci_irq_vector(pdev, 0); - retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); - if (retval) { - dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); - return retval; - } + priv->wake_regs.gwmr = GWMR_MRFLD; + priv->wake_regs.gwsr = GWSR_MRFLD; + priv->wake_regs.gsir = GSIR_MRFLD; + + retval = devm_tng_gpio_probe(dev, priv); + if (retval) + return dev_err_probe(dev, retval, "tng_gpio_probe error\n"); pci_set_drvdata(pdev, priv); return 0; @@ -525,9 +137,9 @@ static struct pci_driver mrfld_gpio_driver = { .id_table = mrfld_gpio_ids, .probe = mrfld_gpio_probe, }; - module_pci_driver(mrfld_gpio_driver); MODULE_AUTHOR("Andy Shevchenko "); MODULE_DESCRIPTION("Intel Merrifield SoC GPIO driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(GPIO_TANGIER); diff --git a/drivers/gpio/gpio-tangier.h b/drivers/gpio/gpio-tangier.h index dd3df3c3f5c6..735b966db423 100644 --- a/drivers/gpio/gpio-tangier.h +++ b/drivers/gpio/gpio-tangier.h @@ -20,6 +20,11 @@ struct device; struct tng_gpio_context; +/* Merrifield specific wake registers */ +#define GWMR_MRFLD 0x400 /* Wake mask */ +#define GWSR_MRFLD 0x418 /* Wake source */ +#define GSIR_MRFLD 0xc00 /* Secure input */ + /** * struct tng_wake_regs - Platform specific wake registers * @gwmr: Wake mask -- cgit From dd0ccef23649d2e54aea1b317be36b2dbde0f329 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Jan 2023 15:44:46 +0100 Subject: gpio: merrifield: Use dev_err_probe() Improve error handling in the probe() function with dev_err_probe(). Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 5c0b460fcd90..c64057343954 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -78,10 +78,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id return retval; retval = pcim_iomap_regions(pdev, BIT(1) | BIT(0), pci_name(pdev)); - if (retval) { - dev_err(&pdev->dev, "I/O memory mapping error\n"); - return retval; - } + if (retval) + return dev_err_probe(dev, retval, "I/O memory mapping error\n"); base = pcim_iomap_table(pdev)[1]; -- cgit From dc537030647a451bca169209d05b50d2ca3fe4f6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 16 Feb 2023 20:03:42 +0200 Subject: gpio: merrifield: Utilise temporary variable for struct device We have a temporary variable to keep pointer to struct device. Utilise it inside the ->probe() implementation. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index c64057343954..421d7e3a6c66 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -51,12 +51,13 @@ static const struct tng_gpio_pinrange mrfld_gpio_ranges[] = { static const char *mrfld_gpio_get_pinctrl_dev_name(struct tng_gpio *priv) { + struct device *dev = priv->dev; struct acpi_device *adev; const char *name; adev = acpi_dev_get_first_match_dev("INTC1002", NULL, -1); if (adev) { - name = devm_kstrdup(priv->dev, acpi_dev_name(adev), GFP_KERNEL); + name = devm_kstrdup(dev, acpi_dev_name(adev), GFP_KERNEL); acpi_dev_put(adev); } else { name = "pinctrl-merrifield"; @@ -89,11 +90,11 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id /* Release the IO mapping, since we already get the info from BAR1 */ pcim_iounmap_regions(pdev, BIT(1)); - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->dev = &pdev->dev; + priv->dev = dev; priv->reg_base = pcim_iomap_table(pdev)[0]; priv->pin_info.pin_ranges = mrfld_gpio_ranges; -- cgit From 9409d8cf78d9c5471cfd229e652f12050c6dbbde Mon Sep 17 00:00:00 2001 From: Pandith N Date: Thu, 16 Feb 2023 20:36:08 +0200 Subject: gpio: elkhartlake: Introduce Intel Elkhart Lake PSE GPIO This driver adds support for Intel Elkhart Lake PSE GPIO controller, using Intel Tangier as a library driver. Signed-off-by: Pandith N Co-developed-by: Raag Jadav Signed-off-by: Raag Jadav Co-developed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- MAINTAINERS | 1 + drivers/gpio/Kconfig | 12 ++++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-elkhartlake.c | 90 +++++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpio-tangier.h | 5 +++ 5 files changed, 109 insertions(+) create mode 100644 drivers/gpio/gpio-elkhartlake.c diff --git a/MAINTAINERS b/MAINTAINERS index 1176ae6b6d4c..958e5570cd59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10281,6 +10281,7 @@ M: Andy Shevchenko L: linux-gpio@vger.kernel.org S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git +F: drivers/gpio/gpio-elkhartlake.c F: drivers/gpio/gpio-ich.c F: drivers/gpio/gpio-merrifield.c F: drivers/gpio/gpio-ml-ioh.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c769d29315e5..8f442ed4a322 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -625,6 +625,7 @@ config GPIO_TANGIER help GPIO support for Intel Tangier and compatible platforms. Currently supported: + - Elkhart Lake - Merrifield If built as a module its name will be gpio-tangier. @@ -1248,6 +1249,17 @@ config HTC_EGPIO several HTC phones. It provides basic support for input pins, output pins, and IRQs. +config GPIO_ELKHARTLAKE + tristate "Intel Elkhart Lake PSE GPIO support" + depends on X86 || COMPILE_TEST + select GPIO_TANGIER + help + Select this option to enable GPIO support for Intel Elkhart Lake + PSE GPIO IP. + + To compile this driver as a module, choose M here: the module will + be called gpio-elkhartlake. + config GPIO_JANZ_TTL tristate "Janz VMOD-TTL Digital IO Module" depends on MFD_JANZ_CMODIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d884abbf6156..594a443eba60 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o +obj-$(CONFIG_GPIO_ELKHARTLAKE) += gpio-elkhartlake.o obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EN7523) += gpio-en7523.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o diff --git a/drivers/gpio/gpio-elkhartlake.c b/drivers/gpio/gpio-elkhartlake.c new file mode 100644 index 000000000000..a9c8b16215be --- /dev/null +++ b/drivers/gpio/gpio-elkhartlake.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Intel Elkhart Lake PSE GPIO driver + * + * Copyright (c) 2023 Intel Corporation. + * + * Authors: Pandith N + * Raag Jadav + */ + +#include +#include +#include +#include +#include + +#include "gpio-tangier.h" + +/* Each Intel EHL PSE GPIO Controller has 30 GPIO pins */ +#define EHL_PSE_NGPIO 30 + +static int ehl_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tng_gpio *priv; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->reg_base)) + return PTR_ERR(priv->reg_base); + + priv->dev = dev; + priv->irq = irq; + + priv->info.base = -1; + priv->info.ngpio = EHL_PSE_NGPIO; + + priv->wake_regs.gwmr = GWMR_EHL; + priv->wake_regs.gwsr = GWSR_EHL; + priv->wake_regs.gsir = GSIR_EHL; + + ret = devm_tng_gpio_probe(dev, priv); + if (ret) + return dev_err_probe(dev, ret, "tng_gpio_probe error\n"); + + platform_set_drvdata(pdev, priv); + return 0; +} + +static int ehl_gpio_suspend(struct device *dev) +{ + return tng_gpio_suspend(dev); +} + +static int ehl_gpio_resume(struct device *dev) +{ + return tng_gpio_resume(dev); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(ehl_gpio_pm_ops, ehl_gpio_suspend, ehl_gpio_resume); + +static const struct platform_device_id ehl_gpio_ids[] = { + { "gpio-elkhartlake" }, + { } +}; +MODULE_DEVICE_TABLE(platform, ehl_gpio_ids); + +static struct platform_driver ehl_gpio_driver = { + .driver = { + .name = "gpio-elkhartlake", + .pm = pm_sleep_ptr(&ehl_gpio_pm_ops), + }, + .probe = ehl_gpio_probe, + .id_table = ehl_gpio_ids, +}; +module_platform_driver(ehl_gpio_driver); + +MODULE_AUTHOR("Pandith N "); +MODULE_AUTHOR("Raag Jadav "); +MODULE_DESCRIPTION("Intel Elkhart Lake PSE GPIO driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(GPIO_TANGIER); diff --git a/drivers/gpio/gpio-tangier.h b/drivers/gpio/gpio-tangier.h index 735b966db423..16c4f22908fb 100644 --- a/drivers/gpio/gpio-tangier.h +++ b/drivers/gpio/gpio-tangier.h @@ -20,6 +20,11 @@ struct device; struct tng_gpio_context; +/* Elkhart Lake specific wake registers */ +#define GWMR_EHL 0x100 /* Wake mask */ +#define GWSR_EHL 0x118 /* Wake source */ +#define GSIR_EHL 0x130 /* Secure input */ + /* Merrifield specific wake registers */ #define GWMR_MRFLD 0x400 /* Wake mask */ #define GWSR_MRFLD 0x418 /* Wake source */ -- cgit From 67f64d1589ba946970aaaed35ee6335d043a4933 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Mar 2023 20:25:55 +0200 Subject: gpiolib: Access device's fwnode via dev_fwnode() GPIO device's fwnode should be accessed via dev_fwnode(). Make sure that gpiochip_setup_dev() follows that. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 700195a1faae..b1aa13d1b7e3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -588,14 +588,15 @@ static void gpiodevice_release(struct device *dev) static int gpiochip_setup_dev(struct gpio_device *gdev) { + struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev); int ret; /* * If fwnode doesn't belong to another device, it's safe to clear its * initialized flag. */ - if (gdev->dev.fwnode && !gdev->dev.fwnode->dev) - fwnode_dev_initialized(gdev->dev.fwnode, false); + if (fwnode && !fwnode->dev) + fwnode_dev_initialized(fwnode, false); ret = gcdev_register(gdev, gpio_devt); if (ret) -- cgit From c135f401265ae1b8b15c8fd607a4a113c61d79f8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Mar 2023 20:25:56 +0200 Subject: gpiolib: Get rid of gpio_bus_match() forward declaration There is nothing specific about gpio_bus_match(), so we may simply move it to the top of the file and get rid of forward declaration. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index b1aa13d1b7e3..7c75e0e5fe22 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -61,7 +61,20 @@ static DEFINE_IDA(gpio_ida); static dev_t gpio_devt; #define GPIO_DEV_MAX 256 /* 256 GPIO chip devices supported */ -static int gpio_bus_match(struct device *dev, struct device_driver *drv); + +static int gpio_bus_match(struct device *dev, struct device_driver *drv) +{ + struct fwnode_handle *fwnode = dev_fwnode(dev); + + /* + * Only match if the fwnode doesn't already have a proper struct device + * created for it. + */ + if (fwnode && fwnode->dev != dev) + return 0; + return 1; +} + static struct bus_type gpio_bus_type = { .name = "gpio", .match = gpio_bus_match, @@ -4417,20 +4430,6 @@ void gpiod_put_array(struct gpio_descs *descs) } EXPORT_SYMBOL_GPL(gpiod_put_array); - -static int gpio_bus_match(struct device *dev, struct device_driver *drv) -{ - struct fwnode_handle *fwnode = dev_fwnode(dev); - - /* - * Only match if the fwnode doesn't already have a proper struct device - * created for it. - */ - if (fwnode && fwnode->dev != dev) - return 0; - return 1; -} - static int gpio_stub_drv_probe(struct device *dev) { /* -- cgit From 56b16a9a80232fc70bebe31ded52c2f6fd3f7ddf Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Tue, 7 Mar 2023 10:54:27 -0600 Subject: gpio: ich: Use devm_gpiochip_add_data() to simplify remove path Use devm version of gpiochip add function to handle removal for us. Signed-off-by: Andrew Davis Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-ich.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 3b31f5e9bf40..0be9285efebc 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -457,7 +457,7 @@ static int ichx_gpio_probe(struct platform_device *pdev) init: ichx_gpiolib_setup(&ichx_priv.chip); - err = gpiochip_add_data(&ichx_priv.chip, NULL); + err = devm_gpiochip_add_data(dev, &ichx_priv.chip, NULL); if (err) { dev_err(dev, "Failed to register GPIOs\n"); return err; @@ -469,19 +469,11 @@ init: return 0; } -static int ichx_gpio_remove(struct platform_device *pdev) -{ - gpiochip_remove(&ichx_priv.chip); - - return 0; -} - static struct platform_driver ichx_gpio_driver = { .driver = { .name = DRV_NAME, }, .probe = ichx_gpio_probe, - .remove = ichx_gpio_remove, }; module_platform_driver(ichx_gpio_driver); -- cgit From b96eb88f59c023bb27891b5ab3dbd2b1a5200d53 Mon Sep 17 00:00:00 2001 From: Yinbo Zhu Date: Thu, 9 Mar 2023 19:14:07 +0800 Subject: gpio: loongson: fixup the warning about OF_GPIO direct dependencies WARNING: unmet direct dependencies detected for OF_GPIO Depends on [n]: GPIOLIB [=y] && OF [=n] && HAS_IOMEM [=y] Selected by [y]: - GPIO_LOONGSON_64BIT [=y] && GPIOLIB [=y] && HAS_IOMEM [=y] && (LOONGARCH || COMPILE_TEST [=y]) Signed-off-by: Yinbo Zhu Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202303091728.UUe6LWye-lkp@intel.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6734c4752caa..5ef2bfbd805b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -384,7 +384,7 @@ config GPIO_LOONGSON config GPIO_LOONGSON_64BIT tristate "Loongson 64 bit GPIO support" depends on LOONGARCH || COMPILE_TEST - select OF_GPIO + depends on OF_GPIO select GPIO_GENERIC help Say yes here to support the GPIO functionality of a number of -- cgit From 424b21e01aafc98a9c086f00b3ad1874302b92fc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Mar 2023 15:52:53 +0100 Subject: mips: ar7: include linux/gpio/driver.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The change to remove the implicit gpio/driver.h include was done after fixing all the other users, but the ar7 file still needs the same change. Reported-by: Naresh Kamboju Fixes: 21d9526d13b5 ("gpiolib: Make the legacy consumer-only") Signed-off-by: Arnd Bergmann Reviewed-by: Florian Fainelli Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- arch/mips/ar7/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c index ae0e01b9438f..4ed833b9cc2f 100644 --- a/arch/mips/ar7/gpio.c +++ b/arch/mips/ar7/gpio.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include -- cgit From 5cd79816d2f25cdaee5e929a5ade4d46c0ab7c3d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:49 +0100 Subject: gpio: altera: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-altera.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 99e137f8097e..338884043bbb 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -24,14 +24,12 @@ * @interrupt_trigger : specifies the hardware configured IRQ trigger type * (rising, falling, both, high) * @mapped_irq : kernel mapped irq number. -* @irq_chip : IRQ chip configuration */ struct altera_gpio_chip { struct of_mm_gpio_chip mmchip; raw_spinlock_t gpio_lock; int interrupt_trigger; int mapped_irq; - struct irq_chip irq_chip; }; static void altera_gpio_irq_unmask(struct irq_data *d) @@ -43,6 +41,7 @@ static void altera_gpio_irq_unmask(struct irq_data *d) altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); mm_gc = &altera_gc->mmchip; + gpiochip_enable_irq(&mm_gc->gc, irqd_to_hwirq(d)); raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags); intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); @@ -68,6 +67,7 @@ static void altera_gpio_irq_mask(struct irq_data *d) intmask &= ~BIT(irqd_to_hwirq(d)); writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK); raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); + gpiochip_disable_irq(&mm_gc->gc, irqd_to_hwirq(d)); } /* @@ -233,6 +233,17 @@ static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static const struct irq_chip altera_gpio_irq_chip = { + .name = "altera-gpio", + .irq_mask = altera_gpio_irq_mask, + .irq_unmask = altera_gpio_irq_unmask, + .irq_set_type = altera_gpio_irq_set_type, + .irq_startup = altera_gpio_irq_startup, + .irq_shutdown = altera_gpio_irq_mask, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int altera_gpio_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -278,15 +289,9 @@ static int altera_gpio_probe(struct platform_device *pdev) } altera_gc->interrupt_trigger = reg; - altera_gc->irq_chip.name = "altera-gpio"; - altera_gc->irq_chip.irq_mask = altera_gpio_irq_mask; - altera_gc->irq_chip.irq_unmask = altera_gpio_irq_unmask; - altera_gc->irq_chip.irq_set_type = altera_gpio_irq_set_type; - altera_gc->irq_chip.irq_startup = altera_gpio_irq_startup; - altera_gc->irq_chip.irq_shutdown = altera_gpio_irq_mask; - girq = &altera_gc->mmchip.gc.irq; - girq->chip = &altera_gc->irq_chip; + gpio_irq_chip_set_chip(girq, &altera_gpio_irq_chip); + if (altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH) girq->parent_handler = altera_gpio_irq_leveL_high_handler; else -- cgit From d4c0cf340861b10a0a984b30306ddd09d2da7131 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:50 +0100 Subject: gpio: adnp: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-adnp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index a6439e3daff0..9b01c391efce 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -307,6 +307,7 @@ static void adnp_irq_mask(struct irq_data *d) unsigned int pos = d->hwirq & 7; adnp->irq_enable[reg] &= ~BIT(pos); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void adnp_irq_unmask(struct irq_data *d) @@ -316,6 +317,7 @@ static void adnp_irq_unmask(struct irq_data *d) unsigned int reg = d->hwirq >> adnp->reg_shift; unsigned int pos = d->hwirq & 7; + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); adnp->irq_enable[reg] |= BIT(pos); } @@ -372,13 +374,15 @@ static void adnp_irq_bus_unlock(struct irq_data *d) mutex_unlock(&adnp->irq_lock); } -static struct irq_chip adnp_irq_chip = { +static const struct irq_chip adnp_irq_chip = { .name = "gpio-adnp", .irq_mask = adnp_irq_mask, .irq_unmask = adnp_irq_unmask, .irq_set_type = adnp_irq_set_type, .irq_bus_lock = adnp_irq_bus_lock, .irq_bus_sync_unlock = adnp_irq_bus_unlock, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int adnp_irq_setup(struct adnp *adnp) @@ -469,7 +473,8 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios, return err; girq = &chip->irq; - girq->chip = &adnp_irq_chip; + gpio_irq_chip_set_chip(girq, &adnp_irq_chip); + /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From 90d17632e71d15bf7e4879eced0cbd2d90c3d60f Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Thu, 9 Mar 2023 08:45:51 +0100 Subject: gpio: aspeed: Always register the irqchip The driver was implemented in a way that made the irqchip optional, if a irq was not present in the device tree. However, all of the device trees have always had an irq, so the optional-ness has never been used. Signed-off-by: Joel Stanley Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-aspeed.c | 49 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index a94da80d3a95..129f6a6b4d1d 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -1137,8 +1137,9 @@ MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table); static int __init aspeed_gpio_probe(struct platform_device *pdev) { const struct of_device_id *gpio_id; + struct gpio_irq_chip *girq; struct aspeed_gpio *gpio; - int rc, i, banks, err; + int rc, irq, i, banks, err; u32 ngpio; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -1201,31 +1202,27 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM); } - /* Optionally set up an irqchip if there is an IRQ */ - rc = platform_get_irq(pdev, 0); - if (rc > 0) { - struct gpio_irq_chip *girq; - - gpio->irq = rc; - girq = &gpio->chip.irq; - girq->chip = &gpio->irqc; - girq->chip->name = dev_name(&pdev->dev); - girq->chip->irq_ack = aspeed_gpio_irq_ack; - girq->chip->irq_mask = aspeed_gpio_irq_mask; - girq->chip->irq_unmask = aspeed_gpio_irq_unmask; - girq->chip->irq_set_type = aspeed_gpio_set_type; - girq->parent_handler = aspeed_gpio_irq_handler; - girq->num_parents = 1; - girq->parents = devm_kcalloc(&pdev->dev, 1, - sizeof(*girq->parents), - GFP_KERNEL); - if (!girq->parents) - return -ENOMEM; - girq->parents[0] = gpio->irq; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_bad_irq; - girq->init_valid_mask = aspeed_init_irq_valid_mask; - } + /* Set up an irqchip */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + gpio->irq = irq; + girq = &gpio->chip.irq; + girq->chip = &gpio->irqc; + girq->chip->name = dev_name(&pdev->dev); + girq->chip->irq_ack = aspeed_gpio_irq_ack; + girq->chip->irq_mask = aspeed_gpio_irq_mask; + girq->chip->irq_unmask = aspeed_gpio_irq_unmask; + girq->chip->irq_set_type = aspeed_gpio_set_type; + girq->parent_handler = aspeed_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = gpio->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->init_valid_mask = aspeed_init_irq_valid_mask; gpio->offset_timer = devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL); -- cgit From 061df08f063a973ce133d0d6be3d89a081ae8998 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:52 +0100 Subject: gpio: aspeed: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Tested-by: Joel Stanley Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-aspeed.c | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 129f6a6b4d1d..da33bbbdacb9 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,7 @@ struct aspeed_gpio_config { */ struct aspeed_gpio { struct gpio_chip chip; - struct irq_chip irqc; + struct device *dev; raw_spinlock_t lock; void __iomem *base; int irq; @@ -566,6 +567,10 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set) addr = bank_reg(gpio, bank, reg_irq_enable); + /* Unmasking the IRQ */ + if (set) + gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d)); + raw_spin_lock_irqsave(&gpio->lock, flags); copro = aspeed_gpio_copro_request(gpio, offset); @@ -579,6 +584,10 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set) if (copro) aspeed_gpio_copro_release(gpio, offset); raw_spin_unlock_irqrestore(&gpio->lock, flags); + + /* Masking the IRQ */ + if (!set) + gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(d)); } static void aspeed_gpio_irq_mask(struct irq_data *d) @@ -1080,6 +1089,30 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio); +static void aspeed_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + const struct aspeed_gpio_bank *bank; + struct aspeed_gpio *gpio; + u32 bit; + int rc, offset; + + rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset); + if (rc) + return; + + seq_printf(p, dev_name(gpio->dev)); +} + +static const struct irq_chip aspeed_gpio_irq_chip = { + .irq_ack = aspeed_gpio_irq_ack, + .irq_mask = aspeed_gpio_irq_mask, + .irq_unmask = aspeed_gpio_irq_unmask, + .irq_set_type = aspeed_gpio_set_type, + .irq_print_chip = aspeed_gpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + /* * Any banks not specified in a struct aspeed_bank_props array are assumed to * have the properties: @@ -1150,6 +1183,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->base)) return PTR_ERR(gpio->base); + gpio->dev = &pdev->dev; + raw_spin_lock_init(&gpio->lock); gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node); @@ -1208,12 +1243,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) return irq; gpio->irq = irq; girq = &gpio->chip.irq; - girq->chip = &gpio->irqc; - girq->chip->name = dev_name(&pdev->dev); - girq->chip->irq_ack = aspeed_gpio_irq_ack; - girq->chip->irq_mask = aspeed_gpio_irq_mask; - girq->chip->irq_unmask = aspeed_gpio_irq_unmask; - girq->chip->irq_set_type = aspeed_gpio_set_type; + gpio_irq_chip_set_chip(girq, &aspeed_gpio_irq_chip); + girq->parent_handler = aspeed_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL); -- cgit From c5dcf76805a759ba42852a69c579fe106e6e116d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:53 +0100 Subject: gpio: aspeed-sgpio: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-aspeed-sgpio.c | 44 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c index ecc94bfded86..72755fee6478 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,7 @@ struct aspeed_sgpio_pdata { struct aspeed_sgpio { struct gpio_chip chip; - struct irq_chip intc; + struct device *dev; struct clk *pclk; raw_spinlock_t lock; void __iomem *base; @@ -296,6 +297,10 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); addr = bank_reg(gpio, bank, reg_irq_enable); + /* Unmasking the IRQ */ + if (set) + gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d)); + raw_spin_lock_irqsave(&gpio->lock, flags); reg = ioread32(addr); @@ -307,6 +312,12 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) iowrite32(reg, addr); raw_spin_unlock_irqrestore(&gpio->lock, flags); + + /* Masking the IRQ */ + if (!set) + gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(d)); + + } static void aspeed_sgpio_irq_mask(struct irq_data *d) @@ -401,6 +412,27 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc) chained_irq_exit(ic, desc); } +static void aspeed_sgpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + const struct aspeed_sgpio_bank *bank; + struct aspeed_sgpio *gpio; + u32 bit; + int offset; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + seq_printf(p, dev_name(gpio->dev)); +} + +static const struct irq_chip aspeed_sgpio_irq_chip = { + .irq_ack = aspeed_sgpio_irq_ack, + .irq_mask = aspeed_sgpio_irq_mask, + .irq_unmask = aspeed_sgpio_irq_unmask, + .irq_set_type = aspeed_sgpio_set_type, + .irq_print_chip = aspeed_sgpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, struct platform_device *pdev) { @@ -423,14 +455,8 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); } - gpio->intc.name = dev_name(&pdev->dev); - gpio->intc.irq_ack = aspeed_sgpio_irq_ack; - gpio->intc.irq_mask = aspeed_sgpio_irq_mask; - gpio->intc.irq_unmask = aspeed_sgpio_irq_unmask; - gpio->intc.irq_set_type = aspeed_sgpio_set_type; - irq = &gpio->chip.irq; - irq->chip = &gpio->intc; + gpio_irq_chip_set_chip(irq, &aspeed_sgpio_irq_chip); irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask; irq->handler = handle_bad_irq; irq->default_type = IRQ_TYPE_NONE; @@ -524,6 +550,8 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->base)) return PTR_ERR(gpio->base); + gpio->dev = &pdev->dev; + pdata = device_get_match_data(&pdev->dev); if (!pdata) return -EINVAL; -- cgit From b11ce7e48121a02ceedec9f4dfcab4f2bee8f35f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:54 +0100 Subject: gpio: ath79: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-ath79.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 3958c6d97639..aa0a954b8392 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -71,6 +71,7 @@ static void ath79_gpio_irq_unmask(struct irq_data *data) u32 mask = BIT(irqd_to_hwirq(data)); unsigned long flags; + gpiochip_enable_irq(&ctrl->gc, irqd_to_hwirq(data)); raw_spin_lock_irqsave(&ctrl->lock, flags); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask); raw_spin_unlock_irqrestore(&ctrl->lock, flags); @@ -85,6 +86,7 @@ static void ath79_gpio_irq_mask(struct irq_data *data) raw_spin_lock_irqsave(&ctrl->lock, flags); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0); raw_spin_unlock_irqrestore(&ctrl->lock, flags); + gpiochip_disable_irq(&ctrl->gc, irqd_to_hwirq(data)); } static void ath79_gpio_irq_enable(struct irq_data *data) @@ -169,13 +171,15 @@ static int ath79_gpio_irq_set_type(struct irq_data *data, return 0; } -static struct irq_chip ath79_gpio_irqchip = { +static const struct irq_chip ath79_gpio_irqchip = { .name = "gpio-ath79", .irq_enable = ath79_gpio_irq_enable, .irq_disable = ath79_gpio_irq_disable, .irq_mask = ath79_gpio_irq_mask, .irq_unmask = ath79_gpio_irq_unmask, .irq_set_type = ath79_gpio_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void ath79_gpio_irq_handler(struct irq_desc *desc) @@ -274,7 +278,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) /* Optional interrupt setup */ if (!np || of_property_read_bool(np, "interrupt-controller")) { girq = &ctrl->gc.irq; - girq->chip = &ath79_gpio_irqchip; + gpio_irq_chip_set_chip(girq, &ath79_gpio_irqchip); girq->parent_handler = ath79_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), -- cgit From 150a988035bb9d124716020b1b9a4e90d8eb23bb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:55 +0100 Subject: gpio: cadence: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-cadence.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c index 137aea49ba02..3720b90cad10 100644 --- a/drivers/gpio/gpio-cadence.c +++ b/drivers/gpio/gpio-cadence.c @@ -70,6 +70,7 @@ static void cdns_gpio_irq_mask(struct irq_data *d) struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip); iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_DIS); + gpiochip_disable_irq(chip, irqd_to_hwirq(d)); } static void cdns_gpio_irq_unmask(struct irq_data *d) @@ -77,6 +78,7 @@ static void cdns_gpio_irq_unmask(struct irq_data *d) struct gpio_chip *chip = irq_data_get_irq_chip_data(d); struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip); + gpiochip_enable_irq(chip, irqd_to_hwirq(d)); iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_EN); } @@ -138,11 +140,13 @@ static void cdns_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } -static struct irq_chip cdns_gpio_irqchip = { +static const struct irq_chip cdns_gpio_irqchip = { .name = "cdns-gpio", .irq_mask = cdns_gpio_irq_mask, .irq_unmask = cdns_gpio_irq_unmask, - .irq_set_type = cdns_gpio_irq_set_type + .irq_set_type = cdns_gpio_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int cdns_gpio_probe(struct platform_device *pdev) @@ -222,7 +226,7 @@ static int cdns_gpio_probe(struct platform_device *pdev) struct gpio_irq_chip *girq; girq = &cgpio->gc.irq; - girq->chip = &cdns_gpio_irqchip; + gpio_irq_chip_set_chip(girq, &cdns_gpio_irqchip); girq->parent_handler = cdns_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, -- cgit From 39bdd6bdada985ff267124f3814093d6339d796c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:56 +0100 Subject: gpio: hisi: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. The IRQ chip was unnamed which seems unwise, so we just assign the name "HISI-GPIO". Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-hisi.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-hisi.c b/drivers/gpio/gpio-hisi.c index 55bd69043bf4..29a03de37fd8 100644 --- a/drivers/gpio/gpio-hisi.c +++ b/drivers/gpio/gpio-hisi.c @@ -37,7 +37,6 @@ struct hisi_gpio { struct device *dev; void __iomem *reg_base; unsigned int line_num; - struct irq_chip irq_chip; int irq; }; @@ -100,12 +99,14 @@ static void hisi_gpio_irq_set_mask(struct irq_data *d) struct gpio_chip *chip = irq_data_get_irq_chip_data(d); hisi_gpio_write_reg(chip, HISI_GPIO_INTMASK_SET_WX, BIT(irqd_to_hwirq(d))); + gpiochip_disable_irq(chip, irqd_to_hwirq(d)); } static void hisi_gpio_irq_clr_mask(struct irq_data *d) { struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + gpiochip_enable_irq(chip, irqd_to_hwirq(d)); hisi_gpio_write_reg(chip, HISI_GPIO_INTMASK_CLR_WX, BIT(irqd_to_hwirq(d))); } @@ -191,20 +192,24 @@ static void hisi_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(irq_c, desc); } +static const struct irq_chip hisi_gpio_irq_chip = { + .name = "HISI-GPIO", + .irq_ack = hisi_gpio_set_ack, + .irq_mask = hisi_gpio_irq_set_mask, + .irq_unmask = hisi_gpio_irq_clr_mask, + .irq_set_type = hisi_gpio_irq_set_type, + .irq_enable = hisi_gpio_irq_enable, + .irq_disable = hisi_gpio_irq_disable, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static void hisi_gpio_init_irq(struct hisi_gpio *hisi_gpio) { struct gpio_chip *chip = &hisi_gpio->chip; struct gpio_irq_chip *girq_chip = &chip->irq; - /* Set hooks for irq_chip */ - hisi_gpio->irq_chip.irq_ack = hisi_gpio_set_ack; - hisi_gpio->irq_chip.irq_mask = hisi_gpio_irq_set_mask; - hisi_gpio->irq_chip.irq_unmask = hisi_gpio_irq_clr_mask; - hisi_gpio->irq_chip.irq_set_type = hisi_gpio_irq_set_type; - hisi_gpio->irq_chip.irq_enable = hisi_gpio_irq_enable; - hisi_gpio->irq_chip.irq_disable = hisi_gpio_irq_disable; - - girq_chip->chip = &hisi_gpio->irq_chip; + gpio_irq_chip_set_chip(girq_chip, &hisi_gpio_irq_chip); girq_chip->default_type = IRQ_TYPE_NONE; girq_chip->num_parents = 1; girq_chip->parents = &hisi_gpio->irq; -- cgit From ab42f021bc015db742e73ac7c39307b72ed9558d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:57 +0100 Subject: gpio: hlwd: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-hlwd.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c index 4e13e937f832..c208ac1c54a6 100644 --- a/drivers/gpio/gpio-hlwd.c +++ b/drivers/gpio/gpio-hlwd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include /* @@ -48,7 +49,7 @@ struct hlwd_gpio { struct gpio_chip gpioc; - struct irq_chip irqc; + struct device *dev; void __iomem *regs; int irq; u32 edge_emulation; @@ -123,6 +124,7 @@ static void hlwd_gpio_irq_mask(struct irq_data *data) mask &= ~BIT(data->hwirq); iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK); raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags); + gpiochip_disable_irq(&hlwd->gpioc, irqd_to_hwirq(data)); } static void hlwd_gpio_irq_unmask(struct irq_data *data) @@ -132,6 +134,7 @@ static void hlwd_gpio_irq_unmask(struct irq_data *data) unsigned long flags; u32 mask; + gpiochip_enable_irq(&hlwd->gpioc, irqd_to_hwirq(data)); raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags); mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK); mask |= BIT(data->hwirq); @@ -202,6 +205,24 @@ static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) return 0; } +static void hlwd_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p) +{ + struct hlwd_gpio *hlwd = + gpiochip_get_data(irq_data_get_irq_chip_data(data)); + + seq_printf(p, dev_name(hlwd->dev)); +} + +static const struct irq_chip hlwd_gpio_irq_chip = { + .irq_mask = hlwd_gpio_irq_mask, + .irq_unmask = hlwd_gpio_irq_unmask, + .irq_enable = hlwd_gpio_irq_enable, + .irq_set_type = hlwd_gpio_irq_set_type, + .irq_print_chip = hlwd_gpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int hlwd_gpio_probe(struct platform_device *pdev) { struct hlwd_gpio *hlwd; @@ -216,6 +237,8 @@ static int hlwd_gpio_probe(struct platform_device *pdev) if (IS_ERR(hlwd->regs)) return PTR_ERR(hlwd->regs); + hlwd->dev = &pdev->dev; + /* * Claim all GPIOs using the OWNER register. This will not work on * systems where the AHBPROT memory firewall hasn't been configured to @@ -259,14 +282,8 @@ static int hlwd_gpio_probe(struct platform_device *pdev) return hlwd->irq; } - hlwd->irqc.name = dev_name(&pdev->dev); - hlwd->irqc.irq_mask = hlwd_gpio_irq_mask; - hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask; - hlwd->irqc.irq_enable = hlwd_gpio_irq_enable; - hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type; - girq = &hlwd->gpioc.irq; - girq->chip = &hlwd->irqc; + gpio_irq_chip_set_chip(girq, &hlwd_gpio_irq_chip); girq->parent_handler = hlwd_gpio_irqhandler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, -- cgit From 9cd9e23ae3ac8a3fc1e9707da192afdb26388e82 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:58 +0100 Subject: gpio: idt3243x: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Tested-by: Thomas Bogendoerfer Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-idt3243x.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c index 1cafdf46f875..00f547d26254 100644 --- a/drivers/gpio/gpio-idt3243x.c +++ b/drivers/gpio/gpio-idt3243x.c @@ -92,6 +92,8 @@ static void idt_gpio_mask(struct irq_data *d) writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void idt_gpio_unmask(struct irq_data *d) @@ -100,6 +102,7 @@ static void idt_gpio_unmask(struct irq_data *d) struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); unsigned long flags; + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); raw_spin_lock_irqsave(&gc->bgpio_lock, flags); ctrl->mask_cache &= ~BIT(d->hwirq); @@ -119,12 +122,14 @@ static int idt_gpio_irq_init_hw(struct gpio_chip *gc) return 0; } -static struct irq_chip idt_gpio_irqchip = { +static const struct irq_chip idt_gpio_irqchip = { .name = "IDTGPIO", .irq_mask = idt_gpio_mask, .irq_ack = idt_gpio_ack, .irq_unmask = idt_gpio_unmask, - .irq_set_type = idt_gpio_irq_set_type + .irq_set_type = idt_gpio_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int idt_gpio_probe(struct platform_device *pdev) @@ -168,7 +173,7 @@ static int idt_gpio_probe(struct platform_device *pdev) return parent_irq; girq = &ctrl->gc.irq; - girq->chip = &idt_gpio_irqchip; + gpio_irq_chip_set_chip(girq, &idt_gpio_irqchip); girq->init_hw = idt_gpio_irq_init_hw; girq->parent_handler = idt_gpio_dispatch; girq->num_parents = 1; -- cgit From db45f0e1052404925a8c160f316f208da2edcbec Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:45:59 +0100 Subject: gpio: msc313: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. This conversion follows the pattern of the gpio-ixp4xx hierarchical GPIO interrupt driver. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Romain Perier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-msc313.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-msc313.c b/drivers/gpio/gpio-msc313.c index b0773e5652fa..036ad2324892 100644 --- a/drivers/gpio/gpio-msc313.c +++ b/drivers/gpio/gpio-msc313.c @@ -532,17 +532,35 @@ static int msc313_gpio_direction_output(struct gpio_chip *chip, unsigned int off return 0; } +static void msc313_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + irq_chip_mask_parent(d); + gpiochip_disable_irq(gc, d->hwirq); +} + +static void msc313_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + gpiochip_enable_irq(gc, d->hwirq); + irq_chip_unmask_parent(d); +} + /* * The interrupt handling happens in the parent interrupt controller, * we don't do anything here. */ -static struct irq_chip msc313_gpio_irqchip = { +static const struct irq_chip msc313_gpio_irqchip = { .name = "GPIO", .irq_eoi = irq_chip_eoi_parent, - .irq_mask = irq_chip_mask_parent, - .irq_unmask = irq_chip_unmask_parent, + .irq_mask = msc313_gpio_irq_mask, + .irq_unmask = msc313_gpio_irq_unmask, .irq_set_type = irq_chip_set_type_parent, .irq_set_affinity = irq_chip_set_affinity_parent, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; /* @@ -644,7 +662,7 @@ static int msc313_gpio_probe(struct platform_device *pdev) gpiochip->names = gpio->gpio_data->names; gpioirqchip = &gpiochip->irq; - gpioirqchip->chip = &msc313_gpio_irqchip; + gpio_irq_chip_set_chip(gpioirqchip, &msc313_gpio_irqchip); gpioirqchip->fwnode = of_node_to_fwnode(dev->of_node); gpioirqchip->parent_domain = parent_domain; gpioirqchip->child_to_parent_hwirq = msc313e_gpio_child_to_parent_hwirq; -- cgit From 5bfff76d27fcd84bfdd579b4bf690c1bb77b87f8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:46:00 +0100 Subject: gpio: mlxbf2: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mlxbf2.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c index 77a41151c921..6abe01bc39c3 100644 --- a/drivers/gpio/gpio-mlxbf2.c +++ b/drivers/gpio/gpio-mlxbf2.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -65,10 +66,10 @@ struct mlxbf2_gpio_context_save_regs { /* BlueField-2 gpio block context structure. */ struct mlxbf2_gpio_context { struct gpio_chip gc; - struct irq_chip irq_chip; /* YU GPIO blocks address */ void __iomem *gpio_io; + struct device *dev; struct mlxbf2_gpio_context_save_regs *csave_regs; }; @@ -237,6 +238,7 @@ static void mlxbf2_gpio_irq_enable(struct irq_data *irqd) unsigned long flags; u32 val; + gpiochip_enable_irq(gc, irqd_to_hwirq(irqd)); raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); val |= BIT(offset); @@ -261,6 +263,7 @@ static void mlxbf2_gpio_irq_disable(struct irq_data *irqd) val &= ~BIT(offset); writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + gpiochip_disable_irq(gc, irqd_to_hwirq(irqd)); } static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr) @@ -322,6 +325,24 @@ mlxbf2_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) return 0; } +static void mlxbf2_gpio_irq_print_chip(struct irq_data *irqd, + struct seq_file *p) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); + + seq_printf(p, dev_name(gs->dev)); +} + +static const struct irq_chip mlxbf2_gpio_irq_chip = { + .irq_set_type = mlxbf2_gpio_irq_set_type, + .irq_enable = mlxbf2_gpio_irq_enable, + .irq_disable = mlxbf2_gpio_irq_disable, + .irq_print_chip = mlxbf2_gpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + /* BlueField-2 GPIO driver initialization routine. */ static int mlxbf2_gpio_probe(struct platform_device *pdev) @@ -340,6 +361,8 @@ mlxbf2_gpio_probe(struct platform_device *pdev) if (!gs) return -ENOMEM; + gs->dev = dev; + /* YU GPIO block address */ gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gs->gpio_io)) @@ -376,13 +399,8 @@ mlxbf2_gpio_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq >= 0) { - gs->irq_chip.name = name; - gs->irq_chip.irq_set_type = mlxbf2_gpio_irq_set_type; - gs->irq_chip.irq_enable = mlxbf2_gpio_irq_enable; - gs->irq_chip.irq_disable = mlxbf2_gpio_irq_disable; - girq = &gs->gc.irq; - girq->chip = &gs->irq_chip; + gpio_irq_chip_set_chip(girq, &mlxbf2_gpio_irq_chip); girq->handler = handle_simple_irq; girq->default_type = IRQ_TYPE_NONE; /* This will let us handle the parent IRQ in the driver */ -- cgit From 706cdfc517fe7ce65d953acde02d316de06820e5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:46:01 +0100 Subject: gpio: max732x: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-max732x.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 68e982cdee73..7f2fde191755 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -351,6 +351,7 @@ static void max732x_irq_mask(struct irq_data *d) struct max732x_chip *chip = gpiochip_get_data(gc); chip->irq_mask_cur &= ~(1 << d->hwirq); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void max732x_irq_unmask(struct irq_data *d) @@ -358,6 +359,7 @@ static void max732x_irq_unmask(struct irq_data *d) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct max732x_chip *chip = gpiochip_get_data(gc); + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); chip->irq_mask_cur |= 1 << d->hwirq; } @@ -429,7 +431,7 @@ static int max732x_irq_set_wake(struct irq_data *data, unsigned int on) return 0; } -static struct irq_chip max732x_irq_chip = { +static const struct irq_chip max732x_irq_chip = { .name = "max732x", .irq_mask = max732x_irq_mask, .irq_unmask = max732x_irq_unmask, @@ -437,6 +439,8 @@ static struct irq_chip max732x_irq_chip = { .irq_bus_sync_unlock = max732x_irq_bus_sync_unlock, .irq_set_type = max732x_irq_set_type, .irq_set_wake = max732x_irq_set_wake, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static uint8_t max732x_irq_pending(struct max732x_chip *chip) @@ -517,7 +521,7 @@ static int max732x_irq_setup(struct max732x_chip *chip, } girq = &chip->gpio_chip.irq; - girq->chip = &max732x_irq_chip; + gpio_irq_chip_set_chip(girq, &max732x_irq_chip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From 1e77c092d3bb65af9b089916a9f09e234d0ccb75 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:46:02 +0100 Subject: gpio: omap: Drop irq_base The OMAP1 at one point was using static irqs but that time is gone, OMAP1 uses sparse irqs like all other multiplatform targets so this static allocation of descriptors should just go. Cc: Janusz Krzysztofik Cc: Tony Lindgren Acked-by: Arnd Bergmann Acked-by: Marc Zyngier Reviewed-by: Tony Lindgren Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-omap.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f5f3d4b22452..1cbd040cf796 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -992,7 +992,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc, struct gpio_irq_chip *irq; static int gpio; const char *label; - int irq_base = 0; int ret; /* @@ -1024,19 +1023,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc, } bank->chip.ngpio = bank->width; -#ifdef CONFIG_ARCH_OMAP1 - /* - * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop - * irq_alloc_descs() since a base IRQ offset will no longer be needed. - */ - irq_base = devm_irq_alloc_descs(bank->chip.parent, - -1, 0, bank->width, 0); - if (irq_base < 0) { - dev_err(bank->chip.parent, "Couldn't allocate IRQ numbers\n"); - return -ENODEV; - } -#endif - /* MPUIO is a bit different, reading IRQ status clears it */ if (bank->is_mpuio && !bank->regs->wkup_en) irqc->irq_set_wake = NULL; @@ -1047,7 +1033,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc, irq->default_type = IRQ_TYPE_NONE; irq->num_parents = 1; irq->parents = &bank->irq; - irq->first = irq_base; ret = gpiochip_add_data(&bank->chip, bank); if (ret) -- cgit From 39575d114fbb377d752d8df25d4795bc29d98042 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:46:03 +0100 Subject: gpio: omap: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. This driver require some special care: .irq_ack() was copied from dummy_irq_chip where it was defined as noop. This only makes sense if using handle_edge_irq() that will unconditionally call .irq_ack() to avoid a crash, but this driver is not ever using handle_edge_irq() so just avoid assigning .irq_ack(). A separate chip had to be created for the non-wakeup instance. Cc: Marc Zyngier Reviewed-by: Tony Lindgren Tested-by: Tony Lindgren Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-omap.c | 68 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 1cbd040cf796..a08be5bf6808 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct gpio_regs { struct gpio_bank { void __iomem *base; const struct omap_gpio_reg_offs *regs; + struct device *dev; int irq; u32 non_wakeup_gpios; @@ -681,6 +683,7 @@ static void omap_gpio_mask_irq(struct irq_data *d) omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); omap_set_gpio_irqenable(bank, offset, 0); raw_spin_unlock_irqrestore(&bank->lock, flags); + gpiochip_disable_irq(&bank->chip, offset); } static void omap_gpio_unmask_irq(struct irq_data *d) @@ -690,6 +693,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d) u32 trigger = irqd_get_trigger_type(d); unsigned long flags; + gpiochip_enable_irq(&bank->chip, offset); raw_spin_lock_irqsave(&bank->lock, flags); omap_set_gpio_irqenable(bank, offset, 1); @@ -708,6 +712,40 @@ static void omap_gpio_unmask_irq(struct irq_data *d) raw_spin_unlock_irqrestore(&bank->lock, flags); } +static void omap_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(d); + + seq_printf(p, dev_name(bank->dev)); +} + +static const struct irq_chip omap_gpio_irq_chip = { + .irq_startup = omap_gpio_irq_startup, + .irq_shutdown = omap_gpio_irq_shutdown, + .irq_mask = omap_gpio_mask_irq, + .irq_unmask = omap_gpio_unmask_irq, + .irq_set_type = omap_gpio_irq_type, + .irq_set_wake = omap_gpio_wake_enable, + .irq_bus_lock = omap_gpio_irq_bus_lock, + .irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, + .irq_print_chip = omap_gpio_irq_print_chip, + .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static const struct irq_chip omap_gpio_irq_chip_nowake = { + .irq_startup = omap_gpio_irq_startup, + .irq_shutdown = omap_gpio_irq_shutdown, + .irq_mask = omap_gpio_mask_irq, + .irq_unmask = omap_gpio_unmask_irq, + .irq_set_type = omap_gpio_irq_type, + .irq_bus_lock = omap_gpio_irq_bus_lock, + .irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, + .irq_print_chip = omap_gpio_irq_print_chip, + .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + /*---------------------------------------------------------------------*/ static int omap_mpuio_suspend_noirq(struct device *dev) @@ -986,8 +1024,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) writel_relaxed(0, base + bank->regs->ctrl); } -static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc, - struct device *pm_dev) +static int omap_gpio_chip_init(struct gpio_bank *bank, struct device *pm_dev) { struct gpio_irq_chip *irq; static int gpio; @@ -1023,12 +1060,12 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc, } bank->chip.ngpio = bank->width; + irq = &bank->chip.irq; /* MPUIO is a bit different, reading IRQ status clears it */ if (bank->is_mpuio && !bank->regs->wkup_en) - irqc->irq_set_wake = NULL; - - irq = &bank->chip.irq; - irq->chip = irqc; + gpio_irq_chip_set_chip(irq, &omap_gpio_irq_chip_nowake); + else + gpio_irq_chip_set_chip(irq, &omap_gpio_irq_chip); irq->handler = handle_bad_irq; irq->default_type = IRQ_TYPE_NONE; irq->num_parents = 1; @@ -1361,7 +1398,6 @@ static int omap_gpio_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; const struct omap_gpio_platform_data *pdata; struct gpio_bank *bank; - struct irq_chip *irqc; int ret; pdata = device_get_match_data(dev); @@ -1374,21 +1410,7 @@ static int omap_gpio_probe(struct platform_device *pdev) if (!bank) return -ENOMEM; - irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); - if (!irqc) - return -ENOMEM; - - irqc->irq_startup = omap_gpio_irq_startup, - irqc->irq_shutdown = omap_gpio_irq_shutdown, - irqc->irq_ack = dummy_irq_chip.irq_ack, - irqc->irq_mask = omap_gpio_mask_irq, - irqc->irq_unmask = omap_gpio_unmask_irq, - irqc->irq_set_type = omap_gpio_irq_type, - irqc->irq_set_wake = omap_gpio_wake_enable, - irqc->irq_bus_lock = omap_gpio_irq_bus_lock, - irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, - irqc->name = dev_name(&pdev->dev); - irqc->flags = IRQCHIP_MASK_ON_SUSPEND; + bank->dev = dev; bank->irq = platform_get_irq(pdev, 0); if (bank->irq <= 0) { @@ -1452,7 +1474,7 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_gpio_mod_init(bank); - ret = omap_gpio_chip_init(bank, irqc, dev); + ret = omap_gpio_chip_init(bank, dev); if (ret) { pm_runtime_put_sync(dev); pm_runtime_disable(dev); -- cgit From 141d5527568e923406392810049ed8be23d9e3cc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:46:04 +0100 Subject: gpio: pci-idio-16: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: William Breathitt Gray Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pci-idio-16.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c index a86ce748384b..6726c32e31e6 100644 --- a/drivers/gpio/gpio-pci-idio-16.c +++ b/drivers/gpio/gpio-pci-idio-16.c @@ -107,6 +107,8 @@ static void idio_16_irq_mask(struct irq_data *data) raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } + + gpiochip_disable_irq(chip, irqd_to_hwirq(data)); } static void idio_16_irq_unmask(struct irq_data *data) @@ -117,6 +119,8 @@ static void idio_16_irq_unmask(struct irq_data *data) const unsigned long prev_irq_mask = idio16gpio->irq_mask; unsigned long flags; + gpiochip_enable_irq(chip, irqd_to_hwirq(data)); + idio16gpio->irq_mask |= mask; if (!prev_irq_mask) { @@ -138,12 +142,14 @@ static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) return 0; } -static struct irq_chip idio_16_irqchip = { +static const struct irq_chip idio_16_irqchip = { .name = "pci-idio-16", .irq_ack = idio_16_irq_ack, .irq_mask = idio_16_irq_mask, .irq_unmask = idio_16_irq_unmask, - .irq_set_type = idio_16_irq_set_type + .irq_set_type = idio_16_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) @@ -242,7 +248,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) idio_16_state_init(&idio16gpio->state); girq = &idio16gpio->chip.irq; - girq->chip = &idio_16_irqchip; + gpio_irq_chip_set_chip(girq, &idio_16_irqchip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From 33886f925752d0f7b0791fcf008db223f0be6278 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Mar 2023 08:46:05 +0100 Subject: gpio: pcie-idio-24: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Acked-by: William Breathitt Gray Acked-by: Marc Zyngier Signed-off-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pcie-idio-24.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c index 8a9b98fa418f..ac42150f4009 100644 --- a/drivers/gpio/gpio-pcie-idio-24.c +++ b/drivers/gpio/gpio-pcie-idio-24.c @@ -396,6 +396,8 @@ static void idio_24_irq_mask(struct irq_data *data) } raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); + + gpiochip_disable_irq(chip, irqd_to_hwirq(data)); } static void idio_24_irq_unmask(struct irq_data *data) @@ -408,6 +410,8 @@ static void idio_24_irq_unmask(struct irq_data *data) const unsigned long bank_offset = bit_offset / 8; unsigned char cos_enable_state; + gpiochip_enable_irq(chip, irqd_to_hwirq(data)); + raw_spin_lock_irqsave(&idio24gpio->lock, flags); prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; @@ -437,12 +441,14 @@ static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type) return 0; } -static struct irq_chip idio_24_irqchip = { +static const struct irq_chip idio_24_irqchip = { .name = "pcie-idio-24", .irq_ack = idio_24_irq_ack, .irq_mask = idio_24_irq_mask, .irq_unmask = idio_24_irq_unmask, - .irq_set_type = idio_24_irq_set_type + .irq_set_type = idio_24_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static irqreturn_t idio_24_irq_handler(int irq, void *dev_id) @@ -535,7 +541,7 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple; girq = &idio24gpio->chip.irq; - girq->chip = &idio_24_irqchip; + gpio_irq_chip_set_chip(girq, &idio_24_irqchip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From 8a36cdc8ef2facc06d8bb973229131846770109b Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Thu, 9 Mar 2023 11:17:55 +0800 Subject: gpio: loongson: Remove unnecessary .owner Remove .owner field if calls are used which set it automatically. ./drivers/gpio/gpio-loongson-64bit.c:225:3-8: No need to set .owner here. The core will do it. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4450 Signed-off-by: Jiapeng Chong Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-loongson-64bit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-loongson-64bit.c b/drivers/gpio/gpio-loongson-64bit.c index 20a68e5e66c1..06213bbfabdd 100644 --- a/drivers/gpio/gpio-loongson-64bit.c +++ b/drivers/gpio/gpio-loongson-64bit.c @@ -222,7 +222,6 @@ MODULE_DEVICE_TABLE(acpi, loongson_gpio_acpi_match); static struct platform_driver loongson_gpio_driver = { .driver = { .name = "loongson-gpio", - .owner = THIS_MODULE, .of_match_table = loongson_gpio_of_match, .acpi_match_table = loongson_gpio_acpi_match, }, -- cgit From 0c14f3aa388d3becd38923869e17f9947a5e5926 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 9 Mar 2023 20:46:35 +0200 Subject: gpio: sim: Deactivate device in reversed order Run the steps to deactivate device in the reserved order to what it has been done in gpio_sim_device_activate_unlocked(). Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-sim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c index e5dfd636c63c..a1c8702f362c 100644 --- a/drivers/gpio/gpio-sim.c +++ b/drivers/gpio/gpio-sim.c @@ -953,9 +953,9 @@ static void gpio_sim_device_deactivate_unlocked(struct gpio_sim_device *dev) swnode = dev_fwnode(&dev->pdev->dev); platform_device_unregister(dev->pdev); + gpio_sim_remove_hogs(dev); gpio_sim_remove_swnode_recursive(swnode); dev->pdev = NULL; - gpio_sim_remove_hogs(dev); } static ssize_t -- cgit From 0db9d2bbd9bf5f03781a1bb3aabb71d71697d3c8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:25:13 +0100 Subject: MAINTAINERS: gpio: xra1403: drop Semi Malinen Emails bounce: 550 5.1.1 No such user - pp Signed-off-by: Krzysztof Kozlowski Signed-off-by: Bartosz Golaszewski --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 75e698bf6e1a..3e512acbb106 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23043,7 +23043,6 @@ F: drivers/i2c/busses/i2c-xlp9xx.c XRA1403 GPIO EXPANDER M: Nandor Han -M: Semi Malinen L: linux-gpio@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/gpio/gpio-xra1403.txt -- cgit From 886b33346d50a625cb882782eee7199f3040c90e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:00 +0100 Subject: gpio: ftgpio010: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/gpio/gpio-ftgpio010.c:336:34: error: ‘ftgpio_gpio_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-ftgpio010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 2728672ef9f8..31e26072f6ae 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -349,7 +349,7 @@ static const struct of_device_id ftgpio_gpio_of_match[] = { static struct platform_driver ftgpio_gpio_driver = { .driver = { .name = "ftgpio010-gpio", - .of_match_table = of_match_ptr(ftgpio_gpio_of_match), + .of_match_table = ftgpio_gpio_of_match, }, .probe = ftgpio_gpio_probe, .remove = ftgpio_gpio_remove, -- cgit From 13577824bded9fefbf627adef21d4cc3cbae799a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:01 +0100 Subject: gpio: altera: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/gpio/gpio-altera.c:324:34: error: ‘altera_gpio_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-altera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 338884043bbb..54d7c450c596 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -335,7 +335,7 @@ MODULE_DEVICE_TABLE(of, altera_gpio_of_match); static struct platform_driver altera_gpio_driver = { .driver = { .name = "altera_gpio", - .of_match_table = of_match_ptr(altera_gpio_of_match), + .of_match_table = altera_gpio_of_match, }, .probe = altera_gpio_probe, .remove = altera_gpio_remove, -- cgit From 072de5a412cc0601c4802e0ed62cbc5ed781d68c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:02 +0100 Subject: gpio: rcar: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/gpio/gpio-rcar.c:435:34: error: ‘gpio_rcar_of_table’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-rcar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 5b117f3bd322..2525adb52f4f 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -663,7 +663,7 @@ static struct platform_driver gpio_rcar_device_driver = { .driver = { .name = "gpio_rcar", .pm = &gpio_rcar_pm_ops, - .of_match_table = of_match_ptr(gpio_rcar_of_table), + .of_match_table = gpio_rcar_of_table, } }; -- cgit From b39cf819f625eeccfc013bc0ceea5075e0a4bd22 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:03 +0100 Subject: gpio: visconti: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/gpio/gpio-visconti.c:187:34: error: ‘visconti_gpio_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-visconti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c index 5e108ba9956a..10d9de41f29b 100644 --- a/drivers/gpio/gpio-visconti.c +++ b/drivers/gpio/gpio-visconti.c @@ -194,7 +194,7 @@ static struct platform_driver visconti_gpio_driver = { .probe = visconti_gpio_probe, .driver = { .name = "visconti_gpio", - .of_match_table = of_match_ptr(visconti_gpio_of_match), + .of_match_table = visconti_gpio_of_match, } }; module_platform_driver(visconti_gpio_driver); -- cgit From 6ae42529547a4f3296fcecbfa3d2cf21c7196773 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:04 +0100 Subject: gpio: sifive: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/gpio/gpio-sifive.c:263:34: error: ‘sifive_gpio_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-sifive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c index bc5660f61c57..98939cd4a71e 100644 --- a/drivers/gpio/gpio-sifive.c +++ b/drivers/gpio/gpio-sifive.c @@ -270,7 +270,7 @@ static struct platform_driver sifive_gpio_driver = { .probe = sifive_gpio_probe, .driver = { .name = "sifive_gpio", - .of_match_table = of_match_ptr(sifive_gpio_match), + .of_match_table = sifive_gpio_match, }, }; builtin_platform_driver(sifive_gpio_driver) -- cgit From 87cb1f51db8619c2e8af250ff2642514c326302b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:05 +0100 Subject: gpio: sama5d2-piobu: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/gpio/gpio-sama5d2-piobu.c:230:34: error: ‘sama5d2_piobu_ids’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-sama5d2-piobu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-sama5d2-piobu.c b/drivers/gpio/gpio-sama5d2-piobu.c index 3e95da717fc9..767c33ae3213 100644 --- a/drivers/gpio/gpio-sama5d2-piobu.c +++ b/drivers/gpio/gpio-sama5d2-piobu.c @@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(of, sama5d2_piobu_ids); static struct platform_driver sama5d2_piobu_driver = { .driver = { .name = "sama5d2-piobu", - .of_match_table = of_match_ptr(sama5d2_piobu_ids) + .of_match_table = sama5d2_piobu_ids, }, .probe = sama5d2_piobu_probe, }; -- cgit From c5521bda998ae434d67daae9310692b21c2b941a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:06 +0100 Subject: gpio: xra1403: mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: drivers/gpio/gpio-xra1403.c:198:34: error: ‘xra1403_spi_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xra1403.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c index 49c878cfd5c6..51d6119e1bb4 100644 --- a/drivers/gpio/gpio-xra1403.c +++ b/drivers/gpio/gpio-xra1403.c @@ -195,7 +195,7 @@ static const struct spi_device_id xra1403_ids[] = { }; MODULE_DEVICE_TABLE(spi, xra1403_ids); -static const struct of_device_id xra1403_spi_of_match[] = { +static const struct of_device_id xra1403_spi_of_match[] __maybe_unused = { { .compatible = "exar,xra1403" }, {}, }; -- cgit From cf67efd1ae74a7448084b8f167f7feaf99513957 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:13:07 +0100 Subject: gpio: raspberrypi-exp: mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: drivers/gpio/gpio-raspberrypi-exp.c:237:34: error: ‘rpi_exp_gpio_ids’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-raspberrypi-exp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c index 3c414e0005fc..ecb0d3800dfe 100644 --- a/drivers/gpio/gpio-raspberrypi-exp.c +++ b/drivers/gpio/gpio-raspberrypi-exp.c @@ -234,7 +234,7 @@ static int rpi_exp_gpio_probe(struct platform_device *pdev) return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio); } -static const struct of_device_id rpi_exp_gpio_ids[] = { +static const struct of_device_id rpi_exp_gpio_ids[] __maybe_unused = { { .compatible = "raspberrypi,firmware-gpio" }, { } }; -- cgit From 0c5ebb4c03308c0a544b5c1e0a33f0a63c40bc7e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 9 Mar 2023 20:56:00 +0200 Subject: gpiolib: Get rid of devprop prefix in one function The devprop prefix in the devprop_gpiochip_set_names() adds confusion. Get rid of it. Note we have more than one function in the same module that handles one or more device properties. This change will unify the naming schema for all of them. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7c75e0e5fe22..8b68a53704bc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -373,7 +373,7 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) } /* - * devprop_gpiochip_set_names - Set GPIO line names using device properties + * gpiochip_set_names - Set GPIO line names using device properties * @chip: GPIO chip whose lines should be named, if possible * * Looks for device property "gpio-line-names" and if it exists assigns @@ -381,7 +381,7 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) * names belong to the underlying firmware node and should not be released * by the caller. */ -static int devprop_gpiochip_set_names(struct gpio_chip *chip) +static int gpiochip_set_names(struct gpio_chip *chip) { struct gpio_device *gdev = chip->gpiodev; struct device *dev = &gdev->dev; @@ -833,7 +833,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, if (ret) goto err_remove_from_list; } - ret = devprop_gpiochip_set_names(gc); + ret = gpiochip_set_names(gc); if (ret) goto err_remove_from_list; -- cgit From 5b0ad5b24327d44b8307e822d160a3d48a70e87c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 14 Mar 2023 10:41:17 -0500 Subject: gpio: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-stp-xway.c | 2 +- drivers/gpio/gpio-tb10x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 0ce1543426a4..4750ea34204c 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -292,7 +292,7 @@ static int xway_stp_probe(struct platform_device *pdev) } /* check which edge trigger we should use, default to a falling edge */ - if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL)) + if (!of_property_read_bool(pdev->dev.of_node, "lantiq,rising")) chip->edge = XWAY_STP_FALLING; clk = devm_clk_get(&pdev->dev, NULL); diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index de6afa3f9716..78f8790168ae 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -167,7 +167,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, tb10x_gpio); - if (of_find_property(np, "interrupt-controller", NULL)) { + if (of_property_read_bool(np, "interrupt-controller")) { struct irq_chip_generic *gc; ret = platform_get_irq(pdev, 0); -- cgit From 7aa90f9055c16c79c0ad174c726f95723d122fe6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Mar 2023 20:25:57 +0200 Subject: gpiolib: Move gpiodevice_*() to gpiodev namespace The functions that operates on the same device object would have the same namespace for better code understanding and maintenance. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8b68a53704bc..0589451e65cb 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -572,7 +572,7 @@ bool gpiochip_line_is_valid(const struct gpio_chip *gc, } EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); -static void gpiodevice_release(struct device *dev) +static void gpiodev_release(struct device *dev) { struct gpio_device *gdev = to_gpio_device(dev); unsigned long flags; @@ -616,7 +616,7 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) return ret; /* From this point, the .release() function cleans up gpio_device */ - gdev->dev.release = gpiodevice_release; + gdev->dev.release = gpiodev_release; ret = gpiochip_sysfs_register(gdev); if (ret) -- cgit From c122f461ccac0e78e8e45d4f6de14e58942572f6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 9 Mar 2023 20:56:26 +0200 Subject: gpiolib: Remove duplicative check in gpiod_find_and_request() The gpiod_find_by_fwnode() already checks for NULL and returns correct error code in case fwnode is invalid. Drop the respective check and assignment in the gpiod_find_and_request(). Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0589451e65cb..405070484fe3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3926,13 +3926,10 @@ static struct gpio_desc *gpiod_find_and_request(struct device *consumer, bool platform_lookup_allowed) { unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT; - struct gpio_desc *desc = ERR_PTR(-ENOENT); + struct gpio_desc *desc; int ret; - if (!IS_ERR_OR_NULL(fwnode)) - desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, - &flags, &lookupflags); - + desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, &flags, &lookupflags); if (gpiod_not_found(desc) && platform_lookup_allowed) { /* * Either we are not using DT or ACPI, or their lookup did not -- cgit From db4064cc108214bf0912b89c7e660c7d9d6bba1d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 9 Mar 2023 20:58:19 +0200 Subject: gpiolib: Use IRQ hardware number getter instead of direct access IRQ framework provides special type and getter to transform the Linux IRQ to the hardware pin. Use that type and getter function instead of direct access. While at it, amend an indentation in a couple of places. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 405070484fe3..9451a627dacd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1218,7 +1218,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, if (ret) return ret; - chip_dbg(gc, "allocate IRQ %d, hwirq %lu\n", irq, hwirq); + chip_dbg(gc, "allocate IRQ %d, hwirq %lu\n", irq, hwirq); ret = girq->child_to_parent_hwirq(gc, hwirq, type, &parent_hwirq, &parent_type); @@ -1386,8 +1386,7 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) * gpiochip by assigning the gpiochip as chip data, and using the irqchip * stored inside the gpiochip. */ -int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) +int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { struct gpio_chip *gc = d->host_data; int ret = 0; @@ -1463,8 +1462,9 @@ int gpiochip_irq_domain_activate(struct irq_domain *domain, struct irq_data *data, bool reserve) { struct gpio_chip *gc = domain->host_data; + unsigned int hwirq = irqd_to_hwirq(data); - return gpiochip_lock_as_irq(gc, data->hwirq); + return gpiochip_lock_as_irq(gc, hwirq); } EXPORT_SYMBOL_GPL(gpiochip_irq_domain_activate); @@ -1481,8 +1481,9 @@ void gpiochip_irq_domain_deactivate(struct irq_domain *domain, struct irq_data *data) { struct gpio_chip *gc = domain->host_data; + unsigned int hwirq = irqd_to_hwirq(data); - return gpiochip_unlock_as_irq(gc, data->hwirq); + return gpiochip_unlock_as_irq(gc, hwirq); } EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate); @@ -1522,33 +1523,37 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset) int gpiochip_irq_reqres(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); - return gpiochip_reqres_irq(gc, d->hwirq); + return gpiochip_reqres_irq(gc, hwirq); } EXPORT_SYMBOL(gpiochip_irq_reqres); void gpiochip_irq_relres(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); - gpiochip_relres_irq(gc, d->hwirq); + gpiochip_relres_irq(gc, hwirq); } EXPORT_SYMBOL(gpiochip_irq_relres); static void gpiochip_irq_mask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); if (gc->irq.irq_mask) gc->irq.irq_mask(d); - gpiochip_disable_irq(gc, d->hwirq); + gpiochip_disable_irq(gc, hwirq); } static void gpiochip_irq_unmask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); - gpiochip_enable_irq(gc, d->hwirq); + gpiochip_enable_irq(gc, hwirq); if (gc->irq.irq_unmask) gc->irq.irq_unmask(d); } @@ -1556,17 +1561,19 @@ static void gpiochip_irq_unmask(struct irq_data *d) static void gpiochip_irq_enable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); - gpiochip_enable_irq(gc, d->hwirq); + gpiochip_enable_irq(gc, hwirq); gc->irq.irq_enable(d); } static void gpiochip_irq_disable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); gc->irq.irq_disable(d); - gpiochip_disable_irq(gc, d->hwirq); + gpiochip_disable_irq(gc, hwirq); } static void gpiochip_set_irq_hooks(struct gpio_chip *gc) -- cgit From 5b3b3e35ac6b07ee45acabecb789079baa845f90 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 30 Nov 2022 17:55:17 +0200 Subject: Documentation: gpio: Input mode is not true Hi-Z The true Hi-Z (a.k.a. high impedance) mode is when pin is completely disconnected from the chip. This includes input buffer as well. Nevertheless, some hardware may not support that mode and they are considering input only as Hi-Z, but more precisely it is an equivalent to that, in electronics it's basically "an antenna mode". Sligthly correct documentation to take the above into consideration. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- Documentation/driver-api/gpio/driver.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index 6baaeab79534..bf6319cc531b 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -218,10 +218,10 @@ not support open drain/open source in hardware, the GPIO library will instead use a trick: when a line is set as output, if the line is flagged as open drain, and the IN output value is low, it will be driven low as usual. But if the IN output value is set to high, it will instead *NOT* be driven high, -instead it will be switched to input, as input mode is high impedance, thus -achieving an "open drain emulation" of sorts: electrically the behaviour will -be identical, with the exception of possible hardware glitches when switching -the mode of the line. +instead it will be switched to input, as input mode is an equivalent to +high impedance, thus achieving an "open drain emulation" of sorts: electrically +the behaviour will be identical, with the exception of possible hardware glitches +when switching the mode of the line. For open source configuration the same principle is used, just that instead of actively driving the line low, it is set to input. -- cgit From 27a80bd09d2c5ec453a2f617f2e2cbe9a2615d97 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Thu, 9 Mar 2023 18:39:29 -0500 Subject: gpio: pcie-idio-24: Prune superfluous license boilerplate The SPDX License Identifier line renders the GPL boilerplate text superfluous, so let's remove it. Signed-off-by: William Breathitt Gray Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pcie-idio-24.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c index ac42150f4009..463c0613abb9 100644 --- a/drivers/gpio/gpio-pcie-idio-24.c +++ b/drivers/gpio/gpio-pcie-idio-24.c @@ -3,15 +3,6 @@ * GPIO driver for the ACCES PCIe-IDIO-24 family * Copyright (C) 2018 William Breathitt Gray * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * * This driver supports the following ACCES devices: PCIe-IDIO-24, * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12. */ -- cgit From d41116f7e476f5211af77454e9938a87a09a179b Mon Sep 17 00:00:00 2001 From: Emanuele Ghidoli Date: Mon, 13 Mar 2023 18:09:49 +0100 Subject: dt-bindings: gpio: add fcs,fxl6408 Add Fairchild FXL6408 8-bit I2C-controlled GPIO expander. Signed-off-by: Emanuele Ghidoli Signed-off-by: Francesco Dolcini Reviewed-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- .../devicetree/bindings/gpio/fcs,fxl6408.yaml | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/fcs,fxl6408.yaml diff --git a/Documentation/devicetree/bindings/gpio/fcs,fxl6408.yaml b/Documentation/devicetree/bindings/gpio/fcs,fxl6408.yaml new file mode 100644 index 000000000000..65b6970e42fb --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/fcs,fxl6408.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/fcs,fxl6408.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Fairchild FXL6408 I2C GPIO Expander + +maintainers: + - Emanuele Ghidoli + +properties: + compatible: + enum: + - fcs,fxl6408 + + reg: + maxItems: 1 + + "#gpio-cells": + const: 2 + + gpio-controller: true + + gpio-line-names: + minItems: 1 + maxItems: 8 + +patternProperties: + "^(hog-[0-9]+|.+-hog(-[0-9]+)?)$": + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + gpio_expander_43: gpio-expander@43 { + compatible = "fcs,fxl6408"; + reg = <0x43>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "Wi-Fi_W_DISABLE", "Wi-Fi_WKUP_WLAN", + "PWR_EN_+V3.3_WiFi_N", "PCIe_REF_CLK_EN", + "USB_RESET_N", "USB_BYPASS_N", "Wi-Fi_PDn", + "Wi-Fi_WKUP_BT"; + }; + }; -- cgit From 03810031c91dfe448cd116ee987d5dc4139006f4 Mon Sep 17 00:00:00 2001 From: Emanuele Ghidoli Date: Mon, 13 Mar 2023 18:09:50 +0100 Subject: gpio: fxl6408: add I2C GPIO expander driver Add minimal driver for Fairchild FXL6408 8-bit I2C-controlled GPIO expander using the generic regmap based GPIO driver (GPIO_REGMAP). The driver implements setting the GPIO direction, reading inputs and writing outputs. In addition to that the FXL6408 has the following functionalities: - allows to monitor input ports for data transitions with an interrupt pin - all inputs can be configured with pull-up or pull-down resistors Datasheet: https://www.onsemi.com/download/data-sheet/pdf/fxl6408-d.pdf Signed-off-by: Emanuele Ghidoli Co-developed-by: Francesco Dolcini Signed-off-by: Francesco Dolcini Reviewed-by: Andy Shevchenko [Bartosz: order includes alphabetically] Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 10 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-fxl6408.c | 158 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 drivers/gpio/gpio-fxl6408.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5ef2bfbd805b..68f58b0ba79f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1007,6 +1007,16 @@ config GPIO_ADNP enough to represent all pins, but the driver will assume a register layout for 64 pins (8 registers). +config GPIO_FXL6408 + tristate "FXL6408 I2C GPIO expander" + select GPIO_REGMAP + select REGMAP_I2C + help + GPIO driver for Fairchild Semiconductor FXL6408 GPIO expander. + + To compile this driver as a module, choose M here: the module will + be called gpio-fxl6408. + config GPIO_GW_PLD tristate "Gateworks PLD GPIO Expander" depends on OF_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 73d1ec260c14..4cdf400a9387 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o +obj-$(CONFIG_GPIO_FXL6408) += gpio-fxl6408.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c new file mode 100644 index 000000000000..208fa851e82a --- /dev/null +++ b/drivers/gpio/gpio-fxl6408.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FXL6408 GPIO driver + * + * Copyright 2023 Toradex + * + * Author: Emanuele Ghidoli + */ + +#include +#include +#include +#include +#include +#include + +#define FXL6408_REG_DEVICE_ID 0x01 +#define FXL6408_MF_FAIRCHILD 0b101 +#define FXL6408_MF_SHIFT 5 + +/* Bits set here indicate that the GPIO is an output. */ +#define FXL6408_REG_IO_DIR 0x03 + +/* + * Bits set here, when the corresponding bit of IO_DIR is set, drive + * the output high instead of low. + */ +#define FXL6408_REG_OUTPUT 0x05 + +/* Bits here make the output High-Z, instead of the OUTPUT value. */ +#define FXL6408_REG_OUTPUT_HIGH_Z 0x07 + +/* Returns the current status (1 = HIGH) of the input pins. */ +#define FXL6408_REG_INPUT_STATUS 0x0f + +/* + * Return the current interrupt status + * This bit is HIGH if input GPIO != default state (register 09h). + * The flag is cleared after being read (bit returns to 0). + * The input must go back to default state and change again before this flag is raised again. + */ +#define FXL6408_REG_INT_STS 0x13 + +#define FXL6408_NGPIO 8 + +static const struct regmap_range rd_range[] = { + { FXL6408_REG_DEVICE_ID, FXL6408_REG_DEVICE_ID }, + { FXL6408_REG_IO_DIR, FXL6408_REG_OUTPUT }, + { FXL6408_REG_INPUT_STATUS, FXL6408_REG_INPUT_STATUS }, +}; + +static const struct regmap_range wr_range[] = { + { FXL6408_REG_DEVICE_ID, FXL6408_REG_DEVICE_ID }, + { FXL6408_REG_IO_DIR, FXL6408_REG_OUTPUT }, + { FXL6408_REG_OUTPUT_HIGH_Z, FXL6408_REG_OUTPUT_HIGH_Z }, +}; + +static const struct regmap_range volatile_range[] = { + { FXL6408_REG_DEVICE_ID, FXL6408_REG_DEVICE_ID }, + { FXL6408_REG_INPUT_STATUS, FXL6408_REG_INPUT_STATUS }, +}; + +static const struct regmap_access_table rd_table = { + .yes_ranges = rd_range, + .n_yes_ranges = ARRAY_SIZE(rd_range), +}; + +static const struct regmap_access_table wr_table = { + .yes_ranges = wr_range, + .n_yes_ranges = ARRAY_SIZE(wr_range), +}; + +static const struct regmap_access_table volatile_table = { + .yes_ranges = volatile_range, + .n_yes_ranges = ARRAY_SIZE(volatile_range), +}; + +static const struct regmap_config regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = FXL6408_REG_INT_STS, + .wr_table = &wr_table, + .rd_table = &rd_table, + .volatile_table = &volatile_table, + + .cache_type = REGCACHE_RBTREE, + .num_reg_defaults_raw = FXL6408_REG_INT_STS + 1, +}; + +static int fxl6408_identify(struct device *dev, struct regmap *regmap) +{ + int val, ret; + + ret = regmap_read(regmap, FXL6408_REG_DEVICE_ID, &val); + if (ret) + return dev_err_probe(dev, ret, "error reading DEVICE_ID\n"); + if (val >> FXL6408_MF_SHIFT != FXL6408_MF_FAIRCHILD) + return dev_err_probe(dev, -ENODEV, "invalid device id 0x%02x\n", val); + + return 0; +} + +static int fxl6408_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + int ret; + struct gpio_regmap_config gpio_config = { + .parent = dev, + .ngpio = FXL6408_NGPIO, + .reg_dat_base = GPIO_REGMAP_ADDR(FXL6408_REG_INPUT_STATUS), + .reg_set_base = GPIO_REGMAP_ADDR(FXL6408_REG_OUTPUT), + .reg_dir_out_base = GPIO_REGMAP_ADDR(FXL6408_REG_IO_DIR), + .ngpio_per_reg = FXL6408_NGPIO, + }; + + gpio_config.regmap = devm_regmap_init_i2c(client, ®map); + if (IS_ERR(gpio_config.regmap)) + return dev_err_probe(dev, PTR_ERR(gpio_config.regmap), + "failed to allocate register map\n"); + + ret = fxl6408_identify(dev, gpio_config.regmap); + if (ret) + return ret; + + /* Disable High-Z of outputs, so that our OUTPUT updates actually take effect. */ + ret = regmap_write(gpio_config.regmap, FXL6408_REG_OUTPUT_HIGH_Z, 0); + if (ret) + return dev_err_probe(dev, ret, "failed to write 'output high Z' register\n"); + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); +} + +static const __maybe_unused struct of_device_id fxl6408_dt_ids[] = { + { .compatible = "fcs,fxl6408" }, + { } +}; +MODULE_DEVICE_TABLE(of, fxl6408_dt_ids); + +static const struct i2c_device_id fxl6408_id[] = { + { "fxl6408", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, fxl6408_id); + +static struct i2c_driver fxl6408_driver = { + .driver = { + .name = "fxl6408", + .of_match_table = fxl6408_dt_ids, + }, + .probe_new = fxl6408_probe, + .id_table = fxl6408_id, +}; +module_i2c_driver(fxl6408_driver); + +MODULE_AUTHOR("Emanuele Ghidoli "); +MODULE_DESCRIPTION("FXL6408 GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit From a7400a48160dc6a00ff93c40ba25d04a8e49f1f4 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 19 Mar 2023 10:36:40 -0400 Subject: gpio: pxa: remove unused gpio_is_pxa_type function clang with W=1 reports drivers/gpio/gpio-pxa.c:174:19: error: unused function 'gpio_is_pxa_type' [-Werror,-Wunused-function] static inline int gpio_is_pxa_type(int type) ^ This function is not used, so remove it. Signed-off-by: Tom Rix Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pxa.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 1198ab0305d0..a1630ed4b741 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -171,11 +171,6 @@ static inline struct pxa_gpio_bank *gpio_to_pxabank(struct gpio_chip *c, return chip_to_pxachip(c)->banks + gpio / 32; } -static inline int gpio_is_pxa_type(int type) -{ - return (type & MMP_GPIO) == 0; -} - static inline int gpio_is_mmp_type(int type) { return (type & MMP_GPIO) != 0; -- cgit From 177b70c03ea5cb1f649ac27d618307b24d660b9a Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Mon, 27 Feb 2023 11:45:23 -0500 Subject: gpio: 104-dio-48e: Utilize no_status regmap-irq flag The 104-DIO-48E lacks an IRQ status register. Rather than use the Clear Interrupt register as the status register, set the no_status flag to true and thus avoid such a hack. Reviewed-by: Andy Shevchenko Signed-off-by: William Breathitt Gray Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-104-dio-48e.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 74e2721f2613..4ec4719bf942 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -194,13 +194,9 @@ static int dio48e_probe(struct device *dev, unsigned int id) return -ENOMEM; chip->name = name; - /* No IRQ status register so use CLEAR_INTERRUPT register instead */ - chip->status_base = DIO48E_CLEAR_INTERRUPT; chip->mask_base = DIO48E_ENABLE_INTERRUPT; chip->ack_base = DIO48E_CLEAR_INTERRUPT; - /* CLEAR_INTERRUPT doubles as status register so we need it cleared */ - chip->clear_ack = true; - chip->status_invert = true; + chip->no_status = true; chip->num_regs = 1; chip->irqs = dio48e_regmap_irqs; chip->num_irqs = ARRAY_SIZE(dio48e_regmap_irqs); -- cgit From a9b4678a40491ddc60a47e1479d93f328c3427a0 Mon Sep 17 00:00:00 2001 From: Keguang Zhang Date: Wed, 15 Mar 2023 19:06:47 +0800 Subject: gpio: loongson1: Convert to SPDX identifier Use SPDX-License-Identifier instead of the license text. The current author name is unofficial, change it to my real name. Signed-off-by: Keguang Zhang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-loongson1.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c index 5d90b3bc5a25..8862c9ea0d41 100644 --- a/drivers/gpio/gpio-loongson1.c +++ b/drivers/gpio/gpio-loongson1.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * GPIO Driver for Loongson 1 SoC * - * Copyright (C) 2015-2016 Zhang, Keguang - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. + * Copyright (C) 2015-2023 Keguang Zhang */ #include @@ -90,6 +87,6 @@ static struct platform_driver ls1x_gpio_driver = { module_platform_driver(ls1x_gpio_driver); -MODULE_AUTHOR("Kelvin Cheung "); +MODULE_AUTHOR("Keguang Zhang "); MODULE_DESCRIPTION("Loongson1 GPIO driver"); MODULE_LICENSE("GPL"); -- cgit From 31b6ec6793a0b0b9b44f540430898e91de080882 Mon Sep 17 00:00:00 2001 From: Keguang Zhang Date: Wed, 15 Mar 2023 19:06:48 +0800 Subject: gpio: loongson1: Introduce ls1x_gpio_chip struct This patch introduces and allocates ls1x_gpio_chip struct containing gpio_chip and reg_base to avoid global gpio_reg_base. Signed-off-by: Keguang Zhang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-loongson1.c | 45 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c index 8862c9ea0d41..dddfc71f0e10 100644 --- a/drivers/gpio/gpio-loongson1.c +++ b/drivers/gpio/gpio-loongson1.c @@ -16,15 +16,19 @@ #define GPIO_DATA 0x20 #define GPIO_OUTPUT 0x30 -static void __iomem *gpio_reg_base; +struct ls1x_gpio_chip { + struct gpio_chip gc; + void __iomem *reg_base; +}; static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) { + struct ls1x_gpio_chip *ls1x_gc = gpiochip_get_data(gc); unsigned long flags; raw_spin_lock_irqsave(&gc->bgpio_lock, flags); - __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | BIT(offset), - gpio_reg_base + GPIO_CFG); + __raw_writel(__raw_readl(ls1x_gc->reg_base + GPIO_CFG) | BIT(offset), + ls1x_gc->reg_base + GPIO_CFG); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); return 0; @@ -32,44 +36,45 @@ static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset) { + struct ls1x_gpio_chip *ls1x_gc = gpiochip_get_data(gc); unsigned long flags; raw_spin_lock_irqsave(&gc->bgpio_lock, flags); - __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~BIT(offset), - gpio_reg_base + GPIO_CFG); + __raw_writel(__raw_readl(ls1x_gc->reg_base + GPIO_CFG) & ~BIT(offset), + ls1x_gc->reg_base + GPIO_CFG); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); } static int ls1x_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct gpio_chip *gc; + struct ls1x_gpio_chip *ls1x_gc; int ret; - gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); - if (!gc) + ls1x_gc = devm_kzalloc(dev, sizeof(*ls1x_gc), GFP_KERNEL); + if (!ls1x_gc) return -ENOMEM; - gpio_reg_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(gpio_reg_base)) - return PTR_ERR(gpio_reg_base); + ls1x_gc->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ls1x_gc->reg_base)) + return PTR_ERR(ls1x_gc->reg_base); - ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA, - gpio_reg_base + GPIO_OUTPUT, NULL, - NULL, gpio_reg_base + GPIO_DIR, 0); + ret = bgpio_init(&ls1x_gc->gc, dev, 4, ls1x_gc->reg_base + GPIO_DATA, + ls1x_gc->reg_base + GPIO_OUTPUT, NULL, + NULL, ls1x_gc->reg_base + GPIO_DIR, 0); if (ret) goto err; - gc->owner = THIS_MODULE; - gc->request = ls1x_gpio_request; - gc->free = ls1x_gpio_free; - gc->base = pdev->id * 32; + ls1x_gc->gc.owner = THIS_MODULE; + ls1x_gc->gc.request = ls1x_gpio_request; + ls1x_gc->gc.free = ls1x_gpio_free; + ls1x_gc->gc.base = pdev->id * 32; - ret = devm_gpiochip_add_data(dev, gc, NULL); + ret = devm_gpiochip_add_data(dev, &ls1x_gc->gc, ls1x_gc); if (ret) goto err; - platform_set_drvdata(pdev, gc); + platform_set_drvdata(pdev, ls1x_gc); dev_info(dev, "Loongson1 GPIO driver registered\n"); return 0; -- cgit From 722cfe4ffa6a13324e956bee81a1c0976034d89d Mon Sep 17 00:00:00 2001 From: Keguang Zhang Date: Wed, 15 Mar 2023 19:06:50 +0800 Subject: dt-bindings: gpio: Add Loongson-1 GPIO Add devicetree binding document for Loongson-1 GPIO. Signed-off-by: Keguang Zhang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bartosz Golaszewski --- .../bindings/gpio/loongson,ls1x-gpio.yaml | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/loongson,ls1x-gpio.yaml diff --git a/Documentation/devicetree/bindings/gpio/loongson,ls1x-gpio.yaml b/Documentation/devicetree/bindings/gpio/loongson,ls1x-gpio.yaml new file mode 100644 index 000000000000..1a472c05697c --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/loongson,ls1x-gpio.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/loongson,ls1x-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson-1 GPIO controller + +maintainers: + - Keguang Zhang + +properties: + compatible: + const: loongson,ls1x-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 2 + + ngpios: + minimum: 1 + maximum: 32 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - ngpios + +additionalProperties: false + +examples: + - | + gpio0: gpio@1fd010c0 { + compatible = "loongson,ls1x-gpio"; + reg = <0x1fd010c0 0x4>; + + gpio-controller; + #gpio-cells = <2>; + + ngpios = <32>; + }; + +... -- cgit From 9bc167e27cc5f3a078492b4cfcaaa2432ebb6eb0 Mon Sep 17 00:00:00 2001 From: Keguang Zhang Date: Wed, 15 Mar 2023 19:06:49 +0800 Subject: gpio: loongson1: Add DT support This patch adds DT support for Loongson-1 GPIO driver. Signed-off-by: Keguang Zhang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-loongson1.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c index dddfc71f0e10..6ca3b969db4d 100644 --- a/drivers/gpio/gpio-loongson1.c +++ b/drivers/gpio/gpio-loongson1.c @@ -68,25 +68,38 @@ static int ls1x_gpio_probe(struct platform_device *pdev) ls1x_gc->gc.owner = THIS_MODULE; ls1x_gc->gc.request = ls1x_gpio_request; ls1x_gc->gc.free = ls1x_gpio_free; - ls1x_gc->gc.base = pdev->id * 32; + /* + * Clear ngpio to let gpiolib get the correct number + * by reading ngpios property + */ + ls1x_gc->gc.ngpio = 0; ret = devm_gpiochip_add_data(dev, &ls1x_gc->gc, ls1x_gc); if (ret) goto err; platform_set_drvdata(pdev, ls1x_gc); - dev_info(dev, "Loongson1 GPIO driver registered\n"); + + dev_info(dev, "GPIO controller registered with %d pins\n", + ls1x_gc->gc.ngpio); return 0; err: - dev_err(dev, "failed to register GPIO device\n"); + dev_err(dev, "failed to register GPIO controller\n"); return ret; } +static const struct of_device_id ls1x_gpio_dt_ids[] = { + { .compatible = "loongson,ls1x-gpio" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ls1x_gpio_dt_ids); + static struct platform_driver ls1x_gpio_driver = { .probe = ls1x_gpio_probe, .driver = { .name = "ls1x-gpio", + .of_match_table = ls1x_gpio_dt_ids, }, }; -- cgit From 957e64bee8eecd3d3c767ab6577c4bf5c4230128 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:08 +0100 Subject: gpio: rda: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Signed-off-by: Linus Walleij Acked-by: Manivannan Sadhasivam Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-rda.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-rda.c b/drivers/gpio/gpio-rda.c index ab4137de5889..cb2f63eee2aa 100644 --- a/drivers/gpio/gpio-rda.c +++ b/drivers/gpio/gpio-rda.c @@ -38,7 +38,6 @@ struct rda_gpio { struct gpio_chip chip; void __iomem *base; spinlock_t lock; - struct irq_chip irq_chip; int irq; }; @@ -74,6 +73,7 @@ static void rda_gpio_irq_mask(struct irq_data *data) value |= BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT; writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR); + gpiochip_disable_irq(chip, offset); } static void rda_gpio_irq_ack(struct irq_data *data) @@ -154,6 +154,7 @@ static void rda_gpio_irq_unmask(struct irq_data *data) u32 offset = irqd_to_hwirq(data); u32 trigger = irqd_get_trigger_type(data); + gpiochip_enable_irq(chip, offset); rda_gpio_set_irq(chip, offset, trigger); } @@ -195,6 +196,16 @@ static void rda_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(ic, desc); } +static const struct irq_chip rda_gpio_irq_chip = { + .name = "rda-gpio", + .irq_ack = rda_gpio_irq_ack, + .irq_mask = rda_gpio_irq_mask, + .irq_unmask = rda_gpio_irq_unmask, + .irq_set_type = rda_gpio_irq_set_type, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int rda_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -241,15 +252,8 @@ static int rda_gpio_probe(struct platform_device *pdev) rda_gpio->chip.base = -1; if (rda_gpio->irq >= 0) { - rda_gpio->irq_chip.name = "rda-gpio", - rda_gpio->irq_chip.irq_ack = rda_gpio_irq_ack, - rda_gpio->irq_chip.irq_mask = rda_gpio_irq_mask, - rda_gpio->irq_chip.irq_unmask = rda_gpio_irq_unmask, - rda_gpio->irq_chip.irq_set_type = rda_gpio_irq_set_type, - rda_gpio->irq_chip.flags = IRQCHIP_SKIP_SET_WAKE, - girq = &rda_gpio->chip.irq; - girq->chip = &rda_gpio->irq_chip; + gpio_irq_chip_set_chip(girq, &rda_gpio_irq_chip); girq->handler = handle_bad_irq; girq->default_type = IRQ_TYPE_NONE; girq->parent_handler = rda_gpio_irq_handler; -- cgit From 5ff8240e47de33db6c0098368784672bd47d57cb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:09 +0100 Subject: gpio: siox: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. In this case I had to figure out a way to get to the struct gpio_chip that would work even when the irq_chip is not part of the driver state container. I did this by just doing what most other GPIO drivers do and pass the state struct as data to devm_gpiochip_add_data() and rewrite accordingly. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-siox.c | 75 ++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/drivers/gpio/gpio-siox.c b/drivers/gpio/gpio-siox.c index f8c5e9fc4bac..051bc99bdfb2 100644 --- a/drivers/gpio/gpio-siox.c +++ b/drivers/gpio/gpio-siox.c @@ -10,7 +10,6 @@ struct gpio_siox_ddata { struct gpio_chip gchip; - struct irq_chip ichip; struct mutex lock; u8 setdata[1]; u8 getdata[3]; @@ -97,9 +96,8 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) static void gpio_siox_irq_ack(struct irq_data *d) { - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct gpio_siox_ddata *ddata = - container_of(ic, struct gpio_siox_ddata, ichip); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_siox_ddata *ddata = gpiochip_get_data(gc); raw_spin_lock(&ddata->irqlock); ddata->irq_status &= ~(1 << d->hwirq); @@ -108,21 +106,21 @@ static void gpio_siox_irq_ack(struct irq_data *d) static void gpio_siox_irq_mask(struct irq_data *d) { - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct gpio_siox_ddata *ddata = - container_of(ic, struct gpio_siox_ddata, ichip); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_siox_ddata *ddata = gpiochip_get_data(gc); raw_spin_lock(&ddata->irqlock); ddata->irq_enable &= ~(1 << d->hwirq); raw_spin_unlock(&ddata->irqlock); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void gpio_siox_irq_unmask(struct irq_data *d) { - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct gpio_siox_ddata *ddata = - container_of(ic, struct gpio_siox_ddata, ichip); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_siox_ddata *ddata = gpiochip_get_data(gc); + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); raw_spin_lock(&ddata->irqlock); ddata->irq_enable |= 1 << d->hwirq; raw_spin_unlock(&ddata->irqlock); @@ -130,9 +128,8 @@ static void gpio_siox_irq_unmask(struct irq_data *d) static int gpio_siox_irq_set_type(struct irq_data *d, u32 type) { - struct irq_chip *ic = irq_data_get_irq_chip(d); - struct gpio_siox_ddata *ddata = - container_of(ic, struct gpio_siox_ddata, ichip); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct gpio_siox_ddata *ddata = gpiochip_get_data(gc); raw_spin_lock(&ddata->irqlock); ddata->irq_type[d->hwirq] = type; @@ -143,8 +140,7 @@ static int gpio_siox_irq_set_type(struct irq_data *d, u32 type) static int gpio_siox_get(struct gpio_chip *chip, unsigned int offset) { - struct gpio_siox_ddata *ddata = - container_of(chip, struct gpio_siox_ddata, gchip); + struct gpio_siox_ddata *ddata = gpiochip_get_data(chip); int ret; mutex_lock(&ddata->lock); @@ -167,8 +163,7 @@ static int gpio_siox_get(struct gpio_chip *chip, unsigned int offset) static void gpio_siox_set(struct gpio_chip *chip, unsigned int offset, int value) { - struct gpio_siox_ddata *ddata = - container_of(chip, struct gpio_siox_ddata, gchip); + struct gpio_siox_ddata *ddata = gpiochip_get_data(chip); u8 mask = 1 << (19 - offset); mutex_lock(&ddata->lock); @@ -208,11 +203,22 @@ static int gpio_siox_get_direction(struct gpio_chip *chip, unsigned int offset) return GPIO_LINE_DIRECTION_OUT; } +static const struct irq_chip gpio_siox_irq_chip = { + .name = "siox-gpio", + .irq_ack = gpio_siox_irq_ack, + .irq_mask = gpio_siox_irq_mask, + .irq_unmask = gpio_siox_irq_unmask, + .irq_set_type = gpio_siox_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int gpio_siox_probe(struct siox_device *sdevice) { struct gpio_siox_ddata *ddata; struct gpio_irq_chip *girq; struct device *dev = &sdevice->dev; + struct gpio_chip *gc; int ret; ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); @@ -224,30 +230,25 @@ static int gpio_siox_probe(struct siox_device *sdevice) mutex_init(&ddata->lock); raw_spin_lock_init(&ddata->irqlock); - ddata->gchip.base = -1; - ddata->gchip.can_sleep = 1; - ddata->gchip.parent = dev; - ddata->gchip.owner = THIS_MODULE; - ddata->gchip.get = gpio_siox_get; - ddata->gchip.set = gpio_siox_set; - ddata->gchip.direction_input = gpio_siox_direction_input; - ddata->gchip.direction_output = gpio_siox_direction_output; - ddata->gchip.get_direction = gpio_siox_get_direction; - ddata->gchip.ngpio = 20; - - ddata->ichip.name = "siox-gpio"; - ddata->ichip.irq_ack = gpio_siox_irq_ack; - ddata->ichip.irq_mask = gpio_siox_irq_mask; - ddata->ichip.irq_unmask = gpio_siox_irq_unmask; - ddata->ichip.irq_set_type = gpio_siox_irq_set_type; - - girq = &ddata->gchip.irq; - girq->chip = &ddata->ichip; + gc = &ddata->gchip; + gc->base = -1; + gc->can_sleep = 1; + gc->parent = dev; + gc->owner = THIS_MODULE; + gc->get = gpio_siox_get; + gc->set = gpio_siox_set; + gc->direction_input = gpio_siox_direction_input; + gc->direction_output = gpio_siox_direction_output; + gc->get_direction = gpio_siox_get_direction; + gc->ngpio = 20; + + girq = &gc->irq; + gpio_irq_chip_set_chip(girq, &gpio_siox_irq_chip); girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; girq->threaded = true; - ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL); + ret = devm_gpiochip_add_data(dev, gc, ddata); if (ret) dev_err(dev, "Failed to register gpio chip (%d)\n", ret); -- cgit From 32585b565fed013449f9a58b05846b508b989e74 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:10 +0100 Subject: gpio: stmpe: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-stmpe.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 0fa4f0a93378..27cc4da53565 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -234,6 +234,7 @@ static void stmpe_gpio_irq_mask(struct irq_data *d) int mask = BIT(offset % 8); stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; + gpiochip_disable_irq(gc, offset); } static void stmpe_gpio_irq_unmask(struct irq_data *d) @@ -244,6 +245,7 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d) int regoffset = offset / 8; int mask = BIT(offset % 8); + gpiochip_enable_irq(gc, offset); stmpe_gpio->regs[REG_IE][regoffset] |= mask; } @@ -357,13 +359,15 @@ static void stmpe_dbg_show(struct seq_file *s, struct gpio_chip *gc) } } -static struct irq_chip stmpe_gpio_irq_chip = { +static const struct irq_chip stmpe_gpio_irq_chip = { .name = "stmpe-gpio", .irq_bus_lock = stmpe_gpio_irq_lock, .irq_bus_sync_unlock = stmpe_gpio_irq_sync_unlock, .irq_mask = stmpe_gpio_irq_mask, .irq_unmask = stmpe_gpio_irq_unmask, .irq_set_type = stmpe_gpio_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; #define MAX_GPIOS 24 @@ -511,7 +515,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) } girq = &stmpe_gpio->chip.irq; - girq->chip = &stmpe_gpio_irq_chip; + gpio_irq_chip_set_chip(girq, &stmpe_gpio_irq_chip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From ef902f54e91b3012586f6387daeebec2966312f0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:11 +0100 Subject: gpio: thunderx: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Whereas in most cases we put the gpiochip_[enable|disable]_irq() calls in the .irq_mask() and .irq_unmask() callbacks, here we need to put them in the .irq_enable() and .irq_disable() callbacks, as this driver uses both .irq_mask() and .irq_mask_ack(). Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-thunderx.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index cc62c6e64103..8521c6aacace 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c @@ -354,16 +354,22 @@ static int thunderx_gpio_irq_set_type(struct irq_data *d, return IRQ_SET_MASK_OK; } -static void thunderx_gpio_irq_enable(struct irq_data *data) +static void thunderx_gpio_irq_enable(struct irq_data *d) { - irq_chip_enable_parent(data); - thunderx_gpio_irq_unmask(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); + irq_chip_enable_parent(d); + thunderx_gpio_irq_unmask(d); } -static void thunderx_gpio_irq_disable(struct irq_data *data) +static void thunderx_gpio_irq_disable(struct irq_data *d) { - thunderx_gpio_irq_mask(data); - irq_chip_disable_parent(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + thunderx_gpio_irq_mask(d); + irq_chip_disable_parent(d); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } /* @@ -372,7 +378,7 @@ static void thunderx_gpio_irq_disable(struct irq_data *data) * semantics and other acknowledgment tasks associated with the GPIO * mechanism. */ -static struct irq_chip thunderx_gpio_irq_chip = { +static const struct irq_chip thunderx_gpio_irq_chip = { .name = "GPIO", .irq_enable = thunderx_gpio_irq_enable, .irq_disable = thunderx_gpio_irq_disable, @@ -383,8 +389,8 @@ static struct irq_chip thunderx_gpio_irq_chip = { .irq_eoi = irq_chip_eoi_parent, .irq_set_affinity = irq_chip_set_affinity_parent, .irq_set_type = thunderx_gpio_irq_set_type, - - .flags = IRQCHIP_SET_TYPE_MASKED + .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, @@ -526,7 +532,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, chip->set_multiple = thunderx_gpio_set_multiple; chip->set_config = thunderx_gpio_set_config; girq = &chip->irq; - girq->chip = &thunderx_gpio_irq_chip; + gpio_irq_chip_set_chip(girq, &thunderx_gpio_irq_chip); girq->fwnode = of_node_to_fwnode(dev->of_node); girq->parent_domain = irq_get_irq_data(txgpio->msix_entries[0].vector)->domain; -- cgit From 8e43827b6ae727a745ce7a8cc19184b28905a965 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:12 +0100 Subject: gpio: tqmx86: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tqmx86.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index e739dcea61b2..6f8bd1155db7 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define TQMX86_NGPIO 8 @@ -34,7 +35,6 @@ struct tqmx86_gpio_data { struct gpio_chip chip; - struct irq_chip irq_chip; void __iomem *io_base; int irq; raw_spinlock_t spinlock; @@ -122,6 +122,7 @@ static void tqmx86_gpio_irq_mask(struct irq_data *data) gpiic &= ~mask; tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); raw_spin_unlock_irqrestore(&gpio->spinlock, flags); + gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data)); } static void tqmx86_gpio_irq_unmask(struct irq_data *data) @@ -134,6 +135,7 @@ static void tqmx86_gpio_irq_unmask(struct irq_data *data) mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); + gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data)); raw_spin_lock_irqsave(&gpio->spinlock, flags); gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); gpiic &= ~mask; @@ -226,6 +228,22 @@ static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip, clear_bit(3, valid_mask); } +static void tqmx86_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + seq_printf(p, gc->label); +} + +static const struct irq_chip tqmx86_gpio_irq_chip = { + .irq_mask = tqmx86_gpio_irq_mask, + .irq_unmask = tqmx86_gpio_irq_unmask, + .irq_set_type = tqmx86_gpio_irq_set_type, + .irq_print_chip = tqmx86_gpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int tqmx86_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -277,14 +295,8 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); if (irq > 0) { - struct irq_chip *irq_chip = &gpio->irq_chip; u8 irq_status; - irq_chip->name = chip->label; - irq_chip->irq_mask = tqmx86_gpio_irq_mask; - irq_chip->irq_unmask = tqmx86_gpio_irq_unmask; - irq_chip->irq_set_type = tqmx86_gpio_irq_set_type; - /* Mask all interrupts */ tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC); @@ -293,7 +305,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); girq = &chip->irq; - girq->chip = irq_chip; + gpio_irq_chip_set_chip(girq, &tqmx86_gpio_irq_chip); girq->parent_handler = tqmx86_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, -- cgit From 5cf3e019a4312564ca9c0a48a515b8a28f9cee25 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:13 +0100 Subject: gpio: visconti: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. The driver is for a hierarchical chip so some extra care needs to be taken to introduce two new callbacks. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-visconti.c | 50 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c index 10d9de41f29b..6734e7e1e2a4 100644 --- a/drivers/gpio/gpio-visconti.c +++ b/drivers/gpio/gpio-visconti.c @@ -15,6 +15,7 @@ #include #include #include +#include #include /* register offset */ @@ -31,7 +32,7 @@ struct visconti_gpio { void __iomem *base; spinlock_t lock; /* protect gpio register */ struct gpio_chip gpio_chip; - struct irq_chip irq_chip; + struct device *dev; }; static int visconti_gpio_irq_set_type(struct irq_data *d, unsigned int type) @@ -119,11 +120,45 @@ static int visconti_gpio_populate_parent_fwspec(struct gpio_chip *chip, return 0; } +static void visconti_gpio_mask_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + irq_chip_mask_parent(d); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); +} + +static void visconti_gpio_unmask_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); + irq_chip_unmask_parent(d); +} + +static void visconti_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct visconti_gpio *priv = gpiochip_get_data(gc); + + seq_printf(p, dev_name(priv->dev)); +} + +static const struct irq_chip visconti_gpio_irq_chip = { + .irq_mask = visconti_gpio_mask_irq, + .irq_unmask = visconti_gpio_unmask_irq, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_type = visconti_gpio_irq_set_type, + .irq_print_chip = visconti_gpio_irq_print_chip, + .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND | + IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int visconti_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct visconti_gpio *priv; - struct irq_chip *irq_chip; struct gpio_irq_chip *girq; struct irq_domain *parent; struct device_node *irq_parent; @@ -134,6 +169,7 @@ static int visconti_gpio_probe(struct platform_device *pdev) return -ENOMEM; spin_lock_init(&priv->lock); + priv->dev = dev; priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) @@ -164,16 +200,8 @@ static int visconti_gpio_probe(struct platform_device *pdev) return ret; } - irq_chip = &priv->irq_chip; - irq_chip->name = dev_name(dev); - irq_chip->irq_mask = irq_chip_mask_parent; - irq_chip->irq_unmask = irq_chip_unmask_parent; - irq_chip->irq_eoi = irq_chip_eoi_parent; - irq_chip->irq_set_type = visconti_gpio_irq_set_type; - irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; - girq = &priv->gpio_chip.irq; - girq->chip = irq_chip; + gpio_irq_chip_set_chip(girq, &visconti_gpio_irq_chip); girq->fwnode = of_node_to_fwnode(dev->of_node); girq->parent_domain = parent; girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq; -- cgit From 9c1282b7459e14e884bb768373f212e9e3b9cd5a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:14 +0100 Subject: gpio: xgs-iproc: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xgs-iproc.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c index fd88500399c6..2d23b27d55af 100644 --- a/drivers/gpio/gpio-xgs-iproc.c +++ b/drivers/gpio/gpio-xgs-iproc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #define IPROC_CCA_INT_F_GPIOINT BIT(0) @@ -27,7 +28,6 @@ #define IPROC_GPIO_CCA_INT_EDGE 0x24 struct iproc_gpio_chip { - struct irq_chip irqchip; struct gpio_chip gc; spinlock_t lock; struct device *dev; @@ -69,6 +69,7 @@ static void iproc_gpio_irq_unmask(struct irq_data *d) u32 irq = d->irq; u32 int_mask, irq_type, event_mask; + gpiochip_enable_irq(gc, pin); spin_lock_irqsave(&chip->lock, flags); irq_type = irq_get_trigger_type(irq); event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK); @@ -110,6 +111,7 @@ static void iproc_gpio_irq_mask(struct irq_data *d) chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK); } spin_unlock_irqrestore(&chip->lock, flags); + gpiochip_disable_irq(gc, pin); } static int iproc_gpio_irq_set_type(struct irq_data *d, u32 type) @@ -191,6 +193,24 @@ static irqreturn_t iproc_gpio_irq_handler(int irq, void *data) return int_bits ? IRQ_HANDLED : IRQ_NONE; } +static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct iproc_gpio_chip *chip = to_iproc_gpio(gc); + + seq_printf(p, dev_name(chip->dev)); +} + +static const struct irq_chip iproc_gpio_irq_chip = { + .irq_ack = iproc_gpio_irq_ack, + .irq_mask = iproc_gpio_irq_mask, + .irq_unmask = iproc_gpio_irq_unmask, + .irq_set_type = iproc_gpio_irq_set_type, + .irq_print_chip = iproc_gpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int iproc_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -230,16 +250,8 @@ static int iproc_gpio_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq > 0) { struct gpio_irq_chip *girq; - struct irq_chip *irqc; u32 val; - irqc = &chip->irqchip; - irqc->name = dev_name(dev); - irqc->irq_ack = iproc_gpio_irq_ack; - irqc->irq_mask = iproc_gpio_irq_mask; - irqc->irq_unmask = iproc_gpio_irq_unmask; - irqc->irq_set_type = iproc_gpio_irq_set_type; - chip->intr = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(chip->intr)) return PTR_ERR(chip->intr); @@ -261,7 +273,7 @@ static int iproc_gpio_probe(struct platform_device *pdev) } girq = &chip->gc.irq; - girq->chip = irqc; + gpio_irq_chip_set_chip(girq, &iproc_gpio_irq_chip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From b4510f8fd5d0e9afa777f115871f5d522540c417 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:15 +0100 Subject: gpio: xilinx: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xilinx.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index e248809965ca..1fa66f2a667f 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -68,7 +68,6 @@ struct xgpio_instance { DECLARE_BITMAP(dir, 64); spinlock_t gpio_lock; /* For serializing operations */ int irq; - struct irq_chip irqchip; DECLARE_BITMAP(enable, 64); DECLARE_BITMAP(rising_edge, 64); DECLARE_BITMAP(falling_edge, 64); @@ -416,6 +415,8 @@ static void xgpio_irq_mask(struct irq_data *irq_data) xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); } spin_unlock_irqrestore(&chip->gpio_lock, flags); + + gpiochip_disable_irq(&chip->gc, irq_offset); } /** @@ -431,6 +432,8 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) u32 old_enable = xgpio_get_value32(chip->enable, bit); u32 mask = BIT(bit / 32), val; + gpiochip_enable_irq(&chip->gc, irq_offset); + spin_lock_irqsave(&chip->gpio_lock, flags); __set_bit(bit, chip->enable); @@ -544,6 +547,16 @@ static void xgpio_irqhandler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } +static const struct irq_chip xgpio_irq_chip = { + .name = "gpio-xilinx", + .irq_ack = xgpio_irq_ack, + .irq_mask = xgpio_irq_mask, + .irq_unmask = xgpio_irq_unmask, + .irq_set_type = xgpio_set_irq_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + /** * xgpio_probe - Probe method for the GPIO device. * @pdev: pointer to the platform device @@ -653,12 +666,6 @@ static int xgpio_probe(struct platform_device *pdev) if (chip->irq <= 0) goto skip_irq; - chip->irqchip.name = "gpio-xilinx"; - chip->irqchip.irq_ack = xgpio_irq_ack; - chip->irqchip.irq_mask = xgpio_irq_mask; - chip->irqchip.irq_unmask = xgpio_irq_unmask; - chip->irqchip.irq_set_type = xgpio_set_irq_type; - /* Disable per-channel interrupts */ xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, 0); /* Clear any existing per-channel interrupts */ @@ -668,7 +675,7 @@ static int xgpio_probe(struct platform_device *pdev) xgpio_writereg(chip->regs + XGPIO_GIER_OFFSET, XGPIO_GIER_IE); girq = &chip->gc.irq; - girq->chip = &chip->irqchip; + gpio_irq_chip_set_chip(girq, &xgpio_irq_chip); girq->parent_handler = xgpio_irqhandler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, -- cgit From 2093bcd872321a5301470978231b23cc121e3476 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Mar 2023 10:55:16 +0100 Subject: gpio: xlp: Convert to immutable irq_chip Convert the driver to immutable irq-chip with a bit of intuition. In this case the driver uses .mask_ack() and .unmask() and since I have a vague idea about the semantics of .mask_ack() I added .irq_enable() to the existing .irq_disable() and called into the gpiolib core from those callbacks instead of mask/unmask. Cc: Marc Zyngier Signed-off-by: Linus Walleij Reviewed-by: Marc Zyngier Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xlp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 0199f545335f..b4b52213bcd9 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -90,6 +90,13 @@ static void xlp_gpio_set_reg(void __iomem *addr, unsigned gpio, int state) writel(value, addr + regset); } +static void xlp_gpio_irq_enable(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); +} + static void xlp_gpio_irq_disable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); @@ -100,6 +107,7 @@ static void xlp_gpio_irq_disable(struct irq_data *d) xlp_gpio_set_reg(priv->gpio_intr_en, d->hwirq, 0x0); __clear_bit(d->hwirq, priv->gpio_enabled_mask); spin_unlock_irqrestore(&priv->lock, flags); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void xlp_gpio_irq_mask_ack(struct irq_data *d) @@ -163,10 +171,12 @@ static int xlp_gpio_set_irq_type(struct irq_data *d, unsigned int type) static struct irq_chip xlp_gpio_irq_chip = { .name = "XLP-GPIO", .irq_mask_ack = xlp_gpio_irq_mask_ack, + .irq_enable = xlp_gpio_irq_enable, .irq_disable = xlp_gpio_irq_disable, .irq_set_type = xlp_gpio_set_irq_type, .irq_unmask = xlp_gpio_irq_unmask, - .flags = IRQCHIP_ONESHOT_SAFE, + .flags = IRQCHIP_ONESHOT_SAFE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void xlp_gpio_generic_handler(struct irq_desc *desc) @@ -272,7 +282,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) spin_lock_init(&priv->lock); girq = &gc->irq; - girq->chip = &xlp_gpio_irq_chip; + gpio_irq_chip_set_chip(girq, &xlp_gpio_irq_chip); girq->parent_handler = xlp_gpio_generic_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, -- cgit From 559e4a3df02991456113089996df1168a74c2e0a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 23 Mar 2023 16:18:19 +0200 Subject: powerpc/40x: Add missing select OF_GPIO_MM_GPIOCHIP Since the split of the legacy of_mm_gpio_chip to a separate file and a specific build configuration option, the users must select it when needed. The PowerPC 40x code misses this, so we have to add the select here. Fixes: a99cc66807d6 ("gpiolib: split of_mm_gpio_chip out of linux/of_gpio.h") Reported-by: kernel test robot Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/40x/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 614ea6dc994c..b3c466c50535 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig @@ -65,6 +65,7 @@ config PPC4xx_GPIO bool "PPC4xx GPIO support" depends on 40x select GPIOLIB + select OF_GPIO_MM_GPIOCHIP help Enable gpiolib support for ppc40x based boards -- cgit From d94ffb99a379a6307af99b6f59b08ec3d58eb958 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 9 Mar 2023 15:41:13 +0100 Subject: sh: mach-x3proto: Add missing #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shx3_defconfig: arch/sh/boards/mach-x3proto/setup.c: In function ‘x3proto_devices_setup’: arch/sh/boards/mach-x3proto/setup.c:246:62: error: invalid use of undefined type ‘struct gpio_chip’ 246 | baseboard_buttons[i].gpio = x3proto_gpio_chip.base + i; | ^ Fix this by replacing the include of the legacy by . Reported-by: Linux Kernel Functional Testing Link: https://lore.kernel.org/r/CA+G9fYs7suzGsEDK40G0pzxXyR1o2V4Pn-oy1owTsTWRVEVHog@mail.gmail.com Fixes: 21d9526d13b5467b ("gpiolib: Make the legacy consumer-only") Signed-off-by: Geert Uytterhoeven Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko --- arch/sh/boards/mach-x3proto/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c index 95b85f2e13dd..ca2802d30565 100644 --- a/arch/sh/boards/mach-x3proto/setup.c +++ b/arch/sh/boards/mach-x3proto/setup.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include -- cgit From 2ffd04ca2ae66c274eb116d5f0330af14cb63383 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 14 Mar 2023 12:55:09 +0200 Subject: gpio: mm-lantiq: Fix typo in the newly added header filename The header with legacy struct of_mmio_gpio_chip and accompanying APIs is called legacy-of-mm-gpiochip.h. Remove repetitive '.h' at the end. Fixes: a99cc66807d6 ("gpiolib: split of_mm_gpio_chip out of linux/of_gpio.h") Reported-by: kernel test robot Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-mm-lantiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index 27ff84c5d162..f3c158259636 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include -- cgit From 5062e4c14b752a21aa24d6500ace6e251fde1d7c Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 10 Mar 2023 14:38:10 +0100 Subject: gpiolib: acpi: use the fwnode in acpi_gpiochip_find() While trying to set up an SSDT override for a USB-2-I2C chip [0], I realized that the function acpi_gpiochip_find() was using the parent of the gpio_chip to do the ACPI matching. This works fine on my Ice Lake laptop because AFAICT, the DSDT presents the PCI device INT3455 as the "Device (GPI0)", but is in fact handled by the pinctrl driver in Linux. The pinctrl driver then creates a gpio_chip device. This means that the gc->parent device in that case is the GPI0 device from ACPI and everything works. However, in the hid-cp2112 case, the parent is the USB device, and the gpio_chip is directly under that USB device. Which means that in this case gc->parent points at the USB device, and so we can not do an ACPI match towards the GPIO device. I think it is safe to resolve the ACPI matching through the fwnode because when we call gpiochip_add_data(), the first thing it does is setting a proper gc->fwnode: if it is not there, it borrows the fwnode of the parent. So in my Ice Lake case, gc->fwnode is the one from the parent, meaning that the ACPI handle we will get is the one from the GPI0 in the DSDT (the pincrtl one). And in the hid-cp2112 case, we get the actual fwnode from the gpiochip we created in the HID device, making it working. Reviewed-by: Mika Westerberg Link: https://lore.kernel.org/linux-input/20230227140758.1575-1-kaehndan@gmail.com/T/#m592f18081ef3b95b618694a612ff864420c5aaf3 [0] Signed-off-by: Benjamin Tissoires Signed-off-by: Andy Shevchenko --- drivers/gpio/gpiolib-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 0605399c84e7..47d34dbd7218 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -128,7 +128,7 @@ static bool acpi_gpio_deferred_req_irqs_done; static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) { - return gc->parent && device_match_acpi_handle(gc->parent, data); + return ACPI_HANDLE_FWNODE(gc->fwnode) == data; } /** -- cgit From af3b462a8e07bc5529e19f60d04a225bfce659e1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 30 Jan 2023 18:13:45 +0200 Subject: gpiolib: acpi: Move ACPI device NULL check to acpi_get_driver_gpio_data() It's logical to check ACPI device for NULL inside acpi_get_driver_gpio_data() instead of requiring that in each caller. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpiolib-acpi.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 47d34dbd7218..4d4a2a6172a2 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -645,7 +645,7 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev, { const struct acpi_gpio_mapping *gm; - if (!adev->driver_gpios) + if (!adev || !adev->driver_gpios) return false; for (gm = adev->driver_gpios; gm->name; gm++) @@ -839,13 +839,10 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, ret = __acpi_node_get_property_reference(fwnode, propname, index, 3, &args); if (ret) { - struct acpi_device *adev = to_acpi_device_node(fwnode); + struct acpi_device *adev; - if (!adev) - return ret; - - if (!acpi_get_driver_gpio_data(adev, propname, index, &args, - &quirks)) + adev = to_acpi_device_node(fwnode); + if (!acpi_get_driver_gpio_data(adev, propname, index, &args, &quirks)) return ret; } /* -- cgit From 782eea0c89f7d071d6b56ecfa1b8b0c81164b9be Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 22 Mar 2023 13:15:47 +0100 Subject: gpiolib: acpi: Add a ignore wakeup quirk for Clevo NL5xNU commit 1796f808e4bb ("HID: i2c-hid: acpi: Stop setting wakeup_capable") changed the policy such that I2C touchpads may be able to wake up the system by default if the system is configured as such. However on Clevo NL5xNU there is a mistake in the ACPI tables that the TP_ATTN# signal connected to GPIO 9 is configured as ActiveLow and level triggered but connected to a pull up. As soon as the system suspends the touchpad loses power and then the system wakes up. To avoid this problem, introduce a quirk for this model that will prevent the wakeup capability for being set for GPIO 9. This patch is analoge to a very similar patch for NL5xRU, just the DMI string changed. Signed-off-by: Werner Sembach Cc: stable@vger.kernel.org Signed-off-by: Andy Shevchenko --- drivers/gpio/gpiolib-acpi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 4d4a2a6172a2..b6321d827d91 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -1613,6 +1613,19 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_interrupt = "AMDI0030:00@18", }, }, + { + /* + * Spurious wakeups from TP_ATTN# pin + * Found in BIOS 1.7.8 + * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627 + */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_wake = "ELAN0415:00@9", + }, + }, { /* * Spurious wakeups from TP_ATTN# pin -- cgit From 79736429c97f517247645e73e75c956efd09ad03 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 21 Mar 2023 15:54:11 +0200 Subject: gpiolib: Replace open coded krealloc() gpiod_get_array() does a new allocation in some cases, followed by copying previously allocated placeholder for the descriptors. Replace that with krealloc(__GFP_ZERO), since it was kzalloc() originally. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9451a627dacd..65253dbde03e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4277,12 +4277,14 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, struct gpio_array *array_info = NULL; struct gpio_chip *gc; int count, bitmap_size; + size_t descs_size; count = gpiod_count(dev, con_id); if (count < 0) return ERR_PTR(count); - descs = kzalloc(struct_size(descs, desc, count), GFP_KERNEL); + descs_size = struct_size(descs, desc, count); + descs = kzalloc(descs_size, GFP_KERNEL); if (!descs) return ERR_PTR(-ENOMEM); @@ -4306,20 +4308,17 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, bitmap_size = BITS_TO_LONGS(gc->ngpio > count ? gc->ngpio : count); - array = kzalloc(struct_size(descs, desc, count) + - struct_size(array_info, invert_mask, - 3 * bitmap_size), GFP_KERNEL); + array = krealloc(descs, descs_size + + struct_size(array_info, invert_mask, 3 * bitmap_size), + GFP_KERNEL | __GFP_ZERO); if (!array) { gpiod_put_array(descs); return ERR_PTR(-ENOMEM); } - memcpy(array, descs, - struct_size(descs, desc, descs->ndescs + 1)); - kfree(descs); - descs = array; - array_info = (void *)(descs->desc + count); + + array_info = (void *)descs + descs_size; array_info->get_mask = array_info->invert_mask + bitmap_size; array_info->set_mask = array_info->get_mask + -- cgit From 4ea0c97776bf8c63805eb0f8182d9c20072219d9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 21 Mar 2023 15:54:12 +0200 Subject: gpiolib: Check array_info for NULL only once in gpiod_get_array() gpiod_get_array() has a long if-else-if branching where each of them tests for the same variable to be not NULL. Instead, check for NULL before even going to that flow. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 65253dbde03e..57fe0552edab 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4288,7 +4288,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, if (!descs) return ERR_PTR(-ENOMEM); - for (descs->ndescs = 0; descs->ndescs < count; ) { + for (descs->ndescs = 0; descs->ndescs < count; descs->ndescs++) { desc = gpiod_get_index(dev, con_id, descs->ndescs, flags); if (IS_ERR(desc)) { gpiod_put_array(descs); @@ -4333,8 +4333,13 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, count - descs->ndescs); descs->info = array_info; } + + /* If there is no cache for fast bitmap processing path, continue */ + if (!array_info) + continue; + /* Unmark array members which don't belong to the 'fast' chip */ - if (array_info && array_info->chip != gc) { + if (array_info->chip != gc) { __clear_bit(descs->ndescs, array_info->get_mask); __clear_bit(descs->ndescs, array_info->set_mask); } @@ -4342,8 +4347,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, * Detect array members which belong to the 'fast' chip * but their pins are not in hardware order. */ - else if (array_info && - gpio_chip_hwgpio(desc) != descs->ndescs) { + else if (gpio_chip_hwgpio(desc) != descs->ndescs) { /* * Don't use fast path if all array members processed so * far belong to the same chip as this one but its pin @@ -4357,7 +4361,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, __clear_bit(descs->ndescs, array_info->set_mask); } - } else if (array_info) { + } else { /* Exclude open drain or open source from fast output */ if (gpiochip_line_is_open_drain(gc, descs->ndescs) || gpiochip_line_is_open_source(gc, descs->ndescs)) @@ -4368,8 +4372,6 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, __set_bit(descs->ndescs, array_info->invert_mask); } - - descs->ndescs++; } if (array_info) dev_dbg(dev, -- cgit From 8deb779d36cb86c1c1c37d767317f5899b32fc76 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 21 Mar 2023 15:53:31 +0200 Subject: gpiolib: Move gpiochip_get_data() higher in the code Move gpiochip_get_data() higher in the code as a preparation for further refactoring. Signed-off-by: Andy Shevchenko [Bartosz: tweak the commit message] Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 57fe0552edab..fd997eb0857f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -680,6 +680,19 @@ static void gpiochip_setup_devs(void) } } +/** + * gpiochip_get_data() - get per-subdriver data for the chip + * @gc: GPIO chip + * + * Returns: + * The per-subdriver data for the chip. + */ +void *gpiochip_get_data(struct gpio_chip *gc) +{ + return gc->gpiodev->data; +} +EXPORT_SYMBOL_GPL(gpiochip_get_data); + int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, struct lock_class_key *lock_key, struct lock_class_key *request_key) @@ -938,19 +951,6 @@ err_print_message: } EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key); -/** - * gpiochip_get_data() - get per-subdriver data for the chip - * @gc: GPIO chip - * - * Returns: - * The per-subdriver data for the chip. - */ -void *gpiochip_get_data(struct gpio_chip *gc) -{ - return gc->gpiodev->data; -} -EXPORT_SYMBOL_GPL(gpiochip_get_data); - /** * gpiochip_remove() - unregister a gpio_chip * @gc: the chip to unregister -- cgit From 7b59bdbc3965ca8add53e084af394c13a2be22a8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 21 Mar 2023 15:53:32 +0200 Subject: gpiolib: Add gpiochip_set_data() helper There are too many 'data' parameters here and there. For the better maintenance keep access GPIO device data via getter and setter. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index fd997eb0857f..88dcf40aca90 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -680,6 +680,11 @@ static void gpiochip_setup_devs(void) } } +static void gpiochip_set_data(struct gpio_chip *gc, void *data) +{ + gc->gpiodev->data = data; +} + /** * gpiochip_get_data() - get per-subdriver data for the chip * @gc: GPIO chip @@ -722,7 +727,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, gdev->dev.bus = &gpio_bus_type; gdev->dev.parent = gc->parent; gdev->chip = gc; + gc->gpiodev = gdev; + gpiochip_set_data(gc, data); device_set_node(&gdev->dev, gc->fwnode); @@ -789,7 +796,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, } gdev->ngpio = gc->ngpio; - gdev->data = data; spin_lock_irqsave(&gpio_lock, flags); @@ -977,9 +983,9 @@ void gpiochip_remove(struct gpio_chip *gc) gpiochip_free_valid_mask(gc); /* * We accept no more calls into the driver from this point, so - * NULL the driver data pointer + * NULL the driver data pointer. */ - gdev->data = NULL; + gpiochip_set_data(gc, NULL); spin_lock_irqsave(&gpio_lock, flags); for (i = 0; i < gdev->ngpio; i++) { -- cgit From 8a4adcf67a39b3f308bb8cf686e41c0e26aa12e8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 11 Apr 2023 10:28:06 +0200 Subject: gpio: gpiolib: Simplify gpiochip_add_data_with_key() fwnode The code defaulting to the parents fwnode if no fwnode was assigned is unnecessarily convoluted, probably due to refactoring. Simplify it and make it more human-readable. Signed-off-by: Linus Walleij Reviewed-by: Anders Roxell Reviewed-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 88dcf40aca90..04fb05df805b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -702,7 +702,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, struct lock_class_key *lock_key, struct lock_class_key *request_key) { - struct fwnode_handle *fwnode = NULL; struct gpio_device *gdev; unsigned long flags; unsigned int i; @@ -710,12 +709,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, int base = 0; int ret = 0; - /* If the calling driver did not initialize firmware node, do it here */ - if (gc->fwnode) - fwnode = gc->fwnode; - else if (gc->parent) - fwnode = dev_fwnode(gc->parent); - gc->fwnode = fwnode; + /* + * If the calling driver did not initialize firmware node, do it here + * using the parent device, if any. + */ + if (!gc->fwnode && gc->parent) + gc->fwnode = dev_fwnode(gc->parent); /* * First: allocate and populate the internal stat container, and -- cgit