Linux GPIO subsystem development
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Yu-Chun Lin <eleanor.lin@realtek.com>
Cc: <linusw@kernel.org>, <andriy.shevchenko@intel.com>,
	<mwalle@kernel.org>, <brgl@kernel.org>, <tychang@realtek.com>,
	<wbg@kernel.org>, <mathieu.dubois-briand@bootlin.com>,
	<nuno.sa@analog.com>, <Michael.Hennerich@analog.com>,
	<andy@kernel.org>, <u.kleine-koenig@baylibre.com>,
	<dakr@kernel.org>, <bhelgaas@google.com>,
	<o-takashi@sakamocchi.jp>, <dlechner@baylibre.com>,
	<linux-kernel@vger.kernel.org>, <linux-gpio@vger.kernel.org>,
	<linux@analog.com>, <linux-iio@vger.kernel.org>,
	<cy.huang@realtek.com>, <james.tai@realtek.com>
Subject: Re: [PATCH v7 5/9] gpio: regmap: Add gpio_regmap_operation to extend reg_mask_xlate callback
Date: Sat, 25 Jul 2026 22:47:46 +0100	[thread overview]
Message-ID: <20260725224746.01ef9757@jic23-huawei> (raw)
In-Reply-To: <20260723034237.2501507-6-eleanor.lin@realtek.com>

On Thu, 23 Jul 2026 11:42:22 +0800
Yu-Chun Lin <eleanor.lin@realtek.com> wrote:

> Extend the reg_mask_xlate callback with an operation type parameter
> (enum gpio_regmap_operation) to allow drivers to return different
> register/mask combinations depending on the specific GPIO operation.
> 
> Consequently, update all existing drivers utilizing the gpio-regmap
> framework (across drivers/gpio, drivers/iio, and drivers/pinctrl)
> to accommodate the new reg_mask_xlate function signature.
> 
> Suggested-by: Linus Walleij <linusw@kernel.org>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Acked-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> # for-iio

