Skip to content

Commit

Permalink
[rom/bootstrap] CTN SRAM driver
Browse files Browse the repository at this point in the history
Implemented CTN SRAM driver that mimics Flash functionality for
bootstrap.

Signed-off-by: Daniel Beitel <[email protected]>
  • Loading branch information
dbeitel-opentitan committed Feb 27, 2024
1 parent a5f5b09 commit 96f91ea
Show file tree
Hide file tree
Showing 8 changed files with 554 additions and 137 deletions.
29 changes: 29 additions & 0 deletions sw/device/silicon_creator/lib/drivers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,35 @@ cc_test(
],
)

dual_cc_library(
name = "ctn_sram",
srcs = dual_inputs(
device = ["ctn_sram.c"],
host = ["mock_ctn_sram.cc"],
),
hdrs = dual_inputs(
host = ["mock_ctn_sram.h"],
shared = ["ctn_sram.h"],
),
deps = dual_inputs(
host = [
"//sw/lib/sw/device/silicon_creator/testing:rom_test",
"//sw/lib/sw/device/base:global_mock",
"@googletest//:gtest",
],
shared = [
"//hw/ip/sram_ctrl/data:sram_ctrl_regs",
"//hw/top_darjeeling/ip/flash_ctrl/data/autogen:flash_ctrl_regs",
"//hw/top_darjeeling/sw/autogen:top_darjeeling",
"//sw/lib/sw/device/base:abs_mmio",
"//sw/lib/sw/device/base:hardened",
"//sw/lib/sw/device/base:memory",
"//sw/lib/sw/device/base:multibits",
"//sw/lib/sw/device/silicon_creator:error",
],
),
)

dual_cc_library(
name = "flash_ctrl",
srcs = dual_inputs(
Expand Down
127 changes: 127 additions & 0 deletions sw/device/silicon_creator/lib/drivers/ctn_sram.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/lib/drivers/ctn_sram.h"

#include <assert.h>

#include "sw/lib/sw/device/base/abs_mmio.h"
#include "sw/lib/sw/device/base/hardened.h"
#include "sw/lib/sw/device/base/memory.h"
#include "sw/lib/sw/device/base/multibits.h"

#include "flash_ctrl_regs.h" // Generated.
#include "hw/top_darjeeling/sw/autogen/top_darjeeling.h"
#include "sram_ctrl_regs.h" // Generated.

enum {
/*
* Base ctn sram address, exclusive.
*/
kBaseAddress = TOP_DARJEELING_RAM_CTN_BASE_ADDR,
/*
* Maximum ctn sram size to be used as flash, exclusive.
*/
kMaxSize = FLASH_CTRL_PARAM_BYTES_PER_BANK * FLASH_CTRL_PARAM_REG_NUM_BANKS,
/**
* Value of a word in sram after erase.
*/
kErasedWord = UINT32_MAX,
};

static_assert(kMaxSize <= TOP_DARJEELING_RAM_CTN_SIZE_BYTES,
"CTN SRAM area for image bootstap must be smaller than total.");

rom_error_t ctn_sram_data_write(uint32_t addr, uint32_t len, const void *data) {
if (addr + len * sizeof(uint32_t) >= kMaxSize) {
return kErrorFlashCtrlDataWrite;
}
memcpy((void *)(kBaseAddress + addr), data, len * sizeof(uint32_t));
return kErrorOk;
}

rom_error_t ctn_sram_data_erase(uint32_t addr,
ctn_sram_erase_type_t erase_type) {
static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_BANK) == 1,
"Bytes per bank must be a power of two.");

if (addr >= kMaxSize) {
return kErrorFlashCtrlDataErase;
}
size_t byte_count = 0;
switch (erase_type) {
case kCtnSramEraseTypeBank:
HARDENED_CHECK_EQ(erase_type, kCtnSramEraseTypeBank);
byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
break;
case kCtnSramEraseTypePage:
HARDENED_CHECK_EQ(erase_type, kCtnSramEraseTypePage);
byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
break;
default:
HARDENED_TRAP();
byte_count = 0U;
break;
}
// Truncate to the closest lower bank/page aligned address.
addr &= ~byte_count + 1;
memset((void *)(kBaseAddress + addr), 0xff, byte_count);
return kErrorOk;
}

