gpio: mpc8xxx: use new generic GPIO chip API
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Mon, 25 Aug 2025 09:48:54 +0000 (11:48 +0200)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Mon, 25 Aug 2025 10:05:38 +0000 (12:05 +0200)
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20250825-gpio-mmio-gpio-conv-v1-13-356b4b1d5110@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpio-mpc8xxx.c

index 121efdd..38643fb 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/acpi.h>
 #include <linux/bitops.h>
 #include <linux/gpio/driver.h>
+#include <linux/gpio/generic.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -34,7 +35,7 @@
 #define GPIO_IBE               0x18
 
 struct mpc8xxx_gpio_chip {
-       struct gpio_chip        gc;
+       struct gpio_generic_chip chip;
        void __iomem *regs;
        raw_spinlock_t lock;
 
@@ -66,8 +67,10 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = gpiochip_get_data(gc);
        u32 out_mask, out_shadow;
 
-       out_mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR);
-       val = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) & ~out_mask;
+       out_mask = gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                        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;
 
        return !!((val | out_shadow) & mpc_pin2mask(gpio));
@@ -108,12 +111,13 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = data;
-       struct gpio_chip *gc = &mpc8xxx_gc->gc;
        unsigned long mask;
        int i;
 
-       mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER)
-               & gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR);
+       mask = gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                    mpc8xxx_gc->regs + GPIO_IER) &
+              gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                    mpc8xxx_gc->regs + GPIO_IMR);
        for_each_set_bit(i, &mask, 32)
                generic_handle_domain_irq(mpc8xxx_gc->irq, 31 - i);
 
@@ -124,15 +128,17 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
-       struct gpio_chip *gc = &mpc8xxx_gc->gc;
+       struct gpio_chip *gc = &mpc8xxx_gc->chip.gc;
        unsigned long flags;
 
        gpiochip_enable_irq(gc, hwirq);
 
        raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-       gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
-               gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
+       gpio_generic_write_reg(&mpc8xxx_gc->chip,
+                              mpc8xxx_gc->regs + GPIO_IMR,
+               gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                     mpc8xxx_gc->regs + GPIO_IMR)
                | mpc_pin2mask(irqd_to_hwirq(d)));
 
        raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
@@ -142,13 +148,14 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
-       struct gpio_chip *gc = &mpc8xxx_gc->gc;
+       struct gpio_chip *gc = &mpc8xxx_gc->chip.gc;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-       gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR,
-               gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR)
+       gpio_generic_write_reg(&mpc8xxx_gc->chip, mpc8xxx_gc->regs + GPIO_IMR,
+               gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                     mpc8xxx_gc->regs + GPIO_IMR)
                & ~mpc_pin2mask(irqd_to_hwirq(d)));
 
        raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
@@ -159,32 +166,34 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
 static void mpc8xxx_irq_ack(struct irq_data *d)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-       struct gpio_chip *gc = &mpc8xxx_gc->gc;
 
-       gc->write_reg(mpc8xxx_gc->regs + GPIO_IER,
+       gpio_generic_write_reg(&mpc8xxx_gc->chip, mpc8xxx_gc->regs + GPIO_IER,
                      mpc_pin2mask(irqd_to_hwirq(d)));
 }
 
 static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-       struct gpio_chip *gc = &mpc8xxx_gc->gc;
        unsigned long flags;
 
        switch (flow_type) {
        case IRQ_TYPE_EDGE_FALLING:
        case IRQ_TYPE_LEVEL_LOW:
                raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-               gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
-                       gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
+               gpio_generic_write_reg(&mpc8xxx_gc->chip,
+                                      mpc8xxx_gc->regs + GPIO_ICR,
+                       gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                             mpc8xxx_gc->regs + GPIO_ICR)
                        | mpc_pin2mask(irqd_to_hwirq(d)));
                raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        case IRQ_TYPE_EDGE_BOTH:
                raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-               gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
-                       gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
+               gpio_generic_write_reg(&mpc8xxx_gc->chip,
+                                      mpc8xxx_gc->regs + GPIO_ICR,
+                       gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                             mpc8xxx_gc->regs + GPIO_ICR)
                        & ~mpc_pin2mask(irqd_to_hwirq(d)));
                raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
@@ -199,7 +208,6 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
-       struct gpio_chip *gc = &mpc8xxx_gc->gc;
        unsigned long gpio = irqd_to_hwirq(d);
        void __iomem *reg;
        unsigned int shift;
