gpio: brcmstb: use new generic GPIO chip API
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Wed, 10 Sep 2025 07:12:43 +0000 (09:12 +0200)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Fri, 12 Sep 2025 07:22:44 +0000 (09:22 +0200)
Convert the driver to using the new generic GPIO chip interfaces from
linux/gpio/generic.h.

Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Acked-by: Doug Berger <opendmb@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20250910-gpio-mmio-gpio-conv-part4-v2-7-f3d1a4c57124@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpio-brcmstb.c

index e29a958..be3ff91 100644 (file)
@@ -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);
-
-       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;
-
-       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);
+       guard(gpio_generic_lock_irqsave)(&bank->chip);
+
+       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;
+
+       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 @@ out_free_domain:
 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 = (struct gpio_generic_chip_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) {