1 /*
2 * Copyright 2023 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef _FSL_EDMA_REV2_H_
8 #define _FSL_EDMA_REV2_H_
9
10 #include "fsl_common.h"
11
12 #if defined(__cplusplus)
13 extern "C" {
14 #endif
15
16 /* flag macros */
17 #define EDMA_HAS_CH_MUX_FLAG EDMA_BIT(0)
18 #define EDMA_ALLOWS_128B_TRANSFER_FLAG EDMA_BIT(1)
19 #define EDMA_HAS_MP_MUX_FLAG EDMA_BIT(2)
20 #define EDMA_HAS_64BIT_TCD_FLAG EDMA_BIT(3)
21
22 /* internal utility macros */
23 #define EDMA_BIT(x) (1 << (x))
24
25 #define EDMA_REGISTER_INDEX_SHIFT 0
26 #define EDMA_REGISTER_ACCESS_SHIFT 16
27
28 #define EDMA_REGISTER_INDEX_MASK 0x0000ffff
29 #define EDMA_REGISTER_ACCESS_MASK 0xffff0000
30
31 #define EDMA_REGISTER_MAKE(index, access)\
32 (((index) << EDMA_REGISTER_INDEX_SHIFT) |\
33 ((access) << EDMA_REGISTER_ACCESS_SHIFT))
34
35 /* register indexes */
36 #define EDMA_MP_CS_INDEX 0
37 #define EDMA_MP_ES_INDEX 1
38 #define EDMA_MP_INT_INDEX 2
39 #define EDMA_MP_HRS_INDEX 3
40 #define EDMA_MP_CH_GRPRI_INDEX 4
41 #define EDMA_TCD_CH_CSR_INDEX 5
42 #define EDMA_TCD_CH_ES_INDEX 6
43 #define EDMA_TCD_CH_INT_INDEX 7
44 #define EDMA_TCD_CH_SBR_INDEX 8
45 #define EDMA_TCD_CH_PRI_INDEX 9
46 #define EDMA_TCD_SADDR_INDEX 10
47 #define EDMA_TCD_SOFF_INDEX 11
48 #define EDMA_TCD_ATTR_INDEX 12
49 #define EDMA_TCD_NBYTES_INDEX 13
50 #define EDMA_TCD_SLAST_SDA_INDEX 14
51 #define EDMA_TCD_DADDR_INDEX 15
52 #define EDMA_TCD_DOFF_INDEX 16
53 #define EDMA_TCD_CITER_INDEX 17
54 #define EDMA_TCD_DLAST_SGA_INDEX 18
55 #define EDMA_TCD_CSR_INDEX 19
56 #define EDMA_TCD_BITER_INDEX 20
57 #define EDMA_MP_INT_LOW_INDEX 21
58 #define EDMA_MP_INT_HIGH_INDEX 22
59 #define EDMA_MP_HRS_LOW_INDEX 23
60 #define EDMA_MP_HRS_HIGH_INDEX 24
61 #define EDMA_TCD_CH_MUX_INDEX 25
62 #define EDMA_TCD_CH_MATTR_INDEX 26
63 #define EDMA_MP_CH_MUX_INDEX 27
64 #define EDMA_TCD_SADDR_HIGH_INDEX 28
65 #define EDMA_TCD_DADDR_HIGH_INDEX 29
66 #define EDMA_TCD_SLAST_SDA_HIGH_INDEX 30
67 #define EDMA_TCD_DLAST_SGA_HIGH_INDEX 31
68
69 /* utility macros - for external and internal usage */
70 #define EDMA_HAS_MUX(cfg) ((cfg)->flags & EDMA_HAS_CH_MUX_FLAG)
71
72 /* register-related macros */
73 #define EDMA_TCD_ATTR_SSIZE_DSIZE_MASK 0x3
74 #define EDMA_TCD_ATTR_DSIZE(x) ((x) & EDMA_TCD_ATTR_SSIZE_DSIZE_MASK)
75 #define EDMA_TCD_ATTR_SSIZE(x) (((x) & EDMA_TCD_ATTR_SSIZE_DSIZE_MASK) << 8)
76
77 #define EDMA_TCD_CITER_ELINKNO_MASK 0xf
78 #define EDMA_TCD_CITER_ELINKNO(x) ((x) & EDMA_TCD_CITER_ELINKNO_MASK)
79
80 #define EDMA_TCD_BITER_ELINKNO_MASK 0xf
81 #define EDMA_TCD_BITER_ELINKNO(x) ((x) & EDMA_TCD_BITER_ELINKNO_MASK)
82
83 #define EDMA_TCD_NBYTES_MLOFFNO_MASK 0x3fffffff
84 #define EDMA_TCD_NBYTES_MLOFFNO(x) ((x) & EDMA_TCD_NBYTES_MLOFFNO_MASK)
85
86 #define EDMA_TCD_CSR_INTHALF_MASK EDMA_BIT(2)
87 #define EDMA_TCD_CSR_INTMAJOR_MASK EDMA_BIT(1)
88
89 #define EDMA_TCD_CH_CSR_ACTIVE_MASK EDMA_BIT(31)
90 #define EDMA_TCD_CH_CSR_DONE_MASK EDMA_BIT(30)
91 #define EDMA_TCD_CH_CSR_ERQ_MASK EDMA_BIT(0)
92
93 #define EDMA_TCD_CH_INT_MASK BIT(1)
94
95 /* EDMA registers */
96 /* common MP-related registers */
97 #define EDMA_MP_CS EDMA_REGISTER_MAKE(EDMA_MP_CS_INDEX, kEDMA_RegAccess32)
98 #define EDMA_MP_ES EDMA_REGISTER_MAKE(EDMA_MP_ES_INDEX, kEDMA_RegAccess32)
99 #define EDMA_MP_INT EDMA_REGISTER_MAKE(EDMA_MP_INT_INDEX, kEDMA_RegAccess32)
100 #define EDMA_MP_HRS EDMA_REGISTER_MAKE(EDMA_MP_HRS_INDEX, kEDMA_RegAccess32)
101 /* TODO: access requires validation */
102 #define EDMA_MP_CH_GRPRI EDMA_REGISTER_MAKE(EDMA_MP_CH_GRPRI_INDEX, kEDMA_RegAccess32)
103 /* common TCD-related registers */
104 #define EDMA_TCD_CH_CSR EDMA_REGISTER_MAKE(EDMA_TCD_CH_CSR_INDEX, kEDMA_RegAccess32)
105 #define EDMA_TCD_CH_ES EDMA_REGISTER_MAKE(EDMA_TCD_CH_ES_INDEX,kEDMA_RegAccess32)
106 #define EDMA_TCD_CH_INT EDMA_REGISTER_MAKE(EDMA_TCD_CH_INT_INDEX, kEDMA_RegAccess32)
107 /* TODO: access requires validation */
108 #define EDMA_TCD_CH_SBR EDMA_REGISTER_MAKE(EDMA_TCD_CH_SBR_INDEX, kEDMA_RegAccess32)
109 #define EDMA_TCD_CH_PRI EDMA_REGISTER_MAKE(EDMA_TCD_CH_PRI_INDEX, kEDMA_RegAccess32)
110 #define EDMA_TCD_SADDR EDMA_REGISTER_MAKE(EDMA_TCD_SADDR_INDEX, kEDMA_RegAccess32)
111 #define EDMA_TCD_SOFF EDMA_REGISTER_MAKE(EDMA_TCD_SOFF_INDEX, kEDMA_RegAccess16)
112 #define EDMA_TCD_ATTR EDMA_REGISTER_MAKE(EDMA_TCD_ATTR_INDEX, kEDMA_RegAccess16)
113 #define EDMA_TCD_NBYTES EDMA_REGISTER_MAKE(EDMA_TCD_NBYTES_INDEX, kEDMA_RegAccess32)
114 #define EDMA_TCD_SLAST_SDA EDMA_REGISTER_MAKE(EDMA_TCD_SLAST_SDA_INDEX, kEDMA_RegAccess32)
115 #define EDMA_TCD_DADDR EDMA_REGISTER_MAKE(EDMA_TCD_DADDR_INDEX, kEDMA_RegAccess32)
116 #define EDMA_TCD_DOFF EDMA_REGISTER_MAKE(EDMA_TCD_DOFF_INDEX, kEDMA_RegAccess16)
117 #define EDMA_TCD_CITER EDMA_REGISTER_MAKE(EDMA_TCD_CITER_INDEX, kEDMA_RegAccess16)
118 #define EDMA_TCD_DLAST_SGA EDMA_REGISTER_MAKE(EDMA_TCD_DLAST_SGA_INDEX, kEDMA_RegAccess32)
119 #define EDMA_TCD_CSR EDMA_REGISTER_MAKE(EDMA_TCD_CSR_INDEX, kEDMA_RegAccess16)
120 #define EDMA_TCD_BITER EDMA_REGISTER_MAKE(EDMA_TCD_BITER_INDEX, kEDMA_RegAccess16)
121 /* non-common MP-related registers */
122 #define EDMA_MP_INT_LOW EDMA_REGISTER_MAKE(EDMA_MP_INT_LOW_INDEX, kEDMA_RegAccess32)
123 #define EDMA_MP_INT_HIGH EDMA_REGISTER_MAKE(EDMA_MP_INT_HIGH_INDEX, kEDMA_RegAccess32)
124 #define EDMA_MP_HRS_LOW EDMA_REGISTER_MAKE(EDMA_MP_HRS_LOW_INDEX, kEDMA_RegAccess32)
125 #define EDMA_MP_HRS_HIGH EDMA_REGISTER_MAKE(EDMA_MP_HRS_HIGH_INDEX, kEDMA_RegAccess32)
126 #define EDMA_MP_CH_MUX EDMA_REGISTER_MAKE(EDMA_MP_CH_MUX_INDEX, kEDMA_RegAccess32)
127 /* non-common TCD-related registers */
128 #define EDMA_TCD_CH_MUX EDMA_REGISTER_MAKE(EDMA_TCD_CH_MUX_INDEX, kEDMA_RegAccess32)
129 #define EDMA_TCD_CH_MATTR EDMA_REGISTER_MAKE(EDMA_TCD_CH_MATTR_INDEX, kEDMA_RegAccess16)
130 #define EDMA_TCD_SADDR_HIGH EDMA_REGISTER_MAKE(EDMA_TCD_SADDR_HIGH_INDEX, kEDMA_RegAccess32)
131 #define EDMA_TCD_DADDR_HIGH EDMA_REGISTER_MAKE(EDMA_TCD_DADDR_HIGH_INDEX, kEDMA_RegAccess32)
132 #define EDMA_TCD_SLAST_SDA_HIGH EDMA_REGISTER_MAKE(EDMA_TCD_SLAST_SDA_HIGH_INDEX, kEDMA_RegAccess32)
133 #define EDMA_TCD_DLAST_SGA_HIGH EDMA_REGISTER_MAKE(EDMA_TCD_DLAST_SGA_HIGH_INDEX, kEDMA_RegAccess32)
134
135 enum _edma_status {
136 /* Passed configuration is invalid */
137 kStatus_EDMA_InvalidConfiguration = MAKE_STATUS(kStatusGroup_EDMA, 0),
138 };
139
140 enum _edma_register_access {
141 kEDMA_RegAccess16 = 0, /* register requires 16-bit access */
142 kEDMA_RegAccess32, /* register requires 32-bit access */
143 };
144
145 enum _edma_transfer_width {
146 kEDMA_TransferWidth1B = 1, /* Transfer width of 1 byte */
147 kEDMA_TransferWidth2B = 2, /* Transfer width of 2 bytes */
148 kEDMA_TransferWidth4B = 4, /* Transfer width of 4 bytes */
149 kEDMA_TransferWidth8B = 8, /* Transfer width of 8 bytes */
150 kEDMA_TransferWidth16B = 16, /* Transfer width of 16 bytes */
151 kEDMA_TransferWidth32B = 32, /* Transfer width of 32 bytes */
152 kEDMA_TransferWidth64B = 64, /* Transfer width of 64 bytes */
153 kEDMA_TransferWidth128B = 128, /* Transfer width of 128 bytes */
154 };
155
156 enum _edma_transfer_type {
157 kEDMA_TransferTypeM2M = 0, /* Memory to memory transfer */
158 kEDMA_TransferTypeM2P, /* Memory to peripheral transfer */
159 kEDMA_TransferTypeP2M, /* Peripheral to memory transfer */
160 };
161
162 typedef struct _edma_config {
163 /* EDMA base address. Should be overwritten by user if working with virtual
164 * addresses.
165 */
166 uint32_t regmap;
167 /* Number of channels the EDMA controller has */
168 const uint32_t channels;
169 /* Offset from EDMA base at which the channel-related reigsters start */
170 const uint32_t channelOffset;
171 /* Size of the memory region in which a channel's registers reside (also
172 * known as channel strobe). For instance, channel 0's registers reside
173 * in region 0x0 - channelWidth, channel 1's registers reside in region
174 * channelWidth - channelWidth * 2, etc...
175 */
176 const uint32_t channelWidth;
177 const uint32_t flags;
178 /* Array describing the registers supported by the EDMA controller */
179 const uint32_t *registerLayout;
180 } edma_config_t;
181
182 /*!
183 * @brief Check if a transfer width is valid
184 *
185 * @param cfg pointer to targeted EDMA's configuration
186 * @param width transfer width to check
187 *
188 * @return true if transfer width is valid, false otherwise.
189 */
EDMA_TransferWidthIsValid(edma_config_t * cfg,uint32_t width)190 static inline bool EDMA_TransferWidthIsValid(edma_config_t *cfg, uint32_t width)
191 {
192 switch (width) {
193 case kEDMA_TransferWidth1B:
194 case kEDMA_TransferWidth2B:
195 case kEDMA_TransferWidth4B:
196 case kEDMA_TransferWidth8B:
197 case kEDMA_TransferWidth16B:
198 case kEDMA_TransferWidth32B:
199 case kEDMA_TransferWidth64B:
200 return true;
201 case kEDMA_TransferWidth128B:
202 if (cfg->flags & EDMA_ALLOWS_128B_TRANSFER_FLAG) {
203 return true;
204 } else {
205 return false;
206 }
207 default:
208 return false;
209 }
210
211 return false;
212 }
213
214 /*!
215 * @brief Function used to write to a channel's register
216 *
217 * Use this function whenever you need to write a channel's TCD register.
218 * Please note that EDMA_MP_CH_GRPRI should also be written using this
219 * function.
220 *
221 * @param cfg pointer to targeted EDMA's configuration
222 * @param channel which channel's registers are targeted
223 * @param reg which register to write
224 * @param value what value to write to the register
225 */
226 void EDMA_ChannelRegWrite(edma_config_t *cfg, int channel, uint32_t reg, uint32_t value);
227
228 /*!
229 * @brief Function used to read a channel's register
230 *
231 * Use this function whenever you need to read a channel's TCD register.
232 * Please note that EDMA_MP_CH_GRPRI should also be read using this
233 * function.
234 *
235 * @param cfg pointer to targeted EDMA's configuration
236 * @param channel which channel's registers are targeted
237 * @param reg which register to read
238 *
239 * @return value from the targeted register
240 */
241 uint32_t EDMA_ChannelRegRead(edma_config_t *cfg, int channel, uint32_t reg);
242
243 /*!
244 * @brief Function use to update a channel's register
245 *
246 * Use this function whenever you need to update a channel's TCD register.
247 * Please note that EDMA_MP_CH_GRPRI should also be updated using this
248 * function.
249 *
250 * @param cfg pointer to targeted EDMA's configuration
251 * @param channel which channel's registers are targeted
252 * @param reg which register to update
253 * @param set mask indicating which bits to set
254 * @param clear mask inidicating which bits to clear
255 */
256 void EDMA_ChannelRegUpdate(edma_config_t *cfg, int channel, uint32_t reg,
257 uint32_t set, uint32_t clear);
258
259 /*!
260 * @brief Function used to write the MP registers
261 *
262 * Use this function whenever you need to write one of the
263 * MP registers (EDMA_MP_CH_GRPRI is excluded).
264 *
265 * @param cfg pointer to targeted EDMA's configuration
266 * @param reg which register to write
267 * @param value what value to write to the register
268 */
269 void EDMA_MPRegWrite(edma_config_t *cfg, uint32_t reg, uint32_t value);
270
271 /*!
272 * @brief Function used to read the MP registers
273 *
274 * Use this function whenever you need to read one of the
275 * MP registers (EDMA_MP_CH_GRPRI is excluded).
276 *
277 * @param cfg pointer to targeted EDMA's configuration
278 * @param reg which register to write
279 *
280 * @return value from the targeted register
281 */
282 uint32_t EDMA_MPRegRead(edma_config_t *cfg, uint32_t reg);
283
284 /*!
285 * @brief Function used to set the channel MUX value.
286 *
287 * Use this function to set the EDMA channel MUX value. Before
288 * using this function, the user needs to check if the EDMA
289 * version support channel multiplexation via the @EDMA_HAS_MUX
290 * macro. The user also needs to check if the channel MUX value is
291 * already set otherwise this function will raise an error.
292 *
293 * @param cfg pointer to targeted EDMA's configuration
294 * @param channel channel for which we're trying to set the mux value
295 * @param mux mux value to set
296 *
297 * @return kStatus_InvalidArgument one of the passed arguments is invalid
298 * @return kStatus_EDMA_InvalidConfiguration the configuration we're trying to
299 * set is invalid
300 * @return kStatus_Busy mux value is already set to a value != 0
301 */
302 status_t EDMA_SetChannelMux(edma_config_t *cfg, int channel, uint32_t mux);
303
304 /*!
305 * @brief Function use to prepare an EDMA channel for a transfer
306 *
307 * @param cfg pointer to targeted EDMA's configuration
308 * @param channel channel to configure for the transfer
309 * @param saddr source address
310 * @param daddr destination address
311 * @param ssize source data transfer size
312 * @param dsize destination data transfer size
313 * @param burstSize number of bytes per transfer
314 * @param transferSize total number of bytes to transfer
315 * @param transferType type of transfer. May be P2M, M2P, M2M.
316 *
317 * @return kStatus_InvalidArgument one of the passed arguments is invalid
318 * @return kStatus_EDMA_InvalidConfiguration the configuration we're trying
319 * to use is invalid
320 */
321 status_t EDMA_ConfigureTransfer(edma_config_t *cfg, int channel,
322 uint32_t saddr, uint32_t daddr,
323 uint32_t ssize, uint32_t dsize,
324 uint32_t burstSize, uint32_t transferSize,
325 uint32_t transferType);
326
327 #if defined(__cplusplus)
328 }
329 #endif
330 #endif /* _FSL_EDMA_REV2_H_ */
331