diff options
-rw-r--r-- | common/battery.c | 22 | ||||
-rw-r--r-- | driver/battery/smart.c | 2 | ||||
-rw-r--r-- | include/battery.h | 24 | ||||
-rw-r--r-- | include/config.h | 14 | ||||
-rw-r--r-- | test/battery_get_params_smart.c | 5 |
5 files changed, 67 insertions, 0 deletions
diff --git a/common/battery.c b/common/battery.c index 9d7277479c..9d380efe86 100644 --- a/common/battery.c +++ b/common/battery.c @@ -21,6 +21,12 @@ #define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) #define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +/* + * See config.h for details. + * TODO: Allow host (powerd) to update it. + */ +static int batt_full_factor = CONFIG_BATT_FULL_FACTOR; + #ifdef CONFIG_BATTERY_V2 /* * Store battery information in these 2 structures. Main (lid) battery is always @@ -557,6 +563,22 @@ DECLARE_HOOK(HOOK_INIT, battery_init, HOOK_PRIO_DEFAULT); #endif /* HAS_TASK_HOSTCMD */ #endif /* CONFIG_BATTERY_V2 */ +void battery_compensate_params(struct batt_params *batt) +{ + int remain = batt->remaining_capacity; + int full = batt->full_capacity; + + if ((batt->flags & BATT_FLAG_BAD_FULL_CAPACITY) || + (batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) + return; + + if (remain <= 0 || full <= 0) + return; + + if (remain * 100 > full * batt_full_factor) + batt->remaining_capacity = full; +} + __attribute__((weak)) int get_battery_manufacturer_name(char *dest, int size) { strzcpy(dest, "<unkn>", size); diff --git a/driver/battery/smart.c b/driver/battery/smart.c index 90abbe80a8..fd27e55ab9 100644 --- a/driver/battery/smart.c +++ b/driver/battery/smart.c @@ -395,6 +395,8 @@ void battery_get_params(struct batt_params *batt) /* Force both to zero */ batt_new.desired_voltage = batt_new.desired_current = 0; + battery_compensate_params(&batt_new); + /* Update visible battery parameters */ memcpy(batt, &batt_new, sizeof(*batt)); } diff --git a/include/battery.h b/include/battery.h index 30ec6fdab7..805dc851c9 100644 --- a/include/battery.h +++ b/include/battery.h @@ -414,4 +414,28 @@ void battery_memmap_set_index(enum battery_index index); extern struct i2c_stress_test_dev battery_i2c_stress_test_dev; #endif +/* + * If remaining charge is more than x% of the full capacity, the + * remaining charge is raised to the full capacity before it's + * reported to the rest of the system. + * + * Some batteries don't update full capacity timely or don't update it + * at all. On such systems, compensation is required to guarantee + * the remaining charge will be equal to the full capacity eventually. + * + * On some systems, Rohm charger generates audio noise when the battery + * is fully charged and AC is plugged. A workaround is to do charge- + * discharge cycles between 93 and 100%. On such systems, compensation + * was also applied to mask this cycle from users. + * + * This used to be done in ACPI, thus, all software components except EC + * was seeing the compensated charge. Now we do it in EC. It has more + * knowledge on the charger and the battery. So, it can perform more + * granular and precise compensation. + * + * TODO: Currently, this is applied only to smart battery. Apply it to other + * battery drivers as needed. + */ +void battery_compensate_params(struct batt_params *batt); + #endif /* __CROS_EC_BATTERY_H */ diff --git a/include/config.h b/include/config.h index e6a72b0d7f..d732145fae 100644 --- a/include/config.h +++ b/include/config.h @@ -492,6 +492,20 @@ #undef CONFIG_BATTERY_MEASURE_IMBALANCE /* + * If remaining capacity is x% of full capacity, remaining capacity is set + * equal to full capacity. + * + * Some batteries don't update full capacity timely or don't update it at all. + * On such systems, compensation is required to guarantee remaining_capacity + * will be equal to full_capacity eventually. This used to be done in ACPI. + * + * This number should match those used by powerd to evenly scale battery + * reading from 0 to 100%. These are default values, which are effective until + * the host boots. + */ +#define CONFIG_BATT_FULL_FACTOR 98 + +/* * Expose some data when it is needed. * For example, battery disconnect state */ diff --git a/test/battery_get_params_smart.c b/test/battery_get_params_smart.c index 316424e080..c44cd64e56 100644 --- a/test/battery_get_params_smart.c +++ b/test/battery_get_params_smart.c @@ -19,6 +19,11 @@ static int fail_on_first, fail_on_last; static int read_count, write_count; struct batt_params batt; + +void battery_compensate_params(struct batt_params *batt) +{ +} + static void reset_and_fail_on(int first, int last) { /* We're not initializing the fake battery, so everything reads zero */ |