diff options
-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); |