Clean up EC hibernate logic

system_hibernate(0, 0) now hibernates until a wake pin assert, with no
RTC wake.

BUG=none
TEST=manual

command -> expected reset flags from 'sysinfo'
1. reboot -> soft
2. reboot hard -> power-on hard
3. hibernate (and press power button) -> power-on wake-pin
4. hibernate 3 (and wait for timeout) -> power-on rtc-alarm
5. hibernate 10 (and press power button before 10 sec) -> power-on wake-pin

hibdelay 10
then shut system down and run on battery
10 sec later, system should hibernate.

Change-Id: I399413d265f6fcf808adf9ed1db7b812a1b12fc2
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/29923
Reviewed-by: Vic Yang <victoryang@chromium.org>
This commit is contained in:
Randall Spangler
2012-08-10 13:15:15 -07:00
committed by Gerrit
parent 397a7aa336
commit 521e97fd13
4 changed files with 45 additions and 26 deletions

View File

@@ -210,13 +210,26 @@ void system_set_rtc(uint32_t seconds)
*
* @param seconds Number of seconds to sleep before RTC alarm
* @param microseconds Number of microseconds to sleep before RTC alarm
* @param flags Hibernate wake flags
* @param flags Additional hibernate wake flags
*/
static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags)
{
uint32_t rtc, rtcss;
uint32_t hibctl;
/* Set up wake reasons and hibernate flags */
hibctl = LM4_HIBERNATE_HIBCTL | LM4_HIBCTL_PINWEN;
flags |= HIBDATA_WAKE_PIN;
if (seconds || microseconds) {
hibctl |= LM4_HIBCTL_RTCWEN;
flags |= HIBDATA_WAKE_RTC;
} else {
hibctl &= ~LM4_HIBCTL_RTCWEN;
}
wait_for_hibctl_wc();
LM4_HIBERNATE_HIBCTL = hibctl;
/* Store hibernate flags */
hibdata_write(HIBDATA_INDEX_WAKE, flags);
@@ -224,10 +237,6 @@ static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags)
wait_for_hibctl_wc();
LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS;
/* TODO: PRESERVE RESET FLAGS */
/* TODO: If sleeping forever, only wake on wake pin. */
/* Add expected overhead for hibernate register writes */
microseconds += HIB_WAIT_USEC * 4;
@@ -254,17 +263,15 @@ static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags)
wait_for_hibctl_wc();
LM4_HIBERNATE_HIBRTCSS = rtcss << 16;
/* Go to hibernation and wake on RTC match or WAKE pin */
hibctl = (LM4_HIBERNATE_HIBCTL | LM4_HIBCTL_RTCWEN |
LM4_HIBCTL_PINWEN | LM4_HIBCTL_HIBREQ);
wait_for_hibctl_wc();
__enter_hibernate(hibctl);
__enter_hibernate(hibctl | LM4_HIBCTL_HIBREQ);
}
void system_hibernate(uint32_t seconds, uint32_t microseconds)
{
hibernate(seconds, microseconds, HIBDATA_WAKE_RTC | HIBDATA_WAKE_PIN);
/* Flush console before hibernating */
cflush();
hibernate(seconds, microseconds, 0);
}
int system_pre_init(void)

View File

@@ -607,24 +607,25 @@ DECLARE_CONSOLE_COMMAND(scratchpad, command_scratchpad,
static int command_hibernate(int argc, char **argv)
{
int seconds;
int seconds = 0;
int microseconds = 0;
if (argc < 2)
return EC_ERROR_PARAM_COUNT;
seconds = strtoi(argv[1], NULL, 0);
if (argc >= 2)
seconds = strtoi(argv[1], NULL, 0);
if (argc >= 3)
microseconds = strtoi(argv[2], NULL, 0);
ccprintf("Hibernating for %d.%06d s\n", seconds, microseconds);
cflush();
if (seconds || microseconds)
ccprintf("Hibernating for %d.%06d s\n", seconds, microseconds);
else
ccprintf("Hibernating until wake pin asserted.\n");
system_hibernate(seconds, microseconds);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(hibernate, command_hibernate,
"sec [usec]",
"[sec] [usec]",
"Hibernate the EC",
NULL);

View File

@@ -444,9 +444,10 @@ void x86_power_task(void)
hibernate_delay * 1000000ull;
time_now = get_time().val;
if (time_now > target_time) {
/* Time's up. Hibernate as long as
* possible. */
system_hibernate(0xffffffff, 0);
/* Time's up. Hibernate until wake pin
* asserted. */
CPRINTF("[%T x86 hibernating]\n");
system_hibernate(0, 0);
}
else {
/* Wait for a message */

View File

@@ -169,11 +169,21 @@ const char *system_get_chip_vendor(void);
const char *system_get_chip_name(void);
const char *system_get_chip_revision(void);
/* TODO: request sleep. How do we want to handle transitioning
* to/from low-power states? */
/* Put the EC in hibernate (lowest EC power state) for the specified
* duration. Note that this is NOT the same as chipset S4/hibernate. */
/**
* Put the EC in hibernate (lowest EC power state).
*
* @param seconds Number of seconds to hibernate.
* @param microseconds Number of microseconds to hibernate.
*
* The EC will hibernate until the wake pin is asserted. If seconds and/or
* microseconds is non-zero, the EC will also automatically wake after that
* period. If both are zero, the EC will only wake on a wake pin assert. Very
* short hibernation delays do not work well; if non-zero, the delays must be
* at least SYSTEM_HIB_MINIMUM_DURATION.
*
* Note although the name is similar, EC hibernate is NOT the same as chipset
* S4/hibernate.
*/
void system_hibernate(uint32_t seconds, uint32_t microseconds);
/* Minimum duration to get proper hibernation */