1 /* drivers/gpu/mali400/mali/platform/exynos4415/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-exynos4415.h>
35 #include <mach/asv-exynos.h>
36 #ifdef CONFIG_CPU_FREQ
37 #ifndef CONFIG_SOC_EXYNOS4415
38 #define EXYNOS4_ASV_ENABLED
42 #ifdef CONFIG_MALI_DVFS_FULL_LEVEL
43 #define MALI_DVFS_FULL_LEVEL
46 /* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */
47 #ifndef S5P_G3D_CONFIGURATION
48 #define S5P_G3D_CONFIGURATION EXYNOS4_G3D_CONFIGURATION
50 #ifndef S5P_G3D_STATUS
51 #define S5P_G3D_STATUS (EXYNOS4_G3D_CONFIGURATION + 0x4)
53 #ifndef S5P_INT_LOCAL_PWR_EN
54 #define S5P_INT_LOCAL_PWR_EN EXYNOS_INT_LOCAL_PWR_EN
58 #include <mach/regs-pmu.h>
59 #include <linux/workqueue.h>
61 #ifdef MALI_DVFS_FULL_LEVEL
62 #define MALI_DVFS_STEPS 7
64 #define MALI_DVFS_STEPS 4
67 #define MALI_DVFS_WATING 10 /* msec */
68 #define MALI_DVFS_DEFAULT_STEP 1
69 #define PD_G3D_LOCK_FLAG 2
71 #define MALI_DVFS_CLK_DEBUG 0
72 #define CPUFREQ_LOCK_DURING_440 1
74 static int bMaliDvfsRun = 0;
76 typedef struct mali_dvfs_tableTag{
80 unsigned int downthreshold;
81 unsigned int upthreshold;
84 typedef struct mali_dvfs_statusTag{
85 unsigned int currentStep;
86 mali_dvfs_table * pCurrentDvfs;
91 mali_dvfs_status_t maliDvfsStatus;
92 int mali_dvfs_control;
94 typedef struct mali_runtime_resumeTag{
98 }mali_runtime_resume_table;
100 mali_runtime_resume_table mali_runtime_resume = {266, 875000, 1};
102 #ifdef MALI_DVFS_FULL_LEVEL
103 /*dvfs table updated on 131203*/
104 mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
105 /*step 0*/{160, 1000000, 850000, 0, 60},
106 /*step 1*/{266, 1000000, 875000, 52, 70},
107 /*step 2*/{350, 1000000, 950000, 62, 80},
108 /*step 3*/{440, 1000000, 1025000, 75, 80},
109 /*step 4*/{550, 1000000, 1125000, 85, 90},
110 /*step 5*/{667, 1000000, 1225000, 85, 95},
111 /*step 6*/{733, 1000000, 1300000, 95, 100} };
113 /*dvfs table updated on 131203*/
114 mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
115 /*step 0*/{160, 1000000, 850000, 0, 70},
116 /*step 1*/{266, 1000000, 875000, 62, 90},
117 /*step 2*/{350, 1000000, 950000, 85, 90},
118 /*step 3*/{440, 1000000, 1025000, 85, 100} };
122 int mali_gpu_clk = 266;
123 int mali_gpu_vol = 875000;
124 #ifdef MALI_DVFS_FULL_LEVEL
125 char *mali_freq_table = "733 667 550 440 350 266 160";
127 char *mali_freq_table = "440 350 266 160";
130 #define EXTXTALCLK_NAME "ext_xtal"
131 #define VPLLSRCCLK_NAME "vpll_src"
132 #define FOUTVPLLCLK_NAME "fout_vpll"
133 #define SCLKEPLLCLK_NAME "sclk_epll"
134 #define SCLVPLLCLK_NAME "sclk_vpll"
135 #define GPUMOUT1CLK_NAME "mout_g3d1"
136 #define GPUMOUT0CLK_NAME "mout_g3d0"
137 #define GPUCLK_NAME "sclk_g3d"
138 #define CLK_DIV_STAT_G3D 0x1003C62C
139 #define CLK_DESC "clk-divider-status"
141 static struct clk *ext_xtal_clock = NULL;
142 static struct clk *vpll_src_clock = NULL;
143 static struct clk *fout_vpll_clock = NULL;
144 static struct clk *sclk_epll_clock = NULL;
145 static struct clk *sclk_vpll_clock = NULL;
146 static struct clk *mali_parent_clock = NULL;
147 static struct clk *mali_clock = NULL;
149 static unsigned int GPU_MHZ = 1000000;
150 static unsigned int const GPU_ASV_VOLT = 1000;
151 static int nPowermode;
152 static atomic_t clk_active;
154 mali_io_address clk_register_map = 0;
156 /* export GPU frequency as a read-only parameter so that it can be read in /sys */
157 module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH);
158 module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH);
159 module_param(mali_freq_table, charp, S_IRUSR | S_IRGRP | S_IROTH);
160 #ifdef CONFIG_MALI_DVFS
161 module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */
162 MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS");
163 DEVICE_ATTR(time_in_state, S_IRUGO|S_IWUSR, show_time_in_state, set_time_in_state);
164 MODULE_PARM_DESC(time_in_state, "Time-in-state of Mali DVFS");
166 MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock");
167 MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage");
168 MODULE_PARM_DESC(mali_freq_table, "Mali frequency table");
170 #ifdef CONFIG_REGULATOR
171 struct regulator *g3d_regulator = NULL;
173 atomic_t mali_cpufreq_lock;
176 #ifdef CONFIG_MALI_DVFS
177 static unsigned int mali_dvfs_utilization = 255;
178 static void update_time_in_state(int level);
179 u64 mali_dvfs_time[MALI_DVFS_STEPS];
182 static void mali_dvfs_work_handler(struct work_struct *w);
183 static struct workqueue_struct *mali_dvfs_wq = 0;
184 _mali_osk_mutex_t *mali_dvfs_lock;
185 int mali_runtime_resumed = -1;
186 static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler);
188 int cpufreq_lock_by_mali(unsigned int freq)
190 #ifdef CONFIG_EXYNOS4_CPUFREQ
193 if (atomic_read(&mali_cpufreq_lock) == 0) {
194 if (exynos_cpufreq_get_level(freq * 1000, &level)) {
195 printk(KERN_ERR "Mali: failed to get cpufreq level for %dMHz", freq);
199 if (exynos_cpufreq_lock(DVFS_LOCK_ID_G3D, level)) {
200 printk(KERN_ERR "Mali: failed to cpufreq lock for L%d", level);
204 atomic_set(&mali_cpufreq_lock, 1);
205 printk(KERN_DEBUG "Mali: cpufreq locked on <%d>%dMHz\n", level, freq);
211 void cpufreq_unlock_by_mali(void)
213 #ifdef CONFIG_EXYNOS4_CPUFREQ
214 if (atomic_read(&mali_cpufreq_lock) == 1) {
215 exynos_cpufreq_lock_free(DVFS_LOCK_ID_G3D);
216 atomic_set(&mali_cpufreq_lock, 0);
217 printk(KERN_DEBUG "Mali: cpufreq locked off\n");
222 #ifdef CONFIG_REGULATOR
223 void mali_regulator_disable(void)
225 if(IS_ERR_OR_NULL(g3d_regulator))
227 MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n"));
230 regulator_disable(g3d_regulator);
233 void mali_regulator_enable(void)
235 if(IS_ERR_OR_NULL(g3d_regulator))
237 MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n"));
240 regulator_enable(g3d_regulator);
243 void mali_regulator_set_voltage(int min_uV, int max_uV)
245 _mali_osk_mutex_wait(mali_dvfs_lock);
246 if(IS_ERR_OR_NULL(g3d_regulator))
248 MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n"));
249 _mali_osk_mutex_signal(mali_dvfs_lock);
252 MALI_DEBUG_PRINT(1, ("= regulator_set_voltage: %d, %d \n", min_uV, max_uV));
253 regulator_set_voltage(g3d_regulator, min_uV, max_uV);
254 mali_gpu_vol = regulator_get_voltage(g3d_regulator);
255 MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol));
256 _mali_osk_mutex_signal(mali_dvfs_lock);
260 static unsigned int get_mali_dvfs_status(void)
262 return maliDvfsStatus.currentStep;
265 mali_bool mali_clk_get(void)
267 if (ext_xtal_clock == NULL) {
268 ext_xtal_clock = clk_get(NULL, EXTXTALCLK_NAME);
269 if (IS_ERR(ext_xtal_clock)) {
270 MALI_PRINT(("MALI Error : failed to get source ext_xtal_clock\n"));
275 if (vpll_src_clock == NULL) {
276 vpll_src_clock = clk_get(NULL, VPLLSRCCLK_NAME);
277 if (IS_ERR(vpll_src_clock)) {
278 MALI_PRINT(("MALI Error : failed to get source vpll_src_clock\n"));
283 if (fout_vpll_clock == NULL) {
284 fout_vpll_clock = clk_get(NULL, FOUTVPLLCLK_NAME);
285 if (IS_ERR(fout_vpll_clock)) {
286 MALI_PRINT(("MALI Error : failed to get source fout_vpll_clock\n"));
291 if (sclk_epll_clock == NULL) {
292 sclk_epll_clock = clk_get(NULL, SCLKEPLLCLK_NAME);
293 if (IS_ERR(fout_vpll_clock)) {
294 MALI_PRINT(("MALI Error : failed to get source sclk_epll_clock\n"));
299 if (sclk_vpll_clock == NULL) {
300 sclk_vpll_clock = clk_get(NULL, SCLVPLLCLK_NAME);
301 if (IS_ERR(sclk_vpll_clock)) {
302 MALI_PRINT(("MALI Error : failed to get source sclk_vpll_clock\n"));
307 if (mali_parent_clock == NULL) {
308 mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME);
309 if (IS_ERR(mali_parent_clock)) {
310 MALI_PRINT(("MALI Error : failed to get source mali parent clock\n"));
315 /* mali clock get always. */
316 if (mali_clock == NULL) {
317 mali_clock = clk_get(NULL, GPUCLK_NAME);
318 if (IS_ERR(mali_clock)) {
319 MALI_PRINT(("MALI Error : failed to get source mali clock\n"));
327 void mali_clk_put(mali_bool binc_mali_clock)
329 if (mali_parent_clock)
331 clk_put(mali_parent_clock);
332 mali_parent_clock = NULL;
337 clk_put(sclk_vpll_clock);
338 sclk_vpll_clock = NULL;
341 if (binc_mali_clock && fout_vpll_clock)
343 clk_put(fout_vpll_clock);
344 fout_vpll_clock = NULL;
349 clk_put(sclk_epll_clock);
350 sclk_epll_clock = NULL;
355 clk_put(vpll_src_clock);
356 vpll_src_clock = NULL;
361 clk_put(ext_xtal_clock);
362 ext_xtal_clock = NULL;
365 if (binc_mali_clock && mali_clock)
372 void mali_clk_set_rate(unsigned int clk, unsigned int mhz)
375 unsigned int read_val;
376 unsigned long rate = (unsigned long)clk * (unsigned long)mhz;
377 unsigned long CurRate = 0;
379 _mali_osk_mutex_wait(mali_dvfs_lock);
380 MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk));
382 if (mali_clk_get() == MALI_FALSE) {
383 _mali_osk_mutex_signal(mali_dvfs_lock);
387 CurRate = clk_get_rate(mali_clock);
390 _mali_osk_mutex_signal(mali_dvfs_lock);
391 MALI_PRINT_ERROR(("clk_get_rate[mali_clock] is 0 - return\n"));
395 err = clk_set_rate(mali_clock, CurRate / 4);
398 MALI_PRINT_ERROR(("Failed to set Mali clock before change PLL: %d\n", err));
400 err = clk_set_parent(mali_parent_clock, sclk_epll_clock);
403 MALI_PRINT_ERROR(("mali_parent set parent to sclk_epll failed\n"));
407 read_val = __raw_readl(EXYNOS4415_CLKMUX_STAT_G3D0);
408 } while (((read_val >> 4) & 0x7) != 0x1);
410 MALI_DEBUG_PRINT(3, ("Mali platform: set to EPLL EXYNOS4415_CLKMUX_STAT_G3D0: 0x%08x\n", __raw_readl(EXYNOS4415_CLKMUX_STAT_G3D0)));
412 err = clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ);
415 MALI_PRINT_ERROR(("Failed to set fout_vpll clock: %d\n", err));
418 err = clk_set_parent(vpll_src_clock, ext_xtal_clock);
421 MALI_PRINT_ERROR(("vpll_src set parent to ext_xtal failed\n"));
423 err = clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
426 MALI_PRINT_ERROR(("sclk_vpll set parent to fout_vpll failed\n"));
428 MALI_DEBUG_PRINT(3, ("Mali platform: set_parent_vpll : %8.x \n", (__raw_readl(EXYNOS4_CLKSRC_TOP0) >> 8) & 0x1));
430 err = clk_set_parent(mali_parent_clock, sclk_vpll_clock);
433 MALI_PRINT_ERROR(("mali_parent set parent to sclk_vpll failed\n"));
437 read_val = __raw_readl(EXYNOS4415_CLKMUX_STAT_G3D0);
438 } while (((read_val >> 4) & 0x7) != 0x2);
440 MALI_DEBUG_PRINT(3, ("SET to VPLL EXYNOS4_CLKMUX_STAT_G3D0 : 0x%08x\n", __raw_readl(EXYNOS4415_CLKMUX_STAT_G3D0)));
442 err = clk_set_parent(mali_clock, mali_parent_clock);
445 MALI_PRINT_ERROR(("mali_clock set parent to mali_parent failed\n"));
447 if (atomic_read(&clk_active) == 0) {
448 if (clk_enable(mali_clock) < 0) {
449 _mali_osk_mutex_signal(mali_dvfs_lock);
452 atomic_set(&clk_active, 1);
455 err = clk_set_rate(mali_clock, rate);
458 MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err));
460 rate = clk_get_rate(mali_clock);
462 MALI_DEBUG_PRINT(1, ("Mali frequency %d\n", rate / mhz));
465 mali_gpu_clk = (int)(rate / mhz);
466 mali_clk_put(MALI_FALSE);
468 _mali_osk_mutex_signal(mali_dvfs_lock);
471 mali_bool set_mali_dvfs_current_step(unsigned int step)
473 _mali_osk_mutex_wait(mali_dvfs_lock);
474 maliDvfsStatus.currentStep = step % MALI_DVFS_STEPS;
475 _mali_osk_mutex_signal(mali_dvfs_lock);
479 static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
481 u32 validatedStep = step;
482 #if MALI_DVFS_CLK_DEBUG
483 unsigned int *pRegMaliClkDiv;
484 unsigned int *pRegMaliMpll;
488 #ifdef CONFIG_REGULATOR
489 /*change the voltage*/
490 #ifdef EXYNOS4_ASV_ENABLED
491 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));
492 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT));
494 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
498 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
501 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
502 #ifdef CONFIG_REGULATOR
503 #ifdef EXYNOS4_ASV_ENABLED
504 /*change the voltage*/
505 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));
506 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_dvfs[step].clock * GPU_ASV_VOLT));
508 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
513 #if defined(CONFIG_MALI400_PROFILING)
514 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
515 MALI_PROFILING_EVENT_CHANNEL_GPU|
516 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
517 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
519 mali_clk_put(MALI_FALSE);
521 #if MALI_DVFS_CLK_DEBUG
522 pRegMaliClkDiv = ioremap(0x1003c52c, 32);
523 pRegMaliMpll = ioremap(0x1003c22c, 32);
524 MALI_PRINT(("Mali MPLL reg:%d, CLK DIV: %d \n", *pRegMaliMpll, *pRegMaliClkDiv));
526 set_mali_dvfs_current_step(validatedStep);
528 maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep];
530 #if CPUFREQ_LOCK_DURING_440
531 /* lock/unlock CPU freq by Mali */
532 if (mali_dvfs[step].clock >= 440)
533 cpufreq_lock_by_mali(400);
535 cpufreq_unlock_by_mali();
540 static void mali_platform_wating(u32 msec)
544 * change this in the future with proper check routine.
546 unsigned int read_val;
548 read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00);
549 if ((read_val & 0x8000)==0x0000) break;
551 _mali_osk_time_ubusydelay(100); /* 1000 -> 100 : 20101218 */
555 static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup )
557 MALI_DEBUG_PRINT(4, ("> change_mali_dvfs_status: %d, %d \n", step, boostup));
559 if (!set_mali_dvfs_status(step, boostup)) {
560 MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup));
564 /* wait until clock and voltage is stablized */
565 mali_platform_wating(MALI_DVFS_WATING); /* msec */
569 static unsigned int decideNextStatus(unsigned int utilization)
571 static unsigned int level = 0;
574 if (mali_runtime_resumed >= 0) {
575 level = mali_runtime_resumed;
576 mali_runtime_resumed = -1;
579 if (mali_dvfs_control == 0) {
580 if (utilization > (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].upthreshold / 100) &&
581 level < MALI_DVFS_STEPS - 1) {
583 } else if (utilization < (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].downthreshold / 100) &&
588 for (iStepCount = MALI_DVFS_STEPS-1; iStepCount >= 0; iStepCount--) {
589 if (mali_dvfs_control >= mali_dvfs[iStepCount].clock) {
598 static mali_bool mali_dvfs_status(unsigned int utilization)
600 unsigned int nextStatus = 0;
601 unsigned int curStatus = 0;
602 mali_bool boostup = MALI_FALSE;
603 static int stay_count = 5;
605 MALI_DEBUG_PRINT(4, ("> mali_dvfs_status: %d \n", utilization));
607 /* decide next step */
608 curStatus = get_mali_dvfs_status();
609 nextStatus = decideNextStatus(utilization);
611 MALI_DEBUG_PRINT(4, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep));
612 /* if next status is same with current status, don't change anything */
613 if(curStatus != nextStatus) {
614 /*check if boost up or not*/
615 if(maliDvfsStatus.currentStep < nextStatus) {
618 } else if (maliDvfsStatus.currentStep > nextStatus){
622 if( boostup == 1 || stay_count <= 0){
623 /*change mali dvfs status*/
624 #ifdef CONFIG_MALI_DVFS
625 update_time_in_state(curStatus);
627 if (!change_mali_dvfs_status(nextStatus, boostup)) {
628 MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n"));
641 static void mali_dvfs_work_handler(struct work_struct *w)
644 MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
646 if(!mali_dvfs_status(mali_dvfs_utilization))
647 MALI_DEBUG_PRINT(1, ( "error on mali dvfs status in mali_dvfs_work_handler"));
652 mali_bool init_mali_dvfs_status(void)
656 * add here with the right function to get initilization value.
659 mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
661 /* add a error handling here */
662 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
667 void deinit_mali_dvfs_status(void)
670 destroy_workqueue(mali_dvfs_wq);
675 mali_bool mali_dvfs_handler(unsigned int utilization)
677 mali_dvfs_utilization = utilization;
678 queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
683 static mali_bool init_mali_clock(void)
685 mali_bool ret = MALI_TRUE;
686 nPowermode = MALI_POWER_MODE_DEEP_SLEEP;
689 return ret; /* already initialized */
691 mali_dvfs_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, 0);
693 if (mali_dvfs_lock == NULL)
694 return _MALI_OSK_ERR_FAULT;
698 MALI_PRINT(("Error: Failed to get Mali clock\n"));
702 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
704 MALI_PRINT(("init_mali_clock mali_clock %x\n", mali_clock));
706 #ifdef CONFIG_REGULATOR
707 g3d_regulator = regulator_get(NULL, "vdd_g3d");
709 if (IS_ERR(g3d_regulator))
711 MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n"));
716 mali_gpu_vol = mali_runtime_resume.vol;
717 #ifdef EXYNOS4_ASV_ENABLED
718 mali_gpu_vol = get_match_volt(ID_G3D, mali_gpu_clk * GPU_ASV_VOLT);
719 mali_runtime_resume.vol = get_match_volt(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT);
722 regulator_enable(g3d_regulator);
723 mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol);
725 #ifdef EXYNOS4_ASV_ENABLED
726 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT));
730 #if defined(CONFIG_MALI400_PROFILING)
731 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
732 MALI_PROFILING_EVENT_CHANNEL_GPU|
733 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
734 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
736 mali_clk_put(MALI_FALSE);
740 #ifdef CONFIG_REGULATOR
742 regulator_put(g3d_regulator);
745 mali_clk_put(MALI_TRUE);
750 static mali_bool deinit_mali_clock(void)
755 #ifdef CONFIG_REGULATOR
758 regulator_put(g3d_regulator);
759 g3d_regulator = NULL;
762 mali_clk_put(MALI_TRUE);
767 static _mali_osk_errcode_t enable_mali_clocks(void)
771 if (atomic_read(&clk_active) == 0) {
772 err = clk_enable(mali_clock);
773 MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err));
774 atomic_set(&clk_active, 1);
778 #ifdef CONFIG_MALI_DVFS
779 if (mali_dvfs_control != 0 || mali_gpu_clk >= mali_runtime_resume.clk) {
780 mali_clk_set_rate(mali_gpu_clk, GPU_MHZ);
782 #ifdef CONFIG_REGULATOR
783 mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol);
784 #ifdef EXYNOS4_ASV_ENABLED
785 exynos_set_abb(ID_G3D, get_match_abb(ID_G3D, mali_runtime_resume.clk * GPU_ASV_VOLT));
788 mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ);
789 set_mali_dvfs_current_step(mali_runtime_resume.step);
792 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
793 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
799 static _mali_osk_errcode_t disable_mali_clocks(void)
801 if (atomic_read(&clk_active)) {
802 clk_disable(mali_clock);
803 MALI_DEBUG_PRINT(3, ("disable_mali_clocks mali_clock %p\n", mali_clock));
804 atomic_set(&clk_active, 0);
809 _mali_osk_errcode_t mali_platform_init(struct device *dev)
811 MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT);
812 atomic_set(&clk_active, 0);
814 #ifdef CONFIG_MALI_DVFS
815 if (!clk_register_map)
816 clk_register_map = _mali_osk_mem_mapioregion(CLK_DIV_STAT_G3D, 0x20, CLK_DESC);
818 if (!init_mali_dvfs_status())
819 MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n"));
821 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
823 mali_platform_power_mode_change(dev, MALI_POWER_MODE_ON);
827 _mali_osk_errcode_t mali_platform_deinit(struct device *dev)
829 mali_platform_power_mode_change(dev, MALI_POWER_MODE_DEEP_SLEEP);
832 #ifdef CONFIG_MALI_DVFS
833 deinit_mali_dvfs_status();
834 if (clk_register_map)
836 _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map);
837 clk_register_map = NULL;
843 _mali_osk_errcode_t mali_platform_power_mode_change(struct device *dev, mali_power_mode power_mode)
847 case MALI_POWER_MODE_ON:
848 MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n",
849 nPowermode ? "powering on" : "already on"));
850 if (nPowermode == MALI_POWER_MODE_LIGHT_SLEEP || nPowermode == MALI_POWER_MODE_DEEP_SLEEP) {
851 MALI_DEBUG_PRINT(4, ("enable clock\n"));
852 enable_mali_clocks();
854 #if defined(CONFIG_MALI400_PROFILING)
855 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
856 MALI_PROFILING_EVENT_CHANNEL_GPU |
857 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
858 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
860 nPowermode = power_mode;
863 case MALI_POWER_MODE_DEEP_SLEEP:
864 case MALI_POWER_MODE_LIGHT_SLEEP:
865 MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode == MALI_POWER_MODE_LIGHT_SLEEP ?
866 "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP",
867 nPowermode ? "already off" : "powering off"));
868 if (nPowermode == MALI_POWER_MODE_ON) {
869 disable_mali_clocks();
871 #if defined(CONFIG_MALI400_PROFILING)
872 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
873 MALI_PROFILING_EVENT_CHANNEL_GPU |
874 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
877 nPowermode = power_mode;
884 void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data)
886 if (nPowermode == MALI_POWER_MODE_ON)
888 #ifdef CONFIG_MALI_DVFS
889 if(!mali_dvfs_handler(data->utilization_gpu))
890 MALI_DEBUG_PRINT(1, ("error on mali dvfs status in utilization\n"));
895 #ifdef CONFIG_MALI_DVFS
896 static void update_time_in_state(int level)
899 static u64 prev_time = 0;
902 prev_time = get_jiffies_64();
904 current_time = get_jiffies_64();
905 mali_dvfs_time[level] += current_time - prev_time;
906 prev_time = current_time;
909 ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, char *buf)
914 update_time_in_state(maliDvfsStatus.currentStep);
916 for (i = 0; i < MALI_DVFS_STEPS; i++) {
917 ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d %llu\n",
922 if (ret < PAGE_SIZE - 1) {
923 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
925 buf[PAGE_SIZE - 2] = '\n';
926 buf[PAGE_SIZE - 1] = '\0';
932 ssize_t set_time_in_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
936 for (i = 0; i < MALI_DVFS_STEPS; i++) {
937 mali_dvfs_time[i] = 0;