1 /*
2 *参考arch/arm/mach-s3c24xx/dma-s3c2410.c
3 */
4 #include <linux/module.h>
5 #include <linux/kernel.h>
6 #include <linux/fs.h>
7 #include <linux/init.h>
8 #include <linux/delay.h>
9 #include <linux/irq.h>
10 #include <asm/uaccess.h>
11 #include <asm/irq.h>
12 #include <asm/io.h>
13 #include <linux/poll.h>
14 #include <plat/regs-dma.h>
15 #include <mach/dma.h>
16 #include <plat/dma-s3c24xx.h>
17 #include <linux/cdev.h>
18 #include <linux/backing-dev.h>
19 #include <linux/wait.h>
20 #include <linux/interrupt.h>
21
22 #define DMA_BASE 0x4b000000
23 #define BUFF_SIZE 512
24
25 static unsigned char *src_addr;//源
26 static unsigned char *dst_addr;//目的
27 static int major;
28 static dma_addr_t psrc_addr;
29 static dma_addr_t pdst_addr;
30
31 static struct class *dma_class;
32 static int dma_ok;
33 #define MEM_COPY_NO_DMA 0
34 #define MEM_COPY_BY_DMA 1
35 static DECLARE_WAIT_QUEUE_HEAD(dma_waitq);
36
37 struct dma_regs {
38 unsigned long disrc;
39 unsigned long disrcc;
40 unsigned long didst;
41 unsigned long didstc;
42 unsigned long dcon;
43 unsigned long dstat;
44 unsigned long dcsrc;
45 unsigned long dcdst;
46 unsigned long dmasktrig;
47 };
48
49 static volatile struct dma_regs *dma_regs;
50
51 long dma_ioctl(struct file *file, unsigned int cmd, unsigned long dat)
52 {
53 int i;
54 memset(src_addr,0xaa,BUFF_SIZE); //从src开始的BUFF_SIZE空间每个字节都设置为0xaa
55 memset(dst_addr,0x55,BUFF_SIZE);
56
57 if(cmd == MEM_COPY_NO_DMA){
58 for(i = 0; i < BUFF_SIZE; i++){
59 dst_addr[i] = src_addr[i];
60 }
61 if(0 == memcmp(src_addr,dst_addr,BUFF_SIZE)){
62 printk("no dma transfer has finished!\n");
63 }else{
64 printk("no dma transfer failed!\n");
65 }
66 }else if(cmd == MEM_COPY_BY_DMA){
67
68 dma_ok = 0;
69
70 dma_regs->disrc = psrc_addr;
71 dma_regs->didst = pdst_addr;
72 dma_regs->dcon = (1<<30) | (1<<29) | (1<<27) | (BUFF_SIZE);
73
74 //启动DMA
75 dma_regs->dmasktrig = (1<<1) | (1<<0);
76
77 /*等待DMA传输完成*/
78 wait_event_interruptible(dma_waitq, dma_ok);
79
80 if(0 == memcmp(src_addr,dst_addr,BUFF_SIZE)){
81 printk("dma transfer has finished!\n");
82 }else{
83 printk("dma transfer failed!\n");
84 }
85
86 }
87 return 0;
88 }
89
90 ssize_t dma_read(struct file *file, char __user *buff, size_t size, loff_t *loff)
91 {
92 int err;
93 err = copy_to_user(buff,dst_addr,size);
94 if(err){
95 return -1;
96 }
97 return 1;
98 }
99
100 static struct file_operations dma_fop = {
101 .owner = THIS_MODULE,
102 .read = dma_read,
103 .unlocked_ioctl = dma_ioctl,
104 };
105
106 irqreturn_t dma_irq(int irq, void *devid)
107 {
108 dma_ok = 1;
109 wake_up_interruptible(&dma_waitq);
110 return IRQ_HANDLED;
111 }
112
113 static int dma_drv_init(void)
114 {
115
116 dma_regs = ioremap(DMA_BASE,sizeof(struct dma_regs));
117
118 src_addr = dma_alloc_writecombine(NULL,BUFF_SIZE, &psrc_addr,GFP_KERNEL);
119 dst_addr = dma_alloc_writecombine(NULL,BUFF_SIZE, &pdst_addr,GFP_KERNEL);
120
121 if(request_irq(IRQ_DMA0,dma_irq,0,"dma_irq",NULL)){
122 printk("request dma irq failed!\n");
123 free_irq(IRQ_DMA0,NULL);
124 return -1;
125 }
126
127 major = register_chrdev(0, "dma-z", &dma_fop);
128 dma_class = class_create(THIS_MODULE, "DMA");
129 device_create(dma_class, NULL, MKDEV(major,0), NULL, "dma0");
130
131 return 0;
132 }
133
134 static void dma_drv_exit(void)
135 {
136 device_destroy(dma_class,MKDEV(major,0));
137 class_destroy(dma_class);
138 free_irq(IRQ_DMA0,NULL);
139 dma_free_writecombine(NULL, BUFF_SIZE,src_addr,psrc_addr);
140 dma_free_writecombine(NULL, BUFF_SIZE,dst_addr,pdst_addr);
141 iounmap(dma_regs);
142 }
143
144 module_init(dma_drv_init);
145 module_exit(dma_drv_exit);
146
147 MODULE_LICENSE("GPL");
148 MODULE_AUTHOR("1653699780@qq.com");