diff options
author | Charlie Mooney <charliemooney@chromium.org> | 2012-08-27 14:12:39 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-08-28 12:09:19 -0700 |
commit | bb3bb9262893453ac6a57d5ee02abd73540cf705 (patch) | |
tree | b4c7fa1c0d78d0a5e887b83a99d02987aac8d305 /board | |
parent | 619032a77c171ff11251648a4af61fb0578dd097 (diff) | |
download | chrome-ec-bb3bb9262893453ac6a57d5ee02abd73540cf705.tar.gz |
Snow: Adding in EC ability to hard reset pmic
By pulling line gio_A15 high, you can for a hard reset of the pmic after
the stuff resistor is changed. This change adds a function that you can
call from the EC and trigger this event (board_hard_reset). The user has
access to this command over the EC console by running "pmu reset" and
it will force the emergency reset.
The board_hard_reset function is used in the pmu's reset code. Whenever
it is trying to initialize or shut down the pmu, it resets many or all
of its registers over i2c. If the i2c commands fail to get a response
from the pmu, the EC will now force a hard reset of the system, which
restores everything, allowing for a restart to fix any situation where
the pmu has gotten its configuration trashed.
BUG=chrome-os-partner:12913
TEST=boot the machine. From EC console check the pmic's register
values, then alter them. Run "pmu reset" to force a reset, and check
the values again. They should be safe values, which you can confirm
by powering on the AP. Repeat this from various starting states: only
the EC on, AP on as well, and setting various registers to 0x00's and
0xff's. To stress test the hard-reset ability from the EC's POV, run
while true; do echo "pmu reset"; sleep 5; done | cu -l DEVICE -s 15200
BRANCH=snow
Change-Id: I911fb9623a7c106d1f993ee4681258c05d4dedae
Signed-off-by: Charlie Mooney <charliemooney@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/31524
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'board')
-rw-r--r-- | board/snow/board.c | 60 | ||||
-rw-r--r-- | board/snow/board.h | 6 |
2 files changed, 50 insertions, 16 deletions
diff --git a/board/snow/board.c b/board/snow/board.c index 55edbedd2d..672df1002b 100644 --- a/board/snow/board.c +++ b/board/snow/board.c @@ -68,6 +68,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"EN_PP5000", GPIO_A, (1<<11), GPIO_OUT_LOW, NULL}, {"EN_PP3300", GPIO_A, (1<<8), GPIO_OUT_LOW, NULL}, {"PMIC_PWRON_L",GPIO_A, (1<<12), GPIO_OUT_HIGH, NULL}, + {"PMIC_RESET", GPIO_A, (1<<15), GPIO_OUT_LOW, NULL}, {"ENTERING_RW", GPIO_D, (1<<0), GPIO_OUT_LOW, NULL}, {"CHARGER_EN", GPIO_B, (1<<2), GPIO_OUT_LOW, NULL}, {"EC_INT", GPIO_B, (1<<9), GPIO_HI_Z, NULL}, @@ -287,41 +288,63 @@ void board_i2c_release(int port) } #endif /* CONFIG_ARBITRATE_I2C */ +/* + * Force the pmic to reset completely. This forces an entire system reset, + * and therefore should never return + */ +void board_hard_reset(void) +{ + /* Force a hard reset of tps Chrome */ + gpio_set_level(GPIO_PMIC_RESET, 1); + /* Hang until the power is cut */ + while (1) + ; +} + #ifdef CONFIG_PMU_BOARD_INIT + /** * Initialize PMU register settings * * PMU init settings depend on board configuration. This function should be * called inside PMU init function. */ -void board_pmu_init(void) +int board_pmu_init(void) { - int ver; + int ver, failure = 0; /* Set fast charging timeout to 6 hours*/ - pmu_set_fastcharge(TIMEOUT_6HRS); + if (!failure) + failure = pmu_set_fastcharge(TIMEOUT_6HRS); /* Enable external gpio CHARGER_EN control */ - pmu_enable_ext_control(1); + if (!failure) + failure = pmu_enable_ext_control(1); /* Disable force charging */ - pmu_enable_charger(0); + if (!failure) + failure = pmu_enable_charger(0); /* Set NOITERM bit */ - pmu_low_current_charging(1); + if (!failure) + failure = pmu_low_current_charging(1); /* * High temperature charging * termination voltage: 2.1V * termination current: 100% */ - pmu_set_term_voltage(RANGE_T34, TERM_V2100); - pmu_set_term_current(RANGE_T34, TERM_I1000); + if (!failure) + failure = pmu_set_term_voltage(RANGE_T34, TERM_V2100); + if (!failure) + failure = pmu_set_term_current(RANGE_T34, TERM_I1000); /* * Standard temperature charging * termination voltage: 2.1V * termination current: 100% */ - pmu_set_term_voltage(RANGE_T23, TERM_V2100); - pmu_set_term_current(RANGE_T23, TERM_I1000); + if (!failure) + failure = pmu_set_term_voltage(RANGE_T23, TERM_V2100); + if (!failure) + failure = pmu_set_term_current(RANGE_T23, TERM_I1000); /* * Ignore TPSCHROME NTC reading in T40. This is snow board specific @@ -329,15 +352,22 @@ void board_pmu_init(void) * http://crosbug.com/p/12221 * http://crosbug.com/p/13171 */ - pmu_set_term_voltage(RANGE_T40, TERM_V2100); - pmu_set_term_current(RANGE_T40, TERM_I1000); + if (!failure) + failure = pmu_set_term_voltage(RANGE_T40, TERM_V2100); + if (!failure) + failure = pmu_set_term_current(RANGE_T40, TERM_I1000); /* Workaround init values before ES3 */ if (pmu_version(&ver) || ver < 3) { /* Termination current: 75% */ - pmu_set_term_current(RANGE_T34, TERM_I0750); - pmu_set_term_current(RANGE_T23, TERM_I0750); - pmu_set_term_current(RANGE_T40, TERM_I0750); + if (!failure) + failure = pmu_set_term_current(RANGE_T34, TERM_I0750); + if (!failure) + failure = pmu_set_term_current(RANGE_T23, TERM_I0750); + if (!failure) + failure = pmu_set_term_current(RANGE_T40, TERM_I0750); } + + return failure ? EC_ERROR_UNKNOWN : EC_SUCCESS; } #endif /* CONFIG_BOARD_PMU_INIT */ diff --git a/board/snow/board.h b/board/snow/board.h index 27eb5d7c6d..79d56ecb5b 100644 --- a/board/snow/board.h +++ b/board/snow/board.h @@ -91,6 +91,7 @@ enum gpio_signal { GPIO_EN_PP5000, /* 5.0v rail enable */ GPIO_EN_PP3300, /* 3.3v rail enable */ GPIO_PMIC_PWRON_L, /* 5v rail ready */ + GPIO_PMIC_RESET, /* Force hard reset of the pmic */ GPIO_EC_ENTERING_RW, /* EC is R/W mode for the kbc mux */ GPIO_CHARGER_EN, GPIO_EC_INT, @@ -123,7 +124,10 @@ void matrix_interrupt(enum gpio_signal signal); void board_interrupt_host(int active); /* Initialize PMU registers using board settings */ -void board_pmu_init(void); +int board_pmu_init(void); + +/* Force the pmu to reset everything on the board */ +void board_hard_reset(void); #endif /* !__ASSEMBLER__ */ |