power: supply: sc27xx: Optimize the battery resistance with measuring temperature
authorYuanjiang Yu <yuanjiang.yu@unisoc.com>
Mon, 9 Dec 2019 03:56:23 +0000 (11:56 +0800)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Thu, 19 Dec 2019 00:36:33 +0000 (01:36 +0100)
Optimize the battery internal resistance in a certain temerature to
get a accurate battery internal resistance.

Signed-off-by: Yuanjiang Yu <yuanjiang.yu@unisoc.com>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/sc27xx_fuel_gauge.c

index bc8f5bd..221b6fb 100644 (file)
  * @max_volt: the maximum constant input voltage in millivolt
  * @min_volt: the minimum drained battery voltage in microvolt
  * @table_len: the capacity table length
+ * @resist_table_len: the resistance table length
  * @cur_1000ma_adc: ADC value corresponding to 1000 mA
  * @vol_1000mv_adc: ADC value corresponding to 1000 mV
  * @cap_table: capacity table with corresponding ocv
+ * @resist_table: resistance percent table with corresponding temperature
  */
 struct sc27xx_fgu_data {
        struct regmap *regmap;
@@ -103,15 +105,18 @@ struct sc27xx_fgu_data {
        int max_volt;
        int min_volt;
        int table_len;
+       int resist_table_len;
        int cur_1000ma_adc;
        int vol_1000mv_adc;
        struct power_supply_battery_ocv_table *cap_table;
+       struct power_supply_resistance_temp_table *resist_table;
 };
 
 static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity);
 static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data,
                                            int cap, bool int_mode);
 static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap);
+static int sc27xx_fgu_get_temp(struct sc27xx_fgu_data *data, int *temp);
 
 static const char * const sc27xx_charger_supply_name[] = {
        "sc2731_charger",
@@ -434,7 +439,7 @@ static int sc27xx_fgu_get_current(struct sc27xx_fgu_data *data, int *val)
 
 static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val)
 {
-       int vol, cur, ret;
+       int vol, cur, ret, temp, resistance;
 
        ret = sc27xx_fgu_get_vbat_vol(data, &vol);
        if (ret)
@@ -444,8 +449,19 @@ static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val)
        if (ret)
                return ret;
 
+       resistance = data->internal_resist;
+       if (data->resist_table_len > 0) {
+               ret = sc27xx_fgu_get_temp(data, &temp);
+               if (ret)
+                       return ret;
+
+               resistance = power_supply_temp2resist_simple(data->resist_table,
+                                               data->resist_table_len, temp);
+               resistance = data->internal_resist * resistance / 100;
+       }
+
        /* Return the battery OCV in micro volts. */
-       *val = vol * 1000 - cur * data->internal_resist;
+       *val = vol * 1000 - cur * resistance;
 
        return 0;
 }
@@ -929,6 +945,18 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
        if (!data->alarm_cap)
                data->alarm_cap += 1;
 
+       data->resist_table_len = info.resist_table_size;
+       if (data->resist_table_len > 0) {
+               data->resist_table = devm_kmemdup(data->dev, info.resist_table,
+                                                 data->resist_table_len *
+                                                 sizeof(struct power_supply_resistance_temp_table),
+                                                 GFP_KERNEL);
+               if (!data->resist_table) {
+                       power_supply_put_battery_info(data->battery, &info);
+                       return -ENOMEM;
+               }
+       }
+
        power_supply_put_battery_info(data->battery, &info);
 
        ret = sc27xx_fgu_calibration(data);