summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorYu-Chun Lin <eleanor.lin@realtek.com>2026-07-26 20:51:57 +0800
committerBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>2026-07-30 11:05:07 +0200
commit5f28e3dbd23199c778f5339c0d4488820435f6d5 (patch)
tree076a39d2b5a051ef7f8846f959bae9d290ddf394 /drivers/gpio
parent6c53312b7e2d9a972e509f5bac002e169e241eca (diff)
downloadlinux-next-5f28e3dbd23199c778f5339c0d4488820435f6d5.tar.gz
linux-next-5f28e3dbd23199c778f5339c0d4488820435f6d5.zip
gpio: regmap: Add value_xlate callback
Introduce a new optional 'value_xlate' callback. This routine allows drivers to translate or modify the register value and mask immediately before a write operation. It is particularly useful for hardware that requires additional control bits, such as a write-enable bit, to be appended to the data dynamically. Reviewed-by: Michael Walle <mwalle@kernel.org> Reviewed-by: Linus Walleij <linusw@kernel.org> Suggested-by: Michael Walle <mwalle@kernel.org> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com> Link: https://patch.msgid.link/20260726125209.140307-7-eleanor.lin@realtek.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-regmap.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c
index ceab805d053c..cff7db8036f7 100644
--- a/drivers/gpio/gpio-regmap.c
+++ b/drivers/gpio/gpio-regmap.c
@@ -45,6 +45,12 @@ struct gpio_regmap {
unsigned int base, unsigned int offset,
unsigned int *reg, unsigned int *mask);
+ int (*value_xlate)(struct gpio_regmap *gpio,
+ enum gpio_regmap_operation op,
+ unsigned int base, unsigned int offset,
+ unsigned int reg, unsigned int *mask,
+ unsigned int *val);
+
void *driver_data;
};
@@ -114,6 +120,13 @@ static int gpio_regmap_set(struct gpio_chip *chip, unsigned int offset,
else
mask_val = 0;
+ if (gpio->value_xlate) {
+ ret = gpio->value_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset,
+ reg, &mask, &mask_val);
+ if (ret)
+ return ret;
+ }
+
/* ignore input values which shadow the old output value */
if (gpio->reg_dat_base == gpio->reg_set_base)
ret = regmap_write_bits(gpio->regmap, reg, mask, mask_val);
@@ -127,7 +140,7 @@ static int gpio_regmap_set_with_clear(struct gpio_chip *chip,
unsigned int offset, int val)
{
struct gpio_regmap *gpio = gpiochip_get_data(chip);
- unsigned int base, reg, mask;
+ unsigned int base, reg, mask, value = 0;
int ret;
if (val)
@@ -139,6 +152,13 @@ static int gpio_regmap_set_with_clear(struct gpio_chip *chip,
if (ret)
return ret;
+ if (gpio->value_xlate) {
+ ret = gpio->value_xlate(gpio, GPIO_REGMAP_SET_OP, base, offset,
+ reg, &mask, &value);
+ if (ret)
+ return ret;
+ }
+
return regmap_write(gpio->regmap, reg, mask);
}
@@ -248,6 +268,13 @@ static int gpio_regmap_set_direction(struct gpio_chip *chip,
else
val = output ? mask : 0;
+ if (gpio->value_xlate) {
+ ret = gpio->value_xlate(gpio, GPIO_REGMAP_SET_DIR_OP, base, offset,
+ reg, &mask, &val);
+ if (ret)
+ return ret;
+ }
+
return regmap_update_bits(gpio->regmap, reg, mask, val);
}
@@ -415,6 +442,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
if (!gpio->reg_mask_xlate)
gpio->reg_mask_xlate = gpio_regmap_simple_xlate;
+ gpio->value_xlate = config->value_xlate;
+
ret = gpiochip_add_data(chip, gpio);
if (ret < 0)
goto err_free_bitmap_output;