| /* |
| * ../vendor/amlogic/common/gpu/utgard/platform/meson_bu/mali_dvfs.c |
| * |
| * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| */ |
| |
| /** |
| * @file arm_core_scaling.c |
| * Example core scaling policy. |
| */ |
| |
| #include <linux/version.h> |
| #include <linux/module.h> |
| #include <linux/workqueue.h> |
| #include <linux/mali/mali_utgard.h> |
| #include <mali_kernel_common.h> |
| #include <mali_osk_profiling.h> |
| #include <linux/time.h> |
| |
| //#include <linux/amlogic/amports/gp_pll.h> |
| #include "meson_main2.h" |
| |
| |
| static int currentStep; |
| static int scaling_mode = MALI_PP_FS_SCALING; |
| //static int scaling_mode = MALI_SCALING_DISABLE; |
| //static int scaling_mode = MALI_PP_SCALING; |
| |
| //static struct gp_pll_user_handle_s *gp_pll_user_gpu; |
| //static int is_gp_pll_get; |
| //static int is_gp_pll_put; |
| |
| static unsigned scaling_dbg_level = 0; |
| module_param(scaling_dbg_level, uint, 0644); |
| MODULE_PARM_DESC(scaling_dbg_level , "scaling debug level"); |
| |
| static mali_plat_info_t* pmali_plat = NULL; |
| static struct workqueue_struct *mali_scaling_wq = NULL; |
| //static DEFINE_SPINLOCK(lock); |
| |
| static int cur_gpu_clk_index = 0; |
| static int exec_gpu_clk_index = 0; |
| #define scalingdbg(level, fmt, arg...) \ |
| do { \ |
| if (scaling_dbg_level >= (level)) \ |
| printk(fmt , ## arg); \ |
| } while (0) |
| |
| struct mali_gpu_clock meson_gpu_clk_info = { |
| .item = NULL, |
| .num_of_steps = 0, |
| }; |
| |
| u32 revise_set_clk(u32 val, u32 flush) |
| { |
| u32 ret = 0; |
| return ret; |
| } |
| |
| void get_mali_rt_clkpp(u32* clk, u32* pp) |
| { |
| } |
| |
| u32 set_mali_rt_clkpp(u32 clk, u32 pp, u32 flush) |
| { |
| u32 ret = 0; |
| return ret; |
| } |
| |
| void revise_mali_rt(void) |
| { |
| } |
| |
| static void do_scaling(struct work_struct *work) |
| { |
| //unsigned long flags; |
| mali_plat_info_t *pinfo = container_of(work, struct mali_plat_info_t, wq_work); |
| |
| *pinfo = *pinfo; |
| //mali_dev_pause(); |
| //spin_lock_irqsave(&lock, flags); |
| mali_clock_set(exec_gpu_clk_index); |
| cur_gpu_clk_index = exec_gpu_clk_index; |
| //spin_unlock_irqrestore(&lock, flags); |
| //mali_dev_resume(); |
| } |
| void flush_scaling_job(void) |
| { |
| if (mali_scaling_wq == NULL) return; |
| |
| flush_workqueue(mali_scaling_wq); |
| printk("%s, %d\n", __func__, __LINE__); |
| } |
| |
| |
| int mali_core_scaling_init(mali_plat_info_t *mali_plat) |
| { |
| pmali_plat = mali_plat; |
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) |
| mali_scaling_wq = alloc_workqueue("gpu_scaling_wq", WQ_HIGHPRI | WQ_UNBOUND, 0); |
| #else |
| mali_scaling_wq = create_workqueue("gpu_scaling_wq"); |
| #endif |
| INIT_WORK(&pmali_plat->wq_work, do_scaling); |
| if (mali_scaling_wq == NULL) printk("Unable to create gpu scaling workqueue\n"); |
| |
| meson_gpu_clk_info.num_of_steps = pmali_plat->scale_info.maxclk; |
| |
| return 0; |
| } |
| |
| void mali_core_scaling_term(void) |
| { |
| flush_scaling_job(); |
| destroy_workqueue(mali_scaling_wq); |
| mali_scaling_wq = NULL; |
| } |
| |
| void mali_pp_scaling_update(struct mali_gpu_utilization_data *data) |
| { |
| } |
| |
| void mali_pp_fs_scaling_update(struct mali_gpu_utilization_data *data) |
| { |
| } |
| |
| u32 get_mali_schel_mode(void) |
| { |
| return scaling_mode; |
| } |
| |
| void set_mali_schel_mode(u32 mode) |
| { |
| scaling_mode = mode; |
| if (scaling_mode == MALI_TURBO_MODE) { |
| printk ("turbo mode\n"); |
| pmali_plat->limit_on = 0; |
| meson_gpu_clk_info.num_of_steps = pmali_plat->turbo_clock; |
| } else { |
| printk ("not turbo mode\n"); |
| pmali_plat->limit_on = 1; |
| meson_gpu_clk_info.num_of_steps = pmali_plat->scale_info.maxclk; |
| } |
| |
| printk("total_enable_steps = %d\n", meson_gpu_clk_info.num_of_steps); |
| } |
| |
| u32 get_current_frequency(void) |
| { |
| return get_mali_freq(currentStep); |
| } |
| |
| void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data) |
| { |
| } |
| |
| void mali_dev_restore(void) |
| { |
| //TO add this |
| //mali_perf_set_num_pp_cores(num_cores_enabled); |
| if (pmali_plat && pmali_plat->pdev) { |
| mali_clock_init_clk_tree(pmali_plat->pdev); |
| } else { |
| printk("error: init clock failed, pmali_plat=%p, pmali_plat->pdev=%p\n", |
| pmali_plat, pmali_plat == NULL ? NULL: pmali_plat->pdev); |
| } |
| } |
| |
| /* Function that platfrom report it's clock info which driver can set, needed when CONFIG_MALI_DVFS enabled */ |
| static void meson_platform_get_clock_info(struct mali_gpu_clock **data) { |
| if (pmali_plat) { |
| meson_gpu_clk_info.item = pmali_plat->clk_items; |
| meson_gpu_clk_info.num_of_steps = pmali_plat->scale_info.maxclk; |
| printk("get clock info\n"); |
| } else { |
| printk("error pmali_plat is null"); |
| } |
| *data = &meson_gpu_clk_info; |
| } |
| |
| /* Function that get the current clock info, needed when CONFIG_MALI_DVFS enabled */ |
| static int meson_platform_get_freq(void) { |
| scalingdbg(1, "cur_gpu_clk_index =%d\n", cur_gpu_clk_index); |
| //dynamically changed the num of steps; |
| return cur_gpu_clk_index; |
| } |
| |
| /* Fuction that platform callback for freq setting, needed when CONFIG_MALI_DVFS enabled */ |
| static int meson_platform_set_freq(int setting_clock_step) { |
| |
| if (exec_gpu_clk_index == setting_clock_step) { |
| return 0; |
| } |
| |
| queue_work(mali_scaling_wq, &pmali_plat->wq_work); |
| exec_gpu_clk_index = setting_clock_step; |
| scalingdbg(1, "set cur_gpu_clk_index =%d\n", cur_gpu_clk_index); |
| return 0; |
| } |
| |
| int mali_meson_get_gpu_data(struct mali_gpu_device_data *mgpu_data) |
| { |
| mgpu_data->get_clock_info = meson_platform_get_clock_info, |
| mgpu_data->get_freq = meson_platform_get_freq, |
| mgpu_data->set_freq = meson_platform_set_freq, |
| mgpu_data->utilization_callback = NULL; |
| return 0; |
| } |