[sw/silicon_creator] Switch otp to sec_mmio
Signed-off-by: Jon Flatley <jflat@google.com>
diff --git a/sw/device/silicon_creator/lib/base/mock_sec_mmio.h b/sw/device/silicon_creator/lib/base/mock_sec_mmio.h
index 1d8794fc..d04ca52 100644
--- a/sw/device/silicon_creator/lib/base/mock_sec_mmio.h
+++ b/sw/device/silicon_creator/lib/base/mock_sec_mmio.h
@@ -65,7 +65,7 @@
}
uint32_t sec_mmio_read32(uint32_t addr) {
- MockSecMmio::Instance().Read32(addr);
+ return MockSecMmio::Instance().Read32(addr);
}
void sec_mmio_write32(uint32_t addr, uint32_t value) {
diff --git a/sw/device/silicon_creator/lib/drivers/meson.build b/sw/device/silicon_creator/lib/drivers/meson.build
index 5d7baf8..8097a77 100644
--- a/sw/device/silicon_creator/lib/drivers/meson.build
+++ b/sw/device/silicon_creator/lib/drivers/meson.build
@@ -177,7 +177,7 @@
'otp.c',
],
dependencies: [
- sw_lib_mmio,
+ sw_silicon_creator_lib_base_sec_mmio,
],
),
)
@@ -191,12 +191,10 @@
],
dependencies: [
sw_vendor_gtest,
- sw_lib_base_testing_mock_mmio,
+ sw_silicon_creator_lib_base_mock_sec_mmio,
],
native: true,
- c_args: ['-DMOCK_MMIO'],
- cpp_args: ['-DMOCK_MMIO'],
- ),
+ ),
suite: 'mask_rom',
)
diff --git a/sw/device/silicon_creator/lib/drivers/otp.c b/sw/device/silicon_creator/lib/drivers/otp.c
index 59e033a..155e584 100644
--- a/sw/device/silicon_creator/lib/drivers/otp.c
+++ b/sw/device/silicon_creator/lib/drivers/otp.c
@@ -6,28 +6,40 @@
#include <stddef.h>
-#include "sw/device/lib/base/bitfield.h"
-#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/base/memory.h"
+#include "sw/device/silicon_creator/lib/base/sec_mmio.h"
#include "sw/device/silicon_creator/lib/error.h"
-#include "otp_ctrl_regs.h"
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+#include "otp_ctrl_regs.h" // Generated.
-uint32_t otp_read32(const otp_t *otp, uint32_t address) {
- return mmio_region_read32(otp->base_addr,
- OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + address);
+enum { kBase = TOP_EARLGREY_OTP_CTRL_BASE_ADDR };
+
+uint32_t otp_read32(uint32_t address) {
+ return sec_mmio_read32(kBase + OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + address);
}
-uint64_t otp_read64(const otp_t *otp, uint32_t address) {
- ptrdiff_t reg_offset = OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + address;
- uint64_t value =
- mmio_region_read32(otp->base_addr, reg_offset + sizeof(uint32_t));
+uint64_t otp_read64(uint32_t address) {
+ uint32_t reg_offset = OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + address;
+ uint64_t value = sec_mmio_read32(kBase + reg_offset + sizeof(uint32_t));
value <<= 32;
- value |= mmio_region_read32(otp->base_addr, reg_offset);
+ value |= sec_mmio_read32(kBase + reg_offset);
return value;
}
-void otp_read(const otp_t *otp, uint32_t address, void *data, size_t len) {
- ptrdiff_t reg_offset = OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + address;
- mmio_region_memcpy_from_mmio32(otp->base_addr, reg_offset, data, len);
+rom_error_t otp_read(uint32_t address, void *data, size_t len) {
+ // TODO Update to use alignment utility functions.
+ // https://github.com/lowRISC/opentitan/issues/6112
+ if (address % alignof(uint32_t) != 0 || len % sizeof(uint32_t) != 0) {
+ return kErrorOtpBadAlignment;
+ }
+
+ uint32_t reg_offset = OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET + address;
+ for (size_t i = 0; i < len; i += sizeof(uint32_t)) {
+ uint32_t word = sec_mmio_read32(kBase + reg_offset + i);
+ memcpy(data + i, &word, sizeof(uint32_t));
+ }
+
+ return kErrorOk;
}
diff --git a/sw/device/silicon_creator/lib/drivers/otp.h b/sw/device/silicon_creator/lib/drivers/otp.h
index 4fcde70..f444c5d 100644
--- a/sw/device/silicon_creator/lib/drivers/otp.h
+++ b/sw/device/silicon_creator/lib/drivers/otp.h
@@ -8,50 +8,47 @@
#include <stddef.h>
#include <stdint.h>
-#include "sw/device/lib/base/mmio.h"
#include "sw/device/silicon_creator/lib/error.h"
#ifdef __cplusplus
extern "C" {
#endif
-typedef struct otp {
- /**
- * The base address for the OTP hardware registers.
- */
- mmio_region_t base_addr;
-} otp_t;
+#define OTP_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
/**
* Perform a blocking 32-bit read from the memory mapped software config
* partitions.
*
- * @param otp The handle to the otp_ctrl device.
* @param address The address to read from offset from the start of OTP memory.
* @return The 32-bit value from OTP.
*/
-uint32_t otp_read32(const otp_t *otp, uint32_t address);
+OTP_WARN_UNUSED_RESULT
+uint32_t otp_read32(uint32_t address);
/**
* Perform a blocking 64-bit read from the memory mapped software config
* partitions.
*
- * @param otp The handle to the otp_ctrl device.
* @param address The address to read from offset from the start of OTP memory.
* @return The 64-bit value from OTP.
*/
-uint64_t otp_read64(const otp_t *otp, uint32_t address);
+OTP_WARN_UNUSED_RESULT
+uint64_t otp_read64(uint32_t address);
/**
* Perform a blocking read of `len` bytes from the memory mapped software config
- * partitions.
+ * partitions. It is required that both `address` and `address` + `len` be
+ * word-aligned.
*
- * @param otp The handle to the otp_ctrl device.
* @param address The address to read from offset from the start of OTP memory.
* @param data The output buffer of at least length `len`.
* @param len The number of bytes to read from OTP.
+ * @return `kErrorOtpBadAlignment` if `address` or `address` + `len` are
+ * misaligned, `kErrorOk` otherwise.
*/
-void otp_read(const otp_t *otp, uint32_t address, void *data, size_t len);
+OTP_WARN_UNUSED_RESULT
+rom_error_t otp_read(uint32_t address, void *data, size_t len);
#ifdef __cplusplus
}
diff --git a/sw/device/silicon_creator/lib/drivers/otp_unittest.cc b/sw/device/silicon_creator/lib/drivers/otp_unittest.cc
index 7fb670d..3f707b6 100644
--- a/sw/device/silicon_creator/lib/drivers/otp_unittest.cc
+++ b/sw/device/silicon_creator/lib/drivers/otp_unittest.cc
@@ -6,19 +6,21 @@
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
-#include "sw/device/lib/base/testing/mock_mmio.h"
+#include "sw/device/lib/testing/mask_rom_test.h"
+#include "sw/device/silicon_creator/lib/base/mock_sec_mmio.h"
#include "sw/device/silicon_creator/lib/error.h"
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "otp_ctrl_regs.h" // Generated.
namespace otp_unittest {
namespace {
-using ::mock_mmio::MmioTest;
-using ::testing::Test;
+using ::testing::ElementsAreArray;
-class OtpTest : public Test, public MmioTest {
+class OtpTest : public mask_rom_test::MaskRomTest {
protected:
- otp_t otp_ = {.base_addr = dev().region()};
+ uint32_t base_ = TOP_EARLGREY_OTP_CTRL_BASE_ADDR;
+ mask_rom_test::MockSecMmio mmio_;
};
class OtpReadTest : public OtpTest {
@@ -27,46 +29,54 @@
};
TEST_F(OtpReadTest, Read32) {
- EXPECT_READ32(offset_, 0x00010203);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_, 0x00010203);
- EXPECT_EQ(otp_read32(&otp_, 0), 0x00010203);
+ EXPECT_EQ(otp_read32(0), 0x00010203);
}
TEST_F(OtpReadTest, Read64) {
- EXPECT_READ32(offset_ + 8, 0x04050607);
- EXPECT_READ32(offset_ + 4, 0x08090A0B);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_ + 8, 0x04050607);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_ + 4, 0x08090A0B);
- EXPECT_EQ(otp_read64(&otp_, 4), 0x0405060708090A0B);
+ EXPECT_EQ(otp_read64(4), 0x0405060708090A0B);
}
TEST_F(OtpReadTest, ReadLen32) {
- EXPECT_READ32(offset_, 0x08090A0B);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_, 0x08090A0B);
uint32_t value = 0;
- otp_read(&otp_, 0, &value, sizeof(value));
+ EXPECT_EQ(otp_read(0, &value, sizeof(value)), kErrorOk);
EXPECT_EQ(value, 0x08090A0B);
}
TEST_F(OtpReadTest, ReadLen64) {
- EXPECT_READ32(offset_, 0x0C0D0E0F);
- EXPECT_READ32(offset_ + 4, 0x08090A0B);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_, 0x0C0D0E0F);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_ + 4, 0x08090A0B);
uint64_t value = 0;
- otp_read(&otp_, 0, &value, sizeof(value));
+ EXPECT_EQ(otp_read(0, &value, sizeof(value)), kErrorOk);
EXPECT_EQ(value, 0x08090A0B0C0D0E0F);
}
TEST_F(OtpReadTest, ReadLenN) {
for (int val = 0; val < 16; ++val) {
- EXPECT_READ32(offset_ + val * sizeof(uint32_t), val);
+ EXPECT_SEC_READ32(mmio_, base_ + offset_ + val * sizeof(uint32_t), val);
}
std::vector<uint32_t> arr(16);
- otp_read(&otp_, 0, &arr[0], arr.size() * sizeof(uint32_t));
+ EXPECT_EQ(otp_read(0, &arr[0], arr.size() * sizeof(uint32_t)), kErrorOk);
- for (int i = 0; i < arr.size(); ++i) {
- EXPECT_EQ(arr[i], i);
- }
+ std::vector<uint32_t> expected(arr.size());
+ std::iota(expected.begin(), expected.end(), 0);
+ EXPECT_THAT(arr, ElementsAreArray(expected));
+}
+
+TEST_F(OtpReadTest, ReadLenNMisaligned) {
+ std::vector<uint32_t> arr(16);
+ EXPECT_EQ(otp_read(1, &arr[0], arr.size() * sizeof(uint32_t)),
+ kErrorOtpBadAlignment);
+ EXPECT_EQ(otp_read(0, &arr[0], arr.size() * sizeof(uint32_t) - 1),
+ kErrorOtpBadAlignment);
}
} // namespace
diff --git a/sw/device/silicon_creator/lib/error.h b/sw/device/silicon_creator/lib/error.h
index 9f32d6c..69b0167 100644
--- a/sw/device/silicon_creator/lib/error.h
+++ b/sw/device/silicon_creator/lib/error.h
@@ -33,6 +33,7 @@
kModuleRomextimage = 0x4552, // ASCII "RE".
kModuleInterrupt = 0x5249, // ASCII "IR".
kModuleEpmp = 0x5045, // ASCII "EP",
+ kModuleOtp = 0x504f, // ASCII "OP".
};
/**
@@ -79,6 +80,7 @@
/* The high-byte of kErrorInterrupt is modified with the interrupt cause */ \
X(kErrorInterrupt, ERROR_(0, kModuleInterrupt, kUnknown)), \
X(kErrorEpmpBadCheck, ERROR_(1, kModuleEpmp, kInternal)), \
+ X(kErrorOtpBadAlignment, ERROR_(1, kModuleOtp, kInvalidArgument)), \
X(kErrorUnknown, 0xFFFFFFFF)
// clang-format on