1  /*
2  * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 /******************************************************************************
20  * @file     dma.h
21  * @brief    header file for dma driver
22  * @version  V1.0
23  * @date     08. Apr 2020
24  * @model    dma
25  ******************************************************************************/
26 
27 #ifndef _DRV_DMA_H_
28 #define _DRV_DMA_H_
29 
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <drv/common.h>
33 #include <drv/list.h>
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /****** DMA Event *****/
40 typedef enum {
41     DMA_EVENT_TRANSFER_DONE       = 0,  ///< transfer complete
42     DMA_EVENT_TRANSFER_HALF_DONE,       ///< transfer half done
43     DMA_EVENT_TRANSFER_ERROR,           ///< transfer error
44 } csi_dma_event_t;
45 
46 typedef enum {
47     DMA_ADDR_INC    = 0,
48     DMA_ADDR_DEC,
49     DMA_ADDR_CONSTANT
50 } csi_dma_addr_inc_t;
51 
52 typedef enum {
53     DMA_DATA_WIDTH_8_BITS  = 0,
54     DMA_DATA_WIDTH_16_BITS,
55     DMA_DATA_WIDTH_32_BITS,
56     DMA_DATA_WIDTH_64_BITS,
57     DMA_DATA_WIDTH_128_BITS,
58     DMA_DATA_WIDTH_512_BITS
59 } csi_dma_data_width_t;
60 
61 typedef enum {
62     DMA_MEM2MEM     = 0,
63     DMA_MEM2PERH,
64     DMA_PERH2MEM,
65 } csi_dma_trans_dir_t;
66 
67 typedef struct {
68     uint8_t ctrl_idx;
69     uint8_t ch_idx;
70 } csi_dma_ch_desc_t;
71 
72 typedef struct {
73     uint16_t dev_tag;
74     uint8_t  ctrl_idx;
75     const csi_dma_ch_desc_t *ch_list;
76 } csi_dma_ch_spt_list_t;
77 
78 typedef struct {
79     csi_dma_addr_inc_t          src_inc;        ///< source address increment
80     csi_dma_addr_inc_t          dst_inc;        ///< destination address increment
81     csi_dma_data_width_t        src_tw;         ///< source transfer width in byte
82     csi_dma_data_width_t        dst_tw;         ///< destination transfer width in byte
83     csi_dma_trans_dir_t         trans_dir;      ///< transfer direction
84     uint16_t                    handshake;      ///< handshake id
85     uint16_t                    group_len;      ///< group transaction length (unit: bytes)
86     uint8_t                     src_reload_en;  ///< 1:dma enable src addr auto reload, 0:disable
87     uint8_t                     dst_reload_en;  ///< 1:dma enable dst addr auto reload, 0:disable
88     uint8_t                     half_int_en;    ///< 1:dma enable half interrupt, 0: disable
89     uint8_t                     lli_src_en;     ///< 1:dma enable llp, 0 disable
90     uint8_t                     lli_dst_en;     ///< 1:dma enable llp, 0 disable
91 } csi_dma_ch_config_t;
92 
93 #ifndef DMA_LLI_SIZE
94 #define DMA_LLI_SIZE 28
95 #endif
96 
97 #define DEFINE_DESC_BUF(buf_name, num) uint8_t buf_name[num * DMA_LLI_SIZE]
98 
99 typedef struct csi_dma_ch csi_dma_ch_t;
100 
101 struct csi_dma_ch {
102     void                *parent;
103     int8_t              ctrl_id;
104     int8_t              ch_id;
105     void                (*callback)(csi_dma_ch_t *dma_ch, csi_dma_event_t event, void *arg);
106     void                *arg;
107     uint32_t            lli_num;                    //lli buffer len
108     uint32_t            lli_count;                  //lli data count
109     int32_t             lli_w_p;                    //write position
110     int32_t             lli_r_p;                    //read position
111     void                *lli;                       //lli buffer
112     uint32_t            lli_loop_buf0;              //lli loop data
113     uint32_t            lli_loop_buf1;              //lli loop data
114     uint8_t             lli_loop[DMA_LLI_SIZE];     //lli loop handle
115     int16_t             etb_ch_id;
116     slist_t             next;
117 };
118 
119 typedef struct {
120     csi_dev_t           dev;
121     slist_t             head;
122     uint32_t            alloc_status;
123     uint32_t            ch_num;
124     void                *priv;
125 } csi_dma_t;
126 
127 /**
128   \brief       Init dma controller
129   \param[in]   dma     the dma controller operate handle
130   \param[in]   ctrl_id  the dma controller id
131   \return      csi error code
132 */
133 csi_error_t csi_dma_init(csi_dma_t *dma, int8_t ctrl_id);
134 
135 /**
136   \brief       Uninit dma controller
137   \param[in]   dma     the dma controller operate handle
138   \return      none
139 */
140 void csi_dma_uninit(csi_dma_t *dma);
141 
142 /**
143   \brief       Alloc a dma channel
144   \param[in]   dma_ch   the dma channel operate handle
145   \param[in]   ch_id    the channel id  of dma; when set -1, means auto alloc
146   \param[in]   ctrl_id  the dma controller id; when set -1, means auto alloc
147   \return      csi error code
148 */
149 csi_error_t csi_dma_ch_alloc(csi_dma_ch_t *dma_ch, int8_t ch_id, int8_t ctrl_id);
150 
151 /**
152   \brief       Free a dma channel
153   \param[in]   dma_ch   the dma channel operate handle
154   \return      none
155 */
156 void csi_dma_ch_free(csi_dma_ch_t *dma_ch);
157 
158 /**
159   \brief       Config a dma channel
160   \param[in]   dma_ch   the dma channel operate handle
161   \param[in]   config   the config structure for dma channel
162   \return      csi error code
163 */
164 csi_error_t csi_dma_ch_config(csi_dma_ch_t *dma_ch, csi_dma_ch_config_t *config);
165 
166 /**
167   \brief       Start a dma channel
168   \param[in]   dma_ch       the dma channel operate handle
169   \param[in]   psrcaddr     transfer source address
170   \param[in]   pdstaddr     transfer destination address
171   \param[in]   length       transfer length (unit: bytes), if set data_width is 16, the length should be the multiple of 2, and
172                             if set data_width is 32, the length should be the multiple of 4
173   \return      none
174 */
175 void csi_dma_ch_start(csi_dma_ch_t *dma_ch, void *srcaddr, void *dstaddr, uint32_t length);
176 
177 /**
178   \brief       Stop a dma channel
179   \param[in]   dma_ch       the dma channel operate handle
180   \return      none
181 */
182 void csi_dma_ch_stop(csi_dma_ch_t *dma_ch);
183 
184 /**
185   \brief       Attach the callback handler to DMA channel
186   \param[in]   dma_ch     operate handle.
187   \param[in]   callback   callback function
188   \param[in]   arg        user can define it by himself as callback's param
189   \return      error code
190 */
191 csi_error_t csi_dma_ch_attach_callback(csi_dma_ch_t *dma_ch, void *callback, void *arg);
192 
193 /**
194   \brief       detach the callback handler
195   \param[in]   uart  operate handle.
196 */
197 void        csi_dma_ch_detach_callback(csi_dma_ch_t *dma_ch);
198 
199 /**
200   \brief       enable dma power manage
201   \param[in]   dma  dma handle to operate.
202   \return      error code
203 */
204 csi_error_t csi_dma_enable_pm(csi_dma_t *dma);
205 
206 /**
207   \brief       disable dma power manage
208   \param[in]   dma  dma handle to operate.
209 */
210 void        csi_dma_disable_pm(csi_dma_t *dma);
211 
212 #ifdef __cplusplus
213 }
214 #endif
215 
216 #endif /* _CSI_DMA_H_ */
217