mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 02:35:28 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user