<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>