diff options
| author | Mark Brown <broonie@kernel.org> | 2026-03-24 22:37:47 +0300 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-03-24 22:37:47 +0300 |
| commit | 3dacdda5e643303a3e56ad303312dfcf72b6fafe (patch) | |
| tree | 18400e613d1502d7b3c11ad80537b6832aa796f9 | |
| parent | 57fca3a8ed8e8e42b456bef93055e8b73b1e358f (diff) | |
| parent | 6c2505e185b09e506542956f473631cc09afc403 (diff) | |
| download | linux-3dacdda5e643303a3e56ad303312dfcf72b6fafe.tar.xz | |
regulator: da91xx: Allow caching of buck registers when no GPIO input control is configured
André Svensson <andre.svensson@axis.com> says:
This series introduces a boolean DT property, dlg,no-gpio-control, for
the DA91xx regulators. Use this property to indicate that GPIO control
is not configured with the functions DVC/RELOAD/EN, allowing buck
registers to be cached.
The DA9121 driver checks dlg,no-gpio-control and updates regmap_config's
volatile_table if the property is present. Buck registers are removed
from the volatile_table if the property is present, enabling caching of
the registers, which removes I2C reads when performing an I2C write to
the buck registers.
Link: https://patch.msgid.link/20260320-no-gpio-control-v2-0-dbc938e462cb@axis.com
Signed-off-by: Mark Brown <broonie@kernel.org>
| -rw-r--r-- | Documentation/devicetree/bindings/regulator/dlg,da9121.yaml | 49 | ||||
| -rw-r--r-- | drivers/regulator/da9121-regulator.c | 43 |
2 files changed, 85 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml b/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml index 13b3f75f8e5e..ce76eb5b85bd 100644 --- a/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml +++ b/Documentation/devicetree/bindings/regulator/dlg,da9121.yaml @@ -81,6 +81,14 @@ properties: Specify the polling period, measured in milliseconds, between interrupt status update checks. Range 1000-10000 ms. + dlg,no-gpio-control: + type: boolean + description: | + Available GPIO input pins of the regulator are strapped to fixed levels, therefore + GPIO configurable input functions, DVC/RELOAD/EN, cannot dynamically update BUCK + registers. GPIO pins connected as output pins are not required to be strapped to a + fixed level. Not allowed together with enable-gpios. + regulators: type: object additionalProperties: false @@ -134,6 +142,17 @@ allOf: properties: buck2: false + - if: + required: + - dlg,no-gpio-control + then: + properties: + regulators: + patternProperties: + "^buck([1-2])$": + properties: + enable-gpios: false + additionalProperties: false examples: @@ -169,6 +188,36 @@ examples: }; - | + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/regulator/dlg,da9121-regulator.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + pmic@68 { + compatible = "dlg,da9121"; + reg = <0x68>; + + interrupt-parent = <&gpio6>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + + dlg,irq-polling-delay-passive-ms = <2000>; + dlg,no-gpio-control; + + regulators { + DA9121_BUCK: buck1 { + regulator-name = "BUCK1"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1900000>; + regulator-min-microamp = <7000000>; + regulator-max-microamp = <20000000>; + regulator-boot-on; + regulator-initial-mode = <DA9121_BUCK_MODE_AUTO>; + }; + }; + }; + }; + + - | #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/regulator/dlg,da9121-regulator.h> diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index ef161eb0ca27..2b150bb4d471 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; |
