2 * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
4 * This program is free software and is provided to you under the terms of the
5 * GNU General Public License version 2 as published by the Free Software
6 * Foundation, and any use by you of this program is subject to the terms of
9 * A copy of the licence is included with the program, and can also be obtained
10 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15 * @file mali_platform.c
16 * Platform specific Mali driver functions for a default platform
19 #include <linux/version.h>
20 #include <linux/clk.h>
21 #include <linux/delay.h>
22 #include <linux/dma-mapping.h>
23 #ifdef CONFIG_SYSTEM_LOAD_ANALYZER
24 #include <linux/load_analyzer.h>
26 #include <linux/mali/mali_utgard.h>
30 #include <linux/platform_device.h>
32 #ifdef CONFIG_PM_RUNTIME
33 #include <linux/pm_runtime.h>
35 #include <linux/semaphore.h>
36 #include <linux/vmalloc.h>
37 #include <linux/workqueue.h>
40 #include <soc/sprd/irqs.h>
41 #include <soc/sprd/sci.h>
42 #include <soc/sprd/sci_glb_regs.h>
44 #include <soc/sprd/sci.h>
45 #include <soc/sprd/sci_glb_regs.h>
49 #include "mali_executor.h"
50 #include "mali_kernel_common.h"
51 #include "mali_kernel_linux.h"
54 #define GPU_GLITCH_FREE_DFS 0
56 #define UP_THRESHOLD 9/10
57 #define DOWN_THRESHOLD 5/10
59 #define __SPRD_GPU_TIMEOUT (3*1000)
61 struct gpu_freq_info {
68 struct gpu_dfs_context {
72 struct clk *gpu_clock;
73 struct clk *gpu_clock_i;
74 struct clk **gpu_clk_src;
79 struct gpu_freq_info *freq_list;
82 const struct gpu_freq_info *freq_cur;
83 const struct gpu_freq_info *freq_next;
85 const struct gpu_freq_info *freq_min;
86 const struct gpu_freq_info *freq_max;
87 const struct gpu_freq_info *freq_default;
88 const struct gpu_freq_info *freq_9;
89 const struct gpu_freq_info *freq_8;
90 const struct gpu_freq_info *freq_7;
91 const struct gpu_freq_info *freq_5;
92 const struct gpu_freq_info *freq_range_max;
93 const struct gpu_freq_info *freq_range_min;
95 struct workqueue_struct *gpu_dfs_workqueue;
96 struct semaphore* sem;
99 extern int gpu_boost_level;
100 extern int gpu_boost_sf_level;
102 extern int gpu_freq_cur;
103 extern int gpu_freq_min_limit;
104 extern int gpu_freq_max_limit;
105 extern char* gpu_freq_list;
107 extern _mali_osk_errcode_t mali_executor_initialize(void);
108 extern void mali_executor_lock(void);
109 extern void mali_executor_unlock(void);
111 static void gpu_dfs_func(struct work_struct *work);
112 static void mali_platform_utilization(struct mali_gpu_utilization_data *data);
114 static DECLARE_WORK(gpu_dfs_work, &gpu_dfs_func);
116 DEFINE_SEMAPHORE(gpu_dfs_sem);
118 static struct gpu_dfs_context gpu_dfs_ctx = {
122 struct mali_gpu_device_data mali_gpu_data = {
123 .shared_mem_size = ARCH_MALI_MEMORY_SIZE_DEFAULT,
124 .control_interval = 100,
125 .utilization_callback = mali_platform_utilization,
126 .get_clock_info = NULL,
131 static void gpu_freq_list_show(char *buf)
133 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
136 for (i = 0; i < ctx->freq_list_len; i++)
137 buf += sprintf(buf, "%2d %6d\n", i, ctx->freq_list[i].freq);
140 static int sprd_gpu_domain_state(void)
142 /* FIXME: rtc domain */
143 unsigned int power_state1, power_state2, power_state3;
144 unsigned long timeout = jiffies + msecs_to_jiffies(__SPRD_GPU_TIMEOUT);
148 power_state1 = sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG,
149 BITS_PD_GPU_TOP_STATE(-1));
150 power_state2 = sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG,
151 BITS_PD_GPU_TOP_STATE(-1));
152 power_state3 = sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG,
153 BITS_PD_GPU_TOP_STATE(-1));
154 if (time_after(jiffies, timeout)) {
155 pr_emerg("gpu domain not ready, state %08x %08x\n",
156 sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, -1),
157 sci_glb_read(REG_AON_APB_APB_EB0, -1));
159 } while ((power_state1 != power_state2) ||
160 (power_state2 != power_state3));
162 return (int)(power_state1);
165 static void sprd_gpu_domain_wait_for_ready(void)
167 int timeout_count = 2000;
169 while (sprd_gpu_domain_state() != BITS_PD_GPU_TOP_STATE(0)) {
170 if (!timeout_count) {
172 "gpu domain not ready too long time, state %08x %08x\n",
173 sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, -1),
174 sci_glb_read(REG_AON_APB_APB_EB0, -1));
182 static inline void mali_set_div(int clock_div)
184 sci_glb_write(REG_GPU_APB_APB_CLK_CTRL, BITS_CLK_GPU_DIV(clock_div - 1),
185 BITS_CLK_GPU_DIV(3));
188 static inline void mali_power_on(void)
190 sci_glb_clr(REG_PMU_APB_PD_GPU_TOP_CFG, BIT_PD_GPU_TOP_FORCE_SHUTDOWN);
192 mali_executor_lock();
193 gpu_dfs_ctx.gpu_power_on = 1;
194 mali_executor_unlock();
197 static inline void mali_power_off(void)
199 mali_executor_lock();
200 gpu_dfs_ctx.gpu_power_on = 0;
201 mali_executor_unlock();
202 sci_glb_set(REG_PMU_APB_PD_GPU_TOP_CFG, BIT_PD_GPU_TOP_FORCE_SHUTDOWN);
205 static inline void mali_clock_on(void)
207 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
210 for (i = 0; i < ctx->gpu_clk_num; i++) {
211 #ifdef CONFIG_COMMON_CLK
212 clk_prepare_enable(ctx->gpu_clk_src[i]);
214 clk_enable(ctx->gpu_clk_src[i]);
218 #ifdef CONFIG_COMMON_CLK
219 clk_prepare_enable(ctx->gpu_clock_i);
221 clk_enable(ctx->gpu_clock_i);
223 sprd_gpu_domain_wait_for_ready();
225 clk_set_parent(ctx->gpu_clock, ctx->freq_default->clk_src);
227 MALI_DEBUG_ASSERT(ctx->freq_cur);
228 clk_set_parent(ctx->gpu_clock, ctx->freq_cur->clk_src);
229 mali_set_div(ctx->freq_cur->div);
231 #ifdef CONFIG_COMMON_CLK
232 clk_prepare_enable(ctx->gpu_clock);
234 clk_enable(ctx->gpu_clock);
238 mali_executor_lock();
239 ctx->gpu_clock_on = 1;
240 mali_executor_unlock();
242 gpu_freq_cur = ctx->freq_cur->freq;
243 #ifdef CONFIG_SYSTEM_LOAD_ANALYZER
244 store_external_load_factor(GPU_FREQ, gpu_freq_cur);
248 static inline void mali_clock_off(void)
250 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
254 #ifdef CONFIG_SYSTEM_LOAD_ANALYZER
255 store_external_load_factor(GPU_UTILIZATION, 0);
256 store_external_load_factor(GPU_FREQ, gpu_freq_cur);
259 mali_executor_lock();
260 ctx->gpu_clock_on = 0;
261 mali_executor_unlock();
263 #ifdef CONFIG_COMMON_CLK
264 clk_disable_unprepare(ctx->gpu_clock);
265 clk_disable_unprepare(ctx->gpu_clock_i);
267 clk_disable(ctx->gpu_clock);
268 clk_disable(ctx->gpu_clock_i);
271 for (i = 0; i < ctx->gpu_clk_num; i++) {
272 #ifdef CONFIG_COMMON_CLK
273 clk_disable_unprepare(ctx->gpu_clk_src[i]);
275 clk_disable(ctx->gpu_clk_src[i]);
280 int mali_platform_device_init(struct platform_device *pdev)
282 #ifndef CONFIG_SCX35L64BIT_FPGA /* not use fpga */
283 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
285 #ifdef CONFIG_ARCH_SCX30G
286 int clksrc_300m_idx = -1;
288 #ifdef CONFIG_MALI_DT
289 extern struct of_device_id base_dt_ids[];
290 struct device_node *np;
293 np = of_find_matching_node(NULL, base_dt_ids);
297 ctx->gpu_clock_i = of_clk_get(np, 0);
298 MALI_DEBUG_ASSERT(ctx->gpu_clock_i);
299 ctx->gpu_clock = of_clk_get(np, 1);
300 MALI_DEBUG_ASSERT(ctx->gpu_clock);
302 clk_cnt = of_property_count_strings(np, "clock-names");
303 ctx->gpu_clk_num = clk_cnt - 2;
304 ctx->gpu_clk_src = vmalloc(sizeof(struct clk *) * ctx->gpu_clk_num);
305 MALI_DEBUG_ASSERT(ctx->gpu_clk_src);
307 for (i = 0; i < ctx->gpu_clk_num; i++) {
308 const char *clk_name;
310 of_property_read_string_index(np, "clock-names", i + 2,
312 ctx->gpu_clk_src[i] = of_clk_get_by_name(np, clk_name);
313 MALI_DEBUG_ASSERT(ctx->gpu_clk_src[i]);
314 #ifdef CONFIG_ARCH_SCX30G
315 if (!strcmp(clk_name, "clk_300m_gpu_gate"))
320 of_property_read_u32(np, "freq-list-len", &ctx->freq_list_len);
322 vmalloc(sizeof(struct gpu_freq_info) * ctx->freq_list_len);
323 MALI_DEBUG_ASSERT(ctx->freq_list);
325 for (i = 0; i < ctx->freq_list_len; i++) {
328 of_property_read_u32_index(np, "freq-lists", 3 * i + 1, &clk);
329 ctx->freq_list[i].clk_src = ctx->gpu_clk_src[clk - 2];
330 MALI_DEBUG_ASSERT(ctx->freq_list[i].clk_src);
331 of_property_read_u32_index(np, "freq-lists", 3 * i,
332 &ctx->freq_list[i].freq);
333 of_property_read_u32_index(np, "freq-lists", 3 * i + 2,
334 &ctx->freq_list[i].div);
335 ctx->freq_list[i].up_threshold =
336 ctx->freq_list[i].freq * UP_THRESHOLD;
339 of_property_read_u32(np, "freq-default", &i);
340 ctx->freq_default = &ctx->freq_list[i];
341 MALI_DEBUG_ASSERT(ctx->freq_default);
343 of_property_read_u32(np, "freq-9", &i);
344 ctx->freq_9 = &ctx->freq_list[i];
345 MALI_DEBUG_ASSERT(ctx->freq_9);
347 of_property_read_u32(np, "freq-8", &i);
348 ctx->freq_8 = &ctx->freq_list[i];
349 MALI_DEBUG_ASSERT(ctx->freq_8);
351 of_property_read_u32(np, "freq-7", &i);
352 ctx->freq_7 = &ctx->freq_list[i];
353 MALI_DEBUG_ASSERT(ctx->freq_7);
355 of_property_read_u32(np, "freq-5", &i);
356 ctx->freq_5 = &ctx->freq_list[i];
357 MALI_DEBUG_ASSERT(ctx->freq_5);
359 of_property_read_u32(np, "freq-range-max", &i);
360 ctx->freq_range_max = &ctx->freq_list[i];
361 MALI_DEBUG_ASSERT(ctx->freq_range_max);
363 of_property_read_u32(np, "freq-range-min", &i);
364 ctx->freq_range_min = &ctx->freq_list[i];
365 MALI_DEBUG_ASSERT(ctx->freq_range_min);
369 ctx->freq_max = ctx->freq_range_max;
370 ctx->freq_min = ctx->freq_range_min;
371 ctx->freq_cur = ctx->freq_default;
374 sci_glb_write(REG_PMU_APB_PD_GPU_TOP_CFG,
375 BITS_PD_GPU_TOP_PWR_ON_DLY(1), 0xff0000);
376 sci_glb_write(REG_PMU_APB_PD_GPU_TOP_CFG,
377 BITS_PD_GPU_TOP_PWR_ON_SEQ_DLY(1), 0xff00);
378 sci_glb_write(REG_PMU_APB_PD_GPU_TOP_CFG,
379 BITS_PD_GPU_TOP_ISO_ON_DLY(1), 0xff);
384 #ifdef CONFIG_ARCH_SCX30G
385 /* CPU could disable MPLL, so should increase MPLL refcnt */
386 if (clksrc_300m_idx != -1) {
387 #ifdef CONFIG_COMMON_CLK
388 clk_prepare_enable(ctx->gpu_clk_src[clksrc_300m_idx]);
390 clk_enable(ctx->gpu_clk_src[clksrc_300m_idx]);
395 ctx->gpu_dfs_workqueue = create_singlethread_workqueue("gpu_dfs");
397 err = platform_device_add_data(pdev, &mali_gpu_data,
398 sizeof(mali_gpu_data));
400 #ifdef CONFIG_PM_RUNTIME
401 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
402 pm_runtime_set_autosuspend_delay(&(pdev->dev), 50);
403 pm_runtime_use_autosuspend(&(pdev->dev));
405 pm_runtime_enable(&(pdev->dev));
409 gpu_freq_list = vmalloc(sizeof(char) * 256);
410 gpu_freq_list_show(gpu_freq_list);
414 #ifdef CONFIG_MALI_DT
415 if (!of_find_matching_node(NULL, gpu_ids))
418 sci_glb_clr(REG_PMU_APB_PD_GPU_TOP_CFG, BIT_PD_GPU_TOP_FORCE_SHUTDOWN);
422 #endif /* use fpga */
425 int mali_platform_device_deinit(struct platform_device *device)
427 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
429 destroy_workqueue(ctx->gpu_dfs_workqueue);
435 vfree(gpu_freq_list);
436 vfree(ctx->freq_list);
437 vfree(ctx->gpu_clk_src);
442 static int freq_search(struct gpu_freq_info freq_list[], int len, int key)
444 int low = 0, high = len - 1, mid;
449 while (low <= high) {
450 mid = (low + high) / 2;
452 if (key == freq_list[mid].freq)
455 if (key < freq_list[mid].freq)
464 void mali_platform_power_mode_change(int power_mode)
466 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
471 ("Mali power mode change %d, gpu_power_on=%d gpu_clock_on=%d\n",
472 power_mode, ctx->gpu_power_on, ctx->gpu_clock_on));
474 switch (power_mode) {
475 case 0: /* MALI_POWER_MODE_ON */
476 if (!ctx->gpu_power_on) {
478 * The max limit feature is applied only utilization
479 * routine, so GPU can work with max freq even though
482 int max_index = freq_search(ctx->freq_list,
487 ctx->freq_max = &ctx->freq_list[max_index];
489 ctx->freq_cur = ctx->freq_max;
494 if (!ctx->gpu_clock_on)
497 case 1: /* MALI_POWER_MODE_LIGHT_SLEEP */
498 case 2: /* MALI_POWER_MODE_DEEP_SLEEP */
500 if (ctx->gpu_clock_on)
503 if (ctx->gpu_power_on)
511 static void gpu_dfs_func(struct work_struct *work)
513 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
517 if (!ctx->gpu_power_on || !ctx->gpu_clock_on) {
522 if (ctx->freq_next == ctx->freq_cur) {
527 #if !GPU_GLITCH_FREE_DFS
530 #ifdef CONFIG_COMMON_CLK
531 clk_disable_unprepare(ctx->gpu_clock);
533 clk_disable(ctx->gpu_clock);
537 if (ctx->freq_next->clk_src != ctx->freq_cur->clk_src)
538 clk_set_parent(ctx->gpu_clock, ctx->freq_next->clk_src);
540 if (ctx->freq_next->div != ctx->freq_cur->div)
541 mali_set_div(ctx->freq_next->div);
543 ctx->freq_cur = ctx->freq_next;
544 gpu_freq_cur = ctx->freq_cur->freq;
545 #ifdef CONFIG_SYSTEM_LOAD_ANALYZER
546 store_external_load_factor(GPU_FREQ, gpu_freq_cur);
549 #if !GPU_GLITCH_FREE_DFS
550 #ifdef CONFIG_COMMON_CLK
551 clk_prepare_enable(ctx->gpu_clock);
553 clk_enable(ctx->gpu_clock);
564 * DVFS of SPRD implementation
567 #if !SPRD_DFS_ONE_STEP_SCALE_DOWN
568 static const struct gpu_freq_info
569 *get_next_freq(const struct gpu_freq_info *min_freq,
570 const struct gpu_freq_info *max_freq, int target)
572 const struct gpu_freq_info *freq;
574 for (freq = min_freq; freq <= max_freq; freq++) {
575 if (freq->up_threshold > target)
583 static void mali_platform_utilization(struct mali_gpu_utilization_data *data)
585 #ifndef CONFIG_SCX35L64BIT_FPGA /* not use fpga */
586 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
587 int max_index, min_index;
589 ctx->cur_load = data->utilization_gpu;
592 ("GPU_DFS mali_utilization gpu:%d gp:%d pp:%d\n",
593 data->utilization_gpu, data->utilization_gp,
594 data->utilization_pp));
596 ("GPU_DFS gpu_boost_level:%d gpu_boost_sf_level:%d\n",
597 gpu_boost_level, gpu_boost_sf_level));
599 switch (gpu_boost_level) {
601 ctx->freq_max = ctx->freq_min =
602 &ctx->freq_list[ctx->freq_list_len - 1];
605 ctx->freq_max = ctx->freq_min = ctx->freq_9;
608 ctx->freq_max = ctx->freq_min = ctx->freq_7;
611 ctx->freq_max = ctx->freq_min = ctx->freq_5;
615 ctx->freq_max = ctx->freq_range_max;
616 ctx->freq_min = ctx->freq_range_min;
620 if (!gpu_boost_level && (gpu_boost_sf_level > 0)) {
621 ctx->freq_max = ctx->freq_min =
622 &ctx->freq_list[ctx->freq_list_len - 1];
626 gpu_boost_sf_level = 0;
629 * SPRD_MATCH_DFS_TO_LOWER_FREQ
631 * If user uses gpufreq_min/max_limit sysfs node, it is possible that
632 * the minimum DFS frequency is higher than the maximum one.
633 * So we should correct this inversion phenomenon and there are two
634 * possible solutions.
635 * The first one is to change the minimum DFS frequency as the maximum
636 * one and is suitable for power-saving mode which requires to keep
637 * minimum frequency always.
638 * The other one is to change the maximum DFS frequency as the minimum
639 * one and is suitable for performance mode which requires to keep
640 * maximum frequency always.
644 min_index = freq_search(ctx->freq_list, ctx->freq_list_len,
646 if ((min_index >= 0) &&
647 (ctx->freq_min->freq < ctx->freq_list[min_index].freq)) {
648 ctx->freq_min = &ctx->freq_list[min_index];
649 #if !SPRD_MATCH_DFS_TO_LOWER_FREQ
650 if (ctx->freq_min->freq > ctx->freq_max->freq)
651 ctx->freq_max = ctx->freq_min;
656 max_index = freq_search(ctx->freq_list, ctx->freq_list_len,
658 if ((max_index >= 0) &&
659 (ctx->freq_max->freq > ctx->freq_list[max_index].freq)) {
660 ctx->freq_max = &ctx->freq_list[max_index];
661 #if SPRD_MATCH_DFS_TO_LOWER_FREQ
662 if (ctx->freq_max->freq < ctx->freq_min->freq)
663 ctx->freq_min = ctx->freq_max;
668 * Scale up to maximum frequency if current load ratio is equal or
669 * greater than UP_THRESHOLD.
671 if (ctx->cur_load >= (256 * UP_THRESHOLD)) {
672 ctx->freq_next = ctx->freq_max;
674 MALI_DEBUG_PRINT(3, ("GPU_DFS util %3d; next_freq %6d\n",
675 ctx->cur_load, ctx->freq_next->freq));
677 int target_freq = ctx->freq_cur->freq * ctx->cur_load / 256;
678 #if SPRD_DFS_ONE_STEP_SCALE_DOWN
680 * Scale down one step if current load ratio is equal or less
681 * than DOWN_THRESHOLD.
683 ctx->freq_next = ctx->freq_cur;
684 if (ctx->cur_load <= (256 * DOWN_THRESHOLD)) {
685 if (ctx->freq_next != &ctx->freq_list[0])
688 /* Avoid meaningless scale down */
689 if (ctx->freq_next->up_threshold < target_freq)
693 /* Consider limit max & min freq */
694 if (ctx->freq_next->freq > ctx->freq_max->freq)
695 ctx->freq_next = ctx->freq_max;
696 else if (ctx->freq_next->freq < ctx->freq_min->freq)
697 ctx->freq_next = ctx->freq_min;
699 /* Scale down to target frequency */
700 ctx->freq_next = get_next_freq(ctx->freq_min, ctx->freq_max,
705 ("GPU_DFS util %3d; target_freq %6d; cur_freq %6d -> next_freq %6d\n",
706 ctx->cur_load, target_freq, ctx->freq_cur->freq,
707 ctx->freq_next->freq));
710 #ifdef CONFIG_SYSTEM_LOAD_ANALYZER
711 store_external_load_factor(GPU_UTILIZATION, ctx->cur_load);
714 if (ctx->freq_next->freq != ctx->freq_cur->freq)
715 queue_work(ctx->gpu_dfs_workqueue, &gpu_dfs_work);
716 #endif /* not use fpga */
719 bool mali_is_on(void)
721 struct gpu_dfs_context *ctx = &gpu_dfs_ctx;
723 if (ctx->gpu_power_on && ctx->gpu_clock_on)
726 MALI_DEBUG_PRINT(5, ("gpu_power_on = %d, gpu_clock_on = %d\n",
727 ctx->gpu_power_on, ctx->gpu_clock_on));