5#include "sw/device/lib/testing/nvm_testutils.h"
12#include "sw/device/lib/base/multibits.h"
14#include "sw/device/lib/testing/flash_ctrl_testutils.h"
15#include "sw/device/lib/testing/test_framework/check.h"
16#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
21enum { kNvmMaxWordCount = 16 };
27 uint32_t partition_id;
35 [kNvmInfoPageFactoryId] = {.page_id = 0, .bank = 0, .partition_id = 0},
36 [kNvmInfoPageCreatorSecret] = {.page_id = 1, .bank = 0, .partition_id = 0},
37 [kNvmInfoPageOwnerSecret] = {.page_id = 2, .bank = 0, .partition_id = 0},
38 [kNvmInfoPageWaferAuthSecret] = {.page_id = 3, .bank = 0, .partition_id = 0},
39 [kNvmInfoPageAttestationKeySeeds] = {.page_id = 4, .bank = 0, .partition_id = 0},
40 [kNvmInfoPageOwnerReserved0] = {.page_id = 5, .bank = 0, .partition_id = 0},
41 [kNvmInfoPageOwnerReserved1] = {.page_id = 6, .bank = 0, .partition_id = 0},
42 [kNvmInfoPageOwnerReserved2] = {.page_id = 7, .bank = 0, .partition_id = 0},
43 [kNvmInfoPageOwnerReserved3] = {.page_id = 8, .bank = 0, .partition_id = 0},
44 [kNvmInfoPageFactoryCerts] = {.page_id = 9, .bank = 0, .partition_id = 0},
46 [kNvmInfoPageBootData0] = {.page_id = 0, .bank = 1, .partition_id = 0},
47 [kNvmInfoPageBootData1] = {.page_id = 1, .bank = 1, .partition_id = 0},
48 [kNvmInfoPageOwnerSlot0] = {.page_id = 2, .bank = 1, .partition_id = 0},
49 [kNvmInfoPageOwnerSlot1] = {.page_id = 3, .bank = 1, .partition_id = 0},
50 [kNvmInfoPageCreatorReserved0] = {.page_id = 4, .bank = 1, .partition_id = 0},
51 [kNvmInfoPageOwnerReserved4] = {.page_id = 5, .bank = 1, .partition_id = 0},
52 [kNvmInfoPageOwnerReserved5] = {.page_id = 6, .bank = 1, .partition_id = 0},
53 [kNvmInfoPageOwnerReserved6] = {.page_id = 7, .bank = 1, .partition_id = 0},
54 [kNvmInfoPageOwnerReserved7] = {.page_id = 8, .bank = 1, .partition_id = 0},
55 [kNvmInfoPageDiceCerts] = {.page_id = 9, .bank = 1, .partition_id = 0},
59const nvm_page_perms_t kPageReadOnly = {.read = kMultiBitBool4True,
60 .write = kMultiBitBool4False,
61 .erase = kMultiBitBool4False};
63const nvm_page_perms_t kPageReadWrite = {.read = kMultiBitBool4True,
64 .write = kMultiBitBool4True,
65 .erase = kMultiBitBool4True};
67const nvm_page_perms_t kPageWriteOnly = {.read = kMultiBitBool4False,
68 .write = kMultiBitBool4True,
69 .erase = kMultiBitBool4True};
71const nvm_page_cfg_t kPageScrambleCfg = {.scrambling = kMultiBitBool4True,
72 .ecc = kMultiBitBool4True,
73 .he = kMultiBitBool4False};
75const nvm_page_cfg_t kPagePlainCfg = {.scrambling = kMultiBitBool4False,
76 .ecc = kMultiBitBool4True,
77 .he = kMultiBitBool4False};
79const nvm_page_cfg_t kPageRawCfg = {.scrambling = kMultiBitBool4False,
80 .ecc = kMultiBitBool4False,
81 .he = kMultiBitBool4False};
84 TRY(dif_flash_ctrl_init_state(
89status_t nvm_testutils_wait_for_init(
void) {
91 TRY(dif_flash_state_init(&flash));
92 TRY(flash_ctrl_testutils_wait_for_init(&flash));
98 region.
bank = p->bank;
100 region.
page = p->page_id;
107 TRY(dif_flash_ctrl_get_info_region_properties(flash, phys_to_region(p),
116 TRY(dif_flash_ctrl_set_info_region_properties(flash, region, props));
117 TRY(dif_flash_ctrl_set_info_region_enablement(flash, region,
122status_t nvm_testutils_rom_init(uint32_t otp_flash_default_cfg) {
124 TRY(dif_flash_state_init(&flash));
125 TRY(dif_flash_ctrl_start_controller_init(&flash));
126 TRY(flash_ctrl_testutils_wait_for_init(&flash));
127 if (otp_flash_default_cfg != 0) {
129 TRY(dif_flash_ctrl_get_default_region_properties(&flash, &props));
130 props.
scramble_en = bitfield_field32_read(otp_flash_default_cfg,
131 FLASH_CTRL_OTP_FIELD_SCRAMBLING);
133 bitfield_field32_read(otp_flash_default_cfg, FLASH_CTRL_OTP_FIELD_ECC);
135 bitfield_field32_read(otp_flash_default_cfg, FLASH_CTRL_OTP_FIELD_HE);
136 TRY(dif_flash_ctrl_set_default_region_properties(&flash, props));
139#ifdef OPENTITAN_IS_EARLGREY
145status_t nvm_testutils_info_page_setup(nvm_info_page_t page,
146 nvm_page_perms_t perms,
147 nvm_page_cfg_t cfg) {
148 TRY_CHECK(page <
ARRAYSIZE(kPageMap),
"invalid page %d", page);
151 TRY(dif_flash_state_init(&flash));
154 .prog_en = perms.write,
155 .erase_en = perms.erase,
156 .scramble_en = cfg.scrambling,
158 .high_endurance_en = cfg.he,
160 TRY(info_page_set_props(&flash, &p, props));
164status_t nvm_testutils_info_page_set(nvm_info_page_t page,
165 nvm_page_perms_t perms,
166 nvm_page_cfg_t cfg) {
167 TRY_CHECK(page <
ARRAYSIZE(kPageMap),
"invalid page %d", page);
170 TRY(dif_flash_state_init(&flash));
172 TRY(info_page_get_props(&flash, &p, &props));
173 if (perms.read == kMultiBitBool4True) {
174 props.
rd_en = kMultiBitBool4True;
176 if (perms.write == kMultiBitBool4True) {
177 props.
prog_en = kMultiBitBool4True;
179 if (perms.erase == kMultiBitBool4True) {
180 props.
erase_en = kMultiBitBool4True;
182 if (cfg.scrambling == kMultiBitBool4True) {
185 if (cfg.ecc == kMultiBitBool4True) {
186 props.
ecc_en = kMultiBitBool4True;
188 if (cfg.he == kMultiBitBool4True) {
191 TRY(info_page_set_props(&flash, &p, props));
195status_t nvm_testutils_info_page_clear(nvm_info_page_t page,
196 nvm_page_perms_t perms,
197 nvm_page_cfg_t cfg) {
198 TRY_CHECK(page <
ARRAYSIZE(kPageMap),
"invalid page %d", page);
201 TRY(dif_flash_state_init(&flash));
203 TRY(info_page_get_props(&flash, &p, &props));
204 if (perms.read == kMultiBitBool4True) {
205 props.
rd_en = kMultiBitBool4False;
207 if (perms.write == kMultiBitBool4True) {
208 props.
prog_en = kMultiBitBool4False;
210 if (perms.erase == kMultiBitBool4True) {
211 props.
erase_en = kMultiBitBool4False;
213 if (cfg.scrambling == kMultiBitBool4True) {
216 if (cfg.ecc == kMultiBitBool4True) {
217 props.
ecc_en = kMultiBitBool4False;
219 if (cfg.he == kMultiBitBool4True) {
222 TRY(info_page_set_props(&flash, &p, props));
226status_t nvm_testutils_write_info_page(nvm_info_page_t page,
227 uint32_t byte_offset,
228 const uint32_t *data,
size_t word_count,
229 bool erase_before_write,
bool readback) {
230 TRY_CHECK(page <
ARRAYSIZE(kPageMap),
"invalid page %d", page);
232 uint32_t address = p.page_id * NVM_BYTES_PER_PAGE + byte_offset;
235 TRY(dif_flash_state_init(&flash));
237 if (erase_before_write) {
238 TRY(flash_ctrl_testutils_erase_and_write_page(
239 &flash, address, p.partition_id, data, kDifFlashCtrlPartitionTypeInfo,
242 TRY(flash_ctrl_testutils_write(&flash, address, p.partition_id, data,
243 kDifFlashCtrlPartitionTypeInfo, word_count));
246 uint32_t rb_buf[kNvmMaxWordCount];
247 size_t remaining = word_count;
248 size_t chunk_offset = 0;
249 while (remaining > 0) {
251 remaining < kNvmMaxWordCount ? remaining : kNvmMaxWordCount;
252 TRY(flash_ctrl_testutils_read(
253 &flash, address + chunk_offset *
sizeof(uint32_t), p.partition_id,
254 rb_buf, kDifFlashCtrlPartitionTypeInfo, chunk, 0));
256 memcmp(data + chunk_offset, rb_buf, chunk *
sizeof(uint32_t)) == 0,
257 "NVM write readback mismatch at page %d offset %d", page,
258 byte_offset + chunk_offset *
sizeof(uint32_t));
259 chunk_offset += chunk;
266status_t nvm_testutils_read_info_page(nvm_info_page_t page,
267 uint32_t byte_offset, uint32_t *data,
269 TRY_CHECK(page <
ARRAYSIZE(kPageMap),
"invalid page %d", page);
271 uint32_t address = p.page_id * NVM_BYTES_PER_PAGE + byte_offset;
274 TRY(dif_flash_state_init(&flash));
276 TRY(flash_ctrl_testutils_read(&flash, address, p.partition_id, data,
277 kDifFlashCtrlPartitionTypeInfo, word_count, 0));
281status_t nvm_testutils_info_page_lock(nvm_info_page_t page,
bool lock) {
285 TRY_CHECK(page <
ARRAYSIZE(kPageMap),
"invalid page %d", page);
288 TRY(dif_flash_state_init(&flash));
289 TRY(dif_flash_ctrl_lock_info_region_properties(&flash, phys_to_region(&p)));
293status_t nvm_testutils_data_region_setup(uint32_t region, uint32_t base,
294 uint32_t size, nvm_page_perms_t perms,
295 nvm_page_cfg_t cfg) {
297 TRY(dif_flash_state_init(&flash));
304 .prog_en = perms.write,
305 .erase_en = perms.erase,
306 .scramble_en = cfg.scrambling,
308 .high_endurance_en = cfg.he,
311 TRY(dif_flash_ctrl_set_data_region_properties(&flash, region, config));
312 TRY(dif_flash_ctrl_set_data_region_enablement(&flash, region,
317status_t nvm_testutils_data_region_lock(uint32_t region,
bool lock) {
322 TRY(dif_flash_state_init(&flash));
323 TRY(dif_flash_ctrl_lock_data_region_properties(&flash, region));
327status_t nvm_testutils_show_faults(
void) {
330 TRY(dif_flash_ctrl_init_state_from_dt(&flash, kFlashCtrlDt));
331 TRY(flash_ctrl_testutils_show_faults(&flash));
335status_t nvm_testutils_default_region_setup(nvm_page_perms_t perms,
336 nvm_page_cfg_t cfg) {
338 TRY(dif_flash_state_init(&flash));
341 .prog_en = perms.write,
342 .erase_en = perms.erase,
343 .scramble_en = cfg.scrambling,
345 .high_endurance_en = cfg.he,
347 TRY(dif_flash_ctrl_set_default_region_properties(&flash, props));