summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2021-10-15 14:18:28 -0700
committerCommit Bot <commit-bot@chromium.org>2021-10-26 22:16:37 +0000
commit8106efd33a7897e071410201ba85804bfba9dfcd (patch)
tree0a706751becdccdf06fb38211730da1c21bd8efc
parent1f1103b4b875a4ce12fb666fa69572747e02996c (diff)
downloadchrome-ec-8106efd33a7897e071410201ba85804bfba9dfcd.tar.gz
Battery: Move battery code to battery_v1.c and v2.c
BUG=b:198722643, b:203031618 BRANCH=None TEST=buildall Change-Id: I595da56412f4d30684b00d1138f7e2339c7f5204 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3227372 Reviewed-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Keith Short <keithshort@chromium.org>
-rw-r--r--common/battery.c154
-rw-r--r--common/battery_v1.c172
-rw-r--r--common/battery_v2.c368
-rw-r--r--common/build.mk2
-rw-r--r--common/charge_state_v2.c393
-rw-r--r--include/battery.h15
-rw-r--r--include/charge_state_v2.h20
-rw-r--r--include/config.h15
-rw-r--r--test/test_config.h2
-rw-r--r--zephyr/CMakeLists.txt4
-rw-r--r--zephyr/Kconfig.battery36
-rw-r--r--zephyr/shim/include/config_chip.h13
12 files changed, 661 insertions, 533 deletions
diff --git a/common/battery.c b/common/battery.c
index 6791e4d3a2..6339573d2e 100644
--- a/common/battery.c
+++ b/common/battery.c
@@ -29,15 +29,6 @@
const static int batt_host_full_factor = CONFIG_BATT_HOST_FULL_FACTOR;
const static int batt_host_shutdown_pct = CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE;
-#ifdef CONFIG_BATTERY_V2
-/*
- * Store battery information in these 2 structures. Main (lid) battery is always
- * at index 0, and secondary (base) battery at index 1.
- */
-struct ec_response_battery_static_info_v1 battery_static[CONFIG_BATTERY_COUNT];
-struct ec_response_battery_dynamic_info battery_dynamic[CONFIG_BATTERY_COUNT];
-#endif
-
#ifdef CONFIG_BATTERY_CUT_OFF
#ifndef CONFIG_BATTERY_CUTOFF_DELAY_US
@@ -469,151 +460,6 @@ DECLARE_HOST_COMMAND(EC_CMD_BATTERY_VENDOR_PARAM,
EC_VER_MASK(0));
#endif /* CONFIG_BATTERY_VENDOR_PARAM */
-#ifdef CONFIG_BATTERY_V2
-#ifdef CONFIG_HOSTCMD_BATTERY_V2
-static void battery_update(enum battery_index i);
-static enum ec_status
-host_command_battery_get_static(struct host_cmd_handler_args *args)
-{
- const struct ec_params_battery_static_info *p = args->params;
- struct ec_response_battery_static_info_v1 *bat;
-
- if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT)
- return EC_RES_INVALID_PARAM;
- bat = &battery_static[p->index];
-
- battery_update(p->index);
- if (args->version == 0) {
- struct ec_response_battery_static_info *r = args->response;
-
- args->response_size = sizeof(*r);
- r->design_capacity = bat->design_capacity;
- r->design_voltage = bat->design_voltage;
- r->cycle_count = bat->cycle_count;
-
- /* Truncate strings to reduced v0 size */
- memcpy(&r->manufacturer, &bat->manufacturer_ext,
- sizeof(r->manufacturer));
- r->manufacturer[sizeof(r->manufacturer) - 1] = 0;
- memcpy(&r->model, &bat->model_ext, sizeof(r->model));
- r->model[sizeof(r->model) - 1] = 0;
- memcpy(&r->serial, &bat->serial_ext, sizeof(r->serial));
- r->serial[sizeof(r->serial) - 1] = 0;
- memcpy(&r->type, &bat->type_ext, sizeof(r->type));
- r->type[sizeof(r->type) - 1] = 0;
- } else {
- /* v1 command stores the same data internally */
- struct ec_response_battery_static_info_v1 *r = args->response;
-
- args->response_size = sizeof(*r);
- memcpy(r, bat, sizeof(*r));
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_STATIC,
- host_command_battery_get_static,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static enum ec_status
-host_command_battery_get_dynamic(struct host_cmd_handler_args *args)
-{
- const struct ec_params_battery_dynamic_info *p = args->params;
- struct ec_response_battery_dynamic_info *r = args->response;
-
- if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT)
- return EC_RES_INVALID_PARAM;
-
- args->response_size = sizeof(*r);
- memcpy(r, &battery_dynamic[p->index], sizeof(*r));
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_DYNAMIC,
- host_command_battery_get_dynamic,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_BATTERY_V2 */
-
-#ifdef HAS_TASK_HOSTCMD
-static void battery_update(enum battery_index i)
-{
- char *batt_str;
- int *memmap_dcap = (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP);
- int *memmap_dvlt = (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT);
- int *memmap_ccnt = (int *)host_get_memmap(EC_MEMMAP_BATT_CCNT);
- int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT);
- int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE);
- int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP);
- int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC);
- uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
-
- /* Smart battery serial number is 16 bits */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL);
- memcpy(batt_str, battery_static[i].serial_ext, EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- /* Design Capacity of Full */
- *memmap_dcap = battery_static[i].design_capacity;
-
- /* Design Voltage */
- *memmap_dvlt = battery_static[i].design_voltage;
-
- /* Cycle Count */
- *memmap_ccnt = battery_static[i].cycle_count;
-
- /* Battery Manufacturer string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR);
- memcpy(batt_str, battery_static[i].manufacturer_ext,
- EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- /* Battery Model string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
- memcpy(batt_str, battery_static[i].model_ext, EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- /* Battery Type string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
- memcpy(batt_str, battery_static[i].type_ext, EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- *memmap_volt = battery_dynamic[i].actual_voltage;
- *memmap_rate = battery_dynamic[i].actual_current;
- *memmap_cap = battery_dynamic[i].remaining_capacity;
- *memmap_lfcc = battery_dynamic[i].full_capacity;
- *memmap_flags = battery_dynamic[i].flags;
-}
-
-void battery_memmap_refresh(enum battery_index index)
-{
- if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index)
- battery_update(index);
-}
-
-void battery_memmap_set_index(enum battery_index index)
-{
- if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index)
- return;
-
- *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID;
- if (index < 0 || index >= CONFIG_BATTERY_COUNT)
- return;
-
- battery_update(index);
- *host_get_memmap(EC_MEMMAP_BATT_INDEX) = index;
-}
-
-static void battery_init(void)
-{
- *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID;
- *host_get_memmap(EC_MEMMAP_BATT_COUNT) = CONFIG_BATTERY_COUNT;
- *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 2;
-
- battery_memmap_set_index(BATT_IDX_MAIN);
-}
-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)
{
diff --git a/common/battery_v1.c b/common/battery_v1.c
new file mode 100644
index 0000000000..3b18f43ee5
--- /dev/null
+++ b/common/battery_v1.c
@@ -0,0 +1,172 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Battery V1 APIs.
+ */
+
+#include "battery.h"
+#include "charge_state.h"
+#include "common.h"
+#include "console.h"
+#include "extpower.h"
+#include "host_command.h"
+#include "math_util.h"
+#include "printf.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+
+/* Returns zero if every item was updated. */
+int update_static_battery_info(void)
+{
+ char *batt_str;
+ int batt_serial;
+ uint8_t batt_flags = 0;
+ /*
+ * The return values have type enum ec_error_list, but EC_SUCCESS is
+ * zero. We'll just look for any failures so we can try them all again.
+ */
+ int rv;
+
+ /* Smart battery serial number is 16 bits */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL);
+ memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
+ rv = battery_serial_number(&batt_serial);
+ if (!rv)
+ snprintf(batt_str, EC_MEMMAP_TEXT_MAX, "%04X", batt_serial);
+
+ /* Design Capacity of Full */
+ rv |= battery_design_capacity(
+ (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP));
+
+ /* Design Voltage */
+ rv |= battery_design_voltage(
+ (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT));
+
+ /* Last Full Charge Capacity (this is only mostly static) */
+ rv |= battery_full_charge_capacity(
+ (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC));
+
+ /* Cycle Count */
+ rv |= battery_cycle_count((int *)host_get_memmap(EC_MEMMAP_BATT_CCNT));
+
+ /* Battery Manufacturer string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR);
+ memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
+ rv |= battery_manufacturer_name(batt_str, EC_MEMMAP_TEXT_MAX);
+
+ /* Battery Model string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
+ memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
+ rv |= battery_device_name(batt_str, EC_MEMMAP_TEXT_MAX);
+
+ /* Battery Type string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
+ rv |= battery_device_chemistry(batt_str, EC_MEMMAP_TEXT_MAX);
+
+ /* Zero the dynamic entries. They'll come next. */
+ *(int *)host_get_memmap(EC_MEMMAP_BATT_VOLT) = 0;
+ *(int *)host_get_memmap(EC_MEMMAP_BATT_RATE) = 0;
+ *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP) = 0;
+ *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC) = 0;
+ if (extpower_is_present())
+ batt_flags |= EC_BATT_FLAG_AC_PRESENT;
+ *host_get_memmap(EC_MEMMAP_BATT_FLAG) = batt_flags;
+
+ if (rv)
+ charge_problem(PR_STATIC_UPDATE, rv);
+ else
+ /* No errors seen. Battery data is now present */
+ *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 1;
+
+ return rv;
+}
+
+void update_dynamic_battery_info(void)
+{
+ /* The memmap address is constant. We should fix these calls somehow. */
+ int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT);
+ int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE);
+ int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP);
+ int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC);
+ uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
+ uint8_t tmp;
+ int send_batt_status_event = 0;
+ int send_batt_info_event = 0;
+ static int batt_present;
+ struct charge_state_data *curr;
+
+ curr = charge_get_status();
+ tmp = 0;
+ if (curr->ac)
+ tmp |= EC_BATT_FLAG_AC_PRESENT;
+
+ if (curr->batt.is_present == BP_YES) {
+ tmp |= EC_BATT_FLAG_BATT_PRESENT;
+ batt_present = 1;
+ /* Tell the AP to read battery info if it is newly present. */
+ if (!(*memmap_flags & EC_BATT_FLAG_BATT_PRESENT))
+ send_batt_info_event++;
+ } else {
+ /*
+ * Require two consecutive updates with BP_NOT_SURE
+ * before reporting it gone to the host.
+ */
+ if (batt_present)
+ tmp |= EC_BATT_FLAG_BATT_PRESENT;
+ else if (*memmap_flags & EC_BATT_FLAG_BATT_PRESENT)
+ send_batt_info_event++;
+ batt_present = 0;
+ }
+
+ if (curr->batt.flags & EC_BATT_FLAG_INVALID_DATA)
+ tmp |= EC_BATT_FLAG_INVALID_DATA;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE))
+ *memmap_volt = curr->batt.voltage;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT))
+ *memmap_rate = ABS(curr->batt.current);
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) {
+ /*
+ * If we're running off the battery, it must have some charge.
+ * Don't report zero charge, as that has special meaning
+ * to Chrome OS powerd.
+ */
+ if (curr->batt.remaining_capacity == 0 && !curr->batt_is_charging)
+ *memmap_cap = 1;
+ else
+ *memmap_cap = curr->batt.remaining_capacity;
+ }
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) &&
+ (curr->batt.full_capacity <= (*memmap_lfcc - LFCC_EVENT_THRESH) ||
+ curr->batt.full_capacity >= (*memmap_lfcc + LFCC_EVENT_THRESH))) {
+ *memmap_lfcc = curr->batt.full_capacity;
+ /* Poke the AP if the full_capacity changes. */
+ send_batt_info_event++;
+ }
+
+ if (curr->batt.is_present == BP_YES &&
+ !(curr->batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
+ curr->batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
+ tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
+
+ tmp |= curr->batt_is_charging ? EC_BATT_FLAG_CHARGING :
+ EC_BATT_FLAG_DISCHARGING;
+
+ /* Tell the AP to re-read battery status if charge state changes */
+ if (*memmap_flags != tmp)
+ send_batt_status_event++;
+
+ /* Update flags before sending host events. */
+ *memmap_flags = tmp;
+
+ if (send_batt_info_event)
+ host_set_single_event(EC_HOST_EVENT_BATTERY);
+ if (send_batt_status_event)
+ host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
+}
diff --git a/common/battery_v2.c b/common/battery_v2.c
new file mode 100644
index 0000000000..3fc203b9e8
--- /dev/null
+++ b/common/battery_v2.c
@@ -0,0 +1,368 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Battery V2 APIs.
+ */
+
+#include "battery.h"
+#include "charge_state.h"
+#include "common.h"
+#include "console.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "printf.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+
+/*
+ * Store battery information in these 2 structures. Main (lid) battery is always
+ * at index 0, and secondary (base) battery at index 1.
+ */
+struct ec_response_battery_static_info_v1 battery_static[CONFIG_BATTERY_COUNT];
+struct ec_response_battery_dynamic_info battery_dynamic[CONFIG_BATTERY_COUNT];
+
+#ifdef HAS_TASK_HOSTCMD
+static void battery_update(enum battery_index i)
+{
+ char *batt_str;
+ int *memmap_dcap = (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP);
+ int *memmap_dvlt = (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT);
+ int *memmap_ccnt = (int *)host_get_memmap(EC_MEMMAP_BATT_CCNT);
+ int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT);
+ int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE);
+ int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP);
+ int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC);
+ uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
+
+ /* Smart battery serial number is 16 bits */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL);
+ memcpy(batt_str, battery_static[i].serial_ext, EC_MEMMAP_TEXT_MAX);
+ batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
+
+ /* Design Capacity of Full */
+ *memmap_dcap = battery_static[i].design_capacity;
+
+ /* Design Voltage */
+ *memmap_dvlt = battery_static[i].design_voltage;
+
+ /* Cycle Count */
+ *memmap_ccnt = battery_static[i].cycle_count;
+
+ /* Battery Manufacturer string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR);
+ memcpy(batt_str, battery_static[i].manufacturer_ext,
+ EC_MEMMAP_TEXT_MAX);
+ batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
+
+ /* Battery Model string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
+ memcpy(batt_str, battery_static[i].model_ext, EC_MEMMAP_TEXT_MAX);
+ batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
+
+ /* Battery Type string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
+ memcpy(batt_str, battery_static[i].type_ext, EC_MEMMAP_TEXT_MAX);
+ batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
+
+ *memmap_volt = battery_dynamic[i].actual_voltage;
+ *memmap_rate = battery_dynamic[i].actual_current;
+ *memmap_cap = battery_dynamic[i].remaining_capacity;
+ *memmap_lfcc = battery_dynamic[i].full_capacity;
+ *memmap_flags = battery_dynamic[i].flags;
+}
+
+#ifdef CONFIG_HOSTCMD_BATTERY_V2
+static enum ec_status
+host_command_battery_get_static(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_battery_static_info *p = args->params;
+ const struct ec_response_battery_static_info_v1 *bat;
+
+ if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT)
+ return EC_RES_INVALID_PARAM;
+ bat = &battery_static[p->index];
+
+ battery_update(p->index);
+ if (args->version == 0) {
+ struct ec_response_battery_static_info *r = args->response;
+
+ r->design_capacity = bat->design_capacity;
+ r->design_voltage = bat->design_voltage;
+ r->cycle_count = bat->cycle_count;
+
+ /* Truncate strings to reduced v0 size */
+ memcpy(&r->manufacturer, &bat->manufacturer_ext,
+ sizeof(r->manufacturer));
+ r->manufacturer[sizeof(r->manufacturer) - 1] = 0;
+ memcpy(&r->model, &bat->model_ext, sizeof(r->model));
+ r->model[sizeof(r->model) - 1] = 0;
+ memcpy(&r->serial, &bat->serial_ext, sizeof(r->serial));
+ r->serial[sizeof(r->serial) - 1] = 0;
+ memcpy(&r->type, &bat->type_ext, sizeof(r->type));
+ r->type[sizeof(r->type) - 1] = 0;
+
+ args->response_size = sizeof(*r);
+ } else if (args->version == 1) {
+ /* v1 command stores the same data internally */
+ struct ec_response_battery_static_info_v1 *r = args->response;
+
+ args->response_size = sizeof(*r);
+ memcpy(r, bat, sizeof(*r));
+ }
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_STATIC,
+ host_command_battery_get_static,
+ EC_VER_MASK(0) | EC_VER_MASK(1));
+
+static enum ec_status
+host_command_battery_get_dynamic(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_battery_dynamic_info *p = args->params;
+ struct ec_response_battery_dynamic_info *r = args->response;
+
+ if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT)
+ return EC_RES_INVALID_PARAM;
+
+ args->response_size = sizeof(*r);
+ memcpy(r, &battery_dynamic[p->index], sizeof(*r));
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_DYNAMIC,
+ host_command_battery_get_dynamic,
+ EC_VER_MASK(0));
+#endif /* CONFIG_HOSTCMD_BATTERY_V2 */
+
+void battery_memmap_refresh(enum battery_index index)
+{
+ if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index)
+ battery_update(index);
+}
+
+void battery_memmap_set_index(enum battery_index index)
+{
+ if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index)
+ return;
+
+ *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID;
+ if (index < 0 || index >= CONFIG_BATTERY_COUNT)
+ return;
+
+ battery_update(index);
+ *host_get_memmap(EC_MEMMAP_BATT_INDEX) = index;
+}
+
+static void battery_init(void)
+{
+ *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID;
+ *host_get_memmap(EC_MEMMAP_BATT_COUNT) = CONFIG_BATTERY_COUNT;
+ *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 2;
+
+ battery_memmap_set_index(BATT_IDX_MAIN);
+}
+DECLARE_HOOK(HOOK_INIT, battery_init, HOOK_PRIO_DEFAULT);
+#endif /* HAS_TASK_HOSTCMD */
+
+static int is_battery_string_reliable(const char *buf)
+{
+ /*
+ * From is_string_printable rule, 0xFF is not printable.
+ * So, EC should think battery string is unreliable if string
+ * include 0xFF.
+ */
+ while (*buf) {
+ if ((*buf) == 0xFF)
+ return 0;
+ buf++;
+ }
+
+ return 1;
+}
+
+int update_static_battery_info(void)
+{
+ int batt_serial;
+ int val;
+ /*
+ * The return values have type enum ec_error_list, but EC_SUCCESS is
+ * zero. We'll just look for any failures so we can try them all again.
+ */
+ int rv, ret;
+
+ struct ec_response_battery_static_info_v1 *const bs =
+ &battery_static[BATT_IDX_MAIN];
+
+ /* Clear all static information. */
+ memset(bs, 0, sizeof(*bs));
+
+ /* Smart battery serial number is 16 bits */
+ rv = battery_serial_number(&batt_serial);
+ if (!rv)
+ snprintf(bs->serial_ext, sizeof(bs->serial_ext),
+ "%04X", batt_serial);
+
+ /* Design Capacity of Full */
+ ret = battery_design_capacity(&val);
+ if (!ret)
+ bs->design_capacity = val;
+ rv |= ret;
+
+ /* Design Voltage */
+ ret = battery_design_voltage(&val);
+ if (!ret)
+ bs->design_voltage = val;
+ rv |= ret;
+
+ /* Cycle Count */
+ ret = battery_cycle_count(&val);
+ if (!ret)
+ bs->cycle_count = val;
+ rv |= ret;
+
+ /* Battery Manufacturer string */
+ rv |= battery_manufacturer_name(bs->manufacturer_ext,
+ sizeof(bs->manufacturer_ext));
+
+ /* Battery Model string */
+ rv |= battery_device_name(bs->model_ext, sizeof(bs->model_ext));
+
+ /* Battery Type string */
+ rv |= battery_device_chemistry(bs->type_ext, sizeof(bs->type_ext));
+
+ /*
+ * b/181639264: Battery gauge follow SMBus SPEC and SMBus define
+ * cumulative clock low extend time for both controller (master) and
+ * peripheral (slave). However, I2C doesn't.
+ * Regarding this issue, we observe EC sometimes pull I2C CLK low
+ * a while after EC start running. Actually, we are not sure the
+ * reason until now.
+ * If EC pull I2C CLK low too long, and it may cause battery fw timeout
+ * because battery count cumulative clock extend time over 25ms.
+ * When it happened, battery will release both its CLK and DATA and
+ * reset itself. So, EC may get 0xFF when EC keep reading data from
+ * battery. Battery static information will be unreliable and need to
+ * be updated.
+ * This change is improvement that EC should retry if battery string is
+ * unreliable.
+ */
+ if (!is_battery_string_reliable(bs->serial_ext) ||
+ !is_battery_string_reliable(bs->manufacturer_ext) ||
+ !is_battery_string_reliable(bs->model_ext) ||
+ !is_battery_string_reliable(bs->type_ext))
+ rv |= EC_ERROR_UNKNOWN;
+
+ /* Zero the dynamic entries. They'll come next. */
+ memset(&battery_dynamic[BATT_IDX_MAIN], 0,
+ sizeof(battery_dynamic[BATT_IDX_MAIN]));
+
+ if (rv)
+ charge_problem(PR_STATIC_UPDATE, rv);
+
+#ifdef HAS_TASK_HOSTCMD
+ battery_memmap_refresh(BATT_IDX_MAIN);
+#endif
+
+ return rv;
+}
+
+void update_dynamic_battery_info(void)
+{
+ static int batt_present;
+ uint8_t tmp;
+ int send_batt_status_event = 0;
+ int send_batt_info_event = 0;
+ struct charge_state_data *curr;
+ struct ec_response_battery_dynamic_info *const bd =
+ &battery_dynamic[BATT_IDX_MAIN];
+
+ curr = charge_get_status();
+ tmp = 0;
+ if (curr->ac)
+ tmp |= EC_BATT_FLAG_AC_PRESENT;
+
+ if (curr->batt.is_present == BP_YES) {
+ tmp |= EC_BATT_FLAG_BATT_PRESENT;
+ batt_present = 1;
+ /* Tell the AP to read battery info if it is newly present. */
+ if (!(bd->flags & EC_BATT_FLAG_BATT_PRESENT))
+ send_batt_info_event++;
+ } else {
+ /*
+ * Require two consecutive updates with BP_NOT_SURE
+ * before reporting it gone to the host.
+ */
+ if (batt_present)
+ tmp |= EC_BATT_FLAG_BATT_PRESENT;
+ else if (bd->flags & EC_BATT_FLAG_BATT_PRESENT)
+ send_batt_info_event++;
+ batt_present = 0;
+ }
+
+ if (curr->batt.flags & EC_BATT_FLAG_INVALID_DATA)
+ tmp |= EC_BATT_FLAG_INVALID_DATA;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE))
+ bd->actual_voltage = curr->batt.voltage;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_CURRENT))
+ bd->actual_current = curr->batt.current;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_DESIRED_VOLTAGE))
+ bd->desired_voltage = curr->batt.desired_voltage;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_DESIRED_CURRENT))
+ bd->desired_current = curr->batt.desired_current;
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) {
+ /*
+ * If we're running off the battery, it must have some charge.
+ * Don't report zero charge, as that has special meaning
+ * to Chrome OS powerd.
+ */
+ if (curr->batt.remaining_capacity == 0 &&
+ !curr->batt_is_charging)
+ bd->remaining_capacity = 1;
+ else
+ bd->remaining_capacity = curr->batt.remaining_capacity;
+ }
+
+ if (!(curr->batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) &&
+ (curr->batt.full_capacity <=
+ (bd->full_capacity - LFCC_EVENT_THRESH) ||
+ curr->batt.full_capacity >=
+ (bd->full_capacity + LFCC_EVENT_THRESH))) {
+ bd->full_capacity = curr->batt.full_capacity;
+ /* Poke the AP if the full_capacity changes. */
+ send_batt_info_event++;
+ }
+
+ if (curr->batt.is_present == BP_YES &&
+ !(curr->batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
+ curr->batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
+ tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
+
+ tmp |= curr->batt_is_charging ? EC_BATT_FLAG_CHARGING :
+ EC_BATT_FLAG_DISCHARGING;
+
+ /* Tell the AP to re-read battery status if charge state changes */
+ if (bd->flags != tmp)
+ send_batt_status_event++;
+
+ bd->flags = tmp;
+
+#ifdef HAS_TASK_HOSTCMD
+ battery_memmap_refresh(BATT_IDX_MAIN);
+#endif
+
+#ifdef CONFIG_HOSTCMD_EVENTS
+ if (send_batt_info_event)
+ host_set_single_event(EC_HOST_EVENT_BATTERY);
+ if (send_batt_status_event)
+ host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
+#endif
+}
diff --git a/common/build.mk b/common/build.mk
index 4135b58800..67217be550 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -46,6 +46,8 @@ common-$(CONFIG_BASE32)+=base32.o
common-$(CONFIG_BLINK)+=blink.o
common-$(CONFIG_DETACHABLE_BASE)+=base_state.o
common-$(CONFIG_BATTERY)+=battery.o math_util.o
+common-$(CONFIG_BATTERY_V1)+=battery_v1.o
+common-$(CONFIG_BATTERY_V2)+=battery_v2.o
common-$(CONFIG_BATTERY_FUEL_GAUGE)+=battery_fuel_gauge.o
common-$(CONFIG_BLUETOOTH_LE)+=bluetooth_le.o
common-$(CONFIG_BLUETOOTH_LE_STACK)+=btle_hci_controller.o btle_ll.o
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index e767ec8d83..abb271cad4 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -44,7 +44,6 @@
#define CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US \
(CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT * SECOND)
#define PRECHARGE_TIMEOUT_US (PRECHARGE_TIMEOUT * SECOND)
-#define LFCC_EVENT_THRESH 5 /* Full-capacity change reqd for host event */
#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
#ifndef CONFIG_HOSTCMD_EVENTS
@@ -156,21 +155,6 @@ static int problems_exist;
static int debugging;
-/* Track problems in communicating with the battery or charger */
-enum problem_type {
- PR_STATIC_UPDATE,
- PR_SET_VOLTAGE,
- PR_SET_CURRENT,
- PR_SET_MODE,
- PR_SET_INPUT_CURR,
- PR_POST_INIT,
- PR_CHG_FLAGS,
- PR_BATT_FLAGS,
- PR_CUSTOM,
- PR_CFG_SEC_CHG,
-
- NUM_PROBLEM_TYPES
-};
static const char * const prob_text[] = {
"static update",
"set voltage",
@@ -189,7 +173,7 @@ BUILD_ASSERT(ARRAY_SIZE(prob_text) == NUM_PROBLEM_TYPES);
* TODO(crosbug.com/p/27639): When do we decide a problem is real and not
* just intermittent? And what do we do about it?
*/
-static void problem(enum problem_type p, int v)
+void charge_problem(enum problem_type p, int v)
{
static int last_prob_val[NUM_PROBLEM_TYPES];
static timestamp_t last_prob_time[NUM_PROBLEM_TYPES];
@@ -770,357 +754,6 @@ static void charge_allocate_input_current_limit(void)
}
#endif /* CONFIG_EC_EC_COMM_BATTERY_CLIENT */
-#ifndef CONFIG_BATTERY_V2
-/* Returns zero if every item was updated. */
-static int update_static_battery_info(void)
-{
- char *batt_str;
- int batt_serial;
- uint8_t batt_flags = 0;
- /*
- * The return values have type enum ec_error_list, but EC_SUCCESS is
- * zero. We'll just look for any failures so we can try them all again.
- */
- int rv;
-
- /* Smart battery serial number is 16 bits */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL);
- memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
- rv = battery_serial_number(&batt_serial);
- if (!rv)
- snprintf(batt_str, EC_MEMMAP_TEXT_MAX, "%04X", batt_serial);
-
- /* Design Capacity of Full */
- rv |= battery_design_capacity(
- (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP));
-
- /* Design Voltage */
- rv |= battery_design_voltage(
- (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT));
-
- /* Last Full Charge Capacity (this is only mostly static) */
- rv |= battery_full_charge_capacity(
- (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC));
-
- /* Cycle Count */
- rv |= battery_cycle_count((int *)host_get_memmap(EC_MEMMAP_BATT_CCNT));
-
- /* Battery Manufacturer string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR);
- memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
- rv |= battery_manufacturer_name(batt_str, EC_MEMMAP_TEXT_MAX);
-
- /* Battery Model string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
- memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
- rv |= battery_device_name(batt_str, EC_MEMMAP_TEXT_MAX);
-
- /* Battery Type string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
- rv |= battery_device_chemistry(batt_str, EC_MEMMAP_TEXT_MAX);
-
- /* Zero the dynamic entries. They'll come next. */
- *(int *)host_get_memmap(EC_MEMMAP_BATT_VOLT) = 0;
- *(int *)host_get_memmap(EC_MEMMAP_BATT_RATE) = 0;
- *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP) = 0;
- *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC) = 0;
- if (extpower_is_present())
- batt_flags |= EC_BATT_FLAG_AC_PRESENT;
- *host_get_memmap(EC_MEMMAP_BATT_FLAG) = batt_flags;
-
- if (rv)
- problem(PR_STATIC_UPDATE, rv);
- else
- /* No errors seen. Battery data is now present */
- *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 1;
-
- return rv;
-}
-
-static void update_dynamic_battery_info(void)
-{
- /* The memmap address is constant. We should fix these calls somehow. */
- int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT);
- int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE);
- int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP);
- int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC);
- uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
- uint8_t tmp;
- int send_batt_status_event = 0;
- int send_batt_info_event = 0;
- static int batt_present;
-
- tmp = 0;
- if (curr.ac)
- tmp |= EC_BATT_FLAG_AC_PRESENT;
-
- if (curr.batt.is_present == BP_YES) {
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- batt_present = 1;
- /* Tell the AP to read battery info if it is newly present. */
- if (!(*memmap_flags & EC_BATT_FLAG_BATT_PRESENT))
- send_batt_info_event++;
- } else {
- /*
- * Require two consecutive updates with BP_NOT_SURE
- * before reporting it gone to the host.
- */
- if (batt_present)
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- else if (*memmap_flags & EC_BATT_FLAG_BATT_PRESENT)
- send_batt_info_event++;
- batt_present = 0;
- }
-
- if (curr.batt.flags & EC_BATT_FLAG_INVALID_DATA)
- tmp |= EC_BATT_FLAG_INVALID_DATA;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE))
- *memmap_volt = curr.batt.voltage;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_CURRENT))
- *memmap_rate = ABS(curr.batt.current);
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) {
- /*
- * If we're running off the battery, it must have some charge.
- * Don't report zero charge, as that has special meaning
- * to Chrome OS powerd.
- */
- if (curr.batt.remaining_capacity == 0 && !curr.batt_is_charging)
- *memmap_cap = 1;
- else
- *memmap_cap = curr.batt.remaining_capacity;
- }
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) &&
- (curr.batt.full_capacity <= (*memmap_lfcc - LFCC_EVENT_THRESH) ||
- curr.batt.full_capacity >= (*memmap_lfcc + LFCC_EVENT_THRESH))) {
- *memmap_lfcc = curr.batt.full_capacity;
- /* Poke the AP if the full_capacity changes. */
- send_batt_info_event++;
- }
-
- if (curr.batt.is_present == BP_YES &&
- !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
- tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
-
- tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING :
- EC_BATT_FLAG_DISCHARGING;
-
- /* Tell the AP to re-read battery status if charge state changes */
- if (*memmap_flags != tmp)
- send_batt_status_event++;
-
- /* Update flags before sending host events. */
- *memmap_flags = tmp;
-
- if (send_batt_info_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY);
- if (send_batt_status_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
-}
-#else /* CONFIG_BATTERY_V2 */
-
-static int is_battery_string_reliable(const char *buf)
-{
- /*
- * From is_string_printable rule, 0xFF is not printable.
- * So, EC should think battery string is unreliable if string
- * include 0xFF.
- */
- while (*buf) {
- if ((*buf) == 0xFF)
- return 0;
- buf++;
- }
-
- return 1;
-}
-
-static int update_static_battery_info(void)
-{
- int batt_serial;
- int val;
- /*
- * The return values have type enum ec_error_list, but EC_SUCCESS is
- * zero. We'll just look for any failures so we can try them all again.
- */
- int rv, ret;
-
- struct ec_response_battery_static_info_v1 *const bs =
- &battery_static[BATT_IDX_MAIN];
-
- /* Clear all static information. */
- memset(bs, 0, sizeof(*bs));
-
- /* Smart battery serial number is 16 bits */
- rv = battery_serial_number(&batt_serial);
- if (!rv)
- snprintf(bs->serial_ext, sizeof(bs->serial_ext),
- "%04X", batt_serial);
-
- /* Design Capacity of Full */
- ret = battery_design_capacity(&val);
- if (!ret)
- bs->design_capacity = val;
- rv |= ret;
-
- /* Design Voltage */
- ret = battery_design_voltage(&val);
- if (!ret)
- bs->design_voltage = val;
- rv |= ret;
-
- /* Cycle Count */
- ret = battery_cycle_count(&val);
- if (!ret)
- bs->cycle_count = val;
- rv |= ret;
-
- /* Battery Manufacturer string */
- rv |= battery_manufacturer_name(bs->manufacturer_ext,
- sizeof(bs->manufacturer_ext));
-
- /* Battery Model string */
- rv |= battery_device_name(bs->model_ext, sizeof(bs->model_ext));
-
- /* Battery Type string */
- rv |= battery_device_chemistry(bs->type_ext, sizeof(bs->type_ext));
-
- /*
- * b/181639264: Battery gauge follow SMBus SPEC and SMBus define
- * cumulative clock low extend time for both controller (master) and
- * peripheral (slave). However, I2C doesn't.
- * Regarding this issue, we observe EC sometimes pull I2C CLK low
- * a while after EC start running. Actually, we are not sure the
- * reason until now.
- * If EC pull I2C CLK low too long, and it may cause battery fw timeout
- * because battery count cumulative clock extend time over 25ms.
- * When it happened, battery will release both its CLK and DATA and
- * reset itself. So, EC may get 0xFF when EC keep reading data from
- * battery. Battery static information will be unreliable and need to
- * be updated.
- * This change is improvement that EC should retry if battery string is
- * unreliable.
- */
- if (!is_battery_string_reliable(bs->serial_ext) ||
- !is_battery_string_reliable(bs->manufacturer_ext) ||
- !is_battery_string_reliable(bs->model_ext) ||
- !is_battery_string_reliable(bs->type_ext))
- rv |= EC_ERROR_UNKNOWN;
-
- /* Zero the dynamic entries. They'll come next. */
- memset(&battery_dynamic[BATT_IDX_MAIN], 0,
- sizeof(battery_dynamic[BATT_IDX_MAIN]));
-
- if (rv)
- problem(PR_STATIC_UPDATE, rv);
-
-#ifdef HAS_TASK_HOSTCMD
- battery_memmap_refresh(BATT_IDX_MAIN);
-#endif
-
- return rv;
-}
-
-static void update_dynamic_battery_info(void)
-{
- static int batt_present;
- uint8_t tmp;
- int send_batt_status_event = 0;
- int send_batt_info_event = 0;
-
- struct ec_response_battery_dynamic_info *const bd =
- &battery_dynamic[BATT_IDX_MAIN];
-
- tmp = 0;
- if (curr.ac)
- tmp |= EC_BATT_FLAG_AC_PRESENT;
-
- if (curr.batt.is_present == BP_YES) {
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- batt_present = 1;
- /* Tell the AP to read battery info if it is newly present. */
- if (!(bd->flags & EC_BATT_FLAG_BATT_PRESENT))
- send_batt_info_event++;
- } else {
- /*
- * Require two consecutive updates with BP_NOT_SURE
- * before reporting it gone to the host.
- */
- if (batt_present)
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- else if (bd->flags & EC_BATT_FLAG_BATT_PRESENT)
- send_batt_info_event++;
- batt_present = 0;
- }
-
- if (curr.batt.flags & EC_BATT_FLAG_INVALID_DATA)
- tmp |= EC_BATT_FLAG_INVALID_DATA;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE))
- bd->actual_voltage = curr.batt.voltage;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_CURRENT))
- bd->actual_current = curr.batt.current;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_DESIRED_VOLTAGE))
- bd->desired_voltage = curr.batt.desired_voltage;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_DESIRED_CURRENT))
- bd->desired_current = curr.batt.desired_current;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) {
- /*
- * If we're running off the battery, it must have some charge.
- * Don't report zero charge, as that has special meaning
- * to Chrome OS powerd.
- */
- if (curr.batt.remaining_capacity == 0 && !curr.batt_is_charging)
- bd->remaining_capacity = 1;
- else
- bd->remaining_capacity = curr.batt.remaining_capacity;
- }
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) &&
- (curr.batt.full_capacity <=
- (bd->full_capacity - LFCC_EVENT_THRESH) ||
- curr.batt.full_capacity >=
- (bd->full_capacity + LFCC_EVENT_THRESH))) {
- bd->full_capacity = curr.batt.full_capacity;
- /* Poke the AP if the full_capacity changes. */
- send_batt_info_event++;
- }
-
- if (curr.batt.is_present == BP_YES &&
- !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
- tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
-
- tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING :
- EC_BATT_FLAG_DISCHARGING;
-
- /* Tell the AP to re-read battery status if charge state changes */
- if (bd->flags != tmp)
- send_batt_status_event++;
-
- bd->flags = tmp;
-
-#ifdef HAS_TASK_HOSTCMD
- battery_memmap_refresh(BATT_IDX_MAIN);
-#endif
-
-#ifdef CONFIG_HOSTCMD_EVENTS
- if (send_batt_info_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY);
- if (send_batt_status_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
-#endif
-}
-#endif /* CONFIG_BATTERY_V2 */
-
static const char * const state_list[] = {
"idle", "discharge", "charge", "precharge"
};
@@ -1352,12 +985,12 @@ static int charge_request(int voltage, int current)
r2 = charger_set_current(0, current);
}
if (r2 != EC_SUCCESS)
- problem(PR_SET_CURRENT, r2);
+ charge_problem(PR_SET_CURRENT, r2);
if (voltage >= 0)
r1 = charger_set_voltage(0, voltage);
if (r1 != EC_SUCCESS)
- problem(PR_SET_VOLTAGE, r1);
+ charge_problem(PR_SET_VOLTAGE, r1);
#ifdef CONFIG_OCPC
/*
@@ -1374,7 +1007,7 @@ static int charge_request(int voltage, int current)
&curr.ocpc,
voltage, current);
if (r3 != EC_SUCCESS)
- problem(PR_CFG_SEC_CHG, r3);
+ charge_problem(PR_CFG_SEC_CHG, r3);
}
#endif /* CONFIG_OCPC */
@@ -1387,7 +1020,7 @@ static int charge_request(int voltage, int current)
else
r4 = charger_set_mode(CHARGE_FLAG_INHIBIT_CHARGE);
if (r4 != EC_SUCCESS)
- problem(PR_SET_MODE, r4);
+ charge_problem(PR_SET_MODE, r4);
/*
* Only update if the request worked, so we'll keep trying on failures.
@@ -1688,6 +1321,11 @@ const struct batt_params *charger_current_battery_params(void)
return &curr.batt;
}
+struct charge_state_data *charge_get_status(void)
+{
+ return &curr;
+}
+
/* Determine if the battery is outside of allowable temperature range */
static int battery_outside_charging_temperature(void)
{
@@ -2014,14 +1652,15 @@ void charger_task(void *u)
int rv = charger_post_init();
if (rv != EC_SUCCESS) {
- problem(PR_POST_INIT, rv);
+ charge_problem(PR_POST_INIT, rv);
} else if (curr.desired_input_current !=
CHARGE_CURRENT_UNINITIALIZED) {
rv = charger_set_input_current_limit(
chgnum,
curr.desired_input_current);
if (rv != EC_SUCCESS)
- problem(PR_SET_INPUT_CURR, rv);
+ charge_problem(
+ PR_SET_INPUT_CURR, rv);
}
if (rv == EC_SUCCESS)
@@ -2109,9 +1748,9 @@ void charger_task(void *u)
* better then flag it as an error.
*/
if (curr.chg.flags & CHG_FLAG_BAD_ANY)
- problem(PR_CHG_FLAGS, curr.chg.flags);
+ charge_problem(PR_CHG_FLAGS, curr.chg.flags);
if (curr.batt.flags & BATT_FLAG_BAD_ANY)
- problem(PR_BATT_FLAGS, curr.batt.flags);
+ charge_problem(PR_BATT_FLAGS, curr.batt.flags);
/*
* If AC is present, check if input current is sufficient to
@@ -2167,7 +1806,7 @@ wait_for_it:
&& get_chg_ctrl_mode() == CHARGE_CONTROL_NORMAL) {
sleep_usec = charger_profile_override(&curr);
if (sleep_usec < 0)
- problem(PR_CUSTOM, sleep_usec);
+ charge_problem(PR_CUSTOM, sleep_usec);
}
if (IS_ENABLED(CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS)
diff --git a/include/battery.h b/include/battery.h
index 2de5835807..be23863c23 100644
--- a/include/battery.h
+++ b/include/battery.h
@@ -54,6 +54,9 @@ extern struct ec_response_battery_dynamic_info
*/
#define BATTERY_LEVEL_SHUTDOWN 3
+/* Full-capacity change reqd for host event */
+#define LFCC_EVENT_THRESH 5
+
/*
* Sometimes we have hardware to detect battery present, sometimes we have to
* wait until we've been able to talk to the battery.
@@ -476,4 +479,16 @@ __override_proto void board_battery_compensate_params(struct batt_params *batt);
void battery_validate_params(struct batt_params *batt);
+/**
+ * Read static battery info from a main battery and store it in a cache.
+ *
+ * @return EC_SUCCESS or EC_ERROR_*.
+ */
+int update_static_battery_info(void);
+
+/**
+ * Read dynamic battery info from a main battery and store it in a cache.
+ */
+void update_dynamic_battery_info(void);
+
#endif /* __CROS_EC_BATTERY_H */
diff --git a/include/charge_state_v2.h b/include/charge_state_v2.h
index 9325bcfdca..dc54ac5a89 100644
--- a/include/charge_state_v2.h
+++ b/include/charge_state_v2.h
@@ -191,4 +191,24 @@ bool charge_is_current_stable(void);
*/
void trigger_ocpc_reset(void);
+/* Track problems in communicating with the battery or charger */
+enum problem_type {
+ PR_STATIC_UPDATE,
+ PR_SET_VOLTAGE,
+ PR_SET_CURRENT,
+ PR_SET_MODE,
+ PR_SET_INPUT_CURR,
+ PR_POST_INIT,
+ PR_CHG_FLAGS,
+ PR_BATT_FLAGS,
+ PR_CUSTOM,
+ PR_CFG_SEC_CHG,
+
+ NUM_PROBLEM_TYPES
+};
+
+void charge_problem(enum problem_type p, int v);
+
+struct charge_state_data *charge_get_status(void);
+
#endif /* __CROS_EC_CHARGE_STATE_V2_H */
diff --git a/include/config.h b/include/config.h
index ff6822ae51..ae78505c4f 100644
--- a/include/config.h
+++ b/include/config.h
@@ -631,14 +631,19 @@
#undef CONFIG_BATTERY_LEVEL_NEAR_FULL
/*
+ * Use memory mapped region to store battery information. It supports only
+ * single battery systems. V2 should be used unless there is a reason not to.
+ */
+#undef CONFIG_BATTERY_V1
+
+/*
* Use an alternative method to store battery information: Instead of writing
* directly to host memory mapped region, this keeps the battery information in
* ec_response_battery_static/dynamic_info structures, that can then be fetched
* using host commands, or via EC_ACPI_MEM_BATTERY_INDEX command, which tells
* the EC to update the shared memory.
*
- * This is required on dual-battery systems, and on on hostless bases with a
- * battery.
+ * This is required on dual-battery systems and hostless bases with a battery.
*/
#undef CONFIG_BATTERY_V2
@@ -5843,6 +5848,12 @@
#endif /* CONFIG_EC_EC_COMM_BATTERY */
/*****************************************************************************/
+/* If battery_v2 isn't used, it's v1. */
+#if defined(CONFIG_BATTERY) && !defined(CONFIG_BATTERY_V2)
+#define CONFIG_BATTERY_V1
+#endif
+
+/*****************************************************************************/
/* Define derived USB PD Discharge common path */
#if defined(CONFIG_USB_PD_DISCHARGE_GPIO) || \
defined(CONFIG_USB_PD_DISCHARGE_TCPC) || \
diff --git a/test/test_config.h b/test/test_config.h
index 53b8658e1d..2a0aa5e77e 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -269,6 +269,8 @@ enum sensor_id {
#ifdef TEST_SBS_CHARGING_V2
#define CONFIG_BATTERY
+#define CONFIG_BATTERY_V2
+#define CONFIG_BATTERY_COUNT 1
#define CONFIG_BATTERY_MOCK
#define CONFIG_BATTERY_SMART
#define CONFIG_CHARGER
diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt
index f2ac7bc20f..64e8ccf150 100644
--- a/zephyr/CMakeLists.txt
+++ b/zephyr/CMakeLists.txt
@@ -147,6 +147,10 @@ zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BACKLIGHT_LID
"${PLATFORM_EC}/common/backlight_lid.c")
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BATTERY
"${PLATFORM_EC}/common/battery.c")
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BATTERY_V1
+ "${PLATFORM_EC}/common/battery_v1.c")
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BATTERY_V2
+ "${PLATFORM_EC}/common/battery_v2.c")
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BATTERY_FUEL_GAUGE
"${PLATFORM_EC}/common/battery_fuel_gauge.c")
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BATTERY_SMART
diff --git a/zephyr/Kconfig.battery b/zephyr/Kconfig.battery
index 77f2086d98..ca5273caff 100644
--- a/zephyr/Kconfig.battery
+++ b/zephyr/Kconfig.battery
@@ -517,4 +517,40 @@ config PLATFORM_EC_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV
This condition is checked on chipset shutdown and startup, AC change
and battery SOC change.
+choice PLATFORM_EC_BATTERY_API
+ prompt "Battery API version"
+ default PLATFORM_EC_BATTERY_V2
+ help
+ Select the battery API version. V2 is required on dual-battery-systems
+ and hostless bases with a battery. V1 should not be used except for
+ testing on legacy boards.
+
+config PLATFORM_EC_BATTERY_V1
+ bool "Enable battery API v1"
+ depends on !PLATFORM_EC_BATTERY_V2
+ help
+ This enables battery API version 1, with support for only a single
+ battery. Battery information strings are trimmed to 8 characters.
+
+config PLATFORM_EC_BATTERY_V2
+ bool "Enable battery API v2"
+ help
+ This enables battery API version 2. This version can support multiple
+ batteries and full size string values in the battery information
+ including manufacturer, model, chemistry.
+
+endchoice
+
+if PLATFORM_EC_BATTERY_V2
+
+config PLATFORM_EC_BATTERY_COUNT
+ int "Battery count"
+ default 1
+ help
+ The number of batteries in the system. It matters only when
+ PLATFORM_EC_BATTERY_V2 is enabled. Note this is different from
+ BATTERY_TYPE_COUNT.
+
+endif # PLATFORM_EC_BATTERY_V2
+
endif # PLATFORM_EC_BATTERY
diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h
index 04bde4d975..16dbd36eca 100644
--- a/zephyr/shim/include/config_chip.h
+++ b/zephyr/shim/include/config_chip.h
@@ -152,6 +152,19 @@
#endif /* CONFIG_PLATFORM_EC_BATTERY_FUEL_GAUGE */
+#undef CONFIG_BATTERY_V1
+#ifdef CONFIG_PLATFORM_EC_BATTERY_V1
+#define CONFIG_BATTERY_V1
+#endif
+
+#undef CONFIG_BATTERY_V2
+#ifdef CONFIG_PLATFORM_EC_BATTERY_V2
+#define CONFIG_BATTERY_V2
+#endif
+
+#undef CONFIG_BATTERY_COUNT
+#define CONFIG_BATTERY_COUNT CONFIG_PLATFORM_EC_BATTERY_COUNT
+
#undef CONFIG_BATTERY_SMART
#ifdef CONFIG_PLATFORM_EC_BATTERY_SMART
#define CONFIG_BATTERY_SMART