blob: 5517a0806e1ead056e7ea93c133a8fcdb1bd4c0d [file] [log] [blame]
// 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/test_main.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_data_t kRamTestPattern1 = {
.words =
{
0xA5A5A5A5,
0xA5A5A5A5,
0xA5A5A5A5,
0xA5A5A5A5,
},
};
/**
* Second test pattern to be written and read from SRAM.
*/
static const sram_ctrl_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;
}