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:
Philip Chen
2018-04-03 15:10:01 -07:00
committed by chrome-bot
parent ec1428f96d
commit bf62593ebd
4 changed files with 58 additions and 4 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);