summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);