Software APIs
lifecycle.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
6
7#include <assert.h>
8#include <stdint.h>
9
10#include "hw/top/dt/lc_ctrl.h"
16
17#include "hw/top/lc_ctrl_regs.h"
18
19static inline uint32_t lc_ctrl_base(void) {
20 return dt_lc_ctrl_primary_reg_block(kDtLcCtrl);
21}
22
23lifecycle_state_t lifecycle_state_get(void) {
24 uint32_t raw_state = lifecycle_raw_state_get();
25
26 switch (launder32(raw_state)) {
27 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0:
28 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0);
29 return kLcStateTest;
30 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1:
31 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1);
32 return kLcStateTest;
33 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2:
34 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2);
35 return kLcStateTest;
36 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3:
37 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3);
38 return kLcStateTest;
39 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4:
40 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4);
41 return kLcStateTest;
42 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5:
43 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5);
44 return kLcStateTest;
45 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6:
46 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6);
47 return kLcStateTest;
48 case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7:
49 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7);
50 return kLcStateTest;
51 case LC_CTRL_LC_STATE_STATE_VALUE_DEV:
52 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_DEV);
53 return kLcStateDev;
54 case LC_CTRL_LC_STATE_STATE_VALUE_PROD:
55 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD);
56 return kLcStateProd;
57 case LC_CTRL_LC_STATE_STATE_VALUE_PROD_END:
58 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD_END);
59 return kLcStateProdEnd;
60 case LC_CTRL_LC_STATE_STATE_VALUE_RMA:
61 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_RMA);
62 return kLcStateRma;
63 default:
66 }
67}
68
69hardened_bool_t lifecycle_is_prod(void) {
70 uint32_t raw_state = lifecycle_raw_state_get();
71
72 if (launder32(raw_state) == LC_CTRL_LC_STATE_STATE_VALUE_PROD) {
73 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD);
74 return kHardenedBoolTrue;
75 }
76 HARDENED_CHECK_NE(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD);
77
78 if (launder32(raw_state) == LC_CTRL_LC_STATE_STATE_VALUE_PROD_END) {
79 HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD_END);
80 return kHardenedBoolTrue;
81 }
82 HARDENED_CHECK_NE(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD_END);
83
84 return kHardenedBoolFalse;
85}
86
87uint32_t lifecycle_raw_state_get(void) {
88 uint32_t value = bitfield_field32_read(
89 sec_mmio_read32(lc_ctrl_base() + LC_CTRL_LC_STATE_REG_OFFSET),
90 LC_CTRL_LC_STATE_STATE_FIELD);
91 return value;
92}
93
94void lifecycle_device_id_get(lifecycle_device_id_t *device_id) {
95 static_assert(
96 kLifecycleDeviceIdNumWords == LC_CTRL_PARAM_NUM_DEVICE_ID_WORDS,
97 "length of the device_id array does not match the length in hardware");
98
99 size_t i = 0, r = kLifecycleDeviceIdNumWords - 1;
100 for (; launder32(i) < kLifecycleDeviceIdNumWords &&
101 launder32(r) < kLifecycleDeviceIdNumWords;
102 ++i, --r) {
103 device_id->device_id[i] = sec_mmio_read32(
104 lc_ctrl_base() + LC_CTRL_DEVICE_ID_0_REG_OFFSET + i * sizeof(uint32_t));
105 }
106 HARDENED_CHECK_EQ(i, kLifecycleDeviceIdNumWords);
107 HARDENED_CHECK_EQ(r, SIZE_MAX);
108}
109
110void lifecycle_hw_rev_get(lifecycle_hw_rev_t *hw_rev) {
111 uint32_t reg0 =
112 sec_mmio_read32(lc_ctrl_base() + LC_CTRL_HW_REVISION0_REG_OFFSET);
113 uint32_t reg1 =
114 sec_mmio_read32(lc_ctrl_base() + LC_CTRL_HW_REVISION1_REG_OFFSET);
115 *hw_rev = (lifecycle_hw_rev_t){
116 .silicon_creator_id = (uint16_t)bitfield_field32_read(
117 reg0, LC_CTRL_HW_REVISION0_SILICON_CREATOR_ID_FIELD),
118 .product_id = (uint16_t)bitfield_field32_read(
119 reg0, LC_CTRL_HW_REVISION0_PRODUCT_ID_FIELD),
120 .revision_id = (uint8_t)bitfield_field32_read(
121 reg1, LC_CTRL_HW_REVISION1_REVISION_ID_FIELD),
122 };
123}
124
125hardened_bool_t lifecycle_din_eq(lifecycle_device_id_t *id, uint32_t *din) {
126 if (id->device_id[1] == din[0] && id->device_id[2] == din[1])
127 return kHardenedBoolTrue;
128 return kHardenedBoolFalse;
129}
130
131bool lifecycle_claim(uint32_t claim) {
132 abs_mmio_write32(lc_ctrl_base() + LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET,
133 claim);
134 return (bool)abs_mmio_read32(lc_ctrl_base() +
135 LC_CTRL_TRANSITION_REGWEN_REG_OFFSET);
136}
137
138void lifecycle_set_status(lifecycle_status_word_t word, uint32_t value) {
139 abs_mmio_write32(lc_ctrl_base() + LC_CTRL_TRANSITION_TOKEN_0_REG_OFFSET +
140 word * sizeof(uint32_t),
141 value);
142}