summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-01-26 14:51:10 +0800
committerDaisuke Nojiri <dnojiri@chromium.org>2018-02-19 10:33:13 -0800
commitabd7e17534bc356565d2914d05a71c7fd246156d (patch)
tree0454a339d543e2c356f6e379db2e74df206e9714
parent275f873534c54941f1976d21a5d84dc21df02759 (diff)
downloadchrome-ec-abd7e17534bc356565d2914d05a71c7fd246156d.tar.gz
battery: Allow 2 batteries to be fetched via ACPI
We share the same shared memory fields for both batteries. When the host wants to switch battery to read out: - The host sets EC_ACPI_MEM_BATTERY_INDEX to the required index - EC then swaps the data is the shared memory fields, then update EC_MEMMAP_BATT_INDEX - Host waits for EC_MEMMAP_BATT_INDEX to have the required value, then fetches the data BRANCH=none BUG=b:65697620 TEST=Boot lux, both /sys/class/power_supply/BAT0 and BAT1 are present, data is valid. TEST=Unplug base, BAT1 goes away, replug, BAT1 comes back. Change-Id: Icce12f9eef2f6f8cde9bae0a968a65e1703d0369 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/888382 Reviewed-by: Gwendal Grignou <gwendal@google.com>
-rw-r--r--common/acpi.c7
-rw-r--r--common/battery.c80
-rw-r--r--common/charge_state_v2.c60
-rw-r--r--include/battery.h18
-rw-r--r--include/ec_commands.h9
5 files changed, 159 insertions, 15 deletions
diff --git a/common/acpi.c b/common/acpi.c
index 76c90127d1..e21eb93b97 100644
--- a/common/acpi.c
+++ b/common/acpi.c
@@ -4,6 +4,7 @@
*/
#include "acpi.h"
+#include "battery.h"
#include "common.h"
#include "console.h"
#include "dptf.h"
@@ -216,6 +217,12 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
case EC_ACPI_MEM_TEST:
acpi_mem_test = data;
break;
+#ifdef CONFIG_BATTERY_V2
+ case EC_ACPI_MEM_BATTERY_INDEX:
+ CPRINTS("ACPI battery %d", data);
+ battery_memmap_set_index(data);
+ break;
+#endif
#ifdef CONFIG_PWM_KBLIGHT
case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
/*
diff --git a/common/battery.c b/common/battery.c
index 711d7f7913..365278d79d 100644
--- a/common/battery.c
+++ b/common/battery.c
@@ -442,10 +442,8 @@ 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
-#ifndef CONFIG_BATTERY_V2
-#error "CONFIG_HOSTCMD_BATTERY_V2 cannot be set without CONFIG_BATTERY_V2."
-#endif
static int host_command_battery_get_static(struct host_cmd_handler_args *args)
{
const struct ec_params_battery_static_info *p = args->params;
@@ -480,3 +478,79 @@ 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, EC_MEMMAP_TEXT_MAX);
+
+ /* 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, EC_MEMMAP_TEXT_MAX);
+
+ /* Battery Model string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
+ memcpy(batt_str, battery_static[i].model, EC_MEMMAP_TEXT_MAX);
+
+ /* Battery Type string */
+ batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
+ memcpy(batt_str, battery_static[i].type, EC_MEMMAP_TEXT_MAX);
+
+ *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 */
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index 787e16d856..ebcf8cc263 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -217,6 +217,7 @@ static const struct dual_battery_policy db_policy = {
(total_power) -= val_capped; \
} while (0)
+/* Update base battery information */
static void update_base_battery_info(void)
{
struct ec_response_battery_dynamic_info *const bd =
@@ -225,21 +226,41 @@ static void update_base_battery_info(void)
base_connected = board_is_base_connected();
if (!base_connected) {
+ const int invalid_flags = EC_BATT_FLAG_INVALID_DATA;
/* Invalidate static/dynamic information */
- bd->flags = EC_BATT_FLAG_INVALID_DATA;
+ if (bd->flags != invalid_flags) {
+ bd->flags = invalid_flags;
+
+ host_set_single_event(EC_HOST_EVENT_BATTERY);
+ host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
+ }
charge_base = -1;
base_responsive = 0;
prev_current_base = 0;
prev_allow_charge_base = 0;
} else if (base_responsive) {
int old_flags = bd->flags;
+ int flags_changed;
+ int old_full_capacity = bd->full_capacity;
ec_ec_master_base_get_dynamic_info();
-
+ flags_changed = (old_flags != bd->flags);
/* Fetch static information when flags change. */
- if (old_flags != bd->flags)
+ if (flags_changed)
ec_ec_master_base_get_static_info();
+ battery_memmap_refresh(BATT_IDX_BASE);
+
+ /* Newly connected battery, or change in capacity. */
+ if (old_flags & EC_BATT_FLAG_INVALID_DATA ||
+ ((old_flags & EC_BATT_FLAG_BATT_PRESENT) !=
+ (bd->flags & EC_BATT_FLAG_BATT_PRESENT)) ||
+ old_full_capacity != bd->full_capacity)
+ host_set_single_event(EC_HOST_EVENT_BATTERY);
+
+ if (flags_changed)
+ host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
+
/* Update charge_base */
if (bd->flags & (BATT_FLAG_BAD_FULL_CAPACITY |
BATT_FLAG_BAD_REMAINING_CAPACITY))
@@ -778,11 +799,10 @@ static int update_static_battery_info(void)
if (rv)
problem(PR_STATIC_UPDATE, rv);
- else
- ; /*
- * TODO(b:65697620): Do we need to set a flag to indicate that
- * the information is now valid?
- */
+
+#ifdef HAS_TASK_HOSTCMD
+ battery_memmap_refresh(BATT_IDX_MAIN);
+#endif
return rv;
}
@@ -791,6 +811,8 @@ static void update_dynamic_battery_info(void)
{
static int __bss_slow 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];
@@ -802,6 +824,9 @@ static void update_dynamic_battery_info(void)
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
@@ -809,6 +834,8 @@ static void update_dynamic_battery_info(void)
*/
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;
}
@@ -845,6 +872,8 @@ static void update_dynamic_battery_info(void)
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 &&
@@ -855,7 +884,22 @@ static void update_dynamic_battery_info(void)
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 */
diff --git a/include/battery.h b/include/battery.h
index b783432ded..a97745b794 100644
--- a/include/battery.h
+++ b/include/battery.h
@@ -13,8 +13,9 @@
/* Battery index, only used with CONFIG_BATTERY_V2. */
enum battery_index {
- BATT_IDX_MAIN,
- BATT_IDX_BASE,
+ BATT_IDX_INVALID = -1,
+ BATT_IDX_MAIN = 0,
+ BATT_IDX_BASE = 1,
};
#ifdef CONFIG_BATTERY_V2
@@ -377,6 +378,19 @@ void print_battery_debug(void);
*/
enum battery_disconnect_state battery_get_disconnect_state(void);
+#ifdef CONFIG_BATTERY_V2
+/**
+ * Refresh battery information in host memory mapped region, if index is
+ * currently presented.
+ */
+void battery_memmap_refresh(enum battery_index index);
+
+/**
+ * Set which index to present in host memory mapped region.
+ */
+void battery_memmap_set_index(enum battery_index index);
+#endif /* CONFIG_BATTERY_V2 */
+
#ifdef CONFIG_CMD_I2C_STRESS_TEST_BATTERY
extern struct i2c_stress_test_dev battery_i2c_stress_test_dev;
#endif
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 00c6dad089..7a6f7648e6 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -84,11 +84,14 @@
#define EC_MEMMAP_SWITCHES 0x30 /* 8 bits */
/* Unused 0x31 - 0x33 */
#define EC_MEMMAP_HOST_EVENTS 0x34 /* 64 bits */
-/* Battery values are all 32 bits */
+/* Battery values are all 32 bits, unless otherwise noted. */
#define EC_MEMMAP_BATT_VOLT 0x40 /* Battery Present Voltage */
#define EC_MEMMAP_BATT_RATE 0x44 /* Battery Present Rate */
#define EC_MEMMAP_BATT_CAP 0x48 /* Battery Remaining Capacity */
-#define EC_MEMMAP_BATT_FLAG 0x4c /* Battery State, defined below */
+#define EC_MEMMAP_BATT_FLAG 0x4c /* Battery State, see below (8-bit) */
+#define EC_MEMMAP_BATT_COUNT 0x4d /* Battery Count (8-bit) */
+#define EC_MEMMAP_BATT_INDEX 0x4e /* Current Battery Data Index (8-bit) */
+/* Unused 0x4f */
#define EC_MEMMAP_BATT_DCAP 0x50 /* Battery Design Capacity */
#define EC_MEMMAP_BATT_DVLT 0x54 /* Battery Design Voltage */
#define EC_MEMMAP_BATT_LFCC 0x58 /* Battery Last Full Charge Capacity */
@@ -347,6 +350,8 @@
#define EC_ACPI_MEM_DEVICE_FEATURES6 0x10
#define EC_ACPI_MEM_DEVICE_FEATURES7 0x11
+#define EC_ACPI_MEM_BATTERY_INDEX 0x12
+
/*
* ACPI addresses 0x20 - 0xff map to EC_MEMMAP offset 0x00 - 0xdf. This data
* is read-only from the AP. Added in EC_ACPI_MEM_VERSION 2.