Software APIs
dif_spi_host_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 
6 
7 #include <array>
8 #include <utility>
9 
10 #include "gtest/gtest.h"
11 #include "sw/device/lib/base/global_mock.h"
14 #include "sw/device/lib/base/mock_mmio.h"
16 
17 #include "spi_host_regs.h" // Generated.
18 
19 namespace dif_spi_host_unittest {
20 namespace {
21 
22 // Mock out the spi_host_fifo functions.
23 namespace internal {
24 class MockFifo : public ::global_mock::GlobalMock<MockFifo> {
25  public:
26  MOCK_METHOD(void, write, (const dif_spi_host_t *, const void *, uint16_t));
27  MOCK_METHOD(void, read, (const dif_spi_host_t *, void *, uint16_t));
28 };
29 } // namespace internal
30 using MockFifo = testing::StrictMock<internal::MockFifo>;
31 extern "C" {
32 dif_result_t spi_host_fifo_write_alias(const dif_spi_host_t *spi_host,
33  const void *src, uint16_t len) {
34  MockFifo::Instance().write(spi_host, src, len);
35  return kDifOk;
36 }
37 dif_result_t spi_host_fifo_read_alias(const dif_spi_host_t *spi_host, void *dst,
38  uint16_t len) {
39  MockFifo::Instance().read(spi_host, dst, len);
40  return kDifOk;
41 }
42 }
43 
46 using testing::ElementsAre;
47 using testing::Test;
48 
49 // Helper macros to make expectations easier to read.
50 #define EXPECT_COMMAND_REG(length, width, direction, last_segment) \
51  EXPECT_WRITE32(SPI_HOST_COMMAND_REG_OFFSET, \
52  { \
53  {SPI_HOST_COMMAND_LEN_OFFSET, (length)-1}, \
54  {SPI_HOST_COMMAND_SPEED_OFFSET, width}, \
55  {SPI_HOST_COMMAND_DIRECTION_OFFSET, direction}, \
56  {SPI_HOST_COMMAND_CSAAT_BIT, !(last_segment)}, \
57  })
58 
59 #define EXPECT_READY(ready) \
60  EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, \
61  {{SPI_HOST_STATUS_READY_BIT, ready}})
62 
63 #define EXPECT_TXQD(txqd) \
64  EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, \
65  {{SPI_HOST_STATUS_TXQD_OFFSET, txqd}})
66 
67 #define EXPECT_RXQD(rxqd) \
68  EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, \
69  {{SPI_HOST_STATUS_RXQD_OFFSET, rxqd}})
70 
71 class SpiHostTest : public Test, public MmioTest {
72  protected:
73  void ExpectDeviceReset() {
74  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
75  // Place IP into reset.
76  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
77  {
78  {SPI_HOST_CONTROL_SW_RST_BIT, true},
79  });
80  // Active bit should be clear.
81  EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, 0);
82  // TXQD and RXQD should be zeros.
83  EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, 0);
84  // Release IP from reset.
85  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
86  {
87  {SPI_HOST_CONTROL_SW_RST_BIT, false},
88  });
89  }
90 
91  dif_spi_host_t spi_host_ = {
92  .base_addr = dev().region(),
93  };
94 
95  dif_spi_host_config config_ = {
96  .spi_clock = 500000,
97  .peripheral_clock_freq_hz = 1000000,
98  .chip_select =
99  {
100  .idle = 0,
101  .trail = 0,
102  .lead = 0,
103  },
104  .full_cycle = false,
105  .cpha = false,
106  .cpol = false,
107  .tx_watermark = 0,
108  .rx_watermark = 0,
109  };
110 };
111 
112 class ConfigTest : public SpiHostTest {};
113 
114 TEST_F(ConfigTest, NullArgs) {
115  EXPECT_DIF_BADARG(dif_spi_host_configure(nullptr, config_));
116 }
117 
118 TEST_F(ConfigTest, BadDivider) {
119  // A spi_clock faster than the peripheral clock is invalid.
120  config_.spi_clock = 1000001;
121  EXPECT_DIF_BADARG(dif_spi_host_configure(&spi_host_, config_));
122 
123  // A spi_clock of zero is invalid.
124  config_.spi_clock = 0;
125  EXPECT_DIF_BADARG(dif_spi_host_configure(&spi_host_, config_));
126 }
127 
128 // Checks the default configuration.
129 TEST_F(ConfigTest, Default) {
130  ExpectDeviceReset();
131  EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
132  {
133  {SPI_HOST_CONFIGOPTS_CLKDIV_OFFSET, 0},
134  {SPI_HOST_CONFIGOPTS_CSNIDLE_OFFSET, 0},
135  {SPI_HOST_CONFIGOPTS_CSNTRAIL_OFFSET, 0},
136  {SPI_HOST_CONFIGOPTS_CSNLEAD_OFFSET, 0},
137  {SPI_HOST_CONFIGOPTS_FULLCYC_BIT, false},
138  {SPI_HOST_CONFIGOPTS_CPHA_BIT, false},
139  {SPI_HOST_CONFIGOPTS_CPOL_BIT, false},
140  });
141 
142  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
143  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET, 0);
144  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
145  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
146  {
147  {SPI_HOST_CONTROL_SPIEN_BIT, true},
148  });
149 
150  EXPECT_DIF_OK(dif_spi_host_configure(&spi_host_, config_));
151 }
152 
153 // Checks the arguments to the output-enablement DIF are validated.
154 TEST_F(ConfigTest, OutputSetEnabledNullHandle) {
156 }
157 
158 // Checks manipulation of the output enable bit.
159 TEST_F(ConfigTest, OutputEnable) {
160  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
161  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
162  {
163  {SPI_HOST_CONTROL_OUTPUT_EN_BIT, true},
164  });
166 }
167 
168 // Checks that the clock divider gets calculated correctly.
169 TEST_F(ConfigTest, ClockRate) {
170  config_.spi_clock = 500000;
171 
172  ExpectDeviceReset();
173  EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
174  {
175  {SPI_HOST_CONFIGOPTS_CLKDIV_OFFSET, 0},
176  {SPI_HOST_CONFIGOPTS_CSNIDLE_OFFSET, 0},
177  {SPI_HOST_CONFIGOPTS_CSNTRAIL_OFFSET, 0},
178  {SPI_HOST_CONFIGOPTS_CSNLEAD_OFFSET, 0},
179  {SPI_HOST_CONFIGOPTS_FULLCYC_BIT, false},
180  {SPI_HOST_CONFIGOPTS_CPHA_BIT, false},
181  {SPI_HOST_CONFIGOPTS_CPOL_BIT, false},
182  });
183  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
184  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET, 0);
185  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
186  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
187  {
188  {SPI_HOST_CONTROL_SPIEN_BIT, true},
189  });
190 
191  EXPECT_DIF_OK(dif_spi_host_configure(&spi_host_, config_));
192 }
193 
194 // Checks that the chip select options get written to the appropriate fields in
195 // the config register.
196 TEST_F(ConfigTest, ChipSelectOptions) {
197  config_.chip_select.idle = 1;
198  config_.chip_select.trail = 2;
199  config_.chip_select.lead = 3;
200 
201  ExpectDeviceReset();
202  EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
203  {
204  {SPI_HOST_CONFIGOPTS_CLKDIV_OFFSET, 0},
205  {SPI_HOST_CONFIGOPTS_CSNIDLE_OFFSET, 1},
206  {SPI_HOST_CONFIGOPTS_CSNTRAIL_OFFSET, 2},
207  {SPI_HOST_CONFIGOPTS_CSNLEAD_OFFSET, 3},
208  {SPI_HOST_CONFIGOPTS_FULLCYC_BIT, false},
209  {SPI_HOST_CONFIGOPTS_CPHA_BIT, false},
210  {SPI_HOST_CONFIGOPTS_CPOL_BIT, false},
211  });
212  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
213  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET, 0);
214  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
215  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
216  {
217  {SPI_HOST_CONTROL_SPIEN_BIT, true},
218  });
219 
220  EXPECT_DIF_OK(dif_spi_host_configure(&spi_host_, config_));
221 }
222 
223 // Checks that the SPI cycle, polarity and phase options get written to the
224 // appropriate fields in the config register.
225 TEST_F(ConfigTest, SpiOptions) {
226  config_.full_cycle = true;
227  config_.cpol = true;
228  config_.cpha = true;
229 
230  ExpectDeviceReset();
231  EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
232  {
233  {SPI_HOST_CONFIGOPTS_CLKDIV_OFFSET, 0},
234  {SPI_HOST_CONFIGOPTS_CSNIDLE_OFFSET, 0},
235  {SPI_HOST_CONFIGOPTS_CSNTRAIL_OFFSET, 0},
236  {SPI_HOST_CONFIGOPTS_CSNLEAD_OFFSET, 0},
237  {SPI_HOST_CONFIGOPTS_FULLCYC_BIT, true},
238  {SPI_HOST_CONFIGOPTS_CPHA_BIT, true},
239  {SPI_HOST_CONFIGOPTS_CPOL_BIT, true},
240  });
241  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
242  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET, 0);
243  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
244  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
245  {
246  {SPI_HOST_CONTROL_SPIEN_BIT, true},
247  });
248 
249  EXPECT_DIF_OK(dif_spi_host_configure(&spi_host_, config_));
250 }
251 
252 // Checks the SPI tx and rx watermark.
253 TEST_F(ConfigTest, SpiTxRxWatermark) {
254  config_.tx_watermark = 0x7f;
255  config_.rx_watermark = 0x7e;
256 
257  ExpectDeviceReset();
258  EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
259  {
260  {SPI_HOST_CONFIGOPTS_CLKDIV_OFFSET, 0},
261  {SPI_HOST_CONFIGOPTS_CSNIDLE_OFFSET, 0},
262  {SPI_HOST_CONFIGOPTS_CSNTRAIL_OFFSET, 0},
263  {SPI_HOST_CONFIGOPTS_CSNLEAD_OFFSET, 0},
264  {SPI_HOST_CONFIGOPTS_FULLCYC_BIT, false},
265  {SPI_HOST_CONFIGOPTS_CPHA_BIT, false},
266  {SPI_HOST_CONFIGOPTS_CPOL_BIT, false},
267  });
268  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
269  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
270  {{SPI_HOST_CONTROL_TX_WATERMARK_OFFSET, 0x7f},
271  {SPI_HOST_CONTROL_RX_WATERMARK_OFFSET, 0x7e}});
272  EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
273  EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
274  {
275  {SPI_HOST_CONTROL_SPIEN_BIT, true},
276  });
277 
278  EXPECT_DIF_OK(dif_spi_host_configure(&spi_host_, config_));
279 }
280 
282  protected:
283  MockFifo fifo_;
284 };
285 
286 // Checks that an opcode segment is sent correctly.
287 TEST_F(TransactionStartTest, IssueOpcode) {
288  dif_spi_host_segment segment;
290  segment.opcode.opcode = 0x5a;
291  segment.opcode.width = kDifSpiHostWidthStandard;
292 
293  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
294  EXPECT_READY(true);
295  EXPECT_TXQD(0);
296  // Opcodes are written directly to the FIFO register.
297  EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 0x5a);
298  EXPECT_COMMAND_REG(/*length=*/1, /*width=*/kDifSpiHostWidthStandard,
299  /*direction=*/kDifSpiHostDirectionTx, /*last=*/true);
300 
301  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
302 }
303 
304 // Checks that an address segment is sent correctly in 3-byte mode.
305 TEST_F(TransactionStartTest, IssueAddressMode3b) {
306  dif_spi_host_segment segment;
308  segment.address.width = kDifSpiHostWidthStandard;
309  segment.address.mode = kDifSpiHostAddrMode3b;
310  segment.address.address = 0x112233;
311 
312  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
313  EXPECT_READY(true);
314  EXPECT_TXQD(0);
315  // SPI addresses are written directly to the FIFO register.
316  EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x332211);
317  EXPECT_COMMAND_REG(/*length=*/3, /*width=*/kDifSpiHostWidthStandard,
318  /*direction=*/kDifSpiHostDirectionTx, /*last=*/true);
319 
320  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
321 }
322 
323 // Checks that an address segment is sent correctly in 4-byte mode.
324 TEST_F(TransactionStartTest, IssueAddressMode4b) {
325  dif_spi_host_segment segment;
327  segment.address.width = kDifSpiHostWidthStandard;
328  segment.address.mode = kDifSpiHostAddrMode4b;
329  segment.address.address = 0x11223344;
330 
331  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
332  EXPECT_READY(true);
333  EXPECT_TXQD(0);
334  // SPI addresses are written directly to the FIFO register.
335  EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x44332211);
336  EXPECT_COMMAND_REG(/*length=*/4, /*width=*/kDifSpiHostWidthStandard,
337  /*direction=*/kDifSpiHostDirectionTx, /*last=*/true);
338 
339  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
340 }
341 
342 // Checks that a dummy segment is sent correctly.
343 TEST_F(TransactionStartTest, IssueDummy) {
344  dif_spi_host_segment segment;
346  segment.dummy.width = kDifSpiHostWidthStandard;
347  segment.dummy.length = 8;
348 
349  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
350  EXPECT_READY(true);
351  EXPECT_COMMAND_REG(/*length=*/8, /*width=*/kDifSpiHostWidthStandard,
352  /*direction=*/kDifSpiHostDirectionDummy, /*last=*/true);
353 
354  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
355 }
356 
357 class TransactionTest : public SpiHostTest {
358  protected:
359  MockFifo fifo_;
360 };
361 
362 // Checks that a transmit segment is sent correctly.
363 TEST_F(TransactionTest, TransmitDual) {
364  uint8_t buf[32];
365  dif_spi_host_segment segment;
366  segment.type = kDifSpiHostSegmentTypeTx;
367  segment.tx.width = kDifSpiHostWidthDual;
368  segment.tx.buf = buf;
369  segment.tx.length = sizeof(buf);
370 
371  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
372  EXPECT_READY(true);
373  EXPECT_COMMAND_REG(/*length=*/sizeof(buf), /*width=*/kDifSpiHostWidthDual,
374  /*direction=*/kDifSpiHostDirectionTx, /*last=*/true);
375  EXPECT_CALL(fifo_, write(&spi_host_, buf, sizeof(buf)));
376 
377  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
378 }
379 
380 // Checks that a receive segment is sent correctly.
381 TEST_F(TransactionTest, ReceiveQuad) {
382  uint8_t buf[32];
383  dif_spi_host_segment segment;
384  segment.type = kDifSpiHostSegmentTypeRx;
385  segment.rx.width = kDifSpiHostWidthQuad;
386  segment.rx.buf = buf;
387  segment.rx.length = sizeof(buf);
388 
389  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
390  EXPECT_READY(true);
391  EXPECT_COMMAND_REG(/*length=*/sizeof(buf), /*width=*/kDifSpiHostWidthQuad,
392  /*direction=*/kDifSpiHostDirectionRx, /*last=*/true);
393  EXPECT_CALL(fifo_, read(&spi_host_, buf, sizeof(buf)));
394 
395  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
396 }
397 
398 // Checks that a tranceive segment is sent correctly.
399 TEST_F(TransactionTest, Transceive) {
400  uint8_t txbuf[32];
401  uint8_t rxbuf[32];
402  dif_spi_host_segment segment;
404  segment.bidir.width = kDifSpiHostWidthStandard;
405  segment.bidir.txbuf = txbuf;
406  segment.bidir.rxbuf = rxbuf;
407  segment.bidir.length = sizeof(txbuf);
408 
409  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
410  EXPECT_READY(true);
411  EXPECT_COMMAND_REG(
412  /*length=*/sizeof(txbuf), /*width=*/kDifSpiHostWidthStandard,
413  /*direction=*/kDifSpiHostDirectionBidirectional, /*last=*/true);
414  EXPECT_CALL(fifo_, write(&spi_host_, txbuf, sizeof(txbuf)));
415  EXPECT_CALL(fifo_, read(&spi_host_, rxbuf, sizeof(rxbuf)));
416 
417  EXPECT_DIF_OK(dif_spi_host_transaction(&spi_host_, 0, &segment, 1));
418 }
419 
420 // Checks that multiple segments are sent correctly.
421 TEST_F(TransactionTest, MultiSegmentTxRx) {
422  uint8_t txbuf[32];
423  uint8_t rxbuf[64];
424  dif_spi_host_segment segment[2];
425 
426  segment[0].type = kDifSpiHostSegmentTypeTx;
427  segment[0].rx.width = kDifSpiHostWidthDual;
428  segment[0].rx.buf = txbuf;
429  segment[0].rx.length = sizeof(txbuf);
430  segment[1].type = kDifSpiHostSegmentTypeRx;
431  segment[1].rx.width = kDifSpiHostWidthDual;
432  segment[1].rx.buf = rxbuf;
433  segment[1].rx.length = sizeof(rxbuf);
434 
435  EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
436  EXPECT_READY(true);
437  EXPECT_COMMAND_REG(/*length=*/sizeof(txbuf), /*width=*/kDifSpiHostWidthDual,
438  /*direction=*/kDifSpiHostDirectionTx, /*last=*/false);
439  EXPECT_CALL(fifo_, write(&spi_host_, txbuf, sizeof(txbuf)));
440  EXPECT_READY(true);
441  EXPECT_COMMAND_REG(/*length=*/sizeof(rxbuf), /*width=*/kDifSpiHostWidthDual,
442  /*direction=*/kDifSpiHostDirectionRx, /*last=*/true);
443  EXPECT_CALL(fifo_, read(&spi_host_, rxbuf, sizeof(rxbuf)));
444 
446  dif_spi_host_transaction(&spi_host_, 0, segment, ARRAYSIZE(segment)));
447 }
448 
449 class FifoTest : public SpiHostTest {};
450 
451 // Checks that arguments are validated.
452 TEST_F(FifoTest, NullArgs) {
453  uint32_t buffer[2] = {1, 2};
454 
455  EXPECT_DIF_BADARG(dif_spi_host_fifo_write(nullptr, buffer, sizeof(buffer)));
457  dif_spi_host_fifo_write(&spi_host_, nullptr, sizeof(buffer)));
458 
459  EXPECT_DIF_BADARG(dif_spi_host_fifo_read(nullptr, buffer, sizeof(buffer)));
461  dif_spi_host_fifo_read(&spi_host_, nullptr, sizeof(buffer)));
462 }
463 
464 // Checks that an aligned source buffer is written as 32-bit words into the
465 // transmit FIFO.
466 TEST_F(FifoTest, AlignedWrite) {
467  uint32_t buffer[] = {1, 2};
468 
469  EXPECT_TXQD(0);
470  EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 1);
471  EXPECT_TXQD(0);
472  EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 2);
473 
474  EXPECT_DIF_OK(dif_spi_host_fifo_write(&spi_host_, buffer, sizeof(buffer)));
475 }
476 
477 template <size_t count, size_t align>
478 struct Aligned {
479  alignas(align) uint8_t value[count];
480  uint8_t *get() { return &value[0]; }
481 };
482 
483 // Checks that a misaligned source buffer is written as bytes into the
484 // transmit FIFO until alignment is reached and then written as 32-bit words.
485 TEST_F(FifoTest, MisalignedWrite) {
486  // We'll intentionally mis-align the buffer by 1 when calling
487  // dif_spi_host_fifo_write.
488  Aligned<9, 4> buffer = {0, 1, 2, 3, 4, 5, 6, 7, 8};
489 
490  // Because of the misalignment, expect three byte writes.
491  EXPECT_TXQD(0);
492  EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 1);
493  EXPECT_TXQD(0);
494  EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 2);
495  EXPECT_TXQD(0);
496  EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 3);
497 
498  // Then a word write when we reach alignment.
499  EXPECT_TXQD(0);
500  EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x07060504);
501 
502  // Then a byte write to finish the buffer.
503  EXPECT_TXQD(0);
504  EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 8);
505 
506  EXPECT_DIF_OK(dif_spi_host_fifo_write(&spi_host_, buffer.get() + 1, 8));
507 }
508 
509 // Checks that an aligned destination buffer receives the contents of the
510 // recieve FIFO.
511 TEST_F(FifoTest, AlignedRead) {
512  uint32_t buffer[2];
513 
514  EXPECT_RXQD(2);
515  EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 1);
516  EXPECT_RXQD(1);
517  EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 2);
518 
519  EXPECT_DIF_OK(dif_spi_host_fifo_read(&spi_host_, buffer, sizeof(buffer)));
520  EXPECT_THAT(buffer, ElementsAre(1, 2));
521 }
522 
523 // Checks that a misaligned destination buffer receives the contents of the
524 // recieve FIFO.
525 TEST_F(FifoTest, MisalignedRead) {
526  // We'll intentionally mis-align the buffer by 1 when calling
527  // dif_spi_host_fifo_read.
528  Aligned<9, 4> buffer{};
529 
530  EXPECT_RXQD(2);
531  EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 0x04030201);
532  EXPECT_RXQD(1);
533  EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 0x08070605);
534 
535  EXPECT_DIF_OK(dif_spi_host_fifo_read(&spi_host_, buffer.get() + 1, 8));
536  EXPECT_THAT(buffer.value, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8));
537 }
538 
540  protected:
541  static constexpr std::array<std::array<uint32_t, 2>, 6> kEventsMap{{
542  {kDifSpiHostEvtRxFull, SPI_HOST_EVENT_ENABLE_RXFULL_BIT},
543  {kDifSpiHostEvtTxEmpty, SPI_HOST_EVENT_ENABLE_TXEMPTY_BIT},
544  {kDifSpiHostEvtRxWm, SPI_HOST_EVENT_ENABLE_RXWM_BIT},
545  {kDifSpiHostEvtTxWm, SPI_HOST_EVENT_ENABLE_TXWM_BIT},
546  {kDifSpiHostEvtReady, SPI_HOST_EVENT_ENABLE_READY_BIT},
547  {kDifSpiHostEvtIdle, SPI_HOST_EVENT_ENABLE_IDLE_BIT},
548  }};
549 };
550 // C++ 14 requires this.
551 constexpr std::array<std::array<uint32_t, 2>, 6> EventEnableRegTest::kEventsMap;
552 TEST_F(EventEnableRegTest, WriteEnable) {
553  // Check individual events.
554  for (auto pair : kEventsMap) {
555  dif_spi_host_events_t evt = pair[0];
556  uint32_t reg_offset = pair[1];
557  EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 0x00);
558  EXPECT_WRITE32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 1 << reg_offset);
559  EXPECT_DIF_OK(dif_spi_host_event_set_enabled(&spi_host_, evt, true));
560  }
561 
562  // Check all the events.
563  uint32_t all_events = 0;
564  for (auto pair : kEventsMap) {
565  all_events |= 1 << pair[1];
566  }
567  EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 0x00);
568  EXPECT_WRITE32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
571 }
572 
573 TEST_F(EventEnableRegTest, WriteDisable) {
574  uint32_t all_events = 0;
575  for (auto pair : kEventsMap) {
576  all_events |= 1 << pair[1];
577  }
578 
579  // Check individual events.
580  for (auto pair : kEventsMap) {
581  dif_spi_host_events_t evt = pair[0];
582  uint32_t reg_offset = pair[1];
583  EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
584  EXPECT_WRITE32(SPI_HOST_EVENT_ENABLE_REG_OFFSET,
585  all_events & ~(1 << reg_offset));
586  EXPECT_DIF_OK(dif_spi_host_event_set_enabled(&spi_host_, evt, false));
587  }
588 
589  // Check all the events.
590  EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
591  EXPECT_WRITE32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 0);
594 }
595 
596 // Checks that arguments are validated.
597 TEST_F(EventEnableRegTest, SetEnableNullArgs) {
601  &spi_host_, static_cast<dif_spi_host_events_code_t>(0xFF), true));
602 }
603 
604 TEST_F(EventEnableRegTest, Read) {
605  dif_spi_host_events_t evt = 0;
606  // Check individual events.
607  for (auto pair : kEventsMap) {
608  uint32_t reg_offset = pair[1];
609  EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 1 << reg_offset);
611  EXPECT_EQ(pair[0], evt);
612  }
613 
614  // Check all the events.
615  uint32_t all_events = 0;
616  for (auto pair : kEventsMap) {
617  all_events |= 1 << pair[1];
618  }
619  EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
621  EXPECT_EQ(all_events, evt);
622 }
623 
624 // Checks that arguments are validated.
625 TEST_F(EventEnableRegTest, GetEnableNullArgs) {
626  dif_spi_host_events_t events;
629 }
630 
631 class StatusTest : public SpiHostTest {
632  protected:
633  void expect_status_eq(dif_spi_host_status_t expected) {
636  EXPECT_EQ(status.ready, expected.ready);
637  EXPECT_EQ(status.active, expected.active);
638  EXPECT_EQ(status.tx_empty, expected.tx_empty);
639  EXPECT_EQ(status.rx_empty, expected.rx_empty);
640  EXPECT_EQ(status.tx_full, expected.tx_full);
641  EXPECT_EQ(status.rx_full, expected.rx_full);
642  EXPECT_EQ(status.tx_water_mark, expected.tx_water_mark);
643  EXPECT_EQ(status.rx_water_mark, expected.rx_water_mark);
644  EXPECT_EQ(status.tx_stall, expected.tx_stall);
645  EXPECT_EQ(status.rx_stall, expected.rx_stall);
646  EXPECT_EQ(status.least_significant_first, expected.least_significant_first);
647  EXPECT_EQ(status.tx_queue_depth, expected.tx_queue_depth);
648  EXPECT_EQ(status.rx_queue_depth, expected.rx_queue_depth);
649  EXPECT_EQ(status.cmd_queue_depth, expected.cmd_queue_depth);
650  }
651 };
652 
653 TEST_F(StatusTest, Read) {
654  static constexpr std::array<std::pair<uint32_t, dif_spi_host_status_t>, 14>
655  kMap = {{
656  {1 << SPI_HOST_STATUS_READY_BIT,
657  (dif_spi_host_status_t){.ready = true}},
658  {1 << SPI_HOST_STATUS_ACTIVE_BIT,
659  (dif_spi_host_status_t){.active = true}},
660  {1 << SPI_HOST_STATUS_TXFULL_BIT,
661  (dif_spi_host_status_t){.tx_full = true}},
662  {1 << SPI_HOST_STATUS_TXEMPTY_BIT,
663  (dif_spi_host_status_t){.tx_empty = true}},
664  {1 << SPI_HOST_STATUS_TXSTALL_BIT,
665  (dif_spi_host_status_t){.tx_stall = true}},
666  {1 << SPI_HOST_STATUS_TXWM_BIT,
667  (dif_spi_host_status_t){.tx_water_mark = true}},
668  {1 << SPI_HOST_STATUS_RXFULL_BIT,
669  (dif_spi_host_status_t){.rx_full = true}},
670  {1 << SPI_HOST_STATUS_RXEMPTY_BIT,
671  (dif_spi_host_status_t){.rx_empty = true}},
672  {1 << SPI_HOST_STATUS_RXSTALL_BIT,
673  (dif_spi_host_status_t){.rx_stall = true}},
674  {1 << SPI_HOST_STATUS_RXWM_BIT,
675  (dif_spi_host_status_t){.rx_water_mark = true}},
676  {1 << SPI_HOST_STATUS_BYTEORDER_BIT,
677  (dif_spi_host_status_t){.least_significant_first = true}},
678  {0xF << SPI_HOST_STATUS_CMDQD_OFFSET,
679  (dif_spi_host_status_t){.cmd_queue_depth = 0xF}},
680  {0xFF << SPI_HOST_STATUS_RXQD_OFFSET,
681  (dif_spi_host_status_t){.rx_queue_depth = 0xFF}},
682  {0xFF << SPI_HOST_STATUS_TXQD_OFFSET,
683  (dif_spi_host_status_t){.tx_queue_depth = 0xFF}},
684  }};
685 
686  for (auto pair : kMap) {
687  EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, pair.first);
688  expect_status_eq(pair.second);
689  }
690 }
691 
692 // Checks that arguments are validated.
693 TEST_F(StatusTest, NullArgs) {
696  EXPECT_DIF_BADARG(dif_spi_host_get_status(&spi_host_, nullptr));
697 }
698 
699 class WriteCommandTest : public SpiHostTest {};
700 
701 TEST_F(WriteCommandTest, NullArgs) {
703  nullptr, 4, kDifSpiHostWidthStandard, kDifSpiHostDirectionRx, false));
704 }
705 
706 // Checks that arguments are validated.
707 TEST_F(WriteCommandTest, ValidArgs) {
708  EXPECT_WRITE32(SPI_HOST_COMMAND_REG_OFFSET,
709  {{SPI_HOST_COMMAND_LEN_OFFSET, 899},
710  {SPI_HOST_COMMAND_SPEED_OFFSET, 1},
711  {SPI_HOST_COMMAND_DIRECTION_OFFSET, 3},
712  {SPI_HOST_COMMAND_CSAAT_BIT, 1}});
713 
717 }
718 
719 // Test the SPI HOST error enable register.
721  protected:
722  static constexpr std::array<std::array<uint32_t, 2>, 5> kErrorsMap{{
723  {kDifSpiHostErrorCmdBusy, SPI_HOST_ERROR_ENABLE_CMDBUSY_BIT},
724  {kDifSpiHostErrorOverflow, SPI_HOST_ERROR_ENABLE_OVERFLOW_BIT},
725  {kDifSpiHostErrorUnderflow, SPI_HOST_ERROR_ENABLE_UNDERFLOW_BIT},
726  {kDifSpiHostErrorCmdInval, SPI_HOST_ERROR_ENABLE_CMDINVAL_BIT},
727  {kDifSpiHostErrorCsIdIval, SPI_HOST_ERROR_ENABLE_CSIDINVAL_BIT},
728  }};
729 };
730 // C++ 14 requires this.
731 constexpr std::array<std::array<uint32_t, 2>, 5> ErrorEnableRegTest::kErrorsMap;
732 TEST_F(ErrorEnableRegTest, WriteEnable) {
733  // Check individual events.
734  for (auto pair : kErrorsMap) {
735  dif_spi_host_errors_t error = pair[0];
736  uint32_t reg_offset = pair[1];
737  EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 0x00);
738  EXPECT_WRITE32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 1 << reg_offset);
739  EXPECT_DIF_OK(dif_spi_host_error_set_enabled(&spi_host_, error, true));
740  }
741 
742  // Check all the events.
743  uint32_t all_errors = 0;
744  for (auto pair : kErrorsMap) {
745  all_errors |= 1 << pair[1];
746  }
747  EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 0x00);
748  EXPECT_WRITE32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
751 }
752 
753 TEST_F(ErrorEnableRegTest, WriteDisable) {
754  uint32_t all_errors = 0;
755  for (auto pair : kErrorsMap) {
756  all_errors |= 1 << pair[1];
757  }
758 
759  // Check individual events.
760  for (auto pair : kErrorsMap) {
761  dif_spi_host_errors_t error = pair[0];
762  uint32_t reg_offset = pair[1];
763  EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
764  EXPECT_WRITE32(SPI_HOST_ERROR_ENABLE_REG_OFFSET,
765  all_errors & ~(1 << reg_offset));
766  EXPECT_DIF_OK(dif_spi_host_error_set_enabled(&spi_host_, error, false));
767  }
768 
769  // Check all the events.
770  EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
771  EXPECT_WRITE32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 0);
773  kDifSpiHostIrqErrorAll, false));
774 }
775 
776 // Checks that arguments are validated.
777 TEST_F(ErrorEnableRegTest, SetEnableNullArgs) {
781  &spi_host_, static_cast<dif_spi_host_events_code_t>(0xFF), true));
782 }
783 
784 TEST_F(ErrorEnableRegTest, Read) {
785  dif_spi_host_errors_t errors = 0;
786  // Check individual events.
787  for (auto pair : kErrorsMap) {
788  uint32_t reg_offset = pair[1];
789  EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 1 << reg_offset);
790  EXPECT_DIF_OK(dif_spi_host_error_get_enabled(&spi_host_, &errors));
791  EXPECT_EQ(pair[0], errors);
792  }
793 
794  // Check all the events.
795  uint32_t all_errors = 0;
796  for (auto pair : kErrorsMap) {
797  all_errors |= 1 << pair[1];
798  }
799  EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
800  EXPECT_DIF_OK(dif_spi_host_error_get_enabled(&spi_host_, &errors));
801  EXPECT_EQ(all_errors, errors);
802 }
803 
804 // Checks that arguments are validated.
805 TEST_F(ErrorEnableRegTest, GetEnableNullArgs) {
806  dif_spi_host_errors_t errors;
809 }
810 
811 class ErrorStatusTest : public SpiHostTest {};
812 
813 TEST_F(ErrorStatusTest, Read) {
814  static constexpr std::array<std::pair<uint32_t, dif_spi_host_errors_t>, 6>
815  kMap = {{
816  {kDifSpiHostErrorCmdBusy, 1 << SPI_HOST_ERROR_STATUS_CMDBUSY_BIT},
817  {kDifSpiHostErrorOverflow, 1 << SPI_HOST_ERROR_STATUS_OVERFLOW_BIT},
818  {kDifSpiHostErrorUnderflow, 1 << SPI_HOST_ERROR_STATUS_UNDERFLOW_BIT},
819  {kDifSpiHostErrorCmdInval, 1 << SPI_HOST_ERROR_STATUS_CMDINVAL_BIT},
820  {kDifSpiHostErrorCsIdIval, 1 << SPI_HOST_ERROR_STATUS_CSIDINVAL_BIT},
822  1 << SPI_HOST_ERROR_STATUS_ACCESSINVAL_BIT},
823  }};
824 
825  for (auto pair : kMap) {
826  EXPECT_READ32(SPI_HOST_ERROR_STATUS_REG_OFFSET, pair.second);
827 
828  dif_spi_host_errors_t error;
829  EXPECT_DIF_OK(dif_spi_host_get_error(&spi_host_, &error));
830  EXPECT_EQ(error, pair.first);
831  }
832 }
833 
834 // Checks that arguments are validated.
835 TEST_F(ErrorStatusTest, NullArgs) {
836  dif_spi_host_errors_t error;
837  EXPECT_DIF_BADARG(dif_spi_host_get_error(nullptr, &error));
838  EXPECT_DIF_BADARG(dif_spi_host_get_error(&spi_host_, nullptr));
839 }
840 
841 } // namespace
842 } // namespace dif_spi_host_unittest