summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/gaia_power.c2
-rw-r--r--common/pmu_tps65090.c69
-rw-r--r--include/pmu_tpschrome.h6
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 */