summaryrefslogtreecommitdiff
path: root/bsp/phytium/libraries/standalone/drivers/dma/fgdma/fgdma.h
blob: 0319af36188f968898ab9ff477ba9b1d9760c1ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*
 * Copyright : (C) 2022 Phytium Information Technology, Inc.
 * All Rights Reserved.
 *
 * This program is OPEN SOURCE software: you can redistribute it and/or modify it
 * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
 * either version 1.0 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the Phytium Public License for more details.
 *
 *
 * FilePath: fgdma.h
 * Date: 2022-02-10 14:53:42
 * LastEditTime: 2022-02-18 08:25:35
 * Description:  This files is for gdma user api implementation
 *
 * Modify History:
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 * 1.0   huanghe    2021-11-5    init commit
 * 1.1   zhugengyu  2022-5-16    modify according to tech manual.
 */

#ifndef DRIVERS_FGDMA_H
#define DRIVERS_FGDMA_H

#ifdef __cplusplus
extern "C"
{
#endif

/***************************** Include Files *********************************/

#include "ftypes.h"
#include "fassert.h"
#include "ferror_code.h"
#include "fkernel.h"

/************************** Constant Definitions *****************************/
typedef enum
{
    FGDMA_CHAN0_INDEX = 0,
    FGDMA_CHAN1_INDEX = 1,
    FGDMA_CHAN2_INDEX = 2,
    FGDMA_CHAN3_INDEX = 3,
    FGDMA_CHAN4_INDEX = 4,
    FGDMA_CHAN5_INDEX = 5,
    FGDMA_CHAN6_INDEX = 6,
    FGDMA_CHAN7_INDEX = 7,
    FGDMA_CHAN8_INDEX = 8,
    FGDMA_CHAN9_INDEX = 9,
    FGDMA_CHAN10_INDEX = 10,
    FGDMA_CHAN11_INDEX = 11,
    FGDMA_CHAN12_INDEX = 12,
    FGDMA_CHAN13_INDEX = 13,
    FGDMA_CHAN14_INDEX = 14,
    FGDMA_CHAN15_INDEX = 15,

    FGDMA_NUM_OF_CHAN
} FGdmaChanIndex; /* 16个独立通道, 0 ~ 15 */

typedef enum
{
    FGDMA_OPER_NONE_PRIORITY_POLL = -1, /* Priority = -1 表示读写请求仲裁模式为Poll */
    FGDMA_OPER_PRIORITY0 = 0, /* Priority >= 0 表示读写请求仲裁模式为Qos */
    FGDMA_OPER_PRIORITY1 = 1,
    FGDMA_OPER_PRIORITY2 = 2,
    FGDMA_OPER_PRIORITY3 = 3,
    FGDMA_OPER_PRIORITY4 = 4,
    FGDMA_OPER_PRIORITY5 = 5,
    FGDMA_OPER_PRIORITY6 = 6,
    FGDMA_OPER_PRIORITY7 = 7,
    FGDMA_OPER_PRIORITY8 = 8,
    FGDMA_OPER_PRIORITY9 = 9,
    FGDMA_OPER_PRIORITY10 = 10,
    FGDMA_OPER_PRIORITY11 = 11,
    FGDMA_OPER_PRIORITY12 = 12,
    FGDMA_OPER_PRIORITY13 = 13,
    FGDMA_OPER_PRIORITY14 = 14,
    FGDMA_OPER_PRIORITY15 = 15
} FGdmaOperPriority; /* Qos配置,值越高,优先级越高 */

typedef enum
{
    FGDMA_OPER_DIRECT = 0, /* 直接操作模式 */
    FGDMA_OPER_BDL /* BDL操作模式 */
} FGdmaOperMode; /* 支持的操作模式 */

typedef enum
{
    FGDMA_BURST_SIZE_1_BYTE = 0,
    FGDMA_BURST_SIZE_2_BYTE = 1,
    FGDMA_BURST_SIZE_4_BYTE = 2,
    FGDMA_BURST_SIZE_8_BYTE = 3,
    FGDMA_BURST_SIZE_16_BYTE = 4
} FGdmaBurstSize; /* 支持的读写请求size大小 */

#define FGDMA_GET_BURST_SIZE(brust_align)   (1U << brust_align)

typedef enum
{
    FGDMA_CHAN_EVT_FIFO_EMPTY = 0, /* 通道Fifo空事件 */
    FGDMA_CHAN_EVT_FIFO_FULL,      /* 通道Fifo满事件 */
    FGDMA_CHAN_EVT_BDL_END,        /* BDL模式下一个BDL条目传输完成 */
    FGDMA_CHAN_EVT_TRANS_END,      /* 所有传输数据完成 */
    FGDMA_CHAN_EVT_BUSY,           /* 前一次传输未完成,当前还处于传输中 */

    FGDMA_CHAN_NUM_OF_EVT
} FGdmaChanEvtType; /* 通道中断事件 */

#define FGDMA_SUCCESS           FT_SUCCESS
#define FGDMA_ERR_NOT_INIT      FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 0)
#define FGDMA_ERR_CHAN_IN_USE   FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 1)
#define FGDMA_ERR_CHAN_NOT_INIT FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 2)
#define FGDMA_ERR_INVALID_ADDR  FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 3)
#define FGDMA_ERR_INVALID_SIZE  FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 4)
#define FGDMA_ERR_BDL_NOT_ENOUGH  FT_MAKE_ERRCODE(ErrModBsp, ErrGdma, 5)

#define FGDMA_ADDR_ALIGMENT                      128U  /* 直接模式和BDL模式的地址需要按128位对齐 */

/**************************** Type Definitions *******************************/
typedef struct _FGdma FGdma;
typedef struct _FGdmaChan FGdmaChan;

typedef struct
{
    u32 instance_id;               /* GDMA控制器ID */
    u32 irq_num;                   /* GDMA控制器中断号 */
    u32 irq_prority;               /* GDMA控制器中断优先级 */
    volatile uintptr_t base_addr;  /* GDMA控制器基地址 */
    FGdmaOperPriority rd_qos;      /* 读操作优先级 */
    FGdmaOperPriority wr_qos;      /* 写操作优先级 */
} FGdmaConfig; /* GDMA控制器配置 */

typedef struct
{
    u32 src_addr_l; /* 0x0, 数据源地址低32位 */
    u32 src_addr_h; /* 0x4, 数据源地址高32位 */
    u32 dst_addr_l; /* 0x8, 数据目的地址低32位 */
    u32 dst_addr_h; /* 0xc, 数据目的地址高32位 */
#define FGDMA_SRC_TC_BDL_BURST_SET(x)      SET_REG32_BITS((x), 1U, 0U)
#define FGDMA_SRC_TC_BDL_SIZE_SET(x)       SET_REG32_BITS((x), 6U, 4U)
#define FGDMA_SRC_TC_BDL_LEN_SET(x)        SET_REG32_BITS((x), 15U, 8U)
    u32 src_tc;     /* 0x10, 源传输控制位 */
#define FGDMA_DST_TC_BDL_BURST_SET(x)      SET_REG32_BITS((x), 1U, 0U)
#define FGDMA_DST_TC_BDL_SIZE_SET(x)       SET_REG32_BITS((x), 6U, 4U)
#define FGDMA_DST_TC_BDL_LEN_SET(x)        SET_REG32_BITS((x), 15U, 8U)
    u32 dst_tc;     /* 0x14, 目的传输控制 */
    u32 total_bytes;/* 0x18, 传输数据总量,以Byte为单位  */
    u32 ioc;        /* 0x1c, 该条目传输完成中断产生控制位  */
} __attribute__((__packed__)) FGdmaBdlDesc; /* BDL描述符 */

FASSERT_STATIC(0x20U == sizeof(FGdmaBdlDesc));

typedef struct
{
    FGdmaChanIndex      chan_id; /* DMA通道ID */
    FGdmaOperPriority   rd_qos;  /* DMA通道读Qos配置 */
    FGdmaOperPriority   wr_qos;  /* DMA通道写Qos配置 */
    FGdmaOperMode       trans_mode; /* DMA通道的操作模式,直接模式或者BDL模式 */
    /* Direct模式有效 */
    FGdmaBurstSize      rd_align; /* DMA读请求的Burst对齐方式 */
    FGdmaBurstSize      wr_align; /* DMA写请求的Burst对齐方式 */
    /* BDL模式有效 */
    boolean             roll_back; /* 循环模式,TRUE: 当前BDL列表完成后,从第一个BDL项从新开始传输 */
    FGdmaBdlDesc        *descs;
    u32                 total_desc_num;
    u32                 valid_desc_num;
} FGdmaChanConfig; /* DMA通道配置 */

typedef void (*FGdmaChanEvtHandler)(FGdmaChan *const chan, void *args);

typedef struct _FGdmaChan
{
    FGdmaChanConfig config;     /* DMA通道配置 */
    FGdma *gdma;                /* DMA控制器实例 */
    FGdmaChanEvtHandler evt_handlers[FGDMA_CHAN_NUM_OF_EVT];  /* DMA通道事件回调函数 */
    void *evt_handler_args[FGDMA_CHAN_NUM_OF_EVT];            /* DMA通道事件回调函数入参 */
} FGdmaChan; /* GDMA通道实例 */

typedef struct _FGdma
{
    FGdmaConfig config;       /* GDMA控制器配置 */
    u32 is_ready;             /* GDMA控制器初始化是否完成 */
    FGdmaChan *chans[FGDMA_NUM_OF_CHAN]; /* GDMA通道实例,如果通道没有分配,值为NULL */
} FGdma; /* GDMA控制器实例 */

/************************** Variable Definitions *****************************/

/***************** Macros (Inline Functions) Definitions *********************/
/* 获取默认的通道配置 */
#define FGDMA_DEFAULT_DIRECT_CHAN_CONFIG(_chan_id)\
(FGdmaChanConfig){ \
    .chan_id = (_chan_id),\
    .rd_align = FGDMA_BURST_SIZE_4_BYTE,\
    .wr_align = FGDMA_BURST_SIZE_4_BYTE,\
    .rd_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
    .wr_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
    .trans_mode = FGDMA_OPER_DIRECT,\
    .roll_back = FALSE\
}

#define FGDMA_DEFAULT_BDL_CHAN_CONFIG(_chan_id, _bdl_descs, _bdl_desc_num)\
(FGdmaChanConfig){ \
    .chan_id = (_chan_id),\
    .rd_align = FGDMA_BURST_SIZE_4_BYTE,\
    .wr_align = FGDMA_BURST_SIZE_4_BYTE,\
    .rd_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
    .wr_qos = FGDMA_OPER_NONE_PRIORITY_POLL,\
    .trans_mode = FGDMA_OPER_BDL,\
    .roll_back = FALSE,\
    .descs = _bdl_descs,\
    .total_desc_num = _bdl_desc_num,\
    .valid_desc_num = 0U\
}

/************************** Function Prototypes ******************************/
/* 获取GDMA控制器默认配置 */
const FGdmaConfig *FGdmaLookupConfig(u32 instance_id);

/* 初始化GDMA控制器实例 */
FError FGdmaCfgInitialize(FGdma *const instance_p, const FGdmaConfig *config_p);

/* 去初始化GDMA控制器实例 */
void FGdmaDeInitialize(FGdma *const instance_p);

/* 分配指定GDMA通道 */
FError FGdmaAllocateChan(FGdma *const instance_p, FGdmaChan *const chan_p,
                         const FGdmaChanConfig *config_p);

/* 释放GDMA通道 */
FError FGdmaDellocateChan(FGdmaChan *const chan_p);

/* 直接操作模式下发起DMA传输 */
FError FGdmaDirectTransfer(FGdmaChan *const chan_p, uintptr src_addr, uintptr dst_addr, fsize_t data_len);

/* 设置BDL描述符的一个条目 */
FError FGdmaAppendBDLEntry(FGdmaChan *const chan_p, uintptr src_addr, uintptr dst_addr, fsize_t data_len);

/* BDL操作模式下发起DMA传输 */
FError FGdmaBDLTransfer(FGdmaChan *const chan_p);

/* 使能启动GDMA控制器 */
FError FGdmaStart(FGdma *const instance_p);

/* 停止GDMA控制器 */
FError FGdmaStop(FGdma *const instance_p);

/* GDMA中断处理函数 */
void FGdmaIrqHandler(s32 vector, void *args);

/* 注册GDMA通道事件回调函数 */
void FGdmaChanRegisterEvtHandler(FGdmaChan *const chan_p, FGdmaChanEvtType evt,
                                 FGdmaChanEvtHandler handler, void *handler_arg);

/* 打印当前的GDMA寄存器值, DEBUG模式下有效 */
void FGdmaDumpRegisterVals(uintptr base_addr, u32 max_chan);

#ifdef __cplusplus
}
#endif

#endif