1 /*
2  * Copyright (c) 2021-2023, The TrustedFirmware-M Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef CC3XX_DMA_H
9 #define CC3XX_DMA_H
10 
11 #include "cc3xx_error.h"
12 #include "cc3xx_config.h"
13 
14 #include <stdint.h>
15 #include <stddef.h>
16 #include <string.h>
17 #include <stdbool.h>
18 
19 #define CC3XX_DMA_BLOCK_BUF_MAX_SIZE 64
20 
21 struct cc3xx_dma_state_t {
22     uint8_t block_buf[CC3XX_DMA_BLOCK_BUF_MAX_SIZE];
23     size_t block_buf_size_in_use;
24     size_t block_buf_size;
25     bool block_buf_needs_output;
26     uintptr_t output_addr;
27     size_t output_size;
28     uint32_t remap_cpusel;
29     size_t current_bytes_output;
30 };
31 
32 extern struct cc3xx_dma_state_t dma_state;
33 
34 #ifdef CC3XX_CONFIG_DMA_REMAP_ENABLE
35 
36 typedef struct {
37     uintptr_t region_base; /*!< The base of the region that will be remapped */
38     size_t region_size;    /*!< The size of the region that will be remapped */
39     uintptr_t remap_base;  /*!< The base of the region that mapped to */
40     size_t remap_cpusel_offset; /*!< How much the remap will be incremented per cpu */
41 } cc3xx_dma_remap_region_t;
42 
43 #endif /* CC3XX_CONFIG_DMA_REMAP_ENABLE */
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 #ifdef CC3XX_CONFIG_DMA_REMAP_ENABLE
50 
51 /**
52  * @brief                        Configure and enable a remap region. Any DMA
53  *                               input/output address that is within a remap
54  *                               region will be altered to the offset into the
55  *                               region plus the remap base (plus an extra
56  *                               cpusel offset if configured). This is intended
57  *                               primarily to be used to remap CPU TCM accesses
58  *                               to use the TCM subordinate interface (as cc3xx
59  *                               has no access via the main TCM mapping).
60 
61  * @param[in]  remap_region_idx  Which remap region should be configured and
62  *                               enabled.
63  * @param[in]  remap_region_idx  The configuration for the remap region.
64  *
65  * @return                       CC3XX_ERR_SUCCESS on success, another
66  *                               cc3xx_err_t on error.
67  */
68 void cc3xx_lowlevel_dma_remap_region_init(uint32_t remap_region_idx,
69                                           cc3xx_dma_remap_region_t *region);
70 /**
71  * @brief                        Clear and disable a remap region.
72  *
73  * @param[in]  remap_region_idx  Which remap region should be cleared and
74  *                               disabled.
75  *
76  * @return                       CC3XX_ERR_SUCCESS on success, another
77  *                               cc3xx_err_t on error.
78  */
79 void cc3xx_lowlevel_dma_remap_region_clear(uint32_t remap_region_idx);
80 
81 /**
82  * @brief             Select which CPU memory space should be used for remap
83  *                    offsets. Useful for selecting different ITCM / DTCMs.
84  *
85  * @param[in]  cpuid  Which CPU's memory space should be accessed when
86  *                    remapping.
87  *
88  * @return            CC3XX_ERR_SUCCESS on success, another cc3xx_err_t on
89  *                    error.
90  */
91 void cc3xx_lowlevel_dma_tcm_cpusel(uint32_t cpuid);
92 
93 #endif /* CC3XX_CONFIG_DMA_REMAP_ENABLE */
94 
95 /**
96  * @brief             Use the cc3xx DMA to copy data directly without performing
97  *                    cryptographic operations on it. This function can be used
98  *                    as a drop-in replacement for memcpy.
99  *
100  * @param[out] dest   The pointer to copy data to.
101  * @param[in]  src    The pointer to copy data from.
102  * @param[in]  length The size of the data.
103  */
104 void cc3xx_lowlevel_dma_copy_data(void* dest, const void* src, size_t length);
105 
106 /**
107  * @brief             Set the DMA input location. This triggers DMA input to be
108  *                    started. This operation buffers data, and
109  *                    cc3xx_dma_flush_buffer must be called to ensure all data
110  *                    is processed.
111  *
112  * @param[in]  buf          The pointer to copy data from.
113  * @param[in]  length       The size of the data.
114  * @param[in]  write_output Whether the data should be output from the engine.
115  *
116  * @return            CC3XX_ERR_SUCCESS on success, another cc3xx_err_t on
117  *                    error.
118  */
119 cc3xx_err_t cc3xx_lowlevel_dma_buffered_input_data(const void* buf, size_t length,
120                                                    bool write_output);
121 
122 /**
123  * @brief             Flush the DMA buffer. Engine setup is not saved with the
124  *                    DMA buffer, so the engine must be configured correctly
125  *                    before this is called.
126  *
127  * @param[in]  zero_pad_first Whether the data should be zero-padded to the DMA
128  *                            buffer size before being input.
129  */
130 void cc3xx_lowlevel_dma_flush_buffer(bool zero_pad_first);
131 
132 /**
133  * @brief             Set the size of the DMA block buffer. This must be called
134  *                    before the DMA is used, as the default value is 0, which
135  *                    is invalid.
136  *
137  * @param[in]  size   The size of the block buffer. Must not be larger than
138  *                    CC3XX_DMA_BLOCK_BUF_MAX_SIZE.
139  */
140 void cc3xx_lowlevel_dma_set_buffer_size(size_t size);
141 
142 /**
143  * @brief             Set the DMA output location. This controls where the
144  *                    DMA will output to after input is started.
145  *
146  * @param[out] buf    The pointer to output to.
147  * @param[in]  length The size of the output location. The DMA will not copy
148  *                    more data than this to the pointer.
149  */
150 void cc3xx_lowlevel_dma_set_output(void* buf, size_t length);
151 
152 /**
153  * @brief                       Uninitialize the DMA.
154  *
155  * @note                        The DMA is not implicitly uninitialized
156  *                              on an error.
157  *
158  */
159 void cc3xx_lowlevel_dma_uninit(void);
160 
161 #ifdef __cplusplus
162 }
163 #endif
164 
165 #endif /* CC3XX_DMA_H */
166