[PATCH v1 2/9] drivers: regulator: Fixes for TPS65941 LDO voltage conversion

Jerome Neanne jneanne at baylibre.com
Thu Apr 6 17:38:13 CEST 2023


Fixes: 065a452ae6a power: regulator: tps65941: add regulator support

LDO voltage conversion was incorrect.
This was checked by writing and reading back value.

Signed-off-by: Jerome Neanne <jneanne at baylibre.com>
---
 drivers/power/regulator/tps65941_regulator.c | 71 +++++++++++++++++---
 1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/drivers/power/regulator/tps65941_regulator.c b/drivers/power/regulator/tps65941_regulator.c
index b041126775..7afd68c5c4 100644
--- a/drivers/power/regulator/tps65941_regulator.c
+++ b/drivers/power/regulator/tps65941_regulator.c
@@ -212,12 +212,55 @@ static int tps65941_ldo_enable(struct udevice *dev, int op, bool *enable)
 	return 0;
 }
 
-static int tps65941_ldo_val2volt(int val)
+static int tps65941_ldo_volt2val(int idx, int uV)
 {
-	if (val > TPS65941_LDO_VOLT_MAX_HEX || val < TPS65941_LDO_VOLT_MIN_HEX)
+	int base = TPS65941_LDO123_VOLT_MIN;
+	int max = TPS65941_LDO_VOLT_MAX;
+	int offset = TPS65941_LDO123_VSET_MIN;
+	int step = TPS65941_LDO123_STEP;
+
+	if (idx > 2) {
+		base = TPS65941_LDO4_VOLT_MIN;
+		offset = TPS65941_LDO4_VSET_MIN;
+		step = TPS65941_LDO4_STEP;
+	}
+
+	if (uV > max)
 		return -EINVAL;
-	else if (val >= TPS65941_LDO_VOLT_MIN_HEX)
-		return 600000 + (val - TPS65941_LDO_VOLT_MIN_HEX) * 50000;
+	else if (uV >= base)
+		return (uV - base) / step + offset;
+	else
+		return -EINVAL;
+}
+
+static int tps65941_ldo_val2volt(int idx, int val)
+{
+	int reg_base = TPS65941_LDO123_VSET_MIN;
+	int reg_max = TPS65941_LDO123_VSET_MAX;
+	int base = TPS65941_LDO123_VOLT_MIN;
+	int max = TPS65941_LDO_VOLT_MAX;
+	int step = TPS65941_LDO123_STEP;
+	int mask = TPS65941_LDO_VOLT_MASK >> 1;
+
+	if (idx > 2) {
+		base = TPS65941_LDO4_VOLT_MIN;
+		max = TPS65941_LDO_VOLT_MAX;
+		reg_base = TPS65941_LDO4_VSET_MIN;
+		reg_max = TPS65941_LDO4_VSET_MAX;
+		step = TPS65941_LDO4_STEP;
+		mask = TPS65941_LDO_VOLT_MASK;
+	} else {
+		val = val >> 1;
+	}
+
+	if (val > mask || val < 0)
+		return -EINVAL;
+	else if (val >= reg_max)
+		return max;
+	else if (val <= reg_base)
+		return base;
+	else if (val >= 0)
+		return base + (step * (val - reg_base));
 	else
 		return -EINVAL;
 }
@@ -227,7 +270,9 @@ static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
 	unsigned int hex, adr;
 	int ret;
 	struct dm_regulator_uclass_plat *uc_pdata;
+	int idx;
 
+	idx = dev->driver_data - 1;
 	uc_pdata = dev_get_uclass_plat(dev);
 
 	if (op == PMIC_OP_GET)
@@ -240,7 +285,8 @@ static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
 		return ret;
 
 	ret &= TPS65941_LDO_VOLT_MASK;
-	ret = tps65941_ldo_val2volt(ret);
+	ret = tps65941_ldo_val2volt(idx, ret);
+
 	if (ret < 0)
 		return ret;
 
@@ -249,12 +295,21 @@ static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
 		return 0;
 	}
 
-	hex = tps65941_buck_volt2val(*uV);
+	/* LDO1, LDO2 & LDO3 in BYPASS mode only supports 1.7V min to 3.6V max */
+	if (idx < 2 &&
+	    (ret & BIT(TPS65941_LDO123_BYP_CONFIG)) &&
+		*uV < TPS65941_LDO123_VOLT_BYP_MIN)
+		return -EINVAL;
+
+	hex = tps65941_ldo_volt2val(idx, *uV);
 	if (hex < 0)
 		return hex;
 
-	ret &= 0x0;
-	ret = hex;
+	if (idx < 2)
+		hex = hex << 1;
+
+	ret &= ~TPS65941_LDO_VOLT_MASK;
+	ret |= hex;
 
 	ret = pmic_reg_write(dev->parent, adr, ret);
 
-- 
2.25.1



More information about the U-Boot mailing list