1 /* drivers/gpu/mali400/mali/platform/exynos3470/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
17 #include "mali_kernel_common.h"
19 #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 /* lock/unlock CPU freq by Mali */
32 #include <linux/types.h>
33 #include <mach/cpufreq.h>
34 #include <mach/regs-clock.h>
35 #include <mach/asv-exynos.h>
36 #ifdef CONFIG_CPU_FREQ
37 #define EXYNOS4_ASV_ENABLED
40 /* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */
41 #ifndef S5P_G3D_CONFIGURATION
42 #define S5P_G3D_CONFIGURATION EXYNOS4_G3D_CONFIGURATION
44 #ifndef S5P_G3D_STATUS
45 #define S5P_G3D_STATUS (EXYNOS4_G3D_CONFIGURATION + 0x4)
47 #ifndef S5P_INT_LOCAL_PWR_EN
48 #define S5P_INT_LOCAL_PWR_EN EXYNOS_INT_LOCAL_PWR_EN
52 #include <mach/regs-pmu.h>
53 #include <linux/workqueue.h>
55 #define MALI_DVFS_STEPS 4
56 #define MALI_DVFS_WATING 10 /* msec */
57 #define MALI_DVFS_DEFAULT_STEP 1
59 #define MALI_DVFS_CLK_DEBUG 0
60 #define CPUFREQ_LOCK_DURING_440 1
62 static int bMaliDvfsRun = 0;
64 typedef struct mali_dvfs_tableTag{
68 unsigned int downthreshold;
69 unsigned int upthreshold;
72 typedef struct mali_dvfs_statusTag{
73 unsigned int currentStep;
74 mali_dvfs_table * pCurrentDvfs;
79 mali_dvfs_status_t maliDvfsStatus;
80 int mali_dvfs_control;
81 static _mali_osk_atomic_t dvfslock_status;
83 typedef struct mali_runtime_resumeTag{
87 }mali_runtime_resume_table;
89 mali_runtime_resume_table mali_runtime_resume = {266, 850000, 1};
91 /*dvfs table updated on 130520*/
92 mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS + 1]={
93 /*step 0*/{160, 1000000, 850000, 0, 70},
94 /*step 1*/{266, 1000000, 850000, 62, 90},
95 /*step 2*/{340, 1000000, 875000, 85, 90},
96 /*step 3*/{440, 1000000, 925000, 85, 100},
97 /*step 4*/{450, 1000000, 925000, 100, 100} };
100 int mali_gpu_clk = 266;
101 int mali_gpu_vol = 850000;
102 unsigned int mali_vpll_clk = 900;
103 char *mali_freq_table = "440 340 266 160";
104 #define EXTXTALCLK_NAME "ext_xtal"
105 #define VPLLSRCCLK_NAME "vpll_src"
106 #define FOUTVPLLCLK_NAME "fout_vpll"
107 #define MOUTEPLLCLK_NAME "mout_epll"
108 #define SCLVPLLCLK_NAME "sclk_vpll"
109 #define GPUMOUT1CLK_NAME "mout_g3d1"
110 #define GPUMOUT0CLK_NAME "mout_g3d0"
111 #define GPUCLK_NAME "sclk_g3d"
112 #define CLK_DIV_STAT_G3D 0x1003C62C
113 #define CLK_DESC "clk-divider-status"
114 #define ISP_LOCK_STEP 4
116 static struct clk *ext_xtal_clock = NULL;
117 static struct clk *vpll_src_clock = NULL;
118 static struct clk *fout_vpll_clock = NULL;
119 static struct clk *mout_epll_clock = NULL;
120 static struct clk *sclk_vpll_clock = NULL;
121 static struct clk *mali_parent_clock = NULL;
122 static struct clk *mali_clock = NULL;
124 static unsigned int GPU_MHZ = 1000000;
125 static unsigned int const GPU_ASV_VOLT = 1000;
126 static int nPowermode;
127 static atomic_t clk_active;
129 mali_io_address clk_register_map = 0;
131 /* export GPU frequency as a read-only parameter so that it can be read in /sys */
132 module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH);
133 module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH);
134 module_param(mali_freq_table, charp, S_IRUSR | S_IRGRP | S_IROTH);
135 #ifdef CONFIG_MALI_DVFS
136 module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */
137 MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS");
138 DEVICE_ATTR(time_in_state, S_IRUGO|S_IWUSR, show_time_in_state, set_time_in_state);
139 MODULE_PARM_DESC(time_in_state, "Time-in-state of Mali DVFS");
141 MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock");
142 MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage");
143 MODULE_PARM_DESC(mali_freq_table, "Mali frequency table");
145 #ifdef CONFIG_REGULATOR
146 struct regulator *g3d_regulator = NULL;
148 atomic_t mali_cpufreq_lock;
151 #ifdef CONFIG_MALI_DVFS
152 static unsigned int mali_dvfs_utilization = 255;
153 static void update_time_in_state(int level);
154 u64 mali_dvfs_time[MALI_DVFS_STEPS];
157 static void mali_dvfs_work_handler(struct work_struct *w);
158 static struct workqueue_struct *mali_dvfs_wq = 0;
159 _mali_osk_mutex_t *mali_dvfs_lock;
160 _mali_osk_mutex_t *mali_isp_lock;
161 int mali_runtime_resumed = -1;
162 static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler);
164 int cpufreq_lock_by_mali(unsigned int freq)
166 #ifdef CONFIG_EXYNOS4_CPUFREQ
169 if (atomic_read(&mali_cpufreq_lock) == 0) {
170 if (exynos_cpufreq_get_level(freq * 1000, &level)) {
171 printk(KERN_ERR "Mali: failed to get cpufreq level for %dMHz", freq);
175 if (exynos_cpufreq_lock(DVFS_LOCK_ID_G3D, level)) {
176 printk(KERN_ERR "Mali: failed to cpufreq lock for L%d", level);
180 atomic_set(&mali_cpufreq_lock, 1);
181 printk(KERN_DEBUG "Mali: cpufreq locked on <%d>%dMHz\n", level, freq);
187 void cpufreq_unlock_by_mali(void)
189 #ifdef CONFIG_EXYNOS4_CPUFREQ
190 if (atomic_read(&mali_cpufreq_lock) == 1) {
191 exynos_cpufreq_lock_free(DVFS_LOCK_ID_G3D);
192 atomic_set(&mali_cpufreq_lock, 0);
193 printk(KERN_DEBUG "Mali: cpufreq locked off\n");
198 #ifdef CONFIG_REGULATOR
199 void mali_regulator_disable(void)
201 if(IS_ERR_OR_NULL(g3d_regulator))
203 MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n"));
206 regulator_disable(g3d_regulator);
209 void mali_regulator_enable(void)
211 if(IS_ERR_OR_NULL(g3d_regulator))
213 MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n"));
216 regulator_enable(g3d_regulator);
219 void mali_regulator_set_voltage(int min_uV, int max_uV)
221 _mali_osk_mutex_wait(mali_dvfs_lock);
222 if(IS_ERR_OR_NULL(g3d_regulator))
224 MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n"));
225 _mali_osk_mutex_signal(mali_dvfs_lock);
228 MALI_DEBUG_PRINT(1, ("= regulator_set_voltage: %d, %d \n", min_uV, max_uV));
229 regulator_set_voltage(g3d_regulator, min_uV, max_uV);
230 mali_gpu_vol = regulator_get_voltage(g3d_regulator);
231 MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol));
232 _mali_osk_mutex_signal(mali_dvfs_lock);
236 #ifdef CONFIG_MALI_DVFS
237 static unsigned int get_mali_dvfs_status(void)
239 return maliDvfsStatus.currentStep;
243 mali_bool mali_clk_get(void)
245 if (ext_xtal_clock == NULL) {
246 ext_xtal_clock = clk_get(NULL, EXTXTALCLK_NAME);
247 if (IS_ERR(ext_xtal_clock)) {
248 MALI_PRINT(("MALI Error : failed to get source ext_xtal_clock\n"));
253 if (vpll_src_clock == NULL) {
254 vpll_src_clock = clk_get(NULL, VPLLSRCCLK_NAME);
255 if (IS_ERR(vpll_src_clock)) {
256 MALI_PRINT(("MALI Error : failed to get source vpll_src_clock\n"));
261 if (fout_vpll_clock == NULL) {
262 fout_vpll_clock = clk_get(NULL, FOUTVPLLCLK_NAME);
263 if (IS_ERR(fout_vpll_clock)) {
264 MALI_PRINT(("MALI Error : failed to get source fout_vpll_clock\n"));
269 if (mout_epll_clock == NULL) {
270 mout_epll_clock = clk_get(NULL, MOUTEPLLCLK_NAME);
271 if (IS_ERR(mout_epll_clock)) {
272 MALI_PRINT(("MALI Error : failed to get source mout_epll_clock\n"));
277 if (sclk_vpll_clock == NULL) {
278 sclk_vpll_clock = clk_get(NULL, SCLVPLLCLK_NAME);
279 if (IS_ERR(sclk_vpll_clock)) {
280 MALI_PRINT(("MALI Error : failed to get source sclk_vpll_clock\n"));
285 if (mali_parent_clock == NULL) {
286 mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME);
287 if (IS_ERR(mali_parent_clock)) {
288 MALI_PRINT(("MALI Error : failed to get source mali parent clock\n"));
293 /* mali clock get always. */
294 if (mali_clock == NULL) {
295 mali_clock = clk_get(NULL, GPUCLK_NAME);
296 if (IS_ERR(mali_clock)) {
297 MALI_PRINT(("MALI Error : failed to get source mali clock\n"));
305 void mali_clk_put(mali_bool binc_mali_clock)
307 if (mali_parent_clock)
309 clk_put(mali_parent_clock);
310 mali_parent_clock = NULL;
315 clk_put(sclk_vpll_clock);
316 sclk_vpll_clock = NULL;
319 if (binc_mali_clock && fout_vpll_clock)
321 clk_put(fout_vpll_clock);
322 fout_vpll_clock = NULL;
327 clk_put(mout_epll_clock);
328 mout_epll_clock = NULL;
333 clk_put(vpll_src_clock);
334 vpll_src_clock = NULL;
339 clk_put(ext_xtal_clock);
340 ext_xtal_clock = NULL;
343 if (binc_mali_clock && mali_clock)
350 void mali_clk_set_rate(unsigned int clk, unsigned int mhz)
353 unsigned int read_val;
354 unsigned long rate = (unsigned long)clk * (unsigned long)mhz;
356 _mali_osk_mutex_wait(mali_dvfs_lock);
358 MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk));
360 if (mali_clk_get() == MALI_FALSE) {
361 _mali_osk_mutex_signal(mali_dvfs_lock);
364 clk_set_parent(mali_parent_clock, mout_epll_clock);
368 read_val = __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0);
369 } while (((read_val >> 4) & 0x7) != 0x1);
371 MALI_DEBUG_PRINT(3, ("Mali platform: set to EPLL EXYNOS4_CLKMUX_STAT_G3D0 : 0x%08x\n", __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0)));
373 err = clk_set_parent(sclk_vpll_clock, ext_xtal_clock);
376 MALI_PRINT_ERROR(("sclk_vpll set parent to ext_xtal failed\n"));
378 MALI_DEBUG_PRINT(3, ("Mali platform: set_parent_vpll : %8.x \n", (__raw_readl(EXYNOS4_CLKSRC_TOP0) >> 8) & 0x1));
380 clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ);
381 clk_set_parent(vpll_src_clock, ext_xtal_clock);
383 err = clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
386 MALI_PRINT_ERROR(("sclk_vpll set parent to fout_vpll failed\n"));
388 MALI_DEBUG_PRINT(3, ("Mali platform: set_parent_vpll : %8.x \n", (__raw_readl(EXYNOS4_CLKSRC_TOP0) >> 8) & 0x1));
390 clk_set_parent(mali_parent_clock, sclk_vpll_clock);
394 read_val = __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0);
395 } while (((read_val >> 4) & 0x7) != 0x2);
397 MALI_DEBUG_PRINT(3, ("SET to VPLL EXYNOS4_CLKMUX_STAT_G3D0 : 0x%08x\n", __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0)));
399 clk_set_parent(mali_clock, mali_parent_clock);
401 if (atomic_read(&clk_active) == 0) {
402 if (clk_enable(mali_clock) < 0) {
403 _mali_osk_mutex_signal(mali_dvfs_lock);
406 atomic_set(&clk_active, 1);
409 err = clk_set_rate(mali_clock, rate);
412 MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err));
414 rate = clk_get_rate(mali_clock);
416 MALI_DEBUG_PRINT(1, ("Mali frequency %d\n", rate / mhz));
419 mali_gpu_clk = (int)(rate / mhz);
420 mali_clk_put(MALI_FALSE);
422 _mali_osk_mutex_signal(mali_dvfs_lock);
425 #ifdef CONFIG_MALI_DVFS
426 mali_bool set_mali_dvfs_current_step(unsigned int step)
428 _mali_osk_mutex_wait(mali_dvfs_lock);
429 maliDvfsStatus.currentStep = step % MALI_DVFS_STEPS;
430 _mali_osk_mutex_signal(mali_dvfs_lock);
434 static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
436 #if MALI_DVFS_CLK_DEBUG
437 unsigned int *pRegMaliClkDiv;
438 unsigned int *pRegMaliMpll;
441 _mali_osk_mutex_wait(mali_isp_lock);
443 if (mali_dvfs_control == mali_dvfs[ISP_LOCK_STEP].clock) {
444 MALI_DEBUG_PRINT(1, ("DVFS is already locked by ISP\n"));
445 _mali_osk_mutex_signal(mali_isp_lock);
447 } else if (step == ISP_LOCK_STEP) {
448 step = mali_runtime_resume.step;
452 #ifdef CONFIG_REGULATOR
453 /*change the voltage*/
454 #ifdef EXYNOS4_ASV_ENABLED
455 mali_regulator_set_voltage(get_match_volt(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT), get_match_volt(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT));
456 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT));
458 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
462 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
465 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
466 #ifdef CONFIG_REGULATOR
467 #ifdef EXYNOS4_ASV_ENABLED
468 /*change the voltage*/
469 mali_regulator_set_voltage(get_match_volt(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT), get_match_volt(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT));
470 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT));
472 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
477 #if defined(CONFIG_MALI400_PROFILING)
478 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
479 MALI_PROFILING_EVENT_CHANNEL_GPU|
480 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
481 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
483 mali_clk_put(MALI_FALSE);
485 #if MALI_DVFS_CLK_DEBUG
486 pRegMaliClkDiv = ioremap(0x1003c52c, 32);
487 pRegMaliMpll = ioremap(0x1003c22c, 32);
488 MALI_PRINT(("Mali MPLL reg:%d, CLK DIV: %d \n", *pRegMaliMpll, *pRegMaliClkDiv));
490 set_mali_dvfs_current_step(step);
492 maliDvfsStatus.pCurrentDvfs = &mali_dvfs[step];
494 #if CPUFREQ_LOCK_DURING_440
495 /* lock/unlock CPU freq by Mali */
496 if (mali_dvfs[step].clock >= 440)
497 cpufreq_lock_by_mali(400);
499 cpufreq_unlock_by_mali();
501 _mali_osk_mutex_signal(mali_isp_lock);
505 static void mali_platform_wating(u32 msec)
509 * change this in the future with proper check routine.
511 unsigned int read_val;
513 read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00);
514 if ((read_val & 0x8000)==0x0000) break;
516 _mali_osk_time_ubusydelay(100); /* 1000 -> 100 : 20101218 */
520 static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup )
522 MALI_DEBUG_PRINT(4, ("> change_mali_dvfs_status: %d, %d \n", step, boostup));
524 if (!set_mali_dvfs_status(step, boostup)) {
525 MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup));
529 /* wait until clock and voltage is stablized */
530 mali_platform_wating(MALI_DVFS_WATING); /* msec */
534 static unsigned int decideNextStatus(unsigned int utilization)
536 static unsigned int level = 0;
539 if (mali_runtime_resumed >= 0) {
540 level = mali_runtime_resumed;
541 mali_runtime_resumed = -1;
544 if (mali_dvfs_control == 0) {
545 if (utilization > (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].upthreshold / 100) &&
546 level < MALI_DVFS_STEPS - 1) {
548 } else if (utilization < (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].downthreshold / 100) &&
552 } else if (mali_dvfs_control == mali_dvfs[ISP_LOCK_STEP].clock) {
553 level = ISP_LOCK_STEP;
555 for (iStepCount = MALI_DVFS_STEPS - 1; iStepCount >= 0; iStepCount--) {
556 if (mali_dvfs_control >= mali_dvfs[iStepCount].clock) {
566 static mali_bool mali_dvfs_status(unsigned int utilization)
568 unsigned int nextStatus = 0;
569 unsigned int curStatus = 0;
570 mali_bool boostup = MALI_FALSE;
571 static int stay_count = 5;
573 MALI_DEBUG_PRINT(4, ("> mali_dvfs_status: %d \n", utilization));
575 /* decide next step */
576 curStatus = get_mali_dvfs_status();
577 nextStatus = decideNextStatus(utilization);
579 MALI_DEBUG_PRINT(4, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep));
580 /* if next status is same with current status, don't change anything */
581 if(curStatus != nextStatus) {
582 /*check if boost up or not*/
583 if(maliDvfsStatus.currentStep < nextStatus) {
586 } else if (maliDvfsStatus.currentStep > nextStatus){
590 if( boostup == 1 || stay_count <= 0){
591 /*change mali dvfs status*/
592 update_time_in_state(curStatus);
593 if (!change_mali_dvfs_status(nextStatus, boostup)) {
594 MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n"));
608 static void mali_dvfs_work_handler(struct work_struct *w)
611 MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
613 #ifdef CONFIG_MALI_DVFS
614 if(!mali_dvfs_status(mali_dvfs_utilization))
615 MALI_DEBUG_PRINT(1, ( "error on mali dvfs status in mali_dvfs_work_handler"));
621 mali_bool init_mali_dvfs_status(void)
625 * add here with the right function to get initilization value.
628 mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
630 _mali_osk_atomic_init(&dvfslock_status, 0);
632 /* add a error handling here */
633 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
638 void deinit_mali_dvfs_status(void)
641 destroy_workqueue(mali_dvfs_wq);
643 _mali_osk_atomic_term(&dvfslock_status);
648 #ifdef CONFIG_MALI_DVFS
649 mali_bool mali_dvfs_handler(unsigned int utilization)
651 mali_dvfs_utilization = utilization;
652 queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
658 static mali_bool init_mali_clock(void)
660 mali_bool ret = MALI_TRUE;
661 nPowermode = MALI_POWER_MODE_DEEP_SLEEP;
664 return ret; /* already initialized */
666 mali_dvfs_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, 0);
667 mali_isp_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, 0);
669 if (mali_dvfs_lock == NULL || mali_isp_lock == NULL)
670 return _MALI_OSK_ERR_FAULT;
674 MALI_PRINT(("Error: Failed to get Mali clock\n"));
678 clk_set_parent(vpll_src_clock, ext_xtal_clock);
679 clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
680 clk_set_parent(mali_parent_clock, sclk_vpll_clock);
681 clk_set_parent(mali_clock, mali_parent_clock);
683 if (!atomic_read(&clk_active)) {
684 if (clk_enable(mali_clock) < 0) {
685 MALI_PRINT(("Error: Failed to enable clock\n"));
688 atomic_set(&clk_active, 1);
691 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
693 MALI_PRINT(("init_mali_clock mali_clock %x\n", mali_clock));
695 #ifdef CONFIG_REGULATOR
696 g3d_regulator = regulator_get(NULL, "vdd_g3d");
698 if (IS_ERR(g3d_regulator))
700 MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n"));
705 mali_gpu_vol = mali_runtime_resume.vol;
706 #ifdef EXYNOS4_ASV_ENABLED
707 mali_gpu_vol = get_match_volt(ID_G3D, mali_gpu_clk * GPU_ASV_VOLT);
708 mali_runtime_resume.vol = get_match_volt(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT);
711 regulator_enable(g3d_regulator);
712 mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol);
714 #ifdef EXYNOS4_ASV_ENABLED
715 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT));
719 #if defined(CONFIG_MALI400_PROFILING)
720 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
721 MALI_PROFILING_EVENT_CHANNEL_GPU|
722 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
723 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
725 mali_clk_put(MALI_FALSE);
729 #ifdef CONFIG_REGULATOR
731 regulator_put(g3d_regulator);
734 mali_clk_put(MALI_TRUE);
739 static mali_bool deinit_mali_clock(void)
744 #ifdef CONFIG_REGULATOR
747 regulator_put(g3d_regulator);
748 g3d_regulator = NULL;
751 mali_clk_put(MALI_TRUE);
756 static _mali_osk_errcode_t enable_mali_clocks(void)
760 if (atomic_read(&clk_active) == 0) {
761 err = clk_enable(mali_clock);
762 MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err));
763 atomic_set(&clk_active, 1);
766 _mali_osk_mutex_wait(mali_isp_lock);
768 if (mali_dvfs_control == mali_dvfs[ISP_LOCK_STEP].clock) {
769 MALI_DEBUG_PRINT(1, ("DVFS is already locked by ISP\n"));
771 #ifdef EXYNOS4_ASV_ENABLED
772 if (samsung_rev() == EXYNOS3470_REV_2_0)
773 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_dvfs[ISP_LOCK_STEP].clock * GPU_ASV_VOLT));
775 _mali_osk_mutex_signal(mali_isp_lock);
780 #ifdef CONFIG_MALI_DVFS
781 #ifdef EXYNOS4_ASV_ENABLED
782 if (samsung_rev() == EXYNOS3470_REV_2_0)
783 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT));
786 if (mali_dvfs_control != 0 || mali_gpu_clk >= mali_runtime_resume.clk) {
787 mali_clk_set_rate(mali_gpu_clk, GPU_MHZ);
789 #ifdef CONFIG_REGULATOR
790 mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol);
791 #ifdef EXYNOS4_ASV_ENABLED
792 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT));
795 mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ);
796 set_mali_dvfs_current_step(mali_runtime_resume.step);
799 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
800 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
803 _mali_osk_mutex_signal(mali_isp_lock);
807 static _mali_osk_errcode_t disable_mali_clocks(void)
809 #ifdef EXYNOS4_ASV_ENABLED
810 if (samsung_rev() == EXYNOS3470_REV_2_0)
811 exynos_set_abb(ID_G3D, ABB_BYPASS);
814 if (atomic_read(&clk_active)) {
815 clk_disable(mali_clock);
816 MALI_DEBUG_PRINT(3, ("disable_mali_clocks mali_clock %p\n", mali_clock));
817 atomic_set(&clk_active, 0);
822 _mali_osk_errcode_t mali_platform_init(struct device *dev)
824 MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT);
825 atomic_set(&clk_active, 0);
827 #ifdef CONFIG_MALI_DVFS
828 if (!clk_register_map)
829 clk_register_map = _mali_osk_mem_mapioregion(CLK_DIV_STAT_G3D, 0x20, CLK_DESC);
831 if (!init_mali_dvfs_status())
832 MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n"));
834 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
836 mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON);
840 _mali_osk_errcode_t mali_platform_deinit(struct device *dev)
842 mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP);
845 #ifdef CONFIG_MALI_DVFS
846 deinit_mali_dvfs_status();
847 if (clk_register_map)
849 _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map);
850 clk_register_map = NULL;
856 _mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode)
860 case MALI_POWER_MODE_ON:
861 MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n",
862 nPowermode ? "powering on" : "already on"));
863 if (nPowermode == MALI_POWER_MODE_LIGHT_SLEEP || nPowermode == MALI_POWER_MODE_DEEP_SLEEP) {
864 MALI_DEBUG_PRINT(4, ("enable clock\n"));
865 enable_mali_clocks();
867 #if defined(CONFIG_MALI400_PROFILING)
868 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
869 MALI_PROFILING_EVENT_CHANNEL_GPU |
870 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
871 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
873 nPowermode = power_mode;
876 case MALI_POWER_MODE_DEEP_SLEEP:
877 case MALI_POWER_MODE_LIGHT_SLEEP:
878 MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode == MALI_POWER_MODE_LIGHT_SLEEP ?
879 "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP",
880 nPowermode ? "already off" : "powering off"));
881 if (nPowermode == MALI_POWER_MODE_ON) {
882 disable_mali_clocks();
884 #if defined(CONFIG_MALI400_PROFILING)
885 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
886 MALI_PROFILING_EVENT_CHANNEL_GPU |
887 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
890 nPowermode = power_mode;
897 void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data)
899 if (nPowermode == MALI_POWER_MODE_ON)
901 #ifdef CONFIG_MALI_DVFS
902 if(!mali_dvfs_handler(data->utilization_gpu))
903 MALI_DEBUG_PRINT(1, ("error on mali dvfs status in utilization\n"));
908 #ifdef CONFIG_MALI_DVFS
909 static void update_time_in_state(int level)
912 static u64 prev_time = 0;
915 prev_time = get_jiffies_64();
917 current_time = get_jiffies_64();
918 mali_dvfs_time[level] += current_time - prev_time;
919 prev_time = current_time;
922 ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf)
927 update_time_in_state(maliDvfsStatus.currentStep);
929 for (i = 0; i < MALI_DVFS_STEPS; i++) {
930 ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d %llu\n",
935 if (ret < PAGE_SIZE - 1) {
936 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
938 buf[PAGE_SIZE - 2] = '\n';
939 buf[PAGE_SIZE - 1] = '\0';
945 ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
949 for (i = 0; i < MALI_DVFS_STEPS; i++) {
950 mali_dvfs_time[i] = 0;
956 int mali_dvfs_level_lock(void)
958 int prev_status = _mali_osk_atomic_read(&dvfslock_status);
959 unsigned long rate = (mali_dvfs[ISP_LOCK_STEP].clock * mali_dvfs[ISP_LOCK_STEP].freq);
960 unsigned int read_val;
961 #ifdef EXYNOS4_ASV_ENABLED
965 if (prev_status < 0) {
966 MALI_PRINT(("DVFS lock status is not valid for lock\n"));
968 } else if (prev_status > 0) {
969 MALI_PRINT(("DVFS lock already enabled\n"));
973 _mali_osk_mutex_wait(mali_isp_lock);
975 #ifdef CONFIG_REGULATOR
976 if(IS_ERR_OR_NULL(g3d_regulator))
978 MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n"));
979 _mali_osk_mutex_signal(mali_isp_lock);
983 #ifdef EXYNOS4_ASV_ENABLED
984 lock_vol = get_match_volt(ID_G3D, mali_dvfs[ISP_LOCK_STEP].clock * GPU_ASV_VOLT);
985 regulator_set_voltage(g3d_regulator, lock_vol, lock_vol);
986 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_dvfs[ISP_LOCK_STEP].clock * GPU_ASV_VOLT));
989 regulator_set_voltage(g3d_regulator, mali_dvfs[ISP_LOCK_STEP].vol, mali_dvfs[ISP_LOCK_STEP].vol);
991 mali_gpu_vol = regulator_get_voltage(g3d_regulator);
992 MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol));
995 if (mali_clk_get() == MALI_FALSE) {
996 _mali_osk_mutex_signal(mali_isp_lock);
999 clk_set_rate(mali_clock, (clk_get_rate(mali_clock) / 2));
1000 clk_set_parent(mali_parent_clock, mout_epll_clock);
1001 clk_set_parent(sclk_vpll_clock, ext_xtal_clock);
1002 clk_set_rate(fout_vpll_clock, mali_vpll_clk * GPU_MHZ);
1003 clk_set_parent(vpll_src_clock, ext_xtal_clock);
1004 clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
1005 clk_set_parent(mali_parent_clock, sclk_vpll_clock);
1009 read_val = __raw_readl(EXYNOS4_CLKMUX_STAT_G3D0);
1010 } while (((read_val >> 4) & 0x7) != 0x2);
1012 clk_set_parent(mali_clock, mali_parent_clock);
1013 clk_set_rate(mali_clock, rate);
1015 rate = clk_get_rate(mali_clock);
1016 mali_gpu_clk = (int)(rate / GPU_MHZ);
1017 mali_clk_put(MALI_FALSE);
1019 mali_dvfs_control = mali_dvfs[ISP_LOCK_STEP].clock;
1021 _mali_osk_mutex_signal(mali_isp_lock);
1022 MALI_DEBUG_PRINT(1, ("DVFS is locked by ISP\n"));
1024 return _mali_osk_atomic_inc_return(&dvfslock_status);
1027 int mali_dvfs_level_unlock(void)
1029 int prev_status = _mali_osk_atomic_read(&dvfslock_status);
1031 if (prev_status <= 0) {
1032 MALI_PRINT(("DVFS lock status is not valid for unlock\n"));
1034 } else if (prev_status >= 1) {
1035 _mali_osk_mutex_wait(mali_isp_lock);
1036 maliDvfsStatus.currentStep = mali_runtime_resume.step;
1037 mali_gpu_clk = mali_runtime_resume.clk;
1039 mali_dvfs_control = 0;
1040 MALI_DEBUG_PRINT(1, ("DVFS lock is released ISP\n"));
1041 _mali_osk_mutex_signal(mali_isp_lock);
1044 return _mali_osk_atomic_dec_return(&dvfslock_status);