diff options
author | Nicolas Boichat <drinkcat@chromium.org> | 2018-01-26 14:51:10 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-02-09 07:55:33 -0800 |
commit | abdb022a2be9cac6a108b69253ccba1dd7e09ba3 (patch) | |
tree | 1a5875279ab48a4187be57b2b3651b4500aa89e8 | |
parent | 730491df202e5b14e489a5ab31a78e47fcd47af3 (diff) | |
download | chrome-ec-abdb022a2be9cac6a108b69253ccba1dd7e09ba3.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.c | 7 | ||||
-rw-r--r-- | common/battery.c | 80 | ||||
-rw-r--r-- | common/charge_state_v2.c | 60 | ||||
-rw-r--r-- | include/battery.h | 18 | ||||
-rw-r--r-- | include/ec_commands.h | 9 |
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. |