Software APIs
dma_testutils.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 "sw/device/lib/testing/dma_testutils.h"
6 
7 #include "hw/top_darjeeling/sw/autogen/top_darjeeling.h"
8 #include "spi_host_regs.h" // Generated.
9 
10 static const top_darjeeling_direct_pads_t spi_host0_direct_pads[6] = {
11  kTopDarjeelingDirectPadsSpiHost0Sck, // sck
12  kTopDarjeelingDirectPadsSpiHost0Csb, // csb
13  kTopDarjeelingDirectPadsSpiHost0Sd3, // sio[3]
14  kTopDarjeelingDirectPadsSpiHost0Sd2, // sio[2]
15  kTopDarjeelingDirectPadsSpiHost0Sd1, // sio[1]
16  kTopDarjeelingDirectPadsSpiHost0Sd0}; // sio[0]
17 
18 /**
19  * Initialize the provided SPI host for being used in the DMA hardware handshake
20  * mode.
21  */
22 void init_spi_host(dif_spi_host_t *spi_host, uint32_t peripheral_clock_freq_hz,
23  uint32_t rx_watermark) {
24  dif_spi_host_config_t config = {
25  .spi_clock = peripheral_clock_freq_hz / 2,
26  .peripheral_clock_freq_hz = peripheral_clock_freq_hz,
27  .chip_select = {.idle = 2, .trail = 2, .lead = 2},
28  .full_cycle = true,
29  .cpha = true,
30  .cpol = true,
31  .rx_watermark = rx_watermark};
32  CHECK_DIF_OK(dif_spi_host_configure(spi_host, config));
33  CHECK_DIF_OK(dif_spi_host_output_set_enabled(spi_host, /*enabled=*/true));
34 }
35 
36 /**
37  * Setup pads for spi_host0
38  *
39  * This peripheral is 'direct' connected to the pads.
40  */
41 void setup_pads_spi_host0(dif_pinmux_t *pinmux) {
42  // set weak pull-ups for all the pads
43  dif_pinmux_pad_attr_t out_attr;
44  dif_pinmux_pad_attr_t in_attr = {
45  .slew_rate = 0,
46  .drive_strength = 0,
47  .flags = kDifPinmuxPadAttrPullResistorEnable |
48  kDifPinmuxPadAttrPullResistorUp};
49  for (uint32_t i = 0; i < ARRAYSIZE(spi_host0_direct_pads); ++i) {
50  CHECK_DIF_OK(dif_pinmux_pad_write_attrs(pinmux, spi_host0_direct_pads[i],
51  kDifPinmuxPadKindDio, in_attr,
52  &out_attr));
53  }
54 }
55 
56 void setup_spi_dma_transaction(dif_spi_host_t *spi_host, dif_dma_t *dma,
57  uint8_t *rx_buffer, uint32_t chunk_size,
58  uint32_t total_size) {
59  dif_spi_host_segment_t host_operations[1] = {
61  .tx = {.width = kDifSpiHostWidthStandard,
62  .buf = NULL,
63  .length = total_size}},
64  };
65 
66  // Issue the SPI transaction
67  CHECK_DIF_OK(dif_spi_host_start_transaction(
68  spi_host, /*csid=*/0, host_operations, ARRAYSIZE(host_operations)));
69 
70  // Configure the DMA to read from SPI in hardware-handshake mode
71  dif_dma_transaction_t transaction = {
72  .source = {.address = TOP_DARJEELING_SPI_HOST0_BASE_ADDR +
73  SPI_HOST_RXDATA_REG_OFFSET,
74  .asid = kDifDmaOpentitanInternalBus},
75  .destination = {.address = (uint32_t)&rx_buffer[0],
76  .asid = kDifDmaOpentitanInternalBus},
77  .src_config = {.wrap = true, .increment = false},
78  .dst_config = {.wrap = false, .increment = true},
79  .total_size = total_size,
80  .chunk_size = chunk_size,
81  .width = kDifDmaTransWidth4Bytes};
82 
83  CHECK_DIF_OK(dif_dma_memory_range_set(dma, TOP_DARJEELING_RAM_MAIN_BASE_ADDR,
84  TOP_DARJEELING_RAM_MAIN_SIZE_BYTES));
85  // Enable LSIO trigger for SPI host at bit 1
86  CHECK_DIF_OK(dif_dma_handshake_irq_enable(dma, 0x2));
87  CHECK_DIF_OK(dif_dma_configure(dma, transaction));
88  CHECK_DIF_OK(dif_dma_handshake_enable(dma));
89 }