From 0564d05b56c993b219707182e5b2c2306234ac7d Mon Sep 17 00:00:00 2001 From: Peter Marheine Date: Tue, 5 May 2020 11:51:33 +1000 Subject: cometlake-discrete: create a S0->S3 fast path Latency for powering off VCCIO needs to be lower than we can reliably achieve using the regular state machine. Add a fast path via a specialized interrupt to do the S0->S3 transition that should have lower latency (low enough to satisfy the relevant timing requirements). BRANCH=None BUG=b:155672968 TEST=Verified shutdown_s0_rails() runs on S3 interrupt with low latency, measured timing is now in spec. Signed-off-by: Peter Marheine Change-Id: I2753d3490bbefc8f6fccba6cc90e808c969e53b1 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2182109 Reviewed-by: Andrew McRae --- power/cometlake-discrete.c | 28 +++++++++++++++++++++++++++- power/cometlake-discrete.h | 13 +++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'power') diff --git a/power/cometlake-discrete.c b/power/cometlake-discrete.c index 5465920334..56465ef61f 100644 --- a/power/cometlake-discrete.c +++ b/power/cometlake-discrete.c @@ -159,6 +159,9 @@ BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); * * This is a separate function so it can be reused when forcing shutdown due to * power failure or other reasons. + * + * This function may be called from an ISR (slp_s3_interrupt) so must not + * assume that it's running in a regular task. */ static void shutdown_s0_rails(void) { @@ -172,7 +175,15 @@ static void shutdown_s0_rails(void) gpio_set_level(GPIO_EC_PCH_SYS_PWROK, 0); gpio_set_level(GPIO_EN_IMVP8_VR, 0); gpio_set_level(GPIO_EN_S0_RAILS, 0); - usleep(1); /* tPCH10: PCH_PWROK to VCCIO off >400 ns */ + /* + * * tPCH10: PCH_PWROK to VCCIO off >400ns (but only on unexpected + * power-down) + * * tPLT18: SLP_S3_L to VCCIO disable <200us + * + * tPCH10 is only 7 CPU cycles at 16 MHz so we should satisfy that + * minimum time with no extra code, and sleeping is likely to cause + * a delay that exceeds tPLT18. + */ gpio_set_level(GPIO_EN_PP950_VCCIO, 0); } @@ -331,6 +342,10 @@ enum power_state power_handle_state(enum power_state state) break; case POWER_S0S3: + /* + * Handled in the slp_s3_interrupt fast path, but also run + * here in case we miss the interrupt somehow. + */ shutdown_s0_rails(); break; @@ -388,3 +403,14 @@ void c10_gate_interrupt(enum gpio_signal signal) return power_signal_interrupt(signal); } + +void slp_s3_interrupt(enum gpio_signal signal) +{ + if (!gpio_get_level(GPIO_SLP_S3_L) + && chipset_in_state(CHIPSET_STATE_ON)) { + /* Falling edge on SLP_S3_L means dropping to S3 from S0 */ + shutdown_s0_rails(); + } + + return power_signal_interrupt(signal); +} diff --git a/power/cometlake-discrete.h b/power/cometlake-discrete.h index e69deb195c..6f5370beee 100644 --- a/power/cometlake-discrete.h +++ b/power/cometlake-discrete.h @@ -101,6 +101,9 @@ enum power_signal { * Board-specific enable for any additional rails in S0. * * Input 0 to turn off, 1 to turn on. + * + * This function may be called from interrupts so must not assume it's running + * in a task. */ void board_enable_s0_rails(int enable); @@ -134,4 +137,14 @@ int board_is_c10_gate_enabled(void); */ void c10_gate_interrupt(enum gpio_signal signal); +/* + * Special interrupt for SLP_S3_L handling. + * + * The time window in which to turn off some rails when dropping to S3 is + * ~200us, and using the regular power state machine path tends to have latency + * >1ms. This ISR short-circuits the relevant signals in a fast path before + * scheduling a state machine update to ensure sufficiently low latency. + */ +void slp_s3_interrupt(enum gpio_signal signal); + #endif /* __CROS_EC_COMETLAKE_DISCRETE_H */ -- cgit v1.2.1