mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 10:45:22 +00:00
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>
This commit is contained in:
committed by
chrome-bot
parent
730491df20
commit
abdb022a2b
@@ -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:
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user