On Wed, 12 Nov 2025 10:45:24 +0100 "Kory Maincent (TI.com)" kory.maincent@bootlin.com wrote:
The TPS65214 PMIC variant has a LOCK_REG register that prevents writes to nearly all registers.
Implement custom regmap operations that automatically unlock before writes and re-lock afterwards for TPS65214, while leaving other chip variants unaffected.
The implementation follows the regmap-i2c design pattern.
After some thought and internal discussions, I think it is better to unlock the registers only one time in the probe instead of adding burden in each regmap write. I will rewrite this patch. Shree I will remove your reviewed-by due to the change.
pw-bot: cr
Cc: stable@vger.kernel.org Fixes: 7947219ab1a2d ("mfd: tps65219: Add support for TI TPS65214 PMIC") Reviewed-by: Shree Ramamoorthy s-ramamoorthy@ti.com Signed-off-by: Kory Maincent (TI.com) kory.maincent@bootlin.com
Changes in v3:
- Removed unused variable.
Changes in v2:
- Setup a custom regmap_bus only for the TPS65214 instead of checking the chip_id every time reg_write is called.
drivers/mfd/tps65219.c | 49 +++++++++++++++++++++++++++++++++++++++++++- include/linux/mfd/tps65219.h | 2 ++ 2 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c index 65a952555218d..d31e808faab1f 100644 --- a/drivers/mfd/tps65219.c +++ b/drivers/mfd/tps65219.c @@ -473,6 +473,48 @@ static const struct tps65219_chip_data chip_info_table[] = { }, }; +static int tps65214_reg_write(void *context, unsigned int reg, unsigned int val) +{
- struct i2c_client *i2c = context;
- int ret;
- if (val > 0xff || reg > 0xff)
return -EINVAL;- ret = i2c_smbus_write_byte_data(i2c, TPS65214_REG_LOCK,
TPS65214_LOCK_ACCESS_CMD);- if (ret)
return ret;- ret = i2c_smbus_write_byte_data(i2c, reg, val);
- if (ret)
return ret;- return i2c_smbus_write_byte_data(i2c, TPS65214_REG_LOCK, 0);
+}
+static int tps65214_reg_read(void *context, unsigned int reg, unsigned int *val) +{
- struct i2c_client *i2c = context;
- int ret;
- if (reg > 0xff)
return -EINVAL;- ret = i2c_smbus_read_byte_data(i2c, reg);
- if (ret < 0)
return ret;- *val = ret;
- return 0;
+}
+static const struct regmap_bus tps65214_regmap_bus = {
- .reg_write = tps65214_reg_write,
- .reg_read = tps65214_reg_read,
+};
static int tps65219_probe(struct i2c_client *client) { struct tps65219 *tps; @@ -491,7 +533,12 @@ static int tps65219_probe(struct i2c_client *client) chip_id = (uintptr_t)i2c_get_match_data(client); pmic = &chip_info_table[chip_id];
- tps->regmap = devm_regmap_init_i2c(client, &tps65219_regmap_config);
- if (chip_id == TPS65214)
tps->regmap = devm_regmap_init(&client->dev,&tps65214_regmap_bus, client,&tps65219_regmap_config);- else
tps->regmap = devm_regmap_init_i2c(client,&tps65219_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); dev_err(tps->dev, "Failed to allocate register map: %d\n", ret); diff --git a/include/linux/mfd/tps65219.h b/include/linux/mfd/tps65219.h index 55234e771ba73..198ee319dd1db 100644 --- a/include/linux/mfd/tps65219.h +++ b/include/linux/mfd/tps65219.h @@ -149,6 +149,8 @@ enum pmic_id { #define TPS65215_ENABLE_LDO2_EN_MASK BIT(5) #define TPS65214_ENABLE_LDO1_EN_MASK BIT(5) #define TPS65219_ENABLE_LDO4_EN_MASK BIT(6) +/* Register Lock */ +#define TPS65214_LOCK_ACCESS_CMD 0x5a /* power ON-OFF sequence slot */ #define TPS65219_BUCKS_LDOS_SEQUENCE_OFF_SLOT_MASK GENMASK(3, 0) #define TPS65219_BUCKS_LDOS_SEQUENCE_ON_SLOT_MASK GENMASK(7, 4)