3 * arch/arm/plat-rk/dma_memcpy_test.c
5 * Copyright (C) 2012 Rochchip.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * Author: hhb@rock-chips.com
13 * Create Date: 2012.03.26
16 * enter the follow command at command line
17 * echo 1 > sys/module/dma_memcpy_test/parameters/debug enable log output,default is enable
18 * echo 1000 > sys/module/dma_memcpy_test/parameters/interval set dma transfer interval, default is 1000ms
19 * echo 1 > /sys/devices/platform/dma_memcpy.0/dmamemcpy to start the dma test
26 *v1.0 : 1. add dam thread number from 2 to 8;
30 #define VERSION_AND_TIME "dma_memcpy_test.c v1.0 2012-08-13"
32 #include <linux/module.h>
33 #include <linux/platform_device.h>
34 #include <linux/irq.h>
36 #include <linux/wait.h>
37 #include <linux/sched.h>
38 #include <linux/delay.h>
39 #include <asm/uaccess.h>
40 #include <asm/current.h>
41 #include <linux/init.h>
42 #include <linux/dma-mapping.h>
43 #include <linux/dmaengine.h>
44 #include <linux/amba/bus.h>
45 #include <linux/amba/pl330.h>
46 #include <linux/slab.h>
49 #define DMA_TEST_BUFFER_SIZE 512
54 unsigned char* src; //virtual address
57 dma_cap_mask_t cap_mask;
58 struct dma_chan *dma_chan;
59 struct dma_slave_config *config;
60 struct dma_async_tx_descriptor *tx;
65 module_param(debug,int,S_IRUGO|S_IWUSR);
66 #define MEMCPY_DMA_DBG(fmt...) {if(debug > 0) printk(fmt);}
68 static struct Dma_MemToMem DmaMemInfo[DMA_THREAD];
70 static void dma_memtest_transfer(struct Dma_MemToMem *DmaMemInfo)
72 dma_async_tx_descriptor_init(DmaMemInfo->tx, DmaMemInfo->dma_chan);
74 dma_async_memcpy_buf_to_buf(DmaMemInfo->dma_chan, DmaMemInfo->dst,
75 DmaMemInfo->src, DMA_TEST_BUFFER_SIZE);
77 dma_wait_for_async_tx(DmaMemInfo->tx);
79 dmaengine_terminate_all(DmaMemInfo->dma_chan);
83 static ssize_t memcpy_dma_read(struct device *device,struct device_attribute *attr, char *argv)
89 static ssize_t memcpy_dma_write(struct device *device, struct device_attribute *attr, const char *argv, size_t count)
93 printk("memcpy_dma_write\n");
95 for(j = DMA_THREAD; j > 0; j--)
97 memset(DmaMemInfo[j-1].src, ((j-1)<<4|(j-1)), DMA_TEST_BUFFER_SIZE);
98 memset(DmaMemInfo[j-1].dst, 0x0, DMA_TEST_BUFFER_SIZE);
103 dma_memtest_transfer(&DmaMemInfo[7]);
105 dma_memtest_transfer(&DmaMemInfo[6]);
107 dma_memtest_transfer(&DmaMemInfo[5]);
109 dma_memtest_transfer(&DmaMemInfo[4]);
111 dma_memtest_transfer(&DmaMemInfo[3]);
113 dma_memtest_transfer(&DmaMemInfo[2]);
115 dma_memtest_transfer(&DmaMemInfo[1]);
117 dma_memtest_transfer(&DmaMemInfo[0]);
120 printk("%s no channel\n", __func__);
125 for(i = 0; i < 16; i++) {
126 for(j = DMA_THREAD; j > 0; j--)
128 printk("src%d:%2x",j,*(DmaMemInfo[j-1].src + i*(DMA_TEST_BUFFER_SIZE/16)));
129 printk(" -> dst%d:%2x\n",j,*(DmaMemInfo[j-1].dst + i*(DMA_TEST_BUFFER_SIZE/16)));
136 static DEVICE_ATTR(dmamemcpy, S_IRUGO|S_IALLUGO, memcpy_dma_read, memcpy_dma_write);
139 static int dma_memtest_channel_setup_and_init(struct Dma_MemToMem *DmaMemInfo, const char *name,
140 u32 direction, u32 addr_width, u32 maxburst)
142 DmaMemInfo->name = name;
143 dma_cap_set(DMA_MEMCPY, DmaMemInfo->cap_mask);
144 DmaMemInfo->dma_chan = dma_request_channel(DmaMemInfo->cap_mask,NULL,NULL);
146 if(DmaMemInfo->dma_chan==NULL)
148 printk("request dma_chan %s fail\n",DmaMemInfo->name);
152 printk("request dma_chan %s success\n",DmaMemInfo->name);
155 DmaMemInfo->config = kmalloc(sizeof(struct dma_slave_config *),GFP_KERNEL);
156 DmaMemInfo->tx = kmalloc(sizeof(struct dma_async_tx_descriptor *),GFP_KERNEL);
157 if(DmaMemInfo->config == NULL)
159 printk("struct config kmalloc memory %s fail\n",DmaMemInfo->name);
164 printk("struct config kmalloc memory %s sucess\n",DmaMemInfo->name);
168 DmaMemInfo->src = kmalloc(DMA_TEST_BUFFER_SIZE, GFP_KERNEL);
169 DmaMemInfo->dst = kmalloc(DMA_TEST_BUFFER_SIZE, GFP_KERNEL);
170 if(DmaMemInfo->src == NULL || DmaMemInfo->dst == NULL)
172 printk("dma_alloc_coherent %s fail\n",DmaMemInfo->name);
177 printk("dma_alloc_coherent %s success\n",DmaMemInfo->name);
185 static int dma_memcpy_probe(struct platform_device *pdev)
189 ret = device_create_file(&pdev->dev, &dev_attr_dmamemcpy);
190 printk(">>>>>>>>>>>>>>>>>>>>> dam_test_probe <<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
194 dma_memtest_channel_setup_and_init(&DmaMemInfo[7], "DmaMemInfo[7]",
195 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
197 dma_memtest_channel_setup_and_init(&DmaMemInfo[6], "DmaMemInfo[6]",
198 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
200 dma_memtest_channel_setup_and_init(&DmaMemInfo[5], "DmaMemInfo[5]",
201 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
203 dma_memtest_channel_setup_and_init(&DmaMemInfo[4], "DmaMemInfo[4]",
204 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
206 dma_memtest_channel_setup_and_init(&DmaMemInfo[3], "DmaMemInfo[3]",
207 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
209 dma_memtest_channel_setup_and_init(&DmaMemInfo[2], "DmaMemInfo[2]",
210 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
212 dma_memtest_channel_setup_and_init(&DmaMemInfo[1], "DmaMemInfo[1]",
213 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
215 dma_memtest_channel_setup_and_init(&DmaMemInfo[0], "DmaMemInfo[0]",
216 DMA_MEM_TO_MEM, DMA_SLAVE_BUSWIDTH_8_BYTES, 16);
219 printk("%s no channel\n", __func__);
223 printk("dma_memcpy_probe sucess\n");
227 static int dma_memcpy_remove(struct platform_device *pdev)
229 device_remove_file(&pdev->dev, &dev_attr_dmamemcpy);
234 static struct platform_driver dma_mempcy_driver = {
236 .name = "dma_memcpy",
237 .owner = THIS_MODULE,
239 .probe = dma_memcpy_probe,
240 .remove = dma_memcpy_remove,
243 struct platform_device rk29_device_dma_cpy = {
244 .name = "dma_memcpy",
250 static int __init dma_test_init(void)
252 platform_device_register(&rk29_device_dma_cpy);
253 return platform_driver_register(&dma_mempcy_driver);
256 static void __exit dma_test_exit(void)
258 dma_release_channel(DmaMemInfo[0].dma_chan);
259 platform_driver_unregister(&dma_mempcy_driver);
262 late_initcall(dma_test_init);
263 module_exit(dma_test_exit);
265 MODULE_DESCRIPTION("RK29 PL330 Dma Test Deiver");
266 MODULE_LICENSE("GPL V2");
267 MODULE_AUTHOR("ZhenFu Fang <fzf@rock-chips.com>");
268 MODULE_AUTHOR("Hong Huibin<hhb@rock-chips.com>");