ec/google/chromeec: Refactor Battery SoC calculation

On certain platforms, such as Qualcomm X1P42100 (Hamoa), the AP cannot
successfully execute the standard CHARGE_STATE_CMD_GET_STATE host
command while in the S0 power state. This is typically due to hardware
arbitration or access restrictions to the battery fuel gauge bus during
active operating states.

This patch introduces a mechanism to fallback to manual State of Charge
(SoC) calculation using dynamic battery metrics:

1. Add EC_GOOGLE_CHROMEEC_BATTERY_SOC_DYNAMIC Kconfig: Allows platforms
   to opt-in to manual SoC calculation.
2. Refactor existing logic: The standard command is moved to an internal
   static helper google_chromeec_read_batt_state_of_charge_cmd().
3. Unified API: google_chromeec_read_batt_state_of_charge() now switches
   between the standard command and the raw/dynamic calculation at
   compile-time based on the Kconfig selection.

By using ec_cmd_battery_get_dynamic(), the AP retrieves cached telemetry
from the EC. This avoids triggering synchronous bus transactions to the
battery, ensuring SoC data is available even when direct fuel gauge
access is restricted.

BUG=none
BRANCH=none
TEST=Build for Hamoa and verify SoC is correctly calculated via the
dynamic info path. Verify standard platforms still use the charge
state command path.

Change-Id: I4928017362140884762140884762140884762140
Signed-off-by: Subrata Banik <subratabanik@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90618
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
This commit is contained in:
Subrata Banik 2025-12-24 17:39:17 +00:00
commit bab8ca2bd0
3 changed files with 41 additions and 12 deletions

View file

@ -234,6 +234,22 @@ config EC_GOOGLE_CHROMEEC_LPC_GENERIC_MEMORY_SIZE
hex
default 0x10000
config EC_GOOGLE_CHROMEEC_BATTERY_SOC_DYNAMIC
bool
default n
help
Enable this option to calculate the battery State of Charge (SoC)
manually using remaining and full capacity metrics.
On certain platforms, such as Qualcomm X1P42100 (Hamoa), the AP
cannot use the standard CHARGE_STATE_CMD_GET_STATE host command
while in the S0 power state due to hardware arbitration or
access restrictions to the battery fuel gauge.
Selecting this option forces the use of ec_cmd_battery_get_dynamic(),
which retrieves cached telemetry from the EC rather than triggering
a synchronous bus transaction to the battery.
endif # EC_GOOGLE_CHROMEEC
source "src/ec/google/chromeec/*/Kconfig"

View file

@ -1862,7 +1862,7 @@ void platform_do_early_poweroff(void)
}
/*
* Reads the current battery charge percentage.
* Reads the current battery charge percentage using CHARGE_STATE_CMD_GET_STATE CMD.
*
* This function communicates with the Embedded Controller (EC) via a host
* command to retrieve the "State of Charge" (SoC) as calculated by the battery fuel gauge.
@ -1871,7 +1871,7 @@ void platform_do_early_poweroff(void)
* Return Value (state): Pointer to a uint32_t where the battery state of charge
* (0-100) will be stored.
*/
int google_chromeec_read_batt_state_of_charge(uint32_t *state)
static int google_chromeec_read_batt_state_of_charge_cmd(uint32_t *state)
{
struct ec_params_charge_state params;
struct ec_response_charge_state resp;
@ -1895,7 +1895,7 @@ int google_chromeec_read_batt_state_of_charge(uint32_t *state)
* Return: 0 on success, -1 on communication failure or invalid battery data.
* Return Value (state): Pointer to store the calculated State of Charge (0-100%).
*/
int google_chromeec_read_batt_state_of_charge_raw(uint32_t *state)
static int google_chromeec_read_batt_state_of_charge_raw(uint32_t *state)
{
struct ec_params_battery_dynamic_info params = {
.index = 0,
@ -1918,3 +1918,25 @@ int google_chromeec_read_batt_state_of_charge_raw(uint32_t *state)
return 0;
}
/*
* Reads the current battery charge percentage.
*
* This function communicates with the Embedded Controller (EC) via a host
* command to retrieve the "State of Charge" (SoC) as calculated by the battery fuel gauge.
*
* Return: 0 on success, -1 on failure (communication error or EC rejection).
* Return Value (state): Pointer to a uint32_t where the battery state of charge
* (0-100) will be stored.
*/
int google_chromeec_read_batt_state_of_charge(uint32_t *state)
{
int ret;
if (CONFIG(EC_GOOGLE_CHROMEEC_BATTERY_SOC_DYNAMIC))
ret = google_chromeec_read_batt_state_of_charge_raw(state);
else
ret = google_chromeec_read_batt_state_of_charge_cmd(state);
return ret;
}

View file

@ -546,13 +546,4 @@ void chipset_ioport_range(uint16_t *base, size_t *size);
*/
int google_chromeec_read_batt_state_of_charge(uint32_t *state);
/*
* Reads the current battery charge percentage from EC dynamic info CMD.
* This is often used when the high-level "Get Charge State" command is unavailable".
*
* @param state Pointer to a uint32_t where the battery state of charge (0-100) will be
* stored.
*/
int google_chromeec_read_batt_state_of_charge_raw(uint32_t *state);
#endif /* _EC_GOOGLE_CHROMEEC_EC_H */