From: AndrĂ© Svensson Date: Fri, 20 Mar 2026 07:33:25 +0000 (+0100) Subject: regulator: da9121: Allow caching BUCK registers X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6c2505e185b09e506542956f473631cc09afc403;p=thirdparty%2Flinux.git regulator: da9121: Allow caching BUCK registers Some BUCK registers may change without software writes when GPIO pins are configured for functions DVC/RELOAD/EN. If the board does not use these pin-controlled features, caching is possible. Caching BUCK registers removes unnecessary I2C reads when performing register updates. For example, updating regulator mode can result in two I2C reads, one from the regulator core regulator_set_mode() and one from the DA9121 driver, where da9121_buck_set_mode() uses regmap_update_bits() (read/modify/write). Check for the optional DT property dlg,no-gpio-control. When present, select the regmap configuration that does not mark the BUCK1 register block (DA9121_REG_BUCK_BUCK1_0..DA9121_REG_BUCK_BUCK1_6) as volatile, so that regmap can cache BUCK1 registers and avoid unnecessary I2C reads. The property dlg,no-gpio-control is required to ensure that BUCK1 registers can be cached, as the absence of relevant GPIO DT properties does not imply that the RELOAD/DVC/EN GPIO functions are unused. These functions are provided by DA91xx GPIO pins and may be controlled by external hardware without corresponding GPIO DT properties. The dlg,no-gpio-control property explicitly indicates that none of these GPIO functions are used. The dlg,no-gpio-control property is mutually exclusive with enable-gpios, regardless of whether the referenced GPIO is connected to a GPIO pin or the IC_EN pin, since pulling IC_EN low powers down the regulator and registers are reinitialized at startup, leaving cached values stale. Co-developed-by: Waqar Hameed Signed-off-by: Waqar Hameed Signed-off-by: AndrĂ© Svensson Link: https://patch.msgid.link/20260320-no-gpio-control-v2-2-dbc938e462cb@axis.com Signed-off-by: Mark Brown --- diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index ef161eb0ca277..2b150bb4d4712 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -400,8 +400,14 @@ static int da9121_of_parse_cb(struct device_node *np, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "da9121-enable"); - if (!IS_ERR(ena_gpiod)) + if (!IS_ERR(ena_gpiod)) { + if (of_property_read_bool(chip->dev->of_node, "dlg,no-gpio-control")) { + gpiod_put(ena_gpiod); + dev_err(chip->dev, "dlg,no-gpio-control conflicts with enable-gpios\n"); + return -EINVAL; + } config->ena_gpiod = ena_gpiod; + } if (variant_parameters[chip->variant_id].num_bucks == 2) { uint32_t ripple_cancel; @@ -864,6 +870,21 @@ static const struct regmap_access_table da9121_volatile_table = { .n_yes_ranges = ARRAY_SIZE(da9121_volatile_ranges), }; +/* + * When GPIO functions DVC/RELOAD/EN are not used, the registers in the range + * DA9121_REG_BUCK_BUCK1_0 to DA9121_REG_BUCK_BUCK1_6 need not be volatile + * because register writes to these registers can only be performed via I2C. + */ +static const struct regmap_range da9121_volatile_ranges_no_gpio_ctrl[] = { + regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_EVENT_2), + regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1), +}; + +static const struct regmap_access_table da9121_volatile_table_no_gpio_ctrl = { + .yes_ranges = da9121_volatile_ranges_no_gpio_ctrl, + .n_yes_ranges = ARRAY_SIZE(da9121_volatile_ranges_no_gpio_ctrl), +}; + /* DA9121 regmap config for 1 channel variants */ static const struct regmap_config da9121_1ch_regmap_config = { .reg_bits = 8, @@ -994,10 +1015,18 @@ static int da9121_assign_chip_model(struct i2c_client *i2c, struct da9121 *chip) { const struct regmap_config *regmap; + struct regmap_config regmap_config_1ch = da9121_1ch_regmap_config; + struct regmap_config regmap_config_2ch = da9121_2ch_regmap_config; + int ret = 0; chip->dev = &i2c->dev; + if (of_property_read_bool(i2c->dev.of_node, "dlg,no-gpio-control")) { + regmap_config_1ch.volatile_table = &da9121_volatile_table_no_gpio_ctrl; + regmap_config_2ch.volatile_table = &da9121_volatile_table_no_gpio_ctrl; + } + /* Use configured subtype to select the regulator descriptor index and * register map, common to both consumer and automotive grade variants */ @@ -1005,29 +1034,29 @@ static int da9121_assign_chip_model(struct i2c_client *i2c, case DA9121_SUBTYPE_DA9121: case DA9121_SUBTYPE_DA9130: chip->variant_id = DA9121_TYPE_DA9121_DA9130; - regmap = &da9121_1ch_regmap_config; + regmap = ®map_config_1ch; break; case DA9121_SUBTYPE_DA9217: chip->variant_id = DA9121_TYPE_DA9217; - regmap = &da9121_1ch_regmap_config; + regmap = ®map_config_1ch; break; case DA9121_SUBTYPE_DA9122: case DA9121_SUBTYPE_DA9131: chip->variant_id = DA9121_TYPE_DA9122_DA9131; - regmap = &da9121_2ch_regmap_config; + regmap = ®map_config_2ch; break; case DA9121_SUBTYPE_DA9220: case DA9121_SUBTYPE_DA9132: chip->variant_id = DA9121_TYPE_DA9220_DA9132; - regmap = &da9121_2ch_regmap_config; + regmap = ®map_config_2ch; break; case DA9121_SUBTYPE_DA9141: chip->variant_id = DA9121_TYPE_DA9141; - regmap = &da9121_1ch_regmap_config; + regmap = ®map_config_1ch; break; case DA9121_SUBTYPE_DA9142: chip->variant_id = DA9121_TYPE_DA9142; - regmap = &da9121_2ch_regmap_config; + regmap = ®map_config_2ch; break; default: return -EINVAL;