Software APIs
dif_dma.h
Go to the documentation of this file.
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 #ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_DMA_H_
6 #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_DMA_H_
7 
8 /**
9  * @file
10  * @brief <a href="/hw/ip/dma/doc/">DMA Controller</a> Device Interface
11  * Functions
12  */
13 
14 #include <stdint.h>
15 
16 #include "dma_regs.h" // Generated.
17 #include "sw/device/lib/dif/autogen/dif_dma_autogen.h"
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif // __cplusplus
22 
23 // Target Address space that the source address pointer refers to.
24 typedef enum dif_dma_address_space_id {
25  /* OpenTitan 32 bit internal bus. */
26  kDifDmaOpentitanInternalBus = 0x07,
27 
28  /* SoC control register address bus using 32 bit (or 64 bits if configured by
29  an SoC) CTN port .*/
30  kDifDmaSoCControlRegisterBus = 0x0a,
31 
32  /* SoC system address bus using 64 bit SYS port. */
33  kDifDmaSoCSystemBus = 0x09,
34 } dif_dma_address_space_id_t;
35 
36 /* Supported transaction widths by the DMA */
37 typedef enum dif_dma_transaction_width {
38  /* Transfer 1 byte at a time.*/
39  kDifDmaTransWidth1Byte = 0x00,
40  /* Transfer 2 byte at a time.*/
41  kDifDmaTransWidth2Bytes = 0x01,
42  /* Transfer 4 byte at a time.*/
43  kDifDmaTransWidth4Bytes = 0x02,
44 } dif_dma_transaction_width_t;
45 
46 /* Supported Opcodes by the DMA */
47 typedef enum dif_dma_transaction_opcode {
48  /* Simple copy from source to destination.*/
49  kDifDmaCopyOpcode = 0x00,
50  /* Inline hashing with SHA2-256.*/
51  kDifDmaSha256Opcode = 0x01,
52  /* Inline hashing with SHA2-384.*/
53  kDifDmaSha384Opcode = 0x02,
54  /* Inline hashing with SHA2-512.*/
55  kDifDmaSha512Opcode = 0x03,
56 } dif_dma_transaction_opcode_t;
57 
58 /**
59  * Define the transaction address space.
60  */
62  uint64_t address;
63  dif_dma_address_space_id_t asid;
65 
66 /**
67  * Addressing configuration.
68  */
69 typedef struct dif_dma_address_config {
70  /* Address wraps after each chunk, so chunks overlap */
71  bool wrap;
72  /* Increment after each (partial-)word transfer */
73  bool increment;
75 
76 /**
77  * Parameters for a DMA Controller transaction.
78  */
79 typedef struct dif_dma_transaction {
82  dif_dma_address_config_t src_config;
83  dif_dma_address_config_t dst_config;
84  /* Chunk size (in bytes) of the data object to transferred.*/
85  size_t chunk_size;
86  /* Total size (in bytes) of the data object to transferred.*/
87  size_t total_size;
88  /* Iteration width.*/
89  dif_dma_transaction_width_t width;
91 
92 /**
93  * Configures DMA Controller for a transaction.
94  *
95  * This function should be called every time before `dif_dma_start`.
96  *
97  * @param dma A DMA Controller handle.
98  * @param config Transaction configuration parameters.
99  * @return The result of the operation.
100  */
102 dif_result_t dif_dma_configure(const dif_dma_t *dma,
103  dif_dma_transaction_t transaction);
104 
105 /**
106  * Configures DMA Controller hardware handshake mode.
107  *
108  * This function should be called before `dif_dma_start`.
109  *
110  * Hardware handshake mode is used to push / pop FIFOs to / from low speed IO
111  * peripherals receiving data e.g. I3C receive buffer.
112  *
113  * @param dma A DMA Controller handle.
114  * @return The result of the operation.
115  */
117 dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma);
118 
119 /**
120  * Disable DMA Controller hardware handshake mode.
121  *
122  * @param dma A DMA Controller handle.
123  * @return The result of the operation.
124  */
126 dif_result_t dif_dma_handshake_disable(const dif_dma_t *dma);
127 
128 /**
129  * Begins a DMA Controller transaction.
130  *
131  * Before this function the DMA transaction shall be configured by calling the
132  * function `dif_dma_configure` and optionally `dif_dma_handshake_enable` can be
133  * called.
134  *
135  * @param dma A DMA Controller handle.
136  * @param opcode Transaction opcode.
137  * @return The result of the operation.
138  */
140 dif_result_t dif_dma_start(const dif_dma_t *dma,
141  dif_dma_transaction_opcode_t opcode);
142 
143 /**
144  * Abort the DMA Controller transaction in execution.
145  *
146  * @param dma A DMA Controller handle.
147  * @return The result of the operation.
148  */
150 dif_result_t dif_dma_abort(const dif_dma_t *dma);
151 
152 /**
153  * Set the DMA enabled memory range within the OT internal memory space.
154  *
155  * @param dma A DMA Controller handle.
156  * @param address Base address.
157  * @param size The range size.
158  * @return The result of the operation.
159  */
161 dif_result_t dif_dma_memory_range_set(const dif_dma_t *dma, uint32_t address,
162  size_t size);
163 
164 /**
165  * Get the DMA enabled memory range within the OT internal memory space.
166  *
167  * @param dma A DMA Controller handle.
168  * @param[out] address Out-param for the base address.
169  * @param[out] size Out-param for the range size.
170  * @return The result of the operation.
171  */
173 dif_result_t dif_dma_memory_range_get(const dif_dma_t *dma, uint32_t *address,
174  size_t *size);
175 /**
176  * Locks out the DMA memory range register.
177  *
178  * This function is reentrant: calling it while functionality is locked will
179  * have no effect and return `kDifOk`.
180  *
181  * @param dma A DMA Controller handle.
182  * @return The result of the operation.
183  */
185 dif_result_t dif_dma_memory_range_lock(const dif_dma_t *dma);
186 
187 /**
188  * Checks whether the DMA memory range is locked.
189  *
190  * @param dma A DMA Controller handle.
191  * @param[out] is_locked Out-param for the locked state.
192  * @return The result of the operation.
193  */
195 dif_result_t dif_dma_is_memory_range_locked(const dif_dma_t *dma,
196  bool *is_locked);
197 
198 /**
199  * Checks whether the DMA memory range is valid.
200  *
201  * @param dma A DMA Controller handle.
202  * @param[out] is_valid Out-param for the valid state.
203  * @return The result of the operation.
204  */
206 dif_result_t dif_dma_is_memory_range_valid(const dif_dma_t *dma,
207  bool *is_valid);
208 
209 typedef enum dif_dma_status_code {
210  // DMA operation is active.
211  kDifDmaStatusBusy = 0x01 << DMA_STATUS_BUSY_BIT,
212  // Configured DMA operation is complete.
213  kDifDmaStatusDone = 0x01 << DMA_STATUS_DONE_BIT,
214  // Set once aborted operation drains.
215  kDifDmaStatusAborted = 0x01 << DMA_STATUS_ABORTED_BIT,
216  // Error occurred during the operation.
217  // Check the error_code for information about the source of the error.
218  kDifDmaStatusError = 0x01 << DMA_STATUS_ERROR_BIT,
219  // Set once the SHA2 digest is valid after finishing a transfer
220  kDifDmaStatusSha2DigestValid = 0x01 << DMA_STATUS_SHA2_DIGEST_VALID_BIT,
221  // Transfer of a single chunk is complete.
222  kDifDmaStatusChunkDone = 0x01 << DMA_STATUS_CHUNK_DONE_BIT,
223 } dif_dma_status_code_t;
224 
225 /**
226  * Bitmask with the `dif_dma_status_code_t` values.
227  */
228 typedef uint32_t dif_dma_status_t;
229 
230 /**
231  * Reads the DMA status.
232  *
233  * @param dma A DMA Controller handle.
234  * @param[out] status Out-param for the status.
235  * @return The result of the operation.
236  */
239 
240 /**
241  * Writes the DMA status register and clears the corrsponding status bits.
242  *
243  * @param dma A DMA Controller handle.
244  * @param status Status bits to be cleared.
245  * @return The result of the operation.
246  */
248 dif_result_t dif_dma_status_write(const dif_dma_t *dma,
250 
251 /**
252  * Clear all status bits of the status register.
253  *
254  * @param dma A DMA Controller handle.
255  * @return The result of the operation.
256  */
258 dif_result_t dif_dma_status_clear(const dif_dma_t *dma);
259 
260 /**
261  * Poll the DMA status util a given flag in the register is set.
262  *
263  * @param dma A DMA Controller handle.
264  * @param flag The status that needs to bet set.
265  * @return The result of the operation.
266  */
268 dif_result_t dif_dma_status_poll(const dif_dma_t *dma,
269  dif_dma_status_code_t flag);
270 
271 typedef enum dif_dma_error_code {
272  // Source address error.
273  kDifDmaErrorNone = 0x00,
274  // Source address error.
275  kDifDmaErrorSourceAddress = 0x01 << 0,
276  // Destination address error.
277  kDifDmaErrorDestinationAddress = 0x01 << 1,
278  // Opcode error.
279  kDifDmaErrorOpcode = 0x01 << 2,
280  // Size error.
281  kDifDmaErrorSize = 0x01 << 3,
282  // Bus transaction error.
283  kDifDmaErrorBus = 0x01 << 4,
284  // DMA enable memory config error.
285  kDifDmaErrorEnableMemoryConfig = 0x01 << 5,
286  // Register range valid error.
287  kDifDmaErrorRangeValid = 0x01 << 6,
288  // Invalid ASID error.
289  kDifDmaErrorInvalidAsid = 0x01 << 7,
290 } dif_dma_error_code_t;
291 
292 /**
293  * Reads the DMA error code.
294  *
295  * @param dma A DMA Controller handle.
296  * @param[out] error Out-param for the error code.
297  * @return The result of the operation.
298  */
300 dif_result_t dif_dma_error_code_get(const dif_dma_t *dma,
301  dif_dma_error_code_t *error);
302 
303 /**
304  * Return the digest length given a DMA opcode.
305  *
306  * @param opcode A DMA opcode.
307  * @param digest_len The digest length.
308  * @return The result of the operation.
309  */
310 dif_result_t dif_dma_get_digest_length(dif_dma_transaction_opcode_t opcode,
311  uint32_t *digest_len);
312 
313 /**
314  * Read out the SHA2 digest
315  *
316  * @param dma A DMA Controller handle.
317  * @param opcode The opcode to select the length of the read digest.
318  * @param[out] digest Pointer to the digest, to store the read values.
319  * @return The result of the operation.
320  */
321 dif_result_t dif_dma_sha2_digest_get(const dif_dma_t *dma,
322  dif_dma_transaction_opcode_t opcode,
323  uint32_t digest[]);
324 
325 /**
326  * Enable DMA controller handshake interrupt.
327  *
328  * @param dma A DMA Controller handle.
329  * @param enable_state Enable state. The bit position corresponds to the IRQ
330  * index.
331  * @return The result of the operation.
332  */
334 dif_result_t dif_dma_handshake_irq_enable(const dif_dma_t *dma,
335  uint32_t enable_state);
336 
337 /**
338  * Enable the corresponding DME handshake interrupt clearing mechanism.
339  *
340  * @param dma A DMA Controller handle.
341  * @param clear_state Enable interrupt clearing mechanism. The bit position
342  * corresponds to the IRQ index.
343  * @return The result of the operation.
344  */
346 dif_result_t dif_dma_handshake_clear_irq(const dif_dma_t *dma,
347  uint32_t clear_state);
348 
349 /**
350  * Select the bus interface for the interrupt clearing mechanism.
351  * 0: CTN/System fabric
352  * 1: OT-internal crossbar
353  *
354  * @param dma A DMA Controller handle.
355  * @param clear_irq_bus Bus selection for the clearing mechanism. The bit
356  * position corresponds to the IRQ index.
357  * @return The result of the operation.
358  */
360 dif_result_t dif_dma_handshake_clear_irq_bus(const dif_dma_t *dma,
361  uint32_t clear_irq_bus);
362 
363 /**
364  * Address index for every interrupt. Used to configure the write address and
365  * write value for the interrupt clearing mechanism.
366  */
367 typedef enum dif_dma_intr_idx {
368  kDifDmaIntrClearIdx0 = 0x0,
369  kDifDmaIntrClearIdx1 = 0x4,
370  kDifDmaIntrClearIdx2 = 0x8,
371  kDifDmaIntrClearIdx3 = 0xC,
372  kDifDmaIntrClearIdx4 = 0x10,
373  kDifDmaIntrClearIdx5 = 0x14,
374  kDifDmaIntrClearIdx6 = 0x18,
375  kDifDmaIntrClearIdx7 = 0x1C,
376  kDifDmaIntrClearIdx8 = 0x20,
377  kDifDmaIntrClearIdx9 = 0x24,
378  kDifDmaIntrClearIdx10 = 0x28,
380 
381 /**
382  * Set the write address for the interrupt clearing mechanism.
383  *
384  * @param dma A DMA Controller handle.
385  * @param idx Index of the selected interrupt.
386  * @param intr_src_addr Address to write the interrupt clearing value to.
387  * @return The result of the operation.
388  */
390 dif_result_t dif_dma_intr_src_addr(const dif_dma_t *dma, dif_dma_intr_idx_t idx,
391  uint32_t intr_src_addr);
392 
393 /**
394  * Set the write value for the interrupt clearing mechanism.
395  *
396  * @param dma A DMA Controller handle.
397  * @param idx Index of the selected interrupt.
398  * @param intr_src_value Value to write the interrupt clearing value to.
399  * @return The result of the operation.
400  */
402 dif_result_t dif_dma_intr_write_value(const dif_dma_t *dma,
403  dif_dma_intr_idx_t idx,
404  uint32_t intr_src_value);
405 
406 #ifdef __cplusplus
407 } // extern "C"
408 #endif // __cplusplus
409 
410 #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_DMA_H_