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