summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-04-04 09:17:15 -0700
committerChromeBot <chrome-bot@google.com>2013-04-05 11:28:51 -0700
commit765c50ef5fc77aec2ef0abca7a76f000b4167d57 (patch)
tree1e6829625db6a36432484600f90c1f33d7ec0fa6
parent0d1c48ea7c4dd25a718f63ce3cbcee8ee0fa026a (diff)
downloadchrome-ec-765c50ef5fc77aec2ef0abca7a76f000b4167d57.tar.gz
Move board hard reset code into tpschrome driver
Hard reset is done by shorting 3.3V to ground. This is only really necessary to work around the PMU's I2C engine getting into a weird / uncommunicative state. This should not make any functional changes; the code is behaving the same way it did before. BUG=chrome-os-partner:18343 BRANCH=none TEST=build daisy, snow, spring Change-Id: I0edbdfc11bd5f6643075ffc83f4df3e11fc14675 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/47199
-rw-r--r--board/snow/board.c18
-rw-r--r--board/snow/board.h1
-rw-r--r--board/spring/board.c18
-rw-r--r--board/spring/board.h7
-rw-r--r--common/gaia_power.c10
-rw-r--r--common/pmu_tps65090.c81
-rw-r--r--include/pmu_tpschrome.h7
7 files changed, 70 insertions, 72 deletions
diff --git a/board/snow/board.c b/board/snow/board.c
index e7fdd50e37..a7840105cc 100644
--- a/board/snow/board.c
+++ b/board/snow/board.c
@@ -26,8 +26,6 @@
#define INT_BOTH_FLOATING (GPIO_INPUT | GPIO_INT_BOTH)
#define INT_BOTH_PULL_UP (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH)
-#define HARD_RESET_TIMEOUT_MS 5
-
/* GPIO signal list. Must match order from enum gpio_signal. */
const struct gpio_info gpio_list[GPIO_COUNT] = {
/* Inputs with interrupt handlers are first for efficiency */
@@ -222,22 +220,6 @@ static void board_shutdown_hook(void)
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_shutdown_hook, HOOK_PRIO_DEFAULT);
-/*
- * 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);
-
- /* Delay while the power is cut */
- udelay(HARD_RESET_TIMEOUT_MS * 1000);
-
- /* Shouldn't get here unless the board doesn't have this capability */
- panic_puts("Hard reset failed! (this board may not be capable)\n");
-}
-
#ifdef CONFIG_PMU_BOARD_INIT
int pmu_board_init(void)
{
diff --git a/board/snow/board.h b/board/snow/board.h
index 7bedbe28e0..c9ab61d305 100644
--- a/board/snow/board.h
+++ b/board/snow/board.h
@@ -32,6 +32,7 @@
#define CONFIG_KEYBOARD_PROTOCOL_MKBP
#define CONFIG_KEYBOARD_SUPPRESS_NOISE
#define CONFIG_PMU_BOARD_INIT
+#define CONFIG_PMU_HARD_RESET
#define CONFIG_PMU_TPS65090
#define CONFIG_SMART_BATTERY
#undef CONFIG_TASK_PROFILING
diff --git a/board/spring/board.c b/board/spring/board.c
index 2eb324929d..e40e3c1e3a 100644
--- a/board/spring/board.c
+++ b/board/spring/board.c
@@ -27,8 +27,6 @@
#define INT_BOTH_FLOATING (GPIO_INPUT | GPIO_INT_BOTH)
#define INT_BOTH_PULL_UP (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH)
-#define HARD_RESET_TIMEOUT_MS 5
-
void usb_charge_interrupt(enum gpio_signal signal);
/* GPIO signal list. Must match order from enum gpio_signal. */
@@ -201,22 +199,6 @@ static void board_shutdown_hook(void)
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_shutdown_hook, HOOK_PRIO_DEFAULT);
-/*
- * 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);
-
- /* Delay while the power is cut */
- udelay(HARD_RESET_TIMEOUT_MS * 1000);
-
- /* Shouldn't get here unless the board doesn't have this capability */
- panic_puts("Hard reset failed! (this board may not be capable)\n");
-}
-
#ifdef CONFIG_PMU_BOARD_INIT
int pmu_board_init(void)
{
diff --git a/board/spring/board.h b/board/spring/board.h
index 32b3612d24..36775dd6fd 100644
--- a/board/spring/board.h
+++ b/board/spring/board.h
@@ -15,17 +15,18 @@
#define CONFIG_CONSOLE_UART 1
/* Debug features */
-#define CONFIG_PANIC_HELP
#define CONFIG_ASSERT_HELP
#define CONFIG_CONSOLE_CMDHELP
+#define CONFIG_PANIC_HELP
+#undef CONFIG_TASK_PROFILING
+#define CONFIG_WATCHDOG_HELP
/* Optional features */
#define CONFIG_CHIPSET_GAIA
#define CONFIG_HOST_COMMAND_STATUS
#define CONFIG_I2C
#define CONFIG_KEYBOARD_PROTOCOL_MKBP
-#undef CONFIG_TASK_PROFILING
-#define CONFIG_WATCHDOG_HELP
+#define CONFIG_PMU_HARD_RESET
/* use STOP mode when we have nothing to do */
#define CONFIG_LOW_POWER_IDLE
diff --git a/common/gaia_power.c b/common/gaia_power.c
index 7f95922deb..a709ddc8fd 100644
--- a/common/gaia_power.c
+++ b/common/gaia_power.c
@@ -457,8 +457,6 @@ static int react_to_xpshold(unsigned int timeout_us)
*/
static void power_off(void)
{
- int pmu_shutdown_retries = 3;
-
/* Call hooks before we drop power rails */
hook_notify(HOOK_CHIPSET_SHUTDOWN);
/* switch off all rails */
@@ -471,13 +469,7 @@ static void power_off(void)
lid_changed = 0;
enable_sleep(SLEEP_MASK_AP_RUN);
powerled_set_state(POWERLED_STATE_OFF);
-
- while (--pmu_shutdown_retries >= 0) {
- if (!pmu_shutdown())
- break;
- }
- if (pmu_shutdown_retries < 0)
- board_hard_reset();
+ pmu_shutdown();
CPUTS("Shutdown complete.\n");
}
diff --git a/common/pmu_tps65090.c b/common/pmu_tps65090.c
index d35644aca6..36ec5e4aea 100644
--- a/common/pmu_tps65090.c
+++ b/common/pmu_tps65090.c
@@ -91,12 +91,7 @@
#define AD_CTRL_ADEOC (1 << 5)
#define AD_CTRL_ADSTART (1 << 6)
-void __board_hard_reset(void)
-{
- CPRINTF("This board is not capable of a hard reset.\n");
-}
-void board_hard_reset(void)
- __attribute__((weak, alias("__board_hard_reset")));
+#define HARD_RESET_TIMEOUT_MS 5
/* Charger temperature threshold table */
static const uint8_t const pmu_temp_threshold[] = {
@@ -106,6 +101,33 @@ static const uint8_t const pmu_temp_threshold[] = {
7, /* 0b111, 60 degree C */
};
+#ifdef CONFIG_PMU_HARD_RESET
+/**
+ * Force the pmic to reset completely.
+ *
+ * This forces an entire system reset, and therefore should never return. The
+ * implementation is rather hacky; it simply shorts out the 3.3V rail to force
+ * the PMIC to panic. We need this unfortunate hack because it's the only way
+ * to reset the I2C engine inside the PMU.
+ */
+static void pmu_hard_reset(void)
+{
+ /* Short out the 3.3V rail to force a hard reset of tps Chrome */
+ gpio_set_level(GPIO_PMIC_RESET, 1);
+
+ /* Delay while the power is cut */
+ udelay(HARD_RESET_TIMEOUT_MS * 1000);
+
+ /* Shouldn't get here unless the board doesn't have this capability */
+ panic_puts("pmu hard reset failed! (this board may not be capable)\n");
+}
+#else
+static void pmu_hard_reset(void)
+{
+ panic_puts("pmu hard reset unsupported!\n");
+}
+#endif
+
/* Read all tps65090 interrupt events */
static int pmu_get_event(int *event)
{
@@ -462,25 +484,48 @@ void pmu_irq_handler(enum gpio_signal signal)
CPRINTF("Charger IRQ received.\n");
}
-int pmu_shutdown(void)
+/**
+ * Attempt shutdown.
+ */
+static int pmu_try_shutdown(void)
{
- int offset, failure = 0;
+ int offset;
/* Disable each of the DCDCs */
for (offset = DCDC1_CTRL; offset <= DCDC3_CTRL; offset++) {
- if (!failure)
- failure = pmu_write(offset, 0x0e);
+ if (pmu_write(offset, 0x0e))
+ return EC_ERROR_UNKNOWN;
}
/* Disable each of the FETs */
for (offset = FET1_CTRL; offset <= FET7_CTRL; offset++) {
- if (!failure)
- failure = pmu_write(offset, 0x02);
+ if (pmu_write(offset, 0x02))
+ return EC_ERROR_UNKNOWN;
}
- /* Clearing AD controls/status */
- if (!failure)
- failure = pmu_write(AD_CTRL, 0x00);
- return failure ? EC_ERROR_UNKNOWN : EC_SUCCESS;
+ /* Clear AD controls/status */
+ if (pmu_write(AD_CTRL, 0x00))
+ return EC_ERROR_UNKNOWN;
+
+ return EC_SUCCESS;
+}
+
+int pmu_shutdown(void)
+{
+ int pmu_shutdown_retries = 3;
+
+ /* Attempt shutdown */
+ while (--pmu_shutdown_retries >= 0) {
+ if (!pmu_try_shutdown())
+ return EC_SUCCESS;
+ }
+
+#ifdef CONFIG_PMU_HARD_RESET
+ /* We ran out of tries, so reset the board */
+ pmu_hard_reset();
+#endif
+
+ /* If we're still here, we couldn't shutdown OR reset */
+ return EC_ERROR_UNKNOWN;
}
/*
@@ -579,7 +624,7 @@ void pmu_init(void)
}
if (failure)
- board_hard_reset();
+ pmu_hard_reset();
}
/* Initializes PMU when power is turned on. This is necessary because the TPS'
@@ -625,7 +670,7 @@ static int command_pmu(int argc, char **argv)
repeat = strtoi(argv[1], &e, 0);
if (*e) {
if (strlen(argv[1]) >= 1 && argv[1][0] == 'r') {
- board_hard_reset();
+ pmu_hard_reset();
/* If this returns, there was an error */
return EC_ERROR_UNKNOWN;
}
diff --git a/include/pmu_tpschrome.h b/include/pmu_tpschrome.h
index ca7a192d7a..97f2b6fb09 100644
--- a/include/pmu_tpschrome.h
+++ b/include/pmu_tpschrome.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
@@ -244,11 +244,6 @@ int pmu_enable_ext_control(int enable);
int pmu_set_fastcharge(enum FASTCHARGE_TIMEOUT timeout);
/**
- * Reset the entire board if it is capable
- */
-void board_hard_reset(void);
-
-/**
* Wake TPS65090 charger task, but throttled to at most one call per tick
*/
void pmu_task_throttled_wake(void);