ARM: rockchip: rk3228: implement function rk3228_restart
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / ddr_test.c
1 #if defined(CONFIG_DDR_TEST)
2 #include <linux/kernel.h>
3 #include <linux/slab.h>
4 #include <linux/cpu.h>
5 #include <linux/delay.h>
6 #include <linux/proc_fs.h>
7 #include <linux/vmalloc.h>
8 #include <linux/random.h>
9 #include <linux/uaccess.h>
10 #include <linux/clk.h>
11 #include <linux/freezer.h>
12 #include <linux/kthread.h>
13 #include <linux/sched/rt.h>
14 #include <linux/rockchip/dvfs.h>
15
16 #include <dt-bindings/clock/ddr.h>
17
18 struct ddrtest {
19     struct clk *pll;
20     struct clk *clk;
21         struct dvfs_node *clk_dvfs_node;
22     volatile unsigned int freq;
23     volatile bool change_end;
24     struct task_struct *task;
25     wait_queue_head_t wait;
26 };
27 static struct ddrtest ddrtest;
28
29 static ssize_t ddr_proc_read(struct file *file, char __user *buffer,
30                              size_t len, loff_t *data)
31 {
32     char version[]={"V100"};
33     u32 i;
34     
35     printk("ddr_test Version V1.0\n");
36     for(i=0;i<len;i++)
37     {
38         buffer[i] = version[i];
39     }
40     return 0;
41 }
42
43 static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
44                               size_t len, loff_t *data)
45 {
46     char *cookie_pot;
47     char *p;
48     uint32_t value, value1, value2;
49     uint32_t count, total;
50     char tmp;
51     struct clk *clk_ddr = NULL;
52     int ret = len;
53     char *buf = vzalloc(len);
54
55     cookie_pot = buf;
56
57     if (!cookie_pot)
58     {
59         return -ENOMEM;
60     }
61     else
62     {
63         if (copy_from_user( cookie_pot, buffer, len )) {
64             ret = -EFAULT;
65             goto out;
66         }
67     }
68
69     clk_ddr = clk_get(NULL, "clk_ddr");
70     if (IS_ERR(clk_ddr)) {
71         ret = PTR_ERR(clk_ddr);
72         clk_ddr = NULL;
73         goto out;
74     }
75
76     switch(cookie_pot[0])
77     {
78         case 'c':
79         case 'C':
80             printk("change ddr freq:\n");
81             if(cookie_pot[1] ==':')
82             {
83                 strsep(&cookie_pot,":");
84                 p=strsep(&cookie_pot,"M");
85                 value = simple_strtol(p,NULL,10);
86                 printk("change!!! freq=%dMHz\n", value);
87                 //clk_set_rate(clk_ddr, value * 1000000);
88                 ddrtest.freq = value;
89                 ddrtest.change_end = false;
90                 wake_up(&ddrtest.wait);
91                 while(ddrtest.change_end != true);  //wait change freq end
92                 value = clk_get_rate(clk_ddr) / 1000000;
93                 printk("success!!! freq=%dMHz\n", value);
94                 msleep(64);
95                 printk("\n");
96             }
97             else
98             {
99                 printk("Error auto change ddr freq debug.\n");
100                 printk("-->'c&&C' change freq,Example: echo 'c:400M' > ddr_test\n");
101             }
102             break;
103
104         case 'a':
105         case 'A':
106             printk("auto change ddr freq test (random):\n");
107             if(cookie_pot[1] ==':')
108             {
109                 strsep(&cookie_pot,":");
110                 p=strsep(&cookie_pot,"M");
111                 value1 = simple_strtol(p,NULL,10);
112                 strsep(&cookie_pot,"-");
113                 p=strsep(&cookie_pot,"M");
114                 value2 = simple_strtol(p,NULL,10);
115                 strsep(&cookie_pot,"-");
116                 p=strsep(&cookie_pot,"T");
117                 total = simple_strtol(p,NULL,10);
118
119                 count = 0;
120
121                 while ( count < total )
122                 {
123                     printk("auto change ddr freq test (random):[%d-%d]\n",count,total);
124                     do
125                     {
126                         value = value1 + prandom_u32();
127                         value %= value2;
128                     }while(value < value1);
129
130                     printk("change!!! freq=%dMHz\n", value);
131                     //clk_set_rate(clk_ddr, value * 1000000);
132                     ddrtest.freq = value;
133                     ddrtest.change_end = false;
134                     wake_up(&ddrtest.wait);
135                     while(ddrtest.change_end != true);  //wait change freq end
136                     value = clk_get_rate(clk_ddr) / 1000000;
137                     printk("success!!! freq=%dMHz\n", value);
138                     msleep(64);
139                     count++;
140                 }
141
142             }
143             else
144             {
145                 printk("Error auto change ddr freq test debug.\n");
146                 printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-1000T' > ddr_test\n");
147             }
148             break;
149
150         case 'b':
151         case 'B':
152             printk("auto change ddr freq test (specific):\n");
153             if(cookie_pot[1] ==':')
154             {
155                 strsep(&cookie_pot,":");
156                 p=strsep(&cookie_pot,"M");
157                 value1 = simple_strtol(p,NULL,10);
158                 strsep(&cookie_pot,"-");
159                 p=strsep(&cookie_pot,"M");
160                 value2 = simple_strtol(p,NULL,10);
161                 strsep(&cookie_pot,"-");
162                 p=strsep(&cookie_pot,"T");
163                 total = simple_strtol(p,NULL,10);
164
165                 count = 0;
166                 tmp = 0;
167
168                 while ( count < total )
169                 {
170                     printk("auto change ddr freq test (specific):[%d-%d]\n",count,total);
171                     if(tmp == 1)
172                     {
173                         value = value1;
174                         tmp = 0;
175                     }
176                     else
177                     {
178                         value = value2;
179                         tmp = 1;
180                     }
181
182                     printk("change!!! freq=%dMHz\n", value);
183                     //clk_set_rate(clk_ddr, value * 1000000);
184                     ddrtest.freq = value;
185                     ddrtest.change_end = false;
186                     wake_up(&ddrtest.wait);
187                     while(ddrtest.change_end != true);  //wait change freq end
188                     value = clk_get_rate(clk_ddr) / 1000000;
189                     printk("success!!! freq=%dMHz\n", value);
190                     msleep(64);
191                     count++;
192                 }
193
194             }
195             else
196             {
197                 printk("Error auto change ddr freq test debug.\n");
198                 printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'a:200M-400M-1000T' > ddr_test\n");
199             }
200             break;
201             
202         case 'h':
203         case 'H':
204         default:
205             printk("Help for ddr_ts .\n-->The Cmd list: \n");
206             printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-100T' > ddr_test\n");
207             printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'b:200M-400M-100T' > ddr_test\n");
208             printk("-->'c&&C' change freq,Example: echo 'c:400M' > ddr_test\n");
209             break;
210     }
211
212 out:
213     if (clk_ddr)
214         clk_put(clk_ddr);
215     vfree(buf);
216     return ret;
217 }
218
219 static const struct file_operations ddr_proc_fops = {
220     .owner              = THIS_MODULE,
221 };
222
223 static void ddrtest_work(unsigned int value)
224 {
225         dvfs_clk_set_rate(ddrtest.clk_dvfs_node, value * 1000000);
226     ddrtest.change_end = true;
227 }
228
229 static int ddrtest_task(void *data)
230 {
231     set_freezable();
232
233     do {
234         //unsigned long status = ddr.sys_status;
235         ddrtest_work(ddrtest.freq);
236         wait_event_freezable(ddrtest.wait, (ddrtest.change_end == false ) || kthread_should_stop());
237     } while (!kthread_should_stop());
238
239     return 0;
240 }
241
242 static const struct file_operations ddrtest_proc_fops = {
243     .owner = THIS_MODULE,
244     .read =  ddr_proc_read,
245     .write = ddr_proc_write,
246 };
247
248 static int ddr_proc_init(void)
249 {
250     struct proc_dir_entry *ddr_proc_entry;
251     int ret=0;
252     struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
253     init_waitqueue_head(&ddrtest.wait);
254
255     //ddrtest.pll = clk_get(NULL, "ddr_pll");
256     ddrtest.clk = clk_get(NULL, "clk_ddr");
257     if (IS_ERR(ddrtest.clk)) {
258         ret = PTR_ERR(ddrtest.clk);
259         ddrtest.clk = NULL;
260         pr_err("failed to get ddr clk, error %d\n", ret);
261         goto err;
262     }
263     ddrtest.freq = clk_get_rate(ddrtest.clk)/1000000;
264
265         ddrtest.clk_dvfs_node = clk_get_dvfs_node("clk_ddr");
266         if (!ddrtest.clk_dvfs_node)
267                 goto err;
268
269     ddr_proc_entry = proc_create("driver/ddr_ts",
270                            S_IRUGO | S_IWUGO | S_IWUSR | S_IRUSR,
271                            NULL,&ddrtest_proc_fops);
272     
273     if(ddr_proc_entry == NULL){
274         ret = -ENOMEM;
275         pr_err("failed to create proc entry, error %d\n", ret);
276         goto err;
277     }
278
279     ddrtest.task = kthread_create(ddrtest_task, NULL, "ddrtestd");
280     if (IS_ERR(ddrtest.task)) {
281         ret = PTR_ERR(ddrtest.task);
282         pr_err("failed to create kthread! error %d\n", ret);
283         goto err;
284     }
285     sched_setscheduler_nocheck(ddrtest.task,SCHED_FIFO, &param);
286     get_task_struct(ddrtest.task);
287     kthread_bind(ddrtest.task, 0);
288     wake_up_process(ddrtest.task);
289
290 err:
291     return 0;
292 }
293
294 late_initcall_sync(ddr_proc_init);
295 #endif // CONFIG_DDR_TEST 
296