5#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
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"
20#include "hw/top/flash_ctrl_regs.h"
21#include "hw/top/otp_ctrl_regs.h"
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");
40static inline uint32_t flash_ctrl_core_base(
void) {
41 return dt_flash_ctrl_primary_reg_block(kFlashCtrlDt);
80} transaction_params_t;
88static void transaction_start(transaction_params_t params) {
90 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_ADDR_REG_OFFSET,
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;
99 case kFlashCtrlEraseTypeBank:
103 case kFlashCtrlEraseTypePage:
110 uint32_t reg = bitfield_bit32_write(0, FLASH_CTRL_CONTROL_START_BIT,
true);
112 bitfield_field32_write(reg, FLASH_CTRL_CONTROL_OP_FIELD, params.
op_type);
114 bitfield_bit32_write(reg, FLASH_CTRL_CONTROL_PARTITION_SEL_BIT, is_info);
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,
120 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_CONTROL_REG_OFFSET, reg);
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) {
135 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_RD_FIFO_REG_OFFSET),
137 data = (
char *)data +
sizeof(uint32_t);
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,
156 data = (
const char *)data +
sizeof(uint32_t);
169static rom_error_t wait_for_done(rom_error_t error) {
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,
178 if (bitfield_bit32_read(op_status, FLASH_CTRL_OP_STATUS_ERR_BIT)) {
195static rom_error_t write(uint32_t addr, flash_ctrl_partition_t partition,
196 uint32_t word_count,
const void *data,
199 kWindowWordCount = FLASH_CTRL_PARAM_REG_BUS_PGM_RES_BYTES /
sizeof(uint32_t)
203 uint32_t window_word_count =
204 kWindowWordCount - ((addr /
sizeof(uint32_t)) % kWindowWordCount);
205 while (word_count > 0) {
208 word_count < window_word_count ? word_count : window_word_count;
210 transaction_start((transaction_params_t){
212 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_PROG,
213 .partition = partition,
214 .word_count = window_word_count,
216 .erase_type = kFlashCtrlEraseTypePage,
219 fifo_write(window_word_count, data);
220 RETURN_IF_ERROR(wait_for_done(error));
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;
231void flash_ctrl_init(
void) {
233 kFlashCtrlSecMmioInit,
234 kFlashCtrlSecMmioDataDefaultCfgSet + 2 * kFlashCtrlSecMmioInfoCfgSet);
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,
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);
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,
261 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_INIT_REG_OFFSET,
262 bitfield_bit32_write(0, FLASH_CTRL_INIT_VAL_BIT,
true));
265 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET);
266 flash_ctrl_cfg_t data_default_cfg = {
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),
272 flash_ctrl_data_default_cfg_set(data_default_cfg);
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);
279void flash_ctrl_disable(
void) {
281 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_DIS_REG_OFFSET, 0);
284void flash_ctrl_status_get(flash_ctrl_status_t *
status) {
287 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_STATUS_REG_OFFSET);
291 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_RD_FULL_BIT);
293 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_RD_EMPTY_BIT);
295 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_PROG_FULL_BIT);
297 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_PROG_EMPTY_BIT);
299 bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_INIT_WIP_BIT);
302void flash_ctrl_error_code_get(flash_ctrl_error_code_t *error_code) {
305 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_ERR_CODE_REG_OFFSET);
309 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_MACRO_ERR_BIT);
311 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_UPDATE_ERR_BIT);
313 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT);
315 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_WIN_ERR_BIT);
317 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_ERR_BIT);
319 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_RD_ERR_BIT);
321 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_MP_ERR_BIT);
323 bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_OP_ERR_BIT);
326rom_error_t flash_ctrl_data_read(uint32_t addr, uint32_t word_count,
328 transaction_start((transaction_params_t){
330 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
331 .partition = kFlashCtrlPartitionData,
332 .word_count = word_count,
334 .erase_type = kFlashCtrlEraseTypePage,
336 fifo_read(word_count, data);
337 return wait_for_done(kErrorFlashCtrlDataRead);
340rom_error_t flash_ctrl_info_read(
const flash_ctrl_info_page_t *info_page,
341 uint32_t offset, uint32_t word_count,
343 transaction_start((transaction_params_t){
345 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
346 .partition = kFlashCtrlPartitionInfo0,
347 .word_count = word_count,
349 .erase_type = kFlashCtrlEraseTypePage,
351 fifo_read(word_count, data);
352 return wait_for_done(kErrorFlashCtrlInfoRead);
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) {
364 memset(data, 0, word_count *
sizeof(uint32_t));
371rom_error_t flash_ctrl_data_write(uint32_t addr, uint32_t word_count,
373 return write(addr, kFlashCtrlPartitionData, word_count, data,
374 kErrorFlashCtrlDataWrite);
377rom_error_t flash_ctrl_info_write(
const flash_ctrl_info_page_t *info_page,
378 uint32_t offset, uint32_t word_count,
380 const uint32_t addr = info_page->
base_addr + offset;
381 return write(addr, kFlashCtrlPartitionInfo0, word_count, data,
382 kErrorFlashCtrlInfoWrite);
385rom_error_t flash_ctrl_data_erase(uint32_t addr,
386 flash_ctrl_erase_type_t erase_type) {
387 transaction_start((transaction_params_t){
389 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
390 .erase_type = erase_type,
391 .partition = kFlashCtrlPartitionData,
395 return wait_for_done(kErrorFlashCtrlDataErase);
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.");
405 size_t byte_count = 0;
406 rom_error_t error = kErrorFlashCtrlDataEraseVerify;
407 switch (launder32(erase_type)) {
408 case kFlashCtrlEraseTypeBank:
410 byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
411 error = kErrorOk ^ (byte_count - 1);
413 case kFlashCtrlEraseTypePage:
415 byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
416 error = kErrorOk ^ (byte_count - 1);
425 addr &= ~byte_count + 1;
426 uint32_t mask = kFlashCtrlErasedWord;
427 size_t i = 0, r = byte_count - 1;
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);
439 if (launder32(mask) == kFlashCtrlErasedWord) {
441 return error ^ (byte_count - 1);
444 return kErrorFlashCtrlDataEraseVerify;
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){
451 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
452 .erase_type = erase_type,
453 .partition = kFlashCtrlPartitionInfo0,
457 return wait_for_done(kErrorFlashCtrlInfoErase);
460void flash_ctrl_exec_set(uint32_t exec_val) {
466void flash_ctrl_data_default_perms_set(flash_ctrl_perms_t perms) {
471 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
472 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_RD_EN_FIELD,
474 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_PROG_EN_FIELD,
476 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_ERASE_EN_FIELD,
479 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
482void flash_ctrl_info_perms_set(
const flash_ctrl_info_page_t *info_page,
483 flash_ctrl_perms_t perms) {
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);
500void flash_ctrl_data_default_cfg_set(flash_ctrl_cfg_t cfg) {
505 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
506 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD,
508 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_ECC_EN_FIELD,
510 reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_HE_EN_FIELD,
513 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
516flash_ctrl_cfg_t flash_ctrl_data_default_cfg_get(
void) {
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),
529flash_ctrl_cfg_t flash_ctrl_boot_data_cfg_get(
void) {
531 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_INFO_BOOT_DATA_CFG_OFFSET);
532 return (flash_ctrl_cfg_t){
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),
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,
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);
556 abs_mmio_write32(kBase + FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET + region,
557 FLASH_CTRL_MP_REGION_CFG_0_REG_RESVAL);
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);
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,
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);
591 sec_mmio_write32(kBase + FLASH_CTRL_REGION_CFG_REGWEN_0_REG_OFFSET + region,
596void flash_ctrl_info_cfg_set(
const flash_ctrl_info_page_t *info_page,
597 flash_ctrl_cfg_t cfg) {
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,
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);
615void flash_ctrl_info_cfg_lock(
const flash_ctrl_info_page_t *info_page) {
619void flash_ctrl_info_page_lockdown(
const flash_ctrl_info_page_t *info_page) {
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);
644 flash_ctrl_core_base() + FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET, reg);