add ddr_test.c
authorhcy <hcy@rock-chips.com>
Wed, 23 Apr 2014 08:51:39 +0000 (16:51 +0800)
committerhcy <hcy@rock-chips.com>
Wed, 23 Apr 2014 08:52:51 +0000 (16:52 +0800)
arch/arm/mach-rockchip/Kconfig
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/ddr_test.c [new file with mode: 0755]
arch/arm/mach-rockchip/pm-rk3188.c

index e89bc5bc6c60070b1eadcd10b868f13671d33c47..b60c4ddfba1182a0f91d1b14b87063f32b59bf08 100755 (executable)
@@ -67,6 +67,11 @@ config RK_PM_TESTS
        select DVFS
        select WATCHDOG
 
+config DDR_TEST
+       bool "DDR Test"
+       select CRC32
+       default n
+
 config RK_VPU
        tristate "VPU (Video Processing Unit) service driver in kernel"
        depends on ARCH_ROCKCHIP
index ce6bf257f39828128813167aea8ceb7474072a97..732fb8d732c5fb10431647751fcaa42856b889e5 100755 (executable)
@@ -15,4 +15,5 @@ obj-$(CONFIG_RK_VCODEC) += vcodec_service.o
 obj-$(CONFIG_RK_VPU) += vpu_service.o
 obj-$(CONFIG_RK_PL330_DMA_TEST) += dma_memcpy_test.o
 obj-$(CONFIG_BLOCK_RKNAND) += rknandbase.o
+obj-$(CONFIG_DDR_TEST) += ddr_test.o
 obj-$(CONFIG_RK_PM_TESTS) += rk_pm_tests/