> ---
> Changes in v7:
> - Move value_xlate changes into patch 6.
> - Add background context to kernel-doc comment for
> 'enum gpio_regmap_operation'.
> ---
>  drivers/gpio/gpio-104-idi-48.c        |  7 +++--
>  drivers/gpio/gpio-i8255.c             |  4 +--
>  drivers/gpio/gpio-idio-16.c           |  6 ++--
>  drivers/gpio/gpio-max7360.c           |  1 +
>  drivers/gpio/gpio-pcie-idio-24.c      |  6 ++--
>  drivers/gpio/gpio-regmap.c            | 31 +++++++++++++++------
>  drivers/iio/adc/ad7173.c              |  8 +++---
>  drivers/iio/addac/stx104.c            |  6 ++--
>  drivers/pinctrl/bcm/pinctrl-bcm63xx.c |  1 +
>  drivers/pinctrl/pinctrl-tps6594.c     |  1 +
>  include/linux/gpio/regmap.h           | 40 +++++++++++++++++++++++++--
>  11 files changed, 81 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
> index ba73ee9c0c29..fb017569cfa8 100644
> --- a/drivers/gpio/gpio-104-idi-48.c
> +++ b/drivers/gpio/gpio-104-idi-48.c
> @@ -36,9 +36,10 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
>  #define IDI48_IRQ_STATUS 0x7
>  #define IDI48_IRQ_ENABLE IDI48_IRQ_STATUS
>  
> -static int idi_48_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
> -				 unsigned int offset, unsigned int *reg,
> -				 unsigned int *mask)
> +static int idi_48_reg_mask_xlate(struct gpio_regmap *gpio,
> +				 enum gpio_regmap_operation op,
> +				 unsigned int base, unsigned int offset,
> +				 unsigned int *reg, unsigned int *mask)
>  {
>  	const unsigned int line = offset % 8;
>  	const unsigned int stride = offset / 8;
> diff --git a/drivers/gpio/gpio-i8255.c b/drivers/gpio/gpio-i8255.c
> index 953018bfa2b1..541a348447cd 100644
> --- a/drivers/gpio/gpio-i8255.c
> +++ b/drivers/gpio/gpio-i8255.c
> @@ -67,8 +67,8 @@ static int i8255_ppi_init(struct regmap *const map, const unsigned int base)
>  	return regmap_write(map, base + I8255_PORTC, 0x00);
>  }
>  
> -static int i8255_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
> -				unsigned int offset, unsigned int *reg,
> +static int i8255_reg_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap_operation op,
> +				unsigned int base, unsigned int offset, unsigned int *reg,
>  				unsigned int *mask)
>  {
>  	const unsigned int ppi = offset / I8255_NGPIO;
> diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c
> index 4fbae6f6a497..9ac967c6b430 100644
> --- a/drivers/gpio/gpio-idio-16.c
> +++ b/drivers/gpio/gpio-idio-16.c
> @@ -66,9 +66,9 @@ static int idio_16_handle_mask_sync(const int index, const unsigned int mask_buf
>  	return 0;
>  }
>  
> -static int idio_16_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
> -				  const unsigned int offset, unsigned int *const reg,
> -				  unsigned int *const mask)
> +static int idio_16_reg_mask_xlate(struct gpio_regmap *const gpio, enum gpio_regmap_operation op,
> +				  const unsigned int base, const unsigned int offset,
> +				  unsigned int *const reg, unsigned int *const mask)
>  {
>  	unsigned int stride;
>  
> diff --git a/drivers/gpio/gpio-max7360.c b/drivers/gpio/gpio-max7360.c
> index 07eda49f375b..6755d58c4534 100644
> --- a/drivers/gpio/gpio-max7360.c
> +++ b/drivers/gpio/gpio-max7360.c
> @@ -93,6 +93,7 @@ static int max7360_set_gpos_count(struct device *dev, struct regmap *regmap)
>  }
>  
>  static int max7360_gpio_reg_mask_xlate(struct gpio_regmap *gpio,
> +				       enum gpio_regmap_operation op,
>  				       unsigned int base, unsigned int offset,
>  				       unsigned int *reg, unsigned int *mask)
>  {
> diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c
> index 80c0ba0afa67..b99f4863443d 100644
> --- a/drivers/gpio/gpio-pcie-idio-24.c
> +++ b/drivers/gpio/gpio-pcie-idio-24.c
> @@ -225,9 +225,9 @@ static int idio_24_set_type_config(unsigned int **const buf, const unsigned int
>  	return ret;
>  }
>  
> -static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
> -				  const unsigned int offset, unsigned int *const reg,
> -				  unsigned int *const mask)
> +static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, enum gpio_regmap_operation op,
> +				  const unsigned int base, const unsigned int offset,
> +				  unsigned int *const reg, unsigned int *const mask)
>  {
>  	const unsigned int out_stride = offset / IDIO_24_NGPIO_PER_REG;
>  	const unsigned int in_stride = (offset - 24) / IDIO_24_NGPIO_PER_REG;
> diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c
> index 658b892b624c..1cc9c03ade99 100644
> --- a/drivers/gpio/gpio-regmap.c
> +++ b/drivers/gpio/gpio-regmap.c
> @@ -40,9 +40,10 @@ struct gpio_regmap {
>  	struct regmap_irq_chip_data *irq_chip_data;
>  #endif
>  
> -	int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base,
> -			      unsigned int offset, unsigned int *reg,
> -			      unsigned int *mask);
> +	int (*reg_mask_xlate)(struct gpio_regmap *gpio,
> +			      enum gpio_regmap_operation op,
> +			      unsigned int base, unsigned int offset,
> +			      unsigned int *reg, unsigned int *mask);
>  
>  	void *driver_data;
>  };
> @@ -56,6 +57,7 @@ static unsigned int gpio_regmap_addr(unsigned int addr)
>  }
>  
>  static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio,
> +				    enum gpio_regmap_operation __maybe_unused op,
>  				    unsigned int base, unsigned int offset,
>  				    unsigned int *reg, unsigned int *mask)
>  {
> @@ -71,7 +73,7 @@ static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio,
>  static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset)
>  {
>  	struct gpio_regmap *gpio = gpiochip_get_data(chip);
> -	unsigned int base, val, reg, mask;
> +	unsigned int base, val, reg, mask, dir_mask;
>  	int ret;
>  
>  	/* we might not have an output register if we are input only */
> @@ -80,7 +82,18 @@ static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset)
>  	else
>  		base = gpio_regmap_addr(gpio->reg_set_base);
>  
> -	ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
> +	ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_GET_OP, base, offset, &reg, &dir_mask);
> +	if (ret)
> +		return ret;
> +
> +	ret = regmap_read(gpio->regmap, reg, &val);
> +	if (ret)
> +		return ret;
> +
> +	if (val & dir_mask)
> +		ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_OUT, base, offset, &reg, &mask);
> +	else
> +		ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_IN, base, offset, &reg, &mask);
>  	if (ret)
>  		return ret;
>  
> @@ -103,7 +116,7 @@ static int gpio_regmap_set(struct gpio_chip *chip, unsigned int offset,
>  	unsigned int reg, mask, mask_val;
>  	int ret;
>  
> -	ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
> +	ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset, &reg, &mask);
>  	if (ret)
>  		return ret;
>  
> @@ -133,7 +146,7 @@ static int gpio_regmap_set_with_clear(struct gpio_chip *chip,
>  	else
>  		base = gpio_regmap_addr(gpio->reg_clr_base);
>  
> -	ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
> +	ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset, &reg, &mask);
>  	if (ret)
>  		return ret;
>  
> @@ -183,7 +196,7 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip,
>  		return -ENOTSUPP;
>  	}
>  
> -	ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
> +	ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_GET_DIR_OP, base, offset, &reg, &mask);
>  	if (ret)
>  		return ret;
>  
> @@ -237,7 +250,7 @@ static int gpio_regmap_set_direction(struct gpio_chip *chip,
>  		return -ENOTSUPP;
>  	}
>  
> -	ret = gpio->reg_mask_xlate(gpio, base, offset, &reg, &mask);
> +	ret = gpio->reg_mask_xlate(gpio, GPIO_REGMAP_SET_DIR_OP, base, offset, &reg, &mask);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c
> index 9ee65d63c525..f78e758706ed 100644
> --- a/drivers/iio/adc/ad7173.c
> +++ b/drivers/iio/adc/ad7173.c
> @@ -560,8 +560,8 @@ static int ad4111_openwire_event(struct iio_dev *indio_dev,
>  	return ret;
>  }
>  
> -static int ad7173_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
> -			     unsigned int offset, unsigned int *reg,
> +static int ad7173_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap_operation op,
> +			     unsigned int base, unsigned int offset, unsigned int *reg,
>  			     unsigned int *mask)
>  {
>  	*mask = AD7173_GPO_DATA(offset);
> @@ -569,8 +569,8 @@ static int ad7173_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
>  	return 0;
>  }
>  
> -static int ad4111_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
> -			     unsigned int offset, unsigned int *reg,
> +static int ad4111_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap_operation op,
> +			     unsigned int base, unsigned int offset, unsigned int *reg,
>  			     unsigned int *mask)
>  {
>  	*mask = AD4111_GPO01_DATA(offset);
> diff --git a/drivers/iio/addac/stx104.c b/drivers/iio/addac/stx104.c
> index 7bdf2cb94176..6207eb2fac74 100644
> --- a/drivers/iio/addac/stx104.c
> +++ b/drivers/iio/addac/stx104.c
> @@ -349,9 +349,9 @@ static const struct iio_chan_spec stx104_channels_diff[] = {
>  	STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1)
>  };
>  
> -static int stx104_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
> -				 unsigned int offset, unsigned int *const reg,
> -				 unsigned int *const mask)
> +static int stx104_reg_mask_xlate(struct gpio_regmap *const gpio, enum gpio_regmap_operation op,
> +				 const unsigned int base, unsigned int offset,
> +				 unsigned int *const reg, unsigned int *const mask)
>  {
>  	/* Output lines are located at same register bit offsets as input lines */
>  	if (offset >= 4)
> diff --git a/drivers/pinctrl/bcm/pinctrl-bcm63xx.c b/drivers/pinctrl/bcm/pinctrl-bcm63xx.c
> index a4aa4146b530..b41a3d16aabe 100644
> --- a/drivers/pinctrl/bcm/pinctrl-bcm63xx.c
> +++ b/drivers/pinctrl/bcm/pinctrl-bcm63xx.c
> @@ -19,6 +19,7 @@
>  #define BCM63XX_DATA_REG	0x0c
>  
>  static int bcm63xx_reg_mask_xlate(struct gpio_regmap *gpio,
> +				  enum gpio_regmap_operation op,
>  				  unsigned int base, unsigned int offset,
>  				  unsigned int *reg, unsigned int *mask)
>  {
> diff --git a/drivers/pinctrl/pinctrl-tps6594.c b/drivers/pinctrl/pinctrl-tps6594.c
> index 456a3cfc8de9..937fc9cb54b7 100644
> --- a/drivers/pinctrl/pinctrl-tps6594.c
> +++ b/drivers/pinctrl/pinctrl-tps6594.c
> @@ -346,6 +346,7 @@ static struct tps6594_pinctrl tps6594_template_pinctrl = {
>  };
>  
>  static int tps6594_gpio_regmap_xlate(struct gpio_regmap *gpio,
> +				     enum gpio_regmap_operation op,
>  				     unsigned int base, unsigned int offset,
>  				     unsigned int *reg, unsigned int *mask)
>  {
> diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h
> index eb3931fbbad0..ececc287d519 100644
> --- a/include/linux/gpio/regmap.h
> +++ b/include/linux/gpio/regmap.h
> @@ -13,6 +13,40 @@ struct regmap;
>  #define GPIO_REGMAP_ADDR_ZERO ((unsigned int)(-1))
>  #define GPIO_REGMAP_ADDR(addr) ((addr) ? : GPIO_REGMAP_ADDR_ZERO)
>  
> +/**
> + * enum gpio_regmap_operation - Operation type for reg_mask_xlate callback
> + *
> + * Traditionally, the operation type was inferred from the base register.
> + * However, that approach does not always work — for example, when all control
> + * bits of a single GPIO reside in the same register. This enum allows the
> + * reg_mask_xlate callback to explicitly distinguish between operation types.
> + * The user is free to choose which method to use.
> + *
> + * Value operations:
> + * @GPIO_REGMAP_GET_OP: Mask for reading direction to detect if GPIO is input or
> + *			output. Used in gpio_regmap_get() to determine the GPIO
> + *			direction.
> + * @GPIO_REGMAP_IN: Mask for reading input value. Used when GPIO is configured as
> + *			input.
> + * @GPIO_REGMAP_OUT: Mask for reading output value. Used when GPIO is configured as
> + *			output.
> + *
> + * Output operations:
> + * @GPIO_REGMAP_SET_OP: Mask for setting GPIO output value.
> + *
> + * Direction operations:
> + * @GPIO_REGMAP_GET_DIR_OP: Mask for reading GPIO direction (input/output).
> + * @GPIO_REGMAP_SET_DIR_OP: Mask for setting GPIO direction (input/output).
> + */
> +enum gpio_regmap_operation {
> +	GPIO_REGMAP_GET_OP,
> +	GPIO_REGMAP_SET_OP,
> +	GPIO_REGMAP_GET_DIR_OP,
> +	GPIO_REGMAP_SET_DIR_OP,
> +	GPIO_REGMAP_IN,
> +	GPIO_REGMAP_OUT,
> +};
> +
>  /**
>   * struct gpio_regmap_config - Description of a generic regmap gpio_chip.
>   * @parent:		The parent device
> @@ -104,9 +138,9 @@ struct gpio_regmap_config {
>  	unsigned long regmap_irq_flags;
>  #endif
>  
> -	int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base,
> -			      unsigned int offset, unsigned int *reg,
> -			      unsigned int *mask);
> +	int (*reg_mask_xlate)(struct gpio_regmap *gpio, enum gpio_regmap_operation,
> +			      unsigned int base, unsigned int offset,
> +			      unsigned int *reg, unsigned int *mask);
>  
>  	int (*init_valid_mask)(struct gpio_chip *gc,
>  			       unsigned long *valid_mask,


  parent reply	other threads:[~2026-07-25 21:47 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23  3:42 [PATCH v7 0/9] gpio: realtek: Add support for Realtek DHC RTD1625 Yu-Chun Lin
2026-07-23  3:42 ` [PATCH v7 1/9] Revert "gpio: realtek: Add driver for Realtek DHC RTD1625 SoC" Yu-Chun Lin
2026-07-23 21:09   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 2/9] gpio: regmap: Provide default IRQ resource request and release callbacks Yu-Chun Lin
2026-07-23 21:10   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 3/9] gpio: regmap: Apply default resource callbacks for regmap IRQ chip Yu-Chun Lin
2026-07-23 16:36   ` Mathieu Dubois-Briand
2026-07-23 21:11   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 4/9] gpio: regmap: Order kernel-doc descriptions with the actual appearance Yu-Chun Lin
2026-07-23 21:11   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 5/9] gpio: regmap: Add gpio_regmap_operation to extend reg_mask_xlate callback Yu-Chun Lin
2026-07-23  6:51   ` Michael Walle
2026-07-23 11:14     ` Yu-Chun Lin [林祐君]
2026-07-23 11:20       ` Michael Walle
2026-07-24  5:47         ` Yu-Chun Lin [林祐君]
2026-07-24 10:22   ` William Breathitt Gray
2026-07-25 21:47   ` Jonathan Cameron [this message]
2026-07-23  3:42 ` [PATCH v7 6/9] gpio: regmap: Add value_xlate callback Yu-Chun Lin
2026-07-23  6:54   ` Michael Walle
2026-07-23 21:14   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 7/9] gpio: regmap: Add set_config callback Yu-Chun Lin
2026-07-23  7:01   ` Michael Walle
2026-07-23 21:15   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 8/9] gpio: regmap: Add IRQ enable/disable helpers Yu-Chun Lin
2026-07-23 21:15   ` Linus Walleij
2026-07-23  3:42 ` [PATCH v7 9/9] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC Yu-Chun Lin
2026-07-23 16:22   ` Mathieu Dubois-Briand
2026-07-24  5:49     ` Yu-Chun Lin [林祐君]
2026-07-25 13:56   ` Linus Walleij

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260725224746.01ef9757@jic23-huawei \
    --to=jic23@kernel.org \
    --cc=Michael.Hennerich@analog.com \
    --cc=andriy.shevchenko@intel.com \
    --cc=andy@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=brgl@kernel.org \
    --cc=cy.huang@realtek.com \
    --cc=dakr@kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=eleanor.lin@realtek.com \
    --cc=james.tai@realtek.com \
    --cc=linusw@kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@analog.com \
    --cc=mathieu.dubois-briand@bootlin.com \
    --cc=mwalle@kernel.org \
    --cc=nuno.sa@analog.com \
    --cc=o-takashi@sakamocchi.jp \
    --cc=tychang@realtek.com \
    --cc=u.kleine-koenig@baylibre.com \
    --cc=wbg@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox