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
This commit is contained in:
Louis Yung-Chieh Lo
2013-11-21 16:35:12 -08:00
committed by chrome-internal-fetch
parent 06e6073491
commit 90d83d2a67
3 changed files with 47 additions and 22 deletions

View File

@@ -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);

View File

@@ -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
};

View File

@@ -45,6 +45,19 @@
/* Long power key press to force shutdown */
#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()))