linux下pl330DMA控制器驱动分析
1#include <linux/kernel.h>
2#include <linux/io.h>
3#include <linux/init.h>
4#include <linux/slab.h>
5#include <linux/module.h>
6#include <linux/string.h>
7#include <linux/delay.h>
8#include <linux/interrupt.h>
9#include <linux/dma-mapping.h>
10#include <linux/dmaengine.h>
11#include <linux/amba/bus.h>
12#include <linux/amba/pl330.h>
13#include <linux/scatterlist.h>
14#include <linux/of.h>
15#include <linux/of_dma.h>
16#include <linux/err.h>
17
18#include "dmaengine.h"
19#define PL330_MAX_CHAN  8
20#define PL330_MAX_IRQS  32
21#define PL330_MAX_PERI  32
22
23enum pl330_cachectrl {
24 CCTRL0,  /* Noncacheable and nonbufferable */
25 CCTRL1,  /* Bufferable only */
26 CCTRL2,  /* Cacheable, but do not allocate */
27 CCTRL3,  /* Cacheable and bufferable, but do not allocate */
28 INVALID1, /* AWCACHE = 0x1000 */
29 INVALID2,
30 CCTRL6,  /* Cacheable write-through, allocate on writes only */
cacheable
31 CCTRL7,  /* Cacheable write-back, allocate on writes only */
32};
33
34enum pl330_byteswap {
35 SWAP_NO,
36 SWAP_2,
37 SWAP_4,
38 SWAP_8,
39 SWAP_16,
40};
41
42/* Register and Bit field Definitions */
43#define DS  0x0
44#define DS_ST_STOP  0x0
45#define DS_ST_EXEC  0x1
46#define DS_ST_CMISS  0x2
47#define DS_ST_UPDTPC  0x3
48#define DS_ST_WFE  0x4
49#define DS_ST_ATBRR  0x5
50#define DS_ST_QBUSY  0x6
51#define DS_ST_WFP  0x7
52#define DS_ST_KILL  0x8
53#define DS_ST_CMPLT  0x9
54#define DS_ST_FLTCMP  0xe
55#define DS_ST_FAULT  0xf
56
57#define DPC  0x4
58#define INTEN  0x20
59#define ES  0x24
60#define INTSTATUS  0x28
60#define INTSTATUS  0x28
61#define INTCLR  0x2c
62#define FSM  0x30
63#define FSC  0x34
64#define FTM  0x38
65
66#define _FTC  0x40
67#define FTC(n)  (_FTC + (n)*0x4) 68
69#define _CS  0x100
70#define CS(n)  (_CS + (n)*0x8)
71#define CS_CNS  (1 << 21)
72
73#define _CPC  0x104
74#define CPC(n)  (_CPC + (n)*0x8) 75
76#define _SA  0x400
77#define SA(n)  (_SA + (n)*0x20)
78
79#define _DA  0x404
80#define DA(n)  (_DA + (n)*0x20)
81
82#define _CC  0x408
83#define CC(n)  (_CC + (n)*0x20)
84
85#define CC_SRCINC  (1 << 0)
86#define CC_DSTINC  (1 << 14)
87#define CC_SRCPRI  (1 << 8)
88#define CC_DSTPRI  (1 << 22)
89#define CC_SRCNS  (1 << 9)
90#define CC_DSTNS  (1 << 23)
91#define CC_SRCIA  (1 << 10)
92#define CC_DSTIA  (1 << 24)
93#define CC_SRCBRSTLEN_SHFT 4 94#define CC_DSTBRSTLEN_SHFT 18 95#define CC_SRCBRSTSIZE_SHFT 1 96#define CC_DSTBRSTSIZE_SHFT 15 97#define CC_SRCCCTRL_SHFT 11 98#define CC_SRCCCTRL_MASK 0x7 99#define CC_DSTCCTRL_SHFT 25 100#define CC_DRCCCTRL_MASK 0x7 101#define CC_SWAP_SHFT  28
102
103#define _LC0  0x40c
104#define LC0(n)  (_LC0 + (n)*0x20) 105
106#define _LC1  0x410
107#define LC1(n)  (_LC1 + (n)*0x20) 108
109#define DBGSTATUS  0xd00
110#define DBG_BUSY  (1 << 0)
111
112#define DBGCMD  0xd04
113#define DBGINST0  0xd08
114#define DBGINST1  0xd0c
115
116#define CR0  0xe00
117#define CR1  0xe04
118#define CR2  0xe08
119#define CR3  0xe0c
120#define CR4  0xe10
121#define CRD  0xe14
122
123#define PERIPH_ID  0xfe0
124#define PERIPH_REV_SHIFT 20 125#define PERIPH_REV_MASK  0xf
126#define PERIPH_REV_R0P0  0
127#define PERIPH_REV_R1P0  1
128#define PERIPH_REV_R1P1  2
129
130#define CR0_PERIPH_REQ_SET (1 << 0)
131#define CR0_BOOT_EN_SET  (1 << 1)
132#define CR0_BOOT_MAN_NS  (1 << 2)
133#define CR0_NUM_CHANS_SHIFT 4
134#define CR0_NUM_CHANS_MASK 0x7
135#define CR0_NUM_PERIPH_SHIFT 12
136#define CR0_NUM_PERIPH_MASK 0x1f
137#define CR0_NUM_EVENTS_SHIFT 17
138#define CR0_NUM_EVENTS_MASK 0x1f
139
140#define CR1_ICACHE_LEN_SHIFT 0
141#define CR1_ICACHE_LEN_MASK 0x7
142#define CR1_NUM_ICACHELINES_SHIFT 4
143#define CR1_NUM_ICACHELINES_MASK 0xf
144
145#define CRD_DATA_WIDTH_SHIFT 0
146#define CRD_DATA_WIDTH_MASK 0x7
147#define CRD_WR_CAP_SHIFT 4
148#define CRD_WR_CAP_MASK  0x7
149#define CRD_WR_Q_DEP_SHIFT 8
150#define CRD_WR_Q_DEP_MASK 0xf
151#define CRD_RD_CAP_SHIFT 12
152#define CRD_RD_CAP_MASK  0x7
153#define CRD_RD_Q_DEP_SHIFT 16
154#define CRD_RD_Q_DEP_MASK 0xf
155#define CRD_DATA_BUFF_SHIFT 20
156#define CRD_DATA_BUFF_MASK 0x3ff
157
158#define PART  0x330
159#define DESIGNER  0x41
160#define REVISION  0x0
161#define INTEG_CFG  0x0
162#define PERIPH_ID_VAL  ((PART << 0) | (DESIGNER << 12))
163
164#define PL330_STATE_STOPPED  (1 << 0)
165#define PL330_STATE_EXECUTING  (1 << 1)
166#define PL330_STATE_WFE  (1 << 2)
167#define PL330_STATE_FAULTING  (1 << 3)
168#define PL330_STATE_COMPLETING  (1 << 4)
169#define PL330_STATE_WFP  (1 << 5)
170#define PL330_STATE_KILLING  (1 << 6)
171#define PL330_STATE_FAULT_COMPLETING (1 << 7)
172#define PL330_STATE_CACHEMISS  (1 << 8)
173#define PL330_STATE_UPDTPC  (1 << 9)
174#define PL330_STATE_ATBARRIER  (1 << 10)
175#define PL330_STATE_QUEUEBUSY  (1 << 11)
176#define PL330_STATE_INVALID  (1 << 15)
177
178#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \ 179    | PL330_STATE_WFE | PL330_STATE_FAULTING)
180
181#define CMD_DMAADDH  0x54
182#define CMD_DMAEND  0x00
183#define CMD_DMAFLUSHP  0x35
184#define CMD_DMAGO  0xa0
185#define CMD_DMALD  0x04
186#define CMD_DMALDP  0x25
187#define CMD_DMALP  0x20
188#define CMD_DMALPEND  0x28
189#define CMD_DMAKILL  0x01
190#define CMD_DMAMOV  0xbc
191#define CMD_DMANOP  0x18
192#define CMD_DMARMB  0x12
193#define CMD_DMASEV  0x34
194#define CMD_DMAST  0x08
195#define CMD_DMASTP  0x29
196#define CMD_DMASTZ  0x0c
197#define CMD_DMAWFE  0x36
198#define CMD_DMAWFP  0x30
199#define CMD_DMAWMB  0x13
200
201#define SZ_DMAADDH  3
202#define SZ_DMAEND  1
203#define SZ_DMAFLUSHP  2
204#define SZ_DMALD  1
205#define SZ_DMALDP  2
206#define SZ_DMALP  2
207#define SZ_DMALPEND  2
208#define SZ_DMAKILL  1
209#define SZ_DMAMOV  6
210#define SZ_DMANOP  1
211#define SZ_DMARMB  1
212#define SZ_DMASEV  2
213#define SZ_DMAST  1
214#define SZ_DMASTP  2
215#define SZ_DMASTZ  1
216#define SZ_DMAWFE  2
217#define SZ_DMAWFP  2
218#define SZ_DMAWMB  1
219#define SZ_DMAGO  6
220
221#define BRST_LEN(ccr)  ((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1) 222#define BRST_SIZE(ccr)  (1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7)) 223
224#define BYTE_TO_BURST(b, ccr) ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr)) 225#define BURST_TO_BYTE(c, ccr) ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr)) 226
227/*
228 * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req
229 * at 1byte/burst for P<->M and M<->M respectively.
230 * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req
231 * should be enough for P<->M and M<->M respectively.
232 */
233#define MCODE_BUFF_PER_REQ 256
234
235/* Use this _only_ to wait on transient states */
236#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax();
237
238#ifdef PL330_DEBUG_MCGEN
239static unsigned cmd_line;
240#define PL330_DBGCMD_DUMP(off, x...) do { \
241      printk("%x:", cmd_line); \
242      printk(x); \
243      cmd_line += off; \
244    } while (0)
245#define PL330_DBGMC_START(addr)  (cmd_line = addr)
246#else
247#define PL330_DBGCMD_DUMP(off, x...) do {} while (0)
248#define PL330_DBGMC_START(addr)  do {} while (0)
249#endif
250
251/* The number of default descriptors */
252
253#define NR_DEFAULT_DESC 16
254
255/* Populated by the PL330 core driver for DMA API driver's info */
256struct pl330_config {
257 u32 periph_id;
258#define DMAC_MODE_NS (1 << 0)
259 unsigned int mode;//dma管理线程的安全状态标记,为secure state
260 unsigned int data_bus_width:10; //AXI接⼝数据宽度(64bit)
261 unsigned int data_buf_dep:10;//MFIFO的深度,值为127+1
262 unsigned int num_chan:4;//通道线程数⽬ 7+1
263 unsigned int num_peri:6;//外设请求接⼝数⽬ 3+1
264 u32  peri_ns;//对应bit位的外设请求接⼝的安全状态标记,0--secure 1--non secure
265 unsigned int num_events:6;//dmac⽀持的事件数⽬ 15+1
266 u32  irq_ns;//各个中断的安全状态 0--secure 1--non secure
267};
268
269/**
270 * Request Configuration.
271 * The PL330 core does not modify this and uses the last
272 * working configuration if the request doesn't provide any.
273 *
274 * The Client may want to provide this info only for the
275 * first request and a request with new settings.
276 */
277struct pl330_reqcfg {
278 /* Address Incrementing */
279 unsigned dst_inc:1;
280 unsigned src_inc:1;
281
282 /*
283  * For now, the SRC & DST protection levels
284  * and burst size/length are assumed same.
285  */
286 bool nonsecure;
287 bool privileged;
288 bool insnaccess;
289 unsigned brst_len:5;//⽤来设置ccr寄存器中dst_burst_len和src_burst_len,这个值要⼩于等于16 290 unsigned brst_size:3; //2的幂次⽅,⽤于设置ccr中dst_burst_size和src_burst_size
291
292 enum pl330_cachectrl dcctl;
293 enum pl330_cachectrl scctl;
294 enum pl330_byteswap swap;
295 struct pl330_config *pcfg;
296};
297
298/*
299 * One cycle of DMAC operation.
300 * There may be more than one xfer in a request.
301 */
302struct pl330_xfer {
303 u32 src_addr;
304 u32 dst_addr;
305 /* Size to xfer */
306 u32 bytes;
307};
308
309/* The xfer callbacks are made with one of these arguments. */
310enum pl330_op_err {
311 /* The all xfers in the request were success. */
312 PL330_ERR_NONE,
313 /* If req aborted due to global error. */
314 PL330_ERR_ABORT,
315 /* If req failed due to problem with Channel. */
316 PL330_ERR_FAIL,
317};
318
319enum dmamov_dst {
320 SAR = 0,

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。