summaryrefslogtreecommitdiff
path: root/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c
blob: 97268e8fe6b9acadef57bc4fd229bb703dd1280e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* Copyright 2022 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <x86_common_pwrseq.h>
#include <x86_non_dsx_common_pwrseq_sm_handler.h>

LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);

/**
 * Determine the current state of the CPU from the
 * power signals.
 */
enum power_states_ndsx chipset_pwr_seq_get_state(void)
{
	/*
	 * Chip is shut down.
	 */
	if ((power_get_signals() & MASK_ALL_POWER_GOOD) == 0) {
		LOG_DBG("Power rails off, G3 state");
		return SYS_POWER_STATE_G3;
	}
	/*
	 * If not all the power rails are available,
	 * then force shutdown to G3 to get to known state.
	 */
	if ((power_get_signals() & MASK_ALL_POWER_GOOD)
			!= MASK_ALL_POWER_GOOD) {
		ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
		LOG_INF("Not all power rails up, forcing shutdown");
		return SYS_POWER_STATE_G3;
	}

	/*
	 * All the power rails are good, so
	 * wait for virtual wire signals to become available.
	 * Not sure how long to wait? 5 seconds total.
	 */
	for (int delay = 0; delay < 500; k_msleep(10), delay++) {
#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S3)
		if (power_signal_get(PWR_SLP_S3) < 0)
			continue;
#endif
#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S4)
		if (power_signal_get(PWR_SLP_S4) < 0)
			continue;
#endif
#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S5)
		if (power_signal_get(PWR_SLP_S5) < 0)
			continue;
#endif
		/*
		 * All signals valid.
		 */
		LOG_DBG("All VW signals valid after %d ms", delay * 10);
		break;
	}
	/*
	 * S0, all power OK, no suspend or sleep on.
	 */
	if ((power_get_signals() & MASK_S0) == MASK_ALL_POWER_GOOD) {
		LOG_DBG("CPU in S0 state");
		return SYS_POWER_STATE_S0;
	}
	/*
	 * S3, all power OK, PWR_SLP_S3 on.
	 */
	if ((power_get_signals() & MASK_S0) ==
		(MASK_ALL_POWER_GOOD | POWER_SIGNAL_MASK(PWR_SLP_S3))) {
		LOG_DBG("CPU in S3 state");
		return SYS_POWER_STATE_S3;
	}
	/*
	 * S5, all power OK, PWR_SLP_S5 on.
	 */
	if ((power_get_signals() & MASK_S5) == MASK_S5) {
		LOG_DBG("CPU in S5 state");
		return SYS_POWER_STATE_S5;
	}
	/*
	 * Unable to determine state, force to G3.
	 */
	ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
	LOG_INF("Unable to determine CPU state, forcing shutdown");
	return SYS_POWER_STATE_G3;
}