blob: b53f25401597936cd9de41c1b8216ea77afc317d [file] [log] [blame]
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -05001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_LC_CTRL_H_
6#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_LC_CTRL_H_
7
8/**
9 * @file
10 * @brief <a href="/hw/ip/lc_ctrl/doc/">Lifecycle Controller</a> Device
11 * Interface Functions
12 */
13
14#include <stdbool.h>
15#include <stdint.h>
16
17#include "sw/device/lib/base/mmio.h"
18#include "sw/device/lib/dif/dif_warn_unused_result.h"
19
20#ifdef __cplusplus
21extern "C" {
22#endif // __cplusplus
23
24/**
25 * A lifecycle controller status code.
26 *
27 * See `dif_lc_ctrl_get_status()`.
28 */
29typedef enum dif_lc_ctrl_status_code {
30 /**
31 * Indicates that the controller has been successfully initialized.
32 */
33 kDifLcCtrlStatusCodeReady,
34 /**
35 * Indicates that the last lifecycle transition succeeded.
36 */
37 kDifLcCtrlStatusCodeSuccess,
38 /**
Michael Mundayd55bc6c2021-02-26 12:24:44 +000039 * Indicates that too many hardware transitions have occurred, and the
40 * hardware will not transition the lifecycle any further.
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -050041 */
42 kDifLcCtrlStatusCodeTooManyTransitions,
43 /**
44 * Indicates that an invalid lifecycle transition was attempted.
45 */
46 kDifLcCtrlStatusCodeInvalidTransition,
47 /**
48 * Indicates that a bad token was supplied for conditional transition.
49 */
50 kDifLcCtrlStatusCodeBadToken,
51 /**
52 * Indicates an error during an OTP operation.
53 *
54 * This error will raise an alert.
55 */
56 kDifLcCtrlStatusCodeOtpError,
57 /**
58 * Indicates an error in the controller's internal state.
59 *
60 * This error will raise an alert.
61 */
62 kDifLcCtrlStatusCodeCorrupt,
63} dif_lc_ctrl_status_code_t;
64
65/**
66 * A bit-vector of `dif_lc_ctrl_status_code_t`s.
67 *
68 * Whether a particular status is contained in this vector can be discovered by
69 * using it as a bit index: `bitfield_bit32_read(status, status_code);`.
70 */
71typedef uint32_t dif_lc_ctrl_status_t;
72
73/**
74 * A lifecycle state.
75 *
76 * This enum represents all states that the lifecycle state register can be in;
77 * some of these do not correspond to "real" lifecycle states, and cannot be
78 * transitioned to.
79 */
80typedef enum dif_lc_ctrl_state_t {
81 /**
82 * The initial post-manufacture state.
83 *
84 * All functions are disabled.
85 */
86 kDifLcCtrlStateRaw,
87 /**
88 * The zeroth test state.
89 *
90 * Debug functions are enabled.
91 */
92 kDifLcCtrlStateTestUnlocked0,
93 /**
94 * The zeroth locked test state.
95 *
96 * All functions are disabled.
97 */
98 kDifLcCtrlStateTestLocked0,
99 /**
100 * The first test state.
101 *
102 * Debug functions are enabled.
103 */
104 kDifLcCtrlStateTestUnlocked1,
105 /**
106 * The first locked test state.
107 *
108 * All functions are disabled.
109 */
110 kDifLcCtrlStateTestLocked1,
111 /**
112 * The second test state.
113 *
114 * Debug functions are enabled.
115 */
116 kDifLcCtrlStateTestUnlocked2,
117 /**
118 * The second locked test state.
119 *
120 * All functions are disabled.
121 */
122 kDifLcCtrlStateTestLocked2,
123 /**
124 * The third test state.
125 *
126 * Debug functions are enabled.
127 */
128 kDifLcCtrlStateTestUnlocked3,
129 /**
130 * The development state.
131 *
132 * Some debug functions are enabled.
133 */
134 kDifLcCtrlStateDev,
135 /**
136 * The main production state.
137 *
138 * No debug functions are enabled.
139 */
140 kDifLcCtrlStateProd,
141 /**
142 * The EOL production state.
143 *
144 * Same as Prod, except Rma cannot be transitioned to.
145 */
146 kDifLcCtrlStateProdEnd,
147 /**
148 * RMA manufacturer analysis state.
149 */
150 kDifLcCtrlStateRma,
151 /**
152 * The scrap EOL state.
153 *
154 * Cannot be transitioned from; all functions are disabled.
155 */
156 kDifLcCtrlStateScrap,
157
158 /**
159 * State entered immediately after a transition occurs.
160 *
161 * Not a real state.
162 */
163 kDifLcCtrlStatePostTransition,
164 /**
165 * State entered immediately after an alert is raised.
166 *
167 * Not a real state.
168 */
169 kDifLcCtrlStateEscalate,
170 /**
171 * Indicates that the encoded lifecycle is invalid.
172 *
173 * Not a real state.
174 */
175 kDifLcCtrlStateInvalid,
176} dif_lc_ctrl_state_t;
177
178/**
179 * A personalization state, indicating whether the device has been successfully
180 * personalized.
181 */
182typedef enum dif_lc_ctrl_id_state {
183 /**
184 * Indicates that the device has not yet been personalized.
185 */
186 kDifLcCtrlIdStateBlank,
187 /**
188 * Indicates that the device has been personalized.
189 */
190 kDifLcCtrlIdStatePersonalized,
191 /**
192 * Indicates that the personalization state is corrupt.
193 */
194 kDifLcCtrlIdStateInvalid,
195} dif_lc_ctrl_id_state_t;
196
197/**
198 * A 128-bit unlock token used for certain kinds of lifecycle transitions.
199 */
200typedef struct dif_lc_ctrl_token {
201 uint8_t data[128 / 8];
202} dif_lc_ctrl_token_t;
203
204/**
205 * Hardware instantiation parameters for a lifecycle controller.
206 *
207 * This struct describes information about the underlying hardware that is
208 * not determined until the hardware design is used as part of a top-level
209 * design.
210 */
211typedef struct dif_lc_ctrl_params {
212 /**
213 * The base address for the lifecycle controller hardware registers.
214 */
215 mmio_region_t base_addr;
216} dif_lc_ctrl_params_t;
217
218/**
219 * A handle to a lifecycle controller.
220 *
221 * This type should be treated as opaque by users.
222 */
223typedef struct dif_lc_ctrl {
224 dif_lc_ctrl_params_t params;
225} dif_lc_ctrl_t;
226
227/**
228 * The result of a lifecycle controller operation.
229 */
230typedef enum dif_lc_ctrl_result {
231 /**
232 * Indicates that the operation succeeded.
233 */
234 kDifLcCtrlOk = 0,
235 /**
236 * Indicates some unspecified failure.
237 */
238 kDifLcCtrlError = 1,
239 /**
240 * Indicates that some parameter passed into a function failed a
241 * precondition.
242 *
Michael Mundayd55bc6c2021-02-26 12:24:44 +0000243 * When this value is returned, no hardware operations occurred.
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -0500244 */
245 kDifLcCtrlBadArg = 2,
246} dif_lc_ctrl_result_t;
247
248/**
249 * The result of a lifecycle attempt counter operation.
250 */
251typedef enum dif_lc_ctrl_attempts_result {
252 /**
253 * Indicates that the operation succeeded.
254 */
255 kDifLcCtrlAttemptsOk = kDifLcCtrlOk,
256 /**
257 * Indicates some unspecified failure.
258 */
259 kDifLcCtrlAttemptsError = kDifLcCtrlError,
260 /**
261 * Indicates that some parameter passed into a function failed a
262 * precondition.
263 *
Michael Mundayd55bc6c2021-02-26 12:24:44 +0000264 * When this value is returned, no hardware operations occurred.
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -0500265 */
266 kDifLcCtrlAttemptsBadArg = kDifLcCtrlBadArg,
267 /**
268 * Indicates that too many lifecycle transitions have occurred, such that the
269 * hardware can no longer keep a count.
270 */
271 kDifLcCtrlAttemptsTooMany,
272} dif_lc_ctrl_attempts_result_t;
273
274/**
275 * The result of a lifecycle controller operation involving the hardware mutex.
276 */
277typedef enum dif_lc_ctrl_mutex_result {
278 /**
279 * Indicates that the operation succeeded.
280 */
281 kDifLcCtrlMutexOk = kDifLcCtrlOk,
282 /**
283 * Indicates some unspecified failure.
284 */
285 kDifLcCtrlMutexError = kDifLcCtrlError,
286 /**
287 * Indicates that some parameter passed into a function failed a
288 * precondition.
289 *
Michael Mundayd55bc6c2021-02-26 12:24:44 +0000290 * When this value is returned, no hardware operations occurred.
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -0500291 */
292 kDifLcCtrlMutexBadArg = kDifLcCtrlBadArg,
293
294 /**
295 * Indicates that a mutex-guarded operation failed because someone (other
296 * than software) is holding it.
297 */
298 kDifLcCtrlMutexAlreadyTaken = 3,
299} dif_lc_ctrl_mutex_result_t;
300
301/**
302 * An alert that can be raised by the hardware.
303 */
304typedef enum dif_lc_ctrl_alert {
305 /**
306 * The alert triggered by a `kDifLcCtrlStatusCodeOtpError`.
307 */
308 kDifLcCtrlAlertOtp,
309 /**
310 * The alert triggered by a `kDifLcCtrlStatusCodeCorrupt`.
311 */
312 kDifLcCtrlAlertCorrupt,
313} dif_lc_ctrl_alert_t;
314
315/**
316 * Creates a new handle for the lifecycle controller.
317 *
318 * This function does not actuate the hardware.
319 *
320 * @param params Hardware instantiation parameters.
321 * @param[out] lc Out param for the initialized handle.
322 * @return The result of the operation.
323 */
324DIF_WARN_UNUSED_RESULT
325dif_lc_ctrl_result_t dif_lc_ctrl_init(dif_lc_ctrl_params_t params,
326 dif_lc_ctrl_t *lc);
327
328/**
329 * Returns the current state of the lifecycle controller.
330 *
331 * @param lc A lifecycle handle.
332 * @param[out] state Out-param for the controller's state.
333 * @return The result of the operation.
334 */
335DIF_WARN_UNUSED_RESULT
336dif_lc_ctrl_result_t dif_lc_ctrl_get_state(const dif_lc_ctrl_t *lc,
337 dif_lc_ctrl_state_t *state);
338
339/**
340 * Returns the number of lifecycle transitions that this device has attempted,
341 * up to 16.
342 *
343 * @param lc A lifecycle handle.
Tobias Wölfel01ec7cf2021-02-12 11:57:12 +0100344 * @param[out] count Out-param for the number of attempts.
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -0500345 * @return The result of the operation.
346 */
347DIF_WARN_UNUSED_RESULT
348dif_lc_ctrl_attempts_result_t dif_lc_ctrl_get_attempts(const dif_lc_ctrl_t *lc,
349 uint8_t *count);
350
351/**
352 * Returns the current status of the lifecycle controller.
353 *
354 * @param lc A lifecycle handle.
355 * @param[out] status Out-param for the controller's status.
356 * @return The result of the operation.
357 */
358DIF_WARN_UNUSED_RESULT
359dif_lc_ctrl_result_t dif_lc_ctrl_get_status(const dif_lc_ctrl_t *lc,
360 dif_lc_ctrl_status_t *status);
361
362/**
363 * Returns the current personalization state of the lifecycle controller.
364 *
365 * @param lc A lifecycle handle.
366 * @param[out] state Out-param for the controller's personalization state.
367 * @return The result of the operation.
368 */
369DIF_WARN_UNUSED_RESULT
370dif_lc_ctrl_result_t dif_lc_ctrl_get_id_state(const dif_lc_ctrl_t *lc,
371 dif_lc_ctrl_id_state_t *state);
372
373/**
374 * Forces a particular alert, causing it to be escalated as if the hardware had
375 * raised it.
376 *
377 * @param lc A lifecycle handle.
378 * @param alert The alert to force.
379 * @return The result of the operation.
380 */
381DIF_WARN_UNUSED_RESULT
382dif_lc_ctrl_result_t dif_lc_ctrl_alert_force(const dif_lc_ctrl_t *lc,
383 dif_lc_ctrl_alert_t alert);
384
385/**
386 * Attempts to acquire the lifecycle controller's HW mutex.
387 *
388 * Returns `kDifLcCtrlMutexHeld` if acquisition fails. It is recommended to
389 * call this function in a busy loop to acquire the mutex.
390 *
391 * @param lc A lifecycle handle.
392 * @return The result of the operation.
393 */
394// Open Q: do we want to be checking REGWEN for all operations dependent on the
395// mutex?
396DIF_WARN_UNUSED_RESULT
397dif_lc_ctrl_mutex_result_t dif_lc_ctrl_mutex_try_acquire(
398 const dif_lc_ctrl_t *lc);
399
400/**
401 * Releases the lifecycle controller's HW mutex.
402 *
403 * Calls to this function must be sequenced with successful calls to
404 * `dif_lc_ctrl_mutex_try_acquire()`.
405 *
406 * @param lc A lifecycle handle.
407 * @return The result of the operation.
408 */
409DIF_WARN_UNUSED_RESULT
410dif_lc_ctrl_mutex_result_t dif_lc_ctrl_mutex_release(const dif_lc_ctrl_t *lc);
411
412/**
413 * Performs a lifecycle transition.
414 *
415 * Note that not all transitions require an unlock token; in that case, NULL
416 * should be passed as the token.
417 *
418 * @param lc A lifecycle handle.
419 * @param state The state to transition to.
420 * @param token A token for unlocking the transition; may be null.
421 * @return The result of the operation.
422 */
423DIF_WARN_UNUSED_RESULT
424dif_lc_ctrl_mutex_result_t dif_lc_ctrl_transition(
425 const dif_lc_ctrl_t *lc, dif_lc_ctrl_state_t state,
426 const dif_lc_ctrl_token_t *token);
427
Michael Schaffner82c321f2021-06-04 20:00:27 -0700428/**
429 * Writes settings to the vendor-specific OTP test control register.
430 *
431 * @param lc A lifecycle handle.
432 * @param settings The settings to write to the register.
433 * @return The result of the operation.
434 */
435DIF_WARN_UNUSED_RESULT
436dif_lc_ctrl_mutex_result_t dif_lc_ctrl_set_otp_test_reg(const dif_lc_ctrl_t *lc,
437 uint32_t settings);
438
439/**
440 * Reads settings from the vendor-specific OTP test control register.
441 *
442 * @param lc A lifecycle handle.
443 * @param settings Output parameter for the settings.
444 * @return The result of the operation.
445 */
446DIF_WARN_UNUSED_RESULT
447dif_lc_ctrl_result_t dif_lc_ctrl_get_otp_test_reg(const dif_lc_ctrl_t *lc,
448 uint32_t *settings);
449
Miguel Young de la Sota29a1e352020-11-18 10:49:59 -0500450#ifdef __cplusplus
451} // extern "C"
452#endif // __cplusplus
453
454#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_LC_CTRL_H_