mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
skylake: Add support for asserting RTCRST if power sequencing fails
In order to pulse RTC reset to the PCH when power sequencing exit fails we need to watch for SLP_S4 to deassert and if it does not then assert RTCRST using a board specific method. This is attempted up to 5 times before giving up and staying in G3. On skylake the RSMRST passthru needs to be honored when the task is woken up, so while waiting call handle_rsmrst() if woken up early. This is needed because it is RSMRST that actually tells the PCH to try and wake. This is all wrapped in a config option and board specific method because not all boards have a GPIO to control RTCRST and if they do they may not all use the same method to assert it. BUG=chrome-os-partner:49564 BRANCH=glados TEST=manually tested on chell EVT: First, ensure board sequences properly if everything is OK for a normal boot. Next, modify handle_rsmrst() to not pass through the signal in order to simulate being stuck in S5, and ensure that the EC attempts to assert RTCRST and power up again 5 times before giving up and staying in G3. Change-Id: Ia3c13069c92762b51beb682a19e5a074194a3c26 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/322724 Reviewed-by: Shawn N <shawnn@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
ebd29d4557
commit
bbe2d886dc
@@ -257,6 +257,9 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* EC has GPIOs to allow board to reset RTC */
|
||||
#undef CONFIG_BOARD_HAS_RTC_RESET
|
||||
|
||||
/*
|
||||
* Call board_config_post_gpio_init() after GPIOs are initialized. See
|
||||
* include/board_config.h for more information.
|
||||
|
||||
101
power/skylake.c
101
power/skylake.c
@@ -130,6 +130,69 @@ enum power_state power_chipset_init(void)
|
||||
return POWER_G3;
|
||||
}
|
||||
|
||||
static void handle_rsmrst(enum power_state state)
|
||||
{
|
||||
/*
|
||||
* Pass through RSMRST asynchronously, as PCH may not react
|
||||
* immediately to power changes.
|
||||
*/
|
||||
int rsmrst_in = gpio_get_level(GPIO_RSMRST_L_PGOOD);
|
||||
int rsmrst_out = gpio_get_level(GPIO_PCH_RSMRST_L);
|
||||
|
||||
/* Nothing to do. */
|
||||
if (rsmrst_in == rsmrst_out)
|
||||
return;
|
||||
/*
|
||||
* Wait at least 10ms between power signals going high
|
||||
* and deasserting RSMRST to PCH.
|
||||
*/
|
||||
if (rsmrst_in)
|
||||
msleep(10);
|
||||
gpio_set_level(GPIO_PCH_RSMRST_L, rsmrst_in);
|
||||
CPRINTS("RSMRST: %d", rsmrst_in);
|
||||
}
|
||||
|
||||
static void handle_slp_sus(enum power_state state)
|
||||
{
|
||||
/* If we're down or going down don't do anythin with SLP_SUS_L. */
|
||||
if (state == POWER_G3 || state == POWER_S5G3)
|
||||
return;
|
||||
|
||||
/* Always mimic PCH SLP_SUS request for all other states. */
|
||||
gpio_set_level(GPIO_PMIC_SLP_SUS_L, gpio_get_level(GPIO_PCH_SLP_SUS_L));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_HAS_RTC_RESET
|
||||
static enum power_state power_wait_s5_rtc_reset(void)
|
||||
{
|
||||
static int s5_exit_tries;
|
||||
|
||||
/* Wait for S5 exit and then attempt RTC reset */
|
||||
while ((power_get_signals() & IN_PCH_SLP_S4_DEASSERTED) == 0) {
|
||||
/* Handle RSMRST passthru event while waiting */
|
||||
handle_rsmrst(POWER_S5);
|
||||
if (task_wait_event(SECOND*4) == TASK_EVENT_TIMER) {
|
||||
CPRINTS("timeout waiting for S5 exit");
|
||||
chipset_force_g3();
|
||||
|
||||
/* Assert RTCRST# and retry 5 times */
|
||||
board_rtc_reset();
|
||||
|
||||
if (++s5_exit_tries > 4) {
|
||||
s5_exit_tries = 0;
|
||||
return POWER_G3; /* Stay off */
|
||||
}
|
||||
|
||||
udelay(10 * MSEC);
|
||||
return POWER_G3S5; /* Power up again */
|
||||
}
|
||||
}
|
||||
|
||||
s5_exit_tries = 0;
|
||||
return POWER_S5S3; /* Power up to next state */
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum power_state _power_handle_state(enum power_state state)
|
||||
{
|
||||
int tries = 0;
|
||||
@@ -143,8 +206,14 @@ static enum power_state _power_handle_state(enum power_state state)
|
||||
power_button_pch_release();
|
||||
forcing_shutdown = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_HAS_RTC_RESET
|
||||
/* Wait for S5 exit and attempt RTC reset it supported */
|
||||
return power_wait_s5_rtc_reset();
|
||||
#else
|
||||
if (gpio_get_level(GPIO_PCH_SLP_S4_L) == 1)
|
||||
return POWER_S5S3; /* Power up to next state */
|
||||
#endif
|
||||
break;
|
||||
|
||||
case POWER_S3:
|
||||
@@ -325,38 +394,6 @@ static enum power_state _power_handle_state(enum power_state state)
|
||||
return state;
|
||||
}
|
||||
|
||||
static void handle_rsmrst(enum power_state state)
|
||||
{
|
||||
/*
|
||||
* Pass through RSMRST asynchronously, as PCH may not react
|
||||
* immediately to power changes.
|
||||
*/
|
||||
int rsmrst_in = gpio_get_level(GPIO_RSMRST_L_PGOOD);
|
||||
int rsmrst_out = gpio_get_level(GPIO_PCH_RSMRST_L);
|
||||
|
||||
/* Nothing to do. */
|
||||
if (rsmrst_in == rsmrst_out)
|
||||
return;
|
||||
/*
|
||||
* Wait at least 10ms between power signals going high
|
||||
* and deasserting RSMRST to PCH.
|
||||
*/
|
||||
if (rsmrst_in)
|
||||
msleep(10);
|
||||
gpio_set_level(GPIO_PCH_RSMRST_L, rsmrst_in);
|
||||
CPRINTS("RSMRST: %d", rsmrst_in);
|
||||
}
|
||||
|
||||
static void handle_slp_sus(enum power_state state)
|
||||
{
|
||||
/* If we're down or going down don't do anythin with SLP_SUS_L. */
|
||||
if (state == POWER_G3 || state == POWER_S5G3)
|
||||
return;
|
||||
|
||||
/* Always mimic PCH SLP_SUS request for all other states. */
|
||||
gpio_set_level(GPIO_PMIC_SLP_SUS_L, gpio_get_level(GPIO_PCH_SLP_SUS_L));
|
||||
}
|
||||
|
||||
enum power_state power_handle_state(enum power_state state)
|
||||
{
|
||||
enum power_state new_state;
|
||||
|
||||
Reference in New Issue
Block a user