summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chen <philipchen@google.com>2018-05-17 18:55:27 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-21 18:19:22 -0700
commit453647e21a9e584cd0ee8567efef3d81371ae27f (patch)
treecd1a505e1945c2233cef34a40bf3a9f0a555544e
parentd8186821885b7403d3118810ab56fc617068db1d (diff)
downloadchrome-ec-453647e21a9e584cd0ee8567efef3d81371ae27f.tar.gz
charge_state_v2: Throttle AP in low battery voltage
When EC sees voltage drops below BAT_LOW_VOLTAGE_THRESH, we kick off a timer and ask AP to throttle. When the timer expires which means EC hasn't seen under-voltage for BAT_UVP_TIMEOUT_US, we ask AP to stop throttling. We reset the throttling status and do nothing when AP is off (S5). BUG=b:73050145, 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 UVP. Change-Id: Ia760989f760f95549f7a8a8acb1d01de23feab5a Signed-off-by: Philip Chen <philipchen@google.com> Reviewed-on: https://chromium-review.googlesource.com/1064983 Commit-Ready: Philip Chen <philipchen@chromium.org> Tested-by: Philip Chen <philipchen@chromium.org> Reviewed-by: David Schneider <dnschneid@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--common/build.mk1
-rw-r--r--common/charge_state_v2.c46
-rw-r--r--include/config.h8
-rw-r--r--include/throttle_ap.h4
4 files changed, 56 insertions, 3 deletions
diff --git a/common/build.mk b/common/build.mk
index 1a0f27e5bf..d64288b5ff 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -109,6 +109,7 @@ 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_THROTTLE_AP_ON_BAT_VOLTAGE)+=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
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index f237e84bc1..28ec48c3b0 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -55,6 +55,14 @@
(BAT_MAX_DISCHG_CURRENT * BAT_OCP_HYSTERESIS_PCT / 100) /* mA */
#endif /* CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT */
+#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
+#ifndef CONFIG_HOSTCMD_EVENTS
+#error "CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE needs CONFIG_HOSTCMD_EVENTS"
+#endif /* CONFIG_HOSTCMD_EVENTS */
+#define BAT_UVP_TIMEOUT_US (60 * SECOND)
+static timestamp_t uvp_throttle_start_time;
+#endif /* CONFIG_THROTTLE_AP_ON_BAT_OLTAGE */
+
static int charge_request(int voltage, int current);
/*
@@ -1320,7 +1328,7 @@ static int shutdown_on_critical_battery(void)
* host events. We send these even if the AP is off, since the AP will read and
* discard any events it doesn't care about the next time it wakes up.
*/
-static void notify_host_of_low_battery(void)
+static void notify_host_of_low_battery_charge(void)
{
/* We can't tell what the current charge is. Assume it's okay. */
if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE)
@@ -1343,6 +1351,29 @@ static void set_charge_state(enum charge_state_v2 state)
curr.state = state;
}
+static void notify_host_of_low_battery_voltage(void)
+{
+#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
+ if ((curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) ||
+ chipset_in_state(CHIPSET_STATE_ANY_OFF))
+ return;
+
+ if (curr.batt.voltage < BAT_LOW_VOLTAGE_THRESH) {
+ if (!uvp_throttle_start_time.val) {
+ throttle_ap(THROTTLE_ON, THROTTLE_SOFT,
+ THROTTLE_SRC_BAT_VOLTAGE);
+ }
+ uvp_throttle_start_time = get_time();
+ } else if (uvp_throttle_start_time.val &&
+ (get_time().val > uvp_throttle_start_time.val +
+ BAT_UVP_TIMEOUT_US)) {
+ throttle_ap(THROTTLE_OFF, THROTTLE_SOFT,
+ THROTTLE_SRC_BAT_VOLTAGE);
+ uvp_throttle_start_time.val = 0;
+ }
+#endif
+}
+
static void notify_host_of_over_current(struct batt_params *batt)
{
#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
@@ -1400,6 +1431,16 @@ DECLARE_HOOK(HOOK_AC_CHANGE, charge_wakeup, HOOK_PRIO_DEFAULT);
DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_base_reset, HOOK_PRIO_DEFAULT);
#endif
+#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
+static void bat_low_voltage_throttle_reset(void)
+{
+ uvp_throttle_start_time.val = 0;
+}
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN,
+ bat_low_voltage_throttle_reset,
+ HOOK_PRIO_DEFAULT);
+#endif
+
static int get_desired_input_current(enum battery_present batt_present,
const struct charger_info * const info)
{
@@ -1702,7 +1743,8 @@ wait_for_it:
/* Wait on the dynamic info until the static info is good. */
if (!need_static)
update_dynamic_battery_info();
- notify_host_of_low_battery();
+ notify_host_of_low_battery_charge();
+ notify_host_of_low_battery_voltage();
/* And the EC console */
is_full = calc_is_full();
diff --git a/include/config.h b/include/config.h
index 4511fb39ea..3264ffa195 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2634,6 +2634,14 @@
#undef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
/*
+ * Throttle the CPU when battery voltage drops below a defined threshold
+ * where the board still boots but some components don't function perfectly.
+ * When this feature is enabled, BAT_LOW_VOLTAGE_THRESH must be defined in
+ * board.h.
+ */
+#undef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
+
+/*
* If defined, dptf is enabled to manage thermals.
*
* NOTE: This doesn't mean that thermal control is completely taken care by
diff --git a/include/throttle_ap.h b/include/throttle_ap.h
index db651c432e..a149207667 100644
--- a/include/throttle_ap.h
+++ b/include/throttle_ap.h
@@ -31,6 +31,7 @@ enum throttle_type {
enum throttle_sources {
THROTTLE_SRC_THERMAL = 0,
THROTTLE_SRC_BAT_DISCHG_CURRENT,
+ THROTTLE_SRC_BAT_VOLTAGE,
};
/**
@@ -44,7 +45,8 @@ enum throttle_sources {
* @param source Which task is requesting throttling
*/
#if defined(CONFIG_THROTTLE_AP) || \
- defined(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)
+ defined(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT) || \
+ defined(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE)
void throttle_ap(enum throttle_level level,
enum throttle_type type,