From 34e285616f0478ac44da7b7fc801e77d414a22b7 Mon Sep 17 00:00:00 2001 From: hhb Date: Thu, 9 Aug 2012 18:36:03 +0800 Subject: [PATCH] add dma pl330 memcpy test --- arch/arm/plat-rk/Kconfig | 4 + arch/arm/plat-rk/Makefile | 1 + arch/arm/plat-rk/dma_memcpy_test.c | 235 +++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+) create mode 100644 arch/arm/plat-rk/dma_memcpy_test.c diff --git a/arch/arm/plat-rk/Kconfig b/arch/arm/plat-rk/Kconfig index 5c7a0859c981..0e8c497183dc 100644 --- a/arch/arm/plat-rk/Kconfig +++ b/arch/arm/plat-rk/Kconfig @@ -166,5 +166,9 @@ config RK_PL330_DMA select PL330 help DMA API Driver for PL330 DMAC + +config RK_PL330_DMA_TEST + bool "pl330 DMA memcpy test" + depends on RK_PL330_DMA endif diff --git a/arch/arm/plat-rk/Makefile b/arch/arm/plat-rk/Makefile index bc9832edc8e0..18c7fd90b035 100644 --- a/arch/arm/plat-rk/Makefile +++ b/arch/arm/plat-rk/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_RK29_LAST_LOG) += last_log.o obj-$(CONFIG_USB_GADGET) += usb_detect.o obj-$(CONFIG_RK29_VPU) += vpu_service.o obj-$(CONFIG_RK_PL330_DMA) += dma-pl330.o +obj-$(CONFIG_RK_PL330_DMA_TEST) += dma_memcpy_test.o obj-$(CONFIG_FIQ) += fiq.o obj-$(CONFIG_FIQ_DEBUGGER) += rk_fiq_debugger.o obj-$(CONFIG_RK_EARLY_PRINTK) += early_printk.o ../kernel/debug.o diff --git a/arch/arm/plat-rk/dma_memcpy_test.c b/arch/arm/plat-rk/dma_memcpy_test.c new file mode 100644 index 000000000000..be658680dae4 --- /dev/null +++ b/arch/arm/plat-rk/dma_memcpy_test.c @@ -0,0 +1,235 @@ +/* + * + * arch/arm/plat-rk/dma_memcpy_test.c + * + * Copyright (C) 2012 Rochchip. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Author: hhb@rock-chips.com + * Date: 2012.03.26 + * + * HOW TO USE IT? + * enter the follow command at command line + * echo 1 > sys/module/dma_memcpy_test/parameters/debug enable log output,default is enable + * echo 1 > sys/module/dma_memcpy_test/parameters/dmac1 set dmac1 memcpy + * echo 1 > sys/module/dma_memcpy_test/parameters/dmac2 set dmac2 memcpy + * echo 1000 > sys/module/dma_memcpy_test/parameters/interval set dma transfer interval, default is 1000ms + * echo 1 > /sys/devices/platform/dma_memcpy.0/dmamemcpy to start the dma test + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DMA_TEST_BUFFER_SIZE 4096 +static DECLARE_WAIT_QUEUE_HEAD(wq); +static int wq_condition = 0; + +struct Dma_MemToMem { + dma_addr_t SrcAddr; //phy address + dma_addr_t DstAddr; + unsigned char* src; //virtual address + unsigned char* dst; + int MenSize; +}; +//wait_queue_head_t dma_memcpy_wait; + +//enable log output +static int debug = 1; +module_param(debug,int,S_IRUGO|S_IWUSR); +//set dma transfer interval time (unit ms) +static int interval = 1000; +module_param(interval,int,S_IRUGO|S_IWUSR); + +static int dmac1 = 1; +module_param(dmac1,int,S_IRUGO|S_IWUSR); + +static int dmac2 = -1; +module_param(dmac2,int,S_IRUGO|S_IWUSR); + + +static struct Dma_MemToMem DmaMemInfo1; +static struct Dma_MemToMem DmaMemInfo2; + + +#define MEMCPY_DMA_DBG(fmt...) {if(debug > 0) printk(fmt);} + + +static struct rk29_dma_client rk29_dma_memcpy_client = { + .name = "rk29-dma-memcpy", +}; + + + +static void rk29_dma_memcpy_callback1(void *buf_id, int size, enum rk29_dma_buffresult result) +{ + if(result != RK29_RES_OK){ + return; + } + MEMCPY_DMA_DBG("rk29_dma_memcpy_callback1 ok\n"); + if(wq_condition == 0){ + wq_condition = 1; + wake_up_interruptible(&wq); + } + //wake_up_interruptible(&dma_memcpy_wait); +} + +static void rk29_dma_memcpy_callback2(void *buf_id, int size, enum rk29_dma_buffresult result) +{ + if(result != RK29_RES_OK){ + return; + } + MEMCPY_DMA_DBG("rk29_dma_memcpy_callback2 ok\n"); + if(wq_condition == 0){ + wq_condition = 1; + wake_up_interruptible(&wq); + } + //wake_up_interruptible(&dma_memcpy_wait); +} + +//int slecount = 0; +static ssize_t memcpy_dma_read(struct device *device,struct device_attribute *attr, char *argv) +{ + + return 0; +} + +static ssize_t memcpy_dma_write(struct device *device, struct device_attribute *attr, const char *argv, size_t count) +{ + int rt, i; + // struct Dma_MemToMem *DmaMemInfo1 = (struct Dma_MemToMem *)argv; + MEMCPY_DMA_DBG("memcpy_dma_write\n"); + + //dmac1 + if(dmac1 > 0) { + memset(DmaMemInfo1.src, 0x55, DMA_TEST_BUFFER_SIZE); + memset(DmaMemInfo1.dst, 0x0, DMA_TEST_BUFFER_SIZE); + rt = rk29_dma_devconfig(DMACH_DMAC1_MEMTOMEM, RK29_DMASRC_MEMTOMEM, DmaMemInfo1.SrcAddr); + rt = rk29_dma_enqueue(DMACH_DMAC1_MEMTOMEM, NULL, DmaMemInfo1.DstAddr, DmaMemInfo1.MenSize); + rt = rk29_dma_ctrl(DMACH_DMAC1_MEMTOMEM, RK29_DMAOP_START); + } + + //dmac2 + if(dmac2 > 0) { + memset(DmaMemInfo2.src, 0xaa, DMA_TEST_BUFFER_SIZE); + memset(DmaMemInfo2.dst, 0x0, DMA_TEST_BUFFER_SIZE); + rt = rk29_dma_devconfig(DMACH_DMAC2_MEMTOMEM, RK29_DMASRC_MEMTOMEM, DmaMemInfo2.SrcAddr); + rt = rk29_dma_enqueue(DMACH_DMAC2_MEMTOMEM, NULL, DmaMemInfo2.DstAddr, DmaMemInfo2.MenSize); + rt = rk29_dma_ctrl(DMACH_DMAC2_MEMTOMEM, RK29_DMAOP_START); + } + + if(dmac2 > 0 || dmac1 > 0) + wait_event_interruptible_timeout(wq, wq_condition, 500); + + if(dmac1 > 0) { + for(i = 0; i < 16; i++) { + MEMCPY_DMA_DBG("dmac1 src1:%x", *(DmaMemInfo1.src + i*(DMA_TEST_BUFFER_SIZE/16))); + MEMCPY_DMA_DBG(" -> dst1:%x\n", *(DmaMemInfo1.dst + i*(DMA_TEST_BUFFER_SIZE/16))); + } + } + + if(dmac2 > 0) { + for(i = 0; i < 16; i++) { + MEMCPY_DMA_DBG("dmac2 src2:%x", *(DmaMemInfo2.src + i*(DMA_TEST_BUFFER_SIZE/16))); + MEMCPY_DMA_DBG(" -> dst2:%x\n", *(DmaMemInfo2.dst + i*(DMA_TEST_BUFFER_SIZE/16))); + } + } + msleep(interval); + wq_condition = 0; + //init_waitqueue_head(&dma_memcpy_wait); + //interruptible_sleep_on(&dma_memcpy_wait); + return 0; +} + +static DEVICE_ATTR(dmamemcpy, S_IRUGO|S_IALLUGO, memcpy_dma_read, memcpy_dma_write); + + +static int __devinit dma_memcpy_probe(struct platform_device *pdev) +{ + int ret; + + ret = device_create_file(&pdev->dev, &dev_attr_dmamemcpy); + printk(">>>>>>>>>>>>>>>>>>>>> dam_test_probe <<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + + //dmac1 + if (rk29_dma_request(DMACH_DMAC1_MEMTOMEM, &rk29_dma_memcpy_client, NULL) == -EBUSY) { + printk("DMACH_DMAC1_MEMTOMEM request fail\n"); + } else { + rk29_dma_config(DMACH_DMAC1_MEMTOMEM, 8, 16); + rk29_dma_set_buffdone_fn(DMACH_DMAC1_MEMTOMEM, rk29_dma_memcpy_callback1); + DmaMemInfo1.src = dma_alloc_coherent(NULL, DMA_TEST_BUFFER_SIZE, &DmaMemInfo1.SrcAddr, GFP_KERNEL); + DmaMemInfo1.dst = dma_alloc_coherent(NULL, DMA_TEST_BUFFER_SIZE, &DmaMemInfo1.DstAddr, GFP_KERNEL); + DmaMemInfo1.MenSize = DMA_TEST_BUFFER_SIZE; + printk("DMACH_DMAC1_MEMTOMEM request sucess\n"); + } + + //dmac2 + if (rk29_dma_request(DMACH_DMAC2_MEMTOMEM, &rk29_dma_memcpy_client, NULL) == -EBUSY) { + printk("DMACH_DMAC2_MEMTOMEM request fail\n"); + } else { + rk29_dma_config(DMACH_DMAC2_MEMTOMEM, 8, 16); + rk29_dma_set_buffdone_fn(DMACH_DMAC2_MEMTOMEM, rk29_dma_memcpy_callback2); + DmaMemInfo2.src = dma_alloc_coherent(NULL, DMA_TEST_BUFFER_SIZE, &DmaMemInfo2.SrcAddr, GFP_KERNEL); + DmaMemInfo2.dst = dma_alloc_coherent(NULL, DMA_TEST_BUFFER_SIZE, &DmaMemInfo2.DstAddr, GFP_KERNEL); + DmaMemInfo2.MenSize = DMA_TEST_BUFFER_SIZE; + printk("DMACH_DMAC2_MEMTOMEM request sucess\n"); + } + return 0; +} + +static int __devexit dma_memcpy_remove(struct platform_device *pdev) +{ + device_remove_file(&pdev->dev, &dev_attr_dmamemcpy); + + return 0; +} + +static struct platform_driver dma_mempcy_driver = { + .driver = { + .name = "dma_memcpy", + .owner = THIS_MODULE, + }, + .probe = dma_memcpy_probe, + .remove = __devexit_p(dma_memcpy_remove), +}; + +struct platform_device rk29_device_dma_cpy = { + .name = "dma_memcpy", + .id = 0, + +}; + + +static int __init dma_test_init(void) +{ + platform_device_register(&rk29_device_dma_cpy); + return platform_driver_register(&dma_mempcy_driver); +} + +static void __exit dma_test_exit(void) +{ + platform_driver_unregister(&dma_mempcy_driver); +} + +late_initcall(dma_test_init); +module_exit(dma_test_exit); + +MODULE_DESCRIPTION("RK29 PL330 Dma Test Deiver"); +MODULE_LICENSE("GPL V2"); +MODULE_AUTHOR("ZhenFu Fang "); -- 2.34.1