Software APIs
spi_device_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/spi_device.h"
6 
7 #include <array>
8 #include <cstring>
9 #include <limits>
10 
11 #include "gtest/gtest.h"
12 #include "sw/device/lib/base/mock_abs_mmio.h"
13 #include "sw/device/silicon_creator/lib/drivers/mock_lifecycle.h"
14 #include "sw/device/silicon_creator/lib/error.h"
15 #include "sw/device/silicon_creator/testing/rom_test.h"
16 
17 #include "flash_ctrl_regs.h"
19 #include "spi_device_regs.h"
20 
21 namespace spi_device_unittest {
22 namespace {
23 using ::testing::NotNull;
24 using ::testing::SetArgPointee;
25 
27  protected:
28  uint32_t base_ = TOP_EARLGREY_SPI_DEVICE_BASE_ADDR;
29  rom_test::MockAbsMmio mmio_;
30  rom_test::MockLifecycle lifecycle_;
31 };
32 
33 class InitTest : public SpiDeviceTest {};
34 
35 TEST_F(InitTest, Init) {
36  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_CFG_REG_OFFSET,
37  {
38  {SPI_DEVICE_CFG_TX_ORDER_BIT, 0},
39  {SPI_DEVICE_CFG_RX_ORDER_BIT, 0},
40  {SPI_DEVICE_CFG_MAILBOX_EN_BIT, 0},
41  });
42  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_ADDR_MODE_REG_OFFSET,
43  {
44  {SPI_DEVICE_ADDR_MODE_ADDR_4B_EN_BIT, 0},
45  });
46  EXPECT_ABS_WRITE32(
47  base_ + SPI_DEVICE_JEDEC_CC_REG_OFFSET,
48  {
49  {SPI_DEVICE_JEDEC_CC_CC_OFFSET, kSpiDeviceJedecContCode},
50  {SPI_DEVICE_JEDEC_CC_NUM_CC_OFFSET, kSpiDeviceJedecContCodeCount},
51  });
52  lifecycle_hw_rev_t hw_rev{
53  .silicon_creator_id = 5, // TODO: unused in the mapping at the moment
54  .product_id = 1,
55  .revision_id = 3,
56  };
57  EXPECT_CALL(lifecycle_, HwRev(NotNull())).WillOnce(SetArgPointee<0>(hw_rev));
58 
59  EXPECT_ABS_WRITE32(
60  base_ + SPI_DEVICE_JEDEC_ID_REG_OFFSET,
61  {
62  {SPI_DEVICE_DEV_ID_CHIP_REV_FIELD.index, hw_rev.revision_id},
63  {SPI_DEVICE_DEV_ID_ROM_BOOTSTRAP_BIT, 1},
64  {SPI_DEVICE_DEV_ID_CHIP_GEN_FIELD.index, hw_rev.product_id},
65  {SPI_DEVICE_DEV_ID_DENSITY_FIELD.index,
67  FLASH_CTRL_PARAM_REG_NUM_BANKS *
68  FLASH_CTRL_PARAM_BYTES_PER_BANK)},
69  {SPI_DEVICE_JEDEC_ID_MF_OFFSET, kSpiDeviceJedecManufId},
70  });
71 
72  std::array<uint32_t, kSpiDeviceSfdpAreaNumBytes / sizeof(uint32_t)>
73  sfdp_buffer;
74  sfdp_buffer.fill(std::numeric_limits<uint32_t>::max());
75  std::memcpy(sfdp_buffer.data(), &kSpiDeviceSfdpTable,
76  sizeof(kSpiDeviceSfdpTable));
77  uint32_t offset =
78  base_ + SPI_DEVICE_EGRESS_BUFFER_REG_OFFSET + kSpiDeviceSfdpAreaOffset;
79  for (size_t i = 0; i < sfdp_buffer.size(); ++i) {
80  EXPECT_ABS_WRITE32(offset, sfdp_buffer[i]);
81  offset += sizeof(uint32_t);
82  }
83 
84  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_FLASH_STATUS_REG_OFFSET, 0);
85 
86  EXPECT_ABS_WRITE32(
87  base_ + SPI_DEVICE_CMD_INFO_0_REG_OFFSET,
88  {
89  {SPI_DEVICE_CMD_INFO_0_OPCODE_0_OFFSET, kSpiDeviceOpcodeReadStatus},
90  {SPI_DEVICE_CMD_INFO_0_VALID_0_BIT, 1},
91  });
92 
93  EXPECT_ABS_WRITE32(
94  base_ + SPI_DEVICE_CMD_INFO_3_REG_OFFSET,
95  {
96  {SPI_DEVICE_CMD_INFO_3_OPCODE_3_OFFSET, kSpiDeviceOpcodeReadJedecId},
97  {SPI_DEVICE_CMD_INFO_3_VALID_3_BIT, 1},
98  });
99 
100  EXPECT_ABS_WRITE32(
101  base_ + SPI_DEVICE_CMD_INFO_4_REG_OFFSET,
102  {
103  {SPI_DEVICE_CMD_INFO_4_OPCODE_4_OFFSET, kSpiDeviceOpcodeReadSfdp},
104  {SPI_DEVICE_CMD_INFO_4_ADDR_MODE_4_OFFSET,
105  SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR3B},
106  {SPI_DEVICE_CMD_INFO_4_DUMMY_SIZE_4_OFFSET, 7},
107  {SPI_DEVICE_CMD_INFO_4_DUMMY_EN_4_BIT, 1},
108  {SPI_DEVICE_CMD_INFO_4_VALID_4_BIT, 1},
109  });
110 
111  EXPECT_ABS_WRITE32(
112  base_ + SPI_DEVICE_CMD_INFO_11_REG_OFFSET,
113  {
114  {SPI_DEVICE_CMD_INFO_11_OPCODE_11_OFFSET, kSpiDeviceOpcodeChipErase},
115  {SPI_DEVICE_CMD_INFO_11_UPLOAD_11_BIT, 1},
116  {SPI_DEVICE_CMD_INFO_11_BUSY_11_BIT, 1},
117  {SPI_DEVICE_CMD_INFO_11_VALID_11_BIT, 1},
118  });
119 
120  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_CMD_INFO_12_REG_OFFSET,
121  {
122  {SPI_DEVICE_CMD_INFO_12_OPCODE_12_OFFSET,
123  kSpiDeviceOpcodeSectorErase},
124  {SPI_DEVICE_CMD_INFO_12_ADDR_MODE_12_OFFSET,
125  SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR3B},
126  {SPI_DEVICE_CMD_INFO_12_UPLOAD_12_BIT, 1},
127  {SPI_DEVICE_CMD_INFO_12_BUSY_12_BIT, 1},
128  {SPI_DEVICE_CMD_INFO_12_VALID_12_BIT, 1},
129  });
130 
131  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_CMD_INFO_13_REG_OFFSET,
132  {
133  {SPI_DEVICE_CMD_INFO_13_OPCODE_13_OFFSET,
134  kSpiDeviceOpcodePageProgram},
135  {SPI_DEVICE_CMD_INFO_13_ADDR_MODE_13_OFFSET,
136  SPI_DEVICE_CMD_INFO_0_ADDR_MODE_0_VALUE_ADDR3B},
137  {SPI_DEVICE_CMD_INFO_13_UPLOAD_13_BIT, 1},
138  {SPI_DEVICE_CMD_INFO_13_BUSY_13_BIT, 1},
139  {SPI_DEVICE_CMD_INFO_13_VALID_13_BIT, 1},
140  });
141 
142  EXPECT_ABS_WRITE32(
143  base_ + SPI_DEVICE_CMD_INFO_14_REG_OFFSET,
144  {
145  {SPI_DEVICE_CMD_INFO_14_OPCODE_14_OFFSET, kSpiDeviceOpcodeReset},
146  {SPI_DEVICE_CMD_INFO_14_UPLOAD_14_BIT, 1},
147  {SPI_DEVICE_CMD_INFO_14_BUSY_14_BIT, 1},
148  {SPI_DEVICE_CMD_INFO_14_VALID_14_BIT, 1},
149  });
150 
151  EXPECT_ABS_WRITE32(
152  base_ + SPI_DEVICE_CMD_INFO_WREN_REG_OFFSET,
153  {
154  {SPI_DEVICE_CMD_INFO_WREN_OPCODE_OFFSET, kSpiDeviceOpcodeWriteEnable},
155  {SPI_DEVICE_CMD_INFO_WREN_VALID_BIT, 1},
156  });
157 
158  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_CMD_INFO_WRDI_REG_OFFSET,
159  {
160  {SPI_DEVICE_CMD_INFO_WRDI_OPCODE_OFFSET,
161  kSpiDeviceOpcodeWriteDisable},
162  {SPI_DEVICE_CMD_INFO_WRDI_VALID_BIT, 1},
163  });
164 
165  spi_device_init();
166 }
167 
168 TEST_F(SpiDeviceTest, FlashStatusClear) {
169  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_FLASH_STATUS_REG_OFFSET, 0);
170 
171  spi_device_flash_status_clear();
172 }
173 
174 TEST_F(SpiDeviceTest, FlashStatusGet) {
175  EXPECT_ABS_READ32(base_ + SPI_DEVICE_FLASH_STATUS_REG_OFFSET, 0xa5);
176 
177  EXPECT_EQ(0xa5, spi_device_flash_status_get());
178 }
179 
181  spi_device_opcode_t opcode;
182  uint32_t address;
183  std::vector<uint8_t> payload;
184 };
185 
186 class CmdGetTest : public SpiDeviceTest,
187  public testing::WithParamInterface<CmdGetTestCase> {};
188 
189 TEST_F(CmdGetTest, PayloadOverflow) {
190  EXPECT_ABS_READ32(base_ + SPI_DEVICE_INTR_STATE_REG_OFFSET, 0);
191  EXPECT_ABS_READ32(base_ + SPI_DEVICE_INTR_STATE_REG_OFFSET,
192  {
193  {SPI_DEVICE_INTR_STATE_UPLOAD_CMDFIFO_NOT_EMPTY_BIT, 1},
194  {SPI_DEVICE_INTR_STATE_UPLOAD_PAYLOAD_OVERFLOW_BIT, 1},
195  });
196  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_INTR_STATE_REG_OFFSET,
197  std::numeric_limits<uint32_t>::max());
198 
199  spi_device_cmd_t cmd;
200  EXPECT_EQ(spi_device_cmd_get(&cmd), kErrorSpiDevicePayloadOverflow);
201 }
202 
203 TEST_P(CmdGetTest, CmdGet) {
204  bool has_address = GetParam().address != kSpiDeviceNoAddress;
205 
206  EXPECT_ABS_READ32(base_ + SPI_DEVICE_INTR_STATE_REG_OFFSET, 0);
207  EXPECT_ABS_READ32(base_ + SPI_DEVICE_INTR_STATE_REG_OFFSET,
208  {{SPI_DEVICE_INTR_STATE_UPLOAD_CMDFIFO_NOT_EMPTY_BIT, 1}});
209  EXPECT_ABS_WRITE32(base_ + SPI_DEVICE_INTR_STATE_REG_OFFSET,
210  std::numeric_limits<uint32_t>::max());
211 
212  EXPECT_ABS_READ32(base_ + SPI_DEVICE_UPLOAD_CMDFIFO_REG_OFFSET,
213  GetParam().opcode);
214 
215  EXPECT_ABS_READ32(
216  base_ + SPI_DEVICE_UPLOAD_STATUS_REG_OFFSET,
217  {{SPI_DEVICE_UPLOAD_STATUS_ADDRFIFO_NOTEMPTY_BIT, has_address}});
218  if (has_address) {
219  EXPECT_ABS_READ32(base_ + SPI_DEVICE_UPLOAD_ADDRFIFO_REG_OFFSET,
220  GetParam().address);
221  }
222 
223  std::vector<uint32_t> payload_area(kSpiDevicePayloadAreaNumWords,
224  std::numeric_limits<uint32_t>::max());
225  std::memcpy(payload_area.data(), GetParam().payload.data(),
226  GetParam().payload.size());
227  EXPECT_ABS_READ32(base_ + SPI_DEVICE_UPLOAD_STATUS2_REG_OFFSET,
228  {{SPI_DEVICE_UPLOAD_STATUS2_PAYLOAD_DEPTH_OFFSET,
229  GetParam().payload.size()}});
230  uint32_t offset = base_ + SPI_DEVICE_INGRESS_BUFFER_REG_OFFSET +
231  kSpiDevicePayloadAreaOffset;
232  for (size_t i = 0; i < GetParam().payload.size(); i += sizeof(uint32_t)) {
233  EXPECT_ABS_READ32(offset + i, payload_area[i / sizeof(uint32_t)]);
234  }
235 
236  spi_device_cmd_t cmd;
237  EXPECT_EQ(spi_device_cmd_get(&cmd), kErrorOk);
238  EXPECT_EQ(cmd.opcode, GetParam().opcode);
239  EXPECT_EQ(cmd.address, GetParam().address);
240  EXPECT_EQ(cmd.payload_byte_count, GetParam().payload.size());
241  std::vector<uint8_t> payload(cmd.payload, std::end(cmd.payload));
242  payload.resize(cmd.payload_byte_count);
243  EXPECT_THAT(payload, GetParam().payload);
244 }
245 
246 INSTANTIATE_TEST_SUITE_P(
247  CmdGetTestCases, CmdGetTest,
248  testing::Values(
249  CmdGetTestCase{
250  .opcode = kSpiDeviceOpcodeChipErase,
251  .address = kSpiDeviceNoAddress,
252  .payload = {},
253  },
254  CmdGetTestCase{
255  .opcode = kSpiDeviceOpcodeSectorErase,
256  .address = 0x00,
257  .payload = {},
258  },
259  CmdGetTestCase{
260  .opcode = kSpiDeviceOpcodePageProgram,
261  .address = 0x0a0b0c,
262  .payload = {0x01, 0x02, 0x03, 0x04},
263  },
264  CmdGetTestCase{
265  .opcode = kSpiDeviceOpcodePageProgram,
266  .address = 0x0a0b0c,
267  .payload = {0x01, 0x02, 0x03, 0x04, 0x05},
268  },
269  CmdGetTestCase{
270  .opcode = kSpiDeviceOpcodePageProgram,
271  .address = 0x0a0b0c,
272  .payload = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
273  },
274  CmdGetTestCase{
275  .opcode = kSpiDeviceOpcodePageProgram,
276  .address = 0x0a0b0c,
277  .payload = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07},
278  },
279  CmdGetTestCase{
280  .opcode = kSpiDeviceOpcodePageProgram,
281  .address = 0x0a0b0c,
282  .payload = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
283  }));
284 
285 } // namespace
286 } // namespace spi_device_unittest