[Letux-kernel] [PATCH 5/6] drivers: power: supply: bq2429x: consolidate register conversion table methodology

Nick Elsmore nicholaselsmore at gmail.com
Thu Aug 13 03:18:30 CEST 2020


Signed-off-by: Nick Elsmore <nicholaselsmore at gmail.com>

---
 drivers/power/supply/bq2429x_charger.c | 167 +++++++++++++++++--------
 1 file changed, 113 insertions(+), 54 deletions(-)

diff --git a/drivers/power/supply/bq2429x_charger.c
b/drivers/power/supply/bq2429x_charger.c
index aaf8c11ab7ca..0fa69eb152e4 100644
--- a/drivers/power/supply/bq2429x_charger.c
+++ b/drivers/power/supply/bq2429x_charger.c
@@ -231,18 +231,32 @@ struct bq2429x_device_info {

 /* helper tables */

-static const unsigned int iinlim_table[] = {
+enum bq2429x_table_ids {
+	/* range tables */
+	TBL_VINDPM = 0,
+	TBL_ICHG,
+	TBL_IPRECHG,
+	TBL_ITERM,
+	TBL_VREG,
+
+	/* lookup tables */
+	TBL_IINLIM,
+	TBL_BOOSTV,
+	TBL_SYS_MIN,
+};
+
+static const unsigned int bq2429x_iinlim_tbl[] = {
 	100000,
 	150000,
 	500000,
 	900000,
 	1000000,
-	1500000,	// for bq24, mp26 has 1800000
+	1500000,
 	2000000,
-	3000000,
+	3000000
 };

-static const unsigned int vsys_VSEL_table[] = {
+static const unsigned int bq2429x_sys_min_tbl[] = {
 	3000000,
 	3100000,
 	3200000,
@@ -253,7 +267,7 @@ static const unsigned int vsys_VSEL_table[] = {
 	3700000,
 };

-static const unsigned int otg_VSEL_table[] = {
+static const unsigned int bq2429x_boostv_tbl[] = {
 	4550000,
 	4614000,
 	4678000,
@@ -272,6 +286,67 @@ static const unsigned int otg_VSEL_table[] = {
 	5510000,
 };

+struct bq2429x_range {
+	unsigned int min;
+	unsigned int max;
+	unsigned int step;
+};
+
+struct bq2429x_lookup {
+	const unsigned int *tbl;
+	int size;
+};
+
+static const union {
+	struct bq2429x_range rt;
+	struct bq2429x_lookup lt;
+} bq2429x_tables[] = {
+	[TBL_VINDPM]	= { .rt = {3880000, 5080000, 80000} },
+	[TBL_ICHG]	= { .rt = {512000,  3008000, 64000} },
+	[TBL_IPRECHG]	= { .rt = {128000,  2048000, 128000} },
+	[TBL_ITERM]	= { .rt = {128000,  2048000, 128000} },
+	[TBL_VREG]	= { .rt = {3504000, 4400000, 16000} },
+
+	[TBL_IINLIM]	= { .lt = {bq2429x_iinlim_tbl, ARRAY_SIZE(bq2429x_iinlim_tbl)} },
+	[TBL_BOOSTV]	= { .lt = {bq2429x_boostv_tbl, ARRAY_SIZE(bq2429x_boostv_tbl)} },
+	[TBL_SYS_MIN]	= { .lt = {bq2429x_sys_min_tbl,
ARRAY_SIZE(bq2429x_sys_min_tbl)} },
+};
+
+static int bq2429x_find_idx(u32 value, enum bq2429x_table_ids id)
+{
+	int idx;
+
+	if ((id > ARRAY_SIZE(bq2429x_tables)) || id < 0)
+		return -EINVAL;
+
+	if (id >= TBL_IINLIM) {
+		const u32 *tbl = bq2429x_tables[id].lt.tbl;
+		u32 tbl_size = bq2429x_tables[id].lt.size;
+
+		for (idx = 1; idx < tbl_size && tbl[idx] <= value; idx++);
+		idx -= 1;
+
+	} else {
+		const struct bq2429x_range *tbl = &bq2429x_tables[id].rt;
+
+		idx = (value - tbl->min) / tbl->step;
+	}
+
+	return idx;
+}
+
+static u32 bq2429x_find_val(u8 idx, enum bq2429x_table_ids id)
+{
+	const struct bq2429x_range *tbl;
+
+	if (id >= TBL_IINLIM)
+		return bq2429x_tables[id].lt.tbl[idx];
+
+	tbl = &bq2429x_tables[id].rt;
+
+	return (idx * tbl->step) + tbl->min;
+}
+
 /*  * Common code for BQ24296 devices read  */
@@ -382,7 +457,7 @@ static int bq2429x_get_vindpm_uV(struct
bq2429x_device_info *di)
 		return ret;
 	}

-	return 3880000 + 80000 * ret;
+	return bq2429x_find_val(ret, TBL_VINDPM);
 }

 static int bq2429x_input_current_limit_uA(struct bq2429x_device_info *di)
@@ -407,37 +482,28 @@ static int bq2429x_input_current_limit_uA(struct
bq2429x_device_info *di)
 	if (di->id->driver_data == CHIP_MP2624 && (ret == 5))
 		return 1800000;

-	return iinlim_table[ret];
+	return bq2429x_find_val(ret, TBL_IINLIM);
 }

 static int bq2429x_set_input_current_limit_uA(struct bq2429x_device_info *di,
 					      int uA)
 {
 	u8 hiz = EN_HIZ_DISABLE;
-	u8 data = 0;
+	int data;
 	int ret;

 	dev_dbg(di->dev, "%s(%d)\n", __func__, uA);

 	if (uA < 80000)		/* includes negative current limit */
 		hiz = EN_HIZ_ENABLE;
-	else if (uA < 120000)
-		data = 0;
-	else if (uA < 400000)
-		data = 1;
-	else if (uA < 700000)
-		data = 2;
-	else if (uA < 1000000)
-		data = 3;
-	else if (uA < 1200000)
-		data = 4;
-// depends on bq24 vs. mp26
-	else if (uA < 1800000)
+
+	data = bq2429x_find_idx(uA, TBL_IINLIM);
+	if (data < 0)
+		return data;
+
+	/* mp26 idx 5 is 1800000 */
+	if (uA > 1200000 && uA < 2200000)
 		data = 5;
-	else if (uA < 2200000)
-		data = 6;
-	else
-		data = 7;

 	ret = bq2429x_field_write(di, F_IINLIM, data);
 	if (ret < 0) {
@@ -466,7 +532,7 @@ static int bq2429x_get_charge_current_uA(struct
bq2429x_device_info *di)
 		return ret;
 	}

-	return 64000 * ret + 512000;
+	return bq2429x_find_val(ret, TBL_ICHG);
 }

 static int bq2429x_set_charge_current_uA(struct bq2429x_device_info
*di, int uA)
@@ -474,11 +540,9 @@ static int bq2429x_set_charge_current_uA(struct
bq2429x_device_info *di, int uA)
 	int data;
 	int ret;

-	if (uA < 0)
-		return -EINVAL;
-
-	data = (uA - 512000 + 32000) / 64000;
-	data = min(0x27, max(data, 0));	/* limit to 512 mA .. 3008 mA */
+	data = bq2429x_find_idx(uA, TBL_ICHG);
+	if (data < 0)
+		return data;

 	ret = bq2429x_field_write(di, F_ICHG, data);
 	if (ret < 0) {
@@ -500,7 +564,7 @@ static int bq2429x_get_precharge_current_uA(struct
bq2429x_device_info *di)
 		return ret;
 	}

-	return 128000 * ret + 128000;
+	return bq2429x_find_val(ret, TBL_IPRECHG);
 }

 static int bq2429x_set_precharge_current_uA(struct
bq2429x_device_info *di, int uA)
@@ -508,11 +572,9 @@ static int
bq2429x_set_precharge_current_uA(struct bq2429x_device_info *di, int
 	int data;
 	int ret;

-	if (uA < 0)
-		return -EINVAL;
-
-	data = (uA - 128000 + 64000) / 128000;
-	data = min(0xf, max(data, 0));	/* limit to 128 mA .. 2048 mA */
+	data = bq2429x_find_idx(uA, TBL_IPRECHG);
+	if (data < 0)
+		return data;

 	ret = bq2429x_field_write(di, F_IPRECHG, data);
 	if (ret < 0) {
@@ -527,11 +589,9 @@ static int
bq2429x_set_charge_term_current_uA(struct bq2429x_device_info *di, in
 	int data;
 	int ret;

-	if (uA < 0)
-		return -EINVAL;
-
-	data = (uA - 128000 + 64000) / 128000;
-	data = min(0xf, max(data, 0));	/* limit to 128 mA .. 2048 mA */
+	data = bq2429x_find_idx(uA, TBL_ITERM);
+	if (data < 0)
+		return data;

 	ret = bq2429x_field_write(di, F_ITERM, data);
 	if (ret < 0) {
@@ -577,9 +637,9 @@ static int bq2429x_get_vsys_voltage_uV(struct
bq2429x_device_info *di)
 		return ret;

 	dev_dbg(di->dev, " => %d uV\n",
-		vsys_VSEL_table[ret]);
+		bq2429x_find_val(ret, TBL_SYS_MIN));

-	return vsys_VSEL_table[ret];
+	return bq2429x_find_val(ret, TBL_SYS_MIN);
 }

 static int bq2429x_set_vsys_voltage_uV(struct bq2429x_device_info *di,
@@ -587,7 +647,7 @@ static int bq2429x_set_vsys_voltage_uV(struct
bq2429x_device_info *di,
 {
 	dev_dbg(di->dev, "%s(%d, %d)\n", __func__, min_uV, max_uV);

-// revisit: the driver should select the voltage closest to min_uV by
scanning vsys_VSEL_table
+// revisit: the driver should select the voltage closest to min_uV by
scanning TBL_SYS_MIN

 	return 0;	/* disabled/untested */
 }
@@ -604,9 +664,9 @@ static int bq2429x_get_otg_voltage_uV(struct
bq2429x_device_info *di)
 		return ret;

 	dev_dbg(di->dev, " => %d uV\n",
-		otg_VSEL_table[ret]);
+		bq2429x_find_val(ret, TBL_BOOSTV));

-	return otg_VSEL_table[ret];
+	return bq2429x_find_val(ret, TBL_BOOSTV);
 }

 static int bq2429x_set_otg_voltage_uV(struct bq2429x_device_info *di,
@@ -747,10 +807,9 @@ static int bq2429x_init_registers(struct
bq2429x_device_info *di)
 	max_uV = min_t(int, max_uV, di->bat_info.voltage_max_design_uv);

 // MP2624 has slightly different scale and offset
-
-	bits = (max_uV - 3504000) / 16000;
-	bits = max(bits, 0);
-	bits = min(bits, 63);
+	bits = bq2429x_find_idx(max_uV, TBL_VREG);
+	if (bits < 0)
+		return bits;

 	dev_dbg(di->dev, "%s(): translated vbatt_max=%u and VSYS_max=%u to
VREG=%u (%02x)\n",
 		__func__,
@@ -1505,13 +1564,13 @@ static int bq2429x_regulator_init(struct
bq2429x_device_info *di)
 		switch (i) {
 		case VSYS_REGULATOR:
 			di->desc[i].ops = &vsys_ops;
-			di->desc[i].n_voltages = ARRAY_SIZE(vsys_VSEL_table);
-			di->desc[i].volt_table = vsys_VSEL_table;
+			di->desc[i].n_voltages = ARRAY_SIZE(bq2429x_sys_min_tbl);
+			di->desc[i].volt_table = bq2429x_sys_min_tbl;
 			break;
 		case OTG_REGULATOR:
 			di->desc[i].ops = &otg_ops;
-			di->desc[i].n_voltages = ARRAY_SIZE(otg_VSEL_table);
-			di->desc[i].volt_table = otg_VSEL_table;
+			di->desc[i].n_voltages = ARRAY_SIZE(bq2429x_boostv_tbl);
+			di->desc[i].volt_table = bq2429x_boostv_tbl;
 			break;
 		}

-- 
2.25.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.goldelico.com/pipermail/letux-kernel/attachments/20200812/3794cd23/attachment.htm>


More information about the Letux-kernel mailing list