Skip to content

Commit 89f64a0

Browse files
author
Al Stone
committed
power: supply: ab8500: Standardize maintenance charging
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2071846 Tested: This is one of a series of patch sets to enable Arm SystemReady IR support in the kernel for NXP i.MX8 platforms. This set updates the power subsystem. This set has been tested via simple boot tests and the CI loop. Conflicts: drivers/power/supply/ab8500-bm.h drivers/power/supply/ab8500_bmdata.c drivers/power/supply/abx500_chargalg.c This device is not currently support, so this part of the patch was ignored. commit d72ce7d Author: Linus Walleij <linus.walleij@linaro.org> Date: Sat Feb 26 00:27:55 2022 +0100 power: supply: ab8500: Standardize maintenance charging Maintenance charging is the phase of keeping up the charge after the battery has charged fully using CC/CV charging. This can be done in many successive phases and is usually done with a slightly lower constant voltage than CV, and a slightly lower allowed current. Add an array of maintenance charging points each with a current, voltage and safety timer, and add helper functions to use these. Migrate the AB8500 code over. This is used in several Samsung products using the AB8500 and these batteries and their complete parameters will be added later as full examples, but the default battery in the AB8500 code serves as a reasonable example so far. 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> (cherry picked from commit d72ce7d) Signed-off-by: Al Stone <ahs3@redhat.com>
1 parent 67ff955 commit 89f64a0

File tree

4 files changed

+78
-7
lines changed

4 files changed

+78
-7
lines changed

drivers/power/supply/ab8500-bm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ struct abx500_v_to_cap {
300300
int voltage;
301301
int capacity;
302302
};
303-
304303
/* Forward declaration */
305304
struct abx500_fg;
306305

drivers/power/supply/abx500_chargalg.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
888888
di->ccm.max_current) {
889889
if (di->ccm.condition_cnt-- == 0) {
890890
/* Increse the iset with cco.test_delta_i */
891-
di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
891+
di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
892892
di->ccm.current_iset += di->ccm.test_delta_i;
893893
di->ccm.level++;
894894
dev_dbg(di->dev, " Maximization needed, increase"
@@ -900,8 +900,8 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
900900
di->ccm.level);
901901
return MAXIM_RET_CHANGE;
902902
} else {
903-
return MAXIM_RET_NOACTION;
904-
}
903+
return MAXIM_RET_NOACTION;
904+
}
905905
} else {
906906
di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
907907
return MAXIM_RET_NOACTION;
@@ -1329,7 +1329,6 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
13291329
di->charge_state == STATE_SUSPENDED) {
13301330
/* We don't do anything here, just don,t continue */
13311331
}
1332-
13331332
/* Safety timer expiration */
13341333
else if (di->events.safety_timer_expired) {
13351334
if (di->charge_state != STATE_SAFETY_TIMER_EXPIRED)
@@ -1443,7 +1442,6 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
14431442
case STATE_SUSPENDED:
14441443
/* CHARGING is suspended */
14451444
break;
1446-
14471445
case STATE_BATT_REMOVED_INIT:
14481446
abx500_chargalg_stop_charging(di);
14491447
abx500_chargalg_state_to(di, STATE_BATT_REMOVED);
@@ -2060,7 +2058,6 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
20602058
return ret;
20612059
}
20622060
di->curr_status.curr_step = CHARGALG_CURR_STEP_HIGH;
2063-
20642061
dev_info(di->dev, "probe success\n");
20652062
return component_add(dev, &abx500_chargalg_component_ops);
20662063
}

drivers/power/supply/power_supply_core.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
595595
info->precharge_voltage_max_uv = -EINVAL;
596596
info->charge_restart_voltage_uv = -EINVAL;
597597
info->overvoltage_limit_uv = -EINVAL;
598+
info->maintenance_charge = NULL;
598599
info->temp_ambient_alert_min = INT_MIN;
599600
info->temp_ambient_alert_max = INT_MAX;
600601
info->temp_alert_min = INT_MIN;
@@ -844,6 +845,16 @@ int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *t
844845
}
845846
EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple);
846847

848+
struct power_supply_maintenance_charge_table *
849+
power_supply_get_maintenance_charging_setting(struct power_supply_battery_info *info,
850+
int index)
851+
{
852+
if (index >= info->maintenance_charge_size)
853+
return NULL;
854+
return &info->maintenance_charge[index];
855+
}
856+
EXPORT_SYMBOL_GPL(power_supply_get_maintenance_charging_setting);
857+
847858
/**
848859
* power_supply_ocv2cap_simple() - find the battery capacity
849860
* @table: Pointer to battery OCV lookup table

include/linux/power_supply.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,52 @@ struct power_supply_resistance_temp_table {
349349
int resistance; /* internal resistance percent */
350350
};
351351

