summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-07-25 22:26:10 -0700
committerVincent Palatin <vpalatin@chromium.org>2013-07-29 06:06:36 -0700
commit00cb64eb4c498947b0015cb926739ce3a6bb2cf8 (patch)
treea2e5047261b5385c4036d255593c1dbfdcf0f6c0
parent3269b78fcfcb0dc9b0e9a12c470048f4aad24c93 (diff)
downloadchrome-ec-00cb64eb4c498947b0015cb926739ce3a6bb2cf8.tar.gz
spring: Cut off the battery when its charge is critically low
When the battery charge is too low, we should cut off the battery to prevent it from being depleted. This allows us to ignore the case where the battery voltage is 0V. Also, if we are already in hibernation, wake up every hour to check battery cut off state. BUG=chrome-os-partner:21107 TEST=Unplug the AC. Wait for the battery to cut off. BRANCH=Spring Change-Id: Ie69a89b4a01db0c5435681f0431d31a99b5014c3 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/63460 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/spring/board.h7
-rw-r--r--chip/stm32/system.c9
-rw-r--r--common/battery_spring.c60
-rw-r--r--common/gaia_power.c20
-rw-r--r--include/battery_pack.h14
5 files changed, 107 insertions, 3 deletions
diff --git a/board/spring/board.h b/board/spring/board.h
index 5510e0087e..baee52d947 100644
--- a/board/spring/board.h
+++ b/board/spring/board.h
@@ -34,6 +34,13 @@
/* Go to STANDBY mode when system is off without external power for too long */
#define CONFIG_AUTO_HIBERNATE_SECS 180
+/* Wake from hibernate every hour */
+#define CONFIG_HIBERNATE_WAKE_PERIOD_SECS 3600
+
+/* Auto battery cut-off */
+#define BATTERY_CUT_OFF_MV 10500
+#define BATTERY_CUT_OFF_DELAY (11 * SECOND)
+
/* use STOP mode when we have nothing to do */
#define CONFIG_LOW_POWER_IDLE
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 7e0c0acb0c..e89c024d12 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -7,6 +7,7 @@
#include "console.h"
#include "cpu.h"
+#include "gpio.h"
#include "registers.h"
#include "system.h"
#include "task.h"
@@ -111,6 +112,14 @@ static void check_reset_cause(void)
/* Hibernated and subsequently awakened */
flags |= RESET_FLAG_HIBERNATE;
+ if (pwr_status & 0x00000001) {
+ flags |= RESET_FLAG_WAKE_PIN;
+
+ if (gpio_get_level(GPIO_BCHGR_VACG) == 0)
+ /* WKUP=1 but not waken by WKUP pin. Must be RTC. */
+ flags |= RESET_FLAG_RTC_ALARM;
+ }
+
if (!flags && (raw_cause & 0xfe000000))
flags |= RESET_FLAG_OTHER;
diff --git a/common/battery_spring.c b/common/battery_spring.c
index 99bf8b771c..34fb2f8aed 100644
--- a/common/battery_spring.c
+++ b/common/battery_spring.c
@@ -5,15 +5,27 @@
* Smart battery driver for Spring.
*/
+#include "battery_pack.h"
+#include "console.h"
#include "host_command.h"
#include "i2c.h"
+#include "pmu_tpschrome.h"
#include "smart_battery.h"
+#include "timer.h"
#include "util.h"
#define PARAM_CUT_OFF_LOW 0x10
#define PARAM_CUT_OFF_HIGH 0x00
-int battery_command_cut_off(struct host_cmd_handler_args *args)
+#ifndef BATTERY_CUT_OFF_MV
+#define BATTERY_CUT_OFF_MV 0
+#endif
+
+#ifndef BATTERY_CUT_OFF_DELAY
+#define BATTERY_CUT_OFF_DELAY 0
+#endif
+
+int battery_cut_off(void)
{
int rv;
uint8_t buf[3];
@@ -27,9 +39,53 @@ int battery_command_cut_off(struct host_cmd_handler_args *args)
rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0);
i2c_unlock();
- if (rv)
+ return rv;
+}
+
+int battery_check_cut_off(void)
+{
+ int voltage;
+
+ if (!BATTERY_CUT_OFF_MV)
+ return 0;
+ if (battery_voltage(&voltage))
+ return 0;
+ if (voltage > BATTERY_CUT_OFF_MV)
+ return 0;
+ if (board_get_ac())
+ return 0;
+
+ ccprintf("[%T Cutting off battery]\n");
+ cflush();
+ battery_cut_off();
+ return 1;
+}
+
+int battery_command_cut_off(struct host_cmd_handler_args *args)
+{
+ if (battery_cut_off())
return EC_RES_ERROR;
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cut_off,
EC_VER_MASK(0));
+
+static int command_cutoff(int argc, char **argv)
+{
+ int tries = 5;
+
+ while (board_get_ac() && tries) {
+ ccprintf("Remove AC power in %d seconds...\n", tries);
+ tries--;
+ usleep(SECOND);
+ }
+
+ if (board_get_ac())
+ return EC_ERROR_UNKNOWN;
+
+ ccprintf("Cutting off. Please wait for 10 seconds.\n");
+
+ return battery_cut_off();
+}
+DECLARE_CONSOLE_COMMAND(cutoff, command_cutoff, NULL,
+ "Cut off the battery", NULL);
diff --git a/common/gaia_power.c b/common/gaia_power.c
index a11990add4..878ea7331b 100644
--- a/common/gaia_power.c
+++ b/common/gaia_power.c
@@ -23,6 +23,7 @@
* - If XPSHOLD is dropped by the AP, then we power the AP off
*/
+#include "battery_pack.h"
#include "clock.h"
#include "chipset.h" /* This module implements chipset functions too */
#include "common.h"
@@ -87,6 +88,10 @@
/* Default timeout for input transition */
#define FAIL_TIMEOUT (500 * MSEC) /* 500ms */
+#ifndef CONFIG_HIBERNATE_WAKE_PERIOD_SECS
+#define CONFIG_HIBERNATE_WAKE_PERIOD_SECS 0
+#endif
+
/* Application processor power state */
static int ap_on;
@@ -150,7 +155,7 @@ static void check_hibernate_timer(void)
!board_get_ac()) {
CPRINTF("[%T hibernating]\n");
pmu_battery_mode();
- system_hibernate(0, 0);
+ system_hibernate(CONFIG_HIBERNATE_WAKE_PERIOD_SECS, 0);
}
}
#else
@@ -576,6 +581,19 @@ void gaia_power_task(void)
gaia_power_init();
ap_on = 0;
+ /*
+ * If we are waken by RTC, check if we want to cut off the battery
+ * instead of booting the AP
+ */
+ if (system_get_reset_flags() & RESET_FLAG_RTC_ALARM) {
+ int rv;
+ auto_power_on = 0;
+ ccprintf("[%T Wake from RTC. Check battery.]\n");
+ rv = battery_check_cut_off();
+ ccprintf("[%T Want cut off = %d]\n", rv);
+ system_hibernate(CONFIG_HIBERNATE_WAKE_PERIOD_SECS, 0);
+ }
+
while (1) {
/* Wait until we need to power on, then power on */
wait_for_power_on();
diff --git a/include/battery_pack.h b/include/battery_pack.h
index 10022ddac1..0a43619102 100644
--- a/include/battery_pack.h
+++ b/include/battery_pack.h
@@ -44,4 +44,18 @@ const struct battery_info *battery_get_info(void);
*/
void battery_vendor_params(struct batt_params *batt);
+/**
+ * Cut off the battery.
+ * This must be called without external power. After the battery is
+ * cut off, the user need to plug in a charger to revive it.
+ */
+int battery_cut_off(void);
+
+/**
+ * Check battery status and cut off the battery if needed.
+ *
+ * @return 1 if cutting off the battery. Otherwise, 0.
+ */
+int battery_check_cut_off(void);
+
#endif