rom_error_t ctn_sram_data_erase_verify(uint32_t addr,
ctn_sram_erase_type_t erase_type) {
static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_BANK) == 1,
"Bytes per bank must be a power of two.");

if (addr >= kMaxSize) {
return kErrorFlashCtrlDataErase;
}
size_t byte_count = 0;
rom_error_t error = kErrorFlashCtrlDataEraseVerify;
switch (launder32(erase_type)) {
case kCtnSramEraseTypeBank:
HARDENED_CHECK_EQ(erase_type, kCtnSramEraseTypeBank);
byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
error = kErrorOk ^ (byte_count - 1);
break;
case kCtnSramEraseTypePage:
HARDENED_CHECK_EQ(erase_type, kCtnSramEraseTypePage);
byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
error = kErrorOk ^ (byte_count - 1);
break;
default:
HARDENED_TRAP();
byte_count = 0U;
break;
}

// Truncate to the closest lower bank/page aligned address.
addr &= ~byte_count + 1;
uint32_t mask = kErasedWord;
size_t i = 0, r = byte_count - 1;
for (; launder32(i) < byte_count && launder32(r) < byte_count;
i += sizeof(uint32_t), r -= sizeof(uint32_t)) {
uint32_t word = abs_mmio_read32(kBaseAddress + addr + i);
mask &= word;
error &= word;
}
HARDENED_CHECK_EQ(i, byte_count);
HARDENED_CHECK_EQ((uint32_t)r, UINT32_MAX);

if (launder32(mask) == kErasedWord) {
HARDENED_CHECK_EQ(mask, kErasedWord);
return error ^ (byte_count - 1);
}

return kErrorFlashCtrlDataEraseVerify;
}

void ctn_sram_data_default_perms_set(ctn_sram_perms_t perms) {
// Note: provided to maintain compatibility with flash controller
}

void ctn_sram_bank_erase_perms_set(hardened_bool_t enable) {
// Note: provided to maintain compatibility with flash controller
}
123 changes: 123 additions & 0 deletions sw/device/silicon_creator/lib/drivers/ctn_sram.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_CTN_SRAM_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_CTN_SRAM_H_

#include "sw/lib/sw/device/base/hardened.h"
#include "sw/lib/sw/device/base/multibits.h"
#include "sw/lib/sw/device/silicon_creator/error.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* Write data into CTN SRAM at a specific address.
*
* @param addr starting address to write data into sram.
* @param len number of words of data to write into sram.
* @param data data to write into sram.
* @return Result of the operation.
*/
rom_error_t ctn_sram_data_write(uint32_t addr, uint32_t len, const void *data);

/*
* Encoding generated with
* $ ./util/design/sparse-fsm-encode.py -d 5 -m 2 -n 32 \
* -s 2181785819 --language=c
*
* Minimum Hamming distance: 14
* Maximum Hamming distance: 14
* Minimum Hamming weight: 14
* Maximum Hamming weight: 18
*/

typedef enum ctn_sram_erase_type {
/**
* Erase a page.
*/
kCtnSramEraseTypePage = 0xaf0eab8b,
/**
* Erase a bank.
*/
kCtnSramEraseTypeBank = 0x80329be9,
} ctn_sram_erase_type_t;

/**
* Erases a data partition page or bank.
*
* The flash controller will truncate to the closest page boundary for page
* erase operations, and to the nearest bank aligned boundary for bank erase
* operations.
*
* @param addr Address that falls within the bank or page being deleted.
* @param erase_type Whether to erase a page or a bank.
* @return Result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t ctn_sram_data_erase(uint32_t addr,
ctn_sram_erase_type_t erase_type);

/**
* Verifies that a data partition page or bank was erased.
*
* @param addr Address that falls within the bank or page erased.
* @param erase_type Whether to verify a page or a bank.
* @return Result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t ctn_sram_data_erase_verify(uint32_t addr,
ctn_sram_erase_type_t erase_type);

/**
* A struct for specifying access permissions.
*
* ctn_sram config registers use 4-bits for boolean values. Use
* `kMultiBitBool4True` to enable and `kMultiBitBool4False` to disable
* permissions.
*
* Note: provided to maintain compatibility with flash controller
*/
typedef struct ctn_sram_perms {
/**
* Read.
*/
multi_bit_bool_t read;
/**
* Write.
*/
multi_bit_bool_t write;
/**
* Erase.
*/
multi_bit_bool_t erase;
} ctn_sram_perms_t;

