summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2013-11-21 16:35:12 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-12-05 01:51:28 +0000
commit90d83d2a6743a48d7ec8209781c4e820e8bdf296 (patch)
treec17edb461b9ac54f63fff8fc13092b0ce170995f
parent06e60734910d952830c2102cd2ab002ddc99029b (diff)
downloadchrome-ec-90d83d2a6743a48d7ec8209781c4e820e8bdf296.tar.gz
nyan: force shutdown uses PMIC THERM instead.
Add a new pin PMIC_THERM_L (PA1) since AP_RESET_L (PA15) is removed. To force shutdown, drive PMIC_THERM_L to low (default high) for 32us. Also rename set_pmic_pwrok() -> set_pmic_pwron(). And add a debounce time for PMIC_PWRON_L pin. BUG=chrome-os-partner:24206 BRANCH=nyan TEST=Verified on the frank's rework board. 'power off' shutdowns the AP immediately. 'reboot' reboots the EC and resets the AP as well. 'sysjump RW' still keeps AP alive. Change-Id: I8643e19081a824e1f6adc812dfad0269222db8ea Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/178631
-rw-r--r--board/nyan/board.c1
-rw-r--r--board/nyan/board.h1
-rw-r--r--power/tegra.c67
3 files changed, 47 insertions, 22 deletions
diff --git a/board/nyan/board.c b/board/nyan/board.c
index ef30a130d5..29c35045fc 100644
--- a/board/nyan/board.c
+++ b/board/nyan/board.c
@@ -82,6 +82,7 @@ const struct gpio_info gpio_list[] = {
{"BAT_LED1", GPIO_A, (1<<8), GPIO_OUT_LOW, NULL},
{"CHARGING", GPIO_A, (1<<11), GPIO_OUT_LOW, NULL},
{"EC_BL_OVERRIDE", GPIO_H, (1<<1), GPIO_ODR_HIGH, NULL},
+ {"PMIC_THERM_L", GPIO_A, (1<<1), GPIO_ODR_HIGH, NULL},
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
diff --git a/board/nyan/board.h b/board/nyan/board.h
index 1b1c5aed48..57483b20d0 100644
--- a/board/nyan/board.h
+++ b/board/nyan/board.h
@@ -86,6 +86,7 @@ enum gpio_signal {
GPIO_BAT_LED1,
GPIO_CHARGING,
GPIO_EC_BL_OVERRIDE,
+ GPIO_PMIC_THERM_L,
/* Number of GPIOs; not an actual GPIO */
GPIO_COUNT
};
diff --git a/power/tegra.c b/power/tegra.c
index 99c350c658..9b44d39f56 100644
--- a/power/tegra.c
+++ b/power/tegra.c
@@ -46,6 +46,19 @@
#define DELAY_FORCE_SHUTDOWN (10200 * MSEC) /* 10.2 seconds */
/*
+ * The minimum time to assert the PMIC PWRON pin is 20ms.
+ * Give it longer to ensure the PMIC doesn't lose it.
+ */
+#define PMIC_PWRON_DEBOUNCE_TIME (20 * MSEC * 3)
+
+/*
+ * The minimum time to assert the PMIC THERM pin is 32us. However,
+ * it needs to be extended to about 50ms to let the 5V rail
+ * dissipate fully.
+ */
+#define PMIC_THERM_HOLD_TIME (50 * MSEC)
+
+/*
* If the power key is pressed to turn on, then held for this long, we
* power off.
*
@@ -132,27 +145,29 @@ static int wait_in_signal(enum gpio_signal signal, int value, int timeout)
}
/**
- * Set the PMIC PWROK signal.
+ * Set the PMIC PWRON signal.
+ *
+ * Note that asserting requires holding for PMIC_PWRON_DEBOUNCE_TIME.
*
* @param asserted Assert (=1) or deassert (=0) the signal. This is the
* logical level of the pin, not the physical level.
*/
-static void set_pmic_pwrok(int asserted)
+static void set_pmic_pwron(int asserted)
{
/* Signal is active-low */
gpio_set_level(GPIO_PMIC_PWRON_L, asserted ? 0 : 1);
}
/**
- * Set the AP RESET signal.
+ * Set the PMIC THERM to force shutdown the AP.
*
* @param asserted Assert (=1) or deassert (=0) the signal. This is the
* logical level of the pin, not the physical level.
*/
-static void set_ap_reset(int asserted)
+static void set_pmic_therm(int asserted)
{
/* Signal is active-low */
- gpio_set_level(GPIO_AP_RESET_L, asserted ? 0 : 1);
+ gpio_set_level(GPIO_PMIC_THERM_L, asserted ? 0 : 1);
}
/**
@@ -188,7 +203,8 @@ static int check_for_power_off_event(void)
now = get_time();
if (pressed) {
- set_pmic_pwrok(1);
+ set_pmic_pwron(1);
+ usleep(PMIC_PWRON_DEBOUNCE_TIME);
if (!power_button_was_pressed) {
power_off_deadline.val = now.val + DELAY_FORCE_SHUTDOWN;
@@ -202,7 +218,7 @@ static int check_for_power_off_event(void)
}
} else if (power_button_was_pressed) {
CPRINTF("[%T power off cancel]\n");
- set_pmic_pwrok(0);
+ set_pmic_pwron(0);
}
power_button_was_pressed = pressed;
@@ -283,6 +299,15 @@ static int tegra_power_init(void)
gpio_enable_interrupt(GPIO_SOC1V8_XPSHOLD);
gpio_enable_interrupt(GPIO_SUSPEND_L);
+ /*
+ * Force the AP shutdown unless we are doing SYSJUMP. Otherwise,
+ * the AP could stay in strange state.
+ */
+ if (!(system_get_reset_flags() & RESET_FLAG_SYSJUMP)) {
+ CPRINTF("[%T not sysjump; forcing AP shutdown]\n");
+ chipset_force_shutdown();
+ }
+
/* Leave power off only if requested by reset flags */
if (!(system_get_reset_flags() & RESET_FLAG_AP_OFF)) {
CPRINTF("[%T auto_power_on is set due to reset_flag 0x%x]\n",
@@ -341,11 +366,13 @@ void chipset_reset(int is_cold)
void chipset_force_shutdown(void)
{
- /* Assert AP reset to shutdown immediately */
- set_ap_reset(1);
-
/* Release the power button, if it was asserted */
- set_pmic_pwrok(0);
+ set_pmic_pwron(0);
+
+ /* Assert AP reset to shutdown immediately */
+ set_pmic_therm(1);
+ udelay(PMIC_THERM_HOLD_TIME);
+ set_pmic_therm(0);
}
/*****************************************************************************/
@@ -360,13 +387,8 @@ void chipset_force_shutdown(void)
*/
static int check_for_power_on_event(void)
{
- /*
- * check if system is already ON:
- * 1. XPSHOLD is high (power is supplied), and
- * 2. AP_RESET_L is high (not a force shutdown).
- */
- if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) &&
- gpio_get_level(GPIO_AP_RESET_L)) {
+ /* check if system is already ON */
+ if (gpio_get_level(GPIO_SOC1V8_XPSHOLD)) {
CPRINTF("[%T system is on, thus clear auto_power_on]\n");
auto_power_on = 0; /* no need to arrange another power on */
return 1;
@@ -406,11 +428,12 @@ static int check_for_power_on_event(void)
*/
static int power_on(void)
{
- /* Make sure we de-assert the AP_RESET_L pin. */
- set_ap_reset(0);
+ /* Make sure we de-assert the PMI_THERM_L pin. */
+ set_pmic_therm(0);
/* Push the power button */
- set_pmic_pwrok(1);
+ set_pmic_pwron(1);
+ usleep(PMIC_PWRON_DEBOUNCE_TIME);
/* Initialize non-AP components if the AP is off. */
if (!ap_on)
@@ -553,7 +576,7 @@ void chipset_task(void)
DELAY_SHUTDOWN_ON_POWER_HOLD))
continue_power = 1;
}
- set_pmic_pwrok(0);
+ set_pmic_pwron(0);
if (continue_power) {
power_button_was_pressed = 0;
while (!(value = check_for_power_off_event()))