blob: d16675ef03850acab3551f070aceca61edb924e0 [file] [log] [blame]
/*
* platform.c
*
* clock source setting and resource config
*
* Created on: Dec 4, 2013
* Author: amlogic
*/
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/module.h> /* kernel module definitions */
#include <linux/ioport.h> /* request_mem_region */
#include <linux/slab.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 29))
#include <mach/register.h>
#include <mach/irqs.h>
#include <mach/io.h>
#endif
#include <asm/io.h>
#ifdef CONFIG_GPU_THERMAL
#include <linux/gpu_cooling.h>
#include <linux/gpucore_cooling.h>
#include <linux/amlogic/aml_thermal_hw.h>
#endif
#include "mali_scaling.h"
#include "mali_clock.h"
#include "meson_main2.h"
/*
* For Meson 8 M2.
*
*/
static void mali_plat_preheat(void);
static mali_plat_info_t mali_plat_data = {
.bst_gpu = 210, /* threshold for boosting gpu. */
.bst_pp = 160, /* threshold for boosting PP. */
.have_switch = 1,
.limit_on = 1,
.plat_preheat = mali_plat_preheat,
};
static void mali_plat_preheat(void)
{
#ifndef CONFIG_MALI_DVFS
u32 pre_fs;
u32 clk, pp;
if (get_mali_schel_mode() != MALI_PP_FS_SCALING)
return;
get_mali_rt_clkpp(&clk, &pp);
pre_fs = mali_plat_data.def_clock + 1;
if (clk < pre_fs)
clk = pre_fs;
if (pp < mali_plat_data.sc_mpp)
pp = mali_plat_data.sc_mpp;
set_mali_rt_clkpp(clk, pp, 1);
#endif
}
mali_plat_info_t* get_mali_plat_data(void) {
return &mali_plat_data;
}
int get_mali_freq_level(int freq)
{
int i = 0, level = -1;
int mali_freq_num;
if (freq < 0)
return level;
mali_freq_num = mali_plat_data.dvfs_table_size - 1;
if (freq < mali_plat_data.clk_sample[0])
level = mali_freq_num-1;
else if (freq >= mali_plat_data.clk_sample[mali_freq_num - 1])
level = 0;
else {
for (i=0; i<mali_freq_num - 1 ;i++) {
if (freq >= mali_plat_data.clk_sample[i] && freq < mali_plat_data.clk_sample[i + 1]) {
level = i;
level = mali_freq_num-level - 1;
break;
}
}
}
return level;
}
unsigned int get_mali_max_level(void)
{
return mali_plat_data.dvfs_table_size - 1;
}
int get_gpu_max_clk_level(void)
{
return mali_plat_data.cfg_clock;
}
#ifdef CONFIG_GPU_THERMAL
static void set_limit_mali_freq(u32 idx)
{
if (mali_plat_data.limit_on == 0)
return;
if (idx > mali_plat_data.turbo_clock || idx < mali_plat_data.scale_info.minclk)
return;
if (idx > mali_plat_data.maxclk_sysfs) {
printk("idx > max freq\n");
return;
}
mali_plat_data.scale_info.maxclk= idx;
revise_mali_rt();
}
static u32 get_limit_mali_freq(void)
{
return mali_plat_data.scale_info.maxclk;
}
#ifdef CONFIG_DEVFREQ_THERMAL
static u32 get_mali_utilization(void)
{
#ifndef MESON_DRV_BRING
return 55;
#else
return (_mali_ukk_utilization_pp() * 100) / 256;
#endif
}
#endif
#endif
#ifdef CONFIG_GPU_THERMAL
static u32 set_limit_pp_num(u32 num)
{
u32 ret = -1;
if (mali_plat_data.limit_on == 0)
goto quit;
if (num > mali_plat_data.cfg_pp ||
num < mali_plat_data.scale_info.minpp)
goto quit;
if (num > mali_plat_data.maxpp_sysfs) {
printk("pp > sysfs set pp\n");
goto quit;
}
mali_plat_data.scale_info.maxpp = num;
revise_mali_rt();
ret = 0;
quit:
return ret;
}
#ifdef CONFIG_DEVFREQ_THERMAL
static u32 mali_get_online_pp(void)
{
unsigned int val;
mali_plat_info_t* pmali_plat = get_mali_plat_data();
val = readl(pmali_plat->reg_base_aobus + 0xf0) & 0xff;
if (val == 0x07) /* No pp is working */
return 0;
#ifndef MESON_DRV_BRING
return 2;
#else
return mali_executor_get_num_cores_enabled();
#endif
}
#endif
#endif
int mali_meson_init_start(struct platform_device* ptr_plt_dev)
{
//dev_set_drvdata(&ptr_plt_dev->dev, &mali_plat_data);
mali_dt_info(ptr_plt_dev, &mali_plat_data);
mali_clock_init_clk_tree(ptr_plt_dev);
return 0;
}
int mali_meson_init_finish(struct platform_device* ptr_plt_dev)
{
if (mali_core_scaling_init(&mali_plat_data) < 0)
return -1;
return 0;
}
int mali_meson_uninit(struct platform_device* ptr_plt_dev)
{
mali_core_scaling_term();
return 0;
}
void mali_post_init(void)
{
#ifdef CONFIG_GPU_THERMAL
int err;
struct gpufreq_cooling_device *gcdev = NULL;
struct gpucore_cooling_device *gccdev = NULL;
gcdev = gpufreq_cooling_alloc();
register_gpu_freq_info(get_current_frequency);
if (IS_ERR(gcdev))
printk("malloc gpu cooling buffer error!!\n");
else if (!gcdev)
printk("system does not enable thermal driver\n");
else {
gcdev->get_gpu_freq_level = get_mali_freq_level;
gcdev->get_gpu_max_level = get_mali_max_level;
gcdev->set_gpu_freq_idx = set_limit_mali_freq;
gcdev->get_gpu_current_max_level = get_limit_mali_freq;
#ifdef CONFIG_DEVFREQ_THERMAL
gcdev->get_gpu_freq = get_mali_freq;
gcdev->get_gpu_loading = get_mali_utilization;
gcdev->get_online_pp = mali_get_online_pp;
#endif
err = gpufreq_cooling_register(gcdev);
#ifdef CONFIG_DEVFREQ_THERMAL
aml_thermal_min_update(gcdev->cool_dev);
#endif
if (err < 0)
printk("register GPU cooling error\n");
printk("gpu cooling register okay with err=%d\n",err);
}
gccdev = gpucore_cooling_alloc();
if (IS_ERR(gccdev))
printk("malloc gpu core cooling buffer error!!\n");
else if (!gccdev)
printk("system does not enable thermal driver\n");
else {
gccdev->max_gpu_core_num=mali_plat_data.cfg_pp;
gccdev->set_max_pp_num=set_limit_pp_num;
err = (int)gpucore_cooling_register(gccdev);
#ifdef CONFIG_DEVFREQ_THERMAL
aml_thermal_min_update(gccdev->cool_dev);
#endif
if (err < 0)
printk("register GPU cooling error\n");
printk("gpu core cooling register okay with err=%d\n",err);
}
#endif
}