Software APIs
otp_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/silicon_creator/lib/drivers/otp.h"
6 
7 #include <array>
8 
9 #include "gtest/gtest.h"
11 #include "sw/device/lib/base/mock_abs_mmio.h"
12 #include "sw/device/silicon_creator/lib/base/mock_sec_mmio.h"
13 #include "sw/device/silicon_creator/lib/error.h"
14 #include "sw/device/silicon_creator/testing/rom_test.h"
15 
17 #include "otp_ctrl_regs.h" // Generated.
18 
19 namespace otp_unittest {
20 namespace {
21 using ::testing::ElementsAre;
22 using ::testing::ElementsAreArray;
23 
24 constexpr int kMaxOtpWordsToRead = 10;
25 
26 class OtpTest : public rom_test::RomTest {
27  protected:
28  uint32_t base_ = TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR;
29  rom_test::MockSecMmio mmio_;
30  rom_test::MockAbsMmio abs_mmio_;
31 };
32 
33 TEST_F(OtpTest, CreatorSwCfgLockdown) {
34  EXPECT_SEC_WRITE32(base_ + OTP_CTRL_CREATOR_SW_CFG_READ_LOCK_REG_OFFSET, 0);
35 
36  otp_creator_sw_cfg_lockdown();
37 }
38 
39 class OtpReadTest : public OtpTest {
40  protected:
41  const ptrdiff_t mmap_window_offset_ = OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET;
42  void ExpectDaiIdleCheck(bool idle) {
43  EXPECT_ABS_READ32(base_ + OTP_CTRL_STATUS_REG_OFFSET,
44  {{OTP_CTRL_STATUS_DAI_IDLE_BIT, idle}});
45  }
46 };
47 
48 TEST_F(OtpReadTest, Read32) {
49  EXPECT_SEC_READ32(base_ + mmap_window_offset_, 0x00010203);
50 
51  EXPECT_EQ(otp_read32(0), 0x00010203);
52 }
53 
54 TEST_F(OtpReadTest, Read64) {
55  EXPECT_SEC_READ32(base_ + mmap_window_offset_ + 8, 0x04050607);
56  EXPECT_SEC_READ32(base_ + mmap_window_offset_ + 4, 0x08090A0B);
57 
58  EXPECT_EQ(otp_read64(4), 0x0405060708090A0B);
59 }
60 
61 TEST_F(OtpReadTest, ReadLen32) {
62  EXPECT_SEC_READ32(base_ + mmap_window_offset_, 0x08090A0B);
63 
64  uint32_t value = 0;
65  otp_read(0, &value, 1);
66  EXPECT_EQ(value, 0x08090A0B);
67 }
68 
69 TEST_F(OtpReadTest, ReadLen64) {
70  EXPECT_SEC_READ32(base_ + mmap_window_offset_, 0x0C0D0E0F);
71  EXPECT_SEC_READ32(base_ + mmap_window_offset_ + 4, 0x08090A0B);
72 
73  std::array<uint32_t, 2> buf;
74  otp_read(0, buf.data(), 2);
75  EXPECT_THAT(buf, ElementsAre(0x0C0D0E0F, 0x08090A0B));
76 }
77 
78 TEST_F(OtpReadTest, ReadLenN) {
79  for (int val = 0; val < 16; ++val) {
80  EXPECT_SEC_READ32(base_ + mmap_window_offset_ + val * sizeof(uint32_t),
81  val);
82  }
83 
84  std::array<uint32_t, 16> arr;
85  otp_read(0, arr.data(), arr.size());
86 
87  std::array<uint32_t, 16> expected;
88  std::iota(expected.begin(), expected.end(), 0);
89  EXPECT_THAT(arr, ElementsAreArray(expected));
90 }
91 
93  otp_partition_t partition;
94  uint32_t digest_offest;
95 };
96 
98  : public OtpTest,
99  public testing::WithParamInterface<DigestReadTestCase> {};
100 
101 TEST_P(OtpPartitionDigestTest, ReadDigest) {
102  EXPECT_SEC_READ32(base_ + GetParam().digest_offest + sizeof(uint32_t),
103  0x12345678);
104  EXPECT_SEC_READ32(base_ + GetParam().digest_offest, 0x87654321);
105  EXPECT_EQ(otp_partition_digest_read(GetParam().partition),
106  0x1234567887654321);
107 }
108 
109 INSTANTIATE_TEST_SUITE_P(
110  ReadPartitionDigests, OtpPartitionDigestTest,
111  testing::Values(
112  DigestReadTestCase{
113  .partition = kOtpPartitionCreatorSwCfg,
114  .digest_offest = OTP_CTRL_CREATOR_SW_CFG_DIGEST_0_REG_OFFSET,
115  },
116  DigestReadTestCase{
117  .partition = kOtpPartitionOwnerSwCfg,
118  .digest_offest = OTP_CTRL_OWNER_SW_CFG_DIGEST_0_REG_OFFSET,
119  },
120  DigestReadTestCase{
121  .partition = kOtpPartitionRotCreatorAuthCodesign,
122  .digest_offest =
123  OTP_CTRL_ROT_CREATOR_AUTH_CODESIGN_DIGEST_0_REG_OFFSET,
124  },
125  DigestReadTestCase{
126  .partition = kOtpPartitionRotCreatorAuthState,
127  .digest_offest =
128  OTP_CTRL_ROT_CREATOR_AUTH_STATE_DIGEST_0_REG_OFFSET,
129  },
130  DigestReadTestCase{
131  .partition = kOtpPartitionHwCfg0,
132  .digest_offest = OTP_CTRL_HW_CFG0_DIGEST_0_REG_OFFSET,
133  },
134  DigestReadTestCase{
135  .partition = kOtpPartitionHwCfg1,
136  .digest_offest = OTP_CTRL_HW_CFG1_DIGEST_0_REG_OFFSET,
137  }));
138 
140  public testing::WithParamInterface<int> {};
141 
142 TEST_F(OtpDaiReadTest, Read32) {
143  ExpectDaiIdleCheck(true);
144  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_ADDRESS_REG_OFFSET,
145  OTP_CTRL_PARAM_CREATOR_SW_CFG_OFFSET);
146  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_CMD_REG_OFFSET, 0x1);
147  ExpectDaiIdleCheck(true);
148  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_0_REG_OFFSET,
149  0x00010203);
150  EXPECT_EQ(otp_dai_read32(kOtpPartitionCreatorSwCfg, 0), 0x00010203);
151 }
152 
153 TEST_F(OtpDaiReadTest, Read32WithIdleWait) {
154  ExpectDaiIdleCheck(false);
155  ExpectDaiIdleCheck(false);
156  ExpectDaiIdleCheck(true);
157  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_ADDRESS_REG_OFFSET,
158  OTP_CTRL_PARAM_CREATOR_SW_CFG_OFFSET);
159  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_CMD_REG_OFFSET, 0x1);
160  ExpectDaiIdleCheck(false);
161  ExpectDaiIdleCheck(true);
162  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_0_REG_OFFSET,
163  0x00010203);
164  EXPECT_EQ(otp_dai_read32(kOtpPartitionCreatorSwCfg, 0), 0x00010203);
165 }
166 
167 TEST_F(OtpDaiReadTest, Read64) {
168  ExpectDaiIdleCheck(true);
169  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_ADDRESS_REG_OFFSET,
170  OTP_CTRL_PARAM_OWNER_SW_CFG_OFFSET + 4);
171  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_CMD_REG_OFFSET, 0x1);
172  ExpectDaiIdleCheck(true);
173  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_1_REG_OFFSET,
174  0x00010203);
175  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_0_REG_OFFSET,
176  0x00040506);
177  EXPECT_EQ(otp_dai_read64(kOtpPartitionOwnerSwCfg, 4), 0x0001020300040506);
178 }
179 
180 TEST_F(OtpDaiReadTest, Read64WithIdleWait) {
181  ExpectDaiIdleCheck(false);
182  ExpectDaiIdleCheck(true);
183  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_ADDRESS_REG_OFFSET,
184  OTP_CTRL_PARAM_CREATOR_SW_CFG_OFFSET);
185  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_CMD_REG_OFFSET, 0x1);
186  ExpectDaiIdleCheck(false);
187  ExpectDaiIdleCheck(false);
188  ExpectDaiIdleCheck(true);
189  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_1_REG_OFFSET,
190  0x00010203);
191  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_0_REG_OFFSET,
192  0x00040506);
193  EXPECT_EQ(otp_dai_read64(kOtpPartitionCreatorSwCfg, 0), 0x0001020300040506);
194 }
195 
196 TEST_P(OtpDaiReadTest, ReadLenN32bitWords) {
197  size_t num_words_to_read = GetParam();
198  for (size_t i = 0; i < num_words_to_read; ++i) {
199  ExpectDaiIdleCheck(true);
200  EXPECT_ABS_WRITE32(
201  base_ + OTP_CTRL_DIRECT_ACCESS_ADDRESS_REG_OFFSET,
202  OTP_CTRL_PARAM_OWNER_SW_CFG_OFFSET + i * sizeof(uint32_t));
203  EXPECT_ABS_WRITE32(base_ + OTP_CTRL_DIRECT_ACCESS_CMD_REG_OFFSET, 0x1);
204  ExpectDaiIdleCheck(true);
205  EXPECT_ABS_READ32(base_ + OTP_CTRL_DIRECT_ACCESS_RDATA_0_REG_OFFSET,
206  0x01020300 + i);
207  }
208 
209  uint32_t data[kMaxOtpWordsToRead] = {0};
210  otp_dai_read(kOtpPartitionOwnerSwCfg, 0, data, num_words_to_read);
211  for (size_t i = 0; i < num_words_to_read; ++i) {
212  EXPECT_EQ(data[i], 0x01020300 + i);
213  }
214 }
215 
216 INSTANTIATE_TEST_SUITE_P(Read32bitWordArrays, OtpDaiReadTest,
217  testing::Range(0, kMaxOtpWordsToRead));
218 
219 } // namespace
220 } // namespace otp_unittest