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 */
cacheable31 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小时内删除。
发表评论