From 83a86dac7ad0fb31d70c54dbfa7fbec8b45e1c8a Mon Sep 17 00:00:00 2001 From: hcy Date: Wed, 23 Apr 2014 16:51:39 +0800 Subject: [PATCH] add ddr_test.c --- arch/arm/mach-rockchip/Kconfig | 5 + arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/ddr_test.c | 291 +++++++++++++++++++++++++++++ arch/arm/mach-rockchip/pm-rk3188.c | 2 +- 4 files changed, 298 insertions(+), 1 deletion(-) create mode 100755 arch/arm/mach-rockchip/ddr_test.c diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index e89bc5bc6c60..b60c4ddfba11 100755 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -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 diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index ce6bf257f398..732fb8d732c5 100755 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -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 index 000000000000..4cf334facece --- /dev/null +++ b/arch/arm/mach-rockchip/ddr_test.c @@ -0,0 +1,291 @@ +#if defined(CONFIG_DDR_TEST) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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'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, ¶m); + 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 + diff --git a/arch/arm/mach-rockchip/pm-rk3188.c b/arch/arm/mach-rockchip/pm-rk3188.c index e65a6c6ce857..68cb66d51ee6 100755 --- a/arch/arm/mach-rockchip/pm-rk3188.c +++ b/arch/arm/mach-rockchip/pm-rk3188.c @@ -530,7 +530,7 @@ static void rkpm_prepare(void) rk30_pm_dump_inten(); #ifdef CONFIG_DDR_TEST // memory tester - ddr_testmode(); + //ddr_testmode(); #endif } -- 2.34.1