Commit 3c87b351 authored by Andrej Picej's avatar Andrej Picej Committed by Alexandre Belloni
Browse files

rtc: rv3028: Add support for "aux-voltage-chargeable" property



Property "trickle-resistor-ohms" allows us to set trickle charger
resistor. However there is no possibility to disable it afterwards.

Add support for "aux-voltage-chargeable" property which can be used to
enable/disable the trickle charger circuit explicitly. The default
behavior of the code is kept as it is!

Additionally, lets make sure we only update internal EEPROM in case of a
change. This prevents wear due to excessive EEPROM writes on each probe.

Signed-off-by: default avatarAndrej Picej <andrej.picej@norik.com>
Link: https://lore.kernel.org/r/20230623081533.76334-1-andrej.picej@norik.com


Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
parent 766c3f8a
Loading
Loading
Loading
Loading
+61 −19
Original line number Diff line number Diff line
@@ -855,11 +855,68 @@ static const struct regmap_config regmap_config = {
        .max_register = 0x37,
};

static u8 rv3028_set_trickle_charger(struct rv3028_data *rv3028,
				     struct i2c_client *client)
{
	int ret, val_old, val;
	u32 ohms, chargeable;

	ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &val_old);
	if (ret < 0)
		return ret;

	/* mask out only trickle charger bits */
	val_old = val_old & (RV3028_BACKUP_TCE | RV3028_BACKUP_TCR_MASK);
	val = val_old;

	/* setup trickle charger */
	if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
				      &ohms)) {
		int i;

		for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
			if (ohms == rv3028_trickle_resistors[i])
				break;

		if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
			/* enable trickle charger and its resistor */
			val = RV3028_BACKUP_TCE | i;
		} else {
			dev_warn(&client->dev, "invalid trickle resistor value\n");
		}
	}

	if (!device_property_read_u32(&client->dev, "aux-voltage-chargeable",
				      &chargeable)) {
		switch (chargeable) {
		case 0:
			val &= ~RV3028_BACKUP_TCE;
			break;
		case 1:
			val |= RV3028_BACKUP_TCE;
			break;
		default:
			dev_warn(&client->dev,
				 "unsupported aux-voltage-chargeable value\n");
			break;
		}
	}

	/* only update EEPROM if changes are necessary */
	if (val_old != val) {
		ret = rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_TCE |
						RV3028_BACKUP_TCR_MASK, val);
		if (ret)
			return ret;
	}

	return ret;
}

static int rv3028_probe(struct i2c_client *client)
{
	struct rv3028_data *rv3028;
	int ret, status;
	u32 ohms;
	struct nvmem_config nvmem_cfg = {
		.name = "rv3028_nvram",
		.word_size = 1,
@@ -937,24 +994,9 @@ static int rv3028_probe(struct i2c_client *client)
	if (ret)
		return ret;

	/* setup trickle charger */
	if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
				      &ohms)) {
		int i;

		for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
			if (ohms == rv3028_trickle_resistors[i])
				break;

		if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
			ret = rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_TCE |
						 RV3028_BACKUP_TCR_MASK, RV3028_BACKUP_TCE | i);
	ret = rv3028_set_trickle_charger(rv3028, client);
	if (ret)
		return ret;
		} else {
			dev_warn(&client->dev, "invalid trickle resistor value\n");
		}
	}

	ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
	if (ret)