power: supply_core: Pass pointer to battery info

The function to retrieve battery info (from the device tree) assumes
we have a static info struct that gets populated by calling into
power_supply_get_battery_info().

This is awkward since I want to support tables of static battery
info by just assigning a pointer to all info based on e.g. a
compatible value in the device tree.

We also have a mixture of static and dynamically allocated
variables here.

Bite the bullet and let power_supply_get_battery_info() allocate
also the memory used for the very top level
struct power_supply_battery_info container. Pass pointers
around and lifecycle this with the psy device just like the
stuff we allocate inside it.

Change all current users over.

As part of the change, initializers need to be added to some
previously uninitialized fields in struct
power_supply_battery_info.

Reviewed-By: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
This commit is contained in:
Linus Walleij 2021-12-15 02:01:18 +01:00 committed by Sebastian Reichel
parent be2c0d5418
commit 25fd330370
19 changed files with 157 additions and 127 deletions

View File

@ -439,7 +439,7 @@ struct ab8500_bm_charger_parameters {
* @fg_params fuel gauge parameters
*/
struct ab8500_bm_data {
struct power_supply_battery_info bi;
struct power_supply_battery_info *bi;
int temp_now;
int temp_interval_chg;
int temp_interval_nochg;

View File

@ -167,15 +167,16 @@ struct ab8500_bm_data ab8500_bm_data = {
int ab8500_bm_of_probe(struct power_supply *psy,
struct ab8500_bm_data *bm)
{
struct power_supply_battery_info *bi = &bm->bi;
struct power_supply_battery_info *bi;
struct device *dev = &psy->dev;
int ret;
ret = power_supply_get_battery_info(psy, bi);
ret = power_supply_get_battery_info(psy, &bm->bi);
if (ret) {
dev_err(dev, "cannot retrieve battery info\n");
return ret;
}
bi = bm->bi;
/* Fill in defaults for any data missing from the device tree */
if (bi->charge_full_design_uah < 0)
@ -240,5 +241,5 @@ int ab8500_bm_of_probe(struct power_supply *psy,
void ab8500_bm_of_remove(struct power_supply *psy,
struct ab8500_bm_data *bm)
{
power_supply_put_battery_info(psy, &bm->bi);
power_supply_put_battery_info(psy, bm->bi);
}

View File

@ -451,12 +451,13 @@ static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
*/
static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
{
struct power_supply_battery_info *bi = di->bm->bi;
int temp, ret;
static int prev;
int rbat, rntc, vntc;
if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) &&
(di->bm->bi.technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN)) {
(bi && (bi->technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) {
rbat = ab8500_btemp_get_batctrl_res(di);
if (rbat < 0) {
@ -540,7 +541,7 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
* that need it.
*/
if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) &&
(di->bm->bi.technology == POWER_SUPPLY_TECHNOLOGY_LIPO) &&
(di->bm->bi && (di->bm->bi->technology == POWER_SUPPLY_TECHNOLOGY_LIPO)) &&
(res <= 53407) && (res >= 12500)) {
dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
@ -807,7 +808,10 @@ static int ab8500_btemp_get_property(struct power_supply *psy,
val->intval = 1;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = di->bm->bi.technology;
if (di->bm->bi)
val->intval = di->bm->bi->technology;
else
val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
break;
case POWER_SUPPLY_PROP_TEMP:
val->intval = ab8500_btemp_get_temp(di);

View File

@ -352,7 +352,7 @@ static void ab8500_chargalg_state_to(struct ab8500_chargalg *di,
static int ab8500_chargalg_check_charger_enable(struct ab8500_chargalg *di)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
switch (di->charge_state) {
case STATE_NORMAL:
@ -731,7 +731,7 @@ static void ab8500_chargalg_start_charging(struct ab8500_chargalg *di,
*/
static void ab8500_chargalg_check_temp(struct ab8500_chargalg *di)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
if (di->batt_data.temp > (bi->temp_alert_min + di->t_hyst_norm) &&
di->batt_data.temp < (bi->temp_alert_max - di->t_hyst_norm)) {
@ -802,10 +802,10 @@ static void ab8500_chargalg_end_of_charge(struct ab8500_chargalg *di)
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
di->charge_state == STATE_NORMAL &&
!di->maintenance_chg && (di->batt_data.volt_uv >=
di->bm->bi.overvoltage_limit_uv ||
di->bm->bi->overvoltage_limit_uv ||
di->events.usb_cv_active || di->events.ac_cv_active) &&
di->batt_data.avg_curr_ua <
di->bm->bi.charge_term_current_ua &&
di->bm->bi->charge_term_current_ua &&
di->batt_data.avg_curr_ua > 0) {
if (++di->eoc_cnt >= EOC_COND_CNT) {
di->eoc_cnt = 0;
@ -827,7 +827,7 @@ static void ab8500_chargalg_end_of_charge(struct ab8500_chargalg *di)
static void init_maxim_chg_curr(struct ab8500_chargalg *di)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
di->ccm.original_iset_ua = bi->constant_charge_current_max_ua;
di->ccm.current_iset_ua = bi->constant_charge_current_max_ua;
@ -920,7 +920,7 @@ static enum maxim_ret ab8500_chargalg_chg_curr_maxim(struct ab8500_chargalg *di)
static void handle_maxim_chg_curr(struct ab8500_chargalg *di)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
enum maxim_ret ret;
int result;
@ -1299,7 +1299,7 @@ static void ab8500_chargalg_external_power_changed(struct power_supply *psy)
*/
static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
int charger_status;
int ret;
int curr_step_lvl_ua;
@ -1723,7 +1723,7 @@ static int ab8500_chargalg_get_property(struct power_supply *psy,
if (di->events.batt_ovv) {
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
} else if (di->events.btemp_underover) {
if (di->batt_data.temp <= di->bm->bi.temp_min)
if (di->batt_data.temp <= di->bm->bi->temp_min)
val->intval = POWER_SUPPLY_HEALTH_COLD;
else
val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;

View File

@ -852,7 +852,7 @@ static int ab8500_fg_bat_voltage(struct ab8500_fg *di)
*/
static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage_uv)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
/* Multiply by 10 because the capacity is tracked in per mille */
return power_supply_batinfo_ocv2cap(bi, voltage_uv, di->bat_temp) * 10;
@ -881,7 +881,7 @@ static int ab8500_fg_uncomp_volt_to_capacity(struct ab8500_fg *di)
*/
static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
{
struct power_supply_battery_info *bi = &di->bm->bi;
struct power_supply_battery_info *bi = di->bm->bi;
int resistance_percent = 0;
int resistance;
@ -2140,11 +2140,13 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
struct power_supply *ext = dev_get_drvdata(dev);
const char **supplicants = (const char **)ext->supplied_to;
struct ab8500_fg *di;
struct power_supply_battery_info *bi;
union power_supply_propval ret;
int j;
psy = (struct power_supply *)data;
di = power_supply_get_drvdata(psy);
bi = di->bm->bi;
/*
* For all psy where the name of your driver
@ -2207,8 +2209,8 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
switch (ext->desc->type) {
case POWER_SUPPLY_TYPE_BATTERY:
if (!di->flags.batt_id_received &&
(di->bm->bi.technology !=
POWER_SUPPLY_TECHNOLOGY_UNKNOWN)) {
(bi && (bi->technology !=
POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) {
const struct ab8500_battery_type *b;
b = di->bm->bat_type;
@ -2216,13 +2218,13 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
di->flags.batt_id_received = true;
di->bat_cap.max_mah_design =
di->bm->bi.charge_full_design_uah;
di->bm->bi->charge_full_design_uah;
di->bat_cap.max_mah =
di->bat_cap.max_mah_design;
di->vbat_nom_uv =
di->bm->bi.voltage_max_design_uv;
di->bm->bi->voltage_max_design_uv;
}
if (ret.intval)
@ -2992,9 +2994,9 @@ static int ab8500_fg_bind(struct device *dev, struct device *master,
return -ENOMEM;
}
di->bat_cap.max_mah_design = di->bm->bi.charge_full_design_uah;
di->bat_cap.max_mah_design = di->bm->bi->charge_full_design_uah;
di->bat_cap.max_mah = di->bat_cap.max_mah_design;
di->vbat_nom_uv = di->bm->bi.voltage_max_design_uv;
di->vbat_nom_uv = di->bm->bi->voltage_max_design_uv;
/* Start the coulomb counter */
ab8500_fg_coulomb_counter(di, true);

View File

@ -561,7 +561,7 @@ static int axp20x_power_probe(struct platform_device *pdev)
{
struct axp20x_batt_ps *axp20x_batt;
struct power_supply_config psy_cfg = {};
struct power_supply_battery_info info;
struct power_supply_battery_info *info;
struct device *dev = &pdev->dev;
if (!of_device_is_available(pdev->dev.of_node))
@ -615,8 +615,8 @@ static int axp20x_power_probe(struct platform_device *pdev)
}
if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
int vmin = info.voltage_min_design_uv;
int ccc = info.constant_charge_current_max_ua;
int vmin = info->voltage_min_design_uv;
int ccc = info->constant_charge_current_max_ua;
if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
vmin))

View File

@ -882,7 +882,7 @@ struct dt_init {
static int bd9995x_fw_probe(struct bd9995x_device *bd)
{
int ret;
struct power_supply_battery_info info;
struct power_supply_battery_info *info;
u32 property;
int i;
int regval;
@ -891,49 +891,41 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
struct battery_init battery_inits[] = {
{
.name = "trickle-charging current",
.info_data = &info.tricklecharge_current_ua,
.range = &charging_current_ranges[0],
.ranges = 2,
.data = &init->itrich_set,
}, {
.name = "pre-charging current",
.info_data = &info.precharge_current_ua,
.range = &charging_current_ranges[0],
.ranges = 2,
.data = &init->iprech_set,
}, {
.name = "pre-to-trickle charge voltage threshold",
.info_data = &info.precharge_voltage_max_uv,
.range = &trickle_to_pre_threshold_ranges[0],
.ranges = 2,
.data = &init->vprechg_th_set,
}, {
.name = "charging termination current",
.info_data = &info.charge_term_current_ua,
.range = &charging_current_ranges[0],
.ranges = 2,
.data = &init->iterm_set,
}, {
.name = "charging re-start voltage",
.info_data = &info.charge_restart_voltage_uv,
.range = &charge_voltage_regulation_ranges[0],
.ranges = 2,
.data = &init->vrechg_set,
}, {
.name = "battery overvoltage limit",
.info_data = &info.overvoltage_limit_uv,
.range = &charge_voltage_regulation_ranges[0],
.ranges = 2,
.data = &init->vbatovp_set,
}, {
.name = "fast-charging max current",
.info_data = &info.constant_charge_current_max_ua,
.range = &fast_charge_current_ranges[0],
.ranges = 1,
.data = &init->ichg_set,
}, {
.name = "fast-charging voltage",
.info_data = &info.constant_charge_voltage_max_uv,
.range = &charge_voltage_regulation_ranges[0],
.ranges = 2,
.data = &init->vfastchg_reg_set1,
@ -966,6 +958,16 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
if (ret < 0)
return ret;
/* Put pointers to the generic battery info */
battery_inits[0].info_data = &info->tricklecharge_current_ua;
battery_inits[1].info_data = &info->precharge_current_ua;
battery_inits[2].info_data = &info->precharge_voltage_max_uv;
battery_inits[3].info_data = &info->charge_term_current_ua;
battery_inits[4].info_data = &info->charge_restart_voltage_uv;
battery_inits[5].info_data = &info->overvoltage_limit_uv;
battery_inits[6].info_data = &info->constant_charge_current_max_ua;
battery_inits[7].info_data = &info->constant_charge_voltage_max_uv;
for (i = 0; i < ARRAY_SIZE(battery_inits); i++) {
int val = *battery_inits[i].info_data;
const struct linear_range *range = battery_inits[i].range;
@ -980,7 +982,7 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
dev_err(bd->dev, "Unsupported value for %s\n",
battery_inits[i].name);
power_supply_put_battery_info(bd->charger, &info);
power_supply_put_battery_info(bd->charger, info);
return -EINVAL;
}
if (!found) {
@ -991,7 +993,7 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
*(battery_inits[i].data) = regval;
}
power_supply_put_battery_info(bd->charger, &info);
power_supply_put_battery_info(bd->charger, info);
for (i = 0; i < ARRAY_SIZE(props); i++) {
ret = device_property_read_u32(bd->dev, props[i].prop,

View File

@ -1670,7 +1670,7 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
static int bq24190_get_config(struct bq24190_dev_info *bdi)
{
const char * const s = "ti,system-minimum-microvolt";
struct power_supply_battery_info info = {};
struct power_supply_battery_info *info;
int v;
if (device_property_read_u32(bdi->dev, s, &v) == 0) {
@ -1684,7 +1684,7 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
if (bdi->dev->of_node &&
!power_supply_get_battery_info(bdi->charger, &info)) {
v = info.precharge_current_ua / 1000;
v = info->precharge_current_ua / 1000;
if (v >= BQ24190_REG_PCTCC_IPRECHG_MIN
&& v <= BQ24190_REG_PCTCC_IPRECHG_MAX)
bdi->iprechg = v;
@ -1692,7 +1692,7 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
dev_warn(bdi->dev, "invalid value for battery:precharge-current-microamp: %d\n",
v);
v = info.charge_term_current_ua / 1000;
v = info->charge_term_current_ua / 1000;
if (v >= BQ24190_REG_PCTCC_ITERM_MIN
&& v <= BQ24190_REG_PCTCC_ITERM_MAX)
bdi->iterm = v;

View File

@ -945,7 +945,7 @@ static int bq2515x_power_supply_register(struct bq2515x_device *bq2515x,
static int bq2515x_hw_init(struct bq2515x_device *bq2515x)
{
int ret;
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
ret = bq2515x_disable_watchdog_timers(bq2515x);
if (ret)
@ -969,13 +969,13 @@ static int bq2515x_hw_init(struct bq2515x_device *bq2515x)
} else {
bq2515x->init_data.ichg =
bat_info.constant_charge_current_max_ua;
bat_info->constant_charge_current_max_ua;
bq2515x->init_data.vbatreg =
bat_info.constant_charge_voltage_max_uv;
bat_info->constant_charge_voltage_max_uv;
bq2515x->init_data.iprechg =
bat_info.precharge_current_ua;
bat_info->precharge_current_ua;
}
ret = bq2515x_set_const_charge_current(bq2515x,

View File

@ -1504,7 +1504,7 @@ static int bq256xx_power_supply_init(struct bq256xx_device *bq,
static int bq256xx_hw_init(struct bq256xx_device *bq)
{
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
int wd_reg_val = BQ256XX_WATCHDOG_DIS;
int ret = 0;
int i;
@ -1526,16 +1526,16 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
if (ret) {
dev_warn(bq->dev, "battery info missing, default values will be applied\n");
bat_info.constant_charge_current_max_ua =
bat_info->constant_charge_current_max_ua =
bq->chip_info->bq256xx_def_ichg;
bat_info.constant_charge_voltage_max_uv =
bat_info->constant_charge_voltage_max_uv =
bq->chip_info->bq256xx_def_vbatreg;
bat_info.precharge_current_ua =
bat_info->precharge_current_ua =
bq->chip_info->bq256xx_def_iprechg;
bat_info.charge_term_current_ua =
bat_info->charge_term_current_ua =
bq->chip_info->bq256xx_def_iterm;
bq->init_data.ichg_max =
@ -1545,10 +1545,10 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
bq->chip_info->bq256xx_max_vbatreg;
} else {
bq->init_data.ichg_max =
bat_info.constant_charge_current_max_ua;
bat_info->constant_charge_current_max_ua;
bq->init_data.vbatreg_max =
bat_info.constant_charge_voltage_max_uv;
bat_info->constant_charge_voltage_max_uv;
}
ret = bq->chip_info->bq256xx_set_vindpm(bq, bq->init_data.vindpm);
@ -1560,26 +1560,26 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
return ret;
ret = bq->chip_info->bq256xx_set_ichg(bq,
bat_info.constant_charge_current_max_ua);
bat_info->constant_charge_current_max_ua);
if (ret)
return ret;
ret = bq->chip_info->bq256xx_set_iprechg(bq,
bat_info.precharge_current_ua);
bat_info->precharge_current_ua);
if (ret)
return ret;
ret = bq->chip_info->bq256xx_set_vbatreg(bq,
bat_info.constant_charge_voltage_max_uv);
bat_info->constant_charge_voltage_max_uv);
if (ret)
return ret;
ret = bq->chip_info->bq256xx_set_iterm(bq,
bat_info.charge_term_current_ua);
bat_info->charge_term_current_ua);
if (ret)
return ret;
power_supply_put_battery_info(bq->charger, &bat_info);
power_supply_put_battery_info(bq->charger, bat_info);
return 0;
}

View File

@ -1079,7 +1079,7 @@ static int bq25980_power_supply_init(struct bq25980_device *bq,
static int bq25980_hw_init(struct bq25980_device *bq)
{
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
int wd_reg_val = BQ25980_WATCHDOG_DIS;
int wd_max_val = BQ25980_NUM_WD_VAL - 1;
int ret = 0;
@ -1112,8 +1112,8 @@ static int bq25980_hw_init(struct bq25980_device *bq)
return -EINVAL;
}
bq->init_data.ichg_max = bat_info.constant_charge_current_max_ua;
bq->init_data.vreg_max = bat_info.constant_charge_voltage_max_uv;
bq->init_data.ichg_max = bat_info->constant_charge_current_max_ua;
bq->init_data.vreg_max = bat_info->constant_charge_voltage_max_uv;
if (bq->state.bypass) {
ret = regmap_update_bits(bq->regmap, BQ25980_CHRGR_CTRL_2,

View File

@ -1474,7 +1474,7 @@ static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
static void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
{
struct power_supply_battery_info info = {};
struct power_supply_battery_info *info;
unsigned int min, max;
if (power_supply_get_battery_info(di->bat, &info) < 0)
@ -1485,43 +1485,43 @@ static void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
return;
}
if (info.energy_full_design_uwh != info.charge_full_design_uah) {
if (info.energy_full_design_uwh == -EINVAL)
if (info->energy_full_design_uwh != info->charge_full_design_uah) {
if (info->energy_full_design_uwh == -EINVAL)
dev_warn(di->dev, "missing battery:energy-full-design-microwatt-hours\n");
else if (info.charge_full_design_uah == -EINVAL)
else if (info->charge_full_design_uah == -EINVAL)
dev_warn(di->dev, "missing battery:charge-full-design-microamp-hours\n");
}
/* assume min == 0 */
max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
if (info.energy_full_design_uwh > max * 1000) {
if (info->energy_full_design_uwh > max * 1000) {
dev_err(di->dev, "invalid battery:energy-full-design-microwatt-hours %d\n",
info.energy_full_design_uwh);
info.energy_full_design_uwh = -EINVAL;
info->energy_full_design_uwh);
info->energy_full_design_uwh = -EINVAL;
}
/* assume min == 0 */
max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
if (info.charge_full_design_uah > max * 1000) {
if (info->charge_full_design_uah > max * 1000) {
dev_err(di->dev, "invalid battery:charge-full-design-microamp-hours %d\n",
info.charge_full_design_uah);
info.charge_full_design_uah = -EINVAL;
info->charge_full_design_uah);
info->charge_full_design_uah = -EINVAL;
}
min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
if ((info.voltage_min_design_uv < min * 1000 ||
info.voltage_min_design_uv > max * 1000) &&
info.voltage_min_design_uv != -EINVAL) {
if ((info->voltage_min_design_uv < min * 1000 ||
info->voltage_min_design_uv > max * 1000) &&
info->voltage_min_design_uv != -EINVAL) {
dev_err(di->dev, "invalid battery:voltage-min-design-microvolt %d\n",
info.voltage_min_design_uv);
info.voltage_min_design_uv = -EINVAL;
info->voltage_min_design_uv);
info->voltage_min_design_uv = -EINVAL;
}
if ((info.energy_full_design_uwh != -EINVAL &&
info.charge_full_design_uah != -EINVAL) ||
info.voltage_min_design_uv != -EINVAL)
bq27xxx_battery_set_config(di, &info);
if ((info->energy_full_design_uwh != -EINVAL &&
info->charge_full_design_uah != -EINVAL) ||
info->voltage_min_design_uv != -EINVAL)
bq27xxx_battery_set_config(di, info);
}
/*

View File

@ -61,7 +61,7 @@ struct cw_battery {
struct delayed_work battery_delay_work;
struct regmap *regmap;
struct power_supply *rk_bat;
struct power_supply_battery_info battery;
struct power_supply_battery_info *battery;
u8 *bat_profile;
bool charger_attached;
@ -505,22 +505,22 @@ static int cw_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
if (cw_bat->battery.charge_full_design_uah > 0)
val->intval = cw_bat->battery.charge_full_design_uah;
if (cw_bat->battery->charge_full_design_uah > 0)
val->intval = cw_bat->battery->charge_full_design_uah;
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
val->intval = cw_bat->battery.charge_full_design_uah;
val->intval = cw_bat->battery->charge_full_design_uah;
val->intval = val->intval * cw_bat->soc / 100;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (cw_battery_valid_time_to_empty(cw_bat) &&
cw_bat->battery.charge_full_design_uah > 0) {
cw_bat->battery->charge_full_design_uah > 0) {
/* calculate remaining capacity */
val->intval = cw_bat->battery.charge_full_design_uah;
val->intval = cw_bat->battery->charge_full_design_uah;
val->intval = val->intval * cw_bat->soc / 100;
/* estimate current based on time to empty */
@ -687,6 +687,12 @@ static int cw_bat_probe(struct i2c_client *client)
ret = power_supply_get_battery_info(cw_bat->rk_bat, &cw_bat->battery);
if (ret) {
/* Allocate an empty battery */
cw_bat->battery = devm_kzalloc(&client->dev,
sizeof(cw_bat->battery),
GFP_KERNEL);
if (!cw_bat->battery)
return -ENOMEM;
dev_warn(cw_bat->dev,
"No monitored battery, some properties will be missing\n");
}
@ -724,7 +730,7 @@ static int cw_bat_remove(struct i2c_client *client)
struct cw_battery *cw_bat = i2c_get_clientdata(client);
cancel_delayed_work_sync(&cw_bat->battery_delay_work);
power_supply_put_battery_info(cw_bat->rk_bat, &cw_bat->battery);
power_supply_put_battery_info(cw_bat->rk_bat, cw_bat->battery);
return 0;
}

View File

@ -18,7 +18,7 @@ struct ingenic_battery {
struct iio_channel *channel;
struct power_supply_desc desc;
struct power_supply *battery;
struct power_supply_battery_info info;
struct power_supply_battery_info *info;
};
static int ingenic_battery_get_property(struct power_supply *psy,
@ -26,7 +26,7 @@ static int ingenic_battery_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
struct ingenic_battery *bat = power_supply_get_drvdata(psy);
struct power_supply_battery_info *info = &bat->info;
struct power_supply_battery_info *info = bat->info;
int ret;
switch (psp) {
@ -80,7 +80,7 @@ static int ingenic_battery_set_scale(struct ingenic_battery *bat)
if (ret != IIO_AVAIL_LIST || scale_type != IIO_VAL_FRACTIONAL_LOG2)
return -EINVAL;
max_mV = bat->info.voltage_max_design_uv / 1000;
max_mV = bat->info->voltage_max_design_uv / 1000;
for (i = 0; i < scale_len; i += 2) {
u64 scale_mV = (max_raw * scale_raw[i]) >> scale_raw[i + 1];
@ -156,13 +156,13 @@ static int ingenic_battery_probe(struct platform_device *pdev)
dev_err(dev, "Unable to get battery info: %d\n", ret);
return ret;
}
if (bat->info.voltage_min_design_uv < 0) {
if (bat->info->voltage_min_design_uv < 0) {
dev_err(dev, "Unable to get voltage min design\n");
return bat->info.voltage_min_design_uv;
return bat->info->voltage_min_design_uv;
}
if (bat->info.voltage_max_design_uv < 0) {
if (bat->info->voltage_max_design_uv < 0) {
dev_err(dev, "Unable to get voltage max design\n");
return bat->info.voltage_max_design_uv;
return bat->info->voltage_max_design_uv;
}
return ingenic_battery_set_scale(bat);

View File

@ -564,14 +564,19 @@ EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle);
#endif /* CONFIG_OF */
int power_supply_get_battery_info(struct power_supply *psy,
struct power_supply_battery_info *info)
struct power_supply_battery_info **info_out)
{
struct power_supply_resistance_temp_table *resist_table;
struct power_supply_battery_info *info;
struct device_node *battery_np;
const char *value;
int err, len, index;
const __be32 *list;
info = devm_kmalloc(&psy->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
info->energy_full_design_uwh = -EINVAL;
info->charge_full_design_uah = -EINVAL;
@ -581,6 +586,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
info->charge_term_current_ua = -EINVAL;
info->constant_charge_current_max_ua = -EINVAL;
info->constant_charge_voltage_max_uv = -EINVAL;
info->tricklecharge_current_ua = -EINVAL;
info->precharge_voltage_max_uv = -EINVAL;
info->charge_restart_voltage_uv = -EINVAL;
info->overvoltage_limit_uv = -EINVAL;
info->temp_ambient_alert_min = INT_MIN;
info->temp_ambient_alert_max = INT_MAX;
info->temp_alert_min = INT_MIN;
@ -728,7 +737,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
list = of_get_property(battery_np, "resistance-temp-table", &len);
if (!list || !len)
goto out_put_node;
goto out_ret_pointer;
info->resist_table_size = len / (2 * sizeof(__be32));
resist_table = info->resist_table = devm_kcalloc(&psy->dev,
@ -746,6 +755,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
resist_table[index].resistance = be32_to_cpu(*list++);
}
out_ret_pointer:
/* Finally return the whole thing */
*info_out = info;
out_put_node:
of_node_put(battery_np);
return err;
@ -764,6 +777,8 @@ void power_supply_put_battery_info(struct power_supply *psy,
if (info->resist_table)
devm_kfree(&psy->dev, info->resist_table);
devm_kfree(&psy->dev, info);
}
EXPORT_SYMBOL_GPL(power_supply_put_battery_info);

View File

@ -368,7 +368,7 @@ static int sc2731_charger_usb_change(struct notifier_block *nb,
static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
{
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
u32 term_currrent, term_voltage, cur_val, vol_val;
int ret;
@ -390,7 +390,7 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
cur_val = 0x2;
vol_val = 0x1;
} else {
term_currrent = bat_info.charge_term_current_ua / 1000;
term_currrent = bat_info->charge_term_current_ua / 1000;
if (term_currrent <= 90)
cur_val = 0;
@ -399,7 +399,7 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
else
cur_val = ((term_currrent - 90) / 25) + 1;
term_voltage = bat_info.constant_charge_voltage_max_uv / 1000;
term_voltage = bat_info->constant_charge_voltage_max_uv / 1000;
if (term_voltage > 4500)
term_voltage = 4500;
@ -409,7 +409,7 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
else
vol_val = 0;
power_supply_put_battery_info(info->psy_usb, &bat_info);
power_supply_put_battery_info(info->psy_usb, bat_info);
}
/* Set charge termination current */

View File

@ -998,7 +998,7 @@ static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
{
struct power_supply_battery_info info = { };
struct power_supply_battery_info *info;
struct power_supply_battery_ocv_table *table;
int ret, delta_clbcnt, alarm_adc;
@ -1008,16 +1008,16 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
return ret;
}
data->total_cap = info.charge_full_design_uah / 1000;
data->max_volt = info.constant_charge_voltage_max_uv / 1000;
data->internal_resist = info.factory_internal_resistance_uohm / 1000;
data->min_volt = info.voltage_min_design_uv;
data->total_cap = info->charge_full_design_uah / 1000;
data->max_volt = info->constant_charge_voltage_max_uv / 1000;
data->internal_resist = info->factory_internal_resistance_uohm / 1000;
data->min_volt = info->voltage_min_design_uv;
/*
* For SC27XX fuel gauge device, we only use one ocv-capacity
* table in normal temperature 20 Celsius.
*/
table = power_supply_find_ocv2cap_table(&info, 20, &data->table_len);
table = power_supply_find_ocv2cap_table(info, 20, &data->table_len);
if (!table)
return -EINVAL;
@ -1025,7 +1025,7 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
data->table_len * sizeof(*table),
GFP_KERNEL);
if (!data->cap_table) {
power_supply_put_battery_info(data->battery, &info);
power_supply_put_battery_info(data->battery, info);
return -ENOMEM;
}
@ -1035,19 +1035,19 @@ 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;
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 = 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);
power_supply_put_battery_info(data->battery, info);
return -ENOMEM;
}
}
power_supply_put_battery_info(data->battery, &info);
power_supply_put_battery_info(data->battery, info);
ret = sc27xx_fgu_calibration(data);
if (ret)

View File

@ -1281,7 +1281,7 @@ static void smb347_dt_parse_dev_info(struct smb347_charger *smb)
static int smb347_get_battery_info(struct smb347_charger *smb)
{
struct power_supply_battery_info info = {};
struct power_supply_battery_info *info;
struct power_supply *supply;
int err;
@ -1296,29 +1296,29 @@ static int smb347_get_battery_info(struct smb347_charger *smb)
if (err)
return err;
if (info.constant_charge_current_max_ua != -EINVAL)
smb->max_charge_current = info.constant_charge_current_max_ua;
if (info->constant_charge_current_max_ua != -EINVAL)
smb->max_charge_current = info->constant_charge_current_max_ua;
if (info.constant_charge_voltage_max_uv != -EINVAL)
smb->max_charge_voltage = info.constant_charge_voltage_max_uv;
if (info->constant_charge_voltage_max_uv != -EINVAL)
smb->max_charge_voltage = info->constant_charge_voltage_max_uv;
if (info.precharge_current_ua != -EINVAL)
smb->pre_charge_current = info.precharge_current_ua;
if (info->precharge_current_ua != -EINVAL)
smb->pre_charge_current = info->precharge_current_ua;
if (info.charge_term_current_ua != -EINVAL)
smb->termination_current = info.charge_term_current_ua;
if (info->charge_term_current_ua != -EINVAL)
smb->termination_current = info->charge_term_current_ua;
if (info.temp_alert_min != INT_MIN)
smb->soft_cold_temp_limit = info.temp_alert_min;
if (info->temp_alert_min != INT_MIN)
smb->soft_cold_temp_limit = info->temp_alert_min;
if (info.temp_alert_max != INT_MAX)
smb->soft_hot_temp_limit = info.temp_alert_max;
if (info->temp_alert_max != INT_MAX)
smb->soft_hot_temp_limit = info->temp_alert_max;
if (info.temp_min != INT_MIN)
smb->hard_cold_temp_limit = info.temp_min;
if (info->temp_min != INT_MIN)
smb->hard_cold_temp_limit = info->temp_min;
if (info.temp_max != INT_MAX)
smb->hard_hot_temp_limit = info.temp_max;
if (info->temp_max != INT_MAX)
smb->hard_hot_temp_limit = info->temp_max;
/* Suspend when battery temperature is outside hard limits */
if (smb->hard_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT ||

View File

@ -575,7 +575,7 @@ devm_power_supply_get_by_phandle(struct device *dev, const char *property)
#endif /* CONFIG_OF */
extern int power_supply_get_battery_info(struct power_supply *psy,
struct power_supply_battery_info *info);
struct power_supply_battery_info **info_out);
extern void power_supply_put_battery_info(struct power_supply *psy,
struct power_supply_battery_info *info);
extern int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,