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
17 #include "mali_kernel_common.h"
19 #include "exynos4_pmm.h"
20 #include <linux/clk.h>
21 #include <linux/err.h>
22 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/regulator/consumer.h>
26 #if defined(CONFIG_MALI400_PROFILING)
27 #include "mali_osk_profiling.h"
30 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
31 /* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */
32 #ifndef S5P_G3D_CONFIGURATION
33 #define S5P_G3D_CONFIGURATION S5P_PMU_G3D_CONF
35 #ifndef S5P_G3D_STATUS
36 #define S5P_G3D_STATUS S5P_PMU_G3D_CONF + 0x4
38 #if defined(CONFIG_PM_RUNTIME)
42 /* Some defines changed names in later Odroid-A kernels. Make sure it works for both. */
43 #ifndef S5P_G3D_CONFIGURATION
44 #define S5P_G3D_CONFIGURATION EXYNOS4_G3D_CONFIGURATION
46 #ifndef S5P_G3D_STATUS
47 #define S5P_G3D_STATUS (EXYNOS4_G3D_CONFIGURATION + 0x4)
49 #ifndef S5P_INT_LOCAL_PWR_EN
50 #define S5P_INT_LOCAL_PWR_EN EXYNOS_INT_LOCAL_PWR_EN
55 #include <mach/regs-pmu.h>
56 #include <linux/pm_qos.h>
57 #ifdef CONFIG_EXYNOS_BUSFREQ_OPP
58 #include <mach/busfreq_exynos4.h>
61 #include <linux/workqueue.h>
63 #define MALI_DVFS_STEPS 5
64 #define MALI_DVFS_WATING 10 /* msec */
65 #define MALI_DVFS_DEFAULT_STEP 1
67 #ifdef CONFIG_CPU_FREQ
69 #define EXYNOS4_ASV_ENABLED
72 #define MALI_DVFS_CLK_DEBUG 0
73 #define SEC_THRESHOLD 1
75 static int bMaliDvfsRun = 0;
77 typedef struct mali_dvfs_tableTag{
82 unsigned int downthreshold;
83 unsigned int upthreshold;
87 typedef struct mali_dvfs_statusTag{
88 unsigned int currentStep;
89 mali_dvfs_table * pCurrentDvfs;
94 mali_dvfs_status_t maliDvfsStatus;
95 int mali_dvfs_control;
97 typedef struct mali_runtime_resumeTag{
101 }mali_runtime_resume_table;
103 /*mali_runtime_resume_table mali_runtime_resume = {266, 900000, 1};*/
104 mali_runtime_resume_table mali_runtime_resume = {160, 875000, 1};
107 mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
108 /*step 0*/{160 ,1000000 ,875000 , 0 , 70},
109 /*step 1*/{266 ,1000000 ,900000 ,62 , 90},
110 /*step 2*/{350 ,1000000 ,950000 ,85 , 90},
111 /*step 3*/{440 ,1000000 ,1025000 ,85 , 90},
112 /*step 4*/{533 ,1000000 ,1075000 ,85 ,100} };
114 #ifdef EXYNOS4_ASV_ENABLED
115 #define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */
116 #define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */
118 static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = {
119 { 962500, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000, 850000}, /* L4(160Mhz) */
120 #if (MALI_DVFS_STEPS > 1)
121 { 987500, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 875000, 875000}, /* L3(266Mhz) */
122 #if (MALI_DVFS_STEPS > 2)
123 { 1037500, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 912500, 900000, 887500}, /* L2(350Mhz) */
124 #if (MALI_DVFS_STEPS > 3)
125 { 1100000, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 975000, 962500, 950000}, /* L1(440Mhz) */
126 #if (MALI_DVFS_STEPS > 4)
127 { 1162500, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1075000, 1062500, 1037500, 1025000, 1012500}, /* L0(533Mhz) */
133 #endif /* ASV_LEVEL */
135 #define EXTXTALCLK_NAME "ext_xtal"
136 #define VPLLSRCCLK_NAME "vpll_src"
137 #define FOUTVPLLCLK_NAME "fout_vpll"
138 #define SCLVPLLCLK_NAME "sclk_vpll"
139 #define GPUMOUT1CLK_NAME "mout_g3d1"
141 #define MPLLCLK_NAME "mout_mpll"
142 #define GPUMOUT0CLK_NAME "mout_g3d0"
143 #define GPUCLK_NAME "sclk_g3d"
144 #define CLK_DIV_STAT_G3D 0x1003C62C
145 #define CLK_DESC "clk-divider-status"
147 static struct clk *ext_xtal_clock = NULL;
148 static struct clk *vpll_src_clock = NULL;
149 static struct clk *fout_vpll_clock = NULL;
150 static struct clk *sclk_vpll_clock = NULL;
152 static struct clk *mpll_clock = NULL;
153 static struct clk *mali_parent_clock = NULL;
154 static struct clk *mali_clock = NULL;
157 static const mali_bool bis_vpll = MALI_TRUE;
158 int mali_gpu_clk = 440;
159 int mali_gpu_vol = 1025000;
161 static unsigned int GPU_MHZ = 1000000;
164 static int bPoweroff;
165 static atomic_t clk_active;
167 #ifdef CONFIG_EXYNOS_BUSFREQ_OPP
168 static struct pm_qos_request mali_pm_qos_busfreq;
171 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
172 static struct pm_qos_request mali_pm_qos_cpufreq;
173 static atomic_t mali_cur_cpufreq = ATOMIC_INIT(0);
176 #ifdef CONFIG_REGULATOR
177 struct regulator *g3d_regulator = NULL;
180 mali_io_address clk_register_map = 0;
183 unsigned int mali_dvfs_utilization = 255;
184 static int mali_gpu_clk_on;
186 static void mali_dvfs_work_handler(struct work_struct *w);
188 static struct workqueue_struct *mali_dvfs_wq = 0;
190 extern mali_io_address clk_register_map;
192 _mali_osk_lock_t *mali_dvfs_lock = 0;
194 int mali_runtime_resumed = -1;
196 static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler);
199 /* export GPU frequency as a read-only parameter so that it can be read in /sys */
200 module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH);
201 MODULE_PARM_DESC(mali_gpu_clk, "GPU frequency in MHz");
204 * The CPU frequency lock is used to guarantee CPU minimum QoS at maximum GPU
205 * clocks. So when GPU clock is 440MHz, CPU QoS is set to minimum 1.2GHz,
206 * and when GPU clock is 533MHz, CPU QoS is set to minimum 1.4GHz.
207 * The other cases, CPU QoS is set to 0.
209 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
210 int cpufreq_lock_by_mali(int freq)
213 return _MALI_OSK_ERR_INVALID_ARGS;
215 if (atomic_read(&mali_cur_cpufreq) != freq) {
216 pm_qos_update_request(&mali_pm_qos_cpufreq, freq * 1000);
217 atomic_set(&mali_cur_cpufreq, freq);
220 return _MALI_OSK_ERR_OK;
223 void cpufreq_unlock_by_mali(void)
225 if (atomic_read(&mali_cur_cpufreq) > 0) {
226 pm_qos_update_request(&mali_pm_qos_cpufreq, 0);
227 atomic_set(&mali_cur_cpufreq, 0);
232 #ifdef CONFIG_REGULATOR
233 void mali_regulator_disable(void)
235 if(IS_ERR_OR_NULL(g3d_regulator))
237 MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n"));
240 regulator_disable(g3d_regulator);
243 void mali_regulator_enable(void)
245 if(IS_ERR_OR_NULL(g3d_regulator))
247 MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n"));
250 regulator_enable(g3d_regulator);
253 void mali_regulator_set_voltage(int min_uV, int max_uV)
255 _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
256 if(IS_ERR_OR_NULL(g3d_regulator))
258 MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n"));
261 MALI_DEBUG_PRINT(3, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV));
262 regulator_set_voltage(g3d_regulator, min_uV, max_uV);
263 mali_gpu_vol = regulator_get_voltage(g3d_regulator);
264 MALI_DEBUG_PRINT(1, ("Mali voltage: %d\n", mali_gpu_vol));
265 _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
269 unsigned long mali_clk_get_rate(void)
271 return clk_get_rate(mali_clock);
275 static unsigned int get_mali_dvfs_status(void)
277 return maliDvfsStatus.currentStep;
280 mali_bool mali_clk_get(void)
284 if (ext_xtal_clock == NULL)
286 ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME);
287 if (IS_ERR(ext_xtal_clock)) {
288 MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n"));
293 if (vpll_src_clock == NULL)
295 vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME);
296 if (IS_ERR(vpll_src_clock)) {
297 MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n"));
302 if (fout_vpll_clock == NULL)
304 fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME);
305 if (IS_ERR(fout_vpll_clock)) {
306 MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n"));
311 if (sclk_vpll_clock == NULL)
313 sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME);
314 if (IS_ERR(sclk_vpll_clock)) {
315 MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n"));
320 if (mali_parent_clock == NULL)
322 mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME);
324 if (IS_ERR(mali_parent_clock)) {
325 MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n"));
332 if (mpll_clock == NULL)
334 mpll_clock = clk_get(NULL,MPLLCLK_NAME);
336 if (IS_ERR(mpll_clock)) {
337 MALI_PRINT( ("MALI Error : failed to get source mpll clock\n"));
342 if (mali_parent_clock == NULL)
344 mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME);
346 if (IS_ERR(mali_parent_clock)) {
347 MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n"));
353 // mali clock get always.
354 if (mali_clock == NULL)
356 mali_clock = clk_get(NULL, GPUCLK_NAME);
358 if (IS_ERR(mali_clock)) {
359 MALI_PRINT( ("MALI Error : failed to get source mali clock\n"));
367 void mali_clk_put(mali_bool binc_mali_clock)
369 if (mali_parent_clock)
371 clk_put(mali_parent_clock);
372 mali_parent_clock = NULL;
383 clk_put(sclk_vpll_clock);
384 sclk_vpll_clock = NULL;
387 if (binc_mali_clock && fout_vpll_clock)
389 clk_put(fout_vpll_clock);
390 fout_vpll_clock = NULL;
395 clk_put(vpll_src_clock);
396 vpll_src_clock = NULL;
401 clk_put(ext_xtal_clock);
402 ext_xtal_clock = NULL;
405 if (binc_mali_clock && mali_clock)
412 void mali_clk_set_rate(unsigned int clk, unsigned int mhz)
415 unsigned long rate = (unsigned long)clk * (unsigned long)mhz;
417 _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
418 MALI_DEBUG_PRINT(3, ("Mali platform: Setting frequency to %d mhz\n", clk));
420 if (mali_clk_get() == MALI_FALSE)
425 clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ);
426 clk_set_parent(vpll_src_clock, ext_xtal_clock);
427 clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
429 clk_set_parent(mali_parent_clock, sclk_vpll_clock);
430 clk_set_parent(mali_clock, mali_parent_clock);
434 clk_set_parent(mali_parent_clock, mpll_clock);
435 clk_set_parent(mali_clock, mali_parent_clock);
438 if (!atomic_read(&clk_active)) {
439 if (clk_enable(mali_clock) < 0)
441 atomic_set(&clk_active, 1);
444 err = clk_set_rate(mali_clock, rate);
445 if (err) MALI_PRINT_ERROR(("Failed to set Mali clock: %d\n", err));
447 rate = mali_clk_get_rate();
449 MALI_DEBUG_PRINT(3, ("Mali frequency %d\n", rate / mhz));
451 mali_gpu_clk = (int)(rate / mhz);
453 mali_clk_put(MALI_FALSE);
455 _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
458 int get_mali_dvfs_control_status(void)
460 return mali_dvfs_control;
463 mali_bool set_mali_dvfs_current_step(unsigned int step)
465 _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
466 maliDvfsStatus.currentStep = step % MALI_DVFS_STEPS;
467 if (step >= MALI_DVFS_STEPS)
468 mali_runtime_resumed = maliDvfsStatus.currentStep;
470 _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
475 static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
477 u32 validatedStep=step;
478 #if MALI_DVFS_CLK_DEBUG
479 unsigned int *pRegMaliClkDiv;
480 unsigned int *pRegMaliMpll;
485 #ifdef CONFIG_REGULATOR
486 /*change the voltage*/
487 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
490 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
493 mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
494 #ifdef CONFIG_REGULATOR
495 /*change the voltage*/
496 mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
500 #if defined(CONFIG_MALI400_PROFILING)
501 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
502 MALI_PROFILING_EVENT_CHANNEL_GPU|
503 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
504 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
506 mali_clk_put(MALI_FALSE);
508 #if MALI_DVFS_CLK_DEBUG
509 pRegMaliClkDiv = ioremap(0x1003c52c,32);
510 pRegMaliMpll = ioremap(0x1003c22c,32);
511 MALI_PRINT( ("Mali MPLL reg:%d, CLK DIV: %d \n",*pRegMaliMpll, *pRegMaliClkDiv));
514 set_mali_dvfs_current_step(validatedStep);
516 maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep];
518 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
519 /* lock/unlock CPU freq by Mali */
520 if (mali_dvfs[step].clock >= 530)
521 err = cpufreq_lock_by_mali(1400);
522 else if (mali_dvfs[step].clock >= 440)
523 err = cpufreq_lock_by_mali(1200);
525 cpufreq_unlock_by_mali();
532 static void mali_platform_wating(u32 msec)
536 * change this in the future with proper check routine.
538 unsigned int read_val;
541 #ifdef CONFIG_SLP_MALI_DBG
542 read_val = _mali_osk_mem_ioread32_cpu(clk_register_map, 0x00);
544 read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00);
546 if ((read_val & 0x8000)==0x0000) break;
548 _mali_osk_time_ubusydelay(100); /* 1000 -> 100 : 20101218 */
550 /* _mali_osk_time_ubusydelay(msec*1000);*/
553 static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup )
555 MALI_DEBUG_PRINT(4, ("> change_mali_dvfs_status: %d, %d \n",step, boostup));
557 if(!set_mali_dvfs_status(step, boostup))
559 MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup));
563 /*wait until clock and voltage is stablized*/
564 mali_platform_wating(MALI_DVFS_WATING); /*msec*/
569 #ifdef EXYNOS4_ASV_ENABLED
570 extern unsigned int exynos_result_of_asv;
572 static mali_bool mali_dvfs_table_update(void)
575 unsigned int step_num = MALI_DVFS_STEPS;
577 MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv));
578 for (i = 0; i < step_num; i++) {
579 mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv];
580 MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol));
587 static unsigned int decideNextStatus(unsigned int utilization)
589 static unsigned int level = 0;
591 if (mali_runtime_resumed >= 0) {
592 level = mali_runtime_resumed;
593 mali_runtime_resumed = -1;
596 if (mali_dvfs_control == 0 && level == get_mali_dvfs_status()) {
597 if (utilization > (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].upthreshold / 100) &&
598 level < MALI_DVFS_STEPS - 1) {
601 else if (utilization < (int)(255 * mali_dvfs[maliDvfsStatus.currentStep].downthreshold / 100) &&
606 for (iStepCount = MALI_DVFS_STEPS-1; iStepCount >= 0; iStepCount--) {
607 if ( mali_dvfs_control >= mali_dvfs[iStepCount].clock ) {
608 maliDvfsStatus.currentStep = iStepCount;
618 static mali_bool mali_dvfs_status(unsigned int utilization)
620 unsigned int nextStatus = 0;
621 unsigned int curStatus = 0;
622 mali_bool boostup = MALI_FALSE;
623 #ifdef EXYNOS4_ASV_ENABLED
624 static mali_bool asv_applied = MALI_FALSE;
627 #ifdef EXYNOS4_ASV_ENABLED
628 if (asv_applied == MALI_FALSE) {
629 mali_dvfs_table_update();
630 change_mali_dvfs_status(1, 0);
631 asv_applied = MALI_TRUE;
637 MALI_DEBUG_PRINT(4, ("> mali_dvfs_status: %d \n",utilization));
640 curStatus = get_mali_dvfs_status();
641 nextStatus = decideNextStatus(utilization);
643 MALI_DEBUG_PRINT(4, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep));
644 /*if next status is same with current status, don't change anything*/
645 if(curStatus!=nextStatus)
647 /*check if boost up or not*/
648 if(nextStatus > maliDvfsStatus.currentStep) boostup = 1;
650 /*change mali dvfs status*/
651 if(!change_mali_dvfs_status(nextStatus,boostup))
653 MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n"));
661 int mali_dvfs_is_running(void)
667 static void mali_dvfs_work_handler(struct work_struct *w)
671 MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
673 if(!mali_dvfs_status(mali_dvfs_utilization))
674 MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler"));
680 mali_bool init_mali_dvfs_status(void)
684 * add here with the right function to get initilization value.
689 mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
692 /*add a error handling here*/
693 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
695 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
696 pm_qos_add_request(&mali_pm_qos_cpufreq, PM_QOS_CPU_FREQ_MIN, 0);
702 void deinit_mali_dvfs_status(void)
706 destroy_workqueue(mali_dvfs_wq);
710 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
711 pm_qos_remove_request(&mali_pm_qos_cpufreq);
715 mali_bool mali_dvfs_handler(unsigned int utilization)
717 mali_dvfs_utilization = utilization;
718 queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
723 static mali_bool init_mali_clock(void)
725 mali_bool ret = MALI_TRUE;
730 return ret; /* already initialized */
732 mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE
733 | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0);
734 if (mali_dvfs_lock == NULL)
735 return _MALI_OSK_ERR_FAULT;
741 MALI_PRINT(("Error: Failed to get Mali clock\n"));
745 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
747 MALI_PRINT(("init_mali_clock mali_clock %x\n", mali_clock));
749 #ifdef CONFIG_REGULATOR
750 g3d_regulator = regulator_get(NULL, "vdd_g3d");
752 if (IS_ERR(g3d_regulator))
754 MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n"));
759 regulator_enable(g3d_regulator);
760 mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol);
763 #if defined(CONFIG_MALI400_PROFILING)
764 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
765 MALI_PROFILING_EVENT_CHANNEL_GPU|
766 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
767 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
770 mali_clk_put(MALI_FALSE);
772 mali_gpu_clk_on = mali_gpu_clk;
776 #ifdef CONFIG_REGULATOR
778 regulator_put(g3d_regulator);
781 mali_clk_put(MALI_TRUE);
786 static mali_bool deinit_mali_clock(void)
791 #ifdef CONFIG_REGULATOR
794 regulator_put(g3d_regulator);
795 g3d_regulator = NULL;
799 mali_clk_put(MALI_TRUE);
805 static _mali_osk_errcode_t enable_mali_clocks(void)
809 if (!atomic_read(&clk_active)) {
810 err = clk_enable(mali_clock);
811 MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err));
812 atomic_set(&clk_active, 1);
815 mali_gpu_clk = mali_gpu_clk_on;
818 #ifdef CONFIG_MALI_DVFS
819 if (get_mali_dvfs_control_status() != 0 || mali_gpu_clk >= mali_runtime_resume.clk) {
820 mali_clk_set_rate(mali_gpu_clk, GPU_MHZ);
822 #ifdef CONFIG_REGULATOR
823 mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol);
825 mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ);
826 set_mali_dvfs_current_step(mali_runtime_resume.step);
829 mali_clk_set_rate((unsigned int)mali_gpu_clk, GPU_MHZ);
831 maliDvfsStatus.currentStep = MALI_DVFS_DEFAULT_STEP;
834 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
835 /* lock/unlock CPU freq by Mali */
836 if (mali_gpu_clk >= 530)
837 err = cpufreq_lock_by_mali(1400);
838 else if (mali_gpu_clk >= 440)
839 err = cpufreq_lock_by_mali(1200);
841 cpufreq_unlock_by_mali();
847 static _mali_osk_errcode_t disable_mali_clocks(void)
849 if (atomic_read(&clk_active)) {
850 clk_disable(mali_clock);
851 atomic_set(&clk_active, 0);
854 MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock));
856 #ifdef CONFIG_ARM_EXYNOS_CPUFREQ
857 cpufreq_unlock_by_mali();
860 /* to reflect the gpu clock off state */
861 mali_gpu_clk_on = mali_gpu_clk;
868 _mali_osk_errcode_t g3d_power_domain_control(int bpower_on)
872 void __iomem *status;
874 __raw_writel(EXYNOS_INT_LOCAL_PWR_EN, S5P_G3D_CONFIGURATION);
875 status = S5P_G3D_STATUS;
878 while ((__raw_readl(status) & EXYNOS_INT_LOCAL_PWR_EN)
879 != EXYNOS_INT_LOCAL_PWR_EN) {
881 MALI_PRINTF(("Power domain enable failed.\n"));
885 _mali_osk_time_ubusydelay(100);
890 void __iomem *status;
892 __raw_writel(0, S5P_G3D_CONFIGURATION);
894 status = S5P_G3D_STATUS;
897 while (__raw_readl(status) & EXYNOS_INT_LOCAL_PWR_EN)
900 MALI_PRINTF(("Power domain disable failed.\n" ));
904 _mali_osk_time_ubusydelay( 100);
911 _mali_osk_errcode_t mali_platform_init(void)
913 MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT);
914 #ifdef CONFIG_MALI_DVFS
915 if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC );
916 if(!init_mali_dvfs_status())
917 MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n"));
920 #ifdef CONFIG_EXYNOS_BUSFREQ_OPP
921 pm_qos_add_request(&mali_pm_qos_busfreq, PM_QOS_BUS_THROUGHPUT, 0);
924 mali_platform_power_mode_change(MALI_POWER_MODE_ON);
929 _mali_osk_errcode_t mali_platform_deinit(void)
932 mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
935 #ifdef CONFIG_MALI_DVFS
936 deinit_mali_dvfs_status();
937 if (clk_register_map )
939 _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map);
940 clk_register_map = NULL;
944 #ifdef CONFIG_EXYNOS_BUSFREQ_OPP
945 pm_qos_remove_request(&mali_pm_qos_busfreq);
951 _mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode)
955 case MALI_POWER_MODE_ON:
956 MALI_DEBUG_PRINT(3, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n",
957 bPoweroff ? "powering on" : "already on"));
960 #if !defined(CONFIG_PM_RUNTIME)
961 g3d_power_domain_control(1);
963 MALI_DEBUG_PRINT(4,("enable clock \n"));
964 enable_mali_clocks();
965 #if defined(CONFIG_MALI400_PROFILING)
966 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
967 MALI_PROFILING_EVENT_CHANNEL_GPU |
968 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
969 mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
975 case MALI_POWER_MODE_LIGHT_SLEEP:
976 case MALI_POWER_MODE_DEEP_SLEEP:
977 MALI_DEBUG_PRINT(3, ("Mali platform: Got %s event, %s\n", power_mode ==
978 MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" :
979 "MALI_POWER_MODE_DEEP_SLEEP", bPoweroff ? "already off" : "powering off"));
982 disable_mali_clocks();
983 #if defined(CONFIG_MALI400_PROFILING)
984 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
985 MALI_PROFILING_EVENT_CHANNEL_GPU |
986 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
990 #if !defined(CONFIG_PM_RUNTIME)
991 g3d_power_domain_control(0);
1001 void mali_gpu_utilization_handler(unsigned int utilization)
1005 #ifdef CONFIG_MALI_DVFS
1006 if(!mali_dvfs_handler(utilization))
1007 MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n"));