diff options
Diffstat (limited to 'drivers/power/supply/sc27xx_fuel_gauge.c')
-rw-r--r-- | drivers/power/supply/sc27xx_fuel_gauge.c | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index a7c8a8453db1..be42e814ea34 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -42,6 +42,8 @@ #define SC27XX_FGU_USER_AREA_SET 0xa0 #define SC27XX_FGU_USER_AREA_CLEAR 0xa4 #define SC27XX_FGU_USER_AREA_STATUS 0xa8 +#define SC27XX_FGU_VOLTAGE_BUF 0xd0 +#define SC27XX_FGU_CURRENT_BUF 0xf0 #define SC27XX_WRITE_SELCLB_EN BIT(0) #define SC27XX_FGU_CLBCNT_MASK GENMASK(15, 0) @@ -82,6 +84,7 @@ * @init_clbcnt: the initial coulomb counter * @max_volt: the maximum constant input voltage in millivolt * @min_volt: the minimum drained battery voltage in microvolt + * @boot_volt: the voltage measured during boot in microvolt * @table_len: the capacity table length * @resist_table_len: the resistance table length * @cur_1000ma_adc: ADC value corresponding to 1000 mA @@ -107,6 +110,7 @@ struct sc27xx_fgu_data { int init_clbcnt; int max_volt; int min_volt; + int boot_volt; int table_len; int resist_table_len; int cur_1000ma_adc; @@ -319,6 +323,7 @@ static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap) volt = sc27xx_fgu_adc_to_voltage(data, volt); ocv = volt * 1000 - oci * data->internal_resist; + data->boot_volt = ocv; /* * Parse the capacity table to look up the correct capacity percent @@ -376,6 +381,44 @@ static int sc27xx_fgu_get_clbcnt(struct sc27xx_fgu_data *data, int *clb_cnt) return 0; } +static int sc27xx_fgu_get_vol_now(struct sc27xx_fgu_data *data, int *val) +{ + int ret; + u32 vol; + + ret = regmap_read(data->regmap, data->base + SC27XX_FGU_VOLTAGE_BUF, + &vol); + if (ret) + return ret; + + /* + * It is ADC values reading from registers which need to convert to + * corresponding voltage values. + */ + *val = sc27xx_fgu_adc_to_voltage(data, vol); + + return 0; +} + +static int sc27xx_fgu_get_cur_now(struct sc27xx_fgu_data *data, int *val) +{ + int ret; + u32 cur; + + ret = regmap_read(data->regmap, data->base + SC27XX_FGU_CURRENT_BUF, + &cur); + if (ret) + return ret; + + /* + * It is ADC values reading from registers which need to convert to + * corresponding current values. + */ + *val = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC); + + return 0; +} + static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap) { int ret, cur_clbcnt, delta_clbcnt, delta_cap, temp; @@ -577,7 +620,7 @@ static int sc27xx_fgu_get_property(struct power_supply *psy, val->intval = value; break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: + case POWER_SUPPLY_PROP_VOLTAGE_AVG: ret = sc27xx_fgu_get_vbat_vol(data, &value); if (ret) goto error; @@ -601,7 +644,6 @@ static int sc27xx_fgu_get_property(struct power_supply *psy, val->intval = value; break; - case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_CURRENT_AVG: ret = sc27xx_fgu_get_current(data, &value); if (ret) @@ -625,6 +667,26 @@ static int sc27xx_fgu_get_property(struct power_supply *psy, break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret = sc27xx_fgu_get_vol_now(data, &value); + if (ret) + goto error; + + val->intval = value * 1000; + break; + + case POWER_SUPPLY_PROP_CURRENT_NOW: + ret = sc27xx_fgu_get_cur_now(data, &value); + if (ret) + goto error; + + val->intval = value * 1000; + break; + + case POWER_SUPPLY_PROP_VOLTAGE_BOOT: + val->intval = data->boot_volt; + break; + default: ret = -EINVAL; break; @@ -656,6 +718,11 @@ static int sc27xx_fgu_set_property(struct power_supply *psy, ret = 0; break; + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + data->total_cap = val->intval / 1000; + ret = 0; + break; + default: ret = -EINVAL; } @@ -676,7 +743,8 @@ static int sc27xx_fgu_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) { return psp == POWER_SUPPLY_PROP_CAPACITY || - psp == POWER_SUPPLY_PROP_CALIBRATE; + psp == POWER_SUPPLY_PROP_CALIBRATE || + psp == POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; } static enum power_supply_property sc27xx_fgu_props[] = { @@ -688,6 +756,8 @@ static enum power_supply_property sc27xx_fgu_props[] = { POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_OCV, + POWER_SUPPLY_PROP_VOLTAGE_AVG, + POWER_SUPPLY_PROP_VOLTAGE_BOOT, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_AVG, POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, @@ -705,6 +775,7 @@ static const struct power_supply_desc sc27xx_fgu_desc = { .set_property = sc27xx_fgu_set_property, .external_power_changed = sc27xx_fgu_external_power_changed, .property_is_writeable = sc27xx_fgu_property_is_writeable, + .no_thermal = true, }; static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap) |