summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorCharlie Mooney <charliemooney@chromium.org>2012-08-27 14:12:39 -0700
committerGerrit <chrome-bot@google.com>2012-08-28 12:09:19 -0700
commitbb3bb9262893453ac6a57d5ee02abd73540cf705 (patch)
treeb4c7fa1c0d78d0a5e887b83a99d02987aac8d305 /board
parent619032a77c171ff11251648a4af61fb0578dd097 (diff)
downloadchrome-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.c60
-rw-r--r--board/snow/board.h6
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__ */