10 #include "gtest/gtest.h"
11 #include "sw/device/lib/base/global_mock.h"
14 #include "sw/device/lib/base/mock_mmio.h"
17 #include "spi_host_regs.h"
19 namespace dif_spi_host_unittest {
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));
30 using MockFifo = testing::StrictMock<internal::MockFifo>;
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);
37 dif_result_t spi_host_fifo_read_alias(
const dif_spi_host_t *spi_host,
void *dst,
39 MockFifo::Instance().read(spi_host, dst, len);
46 using testing::ElementsAre;
50 #define EXPECT_COMMAND_REG(length, width, direction, last_segment) \
51 EXPECT_WRITE32(SPI_HOST_COMMAND_REG_OFFSET, \
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)}, \
59 #define EXPECT_READY(ready) \
60 EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, \
61 {{SPI_HOST_STATUS_READY_BIT, ready}})
63 #define EXPECT_TXQD(txqd) \
64 EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, \
65 {{SPI_HOST_STATUS_TXQD_OFFSET, txqd}})
67 #define EXPECT_RXQD(rxqd) \
68 EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, \
69 {{SPI_HOST_STATUS_RXQD_OFFSET, rxqd}})
73 void ExpectDeviceReset() {
74 EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
76 EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
78 {SPI_HOST_CONTROL_SW_RST_BIT,
true},
81 EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, 0);
83 EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, 0);
85 EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
87 {SPI_HOST_CONTROL_SW_RST_BIT,
false},
91 dif_spi_host_t spi_host_ = {
92 .base_addr = dev().region(),
97 .peripheral_clock_freq_hz = 1000000,
118 TEST_F(ConfigTest, BadDivider) {
120 config_.spi_clock = 1000001;
124 config_.spi_clock = 0;
129 TEST_F(ConfigTest, Default) {
131 EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
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},
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,
147 {SPI_HOST_CONTROL_SPIEN_BIT,
true},
154 TEST_F(ConfigTest, OutputSetEnabledNullHandle) {
159 TEST_F(ConfigTest, OutputEnable) {
160 EXPECT_READ32(SPI_HOST_CONTROL_REG_OFFSET, 0);
161 EXPECT_WRITE32(SPI_HOST_CONTROL_REG_OFFSET,
163 {SPI_HOST_CONTROL_OUTPUT_EN_BIT,
true},
169 TEST_F(ConfigTest, ClockRate) {
170 config_.spi_clock = 500000;
173 EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
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},
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,
188 {SPI_HOST_CONTROL_SPIEN_BIT,
true},
196 TEST_F(ConfigTest, ChipSelectOptions) {
197 config_.chip_select.idle = 1;
198 config_.chip_select.trail = 2;
199 config_.chip_select.lead = 3;
202 EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
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},
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,
217 {SPI_HOST_CONTROL_SPIEN_BIT,
true},
225 TEST_F(ConfigTest, SpiOptions) {
226 config_.full_cycle =
true;
231 EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
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},
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,
246 {SPI_HOST_CONTROL_SPIEN_BIT,
true},
253 TEST_F(ConfigTest, SpiTxRxWatermark) {
254 config_.tx_watermark = 0x7f;
255 config_.rx_watermark = 0x7e;
258 EXPECT_WRITE32(SPI_HOST_CONFIGOPTS_REG_OFFSET,
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},
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,
275 {SPI_HOST_CONTROL_SPIEN_BIT,
true},
290 segment.opcode.opcode = 0x5a;
293 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
297 EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 0x5a);
305 TEST_F(TransactionStartTest, IssueAddressMode3b) {
310 segment.address.address = 0x112233;
312 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
316 EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x332211);
324 TEST_F(TransactionStartTest, IssueAddressMode4b) {
329 segment.address.address = 0x11223344;
331 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
335 EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x44332211);
343 TEST_F(TransactionStartTest, IssueDummy) {
347 segment.dummy.length = 8;
349 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
368 segment.tx.buf = buf;
369 segment.tx.length =
sizeof(buf);
371 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
375 EXPECT_CALL(fifo_, write(&spi_host_, buf,
sizeof(buf)));
381 TEST_F(TransactionTest, ReceiveQuad) {
386 segment.rx.buf = buf;
387 segment.rx.length =
sizeof(buf);
389 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
393 EXPECT_CALL(fifo_, read(&spi_host_, buf,
sizeof(buf)));
399 TEST_F(TransactionTest, Transceive) {
405 segment.bidir.txbuf = txbuf;
406 segment.bidir.rxbuf = rxbuf;
407 segment.bidir.length =
sizeof(txbuf);
409 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
414 EXPECT_CALL(fifo_, write(&spi_host_, txbuf,
sizeof(txbuf)));
415 EXPECT_CALL(fifo_, read(&spi_host_, rxbuf,
sizeof(rxbuf)));
421 TEST_F(TransactionTest, MultiSegmentTxRx) {
428 segment[0].rx.buf = txbuf;
429 segment[0].rx.length =
sizeof(txbuf);
432 segment[1].rx.buf = rxbuf;
433 segment[1].rx.length =
sizeof(rxbuf);
435 EXPECT_WRITE32(SPI_HOST_CSID_REG_OFFSET, 0);
439 EXPECT_CALL(fifo_, write(&spi_host_, txbuf,
sizeof(txbuf)));
443 EXPECT_CALL(fifo_, read(&spi_host_, rxbuf,
sizeof(rxbuf)));
453 uint32_t buffer[2] = {1, 2};
466 TEST_F(FifoTest, AlignedWrite) {
467 uint32_t buffer[] = {1, 2};
470 EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 1);
472 EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 2);
477 template <
size_t count,
size_t align>
479 alignas(align) uint8_t value[count];
480 uint8_t *get() {
return &value[0]; }
492 EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 1);
494 EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 2);
496 EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 3);
500 EXPECT_WRITE32(SPI_HOST_TXDATA_REG_OFFSET, 0x07060504);
504 EXPECT_WRITE8(SPI_HOST_TXDATA_REG_OFFSET, 8);
511 TEST_F(FifoTest, AlignedRead) {
515 EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 1);
517 EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 2);
520 EXPECT_THAT(buffer, ElementsAre(1, 2));
525 TEST_F(FifoTest, MisalignedRead) {
528 Aligned<9, 4> buffer{};
531 EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 0x04030201);
533 EXPECT_READ32(SPI_HOST_RXDATA_REG_OFFSET, 0x08070605);
536 EXPECT_THAT(buffer.value, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8));
541 static constexpr std::array<std::array<uint32_t, 2>, 6> kEventsMap{{
551 constexpr std::array<std::array<uint32_t, 2>, 6> EventEnableRegTest::kEventsMap;
554 for (
auto pair : kEventsMap) {
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);
563 uint32_t all_events = 0;
564 for (
auto pair : kEventsMap) {
565 all_events |= 1 << pair[1];
567 EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 0x00);
568 EXPECT_WRITE32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
573 TEST_F(EventEnableRegTest, WriteDisable) {
574 uint32_t all_events = 0;
575 for (
auto pair : kEventsMap) {
576 all_events |= 1 << pair[1];
580 for (
auto pair : kEventsMap) {
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));
590 EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
591 EXPECT_WRITE32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, 0);
597 TEST_F(EventEnableRegTest, SetEnableNullArgs) {
601 &spi_host_,
static_cast<dif_spi_host_events_code_t
>(0xFF),
true));
604 TEST_F(EventEnableRegTest, Read) {
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);
615 uint32_t all_events = 0;
616 for (
auto pair : kEventsMap) {
617 all_events |= 1 << pair[1];
619 EXPECT_READ32(SPI_HOST_EVENT_ENABLE_REG_OFFSET, all_events);
621 EXPECT_EQ(all_events, evt);
625 TEST_F(EventEnableRegTest, GetEnableNullArgs) {
654 static constexpr std::array<std::pair<uint32_t, dif_spi_host_status_t>, 14>
656 {1 << SPI_HOST_STATUS_READY_BIT,
658 {1 << SPI_HOST_STATUS_ACTIVE_BIT,
660 {1 << SPI_HOST_STATUS_TXFULL_BIT,
662 {1 << SPI_HOST_STATUS_TXEMPTY_BIT,
664 {1 << SPI_HOST_STATUS_TXSTALL_BIT,
666 {1 << SPI_HOST_STATUS_TXWM_BIT,
668 {1 << SPI_HOST_STATUS_RXFULL_BIT,
670 {1 << SPI_HOST_STATUS_RXEMPTY_BIT,
672 {1 << SPI_HOST_STATUS_RXSTALL_BIT,
674 {1 << SPI_HOST_STATUS_RXWM_BIT,
676 {1 << SPI_HOST_STATUS_BYTEORDER_BIT,
678 {0xF << SPI_HOST_STATUS_CMDQD_OFFSET,
680 {0xFF << SPI_HOST_STATUS_RXQD_OFFSET,
682 {0xFF << SPI_HOST_STATUS_TXQD_OFFSET,
686 for (
auto pair : kMap) {
687 EXPECT_READ32(SPI_HOST_STATUS_REG_OFFSET, pair.first);
688 expect_status_eq(pair.second);
693 TEST_F(StatusTest, NullArgs) {
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}});
722 static constexpr std::array<std::array<uint32_t, 2>, 5> kErrorsMap{{
731 constexpr std::array<std::array<uint32_t, 2>, 5> ErrorEnableRegTest::kErrorsMap;
734 for (
auto pair : kErrorsMap) {
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);
743 uint32_t all_errors = 0;
744 for (
auto pair : kErrorsMap) {
745 all_errors |= 1 << pair[1];
747 EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 0x00);
748 EXPECT_WRITE32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
753 TEST_F(ErrorEnableRegTest, WriteDisable) {
754 uint32_t all_errors = 0;
755 for (
auto pair : kErrorsMap) {
756 all_errors |= 1 << pair[1];
760 for (
auto pair : kErrorsMap) {
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));
770 EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
771 EXPECT_WRITE32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 0);
777 TEST_F(ErrorEnableRegTest, SetEnableNullArgs) {
781 &spi_host_,
static_cast<dif_spi_host_events_code_t
>(0xFF),
true));
784 TEST_F(ErrorEnableRegTest, Read) {
787 for (
auto pair : kErrorsMap) {
788 uint32_t reg_offset = pair[1];
789 EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, 1 << reg_offset);
791 EXPECT_EQ(pair[0], errors);
795 uint32_t all_errors = 0;
796 for (
auto pair : kErrorsMap) {
797 all_errors |= 1 << pair[1];
799 EXPECT_READ32(SPI_HOST_ERROR_ENABLE_REG_OFFSET, all_errors);
801 EXPECT_EQ(all_errors, errors);
805 TEST_F(ErrorEnableRegTest, GetEnableNullArgs) {
814 static constexpr std::array<std::pair<uint32_t, dif_spi_host_errors_t>, 6>
822 1 << SPI_HOST_ERROR_STATUS_ACCESSINVAL_BIT},
825 for (
auto pair : kMap) {
826 EXPECT_READ32(SPI_HOST_ERROR_STATUS_REG_OFFSET, pair.second);
830 EXPECT_EQ(error, pair.first);
835 TEST_F(ErrorStatusTest, NullArgs) {