diff options
author | Mary Ruthven <mruthven@chromium.org> | 2022-01-21 10:25:45 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-01-26 22:32:40 +0000 |
commit | 12d62b7996952bb8108af286e312481cecad02a1 (patch) | |
tree | 1f074644a12d7946714560e6d8d7aa58c3e206d2 /board | |
parent | a65cd8208381364b523f00baae1478c714512acf (diff) | |
download | chrome-ec-12d62b7996952bb8108af286e312481cecad02a1.tar.gz |
add vendor command to disable deep sleep
Add a vendor command to disable deep sleep the next time TPM_RST_L is
asserted. Normally cr50 enters deep sleep whenever TPM_RST_L is
asserted. New boards want to disable deep sleep during certain power
states. This vendor command allows the AP to disable deep sleep for the
next suspend cycle.
When deep sleep is disabled, cr50 modifies TPM_RST_L to be WAKE_HIGH and
sets it back to WAKE_LOW after TPM_RST_L is deasserted, so TPM_RST_L
doesn't constantly wake cr50 from regular sleep.
This uses 248 bytes
BUG=b:214479456
TEST=manual
# Check G3 resume works ok.
# Disable Deep Sleep from the AP. The vendor command is 59
# (0x3b)
trunks_send --raw 80010000000c20000000003b
ccdstate
DS Dis: on
AP > shutdown -P now
...
[454.992733 Block DS]
ccdstate
DS Dis: on
pinmux
40060018: DIOM3 0 IN WAKE_HIGH
idle
idle action: sleep
# Verify cr50 starts cycling through sleep spinner at two ticks
# a second.
EC > powerbtn
# check the cr50 console
...
Aï¿œUART on]
10/ 1 [102.484012 Missed edge]
[102.484352 deferred_tpm_rst_isr]
[102.484580 AP on]
[102.484779 set TPM wake]
[102.484981 tpm_reset_request(0, 0)]
[102.485279 tpm_reset_now(0)]
[547.928375 AP on]
[547.928615 set TPM wake]
pinmux
40060018: DIOM3 0 IN WAKE_LOW
# Disable Deep Sleep from the AP. The vendor command is 59
# (0x3b)
trunks_send --raw 80010000000c20000000003b
ccdstate
DS Dis: on
ecrst pulse
...
[602.638427 AP on]
[547.928615 set TPM wake]
[602.638668 tpm_reset_request(0, 0)]
...
ccdstate
DS Dis: off
# Check S3 resume works ok.
# Use AP commands to enter S3
AP > trunks_send --raw 80010000000c20000000003b
AP > echo deep > /sys/power/mem_sleep
AP > echo mem > /sys/power/state
10\ 1 [243.409412 dis DS]
1|[249.536811 tpm_rst_asserted]
[250.537197 AP off]
[250.537631 Block DS]
# Wake the AP with a power button press from the EC
EC > powerbtn
# verify cr50 prints "Missed edge", but the device resumes ok.
1/ 10- 1 [270.112655 Missed edge]
[270.113037 deferred_tpm_rst_isr]
[270.113315 AP on]
[270.113529 set TPM wake]
[270.113712 tpm_reset_request(0, 0)]
[270.114013 tpm_reset_now(0)]
[270.116996 tpm_init]
tpm_manufactured: manufactured
[270.118301 tpm_reset_now: done]
[270.156967 PinWeaver: Loading Tree!]
[270.189353 Skipping commit]
Change-Id: I96049a9d38b5c66acad9c73628f588f4cf6b2b3f
Signed-off-by: Mary Ruthven <mruthven@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3406587
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'board')
-rw-r--r-- | board/cr50/ap_state.c | 70 | ||||
-rw-r--r-- | board/cr50/board.c | 2 | ||||
-rw-r--r-- | board/cr50/board.h | 1 |
3 files changed, 72 insertions, 1 deletions
diff --git a/board/cr50/ap_state.c b/board/cr50/ap_state.c index 97b08acbb3..79506b2a2e 100644 --- a/board/cr50/ap_state.c +++ b/board/cr50/ap_state.c @@ -6,6 +6,7 @@ */ #include "ap_ro_integrity_check.h" #include "ec_commands.h" +#include "extension.h" #include "gpio.h" #include "hooks.h" #include "registers.h" @@ -15,9 +16,11 @@ #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) static enum device_state state = DEVICE_STATE_INIT; +static bool disable_ds_temp; void print_ap_state(void) { + ccprintf("DS Dis: %s\n", disable_ds_temp ? "on" : "off"); ccprintf("AP: %s\n", device_state_name(state)); } @@ -26,6 +29,46 @@ int ap_is_on(void) return state == DEVICE_STATE_ON; } +void pmu_check_tpm_rst(void) +{ + /* + * disable_ds_temp modifies the GPIO_TPM_RST_L wake settings to + * WAKE_HIGH. With that setting it's possible to miss a rising edge. + * If TPM_RST_L is high, but the ap state isn't on, cr50 missed the + * edge. Trigger the interrupt manually. + */ + if (disable_ds_temp && !ap_is_on() && + gpio_get_level(GPIO_TPM_RST_L)) { + tpm_rst_deasserted(GPIO_TPM_RST_L); + CPRINTS("Missed edge"); + } +} + +/* + * Disable deep sleep during the next TPM_RST_L pulse + * + * Normally cr50 enters deep sleep while TPM_RST_L is asserted. This vendor + * command can be used to disable deep sleep the next time TPM_RST_L is + * asserted. + * + * This can be run on any board with any CCD state. + */ +static enum vendor_cmd_rc vc_ds_disable_temp(enum vendor_cmd_cc code, + void *buf, + size_t input_size, + size_t *response_size) +{ + *response_size = 0; + if (input_size) + return VENDOR_RC_BOGUS_ARGS; + + disable_ds_temp = true; + CPRINTS("dis DS"); + + return VENDOR_RC_SUCCESS; +} +DECLARE_VENDOR_COMMAND(VENDOR_CC_DS_DIS_TEMP, vc_ds_disable_temp); + /** * Set the AP state. * @@ -75,8 +118,17 @@ static void deferred_set_ap_off(void) * Note: Presence of platform reset is a poor indicator of deep sleep * support. It happens to be correlated with ARM vs x86 at present. */ - if (board_deep_sleep_allowed()) + if (disable_ds_temp) { + CPRINTS("Block DS"); + disable_deep_sleep(); + /* + * TPM_RST_L will stay asserted until the system resumes. + * Wake from sleep when it goes high. + */ + gpio_set_wakepin(GPIO_TPM_RST_L, GPIO_HIB_WAKE_HIGH); + } else if (board_deep_sleep_allowed()) { enable_deep_sleep(); + } } DECLARE_DEFERRED(deferred_set_ap_off); @@ -100,6 +152,22 @@ void set_ap_on(void) if (board_deep_sleep_allowed()) disable_deep_sleep(); + + + /* + * Restore TPM_RST_L wake low now that TPM_RST_L has been + * deasserted. Only change the TPM_RST_L wake setting if cr50 blocked + * deep sleep. + */ + if (disable_ds_temp) { + CPRINTS("set TPM wake"); + gpio_set_wakepin(GPIO_TPM_RST_L, GPIO_HIB_WAKE_LOW); + } + /* + * disable_ds_temp only survives one TPM_RST_L pulse. Clear it when + * the AP turns back on. + */ + disable_ds_temp = false; } static uint8_t waiting_for_ap_reset; diff --git a/board/cr50/board.c b/board/cr50/board.c index 4f0ea7b66a..323b7d4d71 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -552,6 +552,8 @@ void pmu_wakeup_interrupt(void) if (wakeup_src & GC_PMU_EXITPD_SRC_PIN_PD_EXIT_MASK) { reset_wake_logic(); + pmu_check_tpm_rst(); + /* * Delay sleep long enough for a SPI periph transaction to start * or for the system to be reset. diff --git a/board/cr50/board.h b/board/cr50/board.h index 1e9e0f72d3..a42df3038f 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -395,6 +395,7 @@ void print_ap_uart_state(void); void print_ec_state(void); void print_servo_state(void); +void pmu_check_tpm_rst(void); int ap_is_on(void); int ap_uart_is_on(void); int ec_is_on(void); |