352+
/**
353+
* struct power_supply_maintenance_charge_table - setting for maintenace charging
354+
* @charge_current_max_ua: maintenance charging current that is used to keep
355+
* the charge of the battery full as current is consumed after full charging.
356+
* The corresponding charge_voltage_max_uv is used as a safeguard: when we
357+
* reach this voltage the maintenance charging current is turned off. It is
358+
* turned back on if we fall below this voltage.
359+
* @charge_voltage_max_uv: maintenance charging voltage that is usually a bit
360+
* lower than the constant_charge_voltage_max_uv. We can apply this settings
361+
* charge_current_max_ua until we get back up to this voltage.
362+
* @safety_timer_minutes: maintenance charging safety timer, with an expiry
363+
* time in minutes. We will only use maintenance charging in this setting
364+
* for a certain amount of time, then we will first move to the next
365+
* maintenance charge current and voltage pair in respective array and wait
366+
* for the next safety timer timeout, or, if we reached the last maintencance
367+
* charging setting, disable charging until we reach
368+
* charge_restart_voltage_uv and restart ordinary CC/CV charging from there.
369+
* These timers should be chosen to align with the typical discharge curve
370+
* for the battery.
371+
*
372+
* When the main CC/CV charging is complete the battery can optionally be
373+
* maintenance charged at the voltages from this table: a table of settings is
374+
* traversed using a slightly lower current and voltage than what is used for
375+
* CC/CV charging. The maintenance charging will for safety reasons not go on
376+
* indefinately: we lower the current and voltage with successive maintenance
377+
* settings, then disable charging completely after we reach the last one,
378+
* and after that we do not restart charging until we reach
379+
* charge_restart_voltage_uv (see struct power_supply_battery_info) and restart
380+
* ordinary CC/CV charging from there.
381+
*
382+
* As an example, a Samsung EB425161LA Lithium-Ion battery is CC/CV charged
383+
* at 900mA to 4340mV, then maintenance charged at 600mA and 4150mV for
384+
* 60 hours, then maintenance charged at 600mA and 4100mV for 200 hours.
385+
* After this the charge cycle is restarted waiting for
386+
* charge_restart_voltage_uv.
387+
*
388+
* For most mobile electronics this type of maintenance charging is enough for
389+
* the user to disconnect the device and make use of it before both maintenance
390+
* charging cycles are complete.
391+
*/
392+
struct power_supply_maintenance_charge_table {
393+
int charge_current_max_ua;
394+
int charge_voltage_max_uv;
395+
int charge_safety_timer_minutes;
396+
};
397+
352398
#define POWER_SUPPLY_OCV_TEMP_MAX 20
353399

354400
/**
@@ -394,6 +440,10 @@ struct power_supply_resistance_temp_table {
394440
* @constant_charge_voltage_max_uv: voltage in microvolts signifying the end of
395441
* the CC (constant current) charging phase and the beginning of the CV
396442
* (constant voltage) charging phase.
443+
* @maintenance_charge: an array of maintenance charging settings to be used
444+
* after the main CC/CV charging phase is complete.
445+
* @maintenance_charge_size: the number of maintenance charging settings in
446+
* maintenance_charge.
397447
* @factory_internal_resistance_uohm: the internal resistance of the battery
398448
* at fabrication time, expressed in microohms. This resistance will vary
399449
* depending on the lifetime and charge of the battery, so this is just a
@@ -543,6 +593,8 @@ struct power_supply_battery_info {
543593
int overvoltage_limit_uv;
544594
int constant_charge_current_max_ua;
545595
int constant_charge_voltage_max_uv;
596+
struct power_supply_maintenance_charge_table *maintenance_charge;
597+
int maintenance_charge_size;
546598
int factory_internal_resistance_uohm;
547599
int ocv_temp[POWER_SUPPLY_OCV_TEMP_MAX];
548600
int temp_ambient_alert_min;
@@ -596,13 +648,25 @@ extern int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info,
596648
extern int
597649
power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table,
598650
int table_len, int temp);
651+
extern struct power_supply_maintenance_charge_table *
652+
power_supply_get_maintenance_charging_setting(struct power_supply_battery_info *info, int index);
599653
extern void power_supply_changed(struct power_supply *psy);
600654
extern int power_supply_am_i_supplied(struct power_supply *psy);
601655
int power_supply_get_property_from_supplier(struct power_supply *psy,
602656
enum power_supply_property psp,
603657
union power_supply_propval *val);
604658
extern int power_supply_set_battery_charged(struct power_supply *psy);
605659

660+
static inline bool
661+
power_supply_supports_maintenance_charging(struct power_supply_battery_info *info)
662+
{
663+
struct power_supply_maintenance_charge_table *mt;
664+
665+
mt = power_supply_get_maintenance_charging_setting(info, 0);
666+
667+
return (mt != NULL);
668+
}
669+
606670
#ifdef CONFIG_POWER_SUPPLY
607671
extern int power_supply_is_system_supplied(void);
608672
#else

0 commit comments

Comments
 (0)