Skip to content

Commit

Permalink
[sram_ctrl/sw] Add SW support for readback mode
Browse files Browse the repository at this point in the history
This commit adds the DIF functions for the readback mode (c.f.
#23212) and a basic test.

Closes #23365

Signed-off-by: Pascal Nasahl <[email protected]>
  • Loading branch information
nasahlpa authored and vogelpi committed Jul 8, 2024
1 parent 4a9afc9 commit 35443ed
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 0 deletions.
21 changes: 21 additions & 0 deletions hw/top_earlgrey/data/ip/chip_sram_ctrl_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,27 @@
tests: []
bazel: ["//sw/device/tests:sram_ctrl_memset_test"]
}
{
name: chip_sw_sram_readback
desc: '''Enable the SRAM readback feature and write and read data from and to the SRAM.

- Enable the SRAM readback feature.
- Write some known data to the ret. SRAM and read it back to make sure the write worked
as expected.
- Use the INIT CSR for the relevant sram_ctrl to request that the memory is filled with
pseudo-random data.
- Read the location from the SRAM and check that the data has been wiped.
- Repeat the steps above with the disabled SRAM readback feature.
- Lock the SRAM readback configuration register and try to set it.

'''
features: ["SRAM_CTRL.READBACK"]
stage: V3
si_stage: SV3
lc_states: ["PROD"]
tests: []
bazel: ["//sw/device/tests:sram_ctrl_readback_test"]
}
{
name: chip_sw_sram_subword_access
desc: '''Check that subword access works for each SRAM.
Expand Down
46 changes: 46 additions & 0 deletions sw/device/lib/dif/dif_sram_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ static bool sram_ctrl_exec_locked(const dif_sram_ctrl_t *sram_ctrl) {
: true;
}

/**
* Obtains the lock state of the "Readback enable" register.
*
* When locked, enabling or disabling the readback feature is not possible.
*/
static bool sram_ctrl_readback_locked(const dif_sram_ctrl_t *sram_ctrl) {
return mmio_region_read32(sram_ctrl->base_addr,
SRAM_CTRL_READBACK_REGWEN_REG_OFFSET)
? false
: true;
}

/**
* Locks SRAM Controller "Control" functionality.
*
Expand All @@ -55,6 +67,16 @@ static void sram_ctrl_lock_exec(const dif_sram_ctrl_t *sram_ctrl) {
0);
}

/**
* Locks SRAM Controller "Readback" functionality.
*
* Enabling / disabling the readback functionality is no longer available.
*/
static void sram_ctrl_lock_readback(const dif_sram_ctrl_t *sram_ctrl) {
mmio_region_write32(sram_ctrl->base_addr,
SRAM_CTRL_READBACK_REGWEN_REG_OFFSET, 0);
}

/**
* Obtains the SRAM Controller statues.
*
Expand Down Expand Up @@ -174,6 +196,24 @@ dif_result_t dif_sram_ctrl_exec_set_enabled(const dif_sram_ctrl_t *sram_ctrl,
return kDifOk;
}

dif_result_t dif_sram_ctrl_readback_set(const dif_sram_ctrl_t *sram_ctrl,
dif_toggle_t state) {
if (sram_ctrl == NULL) {
return kDifBadArg;
}

if (sram_ctrl_readback_locked(sram_ctrl)) {
return kDifLocked;
}

uint32_t value =
(state == kDifToggleEnabled) ? kMultiBitBool4True : kMultiBitBool4False;
mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_READBACK_REG_OFFSET,
value);

return kDifOk;
}

dif_result_t dif_sram_ctrl_lock(const dif_sram_ctrl_t *sram_ctrl,
dif_sram_ctrl_lock_t lock) {
if (sram_ctrl == NULL) {
Expand All @@ -187,6 +227,9 @@ dif_result_t dif_sram_ctrl_lock(const dif_sram_ctrl_t *sram_ctrl,
case kDifSramCtrlLockExec:
sram_ctrl_lock_exec(sram_ctrl);
break;
case kDifSramCtrlLockReadback:
sram_ctrl_lock_readback(sram_ctrl);
break;
default:
return kDifError;
}
Expand All @@ -208,6 +251,9 @@ dif_result_t dif_sram_ctrl_is_locked(const dif_sram_ctrl_t *sram_ctrl,
case kDifSramCtrlLockExec:
*is_locked = sram_ctrl_exec_locked(sram_ctrl);
break;
case kDifSramCtrlLockReadback:
*is_locked = sram_ctrl_readback_locked(sram_ctrl);
break;
default:
return kDifError;
}
Expand Down
17 changes: 17 additions & 0 deletions sw/device/lib/dif/dif_sram_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ typedef enum dif_sram_ctrl_lock {
* of the chip (EN_SRAM_IFETCH fuse).
*/
kDifSramCtrlLockExec,
/**
* Readback feature lock. When locked, disabling or enabling the SRAM readback
* feature is not available anymore. Includes the following API:
* `dif_sram_ctrl_readback_set`.
*/
kDifSramCtrlLockReadback,
} dif_sram_ctrl_lock_t;

/**
Expand Down Expand Up @@ -192,6 +198,17 @@ OT_WARN_UNUSED_RESULT
dif_result_t dif_sram_ctrl_exec_set_enabled(const dif_sram_ctrl_t *sram_ctrl,
dif_toggle_t state);

/**
* Sets whether the SRAM readback feature is enabled or disabled.
*
* @param sram_ctrl A SRAM Controller handle.
* @param state The new toggle state for the SRAM readback feature.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_sram_ctrl_readback_set(const dif_sram_ctrl_t *sram_ctrl,
dif_toggle_t state);

/**
* Queries the SRAM Controller status.
*
Expand Down
19 changes: 19 additions & 0 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5493,6 +5493,25 @@ opentitan_test(
],
)

opentitan_test(
name = "sram_ctrl_readback_test",
srcs = ["sram_ctrl_readback_test.c"],
exec_env = dicts.add(
EARLGREY_TEST_ENVS,
EARLGREY_SILICON_OWNER_ROM_EXT_ENVS,
),
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/arch:device",
"//sw/device/lib/base:macros",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:sram_ctrl",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/silicon_creator/lib/drivers:retention_sram",
],
)

opentitan_test(
name = "rv_core_ibex_isa_test_test_unlocked0",
srcs = ["//sw/device/silicon_creator/manuf/tests:idle_functest.c"],
Expand Down
1 change: 1 addition & 0 deletions sw/device/tests/sival/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ test_suite(
"//sw/device/tests:sleep_pwm_pulses_test",
"//sw/device/tests:spi_device_tpm_tx_rx_test",
"//sw/device/tests:sram_ctrl_memset_test",
"//sw/device/tests:sram_ctrl_readback_test",
"//sw/device/tests:sram_ctrl_sleep_sram_ret_contents_no_scramble_test",
"//sw/device/tests:sram_ctrl_subword_access_test",
"//sw/device/tests/autogen:alert_test",
Expand Down
123 changes: 123 additions & 0 deletions sw/device/tests/sram_ctrl_readback_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! This test is identical to the sram_ctrl_memset_test except that the SRAM
//! readack mode gets enabled.

#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_sram_ctrl.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#include "sw/device/silicon_creator/lib/drivers/retention_sram.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "sram_ctrl_regs.h" // Generated.

// Define some amount of data we should leave in SRAM to check it gets wiped.
enum {
kSramCtrlTestDataSizeWords = 16,
};

OTTF_DEFINE_TEST_CONFIG();

static const uint32_t kStatusRegMask = kDifSramCtrlStatusBusIntegErr |
kDifSramCtrlStatusInitErr |
kDifSramCtrlStatusEscalated;

static const uint32_t kRandomData[kSramCtrlTestDataSizeWords] = {
0x6b4abfae, 0x63bdb6e7, 0x87f99b1a, 0xa214dffe, 0xb12291f9, 0xd0cd1abe,
0x5c95e716, 0xe887aab1, 0x307f6ef9, 0x6f5c0464, 0x5882279d, 0x44c19574,
0x1bd20079, 0xf8250ead, 0x4bf362a4, 0xad41437d};

/// Write `kRandomData` to an SRAM region.
static void write_data(mmio_region_t sram_region) {
for (int i = 0; i < kSramCtrlTestDataSizeWords; ++i) {
mmio_region_write32(sram_region, i * (ptrdiff_t)sizeof(uint32_t),
kRandomData[i]);
}
}

/// Check that the contents of an SRAM region match `kRandomData`.
///
/// The `matches` arg is used to specify whether you expect the SRAM region to
/// match `kRandomData`, or whether it should have been re-scrambled and no
/// longer match.
static void check_data_matches(mmio_region_t sram_region, bool matches) {
for (int i = 0; i < kSramCtrlTestDataSizeWords; ++i) {
uint32_t word =
mmio_region_read32(sram_region, i * (ptrdiff_t)sizeof(uint32_t));

if (matches) {
CHECK(word == kRandomData[i],
"Data at index %u mismached, expected: %04x, got: %04x", i,
kRandomData[i], word);
} else if (word != kRandomData[i]) {
return;
}
}

// If we got to this point and expected _not_ to match, fail.
CHECK(matches, "Data in SRAM was not rescrambled correctly");
}

/// (Re-)initialize an SRAM region with pseudorandom data.
static void init_sram(dif_sram_ctrl_t sram_ctrl) {
uint32_t init = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
mmio_region_write32(sram_ctrl.base_addr, SRAM_CTRL_CTRL_REG_OFFSET, init);

// Spin until SRAM_CTRL is ready.
dif_sram_ctrl_status_bitfield_t status;
do {
CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl, &status));
} while ((status & kDifSramCtrlStatusInitDone) == 0x0);

CHECK((status & kStatusRegMask) == 0x0,
"SRAM ret status error bits set, status = %08x.", status);
}

bool test_main(void) {
// Initialize SRAM_CTRL hardware.
dif_sram_ctrl_t sram_ctrl_ret;
CHECK_DIF_OK(dif_sram_ctrl_init(
mmio_region_from_addr(TOP_EARLGREY_SRAM_CTRL_RET_AON_REGS_BASE_ADDR),
&sram_ctrl_ret));

init_sram(sram_ctrl_ret);

uintptr_t sram_ret_buffer_addr =
TOP_EARLGREY_SRAM_CTRL_RET_AON_RAM_BASE_ADDR +
offsetof(retention_sram_t, owner);

mmio_region_t sram_region_ret_addr =
mmio_region_from_addr(sram_ret_buffer_addr);

// Enable the SRAM readback mode for the first test round.
CHECK_DIF_OK(dif_sram_ctrl_readback_set(&sram_ctrl_ret, kDifToggleEnabled));
for (size_t it = 0; it < 2; it++) {
// Write some data to retention SRAM and read it back to validate.
write_data(sram_region_ret_addr);
// Read back the data to validate it was written.
check_data_matches(sram_region_ret_addr, true);
// Redo test with SRAM readback mode disabled.
CHECK_DIF_OK(
dif_sram_ctrl_readback_set(&sram_ctrl_ret, kDifToggleDisabled));
}

// Lock readback enable feature.
CHECK_DIF_OK(dif_sram_ctrl_lock(&sram_ctrl_ret, kDifSramCtrlLockReadback));

// Check if lock works.
CHECK(kDifLocked ==
dif_sram_ctrl_readback_set(&sram_ctrl_ret, kDifToggleEnabled),
"Readback feature not locked.");

// Run initialization on the retention SRAM and check that the data is gone.
init_sram(sram_ctrl_ret);
check_data_matches(sram_region_ret_addr, false);

return true;
}

0 comments on commit 35443ed

Please sign in to comment.