Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1124606
  • 博文数量: 177
  • 博客积分: 761
  • 博客等级: 上士
  • 技术积分: 1518
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-04 22:37
文章分类

全部博文(177)

文章存档

2017年(1)

2016年(3)

2015年(33)

2014年(48)

2013年(60)

2012年(32)

分类: LINUX

2013-02-27 13:34:38

原文地址:s3c6410 linux DMA驱动分析 作者:garyybl

最近准备开发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的列表链

3dbg_showbuffs(struct s3c2410_dma_chan *chan)

打印dma通道号,该通道下一个传输的数据buffer,当前传输数据buffer,最后要传输的数据bufferdma地址,传输数据的源地址,目的地址,使用的dma控制器等信息;

4s3c64xx_dma_map_channel(unsigned int channel)

channel: DMA 通道源(范围0-31

channel映射到数组s3c2410_dma_chan[]中,该数据每个成员是一个结构体s3c2410_dma_chan,表示一个dma通道

5s3c2410_dma_config(unsigned int channel, int xferunit)

channel: DMA 通道源(范围0-31

配置相应dma通道的width(可以为0,1,2字节)

6s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,

                struct pl080s_lli *lli,

                dma_addr_t data, int size)

根据dma传输源(存储器,还是外设)配置dma源地址,目的地址,控制变量(control0control1,该变量控制传输size),并将其保存在结构体pl080s_lli

注:该函数配置的是设备到存储器,存储器到设备传输

7. void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,

                struct pl080s_lli *lli)

将结构体pl080s_lli里的要进行dma信息写到相应寄存器中

8int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)

清除dmac中断,使能dma

9int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)

关闭dma传输通道

10void 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

12s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)

停止dma,清除通道的所有buffer

13s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)

根据操作需要(STARTSTOPFLUSH)控制dma通道

14s3c2410_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_allocs3c64xx_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指向该buffernext_lli指向该buffer的成员lli_dma,形成环形队列;

6)如果没有,则该dma_buffer是独立的,配置s3c2410_dma_chan相关成员currnextend

15int 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相关成员peripheraldma要传输的外设设备号),sourcedev_addr

3)根据source配置dma相应通道的源地址或目的地址,中断等寄存器;

16int s3c2410_dma_getposition(unsigned int channel,

                dma_addr_t *src, dma_addr_t *dst)

PL080_CH_SRC_ADDRPL080_CH_DST_ADDR寄存器中读出源地址和目的地址,保存在变量srcdst

17int s3c2410_dma_request(unsigned int channel,

            struct s3c2410_dma_client *client,

            void *dev)

获取dma通道相应结构体s3c2410_dma_chan,将clientdma name),通道号赋值给s3c2410_dma_chan成员clientperipheral

18int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)

获取dma通道相应结构体s3c2410_dma_chan,将s3c2410_dma_chan成员client赋值为nullin_use赋值为0,将映射的结构体dma数组相应channel成员赋值为null

19. static int __init s3c64xx_dma_init(void)

DMA模块初始化

(1)       调用函数dma_pool_create创建dma池,

(2)       初始化两个DMA控制器


http://hi.baidu.com/percy_place/blog/item/68546dec40e67d2d2797916d.html
阅读(1594) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~