Software APIs
dma_abort.c
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 "dt/dt_dma.h"
6 #include "dt/dt_pinmux.h"
7 #include "dt/dt_spi_host.h"
15 #include "sw/device/lib/testing/dma_testutils.h"
16 #include "sw/device/lib/testing/pinmux_testutils.h"
17 #include "sw/device/lib/testing/rand_testutils.h"
18 #include "sw/device/lib/testing/test_framework/check.h"
20 #include "sw/device/lib/testing/test_framework/status.h"
21 
22 // The TX_SIZE must be in sync with the data size in spi_device_dma_seq.sv
23 // 1 SPI segment can only transfer at maximum 512 bytes
24 #define TX_SIZE 512
25 #define CHUNK_SIZE 32 * 4 // Half the SPI host FIFO size
26 
27 OTTF_DEFINE_TEST_CONFIG();
28 
29 enum {
30  kSoftwareBarrierTimeoutUsec = 500,
31 };
32 
33 // This location will be update from SV
34 static volatile const uint8_t kSoftwareBarrier = 0;
35 
36 // Expected digest value gets backdoor'ed from the hardware
37 // Although not used, we need to keep it here as the shared vseq
38 // wants to write it.
39 static volatile uint32_t kShaDigestExpData[16];
40 static volatile uint8_t kShaMode;
41 
42 uint32_t digest[16];
43 uint8_t received_data[TX_SIZE] __attribute__((aligned(4)));
44 
45 static dif_spi_host_t spi_host;
46 static dif_pinmux_t pinmux;
47 static dif_dma_t dma;
48 
49 bool test_main(void) {
50  // Initialize the pinmux.
51  CHECK_DIF_OK(dif_pinmux_init_from_dt(kDtPinmuxAon, &pinmux));
52  pinmux_testutils_init(&pinmux);
53 
54  // Initialise DMA.
55  CHECK_DIF_OK(dif_dma_init_from_dt(kDtDma, &dma));
56 
57  // Setup pinmux if required, enable weak pull-up on relevant pads
58  setup_pads_spi_host0(&pinmux); // direct
59 
60  // Setup spi host configuration
61  CHECK_DIF_OK(dif_spi_host_init_from_dt((dt_spi_host_t)0, &spi_host));
62  init_spi_host(&spi_host, (uint32_t)kClockFreqHiSpeedPeripheralHz,
63  CHUNK_SIZE / 4);
64 
65  // DV sync message
66  LOG_INFO("spi host configuration complete");
67 
68  // Dummy assignment to avoid any unused variable warnings
69  kShaDigestExpData[0] = 0;
70 
71  setup_spi_dma_transaction(&spi_host, &dma, &received_data[0], CHUNK_SIZE,
72  TX_SIZE);
73 
74  CHECK_DIF_OK(dif_dma_start(&dma, kShaMode));
75 
76  // Wait until the DMA has started to abort the transfer
77  IBEX_SPIN_FOR(kSoftwareBarrier == 1, kSoftwareBarrierTimeoutUsec);
78 
79  CHECK_DIF_OK(dif_dma_abort(&dma));
80 
82  CHECK_DIF_OK(dif_dma_status_get(&dma, &status));
83 
84  CHECK(status & kDifDmaStatusAborted, "Abort bit not set");
85 
86  // Reset and re-init the SPI
87  init_spi_host(&spi_host, (uint32_t)kClockFreqHiSpeedPeripheralHz,
88  CHUNK_SIZE / 4);
89  LOG_INFO("spi host re-configuration complete");
90 
91  // Do the second transaction
92  setup_spi_dma_transaction(&spi_host, &dma, &received_data[0], CHUNK_SIZE,
93  TX_SIZE);
94  CHECK_DIF_OK(dif_dma_start(&dma, kShaMode));
95  CHECK_DIF_OK(dif_dma_status_poll(&dma, kDifDmaStatusDone));
96 
97  CHECK_DIF_OK(dif_dma_sha2_digest_get(&dma, kShaMode, digest));
98 
99  uint32_t digest_len;
100  CHECK_DIF_OK(dif_dma_get_digest_length(kShaMode, &digest_len));
101  CHECK_ARRAYS_EQ((uint8_t *)digest, (uint8_t *)kShaDigestExpData, digest_len);
102 
103  return true;
104 }