5 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
9 #include "dt/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 "flash_ctrl_regs.h"
21 #include "otp_ctrl_regs.h"
23 static const dt_flash_ctrl_t kFlashCtrlDt = kDtFlashCtrl;
28 static_assert(kFlashCtrlPartitionData == 0,
29 "Incorrect enum value for kFlashCtrlRegionData");
30 static_assert(kFlashCtrlPartitionInfo0 >> 1 == 0,
31 "Incorrect enum value for kFlashCtrlRegionInfo0");
32 static_assert(kFlashCtrlPartitionInfo1 >> 1 == 1,
33 "Incorrect enum value for kFlashCtrlRegionInfo1");
34 static_assert(kFlashCtrlPartitionInfo2 >> 1 == 2,
35 "Incorrect enum value for kFlashCtrlRegionInfo2");
40 static inline uint32_t flash_ctrl_core_base(
void) {
41 return dt_flash_ctrl_primary_reg_block(kFlashCtrlDt);
90 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_ADDR_REG_OFFSET,
96 params.
partition, FLASH_CTRL_PARTITION_FIELD_INFO_TYPE);
97 bool bank_erase =
true;
99 case kFlashCtrlEraseTypeBank:
103 case kFlashCtrlEraseTypePage:
120 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_CONTROL_REG_OFFSET, reg);
131 static 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);
151 static 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);
169 static 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);
175 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_OP_STATUS_REG_OFFSET,
195 static 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;
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;
244 void flash_ctrl_init(
void) {
246 kFlashCtrlSecMmioInit,
247 kFlashCtrlSecMmioDataDefaultCfgSet + 2 * kFlashCtrlSecMmioInfoCfgSet);
251 uint32_t reg_val = FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL;
252 uint32_t otp_val = otp_read32(
253 OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_HW_INFO_CFG_OVERRIDE_OFFSET);
255 otp_val, FLASH_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS);
256 if (scramble_dis == kMultiBitBool4True) {
258 reg_val, FLASH_CTRL_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS_FIELD,
262 otp_val, FLASH_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_ECC_DIS);
263 if (ecc_dis == kMultiBitBool4True) {
265 reg_val, FLASH_CTRL_HW_INFO_CFG_OVERRIDE_ECC_DIS_FIELD, ecc_dis);
267 if (reg_val != FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL) {
269 flash_ctrl_core_base() + FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_OFFSET,
274 abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_INIT_REG_OFFSET,
278 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET);
285 flash_ctrl_data_default_cfg_set(data_default_cfg);
288 otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_INFO_BOOT_DATA_CFG_OFFSET);
295 flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageBootData0, boot_data_cfg);
296 flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageBootData1, boot_data_cfg);
302 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_STATUS_REG_OFFSET);
320 abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_ERR_CODE_REG_OFFSET);
341 rom_error_t flash_ctrl_data_read(uint32_t addr, uint32_t word_count,
345 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
346 .partition = kFlashCtrlPartitionData,
347 .word_count = word_count,
349 .erase_type = kFlashCtrlEraseTypePage,
351 fifo_read(word_count, data);
352 return wait_for_done(kErrorFlashCtrlDataRead);
356 uint32_t offset, uint32_t word_count,
360 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
361 .partition = kFlashCtrlPartitionInfo0,
362 .word_count = word_count,
364 .erase_type = kFlashCtrlEraseTypePage,
366 fifo_read(word_count, data);
367 return wait_for_done(kErrorFlashCtrlInfoRead);
370 rom_error_t flash_ctrl_info_read_zeros_on_read_error(
372 uint32_t word_count,
void *data) {
373 rom_error_t err = flash_ctrl_info_read(info_page, offset, word_count, data);
374 if (err != kErrorOk) {
376 flash_ctrl_error_code_get(&flash_ctrl_err_code);
377 if (flash_ctrl_err_code.
rd_err) {
379 memset(data, 0, word_count *
sizeof(uint32_t));
387 abs_mmio_write32(flash_ctrl_core_base() + info_page->
cfg_wen_offset, 0);
390 rom_error_t flash_ctrl_data_write(uint32_t addr, uint32_t word_count,
392 return write(addr, kFlashCtrlPartitionData, word_count, data,
393 kErrorFlashCtrlDataWrite);
397 uint32_t offset, uint32_t word_count,
399 const uint32_t addr = info_page->
base_addr + offset;
400 return write(addr, kFlashCtrlPartitionInfo0, word_count, data,
401 kErrorFlashCtrlInfoWrite);
404 rom_error_t flash_ctrl_data_erase(uint32_t addr,
405 flash_ctrl_erase_type_t erase_type) {
408 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
409 .erase_type = erase_type,
410 .partition = kFlashCtrlPartitionData,
414 return wait_for_done(kErrorFlashCtrlDataErase);
417 rom_error_t flash_ctrl_data_erase_verify(uint32_t addr,
418 flash_ctrl_erase_type_t erase_type) {
419 static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_BANK) == 1,
420 "Bytes per bank must be a power of two.");
421 static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_PAGE) == 1,
422 "Bytes per page must be a power of two.");
424 size_t byte_count = 0;
425 rom_error_t error = kErrorFlashCtrlDataEraseVerify;
426 switch (launder32(erase_type)) {
427 case kFlashCtrlEraseTypeBank:
429 byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
430 error = kErrorOk ^ (byte_count - 1);
432 case kFlashCtrlEraseTypePage:
434 byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
435 error = kErrorOk ^ (byte_count - 1);
444 addr &= ~byte_count + 1;
445 uint32_t mask = kFlashCtrlErasedWord;
446 size_t i = 0, r = byte_count - 1;
448 dt_flash_ctrl_reg_block(kFlashCtrlDt, kDtFlashCtrlRegBlockMem);
449 for (; launder32(i) < byte_count && launder32(r) < byte_count;
450 i +=
sizeof(uint32_t), r -=
sizeof(uint32_t)) {
451 uint32_t word = abs_mmio_read32(mem_base + addr + i);
458 if (launder32(mask) == kFlashCtrlErasedWord) {
460 return error ^ (byte_count - 1);
463 return kErrorFlashCtrlDataEraseVerify;
467 flash_ctrl_erase_type_t erase_type) {
470 .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
471 .erase_type = erase_type,
472 .partition = kFlashCtrlPartitionInfo0,
476 return wait_for_done(kErrorFlashCtrlInfoErase);
479 void flash_ctrl_exec_set(uint32_t exec_val) {
490 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
498 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
509 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
511 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_RD_EN_0_FIELD, perms.
read);
513 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_PROG_EN_0_FIELD, perms.
write);
515 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ERASE_EN_0_FIELD, perms.
erase);
524 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
532 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
537 flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
540 default_region, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD),
542 FLASH_CTRL_DEFAULT_REGION_ECC_EN_FIELD),
544 FLASH_CTRL_DEFAULT_REGION_HE_EN_FIELD),
550 #define FLASH_CTRL_MP_REGIONS(X) \
562 static void flash_ctrl_mp_region_write(flash_ctrl_region_index_t region,
563 uint32_t page_offset,
564 uint32_t num_pages) {
565 #define FLASH_CTRL_MP_REGION_WRITE_(region_macro_arg) \
566 case ((region_macro_arg)): { \
567 HARDENED_CHECK_EQ(region, (region_macro_arg)); \
568 uint32_t mp_region = FLASH_CTRL_MP_REGION_##region_macro_arg##_REG_RESVAL; \
570 mp_region = bitfield_field32_write( \
572 FLASH_CTRL_MP_REGION_##region_macro_arg##_BASE_##region_macro_arg##_FIELD, \
575 mp_region = bitfield_field32_write( \
577 FLASH_CTRL_MP_REGION_##region_macro_arg##_SIZE_##region_macro_arg##_FIELD, \
580 sec_mmio_write32(flash_ctrl_core_base() + \
581 FLASH_CTRL_MP_REGION_##region_macro_arg##_REG_OFFSET, \
586 switch (launder32(region)) {
587 FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_WRITE_)
592 #undef FLASH_CTRL_MP_REGION_WRITE_
597 static void flash_ctrl_mp_region_cfg_reset(flash_ctrl_region_index_t region) {
598 #define FLASH_CTRL_MP_REGION_CFG_RESET_(region_macro_arg) \
599 case ((region_macro_arg)): { \
600 HARDENED_CHECK_EQ(region, (region_macro_arg)); \
602 (FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL & \
603 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_EN_##region_macro_arg##_MASK) == \
604 kMultiBitBool4False, \
605 "FLASH_CTRL_MP_REGION_CFG_" #region_macro_arg \
606 "'s reset value should disable the region"); \
609 flash_ctrl_core_base() + \
610 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \
611 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL); \
615 switch (launder32(region)) {
616 FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_CFG_RESET_)
621 #undef FLASH_CTRL_MP_CFG_RESET_
626 static void flash_ctrl_mp_region_cfg_write(flash_ctrl_region_index_t region,
631 #define FLASH_CTRL_MP_REGION_CFG_WRITE_(region_macro_arg) \
632 case ((region_macro_arg)): { \
633 HARDENED_CHECK_EQ(region, (region_macro_arg)); \
634 uint32_t mp_region_cfg = \
635 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL; \
636 mp_region_cfg = bitfield_field32_write( \
638 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_HE_EN_##region_macro_arg##_FIELD, \
640 mp_region_cfg = bitfield_field32_write( \
642 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_ECC_EN_##region_macro_arg##_FIELD, \
644 mp_region_cfg = bitfield_field32_write( \
646 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_SCRAMBLE_EN_##region_macro_arg##_FIELD, \
648 mp_region_cfg = bitfield_field32_write( \
650 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_ERASE_EN_##region_macro_arg##_FIELD, \
652 mp_region_cfg = bitfield_field32_write( \
654 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_PROG_EN_##region_macro_arg##_FIELD, \
656 mp_region_cfg = bitfield_field32_write( \
658 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_RD_EN_##region_macro_arg##_FIELD, \
660 mp_region_cfg = bitfield_field32_write( \
662 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_EN_##region_macro_arg##_FIELD, \
665 flash_ctrl_core_base() + \
666 FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \
668 if (lock != kHardenedBoolFalse) { \
670 flash_ctrl_core_base() + \
671 FLASH_CTRL_REGION_CFG_REGWEN_##region_macro_arg##_REG_OFFSET, \
677 switch (launder32(region)) {
678 FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_CFG_WRITE_)
683 #undef FLASH_CTRL_MP_REGION_CFG_WRITE_
686 void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,
687 uint32_t page_offset, uint32_t num_pages,
693 flash_ctrl_mp_region_cfg_reset(region);
696 flash_ctrl_mp_region_write(region, page_offset, num_pages);
699 flash_ctrl_mp_region_cfg_write(region, cfg, perms,
700 kMultiBitBool4True, lock);
711 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
713 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD,
716 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ECC_EN_0_FIELD, cfg.ecc);
718 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_HE_EN_0_FIELD, cfg.he);
728 switch (launder32(enable)) {
732 0, FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_0_BIT,
true);
734 reg, FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_1_BIT,
true);
746 flash_ctrl_core_base() + FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET, reg);
756 &kFlashCtrlInfoPageFactoryId,
757 &kFlashCtrlInfoPageCreatorSecret,
758 &kFlashCtrlInfoPageOwnerSecret,
759 &kFlashCtrlInfoPageWaferAuthSecret,
761 &kFlashCtrlInfoPageBootData0,
762 &kFlashCtrlInfoPageBootData1,
766 kInfoPagesNoOwnerAccessCount =
ARRAYSIZE(kInfoPagesNoOwnerAccess),
769 void flash_ctrl_creator_info_pages_lockdown(
void) {
771 2 * kInfoPagesNoOwnerAccessCount);
772 size_t i = 0, r = kInfoPagesNoOwnerAccessCount - 1;
773 for (; launder32(i) < kInfoPagesNoOwnerAccessCount &&
774 launder32(r) < kInfoPagesNoOwnerAccessCount;
776 page_lockdown(kInfoPagesNoOwnerAccess[i]);
784 .ecc = kMultiBitBool4True,
785 .he = kMultiBitBool4False,
788 .
read = kMultiBitBool4True,
789 .write = kMultiBitBool4True,
790 .erase = kMultiBitBool4True,
793 .
read = kMultiBitBool4True,
794 .write = kMultiBitBool4False,
795 .erase = kMultiBitBool4False,
798 void flash_ctrl_cert_info_page_creator_cfg(
801 flash_ctrl_info_cfg_set(info_page, kCertificateInfoPageCfg);
802 flash_ctrl_info_perms_set(info_page, kCertificateInfoPageCreatorAccess);
805 void flash_ctrl_cert_info_page_owner_restrict(
809 flash_ctrl_info_perms_set(info_page, kCertificateInfoPageOwnerAccess);