[PATCH v6 2/8] gpio: regmap: Bypass cache for aliased inputs

Sander Vanheule posted 8 patches 3 months, 2 weeks ago
There is a newer version of this series
[PATCH v6 2/8] gpio: regmap: Bypass cache for aliased inputs
Posted by Sander Vanheule 3 months, 2 weeks ago
GPIO chips often have data input and output registers aliased to the
same offset. The output register is non-valitile and could in theory be
cached. The input register however is volatile by nature and hence
should not be cached, resulting in different requirements for reads and
writes.

The generic gpio chip implementation stores a shadow value of the pin
output data, which is updated and written to hardware on output data
changes in bgpio_set(), bgpio_set_set(). Pin input values are always
obtained by reading the aliased data register from hardware.

For gpio-regmap the situation is more complex as the output data could
be in multiple registers, but we can use the regmap cache to shadow the
output values when marking the data registers as non-volatile. By using
regmap_read_bypassed() we can still treat the input values as volatile,
irrespective of the regmap config. This ensures proper functioning of
writing the output register with regmap_write_bits(), which will then
use and update the cache only on data writes, gaining some performance
from the cached output values.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Michael Walle <mwalle@kernel.org>
--
Changes since RFC:
  - Add review tags
  - Slightly reworded the commit message
---
 drivers/gpio/gpio-regmap.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c
index ba3c19206ccf..afecacf7607f 100644
--- a/drivers/gpio/gpio-regmap.c
+++ b/drivers/gpio/gpio-regmap.c
@@ -81,7 +81,11 @@ static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset)
 	if (ret)
 		return ret;
 
-	ret = regmap_read(gpio->regmap, reg, &val);
+	/* ensure we don't spoil any register cache with pin input values */
+	if (gpio->reg_dat_base == gpio->reg_set_base)
+		ret = regmap_read_bypassed(gpio->regmap, reg, &val);
+	else
+		ret = regmap_read(gpio->regmap, reg, &val);
 	if (ret)
 		return ret;
 
-- 
2.51.0
Re: [PATCH v6 2/8] gpio: regmap: Bypass cache for aliased inputs
Posted by Bartosz Golaszewski 3 months, 2 weeks ago
On Tue, Oct 21, 2025 at 4:24 PM Sander Vanheule <sander@svanheule.net> wrote:
>
> GPIO chips often have data input and output registers aliased to the
> same offset. The output register is non-valitile and could in theory be
> cached. The input register however is volatile by nature and hence
> should not be cached, resulting in different requirements for reads and
> writes.
>
> The generic gpio chip implementation stores a shadow value of the pin
> output data, which is updated and written to hardware on output data
> changes in bgpio_set(), bgpio_set_set(). Pin input values are always
> obtained by reading the aliased data register from hardware.
>
> For gpio-regmap the situation is more complex as the output data could
> be in multiple registers, but we can use the regmap cache to shadow the
> output values when marking the data registers as non-volatile. By using
> regmap_read_bypassed() we can still treat the input values as volatile,
> irrespective of the regmap config. This ensures proper functioning of
> writing the output register with regmap_write_bits(), which will then
> use and update the cache only on data writes, gaining some performance
> from the cached output values.
>
> Signed-off-by: Sander Vanheule <sander@svanheule.net>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Reviewed-by: Michael Walle <mwalle@kernel.org>
> --
> Changes since RFC:
>   - Add review tags
>   - Slightly reworded the commit message

Nit: changelog should not be part of the commit message, I dropped it.

Bart

> ---
>  drivers/gpio/gpio-regmap.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c
> index ba3c19206ccf..afecacf7607f 100644
> --- a/drivers/gpio/gpio-regmap.c
> +++ b/drivers/gpio/gpio-regmap.c
> @@ -81,7 +81,11 @@ static int gpio_regmap_get(struct gpio_chip *chip, unsigned int offset)
>         if (ret)
>                 return ret;
>
> -       ret = regmap_read(gpio->regmap, reg, &val);
> +       /* ensure we don't spoil any register cache with pin input values */
> +       if (gpio->reg_dat_base == gpio->reg_set_base)
> +               ret = regmap_read_bypassed(gpio->regmap, reg, &val);
> +       else
> +               ret = regmap_read(gpio->regmap, reg, &val);
>         if (ret)
>                 return ret;
>
> --
> 2.51.0
>