| // Copyright lowRISC contributors. | 
 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 |  | 
 | #include <stdbool.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include "sw/device/lib/base/mmio.h" | 
 | #include "sw/device/lib/runtime/log.h" | 
 | #include "sw/device/lib/testing/check.h" | 
 | #include "sw/device/lib/testing/sram_ctrl_testutils.h" | 
 | #include "sw/device/lib/testing/test_framework/ottf.h" | 
 | #include "sw/device/lib/testing/test_framework/test_status.h" | 
 |  | 
 | #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" | 
 |  | 
 | const test_config_t kTestConfig; | 
 |  | 
 | static dif_sram_ctrl_t sram_ctrl; | 
 |  | 
 | /** | 
 |  * Retention SRAM start address (inclusive). | 
 |  */ | 
 | static const uintptr_t kRetSramStartAddr = | 
 |     TOP_EARLGREY_SRAM_CTRL_RET_AON_RAM_BASE_ADDR; | 
 |  | 
 | /** | 
 |  * First test pattern to be written and read from SRAM. | 
 |  */ | 
 | static const sram_ctrl_testutils_data_t kRamTestPattern1 = { | 
 |     .words = | 
 |         { | 
 |             0xA5A5A5A5, | 
 |             0xA5A5A5A5, | 
 |             0xA5A5A5A5, | 
 |             0xA5A5A5A5, | 
 |         }, | 
 | }; | 
 |  | 
 | /** | 
 |  * Second test pattern to be written and read from SRAM. | 
 |  */ | 
 | static const sram_ctrl_testutils_data_t kRamTestPattern2 = { | 
 |     .words = | 
 |         { | 
 |             0x5A5A5A5A, | 
 |             0x5A5A5A5A, | 
 |             0x5A5A5A5A, | 
 |             0x5A5A5A5A, | 
 |         }, | 
 | }; | 
 |  | 
 | /** | 
 |  * Tests that the written data to RAM can be read. | 
 |  * | 
 |  * This is a pre-requisite test to check that RAM can be written and read | 
 |  * successfully. The test write-read check one pattern, and then the second, | 
 |  * which prevents a false-negative in case of the value of the memory address | 
 |  * under test is already initialised to one of the patterns. | 
 |  */ | 
 | static void test_ram_write_read_pattern(void) { | 
 |   // Write first pattern to the start of SRAM, and read it out. | 
 |   sram_ctrl_testutils_write(kRetSramStartAddr, &kRamTestPattern1); | 
 |   CHECK(sram_ctrl_testutils_read_check_eq(kRetSramStartAddr, &kRamTestPattern1), | 
 |         "Read-Write first pattern failed"); | 
 |  | 
 |   // Write second pattern to the start of SRAM, and read it out. | 
 |   sram_ctrl_testutils_write(kRetSramStartAddr, &kRamTestPattern2); | 
 |   CHECK(sram_ctrl_testutils_read_check_eq(kRetSramStartAddr, &kRamTestPattern2), | 
 |         "Read-Write second pattern failed"); | 
 | } | 
 |  | 
 | /** | 
 |  * Tests RAM Scrambling. | 
 |  * | 
 |  * This test first writes a pattern to the start and the end of RAM. It then | 
 |  * requests a new scrambling key via dif_sram_ctrl (which scrambles RAM | 
 |  * addresses as well as the data). Finally, it reads back the RAM addresses | 
 |  * and checks them against the original pattern. The test is successful if | 
 |  * these patterns don't match. | 
 |  */ | 
 | bool test_ram_scrambling(const dif_sram_ctrl_t *sram_ctrl) { | 
 |   // Write the pattern at the start of RAM. | 
 |   sram_ctrl_testutils_write(kRetSramStartAddr, &kRamTestPattern1); | 
 |  | 
 |   sram_ctrl_testutils_scramble(sram_ctrl); | 
 |  | 
 |   // Read the first pattern at the start of RAM. It should NOT match the | 
 |   // originally written pattern. | 
 |   return sram_ctrl_testutils_read_check_neq(kRetSramStartAddr, | 
 |                                             &kRamTestPattern1); | 
 | } | 
 |  | 
 | bool test_main(void) { | 
 |   CHECK_DIF_OK(dif_sram_ctrl_init( | 
 |       mmio_region_from_addr(TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_BASE_ADDR), | 
 |       &sram_ctrl)); | 
 |  | 
 |   test_ram_write_read_pattern(); | 
 |  | 
 |   // There is a non-zero chance that the value at the tested address by pure | 
 |   // chance will be the same. So just to be prudent, in case of the failure, | 
 |   // scrambling is tested again. | 
 |   if (!test_ram_scrambling(&sram_ctrl)) { | 
 |     LOG_WARNING("Initial retention RAM scramble test(s) failed, running again"); | 
 |     CHECK(test_ram_scrambling(&sram_ctrl), | 
 |           "Retention RAM Scrambling test has failed (double-checked)"); | 
 |   } | 
 |  | 
 |   return true; | 
 | } |