1 /*
2  * Copyright (c) 2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _SEDI_DRIVER_DMA_H_
8 #define _SEDI_DRIVER_DMA_H_
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include "sedi_driver_common.h"
15 
16 /*!
17  * \defgroup sedi_driver_dma DMA
18  * \ingroup sedi_driver
19  */
20 
21 #define SEDI_DMA_API_VERSION SEDI_DRIVER_VERSION_MAJOR_MINOR(0, 1)
22 
23 #define DMA_CHANNEL_NUM 8
24 
25 /****** DMA Control Codes *****/
26 
27 /*!
28  * \defgroup dma_control_codes  DMA Control Codes
29  * \ingroup sedi_driver_dma
30  * \{
31  */
32 
33 typedef enum {
34 	SEDI_CONFIG_DMA_DIRECTION = 0,
35 	SEDI_CONFIG_DMA_SR_MEM_TYPE,
36 	SEDI_CONFIG_DMA_DT_MEM_TYPE,
37 	SEDI_CONFIG_DMA_LL_SR_MSB, /* MSB bits of source addr in LL mode*/
38 	SEDI_CONFIG_DMA_LL_DT_MSB, /* MSB bits of destination addr in LL mode*/
39 	SEDI_CONFIG_DMA_BURST_LENGTH,
40 	SEDI_CONFIG_DMA_SR_TRANS_WIDTH,
41 	SEDI_CONFIG_DMA_DT_TRANS_WIDTH,
42 	SEDI_CONFIG_DMA_HS_DEVICE_ID,
43 	SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR,
44 	SEDI_CONFIG_DMA_HS_POLARITY,
45 	SEDI_CONFIG_DMA_CONTROL_ID_MAX
46 } dma_control_code;
47 
48 /*!
49  * DMA Burst Transfer Length
50  */
51 typedef enum {
52 	DMA_BURST_TRANS_LENGTH_1 = 0x0,   /**< Burst length 1 data item. */
53 	DMA_BURST_TRANS_LENGTH_4 = 0x1,   /**< Burst length 4 data items. */
54 	DMA_BURST_TRANS_LENGTH_8 = 0x2,   /**< Burst length 8 data items. */
55 	DMA_BURST_TRANS_LENGTH_16 = 0x3,  /**< Burst length 16 data items. */
56 	DMA_BURST_TRANS_LENGTH_32 = 0x4,  /**< Burst length 32 data items. */
57 	DMA_BURST_TRANS_LENGTH_64 = 0x5,  /**< Burst length 64 data items. */
58 	DMA_BURST_TRANS_LENGTH_128 = 0x6, /**< Burst length 128 data items. */
59 	DMA_BURST_TRANS_LENGTH_256 = 0x7, /**< Burst length 256 data items. */
60 	DMA_BURST_TRANS_LENGTH_MAX
61 } dma_burst_length_t;
62 
63 /*!
64  * DMA Transfer Width
65  */
66 typedef enum {
67 	DMA_TRANS_WIDTH_8 = 0x0,   /**< Transfer width of 8 bits. */
68 	DMA_TRANS_WIDTH_16 = 0x1,  /**< Transfer width of 16 bits. */
69 	DMA_TRANS_WIDTH_32 = 0x2,  /**< Transfer width of 32 bits. */
70 	DMA_TRANS_WIDTH_64 = 0x3,  /**< Transfer width of 64 bits. */
71 	DMA_TRANS_WIDTH_128 = 0x4, /**< Transfer width of 128 bits. */
72 	DMA_TRANS_WIDTH_256 = 0x5, /**< Transfer width of 256 bits. */
73 	DMA_TRANS_WIDTH_MAX
74 } dma_transfer_width_t;
75 
76 /*!
77  * DMA channel direction.
78  */
79 typedef enum {
80 	DMA_MEMORY_TO_MEMORY = 0x0,     /**< Memory to memory transfer. */
81 	DMA_MEMORY_TO_PERIPHERAL = 0x1, /**< Memory to peripheral transfer.*/
82 	DMA_PERIPHERAL_TO_MEMORY = 0x2, /**< Peripheral to memory transfer. */
83 	DMA_PERIPHERAL_TO_PERIPHERAL = 0x3, /**< Peripheral to peripheral. */
84 	DMA_DIRECTION_MAX
85 } dma_channel_direction_t;
86 
87 typedef enum {
88 	DMA_SRAM_MEM = 0x0,
89 	DMA_DRAM_MEM = 0x1,
90 	DMA_UMA_MEM = 0x2,
91 	DMA_MEM_TYPE_MAX
92 } dma_memory_type_t;
93 /*!
94  * handshake polarity
95  */
96 typedef enum {
97 	DMA_HS_POLARITY_HIGH = 0x0, /* handshake polarity high */
98 	DMA_HS_POLARITY_LOW = 0x1,  /* handshake polarity low*/
99 	DMA_HS_POLARITY_MAX
100 } dma_hs_polarity_t;
101 
102 /*!
103  * dma handshake rx/tx
104  */
105 typedef enum {
106 	DMA_HS_PER_RX = 0x0, /* handshake peripheral rx */
107 	DMA_HS_PER_TX = 0x1, /* handshake peripheral tx */
108 	DMA_HS_PER_RTX_MAX
109 } dma_hs_per_rtx_t;
110 
111 typedef enum { DMA_INCREMENT_INC, DMA_INCREMENT_NO_CHANGE } dma_increment_t;
112 
113 /* dma channel control register bit map details*/
114 #define LLP_SRC_EN_LOC 28
115 #define LLP_DST_EN_LOC 27
116 #define TT_FC_LOC 20
117 #define SRC_MSIZE_LOC 14
118 #define DEST_MSIZE_LOC 11
119 #define SINC_LOC 10
120 #define DINC_LOC 8
121 #define SRC_TR_WIDTH_LOC 4
122 #define DST_TR_WIDTH_LOC 1
123 #define INT_EN_LOC 0
124 
125 #define BUILD_LL_CTRL_REG(direction, src_burst, dst_burst, src_width,          \
126 			  dst_width, sinc, dinc)                               \
127 	((direction << TT_FC_LOC) | (sinc << SINC_LOC) | (dinc << DINC_LOC) |  \
128 	 (src_burst << SRC_MSIZE_LOC) | (dst_burst << DEST_MSIZE_LOC) |        \
129 	 (src_width << SRC_TR_WIDTH_LOC) | (dst_width << DST_TR_WIDTH_LOC) |   \
130 	 (1 << LLP_DST_EN_LOC) | (1 << LLP_SRC_EN_LOC) | (1 << INT_EN_LOC))
131 
132 #define BUILD_LL_M2M_CTRL_REG(src_burst, dst_burst, src_width, dst_width)      \
133 	BUILD_LL_CTRL_REG(DMA_MEMORY_TO_MEMORY, src_burst, dst_burst,          \
134 			  src_width, dst_width, DMA_INCREMENT_INC,             \
135 			  DMA_INCREMENT_INC)
136 
137 #define BUILD_LL_M2P_CTRL_REG(src_burst, dst_burst, src_width, dst_width)      \
138 	BUILD_LL_CTRL_REG(DMA_MEMORY_TO_PERIPHERAL, src_burst, dst_burst,      \
139 			  src_width, dst_width, DMA_INCREMENT_INC,             \
140 			  DMA_INCREMENT_NO_CHANGE)
141 
142 #define BUILD_LL_P2M_CTRL_REG(src_burst, dst_burst, src_width, dst_width)      \
143 	BUILD_LL_CTRL_REG(DMA_PERIPHERAL_TO_MEMORY, src_burst, dst_burst,      \
144 			  src_width, dst_width, DMA_INCREMENT_NO_CHANGE,       \
145 			  DMA_INCREMENT_INC)
146 /*!
147  * list item for DMA linker list mode.
148  */
149 typedef struct dma_linked_list_item {
150 	uint32_t src_addr; /**< Block source address. */
151 	uint32_t dst_addr; /**< Block destination address. */
152 	/**< Pointer to next LLI. */
153 	const struct dma_linked_list_item *next_ll_p;
154 	/**< Bottom half Ctrl register. */
155 	union {
156 		uint32_t raw;
157 		struct {
158 			uint32_t int_en : 1;
159 			uint32_t dst_tr_width : 3;
160 			uint32_t src_tr_width : 3;
161 			uint32_t resvd0 : 1;
162 			uint32_t dinc : 1;
163 			uint32_t rsevd1 : 1;
164 			uint32_t sinc : 1;
165 			uint32_t dest_burst_len : 3;
166 			uint32_t src_burst_len : 3;
167 			uint32_t resvd2 : 1;
168 			uint32_t resvd3 : 1;
169 			uint32_t resvd4 : 1;
170 			uint32_t direction : 2;
171 			uint32_t resvd5 : 5;
172 			uint32_t llp_dst_en : 1;
173 			uint32_t llp_src_en : 1;
174 			uint32_t resvd6 : 3;
175 		} bits;
176 	} ctrl_low;
177 	/**< Top half Ctrl register. */
178 	union {
179 		uint32_t raw;
180 		struct {
181 			uint32_t resvd0 : 15;
182 			uint32_t block_size : 17;
183 		};
184 	} ctrl_high;
185 	/* write backs for D/S STAT*/
186 	uint32_t dstat;
187 	uint32_t sstat;
188 } dma_linked_list_item_t;
189 
190 /*!
191  * \}
192  */
193 
194 /****** DMA Event *****/
195 
196 /*!
197  * \defgroup dma_event DMA Event Types
198  * \ingroup sedi_driver_dma
199  * \{
200  */
201 
202 /*!
203  * \def SEDI_DMA_EVENT_TRANSFER_DONE
204  * \brief DMA transfer finished
205  */
206 #define SEDI_DMA_EVENT_TRANSFER_DONE (1UL << 0)
207 
208 /*!
209  * \def SEDI_DMA_EVENT_TRANSFER_INCOMPLETE
210  * \brief DMA incomplete transfer
211  */
212 #define SEDI_DMA_EVENT_TRANSFER_INCOMPLETE (1UL << 1)
213 
214 /*!
215  * \def SEDI_DMA_EVENT_BUSY
216  * \brief DMA is busy
217  */
218 #define SEDI_DMA_EVENT_BUSY (1UL << 2)
219 
220 /*!
221  * \def SEDI_DMA_EVENT_BUS_ERROR
222  * \brief Bus error detected
223  */
224 #define SEDI_DMA_EVENT_BUS_ERROR (1UL << 3)
225 
226 /*!
227  * \}
228  */
229 
230 /*!
231  * \struct sedi_dma_status_t
232  * \brief DMA Status
233  * \ingroup sedi_driver_dma
234  */
235 typedef struct {
236 	/**< Busy flag */
237 	uint32_t busy : 1;
238 	uint32_t bus_error : 1;
239 	uint32_t reserved : 30;
240 } sedi_dma_status_t;
241 
242 /*!
243  * \struct sedi_dma_capabilities_t
244  * \brief DMA Driver Capabilities.
245  * \ingroup sedi_driver_dma
246  */
247 typedef struct {
248 	uint32_t is_available : 1; /** 1:available 0:used by host  **/
249 	uint32_t reserved : 31;    /**< Reserved (must be zero) */
250 } sedi_dma_capabilities_t;
251 
252 /*!
253  * \struct dma_sc_attr_t
254  * \brief DMA scatter gather attributions
255  * \ingroup sedi_driver_dma
256  */
257 typedef struct {
258 	uint32_t src_addr;
259 	uint32_t dst_addr;
260 	uint32_t block_size;
261 	uint32_t interval;
262 	uint8_t is_scatter;
263 	uint8_t need_reload;
264 } sc_attr_t;
265 
266 /*!
267  * \defgroup dma_event_handler DMA Event Handler Callback
268  * \ingroup sedi_driver_dma
269  * \{
270  */
271 
272 /*!
273  * \typedef sedi_dma_event_cb_t
274  * \brief Callback function type for signal dma event.
275  * \param[in] event: event type. see \ref dma_event
276  * \param[in] dma_device: dma device id
277  * \param[in] channel_id: dma channel id
278  * \param[inout] param: other params
279  * \return    void
280  */
281 typedef void (*sedi_dma_event_cb_t)(IN sedi_dma_t dma_device, IN int channel_id,
282 				    IN int event, INOUT void *param);
283 
284 /*!
285  * \}
286  */
287 
288 /*!
289  * \defgroup dma_function_calls DMA Driver Function Calls
290  * \ingroup sedi_driver_dma
291  * \{
292  */
293 
294 /*!
295  * \brief Get the dma driver's API version.
296  * \return the version of current dma driver's API
297  */
298 sedi_driver_version_t sedi_dma_get_version(void);
299 
300 /*!
301  * \brief Get the device's capabilities.
302  * \param[in] dma_device: dma device id
303  * \param[inout] cap: the capabilities of specific dma device
304  * \return  \ref return_status
305  */
306 int sedi_dma_get_capabilities(IN sedi_dma_t dma_device,
307 			      INOUT sedi_dma_capabilities_t *cap);
308 
309 /*!
310  * \brief Initialize the device
311  * \param[in] dma_device: dma device id
312  * \param[in] channel_id: dma channel id
313  * \param[in] cb: the callback function which can receive device's events.
314  * \param[inout] param: the user defined callback param, like controller point.
315  * \return  \ref return_status
316  */
317 int32_t sedi_dma_init(IN sedi_dma_t dma_device, IN int channel_id,
318 		      IN sedi_dma_event_cb_t cb, INOUT void *param);
319 
320 /*!
321  * \brief Uninitialize the device
322  * \param[in] dma_device: dma device id
323  * \return  \ref return_status
324  */
325 int32_t sedi_dma_uninit(IN sedi_dma_t dma_device, IN int channel_id);
326 
327 /*!
328  * \brief Set the device's power
329  * \param[in] dma_device: dma device id
330  * \param[in] channel_id: dma channel id
331  * \param[in] state: the power state to be set to the device
332  * \return  \ref return_status
333  */
334 int32_t sedi_dma_set_power(IN sedi_dma_t dma_device, IN int channel_id,
335 			   IN sedi_power_state_t state);
336 
337 /*!
338  * \brief  Control the dma device
339  * \param[in] dma_device: dma device id
340  * \param[in] channel_id: dma channel id
341  * \param[in] control: control operation code. see \ref dma_control_codes
342  * \param[in] arg: argument of operation (optional)
343  * \return  \ref return_status
344  */
345 int32_t sedi_dma_control(IN sedi_dma_t dma_device, IN int channel_id,
346 			 IN uint32_t control_id, IN uint32_t arg);
347 
348 /*!
349  * \brief  Get device's status
350  * \param[in] dma_device: dma device id
351  * \param[in] channel_id: dma channel id
352  * \param[out] status: the memory pointer for dma status
353  * \return  \ref return_status
354  */
355 int sedi_dma_get_status(IN sedi_dma_t dma_device, IN int channel_id,
356 			OUT sedi_dma_status_t *status);
357 
358 /*!
359  * \brief  fill up linked-list node with given configuration
360  * \param[inout] ll_p: linked list pointer to fill up
361  * \param[in] src_addr: source addr
362  * \param[in] dst_addr: destination addr
363  * \param[in] block_size: transfer data length
364  * \param[in] ctrl_reg_low: control register lower 32-bitcontent
365  * \param[in] ll_p_next: the pointer to next node, set NULL for the last one
366  * \return \ref return_status
367  */
368 int dma_fill_linkedlist(INOUT dma_linked_list_item_t *ll_p,
369 			IN uint32_t src_addr, IN uint32_t dst_addr,
370 			IN uint32_t block_size, IN uint32_t ctrl_reg_low,
371 			IN dma_linked_list_item_t *ll_p_next);
372 
373 /*!
374  * \brief  fill up linked-list node with given scatter gather configuration
375  * \param[inout] ll_p: linked list pointer to fill up
376  * \param[in] count: linked-list node count
377  * \param[in] ctrl_reg_low: control register lower 32-bitcontent
378  * \param[in] attr: scatter gather attributions
379  * \return \ref return_status
380  */
381 int dma_fill_sc_linkedlist(INOUT dma_linked_list_item_t *llp,
382 			   IN uint8_t count, IN uint32_t ctrl_reg_low,
383 			   IN sc_attr_t *attr);
384 
385 /*!
386  * \brief  transfer data with dma in linked-list mode
387  * \param[in] dma_device: dma device id
388  * \param[in] channel_id: dma channel id
389  * \param[in] linkedlist_header: linked list header indicating the transferring
390  * \return \ref return_status
391  */
392 int32_t
393 sedi_dma_start_ll_transfer(IN sedi_dma_t dma_device, IN int channel_id,
394 			   IN dma_linked_list_item_t *linkedlist_header);
395 
396 /*!
397  * \brief  transfer data with dma
398  * \param[in] dma_device: dma device id
399  * \param[in] channel_id: dma channel id
400  * \param[in] sr_addr: source addr
401  * \param[in] dest_addr: destination addr
402  * \param[in] length: transfer data length
403  * \return \ref return_status
404  */
405 int32_t sedi_dma_start_transfer(IN sedi_dma_t dma_device, IN int channel_id,
406 				IN uint64_t sr_addr, IN uint64_t dest_addr,
407 				IN uint32_t length);
408 
409 /*!
410  * \brief  transfer data with dma in pulling mode
411  * \param[in] dma_device: dma device id
412  * \param[in] channel_id: dma channel id
413  * \param[in] sr_addr: source addr
414  * \param[in] dest_addr: destination addr
415  * \param[in] length: transfer data length
416  * \return \ref return_status
417  */
418 int32_t sedi_dma_start_transfer_polling(IN sedi_dma_t dma_device,
419 					IN int channel_id, IN uint64_t sr_addr,
420 					IN uint64_t dest_addr,
421 					IN uint32_t length);
422 /*!
423  * \brief  abort dma transfer in process
424  * \param[in] dma_device: dma device id
425  * \param[in] channel_id: dma channel id
426  * \return \ref return_status
427  */
428 int32_t sedi_dma_abort_transfer(IN sedi_dma_t dma_device, IN int channel_id);
429 
430 int32_t sedi_dma_get_done_status(IN sedi_dma_t dma_device, IN int channel_id,
431 	OUT uint32_t *done_bytes, OUT dma_linked_list_item_t **next_llp);
432 /*!
433  * \}
434  */
435 
436 #ifdef __cplusplus
437 }
438 #endif
439 
440 #endif /* _SEDI_DRIVER_DMA_H_*/
441