Software APIs
flash_ctrl.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/flash_ctrl.h"
6
7#include <assert.h>
8
9#include "hw/top/dt/flash_ctrl.h"
15#include "sw/device/lib/base/multibits.h"
17#include "sw/device/silicon_creator/lib/drivers/otp.h"
18#include "sw/device/silicon_creator/lib/error.h"
19
20#include "hw/top/flash_ctrl_regs.h"
21#include "hw/top/otp_ctrl_regs.h"
22
23static const dt_flash_ctrl_t kFlashCtrlDt = kDtFlashCtrl;
24
25// Values of `flash_ctrl_partition_t` constants must be distinct from each
26// other, and `kFlashCtrlRegionInfo* >> 1` should give the correct
27// CONTROL.INFO_SEL value.
28static_assert(kFlashCtrlPartitionData == 0,
29 "Incorrect enum value for kFlashCtrlRegionData");
30static_assert(kFlashCtrlPartitionInfo0 >> 1 == 0,
31 "Incorrect enum value for kFlashCtrlRegionInfo0");
32static_assert(kFlashCtrlPartitionInfo1 >> 1 == 1,
33 "Incorrect enum value for kFlashCtrlRegionInfo1");
34static_assert(kFlashCtrlPartitionInfo2 >> 1 == 2,
35 "Incorrect enum value for kFlashCtrlRegionInfo2");
36
37/**
38 * Base address of the flash_ctrl registers.
39 */
40static inline uint32_t flash_ctrl_core_base(void) {
41 return dt_flash_ctrl_primary_reg_block(kFlashCtrlDt);
42}
43
44/**
45 * Flash transaction parameters.
46 */
47typedef struct transaction_params {
48 /**
49 * Start address of a flash transaction.
50 *
51 * Must be the full byte address. For read and write operations flash
52 * controller will truncate to the closest 32-bit word aligned address. For
53 * page erases, the controller will truncate to the closest lower page aligned
54 * address. For bank erases, the controller will truncate to the closest lower
55 * bank aligned address.
56 */
57 uint32_t addr;
58 /**
59 * Operation type.
60 *
61 * Must be set to one of FLASH_CTRL_CONTROL_OP_VALUE_*.
62 */
63 uint32_t op_type;
64 /**
65 * Whether to erase a bank or a single page.
66 *
67 * Only applies to erase operations.
68 */
69 flash_ctrl_erase_type_t erase_type;
70 /**
71 * Partition to operate on.
72 */
73 flash_ctrl_partition_t partition;
74 /**
75 * Number of 32-bit words.
76 *
77 * Only applies to read and write operations.
78 */
79 uint32_t word_count;
80} transaction_params_t;
81
82/**
83 * Starts a flash transaction.
84 *
85 * @param params Transaction parameters, see `transaction_params_t`.
86 * @return The result of the operation.
87 */
88static void transaction_start(transaction_params_t params) {
89 // Set the address.
90 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_ADDR_REG_OFFSET,
91 params.addr);
92 // Configure flash_ctrl and start the transaction.
93 const bool is_info =
94 bitfield_bit32_read(params.partition, FLASH_CTRL_PARTITION_BIT_IS_INFO);
95 const uint32_t info_type = bitfield_field32_read(
96 params.partition, FLASH_CTRL_PARTITION_FIELD_INFO_TYPE);
97 bool bank_erase = true;
98 switch (launder32(params.erase_type)) {
99 case kFlashCtrlEraseTypeBank:
100 HARDENED_CHECK_EQ(params.erase_type, kFlashCtrlEraseTypeBank);
101 bank_erase = true;
102 break;
103 case kFlashCtrlEraseTypePage:
104 HARDENED_CHECK_EQ(params.erase_type, kFlashCtrlEraseTypePage);
105 bank_erase = false;
106 break;
107 default:
109 }
110 uint32_t reg = bitfield_bit32_write(0, FLASH_CTRL_CONTROL_START_BIT, true);
111 reg =
112 bitfield_field32_write(reg, FLASH_CTRL_CONTROL_OP_FIELD, params.op_type);
113 reg =
114 bitfield_bit32_write(reg, FLASH_CTRL_CONTROL_PARTITION_SEL_BIT, is_info);
115 reg =
116 bitfield_field32_write(reg, FLASH_CTRL_CONTROL_INFO_SEL_FIELD, info_type);
117 reg = bitfield_bit32_write(reg, FLASH_CTRL_CONTROL_ERASE_SEL_BIT, bank_erase);
118 reg = bitfield_field32_write(reg, FLASH_CTRL_CONTROL_NUM_FIELD,
119 params.word_count - 1);
120 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_CONTROL_REG_OFFSET, reg);
121}
122
123/**
124 * Copies `word_count` words from the read FIFO to the given buffer.
125 *
126 * Large reads may create back pressure.
127 *
128 * @param word_count Number of words to read from the FIFO.
129 * @param[out] data Output buffer.
130 */
131static void fifo_read(size_t word_count, void *data) {
132 size_t i = 0, r = word_count - 1;
133 for (; launder32(i) < word_count && launder32(r) < word_count; ++i, --r) {
134 write_32(
135 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_RD_FIFO_REG_OFFSET),
136 data);
137 data = (char *)data + sizeof(uint32_t);
138 }
139 HARDENED_CHECK_EQ(i, word_count);
140 HARDENED_CHECK_EQ(r, SIZE_MAX);
141}
142
143/**
144 * Copies `word_count` words from the given buffer to the program FIFO.
145 *
146 * Large writes may create back pressure.
147 *
148 * @param word_count Number of words to write to the FIFO.
149 * @param data Input buffer.
150 */
151static void fifo_write(size_t word_count, const void *data) {
152 size_t i = 0, r = word_count - 1;
153 for (; launder32(i) < word_count && launder32(r) < word_count; ++i, --r) {
154 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_PROG_FIFO_REG_OFFSET,
155 read_32(data));
156 data = (const char *)data + sizeof(uint32_t);
157 }
158 HARDENED_CHECK_EQ(i, word_count);
159 HARDENED_CHECK_EQ(r, SIZE_MAX);
160}
161
162/**
163 * Blocks until the current flash transaction is complete.
164 *
165 * @param error Error code to return in case of a flash controller error.
166 * @return The result of the operation.
167 */
169static rom_error_t wait_for_done(rom_error_t error) {
170 uint32_t op_status;
171 do {
172 op_status = abs_mmio_read32(flash_ctrl_core_base() +
173 FLASH_CTRL_OP_STATUS_REG_OFFSET);
174 } while (!bitfield_bit32_read(op_status, FLASH_CTRL_OP_STATUS_DONE_BIT));
175 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_OP_STATUS_REG_OFFSET,
176 0u);
177
178 if (bitfield_bit32_read(op_status, FLASH_CTRL_OP_STATUS_ERR_BIT)) {
179 return error;
180 }
181 return kErrorOk;
182}
183
184/**
185 * Writes data to the given partition.
186 *
187 * @param addr Full byte address to write to.
188 * @param partition The partition to write to.
189 * @param word_count Number of bus words to write.
190 * @param data Data to write.
191 * @param error Error code to return in case of a flash controller error.
192 * @return Result of the operation.
193 */
195static rom_error_t write(uint32_t addr, flash_ctrl_partition_t partition,
196 uint32_t word_count, const void *data,
197 rom_error_t error) {
198 enum {
199 kWindowWordCount = FLASH_CTRL_PARAM_REG_BUS_PGM_RES_BYTES / sizeof(uint32_t)
200 };
201
202 // Find the number of words that can be written in the first window.
203 uint32_t window_word_count =
204 kWindowWordCount - ((addr / sizeof(uint32_t)) % kWindowWordCount);
205 while (word_count > 0) {
206 // Program operations can't cross window boundaries.
207 window_word_count =
208 word_count < window_word_count ? word_count : window_word_count;
209
210 transaction_start((transaction_params_t){
211 .addr = addr,
212 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_PROG,
213 .partition = partition,
214 .word_count = window_word_count,
215 // Does not apply to program transactions.
216 .erase_type = kFlashCtrlEraseTypePage,
217 });
218
219 fifo_write(window_word_count, data);
220 RETURN_IF_ERROR(wait_for_done(error));
221
222 addr += window_word_count * sizeof(uint32_t);
223 data = (const char *)data + window_word_count * sizeof(uint32_t);
224 word_count -= window_word_count;
225 window_word_count = kWindowWordCount;
226 }
227
228 return kErrorOk;
229}
230
231void flash_ctrl_init(void) {
233 kFlashCtrlSecMmioInit,
234 kFlashCtrlSecMmioDataDefaultCfgSet + 2 * kFlashCtrlSecMmioInfoCfgSet);
235
236 // Set `HW_INFO_CFG_OVERRIDE` register if needed. This must be done before
237 // initializing the flash_ctrl.
238 uint32_t reg_val = FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL;
239 uint32_t otp_val = otp_read32(
240 OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_HW_INFO_CFG_OVERRIDE_OFFSET);
241 multi_bit_bool_t scramble_dis = bitfield_field32_read(
242 otp_val, FLASH_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS);
243 if (scramble_dis == kMultiBitBool4True) {
244 reg_val = bitfield_field32_write(
245 reg_val, FLASH_CTRL_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS_FIELD,
246 scramble_dis);
247 }
248 multi_bit_bool_t ecc_dis = bitfield_field32_read(
249 otp_val, FLASH_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_ECC_DIS);
250 if (ecc_dis == kMultiBitBool4True) {
251 reg_val = bitfield_field32_write(
252 reg_val, FLASH_CTRL_HW_INFO_CFG_OVERRIDE_ECC_DIS_FIELD, ecc_dis);
253 }
254 if (reg_val != FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL) {
256 flash_ctrl_core_base() + FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_OFFSET,
257 reg_val);
258 }
259
260 // Initialize the flash controller.
261 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_INIT_REG_OFFSET,
262 bitfield_bit32_write(0, FLASH_CTRL_INIT_VAL_BIT, true));
263 // Configure default scrambling, ECC, and HE settings for the data partition.
264 otp_val =
265 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET);
266 flash_ctrl_cfg_t data_default_cfg = {
267 .scrambling =
268 bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_SCRAMBLING),
269 .ecc = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_ECC),
270 .he = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_HE),
271 };
272 flash_ctrl_data_default_cfg_set(data_default_cfg);
273 // Configure scrambling, ECC, and HE for `boot_data` pages.
274 flash_ctrl_cfg_t boot_data_cfg = flash_ctrl_boot_data_cfg_get();
275 flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageBootData0, boot_data_cfg);
276 flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageBootData1, boot_data_cfg);
277}
278
279void flash_ctrl_disable(void) {
280 // Setting DIS (rw0c) to a value other than 5 will disable flash permanently.
281 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_DIS_REG_OFFSET, 0);
282}
283
284void flash_ctrl_status_get(flash_ctrl_status_t *status) {
285 // Read flash controller status.
286 uint32_t fc_status =
287 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_STATUS_REG_OFFSET);
288
289 // Extract flash controller status bits.
290 status->rd_full =
291 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_RD_FULL_BIT);
292 status->rd_empty =
293 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_RD_EMPTY_BIT);
294 status->prog_full =
295 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_PROG_FULL_BIT);
296 status->prog_empty =
297 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_PROG_EMPTY_BIT);
298 status->init_wip =
299 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_INIT_WIP_BIT);
300}
301
302void flash_ctrl_error_code_get(flash_ctrl_error_code_t *error_code) {
303 // Read flash error code.
304 uint32_t code =
305 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_ERR_CODE_REG_OFFSET);
306
307 // Extract flash controller error code bits.
308 error_code->macro_err =
309 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_MACRO_ERR_BIT);
310 error_code->update_err =
311 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_UPDATE_ERR_BIT);
312 error_code->prog_type_err =
313 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT);
314 error_code->prog_win_err =
315 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_WIN_ERR_BIT);
316 error_code->prog_err =
317 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_ERR_BIT);
318 error_code->rd_err =
319 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_RD_ERR_BIT);
320 error_code->mp_err =
321 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_MP_ERR_BIT);
322 error_code->op_err =
323 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_OP_ERR_BIT);
324}
325
326rom_error_t flash_ctrl_data_read(uint32_t addr, uint32_t word_count,
327 void *data) {
328 transaction_start((transaction_params_t){
329 .addr = addr,
330 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
331 .partition = kFlashCtrlPartitionData,
332 .word_count = word_count,
333 // Does not apply to read transactions.
334 .erase_type = kFlashCtrlEraseTypePage,
335 });
336 fifo_read(word_count, data);
337 return wait_for_done(kErrorFlashCtrlDataRead);
338}
339
340rom_error_t flash_ctrl_info_read(const flash_ctrl_info_page_t *info_page,
341 uint32_t offset, uint32_t word_count,
342 void *data) {
343 transaction_start((transaction_params_t){
344 .addr = info_page->base_addr + offset,
345 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
346 .partition = kFlashCtrlPartitionInfo0,
347 .word_count = word_count,
348 // Does not apply to read transactions.
349 .erase_type = kFlashCtrlEraseTypePage,
350 });
351 fifo_read(word_count, data);
352 return wait_for_done(kErrorFlashCtrlInfoRead);
353}
354
355rom_error_t flash_ctrl_info_read_zeros_on_read_error(
356 const flash_ctrl_info_page_t *info_page, uint32_t offset,
357 uint32_t word_count, void *data) {
358 rom_error_t err = flash_ctrl_info_read(info_page, offset, word_count, data);
359 if (err != kErrorOk) {
360 flash_ctrl_error_code_t flash_ctrl_err_code;
361 flash_ctrl_error_code_get(&flash_ctrl_err_code);
362 if (flash_ctrl_err_code.rd_err) {
363 // If we encountered a read error, return all 0s.
364 memset(data, 0, word_count * sizeof(uint32_t));
365 return kErrorOk;
366 }
367 }
368 return err;
369}
370
371rom_error_t flash_ctrl_data_write(uint32_t addr, uint32_t word_count,
372 const void *data) {
373 return write(addr, kFlashCtrlPartitionData, word_count, data,
374 kErrorFlashCtrlDataWrite);
375}
376
377rom_error_t flash_ctrl_info_write(const flash_ctrl_info_page_t *info_page,
378 uint32_t offset, uint32_t word_count,
379 const void *data) {
380 const uint32_t addr = info_page->base_addr + offset;
381 return write(addr, kFlashCtrlPartitionInfo0, word_count, data,
382 kErrorFlashCtrlInfoWrite);
383}
384
385rom_error_t flash_ctrl_data_erase(uint32_t addr,
386 flash_ctrl_erase_type_t erase_type) {
387 transaction_start((transaction_params_t){
388 .addr = addr,
389 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
390 .erase_type = erase_type,
391 .partition = kFlashCtrlPartitionData,
392 // Does not apply to erase transactions.
393 .word_count = 1,
394 });
395 return wait_for_done(kErrorFlashCtrlDataErase);
396}
397
398rom_error_t flash_ctrl_data_erase_verify(uint32_t addr,
399 flash_ctrl_erase_type_t erase_type) {
400 static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_BANK) == 1,
401 "Bytes per bank must be a power of two.");
402 static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_PAGE) == 1,
403 "Bytes per page must be a power of two.");
404
405 size_t byte_count = 0;
406 rom_error_t error = kErrorFlashCtrlDataEraseVerify;
407 switch (launder32(erase_type)) {
408 case kFlashCtrlEraseTypeBank:
409 HARDENED_CHECK_EQ(erase_type, kFlashCtrlEraseTypeBank);
410 byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
411 error = kErrorOk ^ (byte_count - 1);
412 break;
413 case kFlashCtrlEraseTypePage:
414 HARDENED_CHECK_EQ(erase_type, kFlashCtrlEraseTypePage);
415 byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
416 error = kErrorOk ^ (byte_count - 1);
417 break;
418 default:
420 byte_count = 0U;
421 break;
422 }
423
424 // Truncate to the closest lower bank/page aligned address.
425 addr &= ~byte_count + 1;
426 uint32_t mask = kFlashCtrlErasedWord;
427 size_t i = 0, r = byte_count - 1;
428 uint32_t mem_base =
429 dt_flash_ctrl_memory_base(kFlashCtrlDt, kDtFlashCtrlMemoryMem);
430 for (; launder32(i) < byte_count && launder32(r) < byte_count;
431 i += sizeof(uint32_t), r -= sizeof(uint32_t)) {
432 uint32_t word = abs_mmio_read32(mem_base + addr + i);
433 mask &= word;
434 error &= word;
435 }
436 HARDENED_CHECK_EQ(i, byte_count);
437 HARDENED_CHECK_EQ(r, SIZE_MAX);
438
439 if (launder32(mask) == kFlashCtrlErasedWord) {
440 HARDENED_CHECK_EQ(mask, kFlashCtrlErasedWord);
441 return error ^ (byte_count - 1);
442 }
443
444 return kErrorFlashCtrlDataEraseVerify;
445}
446
447rom_error_t flash_ctrl_info_erase(const flash_ctrl_info_page_t *info_page,
448 flash_ctrl_erase_type_t erase_type) {
449 transaction_start((transaction_params_t){
450 .addr = info_page->base_addr,
451 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
452 .erase_type = erase_type,
453 .partition = kFlashCtrlPartitionInfo0,
454 // Does not apply to erase transactions.
455 .word_count = 1,
456 });
457 return wait_for_done(kErrorFlashCtrlInfoErase);
458}
459
460void flash_ctrl_exec_set(uint32_t exec_val) {
461 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioExecSet, 1);
462 sec_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_EXEC_REG_OFFSET,
463 exec_val);
464}
465
466void flash_ctrl_data_default_perms_set(flash_ctrl_perms_t perms) {
467 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataDefaultPermsSet, 1);
468
469 // Read first to preserve ECC, scrambling, and high endurance bits.
470 uint32_t reg = sec_mmio_read32(flash_ctrl_core_base() +
471 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
472 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_RD_EN_FIELD,
473 perms.read);
474 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_PROG_EN_FIELD,
475 perms.write);
476 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_ERASE_EN_FIELD,
477 perms.erase);
479 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
480}
481
482void flash_ctrl_info_perms_set(const flash_ctrl_info_page_t *info_page,
483 flash_ctrl_perms_t perms) {
484 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioInfoPermsSet, 1);
485
486 // Read first to preserve ECC, scrambling, and high endurance bits.
487 uint32_t reg =
488 sec_mmio_read32(flash_ctrl_core_base() + info_page->cfg_offset);
489 reg = bitfield_field32_write(
490 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
491 reg = bitfield_field32_write(
492 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_RD_EN_0_FIELD, perms.read);
493 reg = bitfield_field32_write(
494 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_PROG_EN_0_FIELD, perms.write);
495 reg = bitfield_field32_write(
496 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ERASE_EN_0_FIELD, perms.erase);
497 sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_offset, reg);
498}
499
500void flash_ctrl_data_default_cfg_set(flash_ctrl_cfg_t cfg) {
501 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataDefaultCfgSet, 1);
502
503 // Read first to preserve permission bits.
504 uint32_t reg = sec_mmio_read32(flash_ctrl_core_base() +
505 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
506 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD,
507 cfg.scrambling);
508 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_ECC_EN_FIELD,
509 cfg.ecc);
510 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_HE_EN_FIELD,
511 cfg.he);
513 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
514}
515
516flash_ctrl_cfg_t flash_ctrl_data_default_cfg_get(void) {
517 const uint32_t default_region = sec_mmio_read32(
518 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
519 return (flash_ctrl_cfg_t){
520 .scrambling = bitfield_field32_read(
521 default_region, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD),
522 .ecc = bitfield_field32_read(default_region,
523 FLASH_CTRL_DEFAULT_REGION_ECC_EN_FIELD),
524 .he = bitfield_field32_read(default_region,
525 FLASH_CTRL_DEFAULT_REGION_HE_EN_FIELD),
526 };
527}
528
529flash_ctrl_cfg_t flash_ctrl_boot_data_cfg_get(void) {
530 uint32_t otp_val =
531 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_INFO_BOOT_DATA_CFG_OFFSET);
532 return (flash_ctrl_cfg_t){
533 .scrambling =
534 bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_SCRAMBLING),
535 .ecc = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_ECC),
536 .he = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_HE),
537 };
538}
539
540void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,
541 uint32_t page_offset, uint32_t num_pages,
542 flash_ctrl_perms_t perms,
543 flash_ctrl_cfg_t cfg,
544 hardened_bool_t lock) {
545 const uint32_t kBase = flash_ctrl_core_base();
546 HARDENED_CHECK_GE(region, 0);
547 HARDENED_CHECK_LT(region, 8);
548 region *= sizeof(uint32_t);
549
550 // Reset the region's configuration via the MP_REGION_CFG_${region} register.
551 // This temporarily disables memory protection for the region.
552 //
553 // We use abs_mmio here because we're going to re-write this value later and
554 // the intermediate REG_RESVAL should not be considered a valid data pattern
555 // in this register when we perfom a sec_mmio check.
556 abs_mmio_write32(kBase + FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET + region,
557 FLASH_CTRL_MP_REGION_CFG_0_REG_RESVAL);
558
559 // Set the region's bounds in the MP_REGION_${region} register.
560 uint32_t mp_region = FLASH_CTRL_MP_REGION_0_REG_RESVAL;
561 mp_region = bitfield_field32_write(
562 mp_region, FLASH_CTRL_MP_REGION_0_BASE_0_FIELD, page_offset);
563 mp_region = bitfield_field32_write(
564 mp_region, FLASH_CTRL_MP_REGION_0_SIZE_0_FIELD, num_pages);
565 sec_mmio_write32(kBase + FLASH_CTRL_MP_REGION_0_REG_OFFSET + region,
566 mp_region);
567
568 // Write the new value of MP_REGION_CFG_${region}.
569 uint32_t mp_region_cfg = FLASH_CTRL_MP_REGION_CFG_0_REG_RESVAL;
570 mp_region_cfg = bitfield_field32_write(
571 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_HE_EN_0_FIELD, cfg.he);
572 mp_region_cfg = bitfield_field32_write(
573 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_ECC_EN_0_FIELD, cfg.ecc);
574 mp_region_cfg = bitfield_field32_write(
575 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD,
576 cfg.scrambling);
577 mp_region_cfg = bitfield_field32_write(
578 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_ERASE_EN_0_FIELD, perms.erase);
579 mp_region_cfg = bitfield_field32_write(
580 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_PROG_EN_0_FIELD, perms.write);
581 mp_region_cfg = bitfield_field32_write(
582 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_RD_EN_0_FIELD, perms.read);
583 mp_region_cfg = bitfield_field32_write(
584 mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4True);
585
586 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataRegionProtect, 1);
587 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataRegionProtectLock, 1);
588 sec_mmio_write32(kBase + FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET + region,
589 mp_region_cfg);
590 if (lock != kHardenedBoolFalse) {
591 sec_mmio_write32(kBase + FLASH_CTRL_REGION_CFG_REGWEN_0_REG_OFFSET + region,
592 0);
593 }
594}
595
596void flash_ctrl_info_cfg_set(const flash_ctrl_info_page_t *info_page,
597 flash_ctrl_cfg_t cfg) {
598 SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioInfoCfgSet, 1);
599
600 // Read first to preserve permission bits.
601 uint32_t reg =
602 sec_mmio_read32(flash_ctrl_core_base() + info_page->cfg_offset);
603 reg = bitfield_field32_write(
604 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
605 reg = bitfield_field32_write(
606 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD,
607 cfg.scrambling);
608 reg = bitfield_field32_write(
609 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ECC_EN_0_FIELD, cfg.ecc);
610 reg = bitfield_field32_write(
611 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_HE_EN_0_FIELD, cfg.he);
612 sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_offset, reg);
613}
614
615void flash_ctrl_info_cfg_lock(const flash_ctrl_info_page_t *info_page) {
616 sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_wen_offset, 0);
617}
618
619void flash_ctrl_info_page_lockdown(const flash_ctrl_info_page_t *info_page) {
620 sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_offset, 0);
621 sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_wen_offset, 0);
622}
623
624void flash_ctrl_bank_erase_perms_set(hardened_bool_t enable) {
625 uint32_t reg = 0;
626 switch (launder32(enable)) {
629 reg = bitfield_bit32_write(
630 0, FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_0_BIT, true);
631 reg = bitfield_bit32_write(
632 reg, FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_1_BIT, true);
633 break;
636 reg = 0U;
637 break;
638 default:
640 reg = 0U;
641 break;
642 }
644 flash_ctrl_core_base() + FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET, reg);
645}