[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