diff options
author | Rong Chang <rongchang@chromium.org> | 2012-08-23 04:03:43 +0800 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-08-23 13:47:30 -0700 |
commit | 40cab432565239e6228082f6c59ad0cacb6cfe2f (patch) | |
tree | 97fc4b03e56af689fa502cdb6d892d47270526c7 | |
parent | 89be1be31a32d3c0517af27e248b28db57cdac39 (diff) | |
download | chrome-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.c | 69 | ||||
-rw-r--r-- | common/pmu_tps65090_charger.c | 74 | ||||
-rw-r--r-- | include/pmu_tpschrome.h | 25 |
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, ®_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); |