diff options
-rw-r--r-- | common/gaia_power.c | 2 | ||||
-rw-r--r-- | common/pmu_tps65090.c | 69 | ||||
-rw-r--r-- | include/pmu_tpschrome.h | 6 |
3 files changed, 77 insertions, 0 deletions
diff --git a/common/gaia_power.c b/common/gaia_power.c index aae1bd35b7..88936d18fb 100644 --- a/common/gaia_power.c +++ b/common/gaia_power.c @@ -31,6 +31,7 @@ #include "hooks.h" #include "keyboard_scan.h" #include "power_led.h" +#include "pmu_tpschrome.h" #include "system.h" #include "task.h" #include "timer.h" @@ -446,6 +447,7 @@ static void power_off(void) lid_changed = 0; enable_sleep(SLEEP_MASK_AP_RUN); powerled_set_state(POWERLED_STATE_OFF); + pmu_shutdown(); CPUTS("Shutdown complete.\n"); } diff --git a/common/pmu_tps65090.c b/common/pmu_tps65090.c index d9b72ec765..d26b855756 100644 --- a/common/pmu_tps65090.c +++ b/common/pmu_tps65090.c @@ -33,6 +33,19 @@ #define CG_CTRL5 0x09 #define CG_STATUS1 0x0a #define CG_STATUS2 0x0b +#define DCDC1_CTRL 0x0c +#define DCDC2_CTRL 0x0d +#define DCDC3_CTRL 0x0e +#define FET1_CTRL 0x0f +#define FET2_CTRL 0x10 +#define FET3_CTRL 0x11 +#define FET4_CTRL 0x12 +#define FET5_CTRL 0x13 +#define FET6_CTRL 0x14 +#define FET7_CTRL 0x15 +#define AD_CTRL 0x16 +#define AD_OUT1 0x17 +#define AD_OUT2 0x18 #define TPSCHROME_VER 0x19 /* Charger control */ @@ -334,8 +347,64 @@ int pmu_get_ac(void) return ac_good; } +int pmu_shutdown(void) +{ + int offset, rv = 0; + + /* Disable each of the DCDCs */ + for (offset = DCDC1_CTRL; offset <= DCDC3_CTRL; offset++) + rv |= pmu_write(offset, 0x0e); + /* Disable each of the FETs */ + for (offset = FET1_CTRL; offset <= FET7_CTRL; offset++) + rv |= pmu_write(offset, 0x02); + /* Clearing AD controls/status */ + rv |= pmu_write(AD_CTRL, 0x00); + + return rv ? EC_ERROR_UNKNOWN : EC_SUCCESS; +} + +/* + * Fill all of the pmu registers with known good values, this allows the + * pmu to recover by rebooting the system if its registers were trashed. + */ +static void pmu_init_registers(void) +{ + const struct { + uint8_t index; + uint8_t value; + } reg[] = { + {IRQ1MASK, 0x00}, + {IRQ2MASK, 0x00}, + {CG_CTRL0, 0x02}, + {CG_CTRL1, 0x20}, + {CG_CTRL2, 0x4b}, + {CG_CTRL3, 0xbf}, + {CG_CTRL4, 0xf3}, + {CG_CTRL5, 0xc0}, + {DCDC1_CTRL, 0x0e}, + {DCDC2_CTRL, 0x0e}, + {DCDC3_CTRL, 0x0e}, + {FET1_CTRL, 0x02}, + {FET2_CTRL, 0x02}, + {FET3_CTRL, 0x02}, + {FET4_CTRL, 0x02}, + {FET5_CTRL, 0x02}, + {FET6_CTRL, 0x02}, + {FET7_CTRL, 0x02}, + {AD_CTRL, 0x00}, + {IRQ1_REG, 0x00} + }; + + uint8_t i; + for (i = 0; i < ARRAY_SIZE(reg); i++) + pmu_write(reg[i].index, reg[i].value); +} + void pmu_init(void) { + /* Reset everything to default, safe values */ + pmu_init_registers(); + #ifdef CONFIG_PMU_BOARD_INIT board_pmu_init(); #else diff --git a/include/pmu_tpschrome.h b/include/pmu_tpschrome.h index 57fb84a4a4..5d65b73b45 100644 --- a/include/pmu_tpschrome.h +++ b/include/pmu_tpschrome.h @@ -184,5 +184,11 @@ int pmu_blink_led(int enable); * */ void pmu_init(void); +/** + * Shut down the pmu, by resetting it's registers to disable it's FETs, + * DCDCs and ADC. + */ +int pmu_shutdown(void); + #endif /* __CROS_EC_TPSCHROME_H */ |