summaryrefslogtreecommitdiff
path: root/zephyr/subsys/ap_pwrseq/include/power_signals.h
blob: 5d3e97a52ee2f9c1ca5bdc7b724f6adea5118091 (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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/* Copyright 2022 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/**
 * @file
 * @brief Definition of the power signals API.
 *
 * Defines the API for accessing the power signals.
 *
 * The AP power sequence code uses power signals to monitor and control
 * the startup and shutdown of the AP. These power signals may be
 * accessed from a variety of sources, such as GPIOs, eSPI virtual
 * wires, and board specific sources. Regardless of the source
 * of the signal or control, a single API is used to access these signals.
 * The configuration of the source of the signals is done via
 * devicetree, using a number of different compatibles each
 * representing a different source of the signals.
 *
 * The power sequence code identifies the signals via a common enum,
 * which is generated from a common set of enum names in devicetree.
 *
 * The API defined here also functions to deal with the signals
 * as a set i.e being able to watch for a certain set of signals
 * to become asserted.
 *
 * Intermediate layers provide a way of mapping these signals
 * to the underlying source; the intent is that these signals
 * provide a logical state for the signal, regardless of whatever
 * polarity the physical pin is defined as i.e an input signal may be
 * considered asserted if the voltage is low, but this is a platform
 * specific attribute, and should be configured at the h/w layer e.g
 * a GPIO that is asserted when low should be configured using the
 * GPIO_ACTIVE_LOW flag, so that the logical asserted signal is
 * read as '1', not '0'.
 */

#ifndef __AP_PWRSEQ_POWER_SIGNALS_H__
#define __AP_PWRSEQ_POWER_SIGNALS_H__

#include <zephyr/devicetree.h>

#if DT_HAS_COMPAT_STATUS_OKAY(intel_ap_pwrseq)

/*
 * Create guards so that code used for a source is only
 * included if that signal source is configured in the
 * devicetree.
 */
#define HAS_GPIO_SIGNALS DT_HAS_COMPAT_STATUS_OKAY(intel_ap_pwrseq_gpio)
#define HAS_VW_SIGNALS DT_HAS_COMPAT_STATUS_OKAY(intel_ap_pwrseq_vw)
#define HAS_EXT_SIGNALS DT_HAS_COMPAT_STATUS_OKAY(intel_ap_pwrseq_external)
#define HAS_ADC_SIGNALS DT_HAS_COMPAT_STATUS_OKAY(intel_ap_pwrseq_adc)

/**
 * @brief Definitions for AP power sequence signals.
 *
 * Defines the enums for the AP power sequence signals.
 */

/**
 * @brief Generate the enum for this power signal.
 */
#define PWR_SIGNAL_ENUM(id) DT_STRING_UPPER_TOKEN(id, enum_name)

#define PWR_SIGNAL_ENUM_COMMA(id) PWR_SIGNAL_ENUM(id),
/**
 * @brief Enum of all power signals.
 *
 * Defines the enums of all the power signals configured
 * in the system. Uses the 'enum-name' property to name
 * the signal.
 *
 * The order that these compatibles are processed in
 * must be the same as in power_signals.c
 */
enum power_signal {
	DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_gpio, PWR_SIGNAL_ENUM_COMMA)
		DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_vw,
				       PWR_SIGNAL_ENUM_COMMA)
			DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_external,
					       PWR_SIGNAL_ENUM_COMMA)
				DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_adc,
						       PWR_SIGNAL_ENUM_COMMA)
					POWER_SIGNAL_COUNT,
};

#undef PWR_SIGNAL_ENUM_COMMA

#if HAS_EXT_SIGNALS
/**
 * Definitions required for external (board-specific)
 * power signals.
 *
 * int board_power_signal_get(enum power_signal signal)
 * {
 *     int value;
 *
 *     switch(signal) {
 *     default:
 *         LOG(LOG_ERR, "Unknown power signal!");
 *         return -1;
 *
 *     case PWR_VCCST_PWRGD:
 *         value = ...
 *         return value;
 *     }
 * }
 *
 */

/**
 * @brief Board specific function to get power signal.
 *
 * Function to get power signals that are board specific
 * values. Only required when 'intel_ap_pwrseq_external'
 * compatible nodes are defined in devicetree, indicating that
 * the particular signal is to be sourced via this board
 * level function.
 *
 * @param signal Power signal value to return
 * @return 0 or 1 Power signal value
 * @return negative Error
 */
int board_power_signal_get(enum power_signal signal);

/**
 * @brief Board specific function to set power signal.
 *
 * @param signal Power signal value to set
 * @param value Value to set signal to.
 * @return 0 Success
 * @return negative Error
 */
int board_power_signal_set(enum power_signal signal, int value);

#endif /* HAS_EXT_SIGNALS */

/**
 * @brief Get the value of this power signal.
 *
 * Retrieve the value of this power signal.
 *
 * @param signal The power_signal to get.
 * @return 0 or 1 Value of signal
 * @return negative If error occurred
 */