/**
* Sets default access permissions for the data partition.
*
* A permission is enabled only if the corresponding field in `perms` is
* `kMultiBitBool4True`.
*
* Note: provided to maintain compatibility with flash controller
*
* @param perms New permissions.
*/
void ctn_sram_data_default_perms_set(ctn_sram_perms_t perms);

/**
* Set bank erase permissions for both flash banks.
*
* Note: provided to maintain compatibility with flash controller
*
* @param enable Whether to enable bank erase.
*/
void ctn_sram_bank_erase_perms_set(hardened_bool_t enable);

#ifdef __cplusplus
}
#endif

#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_CTN_SRAM_H_
33 changes: 33 additions & 0 deletions sw/device/silicon_creator/lib/drivers/mock_ctn_sram.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/lib/drivers/mock_ctn_sram.h"

namespace rom_test {
extern "C" {

rom_error_t ctn_sram_data_write(uint32_t addr, uint32_t len, const void *data) {
return MockCtnSram::Instance().DataWrite(addr, len, data);
}

rom_error_t ctn_sram_data_erase(uint32_t addr,
ctn_sram_erase_type_t erase_type) {
return MockCtnSram::Instance().DataErase(addr, erase_type);
}

rom_error_t ctn_sram_data_erase_verify(uint32_t addr,
ctn_sram_erase_type_t erase_type) {
return MockCtnSram::Instance().DataEraseVerify(addr, erase_type);
}

void ctn_sram_data_default_perms_set(ctn_sram_perms_t perms) {
MockCtnSram::Instance().DataDefaultPermsSet(perms);
}

void ctn_sram_bank_erase_perms_set(hardened_bool_t enable) {
MockCtnSram::Instance().BankErasePermsSet(enable);
}

} // extern "C"
} // namespace rom_test
32 changes: 32 additions & 0 deletions sw/device/silicon_creator/lib/drivers/mock_ctn_sram.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_MOCK_CTN_SRAM_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_MOCK_CTN_SRAM_H_

#include "sw/device/silicon_creator/lib/drivers/ctn_sram.h"
#include "sw/lib/sw/device/base/global_mock.h"

namespace rom_test {
namespace internal {

/**
* Mock class for ctn_sram.c.
*/
class MockCtnSram : public global_mock::GlobalMock<MockCtnSram> {
public:
MOCK_METHOD(rom_error_t, DataWrite, (uint32_t, uint32_t, const void *));
MOCK_METHOD(rom_error_t, DataErase, (uint32_t, ctn_sram_erase_type_t));
MOCK_METHOD(rom_error_t, DataEraseVerify, (uint32_t, ctn_sram_erase_type_t));
MOCK_METHOD(void, DataDefaultPermsSet, (ctn_sram_perms_t));
MOCK_METHOD(void, BankErasePermsSet, (hardened_bool_t));
};

} // namespace internal

using MockCtnSram = testing::StrictMock<internal::MockCtnSram>;

} // namespace rom_test

#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_MOCK_CTN_SRAM_H_
2 changes: 1 addition & 1 deletion sw/device/silicon_creator/rom/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ cc_library(
"//hw/ip/otp_ctrl/data:otp_ctrl_regs",
"//hw/top_darjeeling/ip/flash_ctrl/data/autogen:flash_ctrl_regs",
"//hw/top_darjeeling/sw/autogen:top_darjeeling",
"//sw/device/silicon_creator/lib/drivers:flash_ctrl",
"//sw/device/silicon_creator/lib/drivers:ctn_sram",
"//sw/device/silicon_creator/lib/drivers:otp",
"//sw/device/silicon_creator/lib/drivers:rstmgr",
"//sw/device/silicon_creator/lib/drivers:spi_device",
Expand Down
Loading

0 comments on commit 96f91ea

Please sign in to comment.