summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2012-03-28 02:03:57 +0800
committerVic Yang <victoryang@chromium.org>2012-03-28 11:41:46 +0800
commit68faaf2cb41b5548addc41cb6148bd498f55b099 (patch)
tree4bdc9e573fd46021f53e15e68e2750d276915b05
parenta2360b00657ecfe2cfd138edc85840571747c435 (diff)
downloadchrome-ec-68faaf2cb41b5548addc41cb6148bd498f55b099.tar.gz
factory: Deep discharge protection
Cherry-picking for factory/1987-B. Signed-off-by: Rong Chang <rongchang@chromium.org> BUG=none TEST=none Change-Id: I20c641e8e5e83185a07d47059dc038dc5cc62071
-rw-r--r--common/charge_state.c77
1 files changed, 72 insertions, 5 deletions
diff --git a/common/charge_state.c b/common/charge_state.c
index 29ea4bba9c..db42caedca 100644
--- a/common/charge_state.c
+++ b/common/charge_state.c
@@ -19,6 +19,9 @@
#include "timer.h"
#include "uart.h"
#include "util.h"
+#include "x86_power.h"
+#include "system.h"
+#include "chipset.h"
/* Stop charge when state of charge reaches this percentage */
#define STOP_CHARGE_THRESHOLD 100
@@ -29,6 +32,9 @@
#define POLL_PERIOD_SHORT 100000
#define MIN_SLEEP_USEC 50000
+/* charger update period in usec */
+#define CHARGER_UPDATE_PERIOD 1000000
+
/* Power state error flags */
#define F_CHARGER_INIT (1 << 0) /* Charger initialization */
#define F_CHARGER_VOLTAGE (1 << 1) /* Charger maximun output voltage */
@@ -93,6 +99,8 @@ struct power_state_context {
uint32_t *memmap_batt_rate;
uint32_t *memmap_batt_cap;
uint8_t *memmap_batt_flags;
+ /* Charger update timestamp */
+ timestamp_t charger_update_time;
};
/* helper function(s) */
@@ -101,6 +109,49 @@ static inline int get_ac(void)
return gpio_get_level(GPIO_AC_PRESENT);
}
+/* Prevent battery from going into deep discharge state */
+static void poweroff_wait_ac(void)
+{
+ /* Shutdown the main processor
+ * TODO(rong): remove platform dependent code
+ * use host_force_shutdown() instead
+ */
+
+ if (!chipset_in_state(CHIPSET_STATE_ON))
+ return;
+ system_reset(1);
+#ifdef CONFIG_POWER_X86POWER
+ x86_power_force_shutdown();
+
+ /* power_force_shutdown() was not implemented yet.
+ * TODO(rong): remove following code block after
+ * crosbug.com/p/8242
+ */
+ uart_puts("[battery low - x86 forcing G3]\n");
+ gpio_set_level(GPIO_PCH_PWROK, 0);
+ gpio_set_level(GPIO_ENABLE_VCORE, 0);
+ gpio_set_level(GPIO_PCH_RCINn, 0);
+ gpio_set_level(GPIO_ENABLE_VS, 0);
+ gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0);
+ gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0);
+ gpio_set_level(GPIO_ENABLE_1_5V_DDR, 0);
+ gpio_set_level(GPIO_SHUNT_1_5V_DDR, 1);
+ gpio_set_level(GPIO_PCH_RSMRSTn, 0);
+#endif /* CONFIG_POWER_X86POWER */
+
+ /* TODO(rong): battery deep sleep
+ * pause charging task
+ * put battery in deep sleep
+ * enable only GPIO_AC_PRESENT interrupt and deep sleep ec
+ */
+
+ /* Proto1 workaround */
+ while (!get_ac()) {
+ /* Check ac_present every 5 seconds */
+ usleep(5000000);
+ }
+}
+
/* Common handler for charging states.
* This handler gets battery charging parameters, charger state, ac state,
* and timestamp. It also fills memory map and issues power events on state
@@ -185,6 +236,17 @@ static int state_common(struct power_state_context *ctx)
if (rv)
curr->error |= F_BATTERY_STATE_OF_CHARGE;
+ /* Prevent deep discharge
+ * TODO(rong): move voltage threshold to battery pack
+ */
+ if (!curr->ac)
+ if ((batt->state_of_charge == 0 &&
+ !(curr->error & F_BATTERY_STATE_OF_CHARGE)) ||
+ (/*batt->voltage <= 6800 &&*/
+ batt->state_of_charge <= 15 &&
+ !(curr->error & F_BATTERY_VOLTAGE)))
+ poweroff_wait_ac();
+
/* Check battery presence */
if (curr->error & F_BATTERY_MASK) {
*ctx->memmap_batt_flags &= ~EC_BATT_FLAG_BATT_PRESENT;
@@ -287,6 +349,8 @@ static enum power_state state_idle(struct power_state_context *ctx)
return PWR_STATE_ERROR;
if (charger_set_current(ctx->curr.batt.desired_current))
return PWR_STATE_ERROR;
+
+ ctx->charger_update_time = get_time();
return PWR_STATE_CHARGE;
}
@@ -316,12 +380,15 @@ static enum power_state state_charge(struct power_state_context *ctx)
return PWR_STATE_IDLE;
}
- if (ctx->curr.batt.desired_voltage != ctx->curr.charging_voltage)
- if (charger_set_voltage(ctx->curr.batt.desired_voltage))
- return PWR_STATE_ERROR;
- if (ctx->curr.batt.desired_current != ctx->curr.charging_current)
- if (charger_set_current(ctx->curr.batt.desired_current))
+ if ((ctx->curr.batt.desired_voltage != ctx->curr.charging_voltage) ||
+ (ctx->curr.batt.desired_current != ctx->curr.charging_current) ||
+ (ctx->curr.ts.val - ctx->charger_update_time.val >
+ CHARGER_UPDATE_PERIOD)) {
+ if (charger_set_voltage(ctx->curr.batt.desired_voltage) ||
+ charger_set_current(ctx->curr.batt.desired_current))
return PWR_STATE_ERROR;
+ ctx->charger_update_time = get_time();
+ }
return PWR_STATE_UNCHANGE;
}