summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/battery.c22
-rw-r--r--driver/battery/smart.c2
-rw-r--r--include/battery.h24
-rw-r--r--include/config.h14
-rw-r--r--test/battery_get_params_smart.c5
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 */