From 77d641baa3c8e18a1056bec6c64c6103c1a17b1e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Mon, 8 Nov 2021 17:27:05 +0100 Subject: power: supply: core: add POWER_SUPPLY_HEALTH_NO_BATTERY Some chargers can keep the system powered from the mains even when no battery is present. It this case none of the currently defined health statuses applies. Add a new status to report that no battery is present. Suggested-by: Sebastian Reichel Signed-off-by: Luca Ceresoli Signed-off-by: Sebastian Reichel --- include/linux/power_supply.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 9ca1f120a211..2d1318fe2455 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -66,6 +66,7 @@ enum { POWER_SUPPLY_HEALTH_WARM, POWER_SUPPLY_HEALTH_COOL, POWER_SUPPLY_HEALTH_HOT, + POWER_SUPPLY_HEALTH_NO_BATTERY, }; enum { -- cgit v1.2.3-71-gd317 From e0dbd7b0ed021fb9250f7ba4d759325678efefb5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 16 Nov 2021 23:44:28 +0100 Subject: power: supply: core: Add kerneldoc to battery struct This complements the struct power_supply_battery_info with extensive kerneldoc explaining the different semantics of the fields, including an overview of the CC/CV charging concepts implicit in some of the struct members. This is done to first establish semantics before I can add more charging methods by breaking out the CC/CV parameters to its own struct. Tested-by: Randy Dunlap Acked-by: Randy Dunlap Reviewed-by: Matti Vaittinen Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- include/linux/power_supply.h | 215 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 192 insertions(+), 23 deletions(-) (limited to 'include/linux') diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 2d1318fe2455..f6e94eae4f28 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -343,37 +343,206 @@ struct power_supply_resistance_temp_table { #define POWER_SUPPLY_OCV_TEMP_MAX 20 -/* +/** + * struct power_supply_battery_info - information about batteries + * @technology: from the POWER_SUPPLY_TECHNOLOGY_* enum + * @energy_full_design_uwh: energy content when fully charged in microwatt + * hours + * @charge_full_design_uah: charge content when fully charged in microampere + * hours + * @voltage_min_design_uv: minimum voltage across the poles when the battery + * is at minimum voltage level in microvolts. If the voltage drops below this + * level the battery will need precharging when using CC/CV charging. + * @voltage_max_design_uv: voltage across the poles when the battery is fully + * charged in microvolts. This is the "nominal voltage" i.e. the voltage + * printed on the label of the battery. + * @tricklecharge_current_ua: the tricklecharge current used when trickle + * charging the battery in microamperes. This is the charging phase when the + * battery is completely empty and we need to carefully trickle in some + * charge until we reach the precharging voltage. + * @precharge_current_ua: current to use in the precharge phase in microamperes, + * the precharge rate is limited by limiting the current to this value. + * @precharge_voltage_max_uv: the maximum voltage allowed when precharging in + * microvolts. When we pass this voltage we will nominally switch over to the + * CC (constant current) charging phase defined by constant_charge_current_ua + * and constant_charge_voltage_max_uv. + * @charge_term_current_ua: when the current in the CV (constant voltage) + * charging phase drops below this value in microamperes the charging will + * terminate completely and not restart until the voltage over the battery + * poles reach charge_restart_voltage_uv unless we use maintenance charging. + * @charge_restart_voltage_uv: when the battery has been fully charged by + * CC/CV charging and charging has been disabled, and the voltage subsequently + * drops below this value in microvolts, the charging will be restarted + * (typically using CV charging). + * @overvoltage_limit_uv: If the voltage exceeds the nominal voltage + * voltage_max_design_uv and we reach this voltage level, all charging must + * stop and emergency procedures take place, such as shutting down the system + * in some cases. + * @constant_charge_current_max_ua: current in microamperes to use in the CC + * (constant current) charging phase. The charging rate is limited + * by this current. This is the main charging phase and as the current is + * constant into the battery the voltage slowly ascends to + * constant_charge_voltage_max_uv. + * @constant_charge_voltage_max_uv: voltage in microvolts signifying the end of + * the CC (constant current) charging phase and the beginning of the CV + * (constant voltage) charging phase. + * @factory_internal_resistance_uohm: the internal resistance of the battery + * at fabrication time, expressed in microohms. This resistance will vary + * depending on the lifetime and charge of the battery, so this is just a + * nominal ballpark figure. + * @ocv_temp: array indicating the open circuit voltage (OCV) capacity + * temperature indices. This is an array of temperatures in degrees Celsius + * indicating which capacity table to use for a certain temperature, since + * the capacity for reasons of chemistry will be different at different + * temperatures. Determining capacity is a multivariate problem and the + * temperature is the first variable we determine. + * @temp_ambient_alert_min: the battery will go outside of operating conditions + * when the ambient temperature goes below this temperature in degrees + * Celsius. + * @temp_ambient_alert_max: the battery will go outside of operating conditions + * when the ambient temperature goes above this temperature in degrees + * Celsius. + * @temp_alert_min: the battery should issue an alert if the internal + * temperature goes below this temperature in degrees Celsius. + * @temp_alert_max: the battery should issue an alert if the internal + * temperature goes above this temperature in degrees Celsius. + * @temp_min: the battery will go outside of operating conditions when + * the internal temperature goes below this temperature in degrees Celsius. + * Normally this means the system should shut down. + * @temp_max: the battery will go outside of operating conditions when + * the internal temperature goes above this temperature in degrees Celsius. + * Normally this means the system should shut down. + * @ocv_table: for each entry in ocv_temp there is a corresponding entry in + * ocv_table and a size for each entry in ocv_table_size. These arrays + * determine the capacity in percent in relation to the voltage in microvolts + * at the indexed temperature. + * @ocv_table_size: for each entry in ocv_temp this array is giving the size of + * each entry in the array of capacity arrays in ocv_table. + * @resist_table: this is a table that correlates a battery temperature to the + * expected internal resistance at this temperature. The resistance is given + * as a percentage of factory_internal_resistance_uohm. Knowing the + * resistance of the battery is usually necessary for calculating the open + * circuit voltage (OCV) that is then used with the ocv_table to calculate + * the capacity of the battery. The resist_table must be ordered descending + * by temperature: highest temperature with lowest resistance first, lowest + * temperature with highest resistance last. + * @resist_table_size: the number of items in the resist_table. + * * This is the recommended struct to manage static battery parameters, * populated by power_supply_get_battery_info(). Most platform drivers should * use these for consistency. + * * Its field names must correspond to elements in enum power_supply_property. * The default field value is -EINVAL. - * Power supply class itself doesn't use this. + * + * The charging parameters here assume a CC/CV charging scheme. This method + * is most common with Lithium Ion batteries (other methods are possible) and + * looks as follows: + * + * ^ Battery voltage + * | --- overvoltage_limit_uv + * | + * | ................................................... + * | .. constant_charge_voltage_max_uv + * | .. + * | . + * | . + * | . + * | . + * | . + * | .. precharge_voltage_max_uv + * | .. + * |. (trickle charging) + * +------------------------------------------------------------------> time + * + * ^ Current into the battery + * | + * | ............. constant_charge_current_max_ua + * | . . + * | . . + * | . . + * | . . + * | . .. + * | . .... + * | . ..... + * | ... precharge_current_ua ....... charge_term_current_ua + * | . . + * | . . + * |.... tricklecharge_current_ua . + * | . + * +-----------------------------------------------------------------> time + * + * These diagrams are synchronized on time and the voltage and current + * follow each other. + * + * With CC/CV charging commence over time like this for an empty battery: + * + * 1. When the battery is completely empty it may need to be charged with + * an especially small current so that electrons just "trickle in", + * this is the tricklecharge_current_ua. + * + * 2. Next a small initial pre-charge current (precharge_current_ua) + * is applied if the voltage is below precharge_voltage_max_uv until we + * reach precharge_voltage_max_uv. CAUTION: in some texts this is referred + * to as "trickle charging" but the use in the Linux kernel is different + * see below! + * + * 3. Then the main charging current is applied, which is called the constant + * current (CC) phase. A current regulator is set up to allow + * constant_charge_current_max_ua of current to flow into the battery. + * The chemical reaction in the battery will make the voltage go up as + * charge goes into the battery. This current is applied until we reach + * the constant_charge_voltage_max_uv voltage. + * + * 4. At this voltage we switch over to the constant voltage (CV) phase. This + * means we allow current to go into the battery, but we keep the voltage + * fixed. This current will continue to charge the battery while keeping + * the voltage the same. A chemical reaction in the battery goes on + * storing energy without affecting the voltage. Over time the current + * will slowly drop and when we reach charge_term_current_ua we will + * end the constant voltage phase. + * + * After this the battery is fully charged, and if we do not support maintenance + * charging, the charging will not restart until power dissipation makes the + * voltage fall so that we reach charge_restart_voltage_uv and at this point + * we restart charging at the appropriate phase, usually this will be inside + * the CV phase. + * + * If we support maintenance charging the voltage is however kept high after + * the CV phase with a very low current. This is meant to let the same charge + * go in for usage while the charger is still connected, mainly for + * dissipation for the power consuming entity while connected to the + * charger. + * + * All charging MUST terminate if the overvoltage_limit_uv is ever reached. + * Overcharging Lithium Ion cells can be DANGEROUS and lead to fire or + * explosions. + * + * The power supply class itself doesn't use this struct as of now. */ struct power_supply_battery_info { - unsigned int technology; /* from the enum above */ - int energy_full_design_uwh; /* microWatt-hours */ - int charge_full_design_uah; /* microAmp-hours */ - int voltage_min_design_uv; /* microVolts */ - int voltage_max_design_uv; /* microVolts */ - int tricklecharge_current_ua; /* microAmps */ - int precharge_current_ua; /* microAmps */ - int precharge_voltage_max_uv; /* microVolts */ - int charge_term_current_ua; /* microAmps */ - int charge_restart_voltage_uv; /* microVolts */ - int overvoltage_limit_uv; /* microVolts */ - int constant_charge_current_max_ua; /* microAmps */ - int constant_charge_voltage_max_uv; /* microVolts */ - int factory_internal_resistance_uohm; /* microOhms */ - int ocv_temp[POWER_SUPPLY_OCV_TEMP_MAX];/* celsius */ - int temp_ambient_alert_min; /* celsius */ - int temp_ambient_alert_max; /* celsius */ - int temp_alert_min; /* celsius */ - int temp_alert_max; /* celsius */ - int temp_min; /* celsius */ - int temp_max; /* celsius */ + unsigned int technology; + int energy_full_design_uwh; + int charge_full_design_uah; + int voltage_min_design_uv; + int voltage_max_design_uv; + int tricklecharge_current_ua; + int precharge_current_ua; + int precharge_voltage_max_uv; + int charge_term_current_ua; + int charge_restart_voltage_uv; + int overvoltage_limit_uv; + int constant_charge_current_max_ua; + int constant_charge_voltage_max_uv; + int factory_internal_resistance_uohm; + int ocv_temp[POWER_SUPPLY_OCV_TEMP_MAX]; + int temp_ambient_alert_min; + int temp_ambient_alert_max; + int temp_alert_min; + int temp_alert_max; + int temp_min; + int temp_max; struct power_supply_battery_ocv_table *ocv_table[POWER_SUPPLY_OCV_TEMP_MAX]; int ocv_table_size[POWER_SUPPLY_OCV_TEMP_MAX]; struct power_supply_resistance_temp_table *resist_table; -- cgit v1.2.3-71-gd317 From 25fd330370ac40653671f323acc7fb6db27ef6fe Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 15 Dec 2021 02:01:18 +0100 Subject: 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 Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500-bm.h | 2 +- drivers/power/supply/ab8500_bmdata.c | 7 +++--- drivers/power/supply/ab8500_btemp.c | 10 ++++++--- drivers/power/supply/ab8500_chargalg.c | 16 +++++++------- drivers/power/supply/ab8500_fg.c | 18 ++++++++------- drivers/power/supply/axp20x_battery.c | 6 ++--- drivers/power/supply/bd99954-charger.c | 24 +++++++++++--------- drivers/power/supply/bq24190_charger.c | 6 ++--- drivers/power/supply/bq2515x_charger.c | 8 +++---- drivers/power/supply/bq256xx_charger.c | 24 ++++++++++---------- drivers/power/supply/bq25980_charger.c | 6 ++--- drivers/power/supply/bq27xxx_battery.c | 38 ++++++++++++++++---------------- drivers/power/supply/cw2015_battery.c | 20 +++++++++++------ drivers/power/supply/ingenic-battery.c | 14 ++++++------ drivers/power/supply/power_supply_core.c | 19 ++++++++++++++-- drivers/power/supply/sc2731_charger.c | 8 +++---- drivers/power/supply/sc27xx_fuel_gauge.c | 22 +++++++++--------- drivers/power/supply/smb347-charger.c | 34 ++++++++++++++-------------- include/linux/power_supply.h | 2 +- 19 files changed, 157 insertions(+), 127 deletions(-) (limited to 'include/linux') diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h index 57e1a8e27e51..56a5aaf9a27a 100644 --- a/drivers/power/supply/ab8500-bm.h +++ b/drivers/power/supply/ab8500-bm.h @@ -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; diff --git a/drivers/power/supply/ab8500_bmdata.c b/drivers/power/supply/ab8500_bmdata.c index 62953f9cb85a..7ae95f537580 100644 --- a/drivers/power/supply/ab8500_bmdata.c +++ b/drivers/power/supply/ab8500_bmdata.c @@ -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); } diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 20253b8a7fe9..cc33c5187fbb 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -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); diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c index 86d740ce3a63..c4a2fe07126c 100644 --- a/drivers/power/supply/ab8500_chargalg.c +++ b/drivers/power/supply/ab8500_chargalg.c @@ -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; diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index eb3e5c4ca44f..b0919a6a6587 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -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); diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index 18a9db0df4b1..5d197141f476 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -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)) diff --git a/drivers/power/supply/bd99954-charger.c b/drivers/power/supply/bd99954-charger.c index ffd8bfa08179..96e93e1b8094 100644 --- a/drivers/power/supply/bd99954-charger.c +++ b/drivers/power/supply/bd99954-charger.c @@ -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, diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 35ff0c8fe96f..06c34b09349c 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -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; diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c index 374b112f712a..4f76ad9c2f18 100644 --- a/drivers/power/supply/bq2515x_charger.c +++ b/drivers/power/supply/bq2515x_charger.c @@ -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, diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c index f501ecd49202..b274942dc46a 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -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; } diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c index 0008c229fd9c..9daa6d14db4d 100644 --- a/drivers/power/supply/bq25980_charger.c +++ b/drivers/power/supply/bq25980_charger.c @@ -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, diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 7e5e24b585d8..72e727cd31e8 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -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); } /* diff --git a/drivers/power/supply/cw2015_battery.c b/drivers/power/supply/cw2015_battery.c index 091868e9e9e8..0c87ad0dbf71 100644 --- a/drivers/power/supply/cw2015_battery.c +++ b/drivers/power/supply/cw2015_battery.c @@ -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; } diff --git a/drivers/power/supply/ingenic-battery.c b/drivers/power/supply/ingenic-battery.c index 8b18219ebe90..2e7fdfde47ec 100644 --- a/drivers/power/supply/ingenic-battery.c +++ b/drivers/power/supply/ingenic-battery.c @@ -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); diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 2907b84ceea9..fffb87dca5a0 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -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); diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c index 288b79836c13..9ac17cf7a126 100644 --- a/drivers/power/supply/sc2731_charger.c +++ b/drivers/power/supply/sc2731_charger.c @@ -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 */ diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index ae45069bd5e1..632977f84b95 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -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) diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c index 753944e774c4..d56e469043bb 100644 --- a/drivers/power/supply/smb347-charger.c +++ b/drivers/power/supply/smb347-charger.c @@ -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 || diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index f6e94eae4f28..86b4d5c4dab9 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -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, -- cgit v1.2.3-71-gd317