1 /* drivers/gpu/mali400/mali/platform/pegasus-m400/exynos4_pmm.c
3 * Copyright 2011 by S.LSI. Samsung Electronics Inc.
4 * San#24, Nongseo-Dong, Giheung-Gu, Yongin, Korea
6 * Samsung SoC Mali400 DVFS driver
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software FoundatIon.
15 * Platform specific Mali driver functions for the exynos 4XXX based platforms
18 #include "mali_kernel_common.h"
20 #include "exynos4_pmm.h"
21 #include <linux/clk.h>
22 #include <linux/err.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
25 #include <linux/regulator/consumer.h>
27 #if defined(CONFIG_MALI400_PROFILING)
28 #include "mali_osk_profiling.h"
31 #if defined(CONFIG_PM_RUNTIME)
36 #include <mach/regs-pmu.h>
37 #include <mach/cpufreq.h>
39 #include <linux/workqueue.h>
41 #define MALI_DVFS_STEPS 5
42 #define MALI_DVFS_WATING 10 /* msec */
43 #define MALI_DVFS_DEFAULT_STEP 1
44 #define PD_G3D_LOCK_FLAG 2
46 #ifdef CONFIG_CPU_FREQ
48 #define EXYNOS4_ASV_ENABLED
51 #define MALI_DVFS_CLK_DEBUG 0
52 #define SEC_THRESHOLD 1
54 #define CPUFREQ_LOCK_DURING_440 1
55 #define CHIPID_REG (S5P_VA_CHIPID + 0x4)
57 static int bMaliDvfsRun = 0;
59 typedef struct mali_dvfs_tableTag{
64 unsigned int downthreshold;
65 unsigned int upthreshold;
69 typedef struct mali_dvfs_statusTag{
70 unsigned int currentStep;
71 mali_dvfs_table * pCurrentDvfs;
76 mali_dvfs_status_t maliDvfsStatus;
77 int mali_dvfs_control;
79 typedef struct mali_runtime_resumeTag{
83 }mali_runtime_resume_table;
85 mali_runtime_resume_table mali_runtime_resume = {266, 900000, 1};
88 mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
89 #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412)
90 /* step 0 */{160 ,1000000 ,875000 , 0 , 70},
91 /* step 1 */{266 ,1000000 ,900000 ,62 , 90},
92 /* step 2 */{350 ,1000000 ,950000 ,85 , 90},
93 /* step 3 */{440 ,1000000 ,1025000 ,85 , 90},
94 /* step 4 */{533 ,1000000 ,1075000 ,95 ,100} };
96 /* step 0 */{134 ,1000000 , 950000 ,85 , 90},
97 /* step 1 */{267 ,1000000 ,1050000 ,85 ,100} };
100 #ifdef EXYNOS4_ASV_ENABLED
101 #define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */
102 #define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */
103 #define ASV_LEVEL_PD 13
106 static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = {
107 { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */
108 #if (MALI_DVFS_STEPS > 1)
109 { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */
110 #if (MALI_DVFS_STEPS > 2)
111 { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */
112 #if (MALI_DVFS_STEPS > 3)
113 { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */
118 static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = {
119 { 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */
120 #if (MALI_DVFS_STEPS > 1)
121 { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */
122 #if (MALI_DVFS_STEPS > 2)
123 { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */
124 #if (MALI_DVFS_STEPS > 3)
125 { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */
131 static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = {
132 { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000, 850000}, /* L4(160Mhz) */
133 #if (MALI_DVFS_STEPS > 1)
134 { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 875000, 875000}, /* L3(266Mhz) */
135 #if (MALI_DVFS_STEPS > 2)
136 { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 912500, 900000, 887500}, /* L2(350Mhz) */
137 #if (MALI_DVFS_STEPS > 3)
138 { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 975000, 962500, 950000}, /* L1(440Mhz) */
139 #if (MALI_DVFS_STEPS > 4)
140 { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1037500, 1025000, 1012500}, /* L0(533Mhz) */
147 static unsigned int asv_3d_volt_4212_9_table[MALI_DVFS_STEPS][ASV_LEVEL_PD] = {
148 { 950000, 925000, 900000, 900000, 900000, 900000, 900000, 900000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */
149 #if (MALI_DVFS_STEPS > 1)
150 { 975000, 950000, 925000, 925000, 925000, 925000, 925000, 900000, 900000, 900000, 875000, 875000, 875000}, /* L2(266Mhz) */
151 #if (MALI_DVFS_STEPS > 2)
152 { 1025000, 1000000, 975000, 975000, 975000, 950000, 950000, 925000, 925000, 925000, 925000, 900000, 875000}, /* L1(350Mhz) */
153 #if (MALI_DVFS_STEPS > 3)
154 { 1100000, 1075000, 1050000, 1050000, 1050000, 1050000, 1025000, 1000000, 1000000, 975000, 975000, 950000, 925000}, /* L0(440Mhz) */
159 #endif /* ASV_LEVEL */
161 #define EXTXTALCLK_NAME "ext_xtal"
162 #define VPLLSRCCLK_NAME "vpll_src"
163 #define FOUTVPLLCLK_NAME "fout_vpll"
164 #define SCLVPLLCLK_NAME "sclk_vpll"
165 #define GPUMOUT1CLK_NAME "mout_g3d1"
167 #define MPLLCLK_NAME "mout_mpll"
168 #define GPUMOUT0CLK_NAME "mout_g3d0"
169 #define GPUCLK_NAME "sclk_g3d"
170 #define CLK_DIV_STAT_G3D 0x1003C62C
171 #define CLK_DESC "clk-divider-status"
173 static struct clk *ext_xtal_clock = NULL;
174 static struct clk *vpll_src_clock = NULL;
175 static struct clk *fout_vpll_clock = NULL;
176 static struct clk *sclk_vpll_clock = NULL;
178 static struct clk *mpll_clock = NULL;
179 static struct clk *mali_parent_clock = NULL;
180 static struct clk *mali_mout0_clock = NULL;
181 static struct clk *mali_clock = NULL;
183 #if defined(CONFIG_CPU_EXYNOS4412) || defined(CONFIG_CPU_EXYNOS4212)
185 static const mali_bool bis_vpll = MALI_TRUE;
186 int mali_gpu_clk = 440;
187 int mali_gpu_vol = 1025000;
190 static const mali_bool bis_vpll = MALI_FALSE;
191 int mali_gpu_clk = 267;
192 int mali_gpu_vol = 1050000;
195 static unsigned int GPU_MHZ = 1000000;
198 static int bPoweroff;
201 #define MAX_MALI_DVFS_STEPS 5
202 static _mali_osk_atomic_t bottomlock_status;
203 int bottom_lock_step = 0;
205 #if MALI_VOLTAGE_LOCK
206 int mali_lock_vol = 0;
207 static _mali_osk_atomic_t voltage_lock_status;
208 static mali_bool mali_vol_lock_flag = 0;
211 /* Declare for sysfs */
212 #ifdef CONFIG_MALI_DVFS
213 module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */
214 MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS");
216 DEVICE_ATTR(time_in_state, S_IRUGO|S_IWUSR, show_time_in_state, set_time_in_state);
217 MODULE_PARM_DESC(time_in_state, "Time-in-state of Mali DVFS");
220 module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */
221 MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock");
223 module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */
224 MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage");
226 module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */
227 MODULE_PARM_DESC(gpu_power_state, "Mali Power State");
229 #ifdef CONFIG_REGULATOR
230 struct regulator *g3d_regulator = NULL;
232 atomic_t mali_cpufreq_lock;
234 mali_io_address clk_register_map = 0;
237 static unsigned int mali_dvfs_utilization = 255;
238 u64 mali_dvfs_time[MALI_DVFS_STEPS];
239 #ifdef CONFIG_MALI_DVFS
240 static void update_time_in_state(int level);
242 static void mali_dvfs_work_handler(struct work_struct *w);
243 static struct workqueue_struct *mali_dvfs_wq = 0;
244 extern mali_io_address clk_register_map;
245 _mali_osk_mutex_t *mali_dvfs_lock;
246 int mali_runtime_resumed = -1;
247 static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler);
249 int cpufreq_lock_by_mali(unsigned int freq)
251 #ifdef CONFIG_EXYNOS4_CPUFREQ
254 if (atomic_read(&mali_cpufreq_lock) == 0) {
255 if (exynos_cpufreq_get_level(freq * 1000, &level)) {
257 "Mali: failed to get cpufreq level for %dMHz",
262 if (exynos_cpufreq_lock(DVFS_LOCK_ID_G3D, level)) {
264 "Mali: failed to cpufreq lock for L%d", level);
268 atomic_set(&mali_cpufreq_lock, 1);
269 printk(KERN_DEBUG "Mali: cpufreq locked on <%d>%dMHz\n", level,
276 void cpufreq_unlock_by_mali(void)
278 #ifdef CONFIG_EXYNOS4_CPUFREQ
279 if (atomic_read(&mali_cpufreq_lock) == 1) {
280 exynos_cpufreq_lock_free(DVFS_LOCK_ID_G3D);
281 atomic_set(&mali_cpufreq_lock, 0);
282 printk(KERN_DEBUG "Mali: cpufreq locked off\n");
287 #ifdef CONFIG_REGULATOR
288 void mali_regulator_disable(void)
290 if(IS_ERR_OR_NULL(g3d_regulator))
292 MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n"));
295 regulator_disable(g3d_regulator);
298 void mali_regulator_enable(void)
300 if(IS_ERR_OR_NULL(g3d_regulator))
302 MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n"));
305 regulator_enable(g3d_regulator);
308 void mali_regulator_set_voltage(int min_uV, int max_uV)
310 _mali_osk_mutex_wait(mali_dvfs_lock);
311 if(IS_ERR_OR_NULL(g3d_regulator))
313 MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n"));
314 _mali_osk_mutex_signal(mali_dvfs_lock);
317 MALI_PRINT(("= regulator_set_voltage: %d, %d \n",min_uV, max_uV));
318 regulator_set_voltage(g3d_regulator, min_uV, max_uV);
319 mali_gpu_vol = regulator_get_voltage(g3d_regulator);
320 MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol));
321 _mali_osk_mutex_signal(mali_dvfs_lock);
325 unsigned long mali_clk_get_rate(void)
327 return clk_get_rate(mali_clock);
331 static unsigned int get_mali_dvfs_status(void)
333 return maliDvfsStatus.currentStep;
336 mali_bool mali_clk_get(void)
340 if (ext_xtal_clock == NULL)
342 ext_xtal_clock = clk_get(NULL, EXTXTALCLK_NAME);
343 if (IS_ERR(ext_xtal_clock)) {
344 MALI_PRINT(("MALI Error : failed to get source ext_xtal_clock\n"));
349 if (vpll_src_clock == NULL)
351 vpll_src_clock = clk_get(NULL, VPLLSRCCLK_NAME);
352 if (IS_ERR(vpll_src_clock)) {
353 MALI_PRINT(("MALI Error : failed to get source vpll_src_clock\n"));
358 if (fout_vpll_clock == NULL)
360 fout_vpll_clock = clk_get(NULL, FOUTVPLLCLK_NAME);
361 if (IS_ERR(fout_vpll_clock)) {
362 MALI_PRINT(("MALI Error : failed to get source fout_vpll_clock\n"));
367 if (sclk_vpll_clock == NULL)
369 sclk_vpll_clock = clk_get(NULL, SCLVPLLCLK_NAME);
370 if (IS_ERR(sclk_vpll_clock)) {
371 MALI_PRINT(("MALI Error : failed to get source sclk_vpll_clock\n"));
376 if (mali_parent_clock == NULL)
378 mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME);
380 if (IS_ERR(mali_parent_clock)) {
381 MALI_PRINT(( "MALI Error : failed to get source mali parent clock\n"));
386 if (mali_mout0_clock == NULL)
388 mali_mout0_clock = clk_get(NULL, GPUMOUT0CLK_NAME);
390 if (IS_ERR(mali_mout0_clock)) {
391 MALI_PRINT( ( "MALI Error : failed to get source mali mout0 clock\n"));
398 if (mpll_clock == NULL)
400 mpll_clock = clk_get(NULL, MPLLCLK_NAME);
402 if (IS_ERR(mpll_clock)) {
403 MALI_PRINT(("MALI Error : failed to get source mpll clock\n"));
408 if (mali_parent_clock == NULL)
410 mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME);
412 if (IS_ERR(mali_parent_clock)) {
413 MALI_PRINT(( "MALI Error : failed to get source mali parent clock\n"));
419 /* mali clock get always. */
420 if (mali_clock == NULL)
422 mali_clock = clk_get(NULL, GPUCLK_NAME);
424 if (IS_ERR(mali_clock)) {
425 MALI_PRINT(("MALI Error : failed to get source mali clock\n"));
433 void mali_clk_put(mali_bool binc_mali_clock)
435 if (mali_parent_clock)
437 clk_put(mali_parent_clock);
438 mali_parent_clock = NULL;
441 if (mali_mout0_clock)
443 clk_put(mali_mout0_clock);
444 mali_mout0_clock = NULL;
455 clk_put(sclk_vpll_clock);
456 sclk_vpll_clock = NULL;
459 if (binc_mali_clock && fout_vpll_clock)
461 clk_put(fout_vpll_clock);
462 fout_vpll_clock = NULL;
467 clk_put(vpll_src_clock);
468 vpll_src_clock = NULL;
473 clk_put(ext_xtal_clock);
474 ext_xtal_clock = NULL;
477 if (binc_mali_clock && mali_clock)
484 void mali_clk_set_rate(unsigned int clk, unsigned int mhz)
487 unsigned long rate = (unsigned long)clk * (unsigned long)mhz;
489 _mali_osk_mutex_wait(mali_dvfs_lock);
490 MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk));
492 if (mali_clk_get() == MALI_FALSE) {
493 _mali_osk_mutex_signal(mali_dvfs_lock);
499 clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ);
500 clk_set_parent(vpll_src_clock, ext_xtal_clock);
501 clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
503 clk_set_parent(mali_parent_clock, sclk_vpll_clock);
504 clk_set_parent(mali_clock, mali_parent_clock);
508 clk_set_parent(mali_parent_clock, mpll_clock);
509 clk_set_parent(mali_clock, mali_parent_clock);
512 if (atomic_read(&clk_active) == 0) {
513 if (clk_enable(mali_clock) < 0) {
514 _mali_osk_mutex_signal(mali_dvfs_lock);
517 atomic_set(&clk_active, 1);
520 err = clk_set_rate(mali_clock, rate);
522 MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err));
524 rate = mali_clk_get_rate();
526 MALI_PRINT(("Mali frequency %d\n", rate / mhz));
528 mali_gpu_clk = (int)(rate / mhz);
530 mali_clk_put(MALI_FALSE);
532 _mali_osk_mutex_signal(mali_dvfs_lock);
535 int get_mali_dvfs_control_status(void)
537 return mali_dvfs_control;
540 mali_bool set_mali_dvfs_current_step(unsigned int step)
542 _mali_osk_mutex_wait(mali_dvfs_lock);
543 maliDvfsStatus.currentStep = step % MALI_DVFS_STEPS;
544 if (step >= MALI_DVFS_STEPS)
545 mali_runtime_resumed = maliDvfsStatus.currentStep;
547 _mali_osk_mutex_signal(mali_dvfs_lock);
552 static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
554 u32 validatedStep=step;
555 #if MALI_DVFS_CLK_DEBUG
556 unsigned int *pRegMaliClkDiv;
557 unsigned int *pRegMaliMpll;
561 #ifdef CONFIG_REGULATOR
562 /* change the voltage */
563 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
565 /* change the clock */
566 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
568 /* change the clock */
569 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
570 #ifdef CONFIG_REGULATOR
571 /* change the voltage */
572 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
576 #if defined(CONFIG_MALI400_PROFILING)
577 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
578 MALI_PROFILING_EVENT_CHANNEL_GPU|
579 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
580 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
582 mali_clk_put(MALI_FALSE);
584 #if MALI_DVFS_CLK_DEBUG
585 pRegMaliClkDiv = ioremap(0x1003c52c,32);
586 pRegMaliMpll = ioremap(0x1003c22c,32);
587 MALI_PRINT(("Mali MPLL reg:%d, CLK DIV: %d \n",*pRegMaliMpll, *pRegMaliClkDiv));
590 #ifdef EXYNOS4_ASV_ENABLED
591 if (samsung_rev() < EXYNOS4412_REV_2_0) {
592 if (mali_dvfs[step].clock == 160)
593 exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
595 exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
599 set_mali_dvfs_current_step(validatedStep);
601 maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep];
603 #if CPUFREQ_LOCK_DURING_440
604 /* lock/unlock CPU freq by Mali */
605 if (mali_dvfs[step].clock >= 440)
606 cpufreq_lock_by_mali(1200);
608 cpufreq_unlock_by_mali();
615 static void mali_platform_wating(u32 msec)
619 * change this in the future with proper check routine.
621 unsigned int read_val;
623 read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00);
624 if ((read_val & 0x8000)==0x0000) break;
626 _mali_osk_time_ubusydelay(100); /* 1000 -> 100 : 20101218 */
630 static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup )
632 MALI_DEBUG_PRINT(4, ("> change_mali_dvfs_status: %d, %d \n",step, boostup));
634 if (!set_mali_dvfs_status(step, boostup)) {
635 MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup));
639 /* wait until clock and voltage is stablized */
640 mali_platform_wating(MALI_DVFS_WATING); /* msec */
645 #ifdef EXYNOS4_ASV_ENABLED
646 extern unsigned int exynos_result_of_asv;
648 static mali_bool mali_dvfs_table_update(void)
650 unsigned int i, tmp, g3d_lock_volt = 0;
651 unsigned int step_num = MALI_DVFS_STEPS;
652 bool lock_flag_g3d = false;
654 if(samsung_rev() < EXYNOS4412_REV_2_0)
655 step_num = MALI_DVFS_STEPS - 1;
657 if(soc_is_exynos4412()) {
658 if (exynos_armclk_max == 1000000) {
659 MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv));
660 for (i = 0; i < step_num; i++) {
661 mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv];
662 MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol));
664 // Update voltage using for resume
665 if (mali_runtime_resume.clk == mali_dvfs[i].clock) {
666 mali_runtime_resume.vol = mali_dvfs[i].vol;
668 MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol));
671 // update voltage using for init timing
672 if (mali_gpu_clk == mali_dvfs[i].clock) {
673 mali_gpu_vol = mali_dvfs[i].vol;
675 MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol));
678 } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) {
679 MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv));
680 for (i = 0; i < step_num; i++) {
681 mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000;
682 MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol));
684 // Update voltage using for resume
685 if (mali_runtime_resume.clk == mali_dvfs[i].clock) {
686 mali_runtime_resume.vol = mali_dvfs[i].vol;
688 MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol));
691 // update voltage using for init timing
692 if (mali_gpu_clk == mali_dvfs[i].clock) {
693 mali_gpu_vol = mali_dvfs[i].vol;
695 MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol));
698 } else if (samsung_rev() >= EXYNOS4412_REV_2_0) {
699 MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv));
700 for (i = 0; i < step_num; i++) {
701 mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv];
702 MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol));
704 // Update voltage using for resume
705 if (mali_runtime_resume.clk == mali_dvfs[i].clock) {
706 mali_runtime_resume.vol = mali_dvfs[i].vol;
708 MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol));
711 // update voltage using for init timing
712 if (mali_gpu_clk == mali_dvfs[i].clock) {
713 mali_gpu_vol = mali_dvfs[i].vol;
715 MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol));
719 MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv));
720 for (i = 0; i < step_num; i++) {
721 mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv];
722 MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol));
724 // Update voltage using for resume
725 if (mali_runtime_resume.clk == mali_dvfs[i].clock) {
726 mali_runtime_resume.vol = mali_dvfs[i].vol;
728 MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol));
731 // update voltage using for init timing
732 if (mali_gpu_clk == mali_dvfs[i].clock) {
733 mali_gpu_vol = mali_dvfs[i].vol;
735 MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol));
740 else if(soc_is_exynos4212()) {
741 tmp = __raw_readl(CHIPID_REG);
742 lock_flag_g3d = (tmp >> PD_G3D_LOCK_FLAG) & 0x1;
744 g3d_lock_volt = 25000;
746 for (i = 0; i < step_num; i++) {
747 MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
748 mali_dvfs[i].vol = asv_3d_volt_4212_9_table[i][exynos_result_of_asv] + g3d_lock_volt;
749 MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol));
751 // Update voltage using for resume
752 if (mali_runtime_resume.clk == mali_dvfs[i].clock) {
753 mali_runtime_resume.vol = mali_dvfs[i].vol;
755 MALI_PRINT(("mali_runtime_resume.vol = %d \n", mali_runtime_resume.vol));
758 // update voltage using for init timing
759 if (mali_gpu_clk == mali_dvfs[i].clock) {
760 mali_gpu_vol = mali_dvfs[i].vol;
762 MALI_PRINT(("init_gpu_vol = %d \n", mali_gpu_vol));
771 static unsigned int decideNextStatus(unsigned int utilization)
773 static unsigned int level = 0;
775 if (mali_runtime_resumed >= 0) {
776 level = mali_runtime_resumed;
777 mali_runtime_resumed = -1;
780 if (mali_dvfs_control == 0 && level == get_mali_dvfs_status()) {
781 if (utilization > (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].upthreshold / 100) &&
782 level < MALI_DVFS_STEPS - 1) {
784 if ((samsung_rev() < EXYNOS4412_REV_2_0) && 3 == get_mali_dvfs_status()) {
785 level=get_mali_dvfs_status();
788 else if (utilization < (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].downthreshold / 100) &&
793 if (_mali_osk_atomic_read(&bottomlock_status) > 0) {
794 if (level < bottom_lock_step)
795 level = bottom_lock_step;
798 for (iStepCount = MALI_DVFS_STEPS-1; iStepCount >= 0; iStepCount--) {
799 if ( mali_dvfs_control >= mali_dvfs[iStepCount].clock ) {
810 static mali_bool mali_dvfs_status(unsigned int utilization)
812 unsigned int nextStatus = 0;
813 unsigned int curStatus = 0;
814 mali_bool boostup = MALI_FALSE;
815 static int stay_count = 5;
817 MALI_DEBUG_PRINT(4, ("> mali_dvfs_status: %d \n",utilization));
819 /* decide next step */
820 curStatus = get_mali_dvfs_status();
821 nextStatus = decideNextStatus(utilization);
823 MALI_DEBUG_PRINT(4, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep));
824 /* if next status is same with current status, don't change anything */
825 if(curStatus != nextStatus) {
826 /*check if boost up or not*/
827 if(maliDvfsStatus.currentStep < nextStatus) {
830 } else if (maliDvfsStatus.currentStep > nextStatus){
833 if( boostup == 1 || stay_count <= 0){
834 /*change mali dvfs status*/
835 #ifdef CONFIG_MALI_DVFS
836 update_time_in_state(curStatus);
838 if (!change_mali_dvfs_status(nextStatus,boostup)) {
839 MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n"));
852 int mali_dvfs_is_running(void)
858 static void mali_dvfs_work_handler(struct work_struct *w)
862 MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
864 if(!mali_dvfs_status(mali_dvfs_utilization))
865 MALI_DEBUG_PRINT(1, ( "error on mali dvfs status in mali_dvfs_work_handler"));
870 mali_bool init_mali_dvfs_status(void)
874 * add here with the right function to get initilization value.
878 mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
880 _mali_osk_atomic_init(&bottomlock_status, 0);
882 /* add a error handling here */
883 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
888 void deinit_mali_dvfs_status(void)
891 destroy_workqueue(mali_dvfs_wq);
893 _mali_osk_atomic_term(&bottomlock_status);
898 mali_bool mali_dvfs_handler(unsigned int utilization)
900 mali_dvfs_utilization = utilization;
901 queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
906 static mali_bool init_mali_clock(void)
908 mali_bool ret = MALI_TRUE;
913 return ret; /* already initialized */
915 mali_dvfs_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, 0);
916 if (mali_dvfs_lock == NULL)
917 return _MALI_OSK_ERR_FAULT;
921 MALI_PRINT(("Error: Failed to get Mali clock\n"));
925 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
927 MALI_PRINT(("init_mali_clock mali_clock %x\n", mali_clock));
929 #ifdef CONFIG_REGULATOR
930 g3d_regulator = regulator_get(NULL, "vdd_g3d");
932 if (IS_ERR(g3d_regulator))
934 MALI_PRINT(("MALI Error : failed to get vdd_g3d\n"));
939 regulator_enable(g3d_regulator);
940 mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol);
942 #ifdef EXYNOS4_ASV_ENABLED
943 if (samsung_rev() < EXYNOS4412_REV_2_0) {
944 if (mali_gpu_clk == 160)
945 exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
947 exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
952 #if defined(CONFIG_MALI400_PROFILING)
953 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
954 MALI_PROFILING_EVENT_CHANNEL_GPU|
955 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
956 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
959 mali_clk_put(MALI_FALSE);
963 #ifdef CONFIG_REGULATOR
965 regulator_put(g3d_regulator);
968 mali_clk_put(MALI_TRUE);
973 static mali_bool deinit_mali_clock(void)
978 #ifdef CONFIG_REGULATOR
981 regulator_put(g3d_regulator);
982 g3d_regulator = NULL;
986 mali_clk_put(MALI_TRUE);
992 static _mali_osk_errcode_t enable_mali_clocks(void)
996 if (atomic_read(&clk_active) == 0) {
997 err = clk_enable(mali_clock);
998 MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err));
999 atomic_set(&clk_active, 1);
1000 gpu_power_state = 1;
1003 /* set clock rate */
1004 #ifdef CONFIG_MALI_DVFS
1005 if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) {
1006 mali_clk_set_rate(mali_gpu_clk, GPU_MHZ);
1008 #ifdef CONFIG_REGULATOR
1009 mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol);
1011 #ifdef EXYNOS4_ASV_ENABLED
1012 if (samsung_rev() < EXYNOS4412_REV_2_0) {
1013 if (mali_runtime_resume.clk == 160)
1014 exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
1016 exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
1020 mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ);
1021 set_mali_dvfs_current_step(mali_runtime_resume.step);
1024 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
1025 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
1032 static _mali_osk_errcode_t disable_mali_clocks(void)
1034 if (atomic_read(&clk_active) == 1) {
1035 clk_disable(mali_clock);
1036 atomic_set(&clk_active, 0);
1037 gpu_power_state = 0;
1039 MALI_DEBUG_PRINT(3, ("disable_mali_clocks mali_clock %p \n", mali_clock));
1044 /* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */
1045 #ifndef S5P_G3D_CONFIGURATION
1046 #define S5P_G3D_CONFIGURATION S5P_PMU_G3D_CONF
1048 #ifndef S5P_G3D_STATUS
1049 #define S5P_G3D_STATUS S5P_PMU_G3D_CONF + 0x4
1052 _mali_osk_errcode_t g3d_power_domain_control(int bpower_on)
1056 void __iomem *status;
1058 __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_G3D_CONFIGURATION);
1059 status = S5P_G3D_STATUS;
1062 while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN)
1063 != S5P_INT_LOCAL_PWR_EN) {
1065 MALI_PRINTF(("Power domain enable failed.\n"));
1069 _mali_osk_time_ubusydelay(100);
1074 void __iomem *status;
1076 __raw_writel(0, S5P_G3D_CONFIGURATION);
1078 status = S5P_G3D_STATUS;
1081 while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN)
1084 MALI_PRINTF(("Power domain disable failed.\n" ));
1088 _mali_osk_time_ubusydelay(100);
1095 _mali_osk_errcode_t mali_platform_init(struct device *dev)
1097 #ifdef EXYNOS4_ASV_ENABLED
1098 mali_dvfs_table_update();
1101 MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT);
1103 atomic_set(&clk_active, 0);
1105 #ifdef CONFIG_MALI_DVFS
1106 /* Create sysfs for time-in-state */
1107 if (device_create_file(dev, &dev_attr_time_in_state)) {
1108 dev_err(dev, "Couldn't create sysfs file [time_in_state]\n");
1111 if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC );
1112 if (!init_mali_dvfs_status())
1113 MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n"));
1116 mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON);
1121 _mali_osk_errcode_t mali_platform_deinit(struct device *dev)
1124 mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP);
1125 deinit_mali_clock();
1127 #ifdef CONFIG_MALI_DVFS
1128 deinit_mali_dvfs_status();
1129 if (clk_register_map )
1131 _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map);
1132 clk_register_map = NULL;
1139 _mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode)
1143 case MALI_POWER_MODE_ON:
1144 MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n",
1145 bPoweroff ? "powering on" : "already on"));
1148 #if !defined(CONFIG_PM_RUNTIME)
1149 g3d_power_domain_control(1);
1151 MALI_DEBUG_PRINT(4, ("enable clock \n"));
1152 enable_mali_clocks();
1153 #if defined(CONFIG_MALI400_PROFILING)
1154 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
1155 MALI_PROFILING_EVENT_CHANNEL_GPU |
1156 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
1157 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
1163 case MALI_POWER_MODE_LIGHT_SLEEP:
1164 case MALI_POWER_MODE_DEEP_SLEEP:
1165 MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode ==
1166 MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" :
1167 "MALI_POWER_MODE_DEEP_SLEEP", bPoweroff ? "already off" : "powering off"));
1170 disable_mali_clocks();
1171 #if defined(CONFIG_MALI400_PROFILING)
1172 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
1173 MALI_PROFILING_EVENT_CHANNEL_GPU |
1174 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
1178 #if !defined(CONFIG_PM_RUNTIME)
1179 g3d_power_domain_control(0);
1189 void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data)
1193 #ifdef CONFIG_MALI_DVFS
1194 if(!mali_dvfs_handler(data->utilization_gpu))
1195 MALI_DEBUG_PRINT(1, ("error on mali dvfs status in utilization\n"));
1200 int mali_dvfs_bottom_lock_push(int lock_step)
1202 int prev_status = _mali_osk_atomic_read(&bottomlock_status);
1204 if (prev_status < 0) {
1205 MALI_PRINT(("gpu bottom lock status is not valid for push\n"));
1208 if (bottom_lock_step < lock_step) {
1209 bottom_lock_step = lock_step;
1210 if (get_mali_dvfs_status() < lock_step) {
1211 mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol);
1212 mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq);
1213 set_mali_dvfs_current_step(lock_step);
1216 return _mali_osk_atomic_inc_return(&bottomlock_status);
1219 int mali_dvfs_bottom_lock_pop(void)
1221 int prev_status = _mali_osk_atomic_read(&bottomlock_status);
1222 if (prev_status <= 0) {
1223 MALI_PRINT(("gpu bottom lock status is not valid for pop\n"));
1225 } else if (prev_status >= 1) {
1226 bottom_lock_step = 0;
1227 MALI_PRINT(("gpu bottom lock release\n"));
1230 return _mali_osk_atomic_dec_return(&bottomlock_status);
1233 int mali_dvfs_get_vol(int step)
1235 step = step % MAX_MALI_DVFS_STEPS;
1236 MALI_DEBUG_ASSERT(step<MAX_MALI_DVFS_STEPS);
1237 return mali_dvfs[step].vol;
1240 #if MALI_VOLTAGE_LOCK
1241 int mali_voltage_lock_push(int lock_vol)
1243 int prev_status = _mali_osk_atomic_read(&voltage_lock_status);
1245 if (prev_status < 0) {
1246 MALI_PRINT(("gpu voltage lock status is not valid for push\n"));
1249 if (prev_status == 0) {
1250 mali_lock_vol = lock_vol;
1251 if (mali_gpu_vol < mali_lock_vol)
1252 mali_regulator_set_voltage(mali_lock_vol, mali_lock_vol);
1254 MALI_PRINT(("gpu voltage lock status is already pushed, current lock voltage : %d\n", mali_lock_vol));
1258 return _mali_osk_atomic_inc_return(&voltage_lock_status);
1261 int mali_voltage_lock_pop(void)
1263 if (_mali_osk_atomic_read(&voltage_lock_status) <= 0) {
1264 MALI_PRINT(("gpu voltage lock status is not valid for pop\n"));
1267 return _mali_osk_atomic_dec_return(&voltage_lock_status);
1270 int mali_voltage_lock_init(void)
1272 mali_vol_lock_flag = MALI_TRUE;
1277 int mali_vol_get_from_table(int vol)
1280 for (i = 0; i < MALI_DVFS_STEPS; i++) {
1281 if (mali_dvfs[i].vol >= vol)
1282 return mali_dvfs[i].vol;
1284 MALI_PRINT(("Failed to get voltage from mali_dvfs table, maximum voltage is %d uV\n", mali_dvfs[MALI_DVFS_STEPS-1].vol));
1289 #ifdef CONFIG_MALI_DVFS
1290 static void update_time_in_state(int level)
1293 static u64 prev_time=0;
1296 prev_time=get_jiffies_64();
1298 current_time = get_jiffies_64();
1299 mali_dvfs_time[level] += current_time-prev_time;
1300 prev_time = current_time;
1303 ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf)
1308 update_time_in_state(maliDvfsStatus.currentStep);
1310 for (i = 0; i < MALI_DVFS_STEPS; i++) {
1311 ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d %llu\n",
1316 if (ret < PAGE_SIZE - 1) {
1317 ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
1319 buf[PAGE_SIZE-2] = '\n';
1320 buf[PAGE_SIZE-1] = '\0';
1327 ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1331 for (i = 0; i < MALI_DVFS_STEPS; i++) {
1332 mali_dvfs_time[i] = 0;