summaryrefslogtreecommitdiff
path: root/include/chipset.h
blob: 7b684598cb469b577fcee1ee68200b492fa9557f (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/* Copyright 2012 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.
 */

/*
 * Chipset module for Chrome EC.
 *
 * This is intended to be a platform/chipset-neutral interface, implemented by
 * all main chipsets (x86, gaia, etc.).
 */

#ifndef __CROS_EC_CHIPSET_H
#define __CROS_EC_CHIPSET_H

#include "common.h"
#include "compile_time_macros.h"
#include "ec_commands.h"
#include "gpio.h"
#include "stddef.h"

/*
 * Chipset state mask
 *
 * Note that this is a non-exhaustive list of states which the main chipset can
 * be in, and is potentially one-to-many for real, underlying chipset states.
 * That's why chipset_in_state() asks "Is the chipset in something
 * approximating this state?" and not "Tell me what state the chipset is in and
 * I'll compare it myself with the state(s) I want."
 */
enum chipset_state_mask {
	CHIPSET_STATE_HARD_OFF = 0x01,   /* Hard off (G3) */
	CHIPSET_STATE_SOFT_OFF = 0x02,   /* Soft off (S5) */
	CHIPSET_STATE_SUSPEND  = 0x04,   /* Suspend (S3) */
	CHIPSET_STATE_ON       = 0x08,   /* On (S0) */
	CHIPSET_STATE_STANDBY  = 0x10,   /* Standby (S0ix) */
	/* Common combinations */
	CHIPSET_STATE_ANY_OFF = (CHIPSET_STATE_HARD_OFF |
				 CHIPSET_STATE_SOFT_OFF),  /* Any off state */
	/* This combination covers any kind of suspend i.e. S3 or S0ix. */
	CHIPSET_STATE_ANY_SUSPEND = (CHIPSET_STATE_SUSPEND |
				     CHIPSET_STATE_STANDBY),
};

/*
 * Reason codes used by the AP after a shutdown to figure out why it was reset
 * by the EC.  These are sent in EC commands.  Therefore, to maintain protocol
 * compatibility:
 * - New entries must be inserted prior to the _COUNT field
 * - If an existing entry is no longer in service, it must be replaced with a
 *   RESERVED entry instead.
 * - The semantic meaning of an entry should not change.
 * - Do not exceed 2^15 - 1 for reset reasons or 2^16 - 1 for shutdown reasons.
 */
enum chipset_reset_reason {
	CHIPSET_RESET_BEGIN = 0,
	CHIPSET_RESET_UNKNOWN = CHIPSET_RESET_BEGIN,
	/* Custom reason defined by a board.c or baseboard.c file */
	CHIPSET_RESET_BOARD_CUSTOM,
	/* Believe that the AP has hung */
	CHIPSET_RESET_HANG_REBOOT,
	/* Reset by EC console command */
	CHIPSET_RESET_CONSOLE_CMD,
	/* Reset by EC host command */
	CHIPSET_RESET_HOST_CMD,
	/* Keyboard module reset key combination */
	CHIPSET_RESET_KB_SYSRESET,
	/* Keyboard module warm reboot */
	CHIPSET_RESET_KB_WARM_REBOOT,
	/* Debug module warm reboot */
	CHIPSET_RESET_DBG_WARM_REBOOT,
	/* I cannot self-terminate.  You must lower me into the steel. */
	CHIPSET_RESET_AP_REQ,
	/* Reset as side-effect of startup sequence */
	CHIPSET_RESET_INIT,
	/* EC detected an AP watchdog event. */
	CHIPSET_RESET_AP_WATCHDOG,
	CHIPSET_RESET_COUNT,
};

/*
 * Hard shutdowns are logged on the same path as resets.
 */
enum chipset_shutdown_reason {
	CHIPSET_SHUTDOWN_BEGIN = BIT(15),
	CHIPSET_SHUTDOWN_POWERFAIL = CHIPSET_SHUTDOWN_BEGIN,
	/* Forcing a shutdown as part of EC initialization */
	CHIPSET_SHUTDOWN_INIT,
	/* Custom reason on a per-board basis. */
	CHIPSET_SHUTDOWN_BOARD_CUSTOM,
	/* This is a reason to inhibit startup, not cause shut down. */
	CHIPSET_SHUTDOWN_BATTERY_INHIBIT,
	/* A power_wait_signal is being asserted */
	CHIPSET_SHUTDOWN_WAIT,
	/* Critical battery level. */
	CHIPSET_SHUTDOWN_BATTERY_CRIT,
	/* Because you told me to. */
	CHIPSET_SHUTDOWN_CONSOLE_CMD,
	/* Forcing a shutdown to effect entry to G3. */
	CHIPSET_SHUTDOWN_G3,
	/* Force shutdown due to over-temperature. */
	CHIPSET_SHUTDOWN_THERMAL,
	/* Force a chipset shutdown from the power button through EC */
	CHIPSET_SHUTDOWN_BUTTON,

	CHIPSET_SHUTDOWN_COUNT,
};

enum critical_shutdown {
	CRITICAL_SHUTDOWN_IGNORE,
	CRITICAL_SHUTDOWN_HIBERNATE,
	CRITICAL_SHUTDOWN_CUTOFF,
};

#ifdef HAS_TASK_CHIPSET

/**
 * Check if chipset is in a given state.
 *
 * @param state_mask	Combination of one or more CHIPSET_STATE_* flags.
 *
 * @return non-zero if the chipset is in one of the states specified in the
 * mask.
 */
int chipset_in_state(int state_mask);

/**
 * Check if chipset is in a given state or if the chipset task is currently
 * transitioning to that state. For example, G3S5, S5, and S3S5 would all count
 * as the S5 state.
 *
 * @param state_mask	Combination of one or more CHIPSET_STATE_* flags.
 *
 * @return non-zero if the chipset is in one of the states specified in the
 * mask.
 */
int chipset_in_or_transitioning_to_state(int state_mask);

/**
 * Ask the chipset to exit the hard off state.
 *
 * Does nothing if the chipset has already left the state, or was not in the
 * state to begin with.
 */
void chipset_exit_hard_off(void);

/* This is a private chipset-specific implementation for use only by
 * throttle_ap() . Don't call this directly!
 */
void chipset_throttle_cpu(int throttle);

/**
 * Immediately shut off power to main processor and chipset.
 *
 * This is intended for use when the system is too hot or battery power is
 * critical.
 */
void chipset_force_shutdown(enum chipset_shutdown_reason reason);

/**
 * Reset the CPU and/or chipset.
 */
void chipset_reset(enum chipset_reset_reason reason);

/**
 * Interrupt handler to power GPIO inputs.
 */
void power_interrupt(enum gpio_signal signal);

/**
 * Handle assert of eSPI_Reset# pin.
 */
void chipset_handle_espi_reset_assert(void);

/**
 * Perform chipset pre-initialization work within the context of chipset task.
 */
void chipset_pre_init_callback(void);

#else /* !HAS_TASK_CHIPSET */

/* When no chipset is present, assume it is always off. */
static inline int chipset_in_state(int state_mask)
{
	return state_mask & CHIPSET_STATE_ANY_OFF;
}

static inline int chipset_in_or_transitioning_to_state(int state_mask)
{
	return state_mask & CHIPSET_STATE_ANY_OFF;
}

static inline void chipset_exit_hard_off(void) { }
static inline void chipset_throttle_cpu(int throttle) { }
static inline void chipset_force_shutdown(enum chipset_shutdown_reason reason)
{
}

static inline void chipset_reset(enum chipset_reset_reason reason) { }
static inline void power_interrupt(enum gpio_signal signal) { }
static inline void chipset_handle_espi_reset_assert(void) { }
static inline void chipset_handle_reboot(void) { }
static inline void chipset_reset_request_interrupt(enum gpio_signal signal) { }
static inline void chipset_warm_reset_interrupt(enum gpio_signal signal) { }
static inline void chipset_watchdog_interrupt(enum gpio_signal signal) { }

#endif /* !HAS_TASK_CHIPSET */

/**
 * Optional chipset check if PLTRST# is valid.
 *
 * @return non-zero if PLTRST# is valid, 0 if invalid.
 */
int chipset_pltrst_is_valid(void) __attribute__((weak));

/**
 * Execute chipset-specific reboot.
 */
void chipset_handle_reboot(void);

/**
 * GPIO interrupt handler of reset request from AP.
 *
 * It is used in SDM845/MT8183 chipset power sequence.
 */
void chipset_reset_request_interrupt(enum gpio_signal signal);

/**
 * GPIO interrupt handler of warm reset signal from servo or H1.
 *
 * It is used in SDM845 chipset power sequence.
 */
void chipset_warm_reset_interrupt(enum gpio_signal signal);

/**
 * GPIO interrupt handler of watchdog from AP.
 *
 * It is used in MT8183 chipset, where it must be setup to trigger on falling
 * edge only.
 */
void chipset_watchdog_interrupt(enum gpio_signal signal);

/**
 * Callback which allows board to take custom action on G3 timer expiration
 *
 * @param last_shutdown_time Last shutdown time
 * @param target             Expiration time. Can be modified by board.
 * @param now                Current time
 * @return Action to take
 */
__override_proto enum critical_shutdown board_system_is_idle(
		uint64_t last_shutdown_time, uint64_t *target, uint64_t now);

#ifdef CONFIG_CMD_AP_RESET_LOG

/**
 * Report that the AP is being reset to the reset log.
 */
void report_ap_reset(enum chipset_shutdown_reason reason);

/**
 * Get statistics about AP resets.
 *
 * @param reset_log_entries       Pointer to array of log entries.
 * @param num_reset_log_entries   Number of items in reset_log_entries.
 * @param resets_since_ec_boot    Number of AP resets since EC boot.
 */
test_mockable enum ec_error_list
get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries,
		   size_t num_reset_log_entries,
		   uint32_t *resets_since_ec_boot);

#else

static inline void report_ap_reset(enum chipset_shutdown_reason reason) { }

test_mockable_static_inline enum ec_error_list
get_ap_reset_stats(struct ap_reset_log_entry *reset_log_entries,
		   size_t num_reset_log_entries, uint32_t *resets_since_ec_boot)
{
	return EC_SUCCESS;
}

#endif /* !CONFIG_CMD_AP_RESET_LOG */

#endif  /* __CROS_EC_CHIPSET_H */

/**
 * Initialize reset logs and next reset log.
 */
void init_reset_log(void);