<div dir="ltr"><div><br></div><div>Signed-off-by: Nick Elsmore <<a href="mailto:nicholaselsmore@gmail.com">nicholaselsmore@gmail.com</a>></div><div><pre style="margin:0px;line-height:125%">---
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 @@ <span style="font-weight:bold">struct</span> bq2429x_device_info {
<span style="font-style:italic">/* helper tables */</span>
-<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> iinlim_table[] = {
+<span style="font-weight:bold">enum</span> bq2429x_table_ids {
+ <span style="font-style:italic">/* range tables */</span>
+ TBL_VINDPM = 0,
+ TBL_ICHG,
+ TBL_IPRECHG,
+ TBL_ITERM,
+ TBL_VREG,
+
+ <span style="font-style:italic">/* lookup tables */</span>
+ TBL_IINLIM,
+ TBL_BOOSTV,
+ TBL_SYS_MIN,
+};
+
+<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> bq2429x_iinlim_tbl[] = {
100000,
150000,
500000,
900000,
1000000,
- 1500000, <span style="font-style:italic">// for bq24, mp26 has 1800000</span>
+ 1500000,
2000000,
- 3000000,
+ 3000000
};
-<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> vsys_VSEL_table[] = {
+<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> bq2429x_sys_min_tbl[] = {
3000000,
3100000,
3200000,
@@ -253,7 +267,7 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> vsys_VSEL_table[] = {
3700000,
};
-<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> otg_VSEL_table[] = {
+<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> bq2429x_boostv_tbl[] = {
4550000,
4614000,
4678000,
@@ -272,6 +286,67 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> otg_VSEL_table[] = {
5510000,
};
+<span style="font-weight:bold">struct</span> bq2429x_range {
+ <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> min;
+ <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> max;
+ <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> step;
+};
+
+<span style="font-weight:bold">struct</span> bq2429x_lookup {
+ <span style="font-weight:bold">const</span> <span style="font-weight:bold">unsigned</span> <span style="font-weight:bold">int</span> *tbl;
+ <span style="font-weight:bold">int</span> size;
+};
+
+<span style="font-weight:bold">static</span> <span style="font-weight:bold">const</span> <span style="font-weight:bold">union</span> {
+ <span style="font-weight:bold">struct</span> bq2429x_range rt;
+ <span style="font-weight:bold">struct</span> 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)} },
+};
+
+<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_find_idx(u32 value, <span style="font-weight:bold">enum</span> bq2429x_table_ids id)
+{
+ <span style="font-weight:bold">int</span> idx;
+
+ <span style="font-weight:bold">if</span> ((id > ARRAY_SIZE(bq2429x_tables)) || id < 0)
+ <span style="font-weight:bold">return</span> -EINVAL;
+
+ <span style="font-weight:bold">if</span> (id >= TBL_IINLIM) {
+ <span style="font-weight:bold">const</span> u32 *tbl = bq2429x_tables[id].lt.tbl;
+ u32 tbl_size = bq2429x_tables[id].lt.size;
+
+ <span style="font-weight:bold">for</span> (idx = 1; idx < tbl_size && tbl[idx] <= value; idx++);
+ idx -= 1;
+
+ } <span style="font-weight:bold">else</span> {
+ <span style="font-weight:bold">const</span> <span style="font-weight:bold">struct</span> bq2429x_range *tbl = &bq2429x_tables[id].rt;
+
+ idx = (value - tbl->min) / tbl->step;
+ }
+
+ <span style="font-weight:bold">return</span> idx;
+}
+
+<span style="font-weight:bold">static</span> u32 bq2429x_find_val(u8 idx, <span style="font-weight:bold">enum</span> bq2429x_table_ids id)
+{
+ <span style="font-weight:bold">const</span> <span style="font-weight:bold">struct</span> bq2429x_range *tbl;
+
+ <span style="font-weight:bold">if</span> (id >= TBL_IINLIM)
+ <span style="font-weight:bold">return</span> bq2429x_tables[id].lt.tbl[idx];
+
+ tbl = &bq2429x_tables[id].rt;
+
+ <span style="font-weight:bold">return</span> (idx * tbl->step) + tbl->min;
+}
+
<span style="font-style:italic">/*</span>
<span style="font-style:italic"> * Common code for BQ24296 devices read</span>
<span style="font-style:italic"> */</span>
@@ -382,7 +457,7 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_get_vindpm_uV(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">return</span> ret;
}
- <span style="font-weight:bold">return</span> 3880000 + 80000 * ret;
+ <span style="font-weight:bold">return</span> bq2429x_find_val(ret, TBL_VINDPM);
}
<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_input_current_limit_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
@@ -407,37 +482,28 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_input_current_limit_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">if</span> (di->id->driver_data == CHIP_MP2624 && (ret == 5))
<span style="font-weight:bold">return</span> 1800000;
- <span style="font-weight:bold">return</span> iinlim_table[ret];
+ <span style="font-weight:bold">return</span> bq2429x_find_val(ret, TBL_IINLIM);
}
<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_input_current_limit_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di,
<span style="font-weight:bold">int</span> uA)
{
u8 hiz = EN_HIZ_DISABLE;
- u8 data = 0;
+ <span style="font-weight:bold">int</span> data;
<span style="font-weight:bold">int</span> ret;
dev_dbg(di->dev, <span style="font-style:italic">"%s(%d)</span><span style="font-weight:bold;font-style:italic">\n</span><span style="font-style:italic">"</span>, __func__, uA);
<span style="font-weight:bold">if</span> (uA < 80000) <span style="font-style:italic">/* includes negative current limit */</span>
hiz = EN_HIZ_ENABLE;
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 120000)
- data = 0;
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 400000)
- data = 1;
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 700000)
- data = 2;
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 1000000)
- data = 3;
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 1200000)
- data = 4;
-<span style="font-style:italic">// depends on bq24 vs. mp26</span>
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 1800000)
+
+ data = bq2429x_find_idx(uA, TBL_IINLIM);
+ <span style="font-weight:bold">if</span> (data < 0)
+ <span style="font-weight:bold">return</span> data;
+
+ <span style="font-style:italic">/* mp26 idx 5 is 1800000 */</span>
+ <span style="font-weight:bold">if</span> (uA > 1200000 && uA < 2200000)
data = 5;
- <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (uA < 2200000)
- data = 6;
- <span style="font-weight:bold">else</span>
- data = 7;
ret = bq2429x_field_write(di, F_IINLIM, data);
<span style="font-weight:bold">if</span> (ret < 0) {
@@ -466,7 +532,7 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_get_charge_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">return</span> ret;
}
- <span style="font-weight:bold">return</span> 64000 * ret + 512000;
+ <span style="font-weight:bold">return</span> bq2429x_find_val(ret, TBL_ICHG);
}
<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_charge_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di, <span style="font-weight:bold">int</span> uA)
@@ -474,11 +540,9 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_charge_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di, <span style="font-weight:bold">int</span> uA)
<span style="font-weight:bold">int</span> data;
<span style="font-weight:bold">int</span> ret;
- <span style="font-weight:bold">if</span> (uA < 0)
- <span style="font-weight:bold">return</span> -EINVAL;
-
- data = (uA - 512000 + 32000) / 64000;
- data = min(0x27, max(data, 0)); <span style="font-style:italic">/* limit to 512 mA .. 3008 mA */</span>
+ data = bq2429x_find_idx(uA, TBL_ICHG);
+ <span style="font-weight:bold">if</span> (data < 0)
+ <span style="font-weight:bold">return</span> data;
ret = bq2429x_field_write(di, F_ICHG, data);
<span style="font-weight:bold">if</span> (ret < 0) {
@@ -500,7 +564,7 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_get_precharge_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">return</span> ret;
}
- <span style="font-weight:bold">return</span> 128000 * ret + 128000;
+ <span style="font-weight:bold">return</span> bq2429x_find_val(ret, TBL_IPRECHG);
}
<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_precharge_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di, <span style="font-weight:bold">int</span> uA)
@@ -508,11 +572,9 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_precharge_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di, <span style="font-weight:bold">int</span>
<span style="font-weight:bold">int</span> data;
<span style="font-weight:bold">int</span> ret;
- <span style="font-weight:bold">if</span> (uA < 0)
- <span style="font-weight:bold">return</span> -EINVAL;
-
- data = (uA - 128000 + 64000) / 128000;
- data = min(0xf, max(data, 0)); <span style="font-style:italic">/* limit to 128 mA .. 2048 mA */</span>
+ data = bq2429x_find_idx(uA, TBL_IPRECHG);
+ <span style="font-weight:bold">if</span> (data < 0)
+ <span style="font-weight:bold">return</span> data;
ret = bq2429x_field_write(di, F_IPRECHG, data);
<span style="font-weight:bold">if</span> (ret < 0) {
@@ -527,11 +589,9 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_charge_term_current_uA(<span style="font-weight:bold">struct</span> bq2429x_device_info *di, in
<span style="font-weight:bold">int</span> data;
<span style="font-weight:bold">int</span> ret;
- <span style="font-weight:bold">if</span> (uA < 0)
- <span style="font-weight:bold">return</span> -EINVAL;
-
- data = (uA - 128000 + 64000) / 128000;
- data = min(0xf, max(data, 0)); <span style="font-style:italic">/* limit to 128 mA .. 2048 mA */</span>
+ data = bq2429x_find_idx(uA, TBL_ITERM);
+ <span style="font-weight:bold">if</span> (data < 0)
+ <span style="font-weight:bold">return</span> data;
ret = bq2429x_field_write(di, F_ITERM, data);
<span style="font-weight:bold">if</span> (ret < 0) {
@@ -577,9 +637,9 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_get_vsys_voltage_uV(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">return</span> ret;
dev_dbg(di->dev, <span style="font-style:italic">" => %d uV</span><span style="font-weight:bold;font-style:italic">\n</span><span style="font-style:italic">"</span>,
- vsys_VSEL_table[ret]);
+ bq2429x_find_val(ret, TBL_SYS_MIN));
- <span style="font-weight:bold">return</span> vsys_VSEL_table[ret];
+ <span style="font-weight:bold">return</span> bq2429x_find_val(ret, TBL_SYS_MIN);
}
<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_vsys_voltage_uV(<span style="font-weight:bold">struct</span> bq2429x_device_info *di,
@@ -587,7 +647,7 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_vsys_voltage_uV(<span style="font-weight:bold">struct</span> bq2429x_device_info *di,
{
dev_dbg(di->dev, <span style="font-style:italic">"%s(%d, %d)</span><span style="font-weight:bold;font-style:italic">\n</span><span style="font-style:italic">"</span>, __func__, min_uV, max_uV);
-<span style="font-style:italic">// revisit: the driver should select the voltage closest to min_uV by scanning vsys_VSEL_table</span>
+<span style="font-style:italic">// revisit: the driver should select the voltage closest to min_uV by scanning TBL_SYS_MIN</span>
<span style="font-weight:bold">return</span> 0; <span style="font-style:italic">/* disabled/untested */</span>
}
@@ -604,9 +664,9 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_get_otg_voltage_uV(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">return</span> ret;
dev_dbg(di->dev, <span style="font-style:italic">" => %d uV</span><span style="font-weight:bold;font-style:italic">\n</span><span style="font-style:italic">"</span>,
- otg_VSEL_table[ret]);
+ bq2429x_find_val(ret, TBL_BOOSTV));
- <span style="font-weight:bold">return</span> otg_VSEL_table[ret];
+ <span style="font-weight:bold">return</span> bq2429x_find_val(ret, TBL_BOOSTV);
}
<span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_set_otg_voltage_uV(<span style="font-weight:bold">struct</span> bq2429x_device_info *di,
@@ -747,10 +807,9 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_init_registers(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
max_uV = <span style="font-weight:bold">min_t</span>(<span style="font-weight:bold">int</span>, max_uV, di->bat_info.voltage_max_design_uv);
<span style="font-style:italic">// MP2624 has slightly different scale and offset</span>
-
- bits = (max_uV - 3504000) / 16000;
- bits = max(bits, 0);
- bits = min(bits, 63);
+ bits = bq2429x_find_idx(max_uV, TBL_VREG);
+ <span style="font-weight:bold">if</span> (bits < 0)
+ <span style="font-weight:bold">return</span> bits;
dev_dbg(di->dev, <span style="font-style:italic">"%s(): translated vbatt_max=%u and VSYS_max=%u to VREG=%u (%02x)</span><span style="font-weight:bold;font-style:italic">\n</span><span style="font-style:italic">"</span>,
__func__,
@@ -1505,13 +1564,13 @@ <span style="font-weight:bold">static</span> <span style="font-weight:bold">int</span> bq2429x_regulator_init(<span style="font-weight:bold">struct</span> bq2429x_device_info *di)
<span style="font-weight:bold">switch</span> (i) {
<span style="font-weight:bold">case</span> 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;
<span style="font-weight:bold">break</span>;
<span style="font-weight:bold">case</span> 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;
<span style="font-weight:bold">break</span>;
}
--
2.25.1</pre></div></div>