* [PATCH 01/15] gpio: loongson1: allow building the module with COMPILE_TEST enabled
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 02/15] gpio: loongson1: use new generic GPIO chip API Bartosz Golaszewski
` (13 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Increase build coverage by allowing the module to be built with
COMPILE_TEST=y.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 31f8bab4b09df1640c892f4d839860edaa2ad6a3..09cb144f076661e0a2069016175d0692257fb156 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -885,7 +885,7 @@ config GPIO_ZYNQMP_MODEPIN
config GPIO_LOONGSON1
tristate "Loongson1 GPIO support"
- depends on MACH_LOONGSON32
+ depends on MACH_LOONGSON32 || COMPILE_TEST
select GPIO_GENERIC
help
Say Y or M here to support GPIO on Loongson1 SoCs.
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 02/15] gpio: loongson1: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 01/15] gpio: loongson1: allow building the module with COMPILE_TEST enabled Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 03/15] gpio: hlwd: " Bartosz Golaszewski
` (12 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-loongson1.c | 40 +++++++++++++++++++++++-----------------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c
index 6ca3b969db4df231517d021a7b4b5e3ddcf626f7..bb0e101e920889522aa4bbc69e5d6d2c49586cee 100644
--- a/drivers/gpio/gpio-loongson1.c
+++ b/drivers/gpio/gpio-loongson1.c
@@ -5,10 +5,11 @@
* Copyright (C) 2015-2023 Keguang Zhang <keguang.zhang@gmail.com>
*/
+#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/platform_device.h>
-#include <linux/bitops.h>
/* Loongson 1 GPIO Register Definitions */
#define GPIO_CFG 0x0
@@ -17,19 +18,18 @@
#define GPIO_OUTPUT 0x30
struct ls1x_gpio_chip {
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
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);
+ guard(gpio_generic_lock_irqsave)(&ls1x_gc->chip);
+
__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;
}
@@ -37,16 +37,16 @@ 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);
+ guard(gpio_generic_lock_irqsave)(&ls1x_gc->chip);
+
__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 gpio_generic_chip_config config;
struct device *dev = &pdev->dev;
struct ls1x_gpio_chip *ls1x_gc;
int ret;
@@ -59,29 +59,35 @@ static int ls1x_gpio_probe(struct platform_device *pdev)
if (IS_ERR(ls1x_gc->reg_base))
return PTR_ERR(ls1x_gc->reg_base);
- 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);
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = 4,
+ .dat = ls1x_gc->reg_base + GPIO_DATA,
+ .set = ls1x_gc->reg_base + GPIO_OUTPUT,
+ .dirin = ls1x_gc->reg_base + GPIO_DIR,
+ };
+
+ ret = gpio_generic_chip_init(&ls1x_gc->chip, &config);
if (ret)
goto err;
- ls1x_gc->gc.owner = THIS_MODULE;
- ls1x_gc->gc.request = ls1x_gpio_request;
- ls1x_gc->gc.free = ls1x_gpio_free;
+ ls1x_gc->chip.gc.owner = THIS_MODULE;
+ ls1x_gc->chip.gc.request = ls1x_gpio_request;
+ ls1x_gc->chip.gc.free = ls1x_gpio_free;
/*
* Clear ngpio to let gpiolib get the correct number
* by reading ngpios property
*/
- ls1x_gc->gc.ngpio = 0;
+ ls1x_gc->chip.gc.ngpio = 0;
- ret = devm_gpiochip_add_data(dev, &ls1x_gc->gc, ls1x_gc);
+ ret = devm_gpiochip_add_data(dev, &ls1x_gc->chip.gc, ls1x_gc);
if (ret)
goto err;
platform_set_drvdata(pdev, ls1x_gc);
dev_info(dev, "GPIO controller registered with %d pins\n",
- ls1x_gc->gc.ngpio);
+ ls1x_gc->chip.gc.ngpio);
return 0;
err:
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 03/15] gpio: hlwd: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 01/15] gpio: loongson1: allow building the module with COMPILE_TEST enabled Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 02/15] gpio: loongson1: use new generic GPIO chip API Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 04/15] gpio: ath79: " Bartosz Golaszewski
` (11 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-hlwd.c | 105 ++++++++++++++++++++++++-----------------------
1 file changed, 54 insertions(+), 51 deletions(-)
diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c
index 0580f6712bea9a4d510bd332645982adbc5c6a32..137f17c9ff221d524a4281fdbf91d8f27ee24182 100644
--- a/drivers/gpio/gpio-hlwd.c
+++ b/drivers/gpio/gpio-hlwd.c
@@ -6,6 +6,7 @@
// Nintendo Wii (Hollywood) GPIO driver
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -48,7 +49,7 @@
#define HW_GPIO_OWNER 0x3c
struct hlwd_gpio {
- struct gpio_chip gpioc;
+ struct gpio_generic_chip gpioc;
struct device *dev;
void __iomem *regs;
int irq;
@@ -61,45 +62,44 @@ static void hlwd_gpio_irqhandler(struct irq_desc *desc)
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_desc_get_handler_data(desc));
struct irq_chip *chip = irq_desc_get_chip(desc);
- unsigned long flags;
unsigned long pending;
int hwirq;
u32 emulated_pending;
- raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
- pending = ioread32be(hlwd->regs + HW_GPIOB_INTFLAG);
- pending &= ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
+ scoped_guard(gpio_generic_lock_irqsave, &hlwd->gpioc) {
+ pending = ioread32be(hlwd->regs + HW_GPIOB_INTFLAG);
+ pending &= ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
- /* Treat interrupts due to edge trigger emulation separately */
- emulated_pending = hlwd->edge_emulation & pending;
- pending &= ~emulated_pending;
- if (emulated_pending) {
- u32 level, rising, falling;
+ /* Treat interrupts due to edge trigger emulation separately */
+ emulated_pending = hlwd->edge_emulation & pending;
+ pending &= ~emulated_pending;
+ if (emulated_pending) {
+ u32 level, rising, falling;
- level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
- rising = level & emulated_pending;
- falling = ~level & emulated_pending;
+ level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
+ rising = level & emulated_pending;
+ falling = ~level & emulated_pending;
- /* Invert the levels */
- iowrite32be(level ^ emulated_pending,
- hlwd->regs + HW_GPIOB_INTLVL);
+ /* Invert the levels */
+ iowrite32be(level ^ emulated_pending,
+ hlwd->regs + HW_GPIOB_INTLVL);
- /* Ack all emulated-edge interrupts */
- iowrite32be(emulated_pending, hlwd->regs + HW_GPIOB_INTFLAG);
+ /* Ack all emulated-edge interrupts */
+ iowrite32be(emulated_pending, hlwd->regs + HW_GPIOB_INTFLAG);
- /* Signal interrupts only on the correct edge */
- rising &= hlwd->rising_edge;
- falling &= hlwd->falling_edge;
+ /* Signal interrupts only on the correct edge */
+ rising &= hlwd->rising_edge;
+ falling &= hlwd->falling_edge;
- /* Mark emulated interrupts as pending */
- pending |= rising | falling;
+ /* Mark emulated interrupts as pending */
+ pending |= rising | falling;
+ }
}
- raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
chained_irq_enter(chip, desc);
for_each_set_bit(hwirq, &pending, 32)
- generic_handle_domain_irq(hlwd->gpioc.irq.domain, hwirq);
+ generic_handle_domain_irq(hlwd->gpioc.gc.irq.domain, hwirq);
chained_irq_exit(chip, desc);
}
@@ -116,30 +116,29 @@ static void hlwd_gpio_irq_mask(struct irq_data *data)
{
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- unsigned long flags;
u32 mask;
- raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
- mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
- 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));
+ scoped_guard(gpio_generic_lock_irqsave, &hlwd->gpioc) {
+ mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
+ mask &= ~BIT(data->hwirq);
+ iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK);
+ }
+ gpiochip_disable_irq(&hlwd->gpioc.gc, irqd_to_hwirq(data));
}
static void hlwd_gpio_irq_unmask(struct irq_data *data)
{
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_data_get_irq_chip_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);
+ gpiochip_enable_irq(&hlwd->gpioc.gc, irqd_to_hwirq(data));
+
+ guard(gpio_generic_lock_irqsave)(&hlwd->gpioc);
+
mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
mask |= BIT(data->hwirq);
iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK);
- raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
}
static void hlwd_gpio_irq_enable(struct irq_data *data)
@@ -173,10 +172,9 @@ static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- unsigned long flags;
u32 level;
- raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(&hlwd->gpioc);
hlwd->edge_emulation &= ~BIT(data->hwirq);
@@ -197,11 +195,9 @@ static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
hlwd_gpio_irq_setup_emulation(hlwd, data->hwirq, flow_type);
break;
default:
- raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
return -EINVAL;
}
- raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
return 0;
}
@@ -225,6 +221,7 @@ static const struct irq_chip hlwd_gpio_irq_chip = {
static int hlwd_gpio_probe(struct platform_device *pdev)
{
+ struct gpio_generic_chip_config config;
struct hlwd_gpio *hlwd;
u32 ngpios;
int res;
@@ -244,25 +241,31 @@ static int hlwd_gpio_probe(struct platform_device *pdev)
* systems where the AHBPROT memory firewall hasn't been configured to
* permit PPC access to HW_GPIO_*.
*
- * Note that this has to happen before bgpio_init reads the
- * HW_GPIOB_OUT and HW_GPIOB_DIR, because otherwise it reads the wrong
- * values.
+ * Note that this has to happen before gpio_generic_chip_init() reads
+ * the HW_GPIOB_OUT and HW_GPIOB_DIR, because otherwise it reads the
+ * wrong values.
*/
iowrite32be(0xffffffff, hlwd->regs + HW_GPIO_OWNER);
- res = bgpio_init(&hlwd->gpioc, &pdev->dev, 4,
- hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_OUT,
- NULL, hlwd->regs + HW_GPIOB_DIR, NULL,
- BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ config = (typeof(config)){
+ .dev = &pdev->dev,
+ .sz = 4,
+ .dat = hlwd->regs + HW_GPIOB_IN,
+ .set = hlwd->regs + HW_GPIOB_OUT,
+ .dirout = hlwd->regs + HW_GPIOB_DIR,
+ .flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER,
+ };
+
+ res = gpio_generic_chip_init(&hlwd->gpioc, &config);
if (res < 0) {
- dev_warn(&pdev->dev, "bgpio_init failed: %d\n", res);
+ dev_warn(&pdev->dev, "failed to initialize generic GPIO chip: %d\n", res);
return res;
}
res = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios);
if (res)
ngpios = 32;
- hlwd->gpioc.ngpio = ngpios;
+ hlwd->gpioc.gc.ngpio = ngpios;
/* Mask and ack all interrupts */
iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK);
@@ -282,7 +285,7 @@ static int hlwd_gpio_probe(struct platform_device *pdev)
return hlwd->irq;
}
- girq = &hlwd->gpioc.irq;
+ girq = &hlwd->gpioc.gc.irq;
gpio_irq_chip_set_chip(girq, &hlwd_gpio_irq_chip);
girq->parent_handler = hlwd_gpio_irqhandler;
girq->num_parents = 1;
@@ -296,7 +299,7 @@ static int hlwd_gpio_probe(struct platform_device *pdev)
girq->handler = handle_level_irq;
}
- return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
+ return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc.gc, hlwd);
}
static const struct of_device_id hlwd_gpio_match[] = {
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 04/15] gpio: ath79: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (2 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 03/15] gpio: hlwd: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 05/15] gpio: ath79: use the generic GPIO chip lock for IRQ handling Bartosz Golaszewski
` (10 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-ath79.c | 39 ++++++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index de4cc12e5e0399abcef61a89c8c91a1b203d20fb..1b2a59ddbec4088c95fb766277bb94ffff8692b2 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mod_devicetable.h>
@@ -28,7 +29,7 @@
#define AR71XX_GPIO_REG_INT_MASK 0x24
struct ath79_gpio_ctrl {
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
void __iomem *base;
raw_spinlock_t lock;
unsigned long both_edges;
@@ -37,8 +38,9 @@ struct ath79_gpio_ctrl {
static struct ath79_gpio_ctrl *irq_data_to_ath79_gpio(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
- return container_of(gc, struct ath79_gpio_ctrl, gc);
+ return container_of(gen_gc, struct ath79_gpio_ctrl, chip);
}
static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg)
@@ -72,7 +74,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));
+ gpiochip_enable_irq(&ctrl->chip.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);
@@ -87,7 +89,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));
+ gpiochip_disable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
}
static void ath79_gpio_irq_enable(struct irq_data *data)
@@ -187,8 +189,9 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct ath79_gpio_ctrl *ctrl =
- container_of(gc, struct ath79_gpio_ctrl, gc);
+ container_of(gen_gc, struct ath79_gpio_ctrl, chip);
unsigned long flags, pending;
u32 both_edges, state;
int irq;
@@ -224,6 +227,7 @@ MODULE_DEVICE_TABLE(of, ath79_gpio_of_match);
static int ath79_gpio_probe(struct platform_device *pdev)
{
+ struct gpio_generic_chip_config config;
struct device *dev = &pdev->dev;
struct ath79_gpio_ctrl *ctrl;
struct gpio_irq_chip *girq;
@@ -253,21 +257,26 @@ static int ath79_gpio_probe(struct platform_device *pdev)
return PTR_ERR(ctrl->base);
raw_spin_lock_init(&ctrl->lock);
- err = bgpio_init(&ctrl->gc, dev, 4,
- ctrl->base + AR71XX_GPIO_REG_IN,
- ctrl->base + AR71XX_GPIO_REG_SET,
- ctrl->base + AR71XX_GPIO_REG_CLEAR,
- oe_inverted ? NULL : ctrl->base + AR71XX_GPIO_REG_OE,
- oe_inverted ? ctrl->base + AR71XX_GPIO_REG_OE : NULL,
- 0);
+
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = 4,
+ .dat = ctrl->base + AR71XX_GPIO_REG_IN,
+ .set = ctrl->base + AR71XX_GPIO_REG_SET,
+ .clr = ctrl->base + AR71XX_GPIO_REG_CLEAR,
+ .dirout = oe_inverted ? NULL : ctrl->base + AR71XX_GPIO_REG_OE,
+ .dirin = oe_inverted ? ctrl->base + AR71XX_GPIO_REG_OE : NULL,
+ };
+
+ err = gpio_generic_chip_init(&ctrl->chip, &config);
if (err) {
- dev_err(dev, "bgpio_init failed\n");
+ dev_err(dev, "failed to initialize generic GPIO chip\n");
return err;
}
/* Optional interrupt setup */
if (device_property_read_bool(dev, "interrupt-controller")) {
- girq = &ctrl->gc.irq;
+ girq = &ctrl->chip.gc.irq;
gpio_irq_chip_set_chip(girq, &ath79_gpio_irqchip);
girq->parent_handler = ath79_gpio_irq_handler;
girq->num_parents = 1;
@@ -280,7 +289,7 @@ static int ath79_gpio_probe(struct platform_device *pdev)
girq->handler = handle_simple_irq;
}
- return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
+ return devm_gpiochip_add_data(dev, &ctrl->chip.gc, ctrl);
}
static struct platform_driver ath79_gpio_driver = {
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 05/15] gpio: ath79: use the generic GPIO chip lock for IRQ handling
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (3 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 04/15] gpio: ath79: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 06/15] gpio: xgene-sb: use generic GPIO chip register read and write APIs Bartosz Golaszewski
` (9 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This driver uses its own raw spinlock in interrupt routines while the
generic GPIO chip callbacks use a separate one. This is, of course, racy
so use the fact that the lock in generic GPIO chip is also a raw
spinlock and convert the interrupt handling functions in this module to
using the provided generic GPIO chip locking API.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-ath79.c | 51 ++++++++++++++++++-----------------------------
1 file changed, 19 insertions(+), 32 deletions(-)
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index 1b2a59ddbec4088c95fb766277bb94ffff8692b2..75c9e3bf7db1b5fbfede960dd1c0b3a76d2ecb8f 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -31,7 +31,6 @@
struct ath79_gpio_ctrl {
struct gpio_generic_chip chip;
void __iomem *base;
- raw_spinlock_t lock;
unsigned long both_edges;
};
@@ -72,23 +71,22 @@ static void ath79_gpio_irq_unmask(struct irq_data *data)
{
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
u32 mask = BIT(irqd_to_hwirq(data));
- unsigned long flags;
gpiochip_enable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
- raw_spin_lock_irqsave(&ctrl->lock, flags);
+
+ guard(gpio_generic_lock_irqsave)(&ctrl->chip);
+
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static void ath79_gpio_irq_mask(struct irq_data *data)
{
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
u32 mask = BIT(irqd_to_hwirq(data));
- unsigned long flags;
- 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);
+ scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip)
+ ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
+
gpiochip_disable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
}
@@ -96,24 +94,20 @@ static void ath79_gpio_irq_enable(struct irq_data *data)
{
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
u32 mask = BIT(irqd_to_hwirq(data));
- unsigned long flags;
- raw_spin_lock_irqsave(&ctrl->lock, flags);
+ guard(gpio_generic_lock_irqsave)(&ctrl->chip);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static void ath79_gpio_irq_disable(struct irq_data *data)
{
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
u32 mask = BIT(irqd_to_hwirq(data));
- unsigned long flags;
- raw_spin_lock_irqsave(&ctrl->lock, flags);
+ guard(gpio_generic_lock_irqsave)(&ctrl->chip);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static int ath79_gpio_irq_set_type(struct irq_data *data,
@@ -122,7 +116,6 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
u32 mask = BIT(irqd_to_hwirq(data));
u32 type = 0, polarity = 0;
- unsigned long flags;
bool disabled;
switch (flow_type) {
@@ -144,7 +137,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
return -EINVAL;
}
- raw_spin_lock_irqsave(&ctrl->lock, flags);
+ guard(gpio_generic_lock_irqsave)(&ctrl->chip);
if (flow_type == IRQ_TYPE_EDGE_BOTH) {
ctrl->both_edges |= mask;
@@ -169,8 +162,6 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
ath79_gpio_update_bits(
ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-
return 0;
}
@@ -192,26 +183,24 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
struct ath79_gpio_ctrl *ctrl =
container_of(gen_gc, struct ath79_gpio_ctrl, chip);
- unsigned long flags, pending;
+ unsigned long pending;
u32 both_edges, state;
int irq;
chained_irq_enter(irqchip, desc);
- raw_spin_lock_irqsave(&ctrl->lock, flags);
+ scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip) {
+ pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
- pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
-
- /* Update the polarity of the both edges irqs */
- both_edges = ctrl->both_edges & pending;
- if (both_edges) {
- state = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN);
- ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY,
- both_edges, ~state);
+ /* Update the polarity of the both edges irqs */
+ both_edges = ctrl->both_edges & pending;
+ if (both_edges) {
+ state = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_IN);
+ ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_POLARITY,
+ both_edges, ~state);
+ }
}
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-
for_each_set_bit(irq, &pending, gc->ngpio)
generic_handle_domain_irq(gc->irq.domain, irq);
@@ -256,8 +245,6 @@ static int ath79_gpio_probe(struct platform_device *pdev)
if (IS_ERR(ctrl->base))
return PTR_ERR(ctrl->base);
- raw_spin_lock_init(&ctrl->lock);
-
config = (typeof(config)){
.dev = dev,
.sz = 4,
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 06/15] gpio: xgene-sb: use generic GPIO chip register read and write APIs
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (4 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 05/15] gpio: ath79: use the generic GPIO chip lock for IRQ handling Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 07/15] gpio: brcmstb: use new generic GPIO chip API Bartosz Golaszewski
` (8 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
The conversion to using the modernized generic GPIO chip API was
incomplete without also converting the direct calls to write/read_reg()
callbacks. Use the provided wrappers from linux/gpio/generic.h.
Fixes: 38d98a822c14 ("gpio: xgene-sb: use new generic GPIO chip API")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-xgene-sb.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c
index c559a89aadf7a77bd9cce7e5a7d4a2b241307812..62545e358b6c4b1cab25e1135cb24ccc3e955078 100644
--- a/drivers/gpio/gpio-xgene-sb.c
+++ b/drivers/gpio/gpio-xgene-sb.c
@@ -63,14 +63,15 @@ struct xgene_gpio_sb {
static void xgene_gpio_set_bit(struct gpio_chip *gc,
void __iomem *reg, u32 gpio, int val)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
u32 data;
- data = gc->read_reg(reg);
+ data = gpio_generic_read_reg(chip, reg);
if (val)
data |= GPIO_MASK(gpio);
else
data &= ~GPIO_MASK(gpio);
- gc->write_reg(reg, data);
+ gpio_generic_write_reg(chip, reg, data);
}
static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 07/15] gpio: brcmstb: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (5 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 06/15] gpio: xgene-sb: use generic GPIO chip register read and write APIs Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 08/15] gpio: mt7621: " Bartosz Golaszewski
` (7 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-brcmstb.c | 112 ++++++++++++++++++++++++--------------------
1 file changed, 60 insertions(+), 52 deletions(-)
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index e29a9589b3ccbd17d10f6671088dca3e76537927..d03ff4ed9ef4c9d75f3e8c9c6fcb39bc577bcb79 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -3,6 +3,7 @@
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
@@ -37,7 +38,7 @@ enum gio_reg_index {
struct brcmstb_gpio_bank {
struct list_head node;
int id;
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
struct brcmstb_gpio_priv *parent_priv;
u32 width;
u32 wake_active;
@@ -72,19 +73,18 @@ __brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank)
{
void __iomem *reg_base = bank->parent_priv->reg_base;
- return bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) &
- bank->gc.read_reg(reg_base + GIO_MASK(bank->id));
+ return gpio_generic_read_reg(&bank->chip, reg_base + GIO_STAT(bank->id)) &
+ gpio_generic_read_reg(&bank->chip, reg_base + GIO_MASK(bank->id));
}
static unsigned long
brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank)
{
unsigned long status;
- unsigned long flags;
- raw_spin_lock_irqsave(&bank->gc.bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(&bank->chip);
+
status = __brcmstb_gpio_get_active_irqs(bank);
- raw_spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags);
return status;
}
@@ -92,26 +92,26 @@ brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank)
static int brcmstb_gpio_hwirq_to_offset(irq_hw_number_t hwirq,
struct brcmstb_gpio_bank *bank)
{
- return hwirq - bank->gc.offset;
+ return hwirq - bank->chip.gc.offset;
}
static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank,
unsigned int hwirq, bool enable)
{
- struct gpio_chip *gc = &bank->gc;
struct brcmstb_gpio_priv *priv = bank->parent_priv;
u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(hwirq, bank));
u32 imask;
- unsigned long flags;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
- imask = gc->read_reg(priv->reg_base + GIO_MASK(bank->id));
+ guard(gpio_generic_lock_irqsave)(&bank->chip);
+
+ imask = gpio_generic_read_reg(&bank->chip,
+ priv->reg_base + GIO_MASK(bank->id));
if (enable)
imask |= mask;
else
imask &= ~mask;
- gc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_MASK(bank->id), imask);
}
static int brcmstb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
@@ -150,7 +150,8 @@ static void brcmstb_gpio_irq_ack(struct irq_data *d)
struct brcmstb_gpio_priv *priv = bank->parent_priv;
u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank));
- gc->write_reg(priv->reg_base + GIO_STAT(bank->id), mask);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_STAT(bank->id), mask);
}
static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@@ -162,7 +163,6 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
u32 edge_insensitive, iedge_insensitive;
u32 edge_config, iedge_config;
u32 level, ilevel;
- unsigned long flags;
switch (type) {
case IRQ_TYPE_LEVEL_LOW:
@@ -194,23 +194,25 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- raw_spin_lock_irqsave(&bank->gc.bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(&bank->chip);
- iedge_config = bank->gc.read_reg(priv->reg_base +
- GIO_EC(bank->id)) & ~mask;
- iedge_insensitive = bank->gc.read_reg(priv->reg_base +
- GIO_EI(bank->id)) & ~mask;
- ilevel = bank->gc.read_reg(priv->reg_base +
- GIO_LEVEL(bank->id)) & ~mask;
+ iedge_config = gpio_generic_read_reg(&bank->chip,
+ priv->reg_base + GIO_EC(bank->id)) & ~mask;
+ iedge_insensitive = gpio_generic_read_reg(&bank->chip,
+ priv->reg_base + GIO_EI(bank->id)) & ~mask;
+ ilevel = gpio_generic_read_reg(&bank->chip,
+ priv->reg_base + GIO_LEVEL(bank->id)) & ~mask;
- bank->gc.write_reg(priv->reg_base + GIO_EC(bank->id),
- iedge_config | edge_config);
- bank->gc.write_reg(priv->reg_base + GIO_EI(bank->id),
- iedge_insensitive | edge_insensitive);
- bank->gc.write_reg(priv->reg_base + GIO_LEVEL(bank->id),
- ilevel | level);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_EC(bank->id),
+ iedge_config | edge_config);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_EI(bank->id),
+ iedge_insensitive | edge_insensitive);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_LEVEL(bank->id),
+ ilevel | level);
- raw_spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags);
return 0;
}
@@ -263,7 +265,7 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
{
struct brcmstb_gpio_priv *priv = bank->parent_priv;
struct irq_domain *domain = priv->irq_domain;
- int hwbase = bank->gc.offset;
+ int hwbase = bank->chip.gc.offset;
unsigned long status;
while ((status = brcmstb_gpio_get_active_irqs(bank))) {
@@ -303,7 +305,7 @@ static struct brcmstb_gpio_bank *brcmstb_gpio_hwirq_to_bank(
/* banks are in descending order */
list_for_each_entry_reverse(bank, &priv->bank_list, node) {
- i += bank->gc.ngpio;
+ i += bank->chip.gc.ngpio;
if (hwirq < i)
return bank;
}
@@ -332,7 +334,7 @@ static int brcmstb_gpio_irq_map(struct irq_domain *d, unsigned int irq,
dev_dbg(&pdev->dev, "Mapping irq %d for gpio line %d (bank %d)\n",
irq, (int)hwirq, bank->id);
- ret = irq_set_chip_data(irq, &bank->gc);
+ ret = irq_set_chip_data(irq, &bank->chip.gc);
if (ret < 0)
return ret;
irq_set_lockdep_class(irq, &brcmstb_gpio_irq_lock_class,
@@ -394,7 +396,7 @@ static void brcmstb_gpio_remove(struct platform_device *pdev)
* more important to actually perform all of the steps.
*/
list_for_each_entry(bank, &priv->bank_list, node)
- gpiochip_remove(&bank->gc);
+ gpiochip_remove(&bank->chip.gc);
}
static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
@@ -412,7 +414,7 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
- offset = gpiospec->args[0] - bank->gc.offset;
+ offset = gpiospec->args[0] - bank->chip.gc.offset;
if (offset >= gc->ngpio || offset < 0)
return -EINVAL;
@@ -493,19 +495,17 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
static void brcmstb_gpio_bank_save(struct brcmstb_gpio_priv *priv,
struct brcmstb_gpio_bank *bank)
{
- struct gpio_chip *gc = &bank->gc;
unsigned int i;
for (i = 0; i < GIO_REG_STAT; i++)
- bank->saved_regs[i] = gc->read_reg(priv->reg_base +
- GIO_BANK_OFF(bank->id, i));
+ bank->saved_regs[i] = gpio_generic_read_reg(&bank->chip,
+ priv->reg_base + GIO_BANK_OFF(bank->id, i));
}
static void brcmstb_gpio_quiesce(struct device *dev, bool save)
{
struct brcmstb_gpio_priv *priv = dev_get_drvdata(dev);
struct brcmstb_gpio_bank *bank;
- struct gpio_chip *gc;
u32 imask;
/* disable non-wake interrupt */
@@ -513,8 +513,6 @@ static void brcmstb_gpio_quiesce(struct device *dev, bool save)
disable_irq(priv->parent_irq);
list_for_each_entry(bank, &priv->bank_list, node) {
- gc = &bank->gc;
-
if (save)
brcmstb_gpio_bank_save(priv, bank);
@@ -523,8 +521,9 @@ static void brcmstb_gpio_quiesce(struct device *dev, bool save)
imask = bank->wake_active;
else
imask = 0;
- gc->write_reg(priv->reg_base + GIO_MASK(bank->id),
- imask);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_MASK(bank->id),
+ imask);
}
}
@@ -538,12 +537,12 @@ static void brcmstb_gpio_shutdown(struct platform_device *pdev)
static void brcmstb_gpio_bank_restore(struct brcmstb_gpio_priv *priv,
struct brcmstb_gpio_bank *bank)
{
- struct gpio_chip *gc = &bank->gc;
unsigned int i;
for (i = 0; i < GIO_REG_STAT; i++)
- gc->write_reg(priv->reg_base + GIO_BANK_OFF(bank->id, i),
- bank->saved_regs[i]);
+ gpio_generic_write_reg(&bank->chip,
+ priv->reg_base + GIO_BANK_OFF(bank->id, i),
+ bank->saved_regs[i]);
}
static int brcmstb_gpio_suspend(struct device *dev)
@@ -585,6 +584,7 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = {
static int brcmstb_gpio_probe(struct platform_device *pdev)
{
+ struct gpio_generic_chip_config config;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
void __iomem *reg_base;
@@ -665,17 +665,24 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
bank->width = bank_width;
}
+ gc = &bank->chip.gc;
+
/*
* Regs are 4 bytes wide, have data reg, no set/clear regs,
* and direction bits have 0 = output and 1 = input
*/
- gc = &bank->gc;
- err = bgpio_init(gc, dev, 4,
- reg_base + GIO_DATA(bank->id),
- NULL, NULL, NULL,
- reg_base + GIO_IODIR(bank->id), flags);
+
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = 4,
+ .dat = reg_base + GIO_DATA(bank->id),
+ .dirin = reg_base + GIO_IODIR(bank->id),
+ .flags = flags,
+ };
+
+ err = gpio_generic_chip_init(&bank->chip, &config);
if (err) {
- dev_err(dev, "bgpio_init() failed\n");
+ dev_err(dev, "failed to initialize generic GPIO chip\n");
goto fail;
}
@@ -700,7 +707,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
* be retained from S5 cold boot
*/
need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank);
- gc->write_reg(reg_base + GIO_MASK(bank->id), 0);
+ gpio_generic_write_reg(&bank->chip,
+ reg_base + GIO_MASK(bank->id), 0);
err = gpiochip_add_data(gc, bank);
if (err) {
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 08/15] gpio: mt7621: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (6 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 07/15] gpio: brcmstb: use new generic GPIO chip API Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-12 9:49 ` Sergio Paracuellos
2025-09-09 9:15 ` [PATCH 09/15] gpio: mt7621: use the generic GPIO chip lock for IRQ handling Bartosz Golaszewski
` (6 subsequent siblings)
14 siblings, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-mt7621.c | 51 +++++++++++++++++++++++++++++-----------------
1 file changed, 32 insertions(+), 19 deletions(-)
diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c
index 93facbebb80efadbdd3fb4500e0db14936287f1a..ed444cc8bc7c2b921be6588ce850027a2e3088b4 100644
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -6,6 +6,7 @@
#include <linux/err.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -30,7 +31,7 @@
struct mtk_gc {
struct irq_chip irq_chip;
- struct gpio_chip chip;
+ struct gpio_generic_chip chip;
spinlock_t lock;
int bank;
u32 rising;
@@ -59,27 +60,29 @@ struct mtk {
static inline struct mtk_gc *
to_mediatek_gpio(struct gpio_chip *chip)
{
- return container_of(chip, struct mtk_gc, chip);
+ struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(chip);
+
+ return container_of(gen_gc, struct mtk_gc, chip);
}
static inline void
mtk_gpio_w32(struct mtk_gc *rg, u32 offset, u32 val)
{
- struct gpio_chip *gc = &rg->chip;
+ struct gpio_chip *gc = &rg->chip.gc;
struct mtk *mtk = gpiochip_get_data(gc);
offset = (rg->bank * GPIO_BANK_STRIDE) + offset;
- gc->write_reg(mtk->base + offset, val);
+ gpio_generic_write_reg(&rg->chip, mtk->base + offset, val);
}
static inline u32
mtk_gpio_r32(struct mtk_gc *rg, u32 offset)
{
- struct gpio_chip *gc = &rg->chip;
+ struct gpio_chip *gc = &rg->chip.gc;
struct mtk *mtk = gpiochip_get_data(gc);
offset = (rg->bank * GPIO_BANK_STRIDE) + offset;
- return gc->read_reg(mtk->base + offset);
+ return gpio_generic_read_reg(&rg->chip, mtk->base + offset);
}
static irqreturn_t
@@ -220,6 +223,7 @@ static const struct irq_chip mt7621_irq_chip = {
static int
mediatek_gpio_bank_probe(struct device *dev, int bank)
{
+ struct gpio_generic_chip_config config;
struct mtk *mtk = dev_get_drvdata(dev);
struct mtk_gc *rg;
void __iomem *dat, *set, *ctrl, *diro;
@@ -236,21 +240,30 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
ctrl = mtk->base + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_STRIDE);
diro = mtk->base + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_STRIDE);
- ret = bgpio_init(&rg->chip, dev, 4, dat, set, ctrl, diro, NULL,
- BGPIOF_NO_SET_ON_INPUT);
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = 4,
+ .dat = dat,
+ .set = set,
+ .clr = ctrl,
+ .dirout = diro,
+ .flags = BGPIOF_NO_SET_ON_INPUT,
+ };
+
+ ret = gpio_generic_chip_init(&rg->chip, &config);
if (ret) {
- dev_err(dev, "bgpio_init() failed\n");
+ dev_err(dev, "failed to initialize generic GPIO chip\n");
return ret;
}
- rg->chip.of_gpio_n_cells = 2;
- rg->chip.of_xlate = mediatek_gpio_xlate;
- rg->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%s-bank%d",
+ rg->chip.gc.of_gpio_n_cells = 2;
+ rg->chip.gc.of_xlate = mediatek_gpio_xlate;
+ rg->chip.gc.label = devm_kasprintf(dev, GFP_KERNEL, "%s-bank%d",
dev_name(dev), bank);
- if (!rg->chip.label)
+ if (!rg->chip.gc.label)
return -ENOMEM;
- rg->chip.offset = bank * MTK_BANK_WIDTH;
+ rg->chip.gc.offset = bank * MTK_BANK_WIDTH;
if (mtk->gpio_irq) {
struct gpio_irq_chip *girq;
@@ -261,7 +274,7 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
*/
ret = devm_request_irq(dev, mtk->gpio_irq,
mediatek_gpio_irq_handler, IRQF_SHARED,
- rg->chip.label, &rg->chip);
+ rg->chip.gc.label, &rg->chip.gc);
if (ret) {
dev_err(dev, "Error requesting IRQ %d: %d\n",
@@ -269,7 +282,7 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
return ret;
}
- girq = &rg->chip.irq;
+ girq = &rg->chip.gc.irq;
gpio_irq_chip_set_chip(girq, &mt7621_irq_chip);
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
@@ -279,17 +292,17 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
girq->handler = handle_simple_irq;
}
- ret = devm_gpiochip_add_data(dev, &rg->chip, mtk);
+ ret = devm_gpiochip_add_data(dev, &rg->chip.gc, mtk);
if (ret < 0) {
dev_err(dev, "Could not register gpio %d, ret=%d\n",
- rg->chip.ngpio, ret);
+ rg->chip.gc.ngpio, ret);
return ret;
}
/* set polarity to low for all gpios */
mtk_gpio_w32(rg, GPIO_REG_POL, 0);
- dev_info(dev, "registering %d gpios\n", rg->chip.ngpio);
+ dev_info(dev, "registering %d gpios\n", rg->chip.gc.ngpio);
return 0;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [PATCH 08/15] gpio: mt7621: use new generic GPIO chip API
2025-09-09 9:15 ` [PATCH 08/15] gpio: mt7621: " Bartosz Golaszewski
@ 2025-09-12 9:49 ` Sergio Paracuellos
0 siblings, 0 replies; 31+ messages in thread
From: Sergio Paracuellos @ 2025-09-12 9:49 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 9, 2025 at 11:50 AM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Convert the driver to using the new generic GPIO chip interfaces from
> linux/gpio/generic.h.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> ---
> drivers/gpio/gpio-mt7621.c | 51 +++++++++++++++++++++++++++++-----------------
> 1 file changed, 32 insertions(+), 19 deletions(-)
Reviewed-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Best regards,
Sergio Paracuellos
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 09/15] gpio: mt7621: use the generic GPIO chip lock for IRQ handling
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (7 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 08/15] gpio: mt7621: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 10/15] gpio: menz127: use new generic GPIO chip API Bartosz Golaszewski
` (5 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This driver uses its own spinlock in interrupt routines while the
generic GPIO chip callbacks use a separate one. This is, of course, racy
so use the fact that the lock in generic GPIO chip is also a spinlock and
convert the interrupt handling functions in this module to using the
provided generic GPIO chip locking API.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-mt7621.c | 29 ++++++++++++-----------------
1 file changed, 12 insertions(+), 17 deletions(-)
diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c
index ed444cc8bc7c2b921be6588ce850027a2e3088b4..31736f12ca100ef615d4aa4b2c968db6b58ef4e1 100644
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -11,7 +11,6 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/spinlock.h>
#define MTK_BANK_CNT 3
#define MTK_BANK_WIDTH 32
@@ -32,7 +31,6 @@
struct mtk_gc {
struct irq_chip irq_chip;
struct gpio_generic_chip chip;
- spinlock_t lock;
int bank;
u32 rising;
u32 falling;
@@ -111,12 +109,12 @@ mediatek_gpio_irq_unmask(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mtk_gc *rg = to_mediatek_gpio(gc);
int pin = d->hwirq;
- unsigned long flags;
u32 rise, fall, high, low;
gpiochip_enable_irq(gc, d->hwirq);
- spin_lock_irqsave(&rg->lock, flags);
+ guard(gpio_generic_lock_irqsave)(&rg->chip);
+
rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
@@ -125,7 +123,6 @@ mediatek_gpio_irq_unmask(struct irq_data *d)
mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(pin) & rg->falling));
mtk_gpio_w32(rg, GPIO_REG_HLVL, high | (BIT(pin) & rg->hlevel));
mtk_gpio_w32(rg, GPIO_REG_LLVL, low | (BIT(pin) & rg->llevel));
- spin_unlock_irqrestore(&rg->lock, flags);
}
static void
@@ -134,19 +131,18 @@ mediatek_gpio_irq_mask(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mtk_gc *rg = to_mediatek_gpio(gc);
int pin = d->hwirq;
- unsigned long flags;
u32 rise, fall, high, low;
- spin_lock_irqsave(&rg->lock, flags);
- rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
- fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
- high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
- low = mtk_gpio_r32(rg, GPIO_REG_LLVL);
- mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(pin));
- mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(pin));
- mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin));
- mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin));
- spin_unlock_irqrestore(&rg->lock, flags);
+ scoped_guard(gpio_generic_lock_irqsave, &rg->chip) {
+ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
+ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
+ high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
+ low = mtk_gpio_r32(rg, GPIO_REG_LLVL);
+ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(pin));
+ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(pin));
+ mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin));
+ mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin));
+ }
gpiochip_disable_irq(gc, d->hwirq);
}
@@ -232,7 +228,6 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
rg = &mtk->gc_map[bank];
memset(rg, 0, sizeof(*rg));
- spin_lock_init(&rg->lock);
rg->bank = bank;
dat = mtk->base + GPIO_REG_DATA + (rg->bank * GPIO_BANK_STRIDE);
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 10/15] gpio: menz127: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (8 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 09/15] gpio: mt7621: use the generic GPIO chip lock for IRQ handling Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 11/15] gpio: sifive: " Bartosz Golaszewski
` (4 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-menz127.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c
index ebe5da4933bce730c70f83c1c0f86fc4a4cc9906..27cdbc36a5fd468dfcf9e0029651c8d22e176f56 100644
--- a/drivers/gpio/gpio-menz127.c
+++ b/drivers/gpio/gpio-menz127.c
@@ -12,6 +12,7 @@
#include <linux/mcb.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#define MEN_Z127_CTRL 0x00
#define MEN_Z127_PSR 0x04
@@ -30,7 +31,7 @@
(db <= MEN_Z127_DB_MAX_US))
struct men_z127_gpio {
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
void __iomem *reg_base;
struct resource *mem;
};
@@ -64,7 +65,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
debounce /= 50;
}
- raw_spin_lock(&gc->bgpio_lock);
+ guard(gpio_generic_lock)(&priv->chip);
db_en = readl(priv->reg_base + MEN_Z127_DBER);
@@ -79,8 +80,6 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
writel(db_en, priv->reg_base + MEN_Z127_DBER);
writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio));
- raw_spin_unlock(&gc->bgpio_lock);
-
return 0;
}
@@ -91,7 +90,8 @@ static int men_z127_set_single_ended(struct gpio_chip *gc,
struct men_z127_gpio *priv = gpiochip_get_data(gc);
u32 od_en;
- raw_spin_lock(&gc->bgpio_lock);
+ guard(gpio_generic_lock)(&priv->chip);
+
od_en = readl(priv->reg_base + MEN_Z127_ODER);
if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
@@ -101,7 +101,6 @@ static int men_z127_set_single_ended(struct gpio_chip *gc,
od_en &= ~BIT(offset);
writel(od_en, priv->reg_base + MEN_Z127_ODER);
- raw_spin_unlock(&gc->bgpio_lock);
return 0;
}
@@ -137,6 +136,7 @@ static void men_z127_release_mem(void *data)
static int men_z127_probe(struct mcb_device *mdev,
const struct mcb_device_id *id)
{
+ struct gpio_generic_chip_config config;
struct men_z127_gpio *men_z127_gpio;
struct device *dev = &mdev->dev;
int ret;
@@ -163,18 +163,21 @@ static int men_z127_probe(struct mcb_device *mdev,
mcb_set_drvdata(mdev, men_z127_gpio);
- ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4,
- men_z127_gpio->reg_base + MEN_Z127_PSR,
- men_z127_gpio->reg_base + MEN_Z127_CTRL,
- NULL,
- men_z127_gpio->reg_base + MEN_Z127_GPIODR,
- NULL, 0);
+ config = (typeof(config)){
+ .dev = &mdev->dev,
+ .sz = 4,
+ .dat = men_z127_gpio->reg_base + MEN_Z127_PSR,
+ .set = men_z127_gpio->reg_base + MEN_Z127_CTRL,
+ .dirout = men_z127_gpio->reg_base + MEN_Z127_GPIODR,
+ };
+
+ ret = gpio_generic_chip_init(&men_z127_gpio->chip, &config);
if (ret)
return ret;
- men_z127_gpio->gc.set_config = men_z127_set_config;
+ men_z127_gpio->chip.gc.set_config = men_z127_set_config;
- ret = devm_gpiochip_add_data(dev, &men_z127_gpio->gc, men_z127_gpio);
+ ret = devm_gpiochip_add_data(dev, &men_z127_gpio->chip.gc, men_z127_gpio);
if (ret)
return dev_err_probe(dev, ret,
"failed to register MEN 16Z127 GPIO controller");
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 11/15] gpio: sifive: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (9 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 10/15] gpio: menz127: use new generic GPIO chip API Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 12/15] gpio: spacemit-k1: " Bartosz Golaszewski
` (3 subsequent siblings)
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-sifive.c | 73 ++++++++++++++++++++++++----------------------
1 file changed, 38 insertions(+), 35 deletions(-)
diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index 98ef975c44d9a6c9238605cfd1d5820fd70a66ca..07ee5c0b4f8023978c76873f25119d5dc21d996c 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/property.h>
@@ -32,7 +33,7 @@
struct sifive_gpio {
void __iomem *base;
- struct gpio_chip gc;
+ struct gpio_generic_chip gen_gc;
struct regmap *regs;
unsigned long irq_state;
unsigned int trigger[SIFIVE_GPIO_MAX];
@@ -41,10 +42,10 @@ struct sifive_gpio {
static void sifive_gpio_set_ie(struct sifive_gpio *chip, unsigned int offset)
{
- unsigned long flags;
unsigned int trigger;
- raw_spin_lock_irqsave(&chip->gc.bgpio_lock, flags);
+ guard(gpio_generic_lock_irqsave)(&chip->gen_gc);
+
trigger = (chip->irq_state & BIT(offset)) ? chip->trigger[offset] : 0;
regmap_update_bits(chip->regs, SIFIVE_GPIO_RISE_IE, BIT(offset),
(trigger & IRQ_TYPE_EDGE_RISING) ? BIT(offset) : 0);
@@ -54,7 +55,6 @@ static void sifive_gpio_set_ie(struct sifive_gpio *chip, unsigned int offset)
(trigger & IRQ_TYPE_LEVEL_HIGH) ? BIT(offset) : 0);
regmap_update_bits(chip->regs, SIFIVE_GPIO_LOW_IE, BIT(offset),
(trigger & IRQ_TYPE_LEVEL_LOW) ? BIT(offset) : 0);
- raw_spin_unlock_irqrestore(&chip->gc.bgpio_lock, flags);
}
static int sifive_gpio_irq_set_type(struct irq_data *d, unsigned int trigger)
@@ -72,13 +72,12 @@ static int sifive_gpio_irq_set_type(struct irq_data *d, unsigned int trigger)
}
static void sifive_gpio_irq_enable(struct irq_data *d)
-{
+ {
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sifive_gpio *chip = gpiochip_get_data(gc);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
int offset = hwirq % SIFIVE_GPIO_MAX;
u32 bit = BIT(offset);
- unsigned long flags;
gpiochip_enable_irq(gc, hwirq);
irq_chip_enable_parent(d);
@@ -86,13 +85,13 @@ static void sifive_gpio_irq_enable(struct irq_data *d)
/* Switch to input */
gc->direction_input(gc, offset);
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
- /* Clear any sticky pending interrupts */
- regmap_write(chip->regs, SIFIVE_GPIO_RISE_IP, bit);
- regmap_write(chip->regs, SIFIVE_GPIO_FALL_IP, bit);
- regmap_write(chip->regs, SIFIVE_GPIO_HIGH_IP, bit);
- regmap_write(chip->regs, SIFIVE_GPIO_LOW_IP, bit);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ scoped_guard(gpio_generic_lock_irqsave, &chip->gen_gc) {
+ /* Clear any sticky pending interrupts */
+ regmap_write(chip->regs, SIFIVE_GPIO_RISE_IP, bit);
+ regmap_write(chip->regs, SIFIVE_GPIO_FALL_IP, bit);
+ regmap_write(chip->regs, SIFIVE_GPIO_HIGH_IP, bit);
+ regmap_write(chip->regs, SIFIVE_GPIO_LOW_IP, bit);
+ }
/* Enable interrupts */
assign_bit(offset, &chip->irq_state, 1);
@@ -118,15 +117,14 @@ static void sifive_gpio_irq_eoi(struct irq_data *d)
struct sifive_gpio *chip = gpiochip_get_data(gc);
int offset = irqd_to_hwirq(d) % SIFIVE_GPIO_MAX;
u32 bit = BIT(offset);
- unsigned long flags;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
- /* Clear all pending interrupts */
- regmap_write(chip->regs, SIFIVE_GPIO_RISE_IP, bit);
- regmap_write(chip->regs, SIFIVE_GPIO_FALL_IP, bit);
- regmap_write(chip->regs, SIFIVE_GPIO_HIGH_IP, bit);
- regmap_write(chip->regs, SIFIVE_GPIO_LOW_IP, bit);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ scoped_guard(gpio_generic_lock_irqsave, &chip->gen_gc) {
+ /* Clear all pending interrupts */
+ regmap_write(chip->regs, SIFIVE_GPIO_RISE_IP, bit);
+ regmap_write(chip->regs, SIFIVE_GPIO_FALL_IP, bit);
+ regmap_write(chip->regs, SIFIVE_GPIO_HIGH_IP, bit);
+ regmap_write(chip->regs, SIFIVE_GPIO_LOW_IP, bit);
+ }
irq_chip_eoi_parent(d);
}
@@ -179,6 +177,7 @@ static const struct regmap_config sifive_gpio_regmap_config = {
static int sifive_gpio_probe(struct platform_device *pdev)
{
+ struct gpio_generic_chip_config config;
struct device *dev = &pdev->dev;
struct irq_domain *parent;
struct gpio_irq_chip *girq;
@@ -217,13 +216,17 @@ static int sifive_gpio_probe(struct platform_device *pdev)
*/
parent = irq_get_irq_data(chip->irq_number[0])->domain;
- ret = bgpio_init(&chip->gc, dev, 4,
- chip->base + SIFIVE_GPIO_INPUT_VAL,
- chip->base + SIFIVE_GPIO_OUTPUT_VAL,
- NULL,
- chip->base + SIFIVE_GPIO_OUTPUT_EN,
- chip->base + SIFIVE_GPIO_INPUT_EN,
- BGPIOF_READ_OUTPUT_REG_SET);
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = 4,
+ .dat = chip->base + SIFIVE_GPIO_INPUT_VAL,
+ .set = chip->base + SIFIVE_GPIO_OUTPUT_VAL,
+ .dirout = chip->base + SIFIVE_GPIO_OUTPUT_EN,
+ .dirin = chip->base + SIFIVE_GPIO_INPUT_EN,
+ .flags = BGPIOF_READ_OUTPUT_REG_SET,
+ };
+
+ ret = gpio_generic_chip_init(&chip->gen_gc, &config);
if (ret) {
dev_err(dev, "unable to init generic GPIO\n");
return ret;
@@ -236,12 +239,12 @@ static int sifive_gpio_probe(struct platform_device *pdev)
regmap_write(chip->regs, SIFIVE_GPIO_LOW_IE, 0);
chip->irq_state = 0;
- chip->gc.base = -1;
- chip->gc.ngpio = ngpio;
- chip->gc.label = dev_name(dev);
- chip->gc.parent = dev;
- chip->gc.owner = THIS_MODULE;
- girq = &chip->gc.irq;
+ chip->gen_gc.gc.base = -1;
+ chip->gen_gc.gc.ngpio = ngpio;
+ chip->gen_gc.gc.label = dev_name(dev);
+ chip->gen_gc.gc.parent = dev;
+ chip->gen_gc.gc.owner = THIS_MODULE;
+ girq = &chip->gen_gc.gc.irq;
gpio_irq_chip_set_chip(girq, &sifive_gpio_irqchip);
girq->fwnode = dev_fwnode(dev);
girq->parent_domain = parent;
@@ -249,7 +252,7 @@ static int sifive_gpio_probe(struct platform_device *pdev)
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
- return gpiochip_add_data(&chip->gc, chip);
+ return gpiochip_add_data(&chip->gen_gc.gc, chip);
}
static const struct of_device_id sifive_gpio_match[] = {
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 12/15] gpio: spacemit-k1: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (10 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 11/15] gpio: sifive: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:39 ` Yixun Lan
2025-09-09 9:15 ` [PATCH 13/15] gpio: sodaville: " Bartosz Golaszewski
` (2 subsequent siblings)
14 siblings, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-spacemit-k1.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
index 3cc75c701ec40194e602b80d3f96f23204ce3b4d..9e57f43d3d13ad28fcd3327ecdc3f359691a44c9 100644
--- a/drivers/gpio/gpio-spacemit-k1.c
+++ b/drivers/gpio/gpio-spacemit-k1.c
@@ -6,6 +6,7 @@
#include <linux/clk.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -38,7 +39,7 @@
struct spacemit_gpio;
struct spacemit_gpio_bank {
- struct gpio_chip gc;
+ struct gpio_generic_chip chip;
struct spacemit_gpio *sg;
void __iomem *base;
u32 irq_mask;
@@ -72,7 +73,7 @@ static irqreturn_t spacemit_gpio_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
for_each_set_bit(n, &pending, BITS_PER_LONG)
- handle_nested_irq(irq_find_mapping(gb->gc.irq.domain, n));
+ handle_nested_irq(irq_find_mapping(gb->chip.gc.irq.domain, n));
return IRQ_HANDLED;
}
@@ -143,7 +144,7 @@ static void spacemit_gpio_irq_print_chip(struct irq_data *data, struct seq_file
{
struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(data);
- seq_printf(p, "%s-%d", dev_name(gb->gc.parent), spacemit_gpio_bank_index(gb));
+ seq_printf(p, "%s-%d", dev_name(gb->chip.gc.parent), spacemit_gpio_bank_index(gb));
}
static struct irq_chip spacemit_gpio_chip = {
@@ -165,7 +166,7 @@ static bool spacemit_of_node_instance_match(struct gpio_chip *gc, unsigned int i
if (i >= SPACEMIT_NR_BANKS)
return false;
- return (gc == &sg->sgb[i].gc);
+ return (gc == &sg->sgb[i].chip.gc);
}
static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
@@ -173,7 +174,8 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
int index, int irq)
{
struct spacemit_gpio_bank *gb = &sg->sgb[index];
- struct gpio_chip *gc = &gb->gc;
+ struct gpio_generic_chip_config config;
+ struct gpio_chip *gc = &gb->chip.gc;
struct device *dev = sg->dev;
struct gpio_irq_chip *girq;
void __iomem *dat, *set, *clr, *dirin, *dirout;
@@ -187,9 +189,19 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
dirin = gb->base + SPACEMIT_GCDR;
dirout = gb->base + SPACEMIT_GSDR;
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = 4,
+ .dat = dat,
+ .set = set,
+ .clr = clr,
+ .dirout = dirout,
+ .dirin = dirin,
+ .flags = BGPIOF_UNREADABLE_REG_SET | BGPIOF_UNREADABLE_REG_DIR,
+ };
+
/* This registers 32 GPIO lines per bank */
- ret = bgpio_init(gc, dev, 4, dat, set, clr, dirout, dirin,
- BGPIOF_UNREADABLE_REG_SET | BGPIOF_UNREADABLE_REG_DIR);
+ ret = gpio_generic_chip_init(&gb->chip, &config);
if (ret)
return dev_err_probe(dev, ret, "failed to init gpio chip\n");
@@ -221,7 +233,7 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
ret = devm_request_threaded_irq(dev, irq, NULL,
spacemit_gpio_irq_handler,
IRQF_ONESHOT | IRQF_SHARED,
- gb->gc.label, gb);
+ gb->chip.gc.label, gb);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to register IRQ\n");
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [PATCH 12/15] gpio: spacemit-k1: use new generic GPIO chip API
2025-09-09 9:15 ` [PATCH 12/15] gpio: spacemit-k1: " Bartosz Golaszewski
@ 2025-09-09 9:39 ` Yixun Lan
0 siblings, 0 replies; 31+ messages in thread
From: Yixun Lan @ 2025-09-09 9:39 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Andy Shevchenko, linux-gpio, linux-kernel,
linux-mips, linux-arm-kernel, linux-mediatek, linux-riscv,
spacemit, Bartosz Golaszewski
On 11:15 Tue 09 Sep , Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Convert the driver to using the new generic GPIO chip interfaces from
> linux/gpio/generic.h.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Thanks for converting this
Reviewed-by: Yixun Lan <dlan@gentoo.org>
> ---
> drivers/gpio/gpio-spacemit-k1.c | 28 ++++++++++++++++++++--------
> 1 file changed, 20 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
> index 3cc75c701ec40194e602b80d3f96f23204ce3b4d..9e57f43d3d13ad28fcd3327ecdc3f359691a44c9 100644
> --- a/drivers/gpio/gpio-spacemit-k1.c
> +++ b/drivers/gpio/gpio-spacemit-k1.c
> @@ -6,6 +6,7 @@
>
> #include <linux/clk.h>
> #include <linux/gpio/driver.h>
> +#include <linux/gpio/generic.h>
> #include <linux/init.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> @@ -38,7 +39,7 @@
> struct spacemit_gpio;
>
> struct spacemit_gpio_bank {
> - struct gpio_chip gc;
> + struct gpio_generic_chip chip;
> struct spacemit_gpio *sg;
> void __iomem *base;
> u32 irq_mask;
> @@ -72,7 +73,7 @@ static irqreturn_t spacemit_gpio_irq_handler(int irq, void *dev_id)
> return IRQ_NONE;
>
> for_each_set_bit(n, &pending, BITS_PER_LONG)
> - handle_nested_irq(irq_find_mapping(gb->gc.irq.domain, n));
> + handle_nested_irq(irq_find_mapping(gb->chip.gc.irq.domain, n));
>
> return IRQ_HANDLED;
> }
> @@ -143,7 +144,7 @@ static void spacemit_gpio_irq_print_chip(struct irq_data *data, struct seq_file
> {
> struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(data);
>
> - seq_printf(p, "%s-%d", dev_name(gb->gc.parent), spacemit_gpio_bank_index(gb));
> + seq_printf(p, "%s-%d", dev_name(gb->chip.gc.parent), spacemit_gpio_bank_index(gb));
> }
>
> static struct irq_chip spacemit_gpio_chip = {
> @@ -165,7 +166,7 @@ static bool spacemit_of_node_instance_match(struct gpio_chip *gc, unsigned int i
> if (i >= SPACEMIT_NR_BANKS)
> return false;
>
> - return (gc == &sg->sgb[i].gc);
> + return (gc == &sg->sgb[i].chip.gc);
> }
>
> static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
> @@ -173,7 +174,8 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
> int index, int irq)
> {
> struct spacemit_gpio_bank *gb = &sg->sgb[index];
> - struct gpio_chip *gc = &gb->gc;
> + struct gpio_generic_chip_config config;
> + struct gpio_chip *gc = &gb->chip.gc;
> struct device *dev = sg->dev;
> struct gpio_irq_chip *girq;
> void __iomem *dat, *set, *clr, *dirin, *dirout;
> @@ -187,9 +189,19 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
> dirin = gb->base + SPACEMIT_GCDR;
> dirout = gb->base + SPACEMIT_GSDR;
>
> + config = (typeof(config)){
> + .dev = dev,
> + .sz = 4,
> + .dat = dat,
> + .set = set,
> + .clr = clr,
> + .dirout = dirout,
> + .dirin = dirin,
> + .flags = BGPIOF_UNREADABLE_REG_SET | BGPIOF_UNREADABLE_REG_DIR,
> + };
> +
> /* This registers 32 GPIO lines per bank */
> - ret = bgpio_init(gc, dev, 4, dat, set, clr, dirout, dirin,
> - BGPIOF_UNREADABLE_REG_SET | BGPIOF_UNREADABLE_REG_DIR);
> + ret = gpio_generic_chip_init(&gb->chip, &config);
> if (ret)
> return dev_err_probe(dev, ret, "failed to init gpio chip\n");
>
> @@ -221,7 +233,7 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
> ret = devm_request_threaded_irq(dev, irq, NULL,
> spacemit_gpio_irq_handler,
> IRQF_ONESHOT | IRQF_SHARED,
> - gb->gc.label, gb);
> + gb->chip.gc.label, gb);
> if (ret < 0)
> return dev_err_probe(dev, ret, "failed to register IRQ\n");
>
>
> --
> 2.48.1
>
--
Yixun Lan (dlan)
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (11 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 12/15] gpio: spacemit-k1: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 11:31 ` Andy Shevchenko
2025-09-09 9:15 ` [PATCH 14/15] gpio: mmio: " Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 15/15] gpio: move gpio-mmio-specific fields out of struct gpio_chip Bartosz Golaszewski
14 siblings, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-sodaville.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index abd13c79ace09db228e975f93c92e727d3864ef8..6bc224d3a561077bf3438a70591e1f313ac834f3 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -39,7 +40,7 @@ struct sdv_gpio_chip_data {
void __iomem *gpio_pub_base;
struct irq_domain *id;
struct irq_chip_generic *gc;
- struct gpio_chip chip;
+ struct gpio_generic_chip gen_gc;
};
static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
@@ -180,6 +181,7 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
static int sdv_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
+ struct gpio_generic_chip_config config;
struct sdv_gpio_chip_data *sd;
int ret;
u32 mux_val;
@@ -206,15 +208,21 @@ static int sdv_gpio_probe(struct pci_dev *pdev,
if (!ret)
writel(mux_val, sd->gpio_pub_base + GPMUXCTL);
- ret = bgpio_init(&sd->chip, &pdev->dev, 4,
- sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR,
- NULL, sd->gpio_pub_base + GPOER, NULL, 0);
+ config = (typeof(config)){
+ .dev = &pdev->dev,
+ .sz = 4,
+ .dat = sd->gpio_pub_base + GPINR,
+ .set = sd->gpio_pub_base + GPOUTR,
+ .dirout = sd->gpio_pub_base + GPOER,
+ };
+
+ ret = gpio_generic_chip_init(&sd->gen_gc, &config);
if (ret)
return ret;
- sd->chip.ngpio = SDV_NUM_PUB_GPIOS;
+ sd->gen_gc.gc.ngpio = SDV_NUM_PUB_GPIOS;
- ret = devm_gpiochip_add_data(&pdev->dev, &sd->chip, sd);
+ ret = devm_gpiochip_add_data(&pdev->dev, &sd->gen_gc.gc, sd);
if (ret < 0) {
dev_err(&pdev->dev, "gpiochip_add() failed.\n");
return ret;
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 9:15 ` [PATCH 13/15] gpio: sodaville: " Bartosz Golaszewski
@ 2025-09-09 11:31 ` Andy Shevchenko
2025-09-09 11:35 ` Bartosz Golaszewski
0 siblings, 1 reply; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 11:31 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
>
> Convert the driver to using the new generic GPIO chip interfaces from
> linux/gpio/generic.h.
...
> + config = (typeof(config)){
This looks unusual. Why can't properly formed compound literal be used as in
many other places in the kernel?
> + .dev = &pdev->dev,
> + .sz = 4,
> + .dat = sd->gpio_pub_base + GPINR,
> + .set = sd->gpio_pub_base + GPOUTR,
> + .dirout = sd->gpio_pub_base + GPOER,
> + };
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 11:31 ` Andy Shevchenko
@ 2025-09-09 11:35 ` Bartosz Golaszewski
2025-09-09 13:13 ` Andy Shevchenko
0 siblings, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 11:35 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 9, 2025 at 1:31 PM Andy Shevchenko
<andriy.shevchenko@intel.com> wrote:
>
> On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
> >
> > Convert the driver to using the new generic GPIO chip interfaces from
> > linux/gpio/generic.h.
>
> ...
>
> > + config = (typeof(config)){
>
> This looks unusual. Why can't properly formed compound literal be used as in
> many other places in the kernel?
>
It is correct C and checkpatch doesn't raise any warnings. It's the
same kind of argument as between kmalloc(sizeof(struct foo)) vs
kmalloc(sizeof(f)).
I guess it's personal taste but I like this version better.
Bartosz
> > + .dev = &pdev->dev,
> > + .sz = 4,
> > + .dat = sd->gpio_pub_base + GPINR,
> > + .set = sd->gpio_pub_base + GPOUTR,
> > + .dirout = sd->gpio_pub_base + GPOER,
> > + };
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 11:35 ` Bartosz Golaszewski
@ 2025-09-09 13:13 ` Andy Shevchenko
2025-09-09 13:24 ` Bartosz Golaszewski
0 siblings, 1 reply; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 13:13 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 09, 2025 at 01:35:04PM +0200, Bartosz Golaszewski wrote:
> On Tue, Sep 9, 2025 at 1:31 PM Andy Shevchenko
> <andriy.shevchenko@intel.com> wrote:
> > On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
...
> > > + config = (typeof(config)){
> >
> > This looks unusual. Why can't properly formed compound literal be used as in
> > many other places in the kernel?
>
> It is correct C
If it compiles, it doesn't mean it's correct C, it might be non-standard.
Have you checked with the standard (note, I read that part in the past,
but I may forgot the details, so I don't know the answer to this)?
> and checkpatch doesn't raise any warnings.
checkpatch is far from being useful in the questions like this.
It false positively complains for for_each*() macros all over
the kernel, for example.
> It's the
> same kind of argument as between kmalloc(sizeof(struct foo)) vs
> kmalloc(sizeof(f)).
Maybe, but it introduces a new style while all other cases use the other,
_established_ style. So we have a precedent and the form the code is written
in is against the de facto usage of the compound literals.
> I guess it's personal taste but I like this version better.
In kernel we also try to be consistent. This add inconsistency. Am I wrong?
> > > + .dev = &pdev->dev,
> > > + .sz = 4,
> > > + .dat = sd->gpio_pub_base + GPINR,
> > > + .set = sd->gpio_pub_base + GPOUTR,
> > > + .dirout = sd->gpio_pub_base + GPOER,
> > > + };
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 13:13 ` Andy Shevchenko
@ 2025-09-09 13:24 ` Bartosz Golaszewski
2025-09-09 13:45 ` Andy Shevchenko
0 siblings, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 13:24 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski, Bartosz Golaszewski
On Tue, 9 Sep 2025 15:13:04 +0200, Andy Shevchenko
<andriy.shevchenko@intel.com> said:
> On Tue, Sep 09, 2025 at 01:35:04PM +0200, Bartosz Golaszewski wrote:
>> On Tue, Sep 9, 2025 at 1:31 PM Andy Shevchenko
>> <andriy.shevchenko@intel.com> wrote:
>> > On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
>
> ...
>
>> > > + config = (typeof(config)){
>> >
>> > This looks unusual. Why can't properly formed compound literal be used as in
>> > many other places in the kernel?
>>
>> It is correct C
>
> If it compiles, it doesn't mean it's correct C, it might be non-standard.
> Have you checked with the standard (note, I read that part in the past,
> but I may forgot the details, so I don't know the answer to this)?
>
It's a GNU extension alright but it's supported in the kernel as it evaluates
to a simple cast.
>> and checkpatch doesn't raise any warnings.
>
> checkpatch is far from being useful in the questions like this.
> It false positively complains for for_each*() macros all over
> the kernel, for example.
>
>> It's the
>> same kind of argument as between kmalloc(sizeof(struct foo)) vs
>> kmalloc(sizeof(f)).
>
> Maybe, but it introduces a new style while all other cases use the other,
> _established_ style. So we have a precedent and the form the code is written
> in is against the de facto usage of the compound literals.
>
It may not be *very* common but it's hardly new style:
$ git grep -P "\(typeof\(.*\)\) ?\{" | wc
108 529 7315
Bart
>> I guess it's personal taste but I like this version better.
>
> In kernel we also try to be consistent. This add inconsistency. Am I wrong?
>
>> > > + .dev = &pdev->dev,
>> > > + .sz = 4,
>> > > + .dat = sd->gpio_pub_base + GPINR,
>> > > + .set = sd->gpio_pub_base + GPOUTR,
>> > > + .dirout = sd->gpio_pub_base + GPOER,
>> > > + };
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
>
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 13:24 ` Bartosz Golaszewski
@ 2025-09-09 13:45 ` Andy Shevchenko
2025-09-09 13:47 ` Andy Shevchenko
0 siblings, 1 reply; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 13:45 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 09, 2025 at 08:24:23AM -0500, Bartosz Golaszewski wrote:
> On Tue, 9 Sep 2025 15:13:04 +0200, Andy Shevchenko
> <andriy.shevchenko@intel.com> said:
> > On Tue, Sep 09, 2025 at 01:35:04PM +0200, Bartosz Golaszewski wrote:
> >> On Tue, Sep 9, 2025 at 1:31 PM Andy Shevchenko
> >> <andriy.shevchenko@intel.com> wrote:
> >> > On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
...
> >> > > + config = (typeof(config)){
> >> >
> >> > This looks unusual. Why can't properly formed compound literal be used as in
> >> > many other places in the kernel?
> >>
> >> It is correct C
> >
> > If it compiles, it doesn't mean it's correct C, it might be non-standard.
> > Have you checked with the standard (note, I read that part in the past,
> > but I may forgot the details, so I don't know the answer to this)?
>
> It's a GNU extension alright
clang, I suppose, also okay with this?
> but it's supported in the kernel as it evaluates
> to a simple cast.
There is no cast. And that's make a big difference to what the code tries to do.
> >> and checkpatch doesn't raise any warnings.
> >
> > checkpatch is far from being useful in the questions like this.
> > It false positively complains for for_each*() macros all over
> > the kernel, for example.
> >
> >> It's the
> >> same kind of argument as between kmalloc(sizeof(struct foo)) vs
> >> kmalloc(sizeof(f)).
> >
> > Maybe, but it introduces a new style while all other cases use the other,
> > _established_ style. So we have a precedent and the form the code is written
> > in is against the de facto usage of the compound literals.
>
> It may not be *very* common but it's hardly new style:
I think your statement is incorrect see below why.
> $ git grep -P "\(typeof\(.*\)\) ?\{" | wc
> 108 529 7315
Not correct. The correct output will be closer to
$ git grep -l -P "\(typeof\(.*\)\) ?\{" | wc -l
15
And if you looked at the output carefully, you see the bug in the RE you used.
So, even closer will be this one:
$ git grep -l -P "=[[:space:]]+\(typeof\(.*\)\) ?\{" | wc -l
7
2 out of which are related to libeth, effectively makes this 6.
No, this is completely non-standard and unusual thing in the kernel.
> >> I guess it's personal taste but I like this version better.
> >
> > In kernel we also try to be consistent. This add inconsistency. Am I wrong?
> >
> >> > > + .dev = &pdev->dev,
> >> > > + .sz = 4,
> >> > > + .dat = sd->gpio_pub_base + GPINR,
> >> > > + .set = sd->gpio_pub_base + GPOUTR,
> >> > > + .dirout = sd->gpio_pub_base + GPOER,
> >> > > + };
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 13:45 ` Andy Shevchenko
@ 2025-09-09 13:47 ` Andy Shevchenko
2025-09-09 13:56 ` Andy Shevchenko
2025-09-09 13:56 ` Bartosz Golaszewski
0 siblings, 2 replies; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 13:47 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 09, 2025 at 04:45:31PM +0300, Andy Shevchenko wrote:
> On Tue, Sep 09, 2025 at 08:24:23AM -0500, Bartosz Golaszewski wrote:
> > On Tue, 9 Sep 2025 15:13:04 +0200, Andy Shevchenko
> > <andriy.shevchenko@intel.com> said:
> > > On Tue, Sep 09, 2025 at 01:35:04PM +0200, Bartosz Golaszewski wrote:
> > >> On Tue, Sep 9, 2025 at 1:31 PM Andy Shevchenko
> > >> <andriy.shevchenko@intel.com> wrote:
> > >> > On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
...
> > >> > > + config = (typeof(config)){
> > >> >
> > >> > This looks unusual. Why can't properly formed compound literal be used as in
> > >> > many other places in the kernel?
> > >>
> > >> It is correct C
> > >
> > > If it compiles, it doesn't mean it's correct C, it might be non-standard.
> > > Have you checked with the standard (note, I read that part in the past,
> > > but I may forgot the details, so I don't know the answer to this)?
> >
> > It's a GNU extension alright
>
> clang, I suppose, also okay with this?
>
> > but it's supported in the kernel as it evaluates
> > to a simple cast.
>
> There is no cast. And that's make a big difference to what the code tries to do.
>
> > >> and checkpatch doesn't raise any warnings.
> > >
> > > checkpatch is far from being useful in the questions like this.
> > > It false positively complains for for_each*() macros all over
> > > the kernel, for example.
> > >
> > >> It's the
> > >> same kind of argument as between kmalloc(sizeof(struct foo)) vs
> > >> kmalloc(sizeof(f)).
> > >
> > > Maybe, but it introduces a new style while all other cases use the other,
> > > _established_ style. So we have a precedent and the form the code is written
> > > in is against the de facto usage of the compound literals.
> >
> > It may not be *very* common but it's hardly new style:
>
> I think your statement is incorrect see below why.
>
> > $ git grep -P "\(typeof\(.*\)\) ?\{" | wc
> > 108 529 7315
>
> Not correct. The correct output will be closer to
>
> $ git grep -l -P "\(typeof\(.*\)\) ?\{" | wc -l
> 15
>
> And if you looked at the output carefully, you see the bug in the RE you used.
>
> So, even closer will be this one:
>
> $ git grep -l -P "=[[:space:]]+\(typeof\(.*\)\) ?\{" | wc -l
> 7
>
> 2 out of which are related to libeth, effectively makes this 6.
TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
literal as a cast. Which is not!
> No, this is completely non-standard and unusual thing in the kernel.
>
> > >> I guess it's personal taste but I like this version better.
> > >
> > > In kernel we also try to be consistent. This add inconsistency. Am I wrong?
> > >
> > >> > > + .dev = &pdev->dev,
> > >> > > + .sz = 4,
> > >> > > + .dat = sd->gpio_pub_base + GPINR,
> > >> > > + .set = sd->gpio_pub_base + GPOUTR,
> > >> > > + .dirout = sd->gpio_pub_base + GPOER,
> > >> > > + };
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 13:47 ` Andy Shevchenko
@ 2025-09-09 13:56 ` Andy Shevchenko
2025-09-09 13:56 ` Bartosz Golaszewski
1 sibling, 0 replies; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 13:56 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 09, 2025 at 04:47:09PM +0300, Andy Shevchenko wrote:
> On Tue, Sep 09, 2025 at 04:45:31PM +0300, Andy Shevchenko wrote:
> > On Tue, Sep 09, 2025 at 08:24:23AM -0500, Bartosz Golaszewski wrote:
> > > On Tue, 9 Sep 2025 15:13:04 +0200, Andy Shevchenko
> > > <andriy.shevchenko@intel.com> said:
> > > > On Tue, Sep 09, 2025 at 01:35:04PM +0200, Bartosz Golaszewski wrote:
> > > >> On Tue, Sep 9, 2025 at 1:31 PM Andy Shevchenko
> > > >> <andriy.shevchenko@intel.com> wrote:
> > > >> > On Tue, Sep 09, 2025 at 11:15:40AM +0200, Bartosz Golaszewski wrote:
...
> > > >> > > + config = (typeof(config)){
> > > >> >
> > > >> > This looks unusual. Why can't properly formed compound literal be used as in
> > > >> > many other places in the kernel?
> > > >>
> > > >> It is correct C
> > > >
> > > > If it compiles, it doesn't mean it's correct C, it might be non-standard.
> > > > Have you checked with the standard (note, I read that part in the past,
> > > > but I may forgot the details, so I don't know the answer to this)?
> > >
> > > It's a GNU extension alright
> >
> > clang, I suppose, also okay with this?
> >
> > > but it's supported in the kernel as it evaluates
> > > to a simple cast.
> >
> > There is no cast. And that's make a big difference to what the code tries to do.
> >
> > > >> and checkpatch doesn't raise any warnings.
> > > >
> > > > checkpatch is far from being useful in the questions like this.
> > > > It false positively complains for for_each*() macros all over
> > > > the kernel, for example.
> > > >
> > > >> It's the
> > > >> same kind of argument as between kmalloc(sizeof(struct foo)) vs
> > > >> kmalloc(sizeof(f)).
> > > >
> > > > Maybe, but it introduces a new style while all other cases use the other,
> > > > _established_ style. So we have a precedent and the form the code is written
> > > > in is against the de facto usage of the compound literals.
> > >
> > > It may not be *very* common but it's hardly new style:
> >
> > I think your statement is incorrect see below why.
> >
> > > $ git grep -P "\(typeof\(.*\)\) ?\{" | wc
> > > 108 529 7315
> >
> > Not correct. The correct output will be closer to
> >
> > $ git grep -l -P "\(typeof\(.*\)\) ?\{" | wc -l
> > 15
> >
> > And if you looked at the output carefully, you see the bug in the RE you used.
> >
> > So, even closer will be this one:
> >
> > $ git grep -l -P "=[[:space:]]+\(typeof\(.*\)\) ?\{" | wc -l
> > 7
> >
> > 2 out of which are related to libeth, effectively makes this 6.
And for of fullness the picture:
$ git grep -l -P "=[[:space:]]+\(struct [^[:space:]]*\) ?\{" | wc -l
501
So, it's 1:100 ratio.
> TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> literal as a cast. Which is not!
>
> > No, this is completely non-standard and unusual thing in the kernel.
> >
> > > >> I guess it's personal taste but I like this version better.
> > > >
> > > > In kernel we also try to be consistent. This add inconsistency. Am I wrong?
> > > >
> > > >> > > + .dev = &pdev->dev,
> > > >> > > + .sz = 4,
> > > >> > > + .dat = sd->gpio_pub_base + GPINR,
> > > >> > > + .set = sd->gpio_pub_base + GPOUTR,
> > > >> > > + .dirout = sd->gpio_pub_base + GPOER,
> > > >> > > + };
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 13:47 ` Andy Shevchenko
2025-09-09 13:56 ` Andy Shevchenko
@ 2025-09-09 13:56 ` Bartosz Golaszewski
2025-09-09 14:02 ` Andy Shevchenko
1 sibling, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 13:56 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 9, 2025 at 3:47 PM Andy Shevchenko
<andriy.shevchenko@intel.com> wrote:
>
> TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> literal as a cast. Which is not!
>
What do you suggest?
And are we not allowed to use C99 features now anyway?
Bartosz
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 13:56 ` Bartosz Golaszewski
@ 2025-09-09 14:02 ` Andy Shevchenko
2025-09-09 14:05 ` Bartosz Golaszewski
0 siblings, 1 reply; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 14:02 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 09, 2025 at 03:56:41PM +0200, Bartosz Golaszewski wrote:
> On Tue, Sep 9, 2025 at 3:47 PM Andy Shevchenko
> <andriy.shevchenko@intel.com> wrote:
> >
> > TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> > literal as a cast. Which is not!
>
> What do you suggest?
Write it in less odd way :-)
foo = (struct bar) { ... };
> And are we not allowed to use C99 features now anyway?
It's fine, it's not about the C standard number.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 14:02 ` Andy Shevchenko
@ 2025-09-09 14:05 ` Bartosz Golaszewski
2025-09-09 15:15 ` Andy Shevchenko
0 siblings, 1 reply; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 14:05 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Linus Walleij, Keguang Zhang, Alban Bedel, Doug Berger,
Florian Fainelli, Broadcom internal kernel review list,
Matthias Brugger, AngeloGioacchino Del Regno, Paul Walmsley,
Samuel Holland, Yixun Lan, Andy Shevchenko, linux-gpio,
linux-kernel, linux-mips, linux-arm-kernel, linux-mediatek,
linux-riscv, spacemit, Bartosz Golaszewski
On Tue, Sep 9, 2025 at 4:02 PM Andy Shevchenko
<andriy.shevchenko@intel.com> wrote:
>
> On Tue, Sep 09, 2025 at 03:56:41PM +0200, Bartosz Golaszewski wrote:
> > On Tue, Sep 9, 2025 at 3:47 PM Andy Shevchenko
> > <andriy.shevchenko@intel.com> wrote:
> > >
> > > TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> > > literal as a cast. Which is not!
> >
> > What do you suggest?
>
> Write it in less odd way :-)
>
> foo = (struct bar) { ... };
I don't get your reasoning. typeof() itself is well established in the
kernel and doesn't
foo = (struct bar){ ... };
evaluate to the same thing as
foo = (typeof(foo)){ ... };
? Isn't it still the same compound literal?
Bartosz
>
> > And are we not allowed to use C99 features now anyway?
>
> It's fine, it's not about the C standard number.
>
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 14:05 ` Bartosz Golaszewski
@ 2025-09-09 15:15 ` Andy Shevchenko
2025-09-09 15:25 ` Andy Shevchenko
0 siblings, 1 reply; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 15:15 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Andy Shevchenko, Linus Walleij, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko, linux-gpio, linux-kernel, linux-mips,
linux-arm-kernel, linux-mediatek, linux-riscv, spacemit,
Bartosz Golaszewski
On Tue, Sep 9, 2025 at 5:05 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> On Tue, Sep 9, 2025 at 4:02 PM Andy Shevchenko
> <andriy.shevchenko@intel.com> wrote:
> > On Tue, Sep 09, 2025 at 03:56:41PM +0200, Bartosz Golaszewski wrote:
> > > On Tue, Sep 9, 2025 at 3:47 PM Andy Shevchenko
> > > <andriy.shevchenko@intel.com> wrote:
...
> > > > TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> > > > literal as a cast. Which is not!
> > >
> > > What do you suggest?
> >
> > Write it in less odd way :-)
> >
> > foo = (struct bar) { ... };
>
> I don't get your reasoning. typeof() itself is well established in the
> kernel and doesn't
>
> foo = (struct bar){ ... };
>
> evaluate to the same thing as
>
> foo = (typeof(foo)){ ... };
>
> ? Isn't it still the same compound literal?
It makes it so, but typeof() usually is used for casts and not for
compound literals. That's (usage typeof() for compound literals) what
I am against in this case.
> > > And are we not allowed to use C99 features now anyway?
> >
> > It's fine, it's not about the C standard number.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 15:15 ` Andy Shevchenko
@ 2025-09-09 15:25 ` Andy Shevchenko
2025-09-09 16:20 ` Bartosz Golaszewski
0 siblings, 1 reply; 31+ messages in thread
From: Andy Shevchenko @ 2025-09-09 15:25 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Andy Shevchenko, Linus Walleij, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko, linux-gpio, linux-kernel, linux-mips,
linux-arm-kernel, linux-mediatek, linux-riscv, spacemit,
Bartosz Golaszewski
On Tue, Sep 9, 2025 at 6:15 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Tue, Sep 9, 2025 at 5:05 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > On Tue, Sep 9, 2025 at 4:02 PM Andy Shevchenko
> > <andriy.shevchenko@intel.com> wrote:
> > > On Tue, Sep 09, 2025 at 03:56:41PM +0200, Bartosz Golaszewski wrote:
> > > > On Tue, Sep 9, 2025 at 3:47 PM Andy Shevchenko
> > > > <andriy.shevchenko@intel.com> wrote:
...
> > > > > TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> > > > > literal as a cast. Which is not!
> > > >
> > > > What do you suggest?
> > >
> > > Write it in less odd way :-)
> > >
> > > foo = (struct bar) { ... };
> >
> > I don't get your reasoning. typeof() itself is well established in the
> > kernel and doesn't
> >
> > foo = (struct bar){ ... };
> >
> > evaluate to the same thing as
> >
> > foo = (typeof(foo)){ ... };
> >
> > ? Isn't it still the same compound literal?
>
> It makes it so, but typeof() usually is used for casts and not for
> compound literals. That's (usage typeof() for compound literals) what
> I am against in this case.
FWIW, brief googling showed that nobody (okay, I haven't found yet
reddit/SO/GCC or LLVM documentation) uses typeof() for compound
literals. So, this makes me feel right, that the form of typeof() is
weird and works due to unknown reasons. Any pointers to the
documentation you read about it?
> > > > And are we not allowed to use C99 features now anyway?
> > >
> > > It's fine, it's not about the C standard number.
E.g., https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gcc/Compound-Literals.html
(8.1.0 is the same).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH 13/15] gpio: sodaville: use new generic GPIO chip API
2025-09-09 15:25 ` Andy Shevchenko
@ 2025-09-09 16:20 ` Bartosz Golaszewski
0 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 16:20 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Andy Shevchenko, Linus Walleij, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko, linux-gpio, linux-kernel, linux-mips,
linux-arm-kernel, linux-mediatek, linux-riscv, spacemit,
Bartosz Golaszewski
On Tue, Sep 9, 2025 at 5:26 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Tue, Sep 9, 2025 at 6:15 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> > On Tue, Sep 9, 2025 at 5:05 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> > > On Tue, Sep 9, 2025 at 4:02 PM Andy Shevchenko
> > > <andriy.shevchenko@intel.com> wrote:
> > > > On Tue, Sep 09, 2025 at 03:56:41PM +0200, Bartosz Golaszewski wrote:
> > > > > On Tue, Sep 9, 2025 at 3:47 PM Andy Shevchenko
> > > > > <andriy.shevchenko@intel.com> wrote:
>
> ...
>
> > > > > > TBH, I think those 6 all made the same mistake, i.e. thinking of the compound
> > > > > > literal as a cast. Which is not!
> > > > >
> > > > > What do you suggest?
> > > >
> > > > Write it in less odd way :-)
> > > >
> > > > foo = (struct bar) { ... };
> > >
> > > I don't get your reasoning. typeof() itself is well established in the
> > > kernel and doesn't
> > >
> > > foo = (struct bar){ ... };
> > >
> > > evaluate to the same thing as
> > >
> > > foo = (typeof(foo)){ ... };
> > >
> > > ? Isn't it still the same compound literal?
> >
> > It makes it so, but typeof() usually is used for casts and not for
> > compound literals. That's (usage typeof() for compound literals) what
> > I am against in this case.
>
> FWIW, brief googling showed that nobody (okay, I haven't found yet
> reddit/SO/GCC or LLVM documentation) uses typeof() for compound
> literals. So, this makes me feel right, that the form of typeof() is
> weird and works due to unknown reasons. Any pointers to the
> documentation you read about it?
>
Ok I'll change it. I also need to change it in existing patches that
already landed in next then.
> > > > > And are we not allowed to use C99 features now anyway?
> > > >
> > > > It's fine, it's not about the C standard number.
>
> E.g., https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gcc/Compound-Literals.html
> (8.1.0 is the same).
>
I get it, I understood incorrectly how they work, no need to rub it in. :)
Bart
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 14/15] gpio: mmio: use new generic GPIO chip API
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (12 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 13/15] gpio: sodaville: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
2025-09-09 9:15 ` [PATCH 15/15] gpio: move gpio-mmio-specific fields out of struct gpio_chip Bartosz Golaszewski
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpio-mmio.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 79e1be149c94842cb6fa6b657343b11e78701220..a5e2f8a826af40ec96d2a3ea58240f1ca8ed250c 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -57,6 +57,7 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
#include <linux/types.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
#include "gpiolib.h"
@@ -737,6 +738,8 @@ MODULE_DEVICE_TABLE(of, bgpio_of_match);
static int bgpio_pdev_probe(struct platform_device *pdev)
{
+ struct gpio_generic_chip_config config;
+ struct gpio_generic_chip *gen_gc;
struct device *dev = &pdev->dev;
struct resource *r;
void __iomem *dat;
@@ -748,7 +751,6 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
unsigned long flags = 0;
unsigned int base;
int err;
- struct gpio_chip *gc;
const char *label;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
@@ -777,8 +779,8 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
if (IS_ERR(dirin))
return PTR_ERR(dirin);
- gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
- if (!gc)
+ gen_gc = devm_kzalloc(&pdev->dev, sizeof(*gen_gc), GFP_KERNEL);
+ if (!gen_gc)
return -ENOMEM;
if (device_is_big_endian(dev))
@@ -787,13 +789,24 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
if (device_property_read_bool(dev, "no-output"))
flags |= BGPIOF_NO_OUTPUT;
- err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags);
+ config = (typeof(config)){
+ .dev = dev,
+ .sz = sz,
+ .dat = dat,
+ .set = set,
+ .clr = clr,
+ .dirout = dirout,
+ .dirin = dirin,
+ .flags = flags,
+ };
+
+ err = gpio_generic_chip_init(gen_gc, &config);
if (err)
return err;
err = device_property_read_string(dev, "label", &label);
if (!err)
- gc->label = label;
+ gen_gc->gc.label = label;
/*
* This property *must not* be used in device-tree sources, it's only
@@ -801,11 +814,11 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
*/
err = device_property_read_u32(dev, "gpio-mmio,base", &base);
if (!err && base <= INT_MAX)
- gc->base = base;
+ gen_gc->gc.base = base;
- platform_set_drvdata(pdev, gc);
+ platform_set_drvdata(pdev, &gen_gc->gc);
- return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
+ return devm_gpiochip_add_data(&pdev->dev, &gen_gc->gc, NULL);
}
static const struct platform_device_id bgpio_id_table[] = {
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 15/15] gpio: move gpio-mmio-specific fields out of struct gpio_chip
2025-09-09 9:15 [PATCH 00/15] gpio: replace legacy bgpio_init() with its modernized alternative - part 4 Bartosz Golaszewski
` (13 preceding siblings ...)
2025-09-09 9:15 ` [PATCH 14/15] gpio: mmio: " Bartosz Golaszewski
@ 2025-09-09 9:15 ` Bartosz Golaszewski
14 siblings, 0 replies; 31+ messages in thread
From: Bartosz Golaszewski @ 2025-09-09 9:15 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Keguang Zhang, Alban Bedel,
Doug Berger, Florian Fainelli,
Broadcom internal kernel review list, Matthias Brugger,
AngeloGioacchino Del Regno, Paul Walmsley, Samuel Holland,
Yixun Lan, Andy Shevchenko
Cc: linux-gpio, linux-kernel, linux-mips, linux-arm-kernel,
linux-mediatek, linux-riscv, spacemit, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
With all users of bgpio_init() converted to using the modernized generic
GPIO chip API, we can now move the gpio-mmio-specific fields out of
struct gpio_chip and into the dedicated struct gpio_generic_chip. To
that end: adjust the gpio-mmio driver to the new layout, update the
docs, etc.
The changes in gpio-mlxbf2.c and gpio-mpc8xxx.c are here and not in their
respective conversion commits because the former passes the address of
the generic chip's lock to the __releases() annotation and we cannot
really hide it while gpio-mpc8xxx.c accesses the shadow registers in a
driver-specific workaround and there's no reason to make them available
in a public API.
Also: drop the relevant task from TODO as it's now done.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/TODO | 5 -
drivers/gpio/gpio-mlxbf2.c | 2 +-
drivers/gpio/gpio-mmio.c | 321 ++++++++++++++++++++++---------------------
drivers/gpio/gpio-mpc8xxx.c | 5 +-
include/linux/gpio/driver.h | 44 ------
include/linux/gpio/generic.h | 67 ++++++---
6 files changed, 211 insertions(+), 233 deletions(-)
diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO
index b797499e627ee9fdb1ee9c564b8278241f720850..8ed74e05903a972e99e0789319ed19ebd8545a1a 100644
--- a/drivers/gpio/TODO
+++ b/drivers/gpio/TODO
@@ -131,11 +131,6 @@ Work items:
helpers (x86 inb()/outb()) and convert port-mapped I/O drivers to use
this with dry-coding and sending to maintainers to test
-- Move the MMIO GPIO specific fields out of struct gpio_chip into a
- dedicated structure. Currently every GPIO chip has them if gpio-mmio is
- enabled in Kconfig even if it itself doesn't register with the helper
- library.
-
-------------------------------------------------------------------------------
Generic regmap GPIO
diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c
index f99f66cd189ca71c9d188dff0a0b42ef2223abb3..9520d26b20a5851ac8b5de239b8f5980dabc2820 100644
--- a/drivers/gpio/gpio-mlxbf2.c
+++ b/drivers/gpio/gpio-mlxbf2.c
@@ -156,7 +156,7 @@ static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs)
* Release the YU arm_gpio_lock after changing the direction mode.
*/
static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs)
- __releases(&gs->chip.gc.bgpio_lock)
+ __releases(&gs->chip.lock)
__releases(yu_arm_gpio_lock_param.lock)
{
writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io);
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index a5e2f8a826af40ec96d2a3ea58240f1ca8ed250c..2fea986e10b87553f6847e96fe214ba3da76c0e9 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -125,20 +125,23 @@ static unsigned long bgpio_read32be(void __iomem *reg)
static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line)
{
- if (gc->be_bits)
- return BIT(gc->bgpio_bits - 1 - line);
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
+ if (chip->be_bits)
+ return BIT(chip->bits - 1 - line);
return BIT(line);
}
static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long pinmask = bgpio_line2mask(gc, gpio);
- bool dir = !!(gc->bgpio_dir & pinmask);
+ bool dir = !!(chip->sdir & pinmask);
if (dir)
- return !!(gc->read_reg(gc->reg_set) & pinmask);
- else
- return !!(gc->read_reg(gc->reg_dat) & pinmask);
+ return !!(chip->read_reg(chip->reg_set) & pinmask);
+
+ return !!(chip->read_reg(chip->reg_dat) & pinmask);
}
/*
@@ -148,26 +151,28 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
- unsigned long get_mask = 0;
- unsigned long set_mask = 0;
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+ unsigned long get_mask = 0, set_mask = 0;
/* Make sure we first clear any bits that are zero when we read the register */
*bits &= ~*mask;
- set_mask = *mask & gc->bgpio_dir;
- get_mask = *mask & ~gc->bgpio_dir;
+ set_mask = *mask & chip->sdir;
+ get_mask = *mask & ~chip->sdir;
if (set_mask)
- *bits |= gc->read_reg(gc->reg_set) & set_mask;
+ *bits |= chip->read_reg(chip->reg_set) & set_mask;
if (get_mask)
- *bits |= gc->read_reg(gc->reg_dat) & get_mask;
+ *bits |= chip->read_reg(chip->reg_dat) & get_mask;
return 0;
}
static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
{
- return !!(gc->read_reg(gc->reg_dat) & bgpio_line2mask(gc, gpio));
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
+ return !!(chip->read_reg(chip->reg_dat) & bgpio_line2mask(gc, gpio));
}
/*
@@ -176,9 +181,11 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
/* Make sure we first clear any bits that are zero when we read the register */
*bits &= ~*mask;
- *bits |= gc->read_reg(gc->reg_dat) & *mask;
+ *bits |= chip->read_reg(chip->reg_dat) & *mask;
return 0;
}
@@ -188,6 +195,7 @@ static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask,
static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long readmask = 0;
unsigned long val;
int bit;
@@ -200,7 +208,7 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
readmask |= bgpio_line2mask(gc, bit);
/* Read the register */
- val = gc->read_reg(gc->reg_dat) & readmask;
+ val = chip->read_reg(chip->reg_dat) & readmask;
/*
* Mirror the result into the "bits" result, this will give line 0
@@ -219,19 +227,20 @@ static int bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
static int bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long mask = bgpio_line2mask(gc, gpio);
unsigned long flags;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
+ raw_spin_lock_irqsave(&chip->lock, flags);
if (val)
- gc->bgpio_data |= mask;
+ chip->sdata |= mask;
else
- gc->bgpio_data &= ~mask;
+ chip->sdata &= ~mask;
- gc->write_reg(gc->reg_dat, gc->bgpio_data);
+ chip->write_reg(chip->reg_dat, chip->sdata);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
@@ -239,31 +248,32 @@ static int bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
static int bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
int val)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long mask = bgpio_line2mask(gc, gpio);
if (val)
- gc->write_reg(gc->reg_set, mask);
+ chip->write_reg(chip->reg_set, mask);
else
- gc->write_reg(gc->reg_clr, mask);
+ chip->write_reg(chip->reg_clr, mask);
return 0;
}
static int bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
- unsigned long mask = bgpio_line2mask(gc, gpio);
- unsigned long flags;
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+ unsigned long mask = bgpio_line2mask(gc, gpio), flags;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
+ raw_spin_lock_irqsave(&chip->lock, flags);
if (val)
- gc->bgpio_data |= mask;
+ chip->sdata |= mask;
else
- gc->bgpio_data &= ~mask;
+ chip->sdata &= ~mask;
- gc->write_reg(gc->reg_set, gc->bgpio_data);
+ chip->write_reg(chip->reg_set, chip->sdata);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
@@ -273,12 +283,13 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc,
unsigned long *set_mask,
unsigned long *clear_mask)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
int i;
*set_mask = 0;
*clear_mask = 0;
- for_each_set_bit(i, mask, gc->bgpio_bits) {
+ for_each_set_bit(i, mask, chip->bits) {
if (test_bit(i, bits))
*set_mask |= bgpio_line2mask(gc, i);
else
@@ -291,25 +302,27 @@ static void bgpio_set_multiple_single_reg(struct gpio_chip *gc,
unsigned long *bits,
void __iomem *reg)
{
- unsigned long flags;
- unsigned long set_mask, clear_mask;
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+ unsigned long flags, set_mask, clear_mask;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
+ raw_spin_lock_irqsave(&chip->lock, flags);
bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
- gc->bgpio_data |= set_mask;
- gc->bgpio_data &= ~clear_mask;
+ chip->sdata |= set_mask;
+ chip->sdata &= ~clear_mask;
- gc->write_reg(reg, gc->bgpio_data);
+ chip->write_reg(reg, chip->sdata);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ raw_spin_unlock_irqrestore(&chip->lock, flags);
}
static int bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
- bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat);
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
+ bgpio_set_multiple_single_reg(gc, mask, bits, chip->reg_dat);
return 0;
}
@@ -317,7 +330,9 @@ static int bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
static int bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
- bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set);
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
+ bgpio_set_multiple_single_reg(gc, mask, bits, chip->reg_set);
return 0;
}
@@ -326,21 +341,24 @@ static int bgpio_set_multiple_with_clear(struct gpio_chip *gc,
unsigned long *mask,
unsigned long *bits)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long set_mask, clear_mask;
bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
if (set_mask)
- gc->write_reg(gc->reg_set, set_mask);
+ chip->write_reg(chip->reg_set, set_mask);
if (clear_mask)
- gc->write_reg(gc->reg_clr, clear_mask);
+ chip->write_reg(chip->reg_clr, clear_mask);
return 0;
}
static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_out)
{
- if (!gc->bgpio_pinctrl)
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
+ if (!chip->pinctrl)
return 0;
if (dir_out)
@@ -375,39 +393,42 @@ static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long flags;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
+ raw_spin_lock_irqsave(&chip->lock, flags);
- gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
+ chip->sdir &= ~bgpio_line2mask(gc, gpio);
- if (gc->reg_dir_in)
- gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir);
- if (gc->reg_dir_out)
- gc->write_reg(gc->reg_dir_out, gc->bgpio_dir);
+ if (chip->reg_dir_in)
+ chip->write_reg(chip->reg_dir_in, ~chip->sdir);
+ if (chip->reg_dir_out)
+ chip->write_reg(chip->reg_dir_out, chip->sdir);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ raw_spin_unlock_irqrestore(&chip->lock, flags);
return bgpio_dir_return(gc, gpio, false);
}
static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
/* Return 0 if output, 1 if input */
- if (gc->bgpio_dir_unreadable) {
- if (gc->bgpio_dir & bgpio_line2mask(gc, gpio))
+ if (chip->dir_unreadable) {
+ if (chip->sdir & bgpio_line2mask(gc, gpio))
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
- if (gc->reg_dir_out) {
- if (gc->read_reg(gc->reg_dir_out) & bgpio_line2mask(gc, gpio))
+ if (chip->reg_dir_out) {
+ if (chip->read_reg(chip->reg_dir_out) & bgpio_line2mask(gc, gpio))
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
- if (gc->reg_dir_in)
- if (!(gc->read_reg(gc->reg_dir_in) & bgpio_line2mask(gc, gpio)))
+ if (chip->reg_dir_in)
+ if (!(chip->read_reg(chip->reg_dir_in) & bgpio_line2mask(gc, gpio)))
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
@@ -415,18 +436,19 @@ static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
unsigned long flags;
- raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
+ raw_spin_lock_irqsave(&chip->lock, flags);
- gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
+ chip->sdir |= bgpio_line2mask(gc, gpio);
- if (gc->reg_dir_in)
- gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir);
- if (gc->reg_dir_out)
- gc->write_reg(gc->reg_dir_out, gc->bgpio_dir);
+ if (chip->reg_dir_in)
+ chip->write_reg(chip->reg_dir_in, ~chip->sdir);
+ if (chip->reg_dir_out)
+ chip->write_reg(chip->reg_dir_out, chip->sdir);
- raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ raw_spin_unlock_irqrestore(&chip->lock, flags);
}
static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio,
@@ -446,31 +468,30 @@ static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio,
}
static int bgpio_setup_accessors(struct device *dev,
- struct gpio_chip *gc,
+ struct gpio_generic_chip *chip,
bool byte_be)
{
-
- switch (gc->bgpio_bits) {
+ switch (chip->bits) {
case 8:
- gc->read_reg = bgpio_read8;
- gc->write_reg = bgpio_write8;
+ chip->read_reg = bgpio_read8;
+ chip->write_reg = bgpio_write8;
break;
case 16:
if (byte_be) {
- gc->read_reg = bgpio_read16be;
- gc->write_reg = bgpio_write16be;
+ chip->read_reg = bgpio_read16be;
+ chip->write_reg = bgpio_write16be;
} else {
- gc->read_reg = bgpio_read16;
- gc->write_reg = bgpio_write16;
+ chip->read_reg = bgpio_read16;
+ chip->write_reg = bgpio_write16;
}
break;
case 32:
if (byte_be) {
- gc->read_reg = bgpio_read32be;
- gc->write_reg = bgpio_write32be;
+ chip->read_reg = bgpio_read32be;
+ chip->write_reg = bgpio_write32be;
} else {
- gc->read_reg = bgpio_read32;
- gc->write_reg = bgpio_write32;
+ chip->read_reg = bgpio_read32;
+ chip->write_reg = bgpio_write32;
}
break;
#if BITS_PER_LONG >= 64
@@ -480,13 +501,13 @@ static int bgpio_setup_accessors(struct device *dev,
"64 bit big endian byte order unsupported\n");
return -EINVAL;
} else {
- gc->read_reg = bgpio_read64;
- gc->write_reg = bgpio_write64;
+ chip->read_reg = bgpio_read64;
+ chip->write_reg = bgpio_write64;
}
break;
#endif /* BITS_PER_LONG >= 64 */
default:
- dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits);
+ dev_err(dev, "unsupported data width %u bits\n", chip->bits);
return -EINVAL;
}
@@ -515,27 +536,25 @@ static int bgpio_setup_accessors(struct device *dev,
* - an input direction register (named "dirin") where a 1 bit indicates
* the GPIO is an input.
*/
-static int bgpio_setup_io(struct gpio_chip *gc,
- void __iomem *dat,
- void __iomem *set,
- void __iomem *clr,
- unsigned long flags)
+static int bgpio_setup_io(struct gpio_generic_chip *chip,
+ const struct gpio_generic_chip_config *cfg)
{
+ struct gpio_chip *gc = &chip->gc;
- gc->reg_dat = dat;
- if (!gc->reg_dat)
+ chip->reg_dat = cfg->dat;
+ if (!chip->reg_dat)
return -EINVAL;
- if (set && clr) {
- gc->reg_set = set;
- gc->reg_clr = clr;
+ if (cfg->set && cfg->clr) {
+ chip->reg_set = cfg->set;
+ chip->reg_clr = cfg->clr;
gc->set = bgpio_set_with_clear;
gc->set_multiple = bgpio_set_multiple_with_clear;
- } else if (set && !clr) {
- gc->reg_set = set;
+ } else if (cfg->set && !cfg->clr) {
+ chip->reg_set = cfg->set;
gc->set = bgpio_set_set;
gc->set_multiple = bgpio_set_multiple_set;
- } else if (flags & BGPIOF_NO_OUTPUT) {
+ } else if (cfg->flags & BGPIOF_NO_OUTPUT) {
gc->set = bgpio_set_none;
gc->set_multiple = NULL;
} else {
@@ -543,10 +562,10 @@ static int bgpio_setup_io(struct gpio_chip *gc,
gc->set_multiple = bgpio_set_multiple;
}
- if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
- (flags & BGPIOF_READ_OUTPUT_REG_SET)) {
+ if (!(cfg->flags & BGPIOF_UNREADABLE_REG_SET) &&
+ (cfg->flags & BGPIOF_READ_OUTPUT_REG_SET)) {
gc->get = bgpio_get_set;
- if (!gc->be_bits)
+ if (!chip->be_bits)
gc->get_multiple = bgpio_get_set_multiple;
/*
* We deliberately avoid assigning the ->get_multiple() call
@@ -557,7 +576,7 @@ static int bgpio_setup_io(struct gpio_chip *gc,
*/
} else {
gc->get = bgpio_get;
- if (gc->be_bits)
+ if (chip->be_bits)
gc->get_multiple = bgpio_get_multiple_be;
else
gc->get_multiple = bgpio_get_multiple;
@@ -566,27 +585,27 @@ static int bgpio_setup_io(struct gpio_chip *gc,
return 0;
}
-static int bgpio_setup_direction(struct gpio_chip *gc,
- void __iomem *dirout,
- void __iomem *dirin,
- unsigned long flags)
+static int bgpio_setup_direction(struct gpio_generic_chip *chip,
+ const struct gpio_generic_chip_config *cfg)
{
- if (dirout || dirin) {
- gc->reg_dir_out = dirout;
- gc->reg_dir_in = dirin;
- if (flags & BGPIOF_NO_SET_ON_INPUT)
+ struct gpio_chip *gc = &chip->gc;
+
+ if (cfg->dirout || cfg->dirin) {
+ chip->reg_dir_out = cfg->dirout;
+ chip->reg_dir_in = cfg->dirin;
+ if (cfg->flags & BGPIOF_NO_SET_ON_INPUT)
gc->direction_output = bgpio_dir_out_dir_first;
else
gc->direction_output = bgpio_dir_out_val_first;
gc->direction_input = bgpio_dir_in;
gc->get_direction = bgpio_get_dir;
} else {
- if (flags & BGPIOF_NO_OUTPUT)
+ if (cfg->flags & BGPIOF_NO_OUTPUT)
gc->direction_output = bgpio_dir_out_err;
else
gc->direction_output = bgpio_simple_dir_out;
- if (flags & BGPIOF_NO_INPUT)
+ if (cfg->flags & BGPIOF_NO_INPUT)
gc->direction_input = bgpio_dir_in_err;
else
gc->direction_input = bgpio_simple_dir_in;
@@ -595,117 +614,101 @@ static int bgpio_setup_direction(struct gpio_chip *gc,
return 0;
}
-static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
+static int bgpio_request(struct gpio_chip *gc, unsigned int gpio_pin)
{
- if (gpio_pin >= chip->ngpio)
+ struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
+
+ if (gpio_pin >= gc->ngpio)
return -EINVAL;
- if (chip->bgpio_pinctrl)
- return gpiochip_generic_request(chip, gpio_pin);
+ if (chip->pinctrl)
+ return gpiochip_generic_request(gc, gpio_pin);
return 0;
}
/**
- * bgpio_init() - Initialize generic GPIO accessor functions
- * @gc: the GPIO chip to set up
- * @dev: the parent device of the new GPIO chip (compulsory)
- * @sz: the size (width) of the MMIO registers in bytes, typically 1, 2 or 4
- * @dat: MMIO address for the register to READ the value of the GPIO lines, it
- * is expected that a 1 in the corresponding bit in this register means the
- * line is asserted
- * @set: MMIO address for the register to SET the value of the GPIO lines, it is
- * expected that we write the line with 1 in this register to drive the GPIO line
- * high.
- * @clr: MMIO address for the register to CLEAR the value of the GPIO lines, it is
- * expected that we write the line with 1 in this register to drive the GPIO line
- * low. It is allowed to leave this address as NULL, in that case the SET register
- * will be assumed to also clear the GPIO lines, by actively writing the line
- * with 0.
- * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed
- * that setting a line to 1 in this register will turn that line into an
- * output line. Conversely, setting the line to 0 will turn that line into
- * an input.
- * @dirin: MMIO address for the register to set this line as INPUT. It is assumed
- * that setting a line to 1 in this register will turn that line into an
- * input line. Conversely, setting the line to 0 will turn that line into
- * an output.
- * @flags: Different flags that will affect the behaviour of the device, such as
- * endianness etc.
+ * gpio_generic_chip_init() - Initialize a generic GPIO chip.
+ * @chip: Generic GPIO chip to set up.
+ * @cfg: Generic GPIO chip configuration.
+ *
+ * Returns 0 on success, negative error number on failure.
*/
-int bgpio_init(struct gpio_chip *gc, struct device *dev,
- unsigned long sz, void __iomem *dat, void __iomem *set,
- void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
- unsigned long flags)
+int gpio_generic_chip_init(struct gpio_generic_chip *chip,
+ const struct gpio_generic_chip_config *cfg)
{
+ struct gpio_chip *gc = &chip->gc;
+ unsigned long flags = cfg->flags;
+ struct device *dev = cfg->dev;
int ret;
- if (!is_power_of_2(sz))
+ if (!is_power_of_2(cfg->sz))
return -EINVAL;
- gc->bgpio_bits = sz * 8;
- if (gc->bgpio_bits > BITS_PER_LONG)
+ chip->bits = cfg->sz * 8;
+ if (chip->bits > BITS_PER_LONG)
return -EINVAL;
- raw_spin_lock_init(&gc->bgpio_lock);
+ raw_spin_lock_init(&chip->lock);
gc->parent = dev;
gc->label = dev_name(dev);
gc->base = -1;
gc->request = bgpio_request;
- gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN);
+ chip->be_bits = !!(flags & BGPIOF_BIG_ENDIAN);
ret = gpiochip_get_ngpios(gc, dev);
if (ret)
- gc->ngpio = gc->bgpio_bits;
+ gc->ngpio = chip->bits;
- ret = bgpio_setup_io(gc, dat, set, clr, flags);
+ ret = bgpio_setup_io(chip, cfg);
if (ret)
return ret;
- ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ ret = bgpio_setup_accessors(dev, chip,
+ flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret)
return ret;
- ret = bgpio_setup_direction(gc, dirout, dirin, flags);
+ ret = bgpio_setup_direction(chip, cfg);
if (ret)
return ret;
if (flags & BGPIOF_PINCTRL_BACKEND) {
- gc->bgpio_pinctrl = true;
+ chip->pinctrl = true;
/* Currently this callback is only used for pincontrol */
gc->free = gpiochip_generic_free;
}
- gc->bgpio_data = gc->read_reg(gc->reg_dat);
+ chip->sdata = chip->read_reg(chip->reg_dat);
if (gc->set == bgpio_set_set &&
!(flags & BGPIOF_UNREADABLE_REG_SET))
- gc->bgpio_data = gc->read_reg(gc->reg_set);
+ chip->sdata = chip->read_reg(chip->reg_set);
if (flags & BGPIOF_UNREADABLE_REG_DIR)
- gc->bgpio_dir_unreadable = true;
+ chip->dir_unreadable = true;
/*
* Inspect hardware to find initial direction setting.
*/
- if ((gc->reg_dir_out || gc->reg_dir_in) &&
+ if ((chip->reg_dir_out || chip->reg_dir_in) &&
!(flags & BGPIOF_UNREADABLE_REG_DIR)) {
- if (gc->reg_dir_out)
- gc->bgpio_dir = gc->read_reg(gc->reg_dir_out);
- else if (gc->reg_dir_in)
- gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in);
+ if (chip->reg_dir_out)
+ chip->sdir = chip->read_reg(chip->reg_dir_out);
+ else if (chip->reg_dir_in)
+ chip->sdir = ~chip->read_reg(chip->reg_dir_in);
/*
* If we have two direction registers, synchronise
* input setting to output setting, the library
* can not handle a line being input and output at
* the same time.
*/
- if (gc->reg_dir_out && gc->reg_dir_in)
- gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir);
+ if (chip->reg_dir_out && chip->reg_dir_in)
+ chip->write_reg(chip->reg_dir_in, ~chip->sdir);
}
return ret;
}
-EXPORT_SYMBOL_GPL(bgpio_init);
+EXPORT_SYMBOL_GPL(gpio_generic_chip_init);
#if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM)
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 38643fb813c562957076aab48d804f8048cee5e4..2bb6100840ea27fb63ce7cdc3e1eb3e43526eb4d 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -71,7 +71,7 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
mpc8xxx_gc->regs + GPIO_DIR);
val = gpio_generic_read_reg(&mpc8xxx_gc->chip,
mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask;
- out_shadow = gc->bgpio_data & out_mask;
+ out_shadow = mpc8xxx_gc->chip.sdata & out_mask;
return !!((val | out_shadow) & mpc_pin2mask(gpio));
}
@@ -399,7 +399,8 @@ static int mpc8xxx_probe(struct platform_device *pdev)
gpio_generic_write_reg(&mpc8xxx_gc->chip,
mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
/* Also, latch state of GPIOs configured as output by bootloader. */
- gc->bgpio_data = gpio_generic_read_reg(&mpc8xxx_gc->chip,
+ mpc8xxx_gc->chip.sdata =
+ gpio_generic_read_reg(&mpc8xxx_gc->chip,
mpc8xxx_gc->regs + GPIO_DAT) &
gpio_generic_read_reg(&mpc8xxx_gc->chip,
mpc8xxx_gc->regs + GPIO_DIR);
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 9fcd4a988081f74d25dc88535705ba9265e56fd2..9b14fd20f13eee7d465e065e7ded2c92e2bbc78e 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -388,28 +388,6 @@ struct gpio_irq_chip {
* implies that if the chip supports IRQs, these IRQs need to be threaded
* as the chip access may sleep when e.g. reading out the IRQ status
* registers.
- * @read_reg: reader function for generic GPIO
- * @write_reg: writer function for generic GPIO
- * @be_bits: if the generic GPIO has big endian bit order (bit 31 is representing
- * line 0, bit 30 is line 1 ... bit 0 is line 31) this is set to true by the
- * generic GPIO core. It is for internal housekeeping only.
- * @reg_dat: data (in) register for generic GPIO
- * @reg_set: output set register (out=high) for generic GPIO
- * @reg_clr: output clear register (out=low) for generic GPIO
- * @reg_dir_out: direction out setting register for generic GPIO
- * @reg_dir_in: direction in setting register for generic GPIO
- * @bgpio_dir_unreadable: indicates that the direction register(s) cannot
- * be read and we need to rely on out internal state tracking.
- * @bgpio_pinctrl: the generic GPIO uses a pin control backend.
- * @bgpio_bits: number of register bits used for a generic GPIO i.e.
- * <register width> * 8
- * @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep
- * shadowed and real data registers writes together.
- * @bgpio_data: shadowed data register for generic GPIO to clear/set bits
- * safely.
- * @bgpio_dir: shadowed direction register for generic GPIO to clear/set
- * direction safely. A "1" in this word means the line is set as
- * output.
*
* A gpio_chip can help platforms abstract various sources of GPIOs so
* they can all be accessed through a common programming interface.
@@ -475,23 +453,6 @@ struct gpio_chip {
const char *const *names;
bool can_sleep;
-#if IS_ENABLED(CONFIG_GPIO_GENERIC)
- unsigned long (*read_reg)(void __iomem *reg);
- void (*write_reg)(void __iomem *reg, unsigned long data);
- bool be_bits;
- void __iomem *reg_dat;
- void __iomem *reg_set;
- void __iomem *reg_clr;
- void __iomem *reg_dir_out;
- void __iomem *reg_dir_in;
- bool bgpio_dir_unreadable;
- bool bgpio_pinctrl;
- int bgpio_bits;
- raw_spinlock_t bgpio_lock;
- unsigned long bgpio_data;
- unsigned long bgpio_dir;
-#endif /* CONFIG_GPIO_GENERIC */
-
#ifdef CONFIG_GPIOLIB_IRQCHIP
/*
* With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
@@ -723,11 +684,6 @@ int gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc,
#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
-int bgpio_init(struct gpio_chip *gc, struct device *dev,
- unsigned long sz, void __iomem *dat, void __iomem *set,
- void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
- unsigned long flags);
-
#define BGPIOF_BIG_ENDIAN BIT(0)
#define BGPIOF_UNREADABLE_REG_SET BIT(1) /* reg_set is unreadable */
#define BGPIOF_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */
diff --git a/include/linux/gpio/generic.h b/include/linux/gpio/generic.h
index 4c0626b53ec90388a034bc7797eefa53e7ea064e..162430d96660e96b995eb4a2e64183503fc618e3 100644
--- a/include/linux/gpio/generic.h
+++ b/include/linux/gpio/generic.h
@@ -50,9 +50,44 @@ struct gpio_generic_chip_config {
* struct gpio_generic_chip - Generic GPIO chip implementation.
* @gc: The underlying struct gpio_chip object, implementing low-level GPIO
* chip routines.
+ * @read_reg: reader function for generic GPIO
+ * @write_reg: writer function for generic GPIO
+ * @be_bits: if the generic GPIO has big endian bit order (bit 31 is
+ * representing line 0, bit 30 is line 1 ... bit 0 is line 31) this
+ * is set to true by the generic GPIO core. It is for internal
+ * housekeeping only.
+ * @reg_dat: data (in) register for generic GPIO
+ * @reg_set: output set register (out=high) for generic GPIO
+ * @reg_clr: output clear register (out=low) for generic GPIO
+ * @reg_dir_out: direction out setting register for generic GPIO
+ * @reg_dir_in: direction in setting register for generic GPIO
+ * @dir_unreadable: indicates that the direction register(s) cannot be read and
+ * we need to rely on out internal state tracking.
+ * @pinctrl: the generic GPIO uses a pin control backend.
+ * @bits: number of register bits used for a generic GPIO
+ * i.e. <register width> * 8
+ * @lock: used to lock chip->sdata. Also, this is needed to keep
+ * shadowed and real data registers writes together.
+ * @sdata: shadowed data register for generic GPIO to clear/set bits safely.
+ * @sdir: shadowed direction register for generic GPIO to clear/set direction
+ * safely. A "1" in this word means the line is set as output.
*/
struct gpio_generic_chip {
struct gpio_chip gc;
+ unsigned long (*read_reg)(void __iomem *reg);
+ void (*write_reg)(void __iomem *reg, unsigned long data);
+ bool be_bits;
+ void __iomem *reg_dat;
+ void __iomem *reg_set;
+ void __iomem *reg_clr;
+ void __iomem *reg_dir_out;
+ void __iomem *reg_dir_in;
+ bool dir_unreadable;
+ bool pinctrl;
+ int bits;
+ raw_spinlock_t lock;
+ unsigned long sdata;
+ unsigned long sdir;
};
static inline struct gpio_generic_chip *
@@ -61,20 +96,8 @@ to_gpio_generic_chip(struct gpio_chip *gc)
return container_of(gc, struct gpio_generic_chip, gc);
}
-/**
- * gpio_generic_chip_init() - Initialize a generic GPIO chip.
- * @chip: Generic GPIO chip to set up.
- * @cfg: Generic GPIO chip configuration.
- *
- * Returns 0 on success, negative error number on failure.
- */
-static inline int
-gpio_generic_chip_init(struct gpio_generic_chip *chip,
- const struct gpio_generic_chip_config *cfg)
-{
- return bgpio_init(&chip->gc, cfg->dev, cfg->sz, cfg->dat, cfg->set,
- cfg->clr, cfg->dirout, cfg->dirin, cfg->flags);
-}
+int gpio_generic_chip_init(struct gpio_generic_chip *chip,
+ const struct gpio_generic_chip_config *cfg);
/**
* gpio_generic_chip_set() - Set the GPIO line value of the generic GPIO chip.
@@ -110,10 +133,10 @@ gpio_generic_chip_set(struct gpio_generic_chip *chip, unsigned int offset,
static inline unsigned long
gpio_generic_read_reg(struct gpio_generic_chip *chip, void __iomem *reg)
{
- if (WARN_ON(!chip->gc.read_reg))
+ if (WARN_ON(!chip->read_reg))
return 0;
- return chip->gc.read_reg(reg);
+ return chip->read_reg(reg);
}
/**
@@ -125,23 +148,23 @@ gpio_generic_read_reg(struct gpio_generic_chip *chip, void __iomem *reg)
static inline void gpio_generic_write_reg(struct gpio_generic_chip *chip,
void __iomem *reg, unsigned long val)
{
- if (WARN_ON(!chip->gc.write_reg))
+ if (WARN_ON(!chip->write_reg))
return;
- chip->gc.write_reg(reg, val);
+ chip->write_reg(reg, val);
}
#define gpio_generic_chip_lock(gen_gc) \
- raw_spin_lock(&(gen_gc)->gc.bgpio_lock)
+ raw_spin_lock(&(gen_gc)->lock)
#define gpio_generic_chip_unlock(gen_gc) \
- raw_spin_unlock(&(gen_gc)->gc.bgpio_lock)
+ raw_spin_unlock(&(gen_gc)->lock)
#define gpio_generic_chip_lock_irqsave(gen_gc, flags) \
- raw_spin_lock_irqsave(&(gen_gc)->gc.bgpio_lock, flags)
+ raw_spin_lock_irqsave(&(gen_gc)->lock, flags)
#define gpio_generic_chip_unlock_irqrestore(gen_gc, flags) \
- raw_spin_unlock_irqrestore(&(gen_gc)->gc.bgpio_lock, flags)
+ raw_spin_unlock_irqrestore(&(gen_gc)->lock, flags)
DEFINE_LOCK_GUARD_1(gpio_generic_lock,
struct gpio_generic_chip,
--
2.48.1
^ permalink raw reply related [flat|nested] 31+ messages in thread