summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2012-08-23 04:03:43 +0800
committerGerrit <chrome-bot@google.com>2012-08-23 13:47:30 -0700
commit40cab432565239e6228082f6c59ad0cacb6cfe2f (patch)
tree97fc4b03e56af689fa502cdb6d892d47270526c7
parent89be1be31a32d3c0517af27e248b28db57cdac39 (diff)
downloadchrome-ec-40cab432565239e6228082f6c59ad0cacb6cfe2f.tar.gz
Blink charger LED on charging error
Charger LED is controlled by TPSCHROME chip. And it blinks only when hardware detected charging error. On other charging error conditions not detected by TPSCHROME, we set the temperature thresholds to make charger generate the error blink. Signed-off-by: Rong Chang <rongchang@chromium.org> BRANCH=snow BUG=chrome-os-partner:12224 TEST=manual Plug AC power, heat up battery to 65 C. The charging LED should start blinking instead of green. Change-Id: Ib1c38a88c026471a52fbbb4f803e3b2aba93ab40 Reviewed-on: https://gerrit.chromium.org/gerrit/31139 Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Rong Chang <rongchang@chromium.org> Commit-Ready: Rong Chang <rongchang@chromium.org>
-rw-r--r--common/pmu_tps65090.c69
-rw-r--r--common/pmu_tps65090_charger.c74
-rw-r--r--include/pmu_tpschrome.h25
3 files changed, 161 insertions, 7 deletions
diff --git a/common/pmu_tps65090.c b/common/pmu_tps65090.c
index 10e106fd75..d9b72ec765 100644
--- a/common/pmu_tps65090.c
+++ b/common/pmu_tps65090.c
@@ -44,6 +44,12 @@
#define CG_ISET_SHIFT 0
#define CG_ISET_MASK (7 << CG_ISET_SHIFT)
#define CG_NOITERM (1 << 5)
+#define CG_TSET_SHIFT 5
+#define CG_TSET_MASK (7 << CG_TSET_SHIFT)
+
+/* A temperature threshold to force charger hardware error */
+#define CG_TEMP_THRESHOLD_ERROR 0
+
/* IRQ events */
#define EVENT_VACG (1 << 1) /* AC voltage good */
@@ -55,6 +61,14 @@
/* Charger alarm */
#define CHARGER_ALARM 3
+/* Charger temperature threshold table */
+static const uint8_t const pmu_temp_threshold[] = {
+ 1, /* 0b001, 0 degree C */
+ 2, /* 0b010, 10 degree C */
+ 5, /* 0b101, 45 degree C */
+ 7, /* 0b111, 60 degree C */
+};
+
/* Read all tps65090 interrupt events */
static int pmu_get_event(int *event)
{
@@ -200,6 +214,61 @@ int pmu_set_term_voltage(enum TPS_TEMPERATURE_RANGE range,
}
/**
+ * Set temperature threshold
+ *
+ * @param temp_n TSET_T1 to TSET_T4
+ * @param value 0b000 ~ 0b111, temperature threshold
+ */
+int pmu_set_temp_threshold(enum TPS_TEMPERATURE temp_n, uint8_t value)
+{
+ int rv;
+ int reg_val;
+
+ /*
+ * Temperature threshold T1 to T4 are stored in TPSCHROME registers
+ * CG_CTRL1 to CG_CTRL4.
+ */
+ rv = pmu_read(CG_CTRL1 + temp_n, &reg_val);
+ if (rv)
+ return rv;
+
+ reg_val &= ~CG_TSET_MASK;
+ reg_val |= (value << CG_TSET_SHIFT) & CG_TSET_MASK;
+
+ return pmu_write(CG_CTRL1 + temp_n, reg_val);
+}
+
+/**
+ * Force charger into error state, turn off charging and blinks charging LED
+ *
+ * @param enable true to turn off charging and blink LED
+ * @return EC_SUCCESS for success
+ */
+int pmu_blink_led(int enable)
+{
+ int rv;
+ enum TPS_TEMPERATURE t;
+ uint8_t threshold;
+
+ for (t = TSET_T1; t <= TSET_T4; t++) {
+ if (enable)
+ threshold = CG_TEMP_THRESHOLD_ERROR;
+ else
+ threshold = pmu_temp_threshold[t];
+
+ rv = pmu_set_temp_threshold(t, threshold);
+ if (rv) {
+ /* Retry */
+ rv = pmu_set_temp_threshold(t, threshold);
+ if (rv)
+ return rv;
+ }
+ }
+
+ return EC_SUCCESS;
+}
+
+/**
* Enable low current charging
*
* @param enable enable/disable low current charging
diff --git a/common/pmu_tps65090_charger.c b/common/pmu_tps65090_charger.c
index c717216b88..f8bb0cd441 100644
--- a/common/pmu_tps65090_charger.c
+++ b/common/pmu_tps65090_charger.c
@@ -42,18 +42,18 @@
/* Non-SBS charging states */
enum charging_state {
- ST_NONE = 0,
ST_IDLE,
ST_PRE_CHARGING,
ST_CHARGING,
+ ST_CHARGING_ERROR,
ST_DISCHARGING,
};
static const char * const state_list[] = {
- "none",
"idle",
"pre-charging",
"charging",
+ "charging error",
"discharging"
};
@@ -155,6 +155,10 @@ static int calc_next_state(int state)
return ST_IDLE;
}
+ /* Stay in idle mode if charger overtemp */
+ if (pmu_is_charger_alarm())
+ return ST_IDLE;
+
/* Enable charging when battery doesn't respond */
if (battery_temperature(&batt_temp)) {
if (config_low_current_charging(0))
@@ -218,7 +222,7 @@ static int calc_next_state(int state)
CPRINTF("[pmu] charging: temperature out of range "
"%dC\n",
battery_temperature_celsius(batt_temp));
- return ST_IDLE;
+ return ST_CHARGING_ERROR;
}
/*
@@ -226,8 +230,13 @@ static int calc_next_state(int state)
* - over temperature
* - over current
*/
- if (battery_status(&alarm) || (alarm & ALARM_CHARGING)) {
+ if (battery_status(&alarm))
+ return ST_IDLE;
+
+ if (alarm & ALARM_CHARGING) {
CPUTS("[pmu] charging: battery alarm\n");
+ if (alarm & ALARM_OVER_TEMP)
+ return ST_CHARGING_ERROR;
return ST_IDLE;
}
@@ -243,6 +252,33 @@ static int calc_next_state(int state)
return ST_CHARGING;
+ case ST_CHARGING_ERROR:
+ /*
+ * This state indicates AC is plugged but the battery is not
+ * charging. The conditions to exit this state:
+ * - battery detected
+ * - battery temperature is in start charging range
+ * - no battery alarm
+ */
+ if (pmu_get_ac()) {
+ if (battery_status(&alarm))
+ return ST_CHARGING_ERROR;
+
+ if (alarm & ALARM_OVER_TEMP)
+ return ST_CHARGING_ERROR;
+
+ if (battery_temperature(&batt_temp))
+ return ST_CHARGING_ERROR;
+
+ if (!battery_charging_range(batt_temp))
+ return ST_CHARGING_ERROR;
+
+ return ST_CHARGING;
+ }
+
+ return ST_IDLE;
+
+
case ST_DISCHARGING:
/* Go back to idle state when AC is plugged */
if (pmu_get_ac())
@@ -319,15 +355,39 @@ void pmu_charger_task(void)
CPRINTF("[batt] state %s -> %s\n",
state_list[state],
state_list[next_state]);
+
state = next_state;
- if (state == ST_PRE_CHARGING || state == ST_CHARGING)
- enable_charging(1);
- else
+
+ switch (state) {
+ case ST_PRE_CHARGING:
+ case ST_CHARGING:
+ if (pmu_blink_led(0))
+ next_state = ST_CHARGING_ERROR;
+ else
+ enable_charging(1);
+ break;
+ case ST_CHARGING_ERROR:
+ /*
+ * Enable hardware charging circuit after set
+ * PMU to hardware error state.
+ */
+ if (pmu_blink_led(1))
+ enable_charging(0);
+ else
+ enable_charging(1);
+ break;
+ case ST_IDLE:
+ case ST_DISCHARGING:
enable_charging(0);
+ /* Ignore charger error when discharging */
+ pmu_blink_led(0);
+ break;
+ }
}
switch (state) {
case ST_CHARGING:
+ case ST_CHARGING_ERROR:
wait_time = T2_USEC;
break;
case ST_DISCHARGING:
diff --git a/include/pmu_tpschrome.h b/include/pmu_tpschrome.h
index 0c014a864a..57fb84a4a4 100644
--- a/include/pmu_tpschrome.h
+++ b/include/pmu_tpschrome.h
@@ -10,6 +10,15 @@
#include "gpio.h"
+/* JEITA temperature threshold */
+enum TPS_TEMPERATURE {
+ TSET_T1,
+ TSET_T2,
+ TSET_T3,
+ TSET_T4,
+};
+
+/* JEITA temperature range */
enum TPS_TEMPERATURE_RANGE {
RANGE_T01,
RANGE_T12, /* low charging temperature range */
@@ -155,6 +164,22 @@ void pmu_irq_handler(enum gpio_signal signal);
int pmu_get_ac(void);
/**
+ * Set temperature threshold
+ *
+ * @param temp_n TSET_T1 to TSET_T4
+ * @param value 0b000 ~ 0b111, temperature threshold
+ */
+int pmu_set_temp_threshold(enum TPS_TEMPERATURE temp_n, uint8_t value);
+
+/**
+ * Force charger into error state, turn off charging and blinks charging LED
+ *
+ * @param enable true to turn off charging and blink LED
+ * @return EC_SUCCESS if ok
+ */
+int pmu_blink_led(int enable);
+
+/**
* * Initialize pmu
* */
void pmu_init(void);