summaryrefslogtreecommitdiff
path: root/include/linux/gpio/generic.h
diff options
context:
space:
mode:
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>2025-09-10 09:12:51 +0200
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>2025-09-12 09:22:45 +0200
commit9b90afa6d613b66ec4e74ae75f9bfa5baf386ecd (patch)
treeb3d02b6530a2645c7e9f2fcb9fa3ff81fa2f7450 /include/linux/gpio/generic.h
parente43e94fa19cf058c4e465fcdbc2f521123058ea6 (diff)
gpio: move gpio-mmio-specific fields out of struct gpio_chip
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. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20250910-gpio-mmio-gpio-conv-part4-v2-15-f3d1a4c57124@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Diffstat (limited to 'include/linux/gpio/generic.h')
-rw-r--r--include/linux/gpio/generic.h67
1 files changed, 45 insertions, 22 deletions
diff --git a/include/linux/gpio/generic.h b/include/linux/gpio/generic.h
index 4c0626b53ec9..162430d96660 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,