Software APIs
flash_ctrl_write_clear_test.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 
12 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
16 
17 #include "flash_ctrl_regs.h"
19 
20 // See chip_sw_flash_ctrl_write_clear in chip_flash_ctrl_testplan.hjson for
21 // test description.
22 
23 OTTF_DEFINE_TEST_CONFIG();
24 
25 enum {
26  // Some dif_flash_ctrl functions don't require the partition parameter when
27  // interacting with data partitions. This constant is added to improve
28  // readability.
29  kUnusedDataPartitionParam = 0,
30 
31  // Number of bytes per page.
32  kFlashBytesPerPage = FLASH_CTRL_PARAM_BYTES_PER_PAGE,
33 
34  // Number of pages allocated to the ROM_EXT. The same number of pages are
35  // allocated at the begining of each data bank.
36  kRomExtPageCount = CHIP_ROM_EXT_SIZE_MAX / kFlashBytesPerPage,
37 
38  // The start page used by this test. Points to the start of the owner
39  // partition in bank 1, otherwise known as owner partition B.
40  kBank1StartPageNum = 256 + kRomExtPageCount,
41 };
42 
43 // The `flash_word_verify()` function will need to be updated if this assertion
44 // fails.
45 static_assert(
46  FLASH_CTRL_PARAM_BYTES_PER_WORD == sizeof(uint64_t),
47  "This test expects the flash word to be sizeof(uint64_t) bytes long.");
48 
49 static dif_flash_ctrl_state_t flash;
50 
51 /**
52  * Write and verify `expected_value` at flash `address`.
53  *
54  * This function generates a test assertion on failure.
55  *
56  * @param address Flash address, uint32_t aligned.
57  * @param expected_value Value to write and verify.
58  */
59 static void flash_word_write_verify(uintptr_t address,
60  uint64_t expected_value) {
61  size_t kWordSize = sizeof(uint64_t) / sizeof(uint32_t);
62  uint32_t tmp[2] = {(uint32_t)expected_value,
63  (uint32_t)(expected_value >> 32)};
64  CHECK_STATUS_OK(flash_ctrl_testutils_write(
65  &flash, address, kUnusedDataPartitionParam, tmp,
66  kDifFlashCtrlPartitionTypeData, kWordSize));
67 
68  uint32_t tmp2[2];
69  CHECK_STATUS_OK(
70  flash_ctrl_testutils_read(&flash, address, kUnusedDataPartitionParam,
71  tmp2, kDifFlashCtrlPartitionTypeData, kWordSize,
72  /*delay=*/1));
73  uint64_t got_value;
74  memcpy(&got_value, tmp2, sizeof(uint64_t));
75  CHECK(expected_value == got_value);
76 }
77 
78 static void flash_ctrl_write_clear_test(
79  uint32_t mp_region_index,
81  // Configure a memory protected region to implement the page configuration
82  // set in `mp_properties`.
84  &flash, mp_region_index, mp_properties));
86  &flash, mp_region_index, kDifToggleEnabled));
87 
88  uintptr_t start_addr = (uintptr_t)(mp_properties.base * kFlashBytesPerPage);
89  CHECK_STATUS_OK(flash_ctrl_testutils_erase_page(
90  &flash, start_addr, kUnusedDataPartitionParam,
91  kDifFlashCtrlPartitionTypeData));
92 
93  const uint64_t kExpectedValues[] = {
94  UINT64_MAX, UINT64_MAX - 1, 0, 0xa5a5a5a594949494, 0xaaaaaaaaaaaaaaaa,
95  };
96 
97  for (size_t i = 0; i < ARRAYSIZE(kExpectedValues); ++i) {
98  flash_word_write_verify(start_addr + sizeof(uint64_t) * i,
99  kExpectedValues[i]);
100  flash_word_write_verify(start_addr, /*expected_value=*/0);
101  }
102 }
103 
104 bool test_main(void) {
105  CHECK_DIF_OK(dif_flash_ctrl_init_state(
107 
108  // The ROM_EXT configures the default region access. We can't modify the
109  // values after configured.
110  if (kBootStage != kBootStageOwner) {
111  CHECK_STATUS_OK(flash_ctrl_testutils_default_region_access(
112  &flash, /*rd_en=*/true, /*prog_en=*/true, /*erase_en=*/true,
113  /*scramble_en=*/false, /*ecc_en=*/false, /*high_endurance_en=*/false));
114  }
115 
116  LOG_INFO("ECC enabled with high endurance disabled.");
117  flash_ctrl_write_clear_test(/*mp_region_index=*/0,
119  .base = kBank1StartPageNum,
120  .size = 1,
121  .properties = {
122  .rd_en = kMultiBitBool4True,
123  .prog_en = kMultiBitBool4True,
124  .erase_en = kMultiBitBool4True,
125  .scramble_en = kMultiBitBool4False,
126  .ecc_en = kMultiBitBool4True,
127  .high_endurance_en = kMultiBitBool4False,
128  }});
129 
130  LOG_INFO("ECC enabled with high endurance enabled.");
131  flash_ctrl_write_clear_test(/*mp_region_index=*/1,
133  .base = kBank1StartPageNum + 1,
134  .size = 1,
135  .properties = {
136  .rd_en = kMultiBitBool4True,
137  .prog_en = kMultiBitBool4True,
138  .erase_en = kMultiBitBool4True,
139  .scramble_en = kMultiBitBool4False,
140  .ecc_en = kMultiBitBool4True,
141  .high_endurance_en = kMultiBitBool4True,
142  }});
143 
144  return true;
145 }