diff --git a/arch/arm/mach-rockchip/ddr_test.c b/arch/arm/mach-rockchip/ddr_test.c
new file mode 100755 (executable)
index 0000000..4cf334f
--- /dev/null
@@ -0,0 +1,291 @@
+#if defined(CONFIG_DDR_TEST)
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/sched/rt.h>
+
+#include <dt-bindings/clock/ddr.h>
+
+struct ddrtest {
+    struct clk *pll;
+    struct clk *clk;
+    volatile unsigned int freq;
+    volatile bool change_end;
+    struct task_struct *task;
+    wait_queue_head_t wait;
+};
+static struct ddrtest ddrtest;
+
+static ssize_t ddr_proc_read(struct file *file, char __user *buffer,
+               unsigned long len, void *data)
+{
+    char version[]={"V100"};
+    u32 i;
+    
+    printk("ddr_test Version V1.0\n");
+    for(i=0;i<len;i++)
+    {
+        buffer[i] = version[i];
+    }
+    return 0;
+}
+
+static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
+                          unsigned long len, void *data)
+{
+    char *cookie_pot;
+    char *p;
+    uint32_t value, value1, value2;
+    uint32_t count, total;
+    char tmp;
+    struct clk *clk_ddr = NULL;
+    int ret = len;
+    char *buf = vzalloc(len);
+
+    cookie_pot = buf;
+
+    if (!cookie_pot)
+    {
+        return -ENOMEM;
+    }
+    else
+    {
+        if (copy_from_user( cookie_pot, buffer, len )) {
+            ret = -EFAULT;
+            goto out;
+        }
+    }
+
+    clk_ddr = clk_get(NULL, "clk_ddr");
+    if (IS_ERR(clk_ddr)) {
+        ret = PTR_ERR(clk_ddr);
+        clk_ddr = NULL;
+        goto out;
+    }
+
+    switch(cookie_pot[0])
+    {
+        case 'c':
+        case 'C':
+            printk("change ddr freq:\n");
+            if(cookie_pot[1] ==':')
+            {
+                strsep(&cookie_pot,":");
+                p=strsep(&cookie_pot,"M");
+                value = simple_strtol(p,NULL,10);
+                printk("change!!! freq=%dMHz\n", value);
+                //clk_set_rate(clk_ddr, value * 1000000);
+                ddrtest.freq = value;
+                ddrtest.change_end = false;
+                wake_up(&ddrtest.wait);
+                while(ddrtest.change_end != true);  //wait change freq end
+                value = clk_get_rate(clk_ddr) / 1000000;
+                printk("success!!! freq=%dMHz\n", value);
+                msleep(64);
+                printk("\n");
+            }
+            else
+            {
+                printk("Error auto change ddr freq debug.\n");
+                printk("-->'c&&C' change freq,Example: echo 'c:400M' > ddr_test\n");
+            }
+            break;
+
+        case 'a':
+        case 'A':
+            printk("auto change ddr freq test (random):\n");
+            if(cookie_pot[1] ==':')
+            {
+                strsep(&cookie_pot,":");
+                p=strsep(&cookie_pot,"M");
+                value1 = simple_strtol(p,NULL,10);
+                strsep(&cookie_pot,"-");
+                p=strsep(&cookie_pot,"M");
+                value2 = simple_strtol(p,NULL,10);
+                strsep(&cookie_pot,"-");
+                p=strsep(&cookie_pot,"T");
+                total = simple_strtol(p,NULL,10);
+
+                count = 0;
+
+                while ( count < total )
+                {
+                    printk("auto change ddr freq test (random):[%d-%d]\n",count,total);
+                    do
+                    {
+                        value = value1 + prandom_u32();
+                        value %= value2;
+                    }while(value < value1);
+
+                    printk("change!!! freq=%dMHz\n", value);
+                    //clk_set_rate(clk_ddr, value * 1000000);
+                    ddrtest.freq = value;
+                    ddrtest.change_end = false;
+                    wake_up(&ddrtest.wait);
+                    while(ddrtest.change_end != true);  //wait change freq end
+                    value = clk_get_rate(clk_ddr) / 1000000;
+                    printk("success!!! freq=%dMHz\n", value);
+                    msleep(64);
+                    count++;
+                }
+
+            }
+            else
+            {
+                printk("Error auto change ddr freq test debug.\n");
+                printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-1000T' > ddr_test\n");
+            }
+            break;
+
+        case 'b':
+        case 'B':
+            printk("auto change ddr freq test (specific):\n");
+            if(cookie_pot[1] ==':')
+            {
+                strsep(&cookie_pot,":");
+                p=strsep(&cookie_pot,"M");
+                value1 = simple_strtol(p,NULL,10);
+                strsep(&cookie_pot,"-");
+                p=strsep(&cookie_pot,"M");
+                value2 = simple_strtol(p,NULL,10);
+                strsep(&cookie_pot,"-");
+                p=strsep(&cookie_pot,"T");
+                total = simple_strtol(p,NULL,10);
+
+                count = 0;
+                tmp = 0;
+
+                while ( count < total )
+                {
+                    printk("auto change ddr freq test (specific):[%d-%d]\n",count,total);
+                    if(tmp == 1)
+                    {
+                        value = value1;
+                        tmp = 0;
+                    }
+                    else
+                    {
+                        value = value2;
+                        tmp = 1;
+                    }
+
+                    printk("change!!! freq=%dMHz\n", value);
+                    //clk_set_rate(clk_ddr, value * 1000000);
+                    ddrtest.freq = value;
+                    ddrtest.change_end = false;
+                    wake_up(&ddrtest.wait);
+                    while(ddrtest.change_end != true);  //wait change freq end
+                    value = clk_get_rate(clk_ddr) / 1000000;
+                    printk("success!!! freq=%dMHz\n", value);
+                    msleep(64);
+                    count++;
+                }
+
+            }
+            else
+            {
+                printk("Error auto change ddr freq test debug.\n");
+                printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'a:200M-400M-1000T' > ddr_test\n");
+            }
+            break;
+            
+        case 'h':
+        case 'H':
+        default:
+            printk("Help for ddr_ts .\n-->The Cmd list: \n");
+            printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-100T' > ddr_test\n");
+            printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'b:200M-400M-100T' > ddr_test\n");
+            printk("-->'c&&C' change freq,Example: echo 'c:400M' > ddr_test\n");
+            break;
+    }
+
+out:
+    if (clk_ddr)
+        clk_put(clk_ddr);
+    vfree(buf);
+    return ret;
+}
+
+static const struct file_operations ddr_proc_fops = {
+    .owner             = THIS_MODULE,
+};
+
+static void ddrtest_work(unsigned int value)
+{
+
+    clk_set_rate(ddrtest.clk, value * 1000000);
+    ddrtest.change_end = true;
+}
+
+static int ddrtest_task(void *data)
+{
+    set_freezable();
+
+    do {
+        //unsigned long status = ddr.sys_status;
+        ddrtest_work(ddrtest.freq);
+        wait_event_freezable(ddrtest.wait, (ddrtest.change_end == false ) || kthread_should_stop());
+    } while (!kthread_should_stop());
+
+    return 0;
+}
+
+static const struct file_operations ddrtest_proc_fops = {
+    .owner = THIS_MODULE,
+    .read =  ddr_proc_read,
+    .write = ddr_proc_write,
+};
+
+static int ddr_proc_init(void)
+{
+    struct proc_dir_entry *ddr_proc_entry;
+    int ret=0;
+    struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+    init_waitqueue_head(&ddrtest.wait);
+
+    //ddrtest.pll = clk_get(NULL, "ddr_pll");
+    ddrtest.clk = clk_get(NULL, "clk_ddr");
+    if (IS_ERR(ddrtest.clk)) {
+        ret = PTR_ERR(ddrtest.clk);
+        ddrtest.clk = NULL;
+        pr_err("failed to get ddr clk, error %d\n", ret);
+        goto err;
+    }
+    ddrtest.freq = clk_get_rate(ddrtest.clk)/1000000;
+
+    ddr_proc_entry = proc_create("driver/ddr_ts",
+                           S_IRUGO | S_IWUGO | S_IWUSR | S_IRUSR,
+                           NULL,&ddrtest_proc_fops);
+    
+    if(ddr_proc_entry == NULL){
+        ret = -ENOMEM;
+        pr_err("failed to create proc entry, error %d\n", ret);
+        goto err;
+    }
+
+    ddrtest.task = kthread_create(ddrtest_task, NULL, "ddrtestd");
+    if (IS_ERR(ddrtest.task)) {
+        ret = PTR_ERR(ddrtest.task);
+        pr_err("failed to create kthread! error %d\n", ret);
+        goto err;
+    }
+    sched_setscheduler_nocheck(ddrtest.task,SCHED_FIFO, &param);
+    get_task_struct(ddrtest.task);
+    kthread_bind(ddrtest.task, 0);
+    wake_up_process(ddrtest.task);
+
+err:
+    return 0;
+}
+
+late_initcall_sync(ddr_proc_init);
+#endif // CONFIG_DDR_TEST 
+
index e65a6c6ce857004b24dd77440ba0fba3f9705bc2..68cb66d51ee6d2f35960979e9064d6425daccb62 100755 (executable)
@@ -530,7 +530,7 @@ static  void rkpm_prepare(void)
        rk30_pm_dump_inten();
         #ifdef CONFIG_DDR_TEST
         // memory tester
-        ddr_testmode();
+        //ddr_testmode();
         #endif
 }