5#include "sw/device/lib/testing/flash_ctrl_testutils.h"
16#include "sw/device/lib/testing/test_framework/check.h"
18#include "hw/top/flash_ctrl_regs.h"
20#define MODULE_ID MAKE_MODULE_ID('f', 'c', 't')
22status_t flash_ctrl_testutils_wait_for_init(
26 TRY(dif_flash_ctrl_get_status(flash_state, &
status));
27 }
while (
status.controller_init_wip);
31status_t flash_ctrl_testutils_wait_transaction_end(
33 dif_flash_ctrl_output_t output;
36 dif_result = dif_flash_ctrl_end(flash_state, &output);
43 uint32_t error_reg = 0;
44 error_reg = bitfield_bit32_write(error_reg, FLASH_CTRL_ERR_CODE_MP_ERR_BIT,
46 error_reg = bitfield_bit32_write(error_reg, FLASH_CTRL_ERR_CODE_RD_ERR_BIT,
49 bitfield_bit32_write(error_reg, FLASH_CTRL_ERR_CODE_PROG_WIN_ERR_BIT,
52 bitfield_bit32_write(error_reg, FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT,
55 bitfield_bit32_write(error_reg, FLASH_CTRL_ERR_CODE_UPDATE_ERR_BIT,
58 TRY(dif_flash_ctrl_clear_error_codes(flash_state, output.
error_code.
codes));
62status_t flash_ctrl_testutils_data_region_setup_properties(
64 uint32_t data_region, uint32_t region_size,
67 .base = base_page_index,
68 .properties = region_properties,
71 TRY(dif_flash_ctrl_set_data_region_properties(flash_state, data_region,
72 data_region_properties));
73 TRY(dif_flash_ctrl_set_data_region_enablement(flash_state, data_region,
77 dif_flash_ctrl_device_info_t device_info = dif_flash_ctrl_get_device_info();
83status_t flash_ctrl_testutils_data_region_setup(
85 uint32_t data_region, uint32_t region_size, uint32_t *offset) {
87 .ecc_en = kMultiBitBool4True,
88 .high_endurance_en = kMultiBitBool4False,
89 .erase_en = kMultiBitBool4True,
90 .prog_en = kMultiBitBool4True,
91 .rd_en = kMultiBitBool4True,
92 .scramble_en = kMultiBitBool4False};
93 return flash_ctrl_testutils_data_region_setup_properties(
94 flash_state, base_page_index, data_region, region_size, region_properties,
98status_t flash_ctrl_testutils_data_region_scrambled_setup(
100 uint32_t data_region, uint32_t region_size, uint32_t *offset) {
102 .ecc_en = kMultiBitBool4True,
103 .high_endurance_en = kMultiBitBool4False,
104 .erase_en = kMultiBitBool4True,
105 .prog_en = kMultiBitBool4True,
106 .rd_en = kMultiBitBool4True,
107 .scramble_en = kMultiBitBool4True};
108 return flash_ctrl_testutils_data_region_setup_properties(
109 flash_state, base_page_index, data_region, region_size, region_properties,
113status_t flash_ctrl_testutils_info_region_setup_properties(
118 .bank = bank, .page = page_id, .partition_id = partition_id};
120 TRY(dif_flash_ctrl_set_info_region_properties(flash_state, info_region,
122 TRY(dif_flash_ctrl_set_info_region_enablement(flash_state, info_region,
125 if (offset != NULL) {
126 dif_flash_ctrl_device_info_t device_info = dif_flash_ctrl_get_device_info();
132status_t flash_ctrl_testutils_info_region_setup(
134 uint32_t partition_id, uint32_t *offset) {
136 .ecc_en = kMultiBitBool4True,
137 .high_endurance_en = kMultiBitBool4False,
138 .erase_en = kMultiBitBool4True,
139 .prog_en = kMultiBitBool4True,
140 .rd_en = kMultiBitBool4True,
141 .scramble_en = kMultiBitBool4False};
142 return flash_ctrl_testutils_info_region_setup_properties(
143 flash_state, page_id, bank, partition_id, region_properties, offset);
146status_t flash_ctrl_testutils_info_region_scrambled_setup(
148 uint32_t partition_id, uint32_t *offset) {
150 .ecc_en = kMultiBitBool4True,
151 .high_endurance_en = kMultiBitBool4False,
152 .erase_en = kMultiBitBool4True,
153 .prog_en = kMultiBitBool4True,
154 .rd_en = kMultiBitBool4True,
155 .scramble_en = kMultiBitBool4True};
156 return flash_ctrl_testutils_info_region_setup_properties(
157 flash_state, page_id, bank, partition_id, region_properties, offset);
160status_t flash_ctrl_testutils_erase_page(
163 dif_flash_ctrl_transaction_t transaction = {.byte_address = byte_address,
165 .partition_type = partition_type,
166 .partition_id = partition_id,
168 TRY(dif_flash_ctrl_start(flash_state, transaction));
169 return flash_ctrl_testutils_wait_transaction_end(flash_state);
172status_t flash_ctrl_testutils_write(
174 uint32_t partition_id,
const uint32_t *data,
181 if (byte_address & (
sizeof(uint32_t) - 1)) {
182 LOG_ERROR(
"Unaligned address 0x%x", byte_address);
183 return INVALID_ARGUMENT();
185 dif_flash_ctrl_transaction_t transaction = {.byte_address = byte_address,
187 .partition_type = partition_type,
188 .partition_id = partition_id,
190 static_assert(FLASH_CTRL_PARAM_BYTES_PER_WORD >=
sizeof(uint32_t),
191 "flash_ctrl_testutils_write() assumes the flash word width is"
192 "greater than or equal to the bus word width.");
193 uint32_t words_written = 0;
194 uint32_t word_address = byte_address /
sizeof(uint32_t);
195 const uint32_t prog_window_size =
196 (uint32_t)FLASH_CTRL_PARAM_REG_BUS_PGM_RES_BYTES /
sizeof(uint32_t);
197 const uint32_t prog_window_mask = ~(prog_window_size - 1);
199 status_t
status = OK_STATUS();
200 while (words_written < word_count) {
203 uint32_t window_limit =
204 ((word_address + prog_window_size) & prog_window_mask) - word_address;
205 uint32_t words_remaining = word_count - words_written;
206 uint32_t words_to_write =
207 (words_remaining < window_limit) ? words_remaining : window_limit;
208 transaction.
byte_address = word_address *
sizeof(uint32_t);
210 TRY(dif_flash_ctrl_start(flash_state, transaction));
211 TRY(dif_flash_ctrl_prog_fifo_push(flash_state, words_to_write,
212 data + words_written));
213 status = flash_ctrl_testutils_wait_transaction_end(flash_state);
214 word_address += words_to_write;
215 words_written += words_to_write;
221status_t flash_ctrl_testutils_erase_and_write_page(
223 uint32_t partition_id,
const uint32_t *data,
225 TRY(flash_ctrl_testutils_erase_page(flash_state, byte_address, partition_id,
227 TRY(flash_ctrl_testutils_write(flash_state, byte_address, partition_id, data,
228 partition_type, word_count));
232status_t flash_ctrl_testutils_read(
234 uint32_t partition_id, uint32_t *data_out,
236 uint32_t delay_micros) {
237 dif_flash_ctrl_transaction_t transaction = {.byte_address = byte_address,
239 .partition_type = partition_type,
240 .partition_id = partition_id,
241 .word_count = word_count};
244 TRY(dif_flash_ctrl_start(flash_state, transaction));
246 busy_spin_micros(delay_micros);
247 TRY(dif_flash_ctrl_read_fifo_pop(flash_state, word_count, data_out));
248 return flash_ctrl_testutils_wait_transaction_end(flash_state);
251status_t flash_ctrl_testutils_default_region_access(
253 bool erase_en,
bool scramble_en,
bool ecc_en,
bool high_endurance_en) {
255 .rd_en = rd_en ? kMultiBitBool4True : kMultiBitBool4False,
256 .prog_en = prog_en ? kMultiBitBool4True : kMultiBitBool4False,
257 .erase_en = erase_en ? kMultiBitBool4True : kMultiBitBool4False,
258 .scramble_en = scramble_en ? kMultiBitBool4True : kMultiBitBool4False,
259 .ecc_en = ecc_en ? kMultiBitBool4True : kMultiBitBool4False,
261 high_endurance_en ? kMultiBitBool4True : kMultiBitBool4False};
263 TRY(dif_flash_ctrl_set_default_region_properties(flash_state,
264 default_properties));
269 uint32_t bank,
bool data_only) {
271 TRY(dif_flash_ctrl_get_bank_erase_enablement(flash_state, bank,
272 &bank_erase_enabled));
275 TRY(dif_flash_ctrl_set_bank_erase_enablement(flash_state, bank,
279 dif_flash_ctrl_device_info_t flash_info = dif_flash_ctrl_get_device_info();
280 uint32_t byte_address =
283 data_only ? kDifFlashCtrlPartitionTypeData
284 : kDifFlashCtrlPartitionTypeInfo;
285 dif_flash_ctrl_transaction_t transaction = {.byte_address = byte_address,
287 .partition_type = partition_type,
290 TRY(dif_flash_ctrl_start(flash_state, transaction));
291 TRY(flash_ctrl_testutils_wait_transaction_end(flash_state));
293 TRY(dif_flash_ctrl_set_bank_erase_enablement(flash_state, bank,
294 bank_erase_enabled));
298status_t flash_ctrl_testutils_show_faults(
300 dif_flash_ctrl_faults_t faults = {.memory_properties_error =
false};
301 CHECK_DIF_OK(dif_flash_ctrl_get_faults(flash_ctrl, &faults));
302#define LOG_IF_FIELD_SET(_struct, _field) \
303 if (_struct._field != 0) { \
304 LOG_INFO("Flash_ctrl fault status has " #_field); \
307 LOG_IF_FIELD_SET(faults, memory_properties_error);
308 LOG_IF_FIELD_SET(faults, read_error);
309 LOG_IF_FIELD_SET(faults, prog_window_error);
310 LOG_IF_FIELD_SET(faults, prog_type_error);
311 LOG_IF_FIELD_SET(faults, host_gnt_error);
312 LOG_IF_FIELD_SET(faults, register_integrity_error);
313 LOG_IF_FIELD_SET(faults, phy_integrity_error);
314 LOG_IF_FIELD_SET(faults, lifecycle_manager_error);
315 LOG_IF_FIELD_SET(faults, shadow_storage_error);
316#undef LOG_IF_FIELD_SET
321static const char *mubi_prop(multi_bit_bool_t val,
const char *name) {
323 case kMultiBitBool4True:
325 case kMultiBitBool4False:
332void flash_ctrl_testutils_data_region_print(
334 LOG_INFO(
"data region n=%u st=%u sz=%u %s-%s-%s-%s-%s-%s %s", index, p->
base,
341 locked ?
"LK" :
"UN");
344void flash_ctrl_testutils_info_region_print(
347 LOG_INFO(
"info region bank=%u part=%u page=%u %s-%s-%s-%s-%s-%s %s",
352 locked ?
"LK" :
"UN");