int power_signal_get(enum power_signal signal);

/**
 * @brief Set the output of this power signal.
 *
 * Only some signals allow the output to be set.
 *
 * @param signal The power_signal to set.
 * @param value The output value to set it to.
 * @return 0 is successful
 * @return negative If output cannot be set.
 */
int power_signal_set(enum power_signal signal, int value);

/**
 * @brief Enable this power signal
 *
 * Enable this signal to be used as a power_signal.
 * Typically this means the interrupt associated with this
 * signal is enabled.
 *
 * Power signals are enabled by default at startup, and if
 * a power signal is disabled via power_signal_disable(), it will
 * need to be re-enabled before the signal is included in the
 * input handling again.
 *
 * @param signal The power_signal to enable.
 * @return 0 is successful
 * @return negative If unsuccessful
 */
int power_signal_enable(enum power_signal signal);

/**
 * @brief Disable this power signal
 *
 * Disable the signal so that it does not update the
 * input handling (i.e does not call power_signal_interrupt() etc.)
 * Once disabled, a signal must be re-enabled using
 * power_signal_enable() to allow the signal to be used again.
 *
 * @param signal The power_signal to disable.
 * @return 0 is successful
 * @return negative If unsuccessful
 */
int power_signal_disable(enum power_signal signal);

/**
 * @brief Get the debug name associated with this signal.
 *
 * @param signal The power_signal value to get.
 * @return string The name of the signal.
 */
const char *power_signal_name(enum power_signal signal);

/**
 * @brief Initialize the power signal interface.
 *
 * Called when the power sequence code is ready to start
 * processing inputs and outputs.
 */
void power_signal_init(void);

/**
 * @brief Power signal interrupt handler
 *
 * Called when an input signal has changed.
 * May be called from interrupt context.
 *
 * @param signal The power_signal that has changed.
 * @param value The new value of the signal
 */
void power_signal_interrupt(enum power_signal signal, int value);

/**
 * Interrupt based signals update a bitfield mask, which can be
 * used to wait for signal changes.
 */
typedef uint32_t power_signal_mask_t;

/**
 * @brief Get the current interrupt bitfield
 *
 * @return Interrupt power signals as a mask.
 */
power_signal_mask_t power_get_signals(void);

/**
 * @brief Set the signal debug mask
 *
 * Sets a debug mask of signals.
 * A log is generated whenever any of these signals change.
 *
 * @param debug Mask of signals to be flagged for logging
 */
void power_set_debug(power_signal_mask_t debug);

/**
 * @brief Get the signal debug mask
 *
 * Gets the current debug mask of signals.
 *
 * @return Current mask of signals to be flagged for logging
 */
power_signal_mask_t power_get_debug(void);

/**
 * @brief Check if the desired signals match.
 *
 * Masks off the signals using the mask and
 * compare against the wanted signals.
 *
 * @param mask Mask of signals to be checked
 * @param wait Matching value.
 * @return True if all the masked signals match the wanted signals
 */
static inline bool power_signals_match(power_signal_mask_t mask,
				       power_signal_mask_t want)
{
	return (power_get_signals() & mask) == (want & mask);
}

/**
 * @brief Check if all the desired signals are asserted.
 *
 * @param want Mask of signals to be checked
 * @return True if all the wanted signals are asserted.
 */
static inline bool power_signals_on(power_signal_mask_t want)
{
	return power_signals_match(want, want);
}

/**
 * @brief Check if the desired signals are deasserted.
 *
 * @param want Mask of signals to be checked
 * @return True if all the wanted signals are deasserted.
 */
static inline bool power_signals_off(power_signal_mask_t want)
{
	return power_signals_match(want, 0);
}

/**
 * @brief Wait until the selected power signals match
 *
 * Given a signal mask and wanted value, wait until the
 * selected power signals match the wanted value.
 *
 * @param want The value of the signals to wait for.
 * @param mask The mask of the selected signals
 * @param timeout The amount of time to wait in ms.
 * @return 0 if the signals matched.
 * @return negative If the signals did not match before the timeout.
 */
int power_wait_mask_signals_timeout(power_signal_mask_t want,
				    power_signal_mask_t mask, int timeout);

/**
 * @brief Wait until the selected power signals match, with timeout
 *
 * Given a set of signals, wait until all of
 * the signals are asserted.
 *
 * @param want The value of the signals to wait for.
 * @param timeout The amount of time to wait in ms.
 * @return 0 if the signals matched.
 */
static inline int power_wait_signals_timeout(power_signal_mask_t want,
					     int timeout)
{
	return power_wait_mask_signals_timeout(want, want, timeout);
}

/**
 * @brief Create a mask from a power signal.
 */
#define POWER_SIGNAL_MASK(signal) (1 << (signal))

#endif /* DT_HAS_COMPAT_STATUS_OKAY */

#endif /* __AP_PWRSEQ_POWER_SIGNALS_H__ */