@@ -217,7 +225,9 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
        case IRQ_TYPE_EDGE_FALLING:
        case IRQ_TYPE_LEVEL_LOW:
                raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-               gc->write_reg(reg, (gc->read_reg(reg) & ~(3 << shift))
+               gpio_generic_write_reg(&mpc8xxx_gc->chip, reg,
+                                      (gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                                             reg) & ~(3 << shift))
                        | (2 << shift));
                raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
@@ -225,14 +235,18 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
        case IRQ_TYPE_EDGE_RISING:
        case IRQ_TYPE_LEVEL_HIGH:
                raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-               gc->write_reg(reg, (gc->read_reg(reg) & ~(3 << shift))
+               gpio_generic_write_reg(&mpc8xxx_gc->chip, reg,
+                                      (gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                                             reg) & ~(3 << shift))
                        | (1 << shift));
                raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        case IRQ_TYPE_EDGE_BOTH:
                raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
-               gc->write_reg(reg, (gc->read_reg(reg) & ~(3 << shift)));
+               gpio_generic_write_reg(&mpc8xxx_gc->chip, reg,
+                                      (gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                                             reg) & ~(3 << shift)));
                raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
@@ -309,6 +323,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = {
 static int mpc8xxx_probe(struct platform_device *pdev)
 {
        const struct mpc8xxx_gpio_devtype *devtype = NULL;
+       struct gpio_generic_chip_config config;
        struct mpc8xxx_gpio_chip *mpc8xxx_gc;
        struct device *dev = &pdev->dev;
        struct fwnode_handle *fwnode;
@@ -327,26 +342,28 @@ static int mpc8xxx_probe(struct platform_device *pdev)
        if (IS_ERR(mpc8xxx_gc->regs))
                return PTR_ERR(mpc8xxx_gc->regs);
 
-       gc = &mpc8xxx_gc->gc;
+       gc = &mpc8xxx_gc->chip.gc;
        gc->parent = dev;
 
+       config = (typeof(config)){
+               .dev = dev,
+               .sz = 4,
+               .dat = mpc8xxx_gc->regs + GPIO_DAT,
+               .dirout = mpc8xxx_gc->regs + GPIO_DIR,
+               .flags = BGPIOF_BIG_ENDIAN
+       };
+
        if (device_property_read_bool(dev, "little-endian")) {
-               ret = bgpio_init(gc, dev, 4, mpc8xxx_gc->regs + GPIO_DAT,
-                                NULL, NULL, mpc8xxx_gc->regs + GPIO_DIR,
-                                NULL, BGPIOF_BIG_ENDIAN);
-               if (ret)
-                       return ret;
                dev_dbg(dev, "GPIO registers are LITTLE endian\n");
        } else {
-               ret = bgpio_init(gc, dev, 4, mpc8xxx_gc->regs + GPIO_DAT,
-                                NULL, NULL, mpc8xxx_gc->regs + GPIO_DIR,
-                                NULL, BGPIOF_BIG_ENDIAN
-                                | BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-               if (ret)
-                       return ret;
+               config.flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
                dev_dbg(dev, "GPIO registers are BIG endian\n");
        }
 
+       ret = gpio_generic_chip_init(&mpc8xxx_gc->chip, &config);
+       if (ret)
+               return ret;
+
        mpc8xxx_gc->direction_output = gc->direction_output;
 
        devtype = device_get_match_data(dev);
@@ -379,10 +396,13 @@ static int mpc8xxx_probe(struct platform_device *pdev)
            device_is_compatible(dev, "fsl,ls1028a-gpio") ||
            device_is_compatible(dev, "fsl,ls1088a-gpio") ||
            is_acpi_node(fwnode)) {
-               gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
+               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 = gc->read_reg(mpc8xxx_gc->regs + GPIO_DAT) &
-                       gc->read_reg(mpc8xxx_gc->regs + GPIO_DIR);
+               gc->bgpio_data = gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                                      mpc8xxx_gc->regs + GPIO_DAT) &
+                                gpio_generic_read_reg(&mpc8xxx_gc->chip,
+                                                      mpc8xxx_gc->regs + GPIO_DIR);
        }
 
        ret = devm_gpiochip_add_data(dev, gc, mpc8xxx_gc);
@@ -405,8 +425,10 @@ static int mpc8xxx_probe(struct platform_device *pdev)
                return 0;
 
        /* ack and mask all irqs */
-       gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
-       gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0);
+       gpio_generic_write_reg(&mpc8xxx_gc->chip,
+                              mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
+       gpio_generic_write_reg(&mpc8xxx_gc->chip,
+                              mpc8xxx_gc->regs + GPIO_IMR, 0);
 
        ret = devm_request_irq(dev, mpc8xxx_gc->irqn,
                               mpc8xxx_gpio_irq_cascade,