11 #include "sw/device/lib/base/multibits.h"
14 #include "flash_ctrl_regs.h"
27 static ptrdiff_t get_data_region_mp_reg_offset(uint32_t region) {
28 return FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET +
29 (ptrdiff_t)region * (ptrdiff_t)
sizeof(uint32_t);
33 static ptrdiff_t get_data_region_reg_offset(uint32_t region) {
34 return FLASH_CTRL_MP_REGION_0_REG_OFFSET +
35 (ptrdiff_t)region * (ptrdiff_t)
sizeof(uint32_t);
39 static ptrdiff_t get_data_region_lock_reg_offset(uint32_t region) {
40 return FLASH_CTRL_REGION_CFG_REGWEN_0_REG_OFFSET +
41 (ptrdiff_t)region * (ptrdiff_t)
sizeof(uint32_t);
47 static_assert(FLASH_CTRL_PARAM_REG_NUM_BANKS == 2,
48 "Please update the info region register tables.");
52 #ifndef FLASH_CTRL_NUM_INFO_TYPES
53 #define FLASH_CTRL_NUM_INFO_TYPES 3
58 static const ptrdiff_t
59 kInfoConfigOffsets[FLASH_CTRL_NUM_INFO_TYPES]
60 [FLASH_CTRL_PARAM_REG_NUM_BANKS] = {
62 FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_REG_OFFSET,
63 FLASH_CTRL_BANK1_INFO0_PAGE_CFG_0_REG_OFFSET,
66 FLASH_CTRL_BANK0_INFO1_PAGE_CFG_REG_OFFSET,
67 FLASH_CTRL_BANK1_INFO1_PAGE_CFG_REG_OFFSET,
70 FLASH_CTRL_BANK0_INFO2_PAGE_CFG_0_REG_OFFSET,
71 FLASH_CTRL_BANK1_INFO2_PAGE_CFG_0_REG_OFFSET,
75 static const ptrdiff_t
76 kInfoLockOffsets[FLASH_CTRL_NUM_INFO_TYPES]
77 [FLASH_CTRL_PARAM_REG_NUM_BANKS] = {
79 FLASH_CTRL_BANK0_INFO0_REGWEN_0_REG_OFFSET,
80 FLASH_CTRL_BANK1_INFO0_REGWEN_0_REG_OFFSET,
83 FLASH_CTRL_BANK0_INFO1_REGWEN_REG_OFFSET,
84 FLASH_CTRL_BANK1_INFO1_REGWEN_REG_OFFSET,
87 FLASH_CTRL_BANK0_INFO2_REGWEN_0_REG_OFFSET,
88 FLASH_CTRL_BANK1_INFO2_REGWEN_0_REG_OFFSET,
92 static const uint32_t kNumInfoPagesPerBank[FLASH_CTRL_NUM_INFO_TYPES] = {
93 FLASH_CTRL_PARAM_NUM_INFOS0,
94 FLASH_CTRL_PARAM_NUM_INFOS1,
95 FLASH_CTRL_PARAM_NUM_INFOS2,
107 static ptrdiff_t get_info_region_mp_reg_offset(
110 (ptrdiff_t)region.
page * (ptrdiff_t)
sizeof(uint32_t);
114 static ptrdiff_t get_info_region_lock_reg_offset(
117 (ptrdiff_t)region.
page * (ptrdiff_t)
sizeof(uint32_t);
123 if (handle == NULL) {
136 dt_flash_ctrl_t dt) {
144 .
num_banks = FLASH_CTRL_PARAM_REG_NUM_BANKS,
145 .bytes_per_word = FLASH_CTRL_PARAM_BYTES_PER_WORD,
146 .bytes_per_page = FLASH_CTRL_PARAM_BYTES_PER_PAGE,
147 .data_pages = FLASH_CTRL_PARAM_REG_PAGES_PER_BANK,
148 .info0_pages = FLASH_CTRL_PARAM_NUM_INFOS0,
149 .info1_pages = FLASH_CTRL_PARAM_NUM_INFOS1,
150 .info2_pages = FLASH_CTRL_PARAM_NUM_INFOS2,
158 enum multi_bit_bool disable_flash;
159 if (handle == NULL) {
167 disable_flash = kMultiBitBool4False;
170 disable_flash = kMultiBitBool4True;
175 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_DIS_REG_OFFSET,
183 if (handle == NULL || enabled_out == NULL) {
187 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_DIS_REG_OFFSET);
188 enum multi_bit_bool flash_disabled =
193 if (flash_disabled == kMultiBitBool4False) {
205 if (handle == NULL) {
210 value = FLASH_CTRL_PARAM_EXEC_EN;
218 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_EXEC_REG_OFFSET, value);
225 if (handle == NULL || enabled_out == NULL) {
229 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_EXEC_REG_OFFSET);
230 if (reg == FLASH_CTRL_PARAM_EXEC_EN) {
241 if (handle == NULL) {
245 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_INIT_REG_OFFSET);
251 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_INIT_REG_OFFSET, value);
258 if (handle == NULL || status_out == NULL) {
262 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_STATUS_REG_OFFSET);
271 .controller_init_wip =
273 .controller_initialized =
284 if (handle == NULL || allowed_types_out == NULL) {
288 uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
289 FLASH_CTRL_PROG_TYPE_EN_REG_OFFSET);
296 *allowed_types_out = allowed_types;
304 if (handle == NULL) {
308 uint32_t ctrl_regwen = mmio_region_read32(handle->
dev.base_addr,
309 FLASH_CTRL_CTRL_REGWEN_REG_OFFSET);
319 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_PROG_TYPE_EN_REG_OFFSET,
327 if (handle == NULL) {
330 uint32_t ctrl_regwen = mmio_region_read32(handle->
dev.base_addr,
331 FLASH_CTRL_CTRL_REGWEN_REG_OFFSET);
337 transaction.word_count - 1);
338 switch (transaction.op) {
342 FLASH_CTRL_CONTROL_OP_VALUE_READ);
347 FLASH_CTRL_CONTROL_OP_VALUE_PROG);
349 control_reg, FLASH_CTRL_CONTROL_PROG_SEL_BIT,
false);
354 FLASH_CTRL_CONTROL_OP_VALUE_PROG);
356 FLASH_CTRL_CONTROL_PROG_SEL_BIT,
true);
361 FLASH_CTRL_CONTROL_OP_VALUE_ERASE);
363 control_reg, FLASH_CTRL_CONTROL_ERASE_SEL_BIT,
false);
368 FLASH_CTRL_CONTROL_OP_VALUE_ERASE);
370 control_reg, FLASH_CTRL_CONTROL_ERASE_SEL_BIT,
true);
376 switch (transaction.partition_type) {
377 case kDifFlashCtrlPartitionTypeData:
379 control_reg, FLASH_CTRL_CONTROL_PARTITION_SEL_BIT,
false);
381 case kDifFlashCtrlPartitionTypeInfo:
384 transaction.partition_id);
386 control_reg, FLASH_CTRL_CONTROL_PARTITION_SEL_BIT,
true);
392 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_CONTROL_REG_OFFSET,
394 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_ADDR_REG_OFFSET,
395 transaction.byte_address);
396 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_CONTROL_REG_OFFSET,
397 control_reg | (1u << FLASH_CTRL_CONTROL_START_BIT));
412 if (handle == NULL) {
416 if (transaction.partition_type == kDifFlashCtrlPartitionTypeInfo &&
417 transaction.partition_id >= FLASH_CTRL_NUM_INFO_TYPES) {
421 const uint32_t max_word_count = FLASH_CTRL_CONTROL_NUM_MASK;
424 if (transaction.word_count - 1 > max_word_count ||
425 transaction.word_count == 0) {
440 if (!
status.read_fifo_empty || !
status.prog_fifo_empty) {
449 if (handle == NULL) {
454 mmio_region_write32(handle->
dev.base_addr,
455 FLASH_CTRL_ERASE_SUSPEND_REG_OFFSET, reg);
462 if (handle == NULL || request_pending_out == NULL) {
465 uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
466 FLASH_CTRL_ERASE_SUSPEND_REG_OFFSET);
467 *request_pending_out =
477 if (handle == NULL || data == NULL) {
480 uint32_t written = 0;
481 while (written < word_count) {
482 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_PROG_FIFO_REG_OFFSET,
493 const uint32_t *data) {
494 if (handle == NULL || data == NULL) {
503 const uint32_t control_reg =
504 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_CONTROL_REG_OFFSET);
507 if (op != FLASH_CTRL_CONTROL_OP_VALUE_PROG) {
517 if (handle == NULL || data == NULL) {
521 while (read < word_count) {
522 data[read] = mmio_region_read32(handle->
dev.base_addr,
523 FLASH_CTRL_RD_FIFO_REG_OFFSET);
532 uint32_t word_count, uint32_t *data) {
533 if (handle == NULL || data == NULL) {
542 const uint32_t control_reg =
543 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_CONTROL_REG_OFFSET);
546 if (op != FLASH_CTRL_CONTROL_OP_VALUE_READ) {
556 if (handle == NULL || error_code_out == NULL) {
559 const uint32_t code_reg =
560 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_ERR_CODE_REG_OFFSET);
570 .shadow_register_error =
574 const uint32_t address_reg =
575 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_ERR_ADDR_REG_OFFSET);
580 *error_code_out = error_code;
587 if (handle == NULL) {
590 uint32_t code_reg = 0;
598 code_reg, FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT, codes.
prog_type_error);
601 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_ERR_CODE_REG_OFFSET,
609 if (handle == NULL || out == NULL) {
615 uint32_t status_reg = mmio_region_read32(handle->
dev.base_addr,
616 FLASH_CTRL_OP_STATUS_REG_OFFSET);
630 .error_code = error_code_tmp};
632 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_OP_STATUS_REG_OFFSET,
642 if (handle == NULL || region >= FLASH_CTRL_PARAM_NUM_REGIONS) {
653 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
654 uint32_t mp_reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
658 mp_reg, FLASH_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4True);
662 mp_reg, FLASH_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4False);
667 mmio_region_write32(handle->
dev.base_addr, mp_reg_offset, mp_reg);
675 if (handle == NULL || enabled_out == NULL ||
676 region >= FLASH_CTRL_PARAM_NUM_REGIONS) {
679 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
680 uint32_t mp_reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
682 kMultiBitBool4True) {
694 if (handle == NULL || region.
bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS ||
706 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
707 uint32_t mp_reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
711 mp_reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD,
716 mp_reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD,
717 kMultiBitBool4False);
722 mmio_region_write32(handle->
dev.base_addr, mp_reg_offset, mp_reg);
730 if (handle == NULL || enabled_out == NULL ||
731 region.
bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS ||
736 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
737 uint32_t mp_reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
739 kMultiBitBool4True) {
751 if (handle == NULL) {
767 mmio_region_write32(handle->
dev.base_addr,
768 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
776 if (handle == NULL || properties_out == NULL) {
779 const uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
780 FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
789 reg, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD),
795 *properties_out = properties;
803 const uint32_t page_limit =
804 FLASH_CTRL_PARAM_REG_NUM_BANKS * FLASH_CTRL_PARAM_REG_PAGES_PER_BANK;
805 if (handle == NULL || region >= FLASH_CTRL_PARAM_NUM_REGIONS ||
806 config.
base + config.
size > page_limit) {
817 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
818 uint32_t reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
826 FLASH_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD,
833 mmio_region_write32(handle->
dev.base_addr, mp_reg_offset, reg);
836 mp_reg_offset = get_data_region_reg_offset(region);
842 mmio_region_write32(handle->
dev.base_addr, mp_reg_offset, reg);
850 if (handle == NULL || config_out == NULL ||
851 region >= FLASH_CTRL_PARAM_NUM_REGIONS) {
855 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
856 uint32_t reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
865 reg, FLASH_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD);
871 mp_reg_offset = get_data_region_reg_offset(region);
872 reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
875 *config_out = config;
883 if (handle == NULL || region.
bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS ||
896 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
897 uint32_t reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
905 FLASH_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD,
911 mmio_region_write32(handle->
dev.base_addr, mp_reg_offset, reg);
919 if (handle == NULL || properties_out == NULL ||
920 region.
bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS ||
926 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
927 const uint32_t reg = mmio_region_read32(handle->
dev.base_addr, mp_reg_offset);
930 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_RD_EN_0_FIELD);
932 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_PROG_EN_0_FIELD);
934 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ERASE_EN_0_FIELD);
936 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD);
938 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ECC_EN_0_FIELD);
940 reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_HE_EN_0_FIELD);
941 *properties_out = properties;
948 if (handle == NULL || region >= FLASH_CTRL_PARAM_NUM_REGIONS) {
959 ptrdiff_t lock_reg_offset = get_data_region_lock_reg_offset(region);
961 0, FLASH_CTRL_REGION_CFG_REGWEN_0_REGION_0_BIT,
false);
962 mmio_region_write32(handle->
dev.base_addr, lock_reg_offset, reg);
969 if (handle == NULL || region.
bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS ||
982 ptrdiff_t lock_reg_offset = get_info_region_lock_reg_offset(region);
984 0, FLASH_CTRL_BANK0_INFO0_REGWEN_0_REGION_0_BIT,
false);
985 mmio_region_write32(handle->
dev.base_addr, lock_reg_offset, reg);
992 if (handle == NULL || locked_out == NULL ||
993 region >= FLASH_CTRL_PARAM_NUM_REGIONS) {
996 ptrdiff_t lock_reg_offset = get_data_region_lock_reg_offset(region);
997 uint32_t reg = mmio_region_read32(handle->
dev.base_addr, lock_reg_offset);
1007 if (handle == NULL || locked_out == NULL ||
1008 region.
bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS ||
1014 ptrdiff_t lock_reg_offset = get_info_region_lock_reg_offset(region);
1015 uint32_t reg = mmio_region_read32(handle->
dev.base_addr, lock_reg_offset);
1024 if (handle == NULL || bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS) {
1036 uint32_t value = mmio_region_read32(
1037 handle->
dev.base_addr, FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET);
1048 mmio_region_write32_shadowed(
1049 handle->
dev.base_addr, FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET, value);
1057 if (handle == NULL || enabled_out == NULL ||
1058 bank >= FLASH_CTRL_PARAM_REG_NUM_BANKS) {
1061 uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
1062 FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET);
1076 if (handle == NULL) {
1089 mmio_region_write32(handle->
dev.base_addr,
1090 FLASH_CTRL_BANK_CFG_REGWEN_REG_OFFSET, reg);
1097 if (handle == NULL || locked_out == NULL) {
1100 const uint32_t reg = mmio_region_read32(
1101 handle->
dev.base_addr, FLASH_CTRL_BANK_CFG_REGWEN_REG_OFFSET);
1109 if (handle == NULL || level > FLASH_CTRL_FIFO_LVL_PROG_MASK) {
1113 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_FIFO_LVL_REG_OFFSET);
1115 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_FIFO_LVL_REG_OFFSET,
1123 if (handle == NULL || level > FLASH_CTRL_FIFO_LVL_RD_MASK) {
1127 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_FIFO_LVL_REG_OFFSET);
1129 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_FIFO_LVL_REG_OFFSET,
1137 uint32_t *read_out) {
1138 if (handle == NULL) {
1141 const uint32_t reg =
1142 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_FIFO_LVL_REG_OFFSET);
1143 if (prog_out != NULL) {
1146 if (read_out != NULL) {
1155 if (handle == NULL) {
1159 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_FIFO_RST_REG_OFFSET,
1162 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_FIFO_RST_REG_OFFSET,
1170 if (handle == NULL || faults_out == NULL) {
1173 uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
1174 FLASH_CTRL_FAULT_STATUS_REG_OFFSET);
1186 reg = mmio_region_read32(handle->
dev.base_addr,
1187 FLASH_CTRL_STD_FAULT_STATUS_REG_OFFSET);
1196 *faults_out = faults;
1204 if (handle == NULL || errors_out == NULL ||
1205 bank > FLASH_CTRL_PARAM_REG_NUM_BANKS) {
1209 ptrdiff_t last_addr_reg_offset;
1210 #if FLASH_CTRL_PARAM_REG_NUM_BANKS > 2
1211 #error "Revise this function to handle more banks."
1215 FLASH_CTRL_ECC_SINGLE_ERR_CNT_ECC_SINGLE_ERR_CNT_0_FIELD;
1216 last_addr_reg_offset = FLASH_CTRL_ECC_SINGLE_ERR_ADDR_0_REG_OFFSET;
1219 FLASH_CTRL_ECC_SINGLE_ERR_CNT_ECC_SINGLE_ERR_CNT_1_FIELD;
1220 last_addr_reg_offset = FLASH_CTRL_ECC_SINGLE_ERR_ADDR_1_REG_OFFSET;
1223 uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
1224 FLASH_CTRL_ECC_SINGLE_ERR_CNT_REG_OFFSET);
1228 mmio_region_read32(handle->
dev.base_addr, last_addr_reg_offset);
1236 if (handle == NULL || status_out == NULL) {
1239 const uint32_t reg = mmio_region_read32(handle->
dev.base_addr,
1240 FLASH_CTRL_PHY_STATUS_REG_OFFSET);
1244 .prog_normal_available =
1246 .prog_repair_available =
1256 if (handle == NULL) {
1259 mmio_region_write32(handle->
dev.base_addr, FLASH_CTRL_SCRATCH_REG_OFFSET,
1266 uint32_t *value_out) {
1267 if (handle == NULL || value_out == NULL) {
1271 mmio_region_read32(handle->
dev.base_addr, FLASH_CTRL_SCRATCH_REG_OFFSET);