rockchip:midgard:disable temperature control temporarily
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / platform / rk / mali_kbase_dvfs.c
1 /* drivers/gpu/t6xx/kbase/src/platform/manta/mali_kbase_dvfs.c
2   * 
3   *
4  * Rockchip SoC Mali-T764 DVFS driver
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software FoundatIon.
9  */
10
11 /**
12  * @file mali_kbase_dvfs.c
13  * DVFS
14  */
15
16 #include <mali_kbase.h>
17 #include <mali_kbase_uku.h>
18 #include <mali_kbase_mem.h>
19 #include <mali_midg_regmap.h>
20 #include <mali_kbase_mem_linux.h>
21
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/poll.h>
25 #include <linux/kernel.h>
26 #include <linux/errno.h>
27 #include <linux/platform_device.h>
28 #include <linux/pci.h>
29 #include <linux/miscdevice.h>
30 #include <linux/list.h>
31 #include <linux/semaphore.h>
32 #include <linux/fs.h>
33 #include <linux/uaccess.h>
34 #include <linux/interrupt.h>
35 #include <linux/io.h>
36 #include <linux/cpufreq.h>
37 #include <linux/fb.h>
38 #include <linux/clk.h>
39 #include <linux/delay.h>
40 #include <linux/regulator/consumer.h>
41 #include <linux/regulator/driver.h>
42 #include <linux/rk_fb.h>
43
44 #include <linux/rockchip/common.h>
45
46 #include <platform/rk/mali_kbase_platform.h>
47 #include <platform/rk/mali_kbase_dvfs.h>
48 #include <mali_kbase_gator.h>
49 #include <linux/rockchip/dvfs.h>
50 /***********************************************************/
51 /*  This table and variable are using the check time share of GPU Clock  */
52 /***********************************************************/
53 extern int rockchip_tsadc_get_temp(int chn);
54 #define gpu_temp_limit 110
55 #define gpu_temp_statis_time 1
56 #define level0_min 0
57 #define level0_max 70
58 #define levelf_max 100
59 static u32 div_dvfs = 0 ;
60
61 static mali_dvfs_info mali_dvfs_infotbl[] = {
62           {925000, 100000, 0, 70, 0},
63       {925000, 160000, 50, 65, 0},
64       {1025000, 266000, 60, 78, 0},
65       {1075000, 350000, 65, 75, 0},
66       {1125000, 400000, 70, 75, 0},
67       {1200000, 500000, 90, 100, 0},
68 };
69 mali_dvfs_info *p_mali_dvfs_infotbl = NULL;
70
71 unsigned int MALI_DVFS_STEP = ARRAY_SIZE(mali_dvfs_infotbl);
72
73 static struct cpufreq_frequency_table *mali_freq_table = NULL;
74 #ifdef CONFIG_MALI_MIDGARD_DVFS
75 typedef struct _mali_dvfs_status_type {
76         kbase_device *kbdev;
77         int step;
78         int utilisation;
79         u32 temperature;
80         u32 temperature_time;
81 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
82         int upper_lock;
83         int under_lock;
84 #endif
85
86 } mali_dvfs_status;
87
88 static struct workqueue_struct *mali_dvfs_wq = 0;
89 spinlock_t mali_dvfs_spinlock;
90 struct mutex mali_set_clock_lock;
91 struct mutex mali_enable_clock_lock;
92
93 #ifdef CONFIG_MALI_MIDGARD_DEBUG_SYS
94 static void update_time_in_state(int level);
95 #endif
96 /*dvfs status*/
97 static mali_dvfs_status mali_dvfs_status_current;
98
99 #define LIMIT_FPS 60
100 #define LIMIT_FPS_POWER_SAVE 50
101 static void mali_dvfs_event_proc(struct work_struct *w)
102 {
103         unsigned long flags;
104         mali_dvfs_status *dvfs_status;
105         static int level_down_time = 0;
106         static int level_up_time = 0;
107         static u32 temp_tmp;
108         struct rk_context *platform;
109         u32 fps=0;
110         u32 fps_limit;
111         u32 policy;
112         mutex_lock(&mali_enable_clock_lock);
113         dvfs_status = &mali_dvfs_status_current;
114
115         if (!kbase_platform_dvfs_get_enable_status()) {
116                 mutex_unlock(&mali_enable_clock_lock);
117                 return;
118         }
119         platform = (struct rk_context *)dvfs_status->kbdev->platform_context;
120         
121         fps = rk_get_real_fps(0);
122
123         dvfs_status->temperature_time++;
124         /*
125         temp_tmp += rockchip_tsadc_get_temp(2);
126         */
127         if(dvfs_status->temperature_time >= gpu_temp_statis_time)
128         {
129                 dvfs_status->temperature_time = 0;
130                 dvfs_status->temperature = temp_tmp / gpu_temp_statis_time;
131                 temp_tmp = 0;
132                 /*pr_info("dvfs_status->temperature = %d\n",dvfs_status->temperature);*/
133         }
134
135         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
136         /*
137         policy = rockchip_pm_get_policy();
138         */
139         policy = ROCKCHIP_PM_POLICY_NORMAL;
140         
141         if(ROCKCHIP_PM_POLICY_PERFORMANCE == policy)
142         {
143                 dvfs_status->step = MALI_DVFS_STEP - 1; /*Highest level when performance mode*/
144         }
145         else
146         {
147                 fps_limit = (ROCKCHIP_PM_POLICY_NORMAL == policy)?LIMIT_FPS : LIMIT_FPS_POWER_SAVE;
148                 /*
149                 printk("policy : %d , fps_limit = %d\n",policy,fps_limit);
150                 */
151                 
152                 /*give priority to temperature unless in performance mode */
153                 if(dvfs_status->temperature > gpu_temp_limit)
154                 {
155                         if(dvfs_status->step > 0)
156                                 dvfs_status->step--;
157                         
158                         if(gpu_temp_statis_time > 1)
159                                 dvfs_status->temperature = 0;
160                 }
161                 else if ((dvfs_status->utilisation > mali_dvfs_infotbl[dvfs_status->step].max_threshold) && (dvfs_status->step < MALI_DVFS_STEP-1) && fps < fps_limit) 
162                 {
163                         level_up_time++;
164                         if(level_up_time == MALI_DVFS_TIME_INTERVAL)
165                         {
166                                 /*
167                                 printk("up,utilisation=%d,current clock=%d,fps = %d",dvfs_status->utilisation,mali_dvfs_infotbl[dvfs_status->step].clock,fps);
168                                 */
169                                 dvfs_status->step++;
170                                 level_up_time = 0;
171                                 /*
172                                 printk(" next clock=%d\n",mali_dvfs_infotbl[dvfs_status->step].clock);
173                                 */
174                                 BUG_ON(dvfs_status->step >= MALI_DVFS_STEP);
175                         }
176                         level_down_time = 0;
177                 } 
178                 else if((dvfs_status->step > 0) && (dvfs_status->utilisation < mali_dvfs_infotbl[dvfs_status->step].min_threshold)) 
179                 /*else if((dvfs_status->step > 0) && (platform->time_tick == MALI_DVFS_TIME_INTERVAL) && (platform->utilisation < mali_dvfs_infotbl[dvfs_status->step].min_threshold)) */
180                 {
181                         level_down_time++;
182                         if(level_down_time==MALI_DVFS_TIME_INTERVAL)
183                         {
184                                 /*
185                                 printk("down,utilisation=%d,current clock=%d,fps = %d",dvfs_status->utilisation,mali_dvfs_infotbl[dvfs_status->step].clock,fps);
186                                 */
187                                 BUG_ON(dvfs_status->step <= 0);
188                                 dvfs_status->step--;
189                                 level_down_time = 0;
190                                 /*
191                                 printk(" next clock=%d\n",mali_dvfs_infotbl[dvfs_status->step].clock);
192                                 */
193                         }
194                         level_up_time = 0;
195                 }
196                 else
197                 {
198                         level_down_time = 0;
199                         level_up_time = 0;
200                         /*
201                         printk("keep,utilisation=%d,current clock=%d,fps = %d\n",dvfs_status->utilisation,mali_dvfs_infotbl[dvfs_status->step].clock,fps);
202                         */              
203                 }
204         }
205 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
206         if ((dvfs_status->upper_lock >= 0) && (dvfs_status->step > dvfs_status->upper_lock)) 
207         {
208                 dvfs_status->step = dvfs_status->upper_lock;
209         }
210
211         if (dvfs_status->under_lock > 0) 
212         {
213                 if (dvfs_status->step < dvfs_status->under_lock)
214                         dvfs_status->step = dvfs_status->under_lock;
215         }
216 #endif
217         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
218         kbase_platform_dvfs_set_level(dvfs_status->kbdev, dvfs_status->step);
219
220         mutex_unlock(&mali_enable_clock_lock);
221 }
222
223 static DECLARE_WORK(mali_dvfs_work, mali_dvfs_event_proc);
224
225 int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation)
226 {
227         unsigned long flags;
228         struct rk_context *platform;
229
230         BUG_ON(!kbdev);
231         platform = (struct rk_context *)kbdev->platform_context;
232
233         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
234         if (platform->time_tick < MALI_DVFS_TIME_INTERVAL) {
235                 platform->time_tick++;
236                 platform->time_busy += kbdev->pm.metrics.time_busy;
237                 platform->time_idle += kbdev->pm.metrics.time_idle;
238         } else {
239                 platform->time_busy = kbdev->pm.metrics.time_busy;
240                 platform->time_idle = kbdev->pm.metrics.time_idle;
241                 platform->time_tick = 0;
242         }
243
244         if ((platform->time_tick == MALI_DVFS_TIME_INTERVAL) && (platform->time_idle + platform->time_busy > 0))
245                 platform->utilisation = (100 * platform->time_busy) / (platform->time_idle + platform->time_busy);
246
247         mali_dvfs_status_current.utilisation = utilisation;
248         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
249
250         queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
251         /*add error handle here */
252         return MALI_TRUE;
253 }
254
255 int kbase_platform_dvfs_get_utilisation(void)
256 {
257         unsigned long flags;
258         int utilisation = 0;
259
260         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
261         utilisation = mali_dvfs_status_current.utilisation;
262         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
263
264         return utilisation;
265 }
266
267 int kbase_platform_dvfs_get_enable_status(void)
268 {
269         struct kbase_device *kbdev;
270         unsigned long flags;
271         int enable;
272
273         kbdev = mali_dvfs_status_current.kbdev;
274         spin_lock_irqsave(&kbdev->pm.metrics.lock, flags);
275         enable = kbdev->pm.metrics.timer_active;
276         spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags);
277
278         return enable;
279 }
280
281 int kbase_platform_dvfs_enable(bool enable, int freq)
282 {
283         mali_dvfs_status *dvfs_status;
284         struct kbase_device *kbdev;
285         unsigned long flags;
286         struct rk_context *platform;
287
288         dvfs_status = &mali_dvfs_status_current;
289         kbdev = mali_dvfs_status_current.kbdev;
290
291         BUG_ON(kbdev == NULL);
292         platform = (struct rk_context *)kbdev->platform_context;
293
294         mutex_lock(&mali_enable_clock_lock);
295
296         if (enable != kbdev->pm.metrics.timer_active) {
297                 if (enable) {
298                         spin_lock_irqsave(&kbdev->pm.metrics.lock, flags);
299                         kbdev->pm.metrics.timer_active = MALI_TRUE;
300                         spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags);
301                         hrtimer_start(&kbdev->pm.metrics.timer,
302                                         HR_TIMER_DELAY_MSEC(KBASE_PM_DVFS_FREQUENCY),
303                                         HRTIMER_MODE_REL);
304                 } else {
305                         spin_lock_irqsave(&kbdev->pm.metrics.lock, flags);
306                         kbdev->pm.metrics.timer_active = MALI_FALSE;
307                         spin_unlock_irqrestore(&kbdev->pm.metrics.lock, flags);
308                         hrtimer_cancel(&kbdev->pm.metrics.timer);
309                 }
310         }
311
312         if (freq != MALI_DVFS_CURRENT_FREQ) {
313                 spin_lock_irqsave(&mali_dvfs_spinlock, flags);
314                 platform->time_tick = 0;
315                 platform->time_busy = 0;
316                 platform->time_idle = 0;
317                 platform->utilisation = 0;
318                 dvfs_status->step = kbase_platform_dvfs_get_level(freq);
319                 spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
320                 kbase_platform_dvfs_set_level(dvfs_status->kbdev, dvfs_status->step);
321         }
322  
323         mutex_unlock(&mali_enable_clock_lock);
324
325         return MALI_TRUE;
326 }
327 #define dividend 7
328 #define fix_float(a) ((((a)*dividend)%10)?((((a)*dividend)/10)+1):(((a)*dividend)/10))
329 static bool calculate_dvfs_max_min_threshold(u32 level)
330 {
331         u32 pre_level;
332         u32     tmp ;
333         if(0 == level)
334         {
335                 if((MALI_DVFS_STEP-1) == level)
336                 {
337                         mali_dvfs_infotbl[level].min_threshold = level0_min;
338                         mali_dvfs_infotbl[level].max_threshold = levelf_max;
339                 }
340                 else 
341                 {
342                         mali_dvfs_infotbl[level].min_threshold = level0_min;
343                         mali_dvfs_infotbl[level].max_threshold = level0_max;
344                 }
345         }
346         else
347         {
348                 pre_level = level - 1;
349                 if((MALI_DVFS_STEP-1) == level)
350                 {
351                         mali_dvfs_infotbl[level].max_threshold = levelf_max;
352                 }
353                 else
354                 {
355                         mali_dvfs_infotbl[level].max_threshold = mali_dvfs_infotbl[pre_level].max_threshold + div_dvfs;
356                 }
357                 mali_dvfs_infotbl[level].min_threshold = (mali_dvfs_infotbl[pre_level].max_threshold * (mali_dvfs_infotbl[pre_level].clock/1000)) 
358                                                                                                 / (mali_dvfs_infotbl[level].clock/1000); 
359                 
360                 tmp = mali_dvfs_infotbl[level].max_threshold - mali_dvfs_infotbl[level].min_threshold;
361                 
362                 mali_dvfs_infotbl[level].min_threshold += fix_float(tmp);
363         }
364         #if 1
365         printk("mali_dvfs_infotbl[%d].clock=%d,min_threshold=%d,max_threshold=%d\n",level,
366                                                                                                                                                                 mali_dvfs_infotbl[level].clock,
367                                                                                                                                                                 mali_dvfs_infotbl[level].min_threshold,
368                                                                                                                                                                 mali_dvfs_infotbl[level].max_threshold
369                                                                                                                                                                 );
370         #endif
371         return MALI_TRUE;
372 }
373
374 int kbase_platform_dvfs_init(struct kbase_device *kbdev)
375 {
376         unsigned long flags;
377         /*default status
378            add here with the right function to get initilization value.
379          */
380         struct rk_context *platform;
381         int i;
382         
383         platform = (struct rk_context *)kbdev->platform_context;
384         if (NULL == platform)
385                 panic("oops");
386                     
387         mali_freq_table = dvfs_get_freq_volt_table(platform->mali_clk_node);
388         
389         if (mali_freq_table == NULL) 
390         {
391                 printk("mali freq table not assigned yet,use default\n");
392                 goto not_assigned ;
393         }
394         else 
395         {
396                 /*recalculte step*/
397                 MALI_DVFS_STEP = 0;
398                 for (i = 0; mali_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) 
399                 {
400                         mali_dvfs_infotbl[i].clock = mali_freq_table[i].frequency;
401                         MALI_DVFS_STEP++;
402                 }
403                 if(MALI_DVFS_STEP > 1)
404                         div_dvfs = round_up(((levelf_max - level0_max)/(MALI_DVFS_STEP-1)),1);
405                 printk("MALI_DVFS_STEP=%d,div_dvfs=%d\n",MALI_DVFS_STEP,div_dvfs);
406                 
407                 for(i=0;i<MALI_DVFS_STEP;i++)
408                 {
409                         calculate_dvfs_max_min_threshold(i);
410                 }
411                 p_mali_dvfs_infotbl = mali_dvfs_infotbl;                                
412         }
413 not_assigned :
414         if (!mali_dvfs_wq)
415                 mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
416
417         spin_lock_init(&mali_dvfs_spinlock);
418         mutex_init(&mali_set_clock_lock);
419         mutex_init(&mali_enable_clock_lock);
420
421         /*add a error handling here */
422         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
423         mali_dvfs_status_current.kbdev = kbdev;
424         mali_dvfs_status_current.utilisation = 0;
425         mali_dvfs_status_current.step = 0;
426 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
427         mali_dvfs_status_current.upper_lock = -1;
428         mali_dvfs_status_current.under_lock = -1;
429 #endif
430
431         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
432
433         return MALI_TRUE;
434 }
435
436 void kbase_platform_dvfs_term(void)
437 {
438         if (mali_dvfs_wq)
439                 destroy_workqueue(mali_dvfs_wq);
440
441         mali_dvfs_wq = NULL;
442 }
443 #endif /*CONFIG_MALI_MIDGARD_DVFS*/
444
445 int mali_get_dvfs_upper_locked_freq(void)
446 {
447         unsigned long flags;
448         int locked_level = -1;
449
450 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
451         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
452         if (mali_dvfs_status_current.upper_lock >= 0)
453                 locked_level = mali_dvfs_infotbl[mali_dvfs_status_current.upper_lock].clock;
454         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
455 #endif
456         return locked_level;
457 }
458
459 int mali_get_dvfs_under_locked_freq(void)
460 {
461         unsigned long flags;
462         int locked_level = -1;
463
464 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
465         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
466         if (mali_dvfs_status_current.under_lock >= 0)
467                 locked_level = mali_dvfs_infotbl[mali_dvfs_status_current.under_lock].clock;
468         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
469 #endif
470         return locked_level;
471 }
472
473 int mali_get_dvfs_current_level(void)
474 {
475         unsigned long flags;
476         int current_level = -1;
477
478 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
479         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
480         current_level = mali_dvfs_status_current.step;
481         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
482 #endif
483         return current_level;
484 }
485
486 int mali_dvfs_freq_lock(int level)
487 {
488         unsigned long flags;
489 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
490         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
491         if (mali_dvfs_status_current.under_lock >= 0 && mali_dvfs_status_current.under_lock > level) {
492                 printk(KERN_ERR " Upper lock Error : Attempting to set upper lock to below under lock\n");
493                 spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
494                 return -1;
495         }
496         mali_dvfs_status_current.upper_lock = level;
497         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
498
499         printk(KERN_DEBUG " Upper Lock Set : %d\n", level);
500 #endif
501         return 0;
502 }
503
504 void mali_dvfs_freq_unlock(void)
505 {
506         unsigned long flags;
507 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
508         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
509         mali_dvfs_status_current.upper_lock = -1;
510         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
511 #endif
512         printk(KERN_DEBUG "mali Upper Lock Unset\n");
513 }
514
515 int mali_dvfs_freq_under_lock(int level)
516 {
517         unsigned long flags;
518 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
519         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
520         if (mali_dvfs_status_current.upper_lock >= 0 && mali_dvfs_status_current.upper_lock < level) {
521                 printk(KERN_ERR "mali Under lock Error : Attempting to set under lock to above upper lock\n");
522                 spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
523                 return -1;
524         }
525         mali_dvfs_status_current.under_lock = level;
526         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
527
528         printk(KERN_DEBUG "mali Under Lock Set : %d\n", level);
529 #endif
530         return 0;
531 }
532
533 void mali_dvfs_freq_under_unlock(void)
534 {
535         unsigned long flags;
536 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
537         spin_lock_irqsave(&mali_dvfs_spinlock, flags);
538         mali_dvfs_status_current.under_lock = -1;
539         spin_unlock_irqrestore(&mali_dvfs_spinlock, flags);
540 #endif
541         printk(KERN_DEBUG " mali clock Under Lock Unset\n");
542 }
543
544 void kbase_platform_dvfs_set_clock(kbase_device *kbdev, int freq)
545 {
546         struct rk_context *platform;
547
548         if (!kbdev)
549                 panic("oops");
550
551         platform = (struct rk_context *)kbdev->platform_context;
552         if (NULL == platform)
553                 panic("oops");
554
555         if (!platform->mali_clk_node) 
556         {
557                 printk("mali_clk_node not init\n");
558                 return;
559         }
560         mali_dvfs_clk_set(platform->mali_clk_node,freq);
561         
562         return;
563 }
564
565
566 int kbase_platform_dvfs_get_level(int freq)
567 {
568         int i;
569         for (i = 0; i < MALI_DVFS_STEP; i++) {
570                 if (mali_dvfs_infotbl[i].clock == freq)
571                         return i;
572         }
573         return -1;
574 }
575 void kbase_platform_dvfs_set_level(kbase_device *kbdev, int level)
576 {
577         static int prev_level = -1;
578
579         if (level == prev_level)
580                 return;
581
582         if (WARN_ON((level >= MALI_DVFS_STEP) || (level < 0)))
583         {
584                 printk("unkown mali dvfs level:level = %d,set clock not done \n",level);
585                 return  ;
586         }
587         /*panic("invalid level");*/
588 #ifdef CONFIG_MALI_MIDGARD_FREQ_LOCK
589         if (mali_dvfs_status_current.upper_lock >= 0 && level > mali_dvfs_status_current.upper_lock)
590                 level = mali_dvfs_status_current.upper_lock;
591         if (mali_dvfs_status_current.under_lock >= 0 && level < mali_dvfs_status_current.under_lock)
592                 level = mali_dvfs_status_current.under_lock;
593 #endif
594 #ifdef CONFIG_MALI_MIDGARD_DVFS
595         mutex_lock(&mali_set_clock_lock);
596 #endif
597
598         kbase_platform_dvfs_set_clock(kbdev, mali_dvfs_infotbl[level].clock);
599 #if defined(CONFIG_MALI_MIDGARD_DEBUG_SYS) && defined(CONFIG_MALI_MIDGARD_DVFS)
600         update_time_in_state(prev_level);
601 #endif
602         prev_level = level;
603 #ifdef CONFIG_MALI_MIDGARD_DVFS
604         mutex_unlock(&mali_set_clock_lock);
605 #endif
606 }
607
608 #ifdef CONFIG_MALI_MIDGARD_DEBUG_SYS
609 #ifdef CONFIG_MALI_MIDGARD_DVFS
610 static void update_time_in_state(int level)
611 {
612         u64 current_time;
613         static u64 prev_time=0;
614
615         if (level < 0)
616                 return;
617
618         if (!kbase_platform_dvfs_get_enable_status())
619                 return;
620
621         if (prev_time ==0)
622                 prev_time=get_jiffies_64();
623
624         current_time = get_jiffies_64();
625         mali_dvfs_infotbl[level].time += current_time-prev_time;
626
627         prev_time = current_time;
628 }
629 #endif
630
631 ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf)
632 {
633         struct kbase_device *kbdev;
634         ssize_t ret = 0;
635         int i;
636
637         kbdev = dev_get_drvdata(dev);
638
639 #ifdef CONFIG_MALI_MIDGARD_DVFS
640         update_time_in_state(mali_dvfs_status_current.step);
641 #endif
642         if (!kbdev)
643                 return -ENODEV;
644
645         for (i = 0; i < MALI_DVFS_STEP; i++)
646                 ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d %llu\n", mali_dvfs_infotbl[i].clock, mali_dvfs_infotbl[i].time);
647
648         if (ret < PAGE_SIZE - 1)
649                 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
650         else {
651                 buf[PAGE_SIZE - 2] = '\n';
652                 buf[PAGE_SIZE - 1] = '\0';
653                 ret = PAGE_SIZE - 1;
654         }
655
656         return ret;
657 }
658
659 ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
660 {
661         int i;
662
663         for (i = 0; i < MALI_DVFS_STEP; i++)
664                 mali_dvfs_infotbl[i].time = 0;
665
666         printk(KERN_DEBUG "time_in_state value is reset complete.\n");
667         return count;
668 }
669 #endif