add dma pl330 memcpy test
authorhhb <hhb@rock-chips.com>
Thu, 9 Aug 2012 10:36:03 +0000 (18:36 +0800)
committerhhb <hhb@rock-chips.com>
Thu, 9 Aug 2012 10:36:47 +0000 (18:36 +0800)
arch/arm/plat-rk/Kconfig
arch/arm/plat-rk/Makefile
arch/arm/plat-rk/dma_memcpy_test.c [new file with mode: 0644]

index 5c7a0859c9816a9902486e18874e9adac61a1999..0e8c497183dc628eb9d43128f51560432f791cc6 100644 (file)
@@ -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
index bc9832edc8e06aa66b763fe03a4b71fb346ca88d..18c7fd90b03580ff537d356137003b3dcd7a88c6 100644 (file)
@@ -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 (file)
index 0000000..be65868
--- /dev/null
@@ -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 <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <mach/io.h>
+#include <plat/dma-pl330.h>
+#include <asm/uaccess.h>
+#include <asm/current.h>
+
+#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 <fzf@rock-chips.com>");