mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-12 19:04:59 +00:00
charge_state_v2: Throttle AP in high battery discharge current
When EC sees discharge current hit BAT_MAX_DISCHG_CURRENT, we kick off a timer and ask AP to throttle. Then EC keeps monitoring discharge current. If the current doesn't drop below BAT_MAX_DISCHG_CURRENT - BAT_OCP_HYSTERESIS, we restart the timer and notify AP again, which shouldn't happen unless AP misses or ignores the first notification. When the timer expires, which means EC hasn't seen over-current for BAT_OCP_TIMEOUT_US, we ask AP to stop throttling. BUG=b:74321682, chromium:838754 BRANCH=scarlet TEST=manually test on scarlet, confirm EC sends EC_HOST_EVENT_THROTTLE_START and EC_HOST_EVENT_THROTTLE_STOP host events when entering/exiting OCP. Change-Id: I1e55fc23249596d8afec52a3885655ca9c1f2151 Signed-off-by: Philip Chen <philipchen@google.com> Reviewed-on: https://chromium-review.googlesource.com/994188 Commit-Ready: Philip Chen <philipchen@chromium.org> Tested-by: Philip Chen <philipchen@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
This commit is contained in:
@@ -107,6 +107,7 @@ common-$(CONFIG_SW_CRC)+=crc.o
|
||||
common-$(CONFIG_TABLET_MODE)+=tablet_mode.o
|
||||
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o
|
||||
common-$(CONFIG_THROTTLE_AP)+=thermal.o throttle_ap.o
|
||||
common-$(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)+=throttle_ap.o
|
||||
common-$(CONFIG_TPM_I2CS)+=i2cs_tpm.o
|
||||
common-$(CONFIG_TPM_LOGGING)+=event_log.o tpm_log.o
|
||||
common-$(CONFIG_U2F)+=u2f.o
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "printf.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "throttle_ap.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -41,6 +42,20 @@
|
||||
#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
|
||||
#error "CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT needs CONFIG_HOSTCMD_EVENTS"
|
||||
#endif /* CONFIG_HOSTCMD_EVENTS */
|
||||
#define BAT_OCP_TIMEOUT_US (60 * SECOND)
|
||||
/* BAT_OCP_HYSTERESIS_PCT can be optionally overridden in board.h. */
|
||||
#ifndef BAT_OCP_HYSTERESIS_PCT
|
||||
#define BAT_OCP_HYSTERESIS_PCT 10
|
||||
#endif /* BAT_OCP_HYSTERESIS_PCT */
|
||||
#define BAT_OCP_HYSTERESIS \
|
||||
(BAT_MAX_DISCHG_CURRENT * BAT_OCP_HYSTERESIS_PCT / 100) /* mA */
|
||||
static timestamp_t ocp_throttle_start_time;
|
||||
#endif /* CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT */
|
||||
|
||||
static int charge_request(int voltage, int current);
|
||||
|
||||
/*
|
||||
@@ -1326,6 +1341,33 @@ static void set_charge_state(enum charge_state_v2 state)
|
||||
curr.state = state;
|
||||
}
|
||||
|
||||
static void notify_host_of_over_current(struct batt_params *batt)
|
||||
{
|
||||
#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
|
||||
if (batt->flags & BATT_FLAG_BAD_CURRENT)
|
||||
return;
|
||||
|
||||
if ((!ocp_throttle_start_time.val &&
|
||||
(batt->current < -BAT_MAX_DISCHG_CURRENT)) ||
|
||||
(ocp_throttle_start_time.val &&
|
||||
(batt->current < -BAT_MAX_DISCHG_CURRENT + BAT_OCP_HYSTERESIS))) {
|
||||
ocp_throttle_start_time = get_time();
|
||||
throttle_ap(THROTTLE_ON, THROTTLE_SOFT,
|
||||
THROTTLE_SRC_BAT_DISCHG_CURRENT);
|
||||
} else if (ocp_throttle_start_time.val &&
|
||||
(get_time().val > ocp_throttle_start_time.val +
|
||||
BAT_OCP_TIMEOUT_US)) {
|
||||
/*
|
||||
* Clear the timer and notify AP to stop throttling if
|
||||
* we haven't seen over current for BAT_OCP_TIMEOUT_US.
|
||||
*/
|
||||
ocp_throttle_start_time.val = 0;
|
||||
throttle_ap(THROTTLE_OFF, THROTTLE_SOFT,
|
||||
THROTTLE_SRC_BAT_DISCHG_CURRENT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const struct batt_params *charger_current_battery_params(void)
|
||||
{
|
||||
return &curr.batt;
|
||||
@@ -1500,6 +1542,8 @@ void charger_task(void *u)
|
||||
curr.batt.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE;
|
||||
}
|
||||
|
||||
notify_host_of_over_current(&curr.batt);
|
||||
|
||||
/*
|
||||
* Now decide what we want to do about it. We'll normally just
|
||||
* pass along whatever the battery wants to the charger. Note
|
||||
|
||||
@@ -2616,6 +2616,13 @@
|
||||
|
||||
/* Compile common code for throttling the CPU based on the temp sensors */
|
||||
#undef CONFIG_THROTTLE_AP
|
||||
|
||||
/*
|
||||
* Throttle the CPU when battery discharge current is too high. When
|
||||
* this feature is enabled, BAT_MAX_DISCHG_CURRENT must be defined in board.h.
|
||||
*/
|
||||
#undef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
|
||||
|
||||
/*
|
||||
* If defined, dptf is enabled to manage thermals.
|
||||
*
|
||||
@@ -3416,8 +3423,8 @@
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Throttle AP must have temperature sensor enabled to get the readings for
|
||||
* thermal throttling.
|
||||
* Thermal throttling AP must have temperature sensor enabled to get
|
||||
* the temperature readings.
|
||||
*/
|
||||
#if defined(CONFIG_THROTTLE_AP) && !defined(CONFIG_TEMP_SENSOR)
|
||||
#define CONFIG_TEMP_SENSOR
|
||||
|
||||
@@ -30,7 +30,7 @@ enum throttle_type {
|
||||
*/
|
||||
enum throttle_sources {
|
||||
THROTTLE_SRC_THERMAL = 0,
|
||||
THROTTLE_SRC_POWER,
|
||||
THROTTLE_SRC_BAT_DISCHG_CURRENT,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,7 +43,9 @@ enum throttle_sources {
|
||||
* @param type Type of throttling desired
|
||||
* @param source Which task is requesting throttling
|
||||
*/
|
||||
#ifdef CONFIG_TEMP_SENSOR
|
||||
#if defined(CONFIG_THROTTLE_AP) || \
|
||||
defined(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)
|
||||
|
||||
void throttle_ap(enum throttle_level level,
|
||||
enum throttle_type type,
|
||||
enum throttle_sources source);
|
||||
|
||||
Reference in New Issue
Block a user