分类: LINUX
最近准备开发DMA驱动,先对s3c6410驱动做了一些分析。
代码路径:arch\arm\plat-s3c64xx\Dma.c
1. static void dbg_showchan(struct s3c2410_dma_chan *chan)
通过读寄存器查看channel信息
2. static void show_lli(struct pl080s_lli *lli)
查看 dma 通道数据buffer的列表链
3.dbg_showbuffs(struct s3c2410_dma_chan *chan)
打印dma通道号,该通道下一个传输的数据buffer,当前传输数据buffer,最后要传输的数据buffer,dma地址,传输数据的源地址,目的地址,使用的dma控制器等信息;
4.s3c64xx_dma_map_channel(unsigned int channel)
channel: DMA 通道源(范围0-31)
将channel映射到数组s3c2410_dma_chan[]中,该数据每个成员是一个结构体s3c2410_dma_chan,表示一个dma通道
5.s3c2410_dma_config(unsigned int channel, int xferunit)
channel: DMA 通道源(范围0-31)
配置相应dma通道的width(可以为0,1,2字节)
6.s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
struct pl080s_lli *lli,
dma_addr_t data, int size)
根据dma传输源(存储器,还是外设)配置dma源地址,目的地址,控制变量(control0,control1,该变量控制传输size),并将其保存在结构体pl080s_lli中
注:该函数配置的是设备到存储器,存储器到设备传输
7. void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
struct pl080s_lli *lli)
将结构体pl080s_lli里的要进行dma信息写到相应寄存器中
8.int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
清除dmac中断,使能dma
9.int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
关闭dma传输通道
10.void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
struct s3c64xx_dma_buff *buf,
enum s3c2410_dma_buffresult result)
11 void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
释放dma数据buffer
12.s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
停止dma,清除通道的所有buffer
13. s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
根据操作需要(START,STOP,FLUSH)控制dma通道
14. s3c2410_dma_enqueue(unsigned int channel, void *id,
dma_addr_t data, int size)
将dma_buffer插入队列中
(1)调用函数s3c_dma_lookup_channel找到与通道相关的结构体s3c2410_dma_chan;
(2)为s3c64xx_dma_buff结构体申请内存,保存该结构体;
(3)调用函数dma_pool_alloc为s3c64xx_dma_buff指定的buffer地址处为buffer申请一段连续地址的dma池;
(4)调用函数s3c64xx_dma_fill_lli(chan, lli, data, size)填充chan的成员lli;
(5)如果该s3c64xx_dma_buff还有下一个dma_buffer,则将dma_buffer队列的最后一个成员的下一个buffer指针next指向该buffer,next_lli指向该buffer的成员lli_dma,形成环形队列;
(6)如果没有,则该dma_buffer是独立的,配置s3c2410_dma_chan相关成员curr,next,end;
15.int s3c2410_dma_devconfig(int channel,
enum s3c2410_dmasrc source,
unsigned long devaddr)
配置dma相关寄存器ConfigurationExp
(1)调用函数s3c_dma_lookup_channel找到与通道相关的结构体s3c2410_dma_chan;
(2)给s3c2410_dma_chan相关成员peripheral(dma要传输的外设设备号),source,dev_addr;
(3)根据source配置dma相应通道的源地址或目的地址,中断等寄存器;
16.int s3c2410_dma_getposition(unsigned int channel,
dma_addr_t *src, dma_addr_t *dst)
从PL080_CH_SRC_ADDR和PL080_CH_DST_ADDR寄存器中读出源地址和目的地址,保存在变量src和dst中
17.int s3c2410_dma_request(unsigned int channel,
struct s3c2410_dma_client *client,
void *dev)
获取dma通道相应结构体s3c2410_dma_chan,将client(dma name),通道号赋值给s3c2410_dma_chan成员client,peripheral
18.int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
获取dma通道相应结构体s3c2410_dma_chan,将s3c2410_dma_chan成员client赋值为null,in_use赋值为0,将映射的结构体dma数组相应channel成员赋值为null;
19. static int __init s3c64xx_dma_init(void)
DMA模块初始化
(1) 调用函数dma_pool_create创建dma池,
(2) 初始化两个DMA控制器