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