ifeq ($(TARGET_PLATFORM),meson_m450)
ccflags-y += -DCONFIG_MALI450=y
+mali-y += \
+ platform/meson_m450/scaling.o
+
mali-$(CONFIG_ARCH_MESON8) += \
- platform/meson_m450/platform_m8.o \
- platform/meson_m450/scaling_m8.o
+ platform/meson_m450/platform_m8.o
mali-$(CONFIG_ARCH_MESON6TVD) += \
- platform/meson_m450/platform_m6tvd.o \
-
-
+ platform/meson_m450/platform_m6tvd.o
+
mali-$(CONFIG_ARCH_MESON8B) += \
- platform/meson_m450/platform_m8b.o \
- platform/meson_m450/scaling_m8b.o
+ platform/meson_m450/platform_m8b.o
endif
##################### end Kasin Added. ###################
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-
- //#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <mach/am_regs.h>
-#include <linux/module.h>
-//#endif
+#include <linux/types.h>
+#include <mach/cpu.h>
#include "mali_kernel_common.h"
#include "mali_group.h"
#include "mali_osk.h"
}
#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-inline mali_bool mali_group_power_is_on_2(struct mali_group *group)
-{
-#ifdef DEBUG
- if(_mali_osk_lock_get_owner(group->lock) == _mali_osk_get_tid())
- return group->power_is_on;
- else
- return MALI_FALSE;
-#else
- return group->power_is_on;
-#endif
-}
+#define INT_MALI_PP2_MMU ( 6+32)
+struct _mali_osk_irq_t_struct;
+u32 get_irqnum(struct _mali_osk_irq_t_struct* irq);
#endif
-
_mali_osk_errcode_t mali_group_upper_half_mmu(void * data)
{
_mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
MALI_DEBUG_ASSERT_POINTER(mmu);
#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
- if ( MALI_FALSE == mali_group_power_is_on_2(group) )
- {
- if (mmu->id == 2)
- malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
- else if (mmu->id == 3)
- malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
- MALI_DEBUG_PRINT(4, ("Mali MMU: invalid interrupt. <<-- \n"));
+ if (MALI_FALSE == group->power_is_on)
MALI_SUCCESS;
- }
-#endif
-
-#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
- if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) {
- goto out;
+ if (get_irqnum(mmu->irq) == INT_MALI_PP2_MMU)
+ {
+ if (group->pp_core->core_id == 0) {
+ if (malifix_get_mmu_int_process_state(0) == MMU_INT_HIT)
+ malifix_set_mmu_int_process_state(0, MMU_INT_TOP);
+ else
+ MALI_SUCCESS;
+ }
+ else if (group->pp_core->core_id == 1) {
+ if (malifix_get_mmu_int_process_state(1) == MMU_INT_HIT)
+ malifix_set_mmu_int_process_state(1, MMU_INT_TOP);
+ else
+ MALI_SUCCESS;
+ } else
+ MALI_SUCCESS;
}
#endif
return;
}
#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
- if (mmu->id == 2)
- malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
- else if (mmu->id == 3)
- malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
+ if (get_irqnum(mmu->irq) == INT_MALI_PP2_MMU)
+ {
+ if (group->pp_core->core_id == 0) {
+ if (malifix_get_mmu_int_process_state(0) == MMU_INT_TOP)
+ malifix_set_mmu_int_process_state(0, MMU_INT_NONE);
+ }
+ else if (group->pp_core->core_id == 1) {
+ if (malifix_get_mmu_int_process_state(1) == MMU_INT_TOP)
+ malifix_set_mmu_int_process_state(1, MMU_INT_NONE);
+ }
+ }
#endif
mali_group_unlock(group);
mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
if (NULL != mmu)
{
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
- extern int static_pp_mmu_cnt;
- mmu->id = static_pp_mmu_cnt++;
- //MALI_DEBUG_PRINT(3, ("Mali MMU: mmu_id: %d\n", resource->mmu_id));
-#endif
if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) {
if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu)) {
if (is_virtual) {
struct mali_mmu_core {
struct mali_hw_core hw_core; /**< Common for all HW cores */
_mali_osk_irq_t *irq; /**< IRQ handler */
-
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
- u32 id;
-#endif
};
_mali_osk_errcode_t mali_mmu_initialize(void);
static void mali_pp_scheduler_core_scale_up(unsigned int target_core_nr)
{
- MALI_DEBUG_PRINT(2, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores));
+ MALI_DEBUG_PRINT(3, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores));
_mali_osk_pm_dev_ref_add_no_power_on();
_mali_osk_pm_dev_barrier();
static void mali_pp_scheduler_core_scale_down(unsigned int target_core_nr)
{
- MALI_DEBUG_PRINT(2, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr));
+ MALI_DEBUG_PRINT(3, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr));
mali_pp_scheduler_suspend();
* Implementation of the OS abstraction layer for the kernel device driver
*/
+#include <linux/types.h>
+#include <mach/cpu.h>
#include <linux/slab.h> /* For memory allocation */
#include <linux/interrupt.h>
#include <linux/wait.h>
typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *);
static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+u32 get_irqnum(struct _mali_osk_irq_t_struct* irq)
+{
+ if (irq)
+ return irq->irqnum;
+ else
+ return 0;
+}
+#endif
+
#if defined(DEBUG)
#if 0
struct sync_pt *new_pt;
MALI_DEBUG_ASSERT_POINTER(pt);
+
+ if (NULL == pt) {
+ dump_stack();
+ return NULL;
+ }
mpt = to_mali_sync_pt(pt);
new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt));
#include <mach/io.h>
#include <plat/io.h>
#include <asm/io.h>
-
#include "meson_main.h"
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+
#define FCLK_MPLL2 (2 << 9)
-static DEFINE_SPINLOCK(lock);
+static DEFINE_SPINLOCK(lock);
+static mali_plat_info_t* pmali_plat = NULL;
static u32 mali_extr_backup = 0;
+static u32 mali_extr_sample_backup = 0;
-#if MESON_CPU_TYPE > MESON_CPU_TYPE_MESON8
-#define HAVE_MALI_CLOCK_SWITCH 1
-#endif
-
-int mali_clock_init(u32 def_clk_idx)
+int mali_clock_init(mali_plat_info_t* mali_plat)
{
-#ifdef HAVE_MALI_CLOCK_SWITCH
- writel((mali_dvfs_clk[def_clk_idx]<<16)|(mali_dvfs_clk[def_clk_idx]<<16), (u32*)P_HHI_MALI_CLK_CNTL);
- setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 24);
- setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
-#else
- mali_clock_set(def_clk_idx);
-#endif
-#if MESON_CPU_TYPE > MESON_CPU_TYPE_MESON8
- mali_extr_backup = mali_dvfs_clk[get_mali_tbl_size() -1];
-#endif
+ u32 def_clk_data;
+ if (mali_plat == NULL) {
+ printk(" Mali platform data is NULL!!!\n");
+ return -1;
+ }
+
+ pmali_plat = mali_plat;
+ if (pmali_plat->have_switch) {
+ def_clk_data = pmali_plat->clk[pmali_plat->def_clock];
+ writel(def_clk_data | (def_clk_data << 16), (u32*)P_HHI_MALI_CLK_CNTL);
+ setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 24);
+ setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
+ } else {
+ mali_clock_set(pmali_plat->def_clock);
+ }
+
+ mali_extr_backup = pmali_plat->clk[pmali_plat->clk_len - 1];
+ mali_extr_sample_backup = pmali_plat->clk_sample[pmali_plat->clk_len - 1];
return 0;
}
static int critical_clock_set(size_t param)
{
unsigned int idx = param;
-#ifdef HAVE_MALI_CLOCK_SWITCH
- u32 clk_value;
- setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 31);
- clk_value = readl((u32 *)P_HHI_MALI_CLK_CNTL) & 0xffff0000;
- clk_value = clk_value | mali_dvfs_clk[idx] | (1 << 8);
- writel(clk_value, (u32*)P_HHI_MALI_CLK_CNTL);
- clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 31);
-#else
- clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
- clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, (0x7F | (0x7 << 9)));
- writel(mali_dvfs_clk[idx], (u32*)P_HHI_MALI_CLK_CNTL); /* set clock to 333MHZ.*/
- setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
-#endif
+ if (pmali_plat->have_switch) {
+ u32 clk_value;
+ setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 31);
+ clk_value = readl((u32 *)P_HHI_MALI_CLK_CNTL) & 0xffff0000;
+ clk_value = clk_value | pmali_plat->clk[idx] | (1 << 8);
+ writel(clk_value, (u32*)P_HHI_MALI_CLK_CNTL);
+ clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 31);
+ } else {
+ clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
+ clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, (0x7F | (0x7 << 9)));
+ writel(pmali_plat->clk[idx], (u32*)P_HHI_MALI_CLK_CNTL);
+ setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
+ }
return 0;
}
void disable_clock(void)
{
unsigned long flags;
+
spin_lock_irqsave(&lock, flags);
clrbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
spin_unlock_irqrestore(&lock, flags);
void enable_clock(void)
{
- u32 ret = 0;
+ u32 ret;
unsigned long flags;
+
spin_lock_irqsave(&lock, flags);
setbits_le32((u32)P_HHI_MALI_CLK_CNTL, 1 << 8);
ret = readl((u32 *)P_HHI_MALI_CLK_CNTL) & (1 << 8);
u32 get_mali_freq(u32 idx)
{
- return mali_dvfs_clk_sample[idx];
+ return pmali_plat->clk_sample[idx];
}
void set_str_src(u32 data)
{
-#if MESON_CPU_TYPE > MESON_CPU_TYPE_MESON8
if (data == 11) {
writel(0x0004d000, (u32*)P_HHI_MPLL_CNTL9);
} else if (data > 11) {
writel(data, (u32*)P_HHI_MPLL_CNTL9);
}
-
if (data == 0) {
- mali_dvfs_clk[get_mali_tbl_size() -1] = mali_extr_backup;
+ pmali_plat->clk[pmali_plat->clk_len - 1] = mali_extr_backup;
+ pmali_plat->clk_sample[pmali_plat->clk_len - 1] = mali_extr_sample_backup;
} else if (data > 10) {
- mali_dvfs_clk[get_mali_tbl_size() -1] = FCLK_MPLL2;
+ pmali_plat->clk_sample[pmali_plat->clk_len - 1] = 600;
+ pmali_plat->clk[pmali_plat->clk_len - 1] = FCLK_MPLL2;
}
-#endif
}
+#endif
typedef int (*critical_t)(size_t param);
int mali_clock_critical(critical_t critical, size_t param);
-int mali_clock_init(u32 def_clk_idx);
+int mali_clock_init(mali_plat_info_t*);
int mali_clock_set(unsigned int index);
void disable_clock(void);
void enable_clock(void);
#ifndef __ARM_CORE_SCALING_H__
#define __ARM_CORE_SCALING_H__
+enum mali_scale_mode_t {
+ MALI_PP_SCALING = 0,
+ MALI_PP_FS_SCALING,
+ MALI_SCALING_DISABLE,
+ MALI_TURBO_MODE,
+ MALI_SCALING_MODE_MAX
+};
+
typedef struct mali_dvfs_threshold_table {
unsigned int freq_index;
unsigned int voltage;
unsigned int keep_count;
unsigned int downthreshold;
unsigned int upthreshold;
-} mali_dvfs_threshold_table_t;
+} mali_dvfs_threshold_table;
+
+/**
+ * restrictions on frequency and number of pp.
+ */
+typedef struct mali_scale_info_t {
+ u32 minpp;
+ u32 maxpp;
+ u32 minclk;
+ u32 maxclk;
+} mali_scale_info_t;
+
+/**
+ * Platform spesific data for meson chips.
+ */
+typedef struct mali_plat_info_t {
+ u32 cfg_pp; /* number of pp. */
+ u32 cfg_min_pp;
+ u32 turbo_clock; /* reserved clock src. */
+ u32 def_clock; /* gpu clock used most of time.*/
+ u32 cfg_clock; /* max clock could be used.*/
+ u32 cfg_min_clock;
+
+ u32 sc_mpp; /* number of pp used most of time.*/
+ u32 bst_gpu; /* threshold for boosting gpu. */
+ u32 bst_pp; /* threshold for boosting PP. */
+
+ u32 *clk;
+ u32 *clk_sample;
+ u32 clk_len;
+ u32 have_switch; /* have clock gate switch or not. */
+
+ mali_dvfs_threshold_table *dvfs_table;
+ u32 dvfs_table_size;
+
+ mali_scale_info_t scale_info;
+
+ /* set upper limit of pp or frequency, for THERMAL thermal or band width saving.*/
+ u32 limit_on;
+
+ /* for boost up gpu by user. */
+ void (*plat_preheat)(void);
+} mali_plat_info_t;
+mali_plat_info_t* get_mali_plat_data(void);
/**
* Initialize core scaling policy.
*
* @param num_pp_cores Total number of PP cores.
*/
-void mali_core_scaling_init(int pp, int clock_idx);
+int mali_core_scaling_init(mali_plat_info_t*);
/**
* Terminate core scaling policy.
*/
void mali_core_scaling_term(void);
-/**
- * Update core scaling policy with new utilization data.
- *
- * @param data Utilization data.
- */
-
/**
* cancel and flush scaling job queue.
*/
void flush_scaling_job(void);
-u32 set_mali_dvfs_tbl_size(u32 size);
-u32 get_max_dvfs_tbl_size(void);
-uint32_t* get_mali_dvfs_tbl_addr(void);
-
-/* get or set the max/min number of pp cores. */
-u32 get_max_pp_num(void);
-u32 set_max_pp_num(u32 num);
-u32 get_min_pp_num(void);
-u32 set_min_pp_num(u32 num);
-
-/* get or set the max/min frequency of GPU. */
-u32 get_max_mali_freq(void);
-u32 set_max_mali_freq(u32 idx);
-u32 get_min_mali_freq(void);
-u32 set_min_mali_freq(u32 idx);
+/* get current state(pp, clk). */
+void get_mali_rt_clkpp(u32* clk, u32* pp);
+u32 set_mali_rt_clkpp(u32 clk, u32 pp, u32 flush);
+void revise_mali_rt(void);
/* get or set the scale mode. */
u32 get_mali_schel_mode(void);
void set_mali_schel_mode(u32 mode);
-/* preheat of the GPU. */
-void mali_plat_preheat(void);
-
/* for frequency reporter in DS-5 streamline. */
u32 get_current_frequency(void);
+
+extern int mali_pm_statue;
#endif /* __ARM_CORE_SCALING_H__ */
static struct mali_dvfs_threshold_table mali_dvfs_threshold[1];
-u32 set_mali_dvfs_tbl_size(u32 size)
-{
- return 0;
-}
-
-u32 get_max_dvfs_tbl_size(void)
-{
- return 0;
-}
-
-uint32_t* get_mali_dvfs_tbl_addr(void)
-{
- return mali_dvfs_threshold;
-}
-
-
-
#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TV
#undef INT_MALI_GP
#undef INT_MALI_GP_MMU
#elif MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
-int static_pp_mmu_cnt;
-
#undef INT_MALI_GP
#undef INT_MALI_GP_MMU
#undef INT_MALI_PP
}
+mali_plat_info_t mali_plat_data = {
+
+};
+
int mali_meson_init_start(struct platform_device* ptr_plt_dev)
{
/* for mali platform data. */
/*
* platform.c
- *
+ *
* clock source setting and resource config
*
* Created on: Dec 4, 2013
#include "meson_main.h"
-/**
- * For Meson 6tvd.
- *
+/*
+ * For Meson 8TVD.
+ *
*/
-#ifdef MESON_CPU_TYPE_MESON6TVD
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TVD
-
-u32 mali_clock_turbo_index = 3;
-u32 mali_default_clock_idx = 3;
-u32 mali_up_clock_idx = 3;
+#define CFG_PP 2
+#define CFG_CLOCK 3
+#define CFG_MIN_PP 1
+#define CFG_MIN_CLOCK 0
/* fclk is 2Ghz. */
#define FCLK_DEV5 (7 << 9) /* 400 Mhz */
};
u32 mali_dvfs_clk_sample[] = {
- 182, /* 182.1 Mhz */
- 319, /* 318.7 Mhz */
- 425, /* 425 Mhz */
- 510, /* 510 Mhz */
- 637, /* 637.5 Mhz */
+ 100, /* 182.1 Mhz */
+ 200, /* 318.7 Mhz */
+ 333, /* 425 Mhz */
+ 400, /* 510 Mhz */
+};
+
+static mali_plat_info_t mali_plat_data = {
+ .cfg_pp = CFG_PP, /* number of pp. */
+ .cfg_min_pp = CFG_MIN_PP,
+ .def_clock = CFG_CLOCK, /* gpu clock used most of time.*/
+ .cfg_clock = CFG_CLOCK, /* max gpu clock. */
+ .cfg_min_clock = CFG_MIN_CLOCK,
+
+ .clk = mali_dvfs_clk, /* clock source table. */
+ .clk_sample = mali_dvfs_clk_sample, /* freqency table for show. */
+ .clk_len = sizeof(mali_dvfs_clk) / sizeof(mali_dvfs_clk[0]),
+ .have_switch = 0,
};
-#define MALI_PP_NUMBER 2
#define MALI_USER_PP0 AM_IRQ4(31)
static struct resource mali_gpu_resources[] =
{
ptr_plt_dev->num_resources = ARRAY_SIZE(mali_gpu_resources);
ptr_plt_dev->resource = mali_gpu_resources;
- return mali_clock_init(mali_default_clock_idx);
+ return mali_clock_init(&mali_plat_data);
}
int mali_meson_init_finish(struct platform_device* ptr_plt_dev)
return 0;
}
-u32 set_mali_dvfs_tbl_size(u32 size)
-{
- return 0;
-}
-
-u32 get_max_dvfs_tbl_size(void)
-{
- return 0;
-}
-
-uint32_t* get_mali_dvfs_tbl_addr(void)
-{
- return NULL;
-}
-
-void mali_core_scaling_term(void)
-{
-
-}
-
static int mali_cri_pmu_on_off(size_t param)
{
struct mali_pmu_core *pmu;
return ret;
}
-#endif /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 */
-#endif /* define MESON_CPU_TYPE_MESON6TVD */
+
*
*/
-#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8
-u32 mali_clock_turbo_index = 4;
-u32 mali_default_clock_idx = 0;
-u32 mali_up_clock_idx = 3;
+#define CFG_PP 6
+#define CFG_CLOCK 3
+#define CFG_MIN_PP 1
+#define CFG_MIN_CLOCK 0
/* fclk is 2550Mhz. */
#define FCLK_DEV3 (6 << 9) /* 850 Mhz */
#define FCLK_DEV5 (7 << 9) /* 510 Mhz */
#define FCLK_DEV7 (4 << 9) /* 364.3 Mhz */
-u32 mali_dvfs_clk[] = {
+static u32 mali_dvfs_clk[] = {
FCLK_DEV7 | 1, /* 182.1 Mhz */
FCLK_DEV4 | 1, /* 318.7 Mhz */
FCLK_DEV3 | 1, /* 425 Mhz */
FCLK_DEV4 | 0, /* 637.5 Mhz */
};
-u32 mali_dvfs_clk_sample[] = {
+static u32 mali_dvfs_clk_sample[] = {
182, /* 182.1 Mhz */
319, /* 318.7 Mhz */
425, /* 425 Mhz */
637, /* 637.5 Mhz */
};
-u32 get_mali_tbl_size(void)
+static mali_dvfs_threshold_table mali_dvfs_table[]={
+ { 0, 0, 3, 70, 180}, /* for 182.1 */
+ { 1, 1, 3, 108, 205}, /* for 318.7 */
+ { 2, 2, 3, 150, 215}, /* for 425.0 */
+ { 3, 3, 3, 170, 253}, /* for 510.0 */
+ { 4, 4, 3, 230, 256}, /* for 637.5 */
+ { 0, 0, 3, 0, 0}
+};
+
+static void mali_plat_preheat(void);
+static mali_plat_info_t mali_plat_data = {
+ .cfg_pp = CFG_PP, /* number of pp. */
+ .cfg_min_pp = CFG_MIN_PP,
+ .turbo_clock = 4, /* reserved clock src. */
+ .def_clock = 2, /* gpu clock used most of time.*/
+ .cfg_clock = CFG_CLOCK, /* max gpu clock. */
+ .cfg_min_clock = CFG_MIN_CLOCK,
+
+ .sc_mpp = 3, /* number of pp used most of time.*/
+ .bst_gpu = 210, /* threshold for boosting gpu. */
+ .bst_pp = 160, /* threshold for boosting PP. */
+
+ .clk = mali_dvfs_clk, /* clock source table. */
+ .clk_sample = mali_dvfs_clk_sample, /* freqency table for show. */
+ .clk_len = sizeof(mali_dvfs_clk) / sizeof(mali_dvfs_clk[0]),
+ .have_switch = 0,
+
+ .dvfs_table = mali_dvfs_table, /* DVFS table. */
+ .dvfs_table_size = sizeof(mali_dvfs_table) / sizeof(mali_dvfs_threshold_table),
+
+ .scale_info = {
+ CFG_MIN_PP, /* minpp */
+ CFG_PP, /* maxpp, should be same as cfg_pp */
+ CFG_MIN_CLOCK, /* minclk */
+ CFG_CLOCK, /* maxclk should be same as cfg_clock */
+ },
+
+ .limit_on = 1,
+ .plat_preheat = mali_plat_preheat,
+};
+
+static void mali_plat_preheat(void)
{
- return sizeof(mali_dvfs_clk) / sizeof(u32);
+ 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);
+}
+
+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;
- int mali_freq_num = sizeof(mali_dvfs_clk_sample) / sizeof(mali_dvfs_clk_sample[0]) - 1;
- if(freq <= mali_dvfs_clk_sample[0])
+ mali_freq_num = mali_plat_data.dvfs_table_size - 1;
+ if(freq <= mali_plat_data.clk_sample[0])
level = mali_freq_num-1;
- if(freq >= mali_dvfs_clk_sample[mali_freq_num - 1])
+ if(freq >= mali_plat_data.clk_sample[mali_freq_num - 1])
level = 0;
for(i=0; i<mali_freq_num - 1 ;i++) {
- if(freq >= mali_dvfs_clk_sample[i] && freq<=mali_dvfs_clk_sample[i+1]) {
+ if(freq >= mali_plat_data.clk_sample[i] && freq<=mali_plat_data.clk_sample[i + 1]) {
level = i;
- level = mali_freq_num-level-1;
+ level = mali_freq_num-level - 1;
}
}
return level;
unsigned int get_mali_max_level(void)
{
- int mali_freq_num = sizeof(mali_dvfs_clk_sample) / sizeof(mali_dvfs_clk_sample[0]);
- return mali_freq_num - 1;
+ return mali_plat_data.dvfs_table_size - 1;
}
-#define MALI_PP_NUMBER 6
-
static struct resource mali_gpu_resources[] =
{
MALI_GPU_RESOURCES_MALI450_MP6_PMU(IO_MALI_APB_PHY_BASE, INT_MALI_GP, INT_MALI_GP_MMU,
INT_MALI_PP)
};
+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;
+ mali_plat_data.scale_info.maxclk= idx;
+ revise_mali_rt();
+}
+
+static u32 get_limit_mali_freq(void)
+{
+ return mali_plat_data.scale_info.maxclk;
+}
+
+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;
+ mali_plat_data.scale_info.maxpp = num;
+ revise_mali_rt();
+ ret = 0;
+quit:
+ return ret;
+}
+
#ifdef CONFIG_AM_VDEC_H264_4K2K
+static u32 grd_pp_bk = CFG_PP;
static void mali_4k2k_enter(void)
{
- set_max_pp_num(1);
+ if (mali_plat_data.limit_on == 0)
+ return;
+ grd_pp_bk = mali_plat_data.scale_info.maxpp;
+ set_limit_pp_num(mali_plat_data.scale_info.minpp);
}
static void mali_4k2k_exit(void)
{
- set_max_pp_num(6);
+ if (mali_plat_data.limit_on == 0)
+ return;
+ set_limit_pp_num(grd_pp_bk);
}
void vh264_4k2k_register_module_callback(void(*enter_func)(void), void(*remove_func)(void));
void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
int mali_meson_init_start(struct platform_device* ptr_plt_dev)
{
-
struct mali_gpu_device_data* pdev = ptr_plt_dev->dev.platform_data;
/* for mali platform data. */
- pdev->utilization_interval = 500,
+ pdev->utilization_interval = 300,
pdev->utilization_callback = mali_gpu_utilization_callback,
/* for resource data. */
ptr_plt_dev->num_resources = ARRAY_SIZE(mali_gpu_resources);
ptr_plt_dev->resource = mali_gpu_resources;
- return mali_clock_init(mali_default_clock_idx);
+ return mali_clock_init(&mali_plat_data);
}
int mali_meson_init_finish(struct platform_device* ptr_plt_dev)
#ifdef CONFIG_GPU_THERMAL
int err;
struct gpufreq_cooling_device *gcdev = NULL;
+ struct gpucore_cooling_device *gccdev = NULL;
+#endif
+ if (mali_core_scaling_init(&mali_plat_data) < 0)
+ return -1;
+
+#ifdef CONFIG_GPU_THERMAL
gcdev = gpufreq_cooling_alloc();
- register_gpu_freq_info(get_current_frequency);
+ register_gpu_freq_info(get_current_frequency);
if(IS_ERR(gcdev))
printk("malloc gpu cooling buffer error!!\n");
else if(!gcdev)
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_max_mali_freq;
- gcdev->get_gpu_current_max_level = get_max_mali_freq;
+ gcdev->set_gpu_freq_idx = set_limit_mali_freq;
+ gcdev->get_gpu_current_max_level = get_limit_mali_freq;
err = gpufreq_cooling_register(gcdev);
if(err < 0)
printk("register GPU cooling error\n");
printk("gpu cooling register okay with err=%d\n",err);
}
-
- struct gpucore_cooling_device *gccdev=NULL;
+
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_PP_NUMBER;
- gccdev->set_max_pp_num=set_max_pp_num;
- err=gpucore_cooling_register(gccdev);
+ 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);
if(err < 0)
printk("register GPU cooling error\n");
printk("gpu core cooling register okay with err=%d\n",err);
}
#endif
- mali_core_scaling_init(MALI_PP_NUMBER, mali_default_clock_idx);
#ifdef CONFIG_AM_VDEC_H264_4K2K
vh264_4k2k_register_module_callback(mali_4k2k_enter, mali_4k2k_exit);
#endif /* CONFIG_AM_VDEC_H264_4K2K */
MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
get_current_frequency(), 0, 0, 0, 0);
#endif
-
return ret;
}
return ret;
}
-#endif /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8 */
#include <mach/io.h>
#include <asm/io.h>
#include <linux/mali/mali_utgard.h>
-
+#include <linux/gpu_cooling.h>
+#include <linux/gpucore_cooling.h>
#include <common/mali_kernel_common.h>
#include <common/mali_osk_profiling.h>
#include <common/mali_pmu.h>
-#include <linux/gpu_cooling.h>
-#include <linux/gpucore_cooling.h>
+
#include "meson_main.h"
-/**
- * For Meson 8.
+/*
+ * For Meson 8B.
*
*/
-
-u32 mali_clock_turbo_index = 4;
-u32 mali_default_clock_idx = 1;
-u32 mali_up_clock_idx = 3;
+
+#define CFG_PP 2
+#define CFG_CLOCK 3
+#define CFG_MIN_PP 1
+#define CFG_MIN_CLOCK 0
/* fclk is 2550Mhz. */
#define FCLK_DEV3 (6 << 9) /* 850 Mhz */
637, /* 637.5 Mhz */
};
-u32 get_mali_tbl_size(void)
+static mali_dvfs_threshold_table mali_dvfs_table[]={
+ { 0, 0, 5, 0 , 180}, /* for 255 */
+ { 1, 1, 5, 152, 205}, /* for 364 */
+ { 2, 2, 5, 180, 212}, /* for 425 */
+ { 3, 3, 5, 205, 236}, /* for 510 */
+ { 4, 4, 5, 230, 256}, /* for 637 */
+ { 0, 0, 5, 0, 0}
+};
+
+static void mali_plat_preheat(void);
+static mali_plat_info_t mali_plat_data = {
+ .cfg_pp = CFG_PP, /* number of pp. */
+ .cfg_min_pp = CFG_MIN_PP,
+ .turbo_clock = 4, /* reserved clock src. */
+ .def_clock = 2, /* gpu clock used most of time.*/
+ .cfg_clock = CFG_CLOCK, /* max gpu clock. */
+ .cfg_min_clock = CFG_MIN_CLOCK,
+
+ .sc_mpp = 2, /* number of pp used most of time.*/
+ .bst_gpu = 210, /* threshold for boosting gpu. */
+ .bst_pp = 160, /* threshold for boosting PP. */
+
+ .clk = mali_dvfs_clk, /* clock source table. */
+ .clk_sample = mali_dvfs_clk_sample, /* freqency table for show. */
+ .clk_len = sizeof(mali_dvfs_clk) / sizeof(mali_dvfs_clk[0]),
+ .have_switch = 1,
+
+ .dvfs_table = mali_dvfs_table, /* DVFS table. */
+ .dvfs_table_size = sizeof(mali_dvfs_table) / sizeof(mali_dvfs_threshold_table),
+
+ .scale_info = {
+ CFG_MIN_PP, /* minpp */
+ CFG_PP, /* maxpp, should be same as cfg_pp */
+ CFG_MIN_CLOCK, /* minclk */
+ CFG_CLOCK, /* maxclk should be same as cfg_clock */
+ },
+
+ .limit_on = 1,
+ .plat_preheat = mali_plat_preheat,
+};
+
+static void mali_plat_preheat(void)
{
- return sizeof(mali_dvfs_clk) / sizeof(u32);
+ 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);
+}
+
+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;
- int mali_freq_num = sizeof(mali_dvfs_clk_sample) / sizeof(mali_dvfs_clk_sample[0]) - 1;
- if(freq <= mali_dvfs_clk_sample[0])
+ mali_freq_num = mali_plat_data.dvfs_table_size - 1;
+ if(freq <= mali_plat_data.clk_sample[0])
level = mali_freq_num-1;
- if(freq >= mali_dvfs_clk_sample[mali_freq_num - 1])
+ if(freq >= mali_plat_data.clk_sample[mali_freq_num - 1])
level = 0;
for(i=0; i<mali_freq_num - 1 ;i++) {
- if(freq >= mali_dvfs_clk_sample[i] && freq<=mali_dvfs_clk_sample[i+1]) {
+ if(freq >= mali_plat_data.clk_sample[i] && freq<=mali_plat_data.clk_sample[i + 1]) {
level = i;
- level = mali_freq_num-level-1;
+ level = mali_freq_num-level - 1;
}
}
return level;
unsigned int get_mali_max_level(void)
{
- int mali_freq_num = sizeof(mali_dvfs_clk_sample) / sizeof(mali_dvfs_clk_sample[0]);
- return mali_freq_num - 1;
+ return mali_plat_data.dvfs_table_size - 1;
}
-#define MALI_PP_NUMBER 2
static struct resource mali_gpu_resources[] =
{
INT_MALI_PP)
};
+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;
+ mali_plat_data.scale_info.maxclk= idx;
+ revise_mali_rt();
+}
+
+static u32 get_limit_mali_freq(void)
+{
+ return mali_plat_data.scale_info.maxclk;
+}
+
+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;
+ mali_plat_data.scale_info.maxpp = num;
+ revise_mali_rt();
+ ret = 0;
+quit:
+ return ret;
+}
+
void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
int mali_meson_init_start(struct platform_device* ptr_plt_dev)
{
/* for resource data. */
ptr_plt_dev->num_resources = ARRAY_SIZE(mali_gpu_resources);
ptr_plt_dev->resource = mali_gpu_resources;
- return mali_clock_init(mali_default_clock_idx);
+ return mali_clock_init(&mali_plat_data);
}
int mali_meson_init_finish(struct platform_device* ptr_plt_dev)
{
- mali_core_scaling_init(MALI_PP_NUMBER, mali_default_clock_idx);
#ifdef CONFIG_GPU_THERMAL
int err;
struct gpufreq_cooling_device *gcdev = NULL;
+#endif
+ if (mali_core_scaling_init(&mali_plat_data) < 0)
+ return -1;
+
+#ifdef CONFIG_GPU_THERMAL
gcdev = gpufreq_cooling_alloc();
if(IS_ERR(gcdev))
printk("malloc gpu cooling buffer error!!\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_max_mali_freq;
- gcdev->get_gpu_current_max_level = get_max_mali_freq;
+ gcdev->set_gpu_freq_idx = set_limit_mali_freq;
+ gcdev->get_gpu_current_max_level = get_limit_mali_freq;
err = gpufreq_cooling_register(gcdev);
if(err < 0)
printk("register GPU cooling error\n");
printk("gpu cooling register okay with err=%d\n",err);
}
-#if 0
- struct gpucore_cooling_device *gccdev=NULL;
- 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_PP_NUMBER;
- gccdev->set_max_pp_num=set_max_pp_num;
- err=gpucore_cooling_register(gccdev);
- if(err < 0)
- printk("register GPU cooling error\n");
- printk("gpu core cooling register okay with err=%d\n",err);
- }
-#endif
+
#endif
return 0;
}
--- /dev/null
+/*
+ * Copyright (C) 2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 "common/mali_osk_profiling.h"
+#include "common/mali_kernel_utilization.h"
+#include "common/mali_pp_scheduler.h"
+
+#include <meson_main.h>
+
+#define LOG_MALI_SCALING 0
+
+static int num_cores_enabled;
+static int currentStep;
+static int lastStep;
+static struct work_struct wq_work;
+static mali_plat_info_t* pmali_plat = NULL;
+static int scaling_mode = MALI_PP_FS_SCALING;
+
+static void do_scaling(struct work_struct *work)
+{
+ mali_dvfs_threshold_table * pdvfs = pmali_plat->dvfs_table;
+ int err = mali_perf_set_num_pp_cores(num_cores_enabled);
+ MALI_DEBUG_ASSERT(0 == err);
+ MALI_IGNORE(err);
+ if (pdvfs[currentStep].freq_index != pdvfs[lastStep].freq_index) {
+ mali_dev_pause();
+ mali_clock_set(pdvfs[currentStep].freq_index);
+ mali_dev_resume();
+ lastStep = currentStep;
+ }
+#ifdef CONFIG_MALI400_PROFILING
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
+ MALI_PROFILING_EVENT_CHANNEL_GPU |
+ MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
+ get_current_frequency(),
+ 0, 0, 0, 0);
+#endif
+}
+
+u32 revise_set_clk(u32 val, u32 flush)
+{
+ mali_scale_info_t* pinfo;
+ u32 ret = 0;
+
+ pinfo = &pmali_plat->scale_info;
+
+ if (val < pinfo->minclk)
+ val = pinfo->minclk;
+ else if (val > pinfo->maxclk)
+ val = pinfo->maxclk;
+
+ if (val != currentStep) {
+ currentStep = val;
+ if (flush)
+ schedule_work(&wq_work);
+ else
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void get_mali_rt_clkpp(u32* clk, u32* pp)
+{
+ *clk = currentStep;
+ *pp = num_cores_enabled;
+}
+
+u32 set_mali_rt_clkpp(u32 clk, u32 pp, u32 flush)
+{
+ mali_scale_info_t* pinfo;
+ u32 ret = 0;
+ u32 flush_work = 0;
+
+ pinfo = &pmali_plat->scale_info;
+ if (clk < pinfo->minclk)
+ clk = pinfo->minclk;
+ else if (clk > pinfo->maxclk)
+ clk = pinfo->maxclk;
+
+ if (clk != currentStep) {
+ currentStep = clk;
+ if (flush)
+ flush_work++;
+ else
+ ret = 1;
+ }
+ if (pp < pinfo->minpp)
+ pp = pinfo->minpp;
+ else if (pp > pinfo->maxpp)
+ pp = pinfo->maxpp;
+
+ if (pp != num_cores_enabled) {
+ num_cores_enabled = pp;
+ if (flush)
+ flush_work++;
+ else
+ ret = 1;
+ }
+
+ if (flush_work)
+ schedule_work(&wq_work);
+ return ret;
+}
+
+void revise_mali_rt(void)
+{
+ set_mali_rt_clkpp(currentStep, num_cores_enabled, 1);
+}
+
+void flush_scaling_job(void)
+{
+ cancel_work_sync(&wq_work);
+}
+
+static u32 enable_one_core(void)
+{
+ return set_mali_rt_clkpp(currentStep, num_cores_enabled + 1, 0);
+}
+
+static u32 disable_one_core(void)
+{
+ return set_mali_rt_clkpp(currentStep, num_cores_enabled - 1, 0);
+}
+
+static u32 enable_max_num_cores(void)
+{
+ return set_mali_rt_clkpp(currentStep, pmali_plat->scale_info.maxpp, 0);
+}
+
+static u32 enable_pp_cores(u32 val)
+{
+ return set_mali_rt_clkpp(currentStep, val, 0);
+}
+
+int mali_core_scaling_init(mali_plat_info_t *mali_plat)
+{
+ if (mali_plat == NULL) {
+ printk(" Mali platform data is NULL!!!\n");
+ return -1;
+ }
+
+ pmali_plat = mali_plat;
+ num_cores_enabled = pmali_plat->sc_mpp;
+
+ currentStep = pmali_plat->def_clock;
+ lastStep = currentStep;
+ INIT_WORK(&wq_work, do_scaling);
+
+ return 0;
+ /* NOTE: Mali is not fully initialized at this point. */
+}
+
+void mali_core_scaling_term(void)
+{
+ flush_scheduled_work();
+}
+
+static u32 mali_threshold [] = {
+ 102, /* 40% */
+ 128, /* 50% */
+ 230, /* 90% */
+};
+
+void mali_pp_scaling_update(struct mali_gpu_utilization_data *data)
+{
+ int ret = 0;
+
+ if (mali_threshold[2] < data->utilization_pp)
+ ret = enable_max_num_cores();
+ else if (mali_threshold[1]< data->utilization_pp)
+ ret = enable_one_core();
+ else if (0 < data->utilization_pp)
+ ret = disable_one_core();
+ if (ret == 1)
+ schedule_work(&wq_work);
+}
+
+#if LOG_MALI_SCALING
+void trace_utilization(struct mali_gpu_utilization_data *data, u32 current_idx, u32 next,
+ u32 current_pp, u32 next_pp)
+{
+ char direction;
+ if (next > current_idx)
+ direction = '>';
+ else if ((current_idx > pmali_plat->scale_info.minpp) && (next < current_idx))
+ direction = '<';
+ else
+ direction = '~';
+
+ printk("[SCALING]%c (%3d-->%3d)@%3d{%3d - %3d}. pp:(%d-->%d)\n",
+ direction,
+ get_mali_freq(current_idx),
+ get_mali_freq(next),
+ data->utilization_gpu,
+ pmali_plat->dvfs_table[current_idx].downthreshold,
+ pmali_plat->dvfs_table[current_idx].upthreshold,
+ current_pp, next_pp);
+}
+#endif
+
+static int mali_stay_count = 0;
+static void mali_decide_next_status(struct mali_gpu_utilization_data *data, int* next_fs_idx,
+ int* pp_change_flag)
+{
+ u32 utilization, mali_up_limit, decided_fs_idx;
+ u32 ld_left, ld_right;
+ u32 ld_up, ld_down;
+ char change_mode;
+
+ *pp_change_flag = 0;
+ change_mode = 0;
+ utilization = data->utilization_gpu;
+
+ mali_up_limit = (scaling_mode == MALI_TURBO_MODE) ?
+ pmali_plat->turbo_clock : pmali_plat->scale_info.maxclk;
+ decided_fs_idx = currentStep;
+
+ ld_up = pmali_plat->dvfs_table[currentStep].upthreshold;
+ ld_down = pmali_plat->dvfs_table[currentStep].downthreshold;
+ if (utilization >= ld_up) { /* go up */
+ if (currentStep < mali_up_limit) {
+ change_mode = 1;
+ if ((currentStep < pmali_plat->def_clock) && (utilization > pmali_plat->bst_gpu))
+ decided_fs_idx = pmali_plat->def_clock;
+ else
+ decided_fs_idx++;
+ }
+ if ((data->utilization_pp > ld_up) &&
+ (num_cores_enabled < pmali_plat->scale_info.maxpp)) {
+ if ((num_cores_enabled < pmali_plat->sc_mpp) && (data->utilization_pp >= pmali_plat->bst_pp)) {
+ *pp_change_flag = 1;
+ change_mode = 1;
+ } else if (change_mode == 0) {
+ *pp_change_flag = 2;
+ change_mode = 1;
+ }
+ }
+ } else if (utilization <= ld_down) { /* go down */
+ if (mali_stay_count > 0) {
+ *next_fs_idx = decided_fs_idx;
+ mali_stay_count--;
+ return;
+ }
+
+ if (num_cores_enabled > pmali_plat->sc_mpp) {
+ change_mode = 1;
+ if (data->utilization_pp <= ld_down) {
+ ld_left = data->utilization_pp * num_cores_enabled;
+ ld_right = (pmali_plat->dvfs_table[currentStep].upthreshold) *
+ (num_cores_enabled - 1);
+ if (ld_left < ld_right) {
+ change_mode = 2;
+ }
+ }
+ } else if (currentStep > pmali_plat->scale_info.minpp) {
+ change_mode = 1;
+ } else if (num_cores_enabled > 1) { /* decrease PPS */
+ if (data->utilization_pp <= ld_down) {
+ ld_left = data->utilization_pp * num_cores_enabled;
+ ld_right = (pmali_plat->dvfs_table[currentStep].upthreshold) *
+ (num_cores_enabled - 1);
+ if (ld_left < ld_right) {
+ change_mode = 2;
+ }
+ }
+ }
+
+ if (change_mode == 1) {
+ decided_fs_idx--;
+ } else if (change_mode == 2) { /* decrease PPS */
+ *pp_change_flag = -1;
+ }
+ }
+ if (change_mode)
+ mali_stay_count = pmali_plat->dvfs_table[decided_fs_idx].keep_count;
+ *next_fs_idx = decided_fs_idx;
+}
+
+void mali_pp_fs_scaling_update(struct mali_gpu_utilization_data *data)
+{
+ int ret = 0;
+ int pp_change_flag = 0;
+ u32 next_idx = 0;
+
+#if LOG_MALI_SCALING
+ u32 last_pp = num_cores_enabled;
+#endif
+ mali_decide_next_status(data, &next_idx, &pp_change_flag);
+
+ if (pp_change_flag == 1)
+ ret = enable_pp_cores(pmali_plat->sc_mpp);
+ else if (pp_change_flag == 2)
+ ret = enable_one_core();
+ else if (pp_change_flag == -1) {
+ ret = disable_one_core();
+ }
+
+#if LOG_MALI_SCALING
+ if (pp_change_flag || (next_idx != currentStep))
+ trace_utilization(data, currentStep, next_idx, last_pp, num_cores_enabled);
+#endif
+
+ if (next_idx != currentStep) {
+ ret = 1;
+ currentStep = next_idx;
+ }
+
+ if (ret == 1)
+ schedule_work(&wq_work);
+#ifdef CONFIG_MALI400_PROFILING
+ else
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
+ MALI_PROFILING_EVENT_CHANNEL_GPU |
+ MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
+ get_current_frequency(),
+ 0, 0, 0, 0);
+#endif
+}
+
+u32 get_mali_schel_mode(void)
+{
+ return scaling_mode;
+}
+
+void set_mali_schel_mode(u32 mode)
+{
+ MALI_DEBUG_ASSERT(mode < MALI_SCALING_MODE_MAX);
+ if (mode >= MALI_SCALING_MODE_MAX)
+ return;
+ scaling_mode = mode;
+ if (scaling_mode != MALI_PP_FS_SCALING) {
+ pmali_plat->scale_info.minclk = pmali_plat->cfg_min_clock;
+ pmali_plat->scale_info.maxclk = pmali_plat->cfg_clock;
+ pmali_plat->scale_info.minpp = pmali_plat->cfg_min_pp;
+ pmali_plat->scale_info.maxpp = pmali_plat->cfg_pp;
+ }
+ if (scaling_mode == MALI_TURBO_MODE) {
+ currentStep = pmali_plat->turbo_clock;
+ pmali_plat->scale_info.maxclk = currentStep;
+ } else
+ currentStep = pmali_plat->scale_info.maxclk;
+ enable_max_num_cores();
+ schedule_work(&wq_work);
+}
+
+u32 get_current_frequency(void)
+{
+ return get_mali_freq(currentStep);
+}
+
+void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
+{
+ switch (scaling_mode) {
+ case MALI_PP_FS_SCALING:
+ mali_pp_fs_scaling_update(data);
+ break;
+ case MALI_PP_SCALING:
+ mali_pp_scaling_update(data);
+ break;
+ default:
+ break;
+ }
+}
+++ /dev/null
-/*
- * Copyright (C) 2013 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
- *
- * A copy of the licence is included with the program, and can also be obtained from Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/**
- * @file arm_core_scaling.c
- * Example core scaling policy.
- */
-#include <linux/workqueue.h>
-#include <linux/mali/mali_utgard.h>
-#include <mach/smp.h>
-#include "mali_kernel_common.h"
-#include "common/mali_osk_profiling.h"
-#include "common/mali_kernel_utilization.h"
-#include "common/mali_pp_scheduler.h"
-
-#include "meson_main.h"
-
-#define MALI_TABLE_SIZE 6
-
-static int num_cores_total;
-static int num_cores_enabled;
-static int currentStep;
-static int lastStep;
-static struct work_struct wq_work;
-
-unsigned int min_mali_clock = 0;
-unsigned int max_mali_clock = 3;
-unsigned int min_pp_num = 1;
-
-/* Configure dvfs mode */
-enum mali_scale_mode_t {
- MALI_PP_SCALING = 0,
- MALI_PP_FS_SCALING,
- MALI_SCALING_DISABLE,
- MALI_TURBO_MODE,
- MALI_SCALING_MODE_MAX
-};
-
-
-static int scaling_mode = MALI_PP_FS_SCALING;
-
-enum mali_pp_scale_threshold_t {
- MALI_PP_THRESHOLD_20,
- MALI_PP_THRESHOLD_30,
- MALI_PP_THRESHOLD_40,
- MALI_PP_THRESHOLD_50,
- MALI_PP_THRESHOLD_60,
- MALI_PP_THRESHOLD_80,
- MALI_PP_THRESHOLD_90,
- MALI_PP_THRESHOLD_MAX,
-};
-static u32 mali_pp_scale_threshold [] = {
- 51, /* 20% */
- 77, /* 30% */
- 102, /* 40% */
- 128, /* 50% */
- 154, /* 60% */
- 205, /* 80% */
- 230, /* 90% */
-};
-
-
-static u32 mali_dvfs_table_size = MALI_TABLE_SIZE;
-
-static struct mali_dvfs_threshold_table mali_dvfs_threshold[MALI_TABLE_SIZE]={
- { 0, 0, 2, 0 , 200}, /* for 182.1 */
- { 1, 1, 2, 152, 205}, /* for 318.7 */
- { 2, 2, 2, 180, 212}, /* for 425.0 */
- { 3, 3, 2, 205, 236}, /* for 510.0 */
- { 4, 4, 2, 230, 256}, /* for 637.5 */
- { 0, 0, 2, 0, 0}
-};
-
-u32 set_mali_dvfs_tbl_size(u32 size)
-{
- if (size <= 0 && size > MALI_TABLE_SIZE) return -1;
- mali_dvfs_table_size = size;
- return 0;
-}
-
-u32 get_max_dvfs_tbl_size(void)
-{
- return MALI_TABLE_SIZE;
-}
-
-uint32_t* get_mali_dvfs_tbl_addr(void)
-{
- return (uint32_t*)mali_dvfs_threshold;
-}
-
-static void do_scaling(struct work_struct *work)
-{
- int err = mali_perf_set_num_pp_cores(num_cores_enabled);
- MALI_DEBUG_ASSERT(0 == err);
- MALI_IGNORE(err);
- if (mali_dvfs_threshold[currentStep].freq_index != mali_dvfs_threshold[lastStep].freq_index) {
- mali_dev_pause();
- mali_clock_set(mali_dvfs_threshold[currentStep].freq_index);
- mali_dev_resume();
- lastStep = currentStep;
- }
-#ifdef CONFIG_MALI400_PROFILING
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
- MALI_PROFILING_EVENT_CHANNEL_GPU |
- MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
- get_current_frequency(),
- 0, 0, 0, 0);
-#endif
-}
-
-void flush_scaling_job(void)
-{
- cancel_work_sync(&wq_work);
-}
-
-static u32 enable_one_core(void)
-{
- u32 ret = 0;
- if (num_cores_enabled < num_cores_total)
- {
- ++num_cores_enabled;
- ret = 1;
- MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
- }
-
- MALI_DEBUG_ASSERT( 1 <= num_cores_enabled);
- MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
- return ret;
-}
-
-static u32 disable_one_core(void)
-{
- u32 ret = 0;
- if (min_pp_num < num_cores_enabled)
- {
- --num_cores_enabled;
- ret = 1;
- MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
- }
-
- MALI_DEBUG_ASSERT(min_pp_num <= num_cores_enabled);
- MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
- return ret;
-}
-
-static u32 enable_max_num_cores(void)
-{
- u32 ret = 0;
- if (num_cores_enabled < num_cores_total)
- {
- num_cores_enabled = num_cores_total;
- ret = 1;
- MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
- }
-
- MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
- return ret;
-}
-
-void mali_core_scaling_init(int pp, int clock_idx)
-{
- INIT_WORK(&wq_work, do_scaling);
-
- num_cores_total = pp;
- num_cores_enabled = num_cores_total;
-
- currentStep = clock_idx;
- lastStep = currentStep;
- /* NOTE: Mali is not fully initialized at this point. */
-}
-
-void mali_core_scaling_term(void)
-{
- flush_scheduled_work();
-}
-
-void mali_pp_scaling_update(struct mali_gpu_utilization_data *data)
-{
- int ret = 0;
- currentStep = mali_up_clock_idx;
-
- MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, data->utilization_pp, num_cores_enabled, num_cores_total));
-
- /* NOTE: this function is normally called directly from the utilization callback which is in
- * timer context. */
-
- if (mali_pp_scale_threshold[MALI_PP_THRESHOLD_90] < data->utilization_pp)
- {
- ret = enable_max_num_cores();
- }
- else if (mali_pp_scale_threshold[MALI_PP_THRESHOLD_50]< data->utilization_pp)
- {
- ret = enable_one_core();
- }
- else if (mali_pp_scale_threshold[MALI_PP_THRESHOLD_40]< data->utilization_pp)
- {
- #if 0
- currentStep = MALI_CLOCK_425;
- schedule_work(&wq_work);
- #endif
- }
- else if (0 < data->utilization_pp)
- {
- ret = disable_one_core();
- }
- else
- {
- /* do nothing */
- }
- if (ret == 1)
- schedule_work(&wq_work);
-}
-
-void mali_pp_fs_scaling_update(struct mali_gpu_utilization_data *data)
-{
- u32 ret = 0;
- u32 utilization = data->utilization_gpu;
- //(data->utilization_pp < data->utilization_gp)?data->utilization_gp:data->utilization_pp;
- u32 loading_complete = (1<<16);//mali_utilization_bw_get_period();
- u32 mali_up_limit = (scaling_mode == MALI_TURBO_MODE) ? mali_clock_turbo_index : max_mali_clock;
-
- if (loading_complete > (2<<16) &&
- currentStep > min_mali_clock) {
- currentStep --;
- MALI_DEBUG_PRINT(3, (" active time vs command complete:%d\n", loading_complete));
- goto exit;
- }
-
- if (utilization >= mali_dvfs_threshold[currentStep].upthreshold) {
- if (utilization < mali_pp_scale_threshold[MALI_PP_THRESHOLD_80] && currentStep < mali_up_limit)
- currentStep ++;
- else
- currentStep = mali_up_limit;
-
- if (data->utilization_pp > MALI_PP_THRESHOLD_80) {
- enable_max_num_cores();
- } else {
- enable_one_core();
- }
- MALI_DEBUG_PRINT(3, (" > utilization:%d currentStep:%d.pp:%d. upthreshold:%d.\n",
- utilization, currentStep, num_cores_enabled, mali_dvfs_threshold[currentStep].upthreshold ));
- } else if (utilization < mali_dvfs_threshold[currentStep].downthreshold && currentStep > min_mali_clock) {
- currentStep--;
- MALI_DEBUG_PRINT(3, (" < utilization:%d currentStep:%d. downthreshold:%d.\n",
- utilization, currentStep,mali_dvfs_threshold[currentStep].downthreshold ));
- } else {
- if (data->utilization_pp < mali_pp_scale_threshold[MALI_PP_THRESHOLD_30])
- ret = disable_one_core();
- MALI_DEBUG_PRINT(3, (" < utilization:%d currentStep:%d. downthreshold:%d.pp:%d\n",
- utilization, currentStep,mali_dvfs_threshold[currentStep].downthreshold, num_cores_enabled));
- }
-
-exit:
- if ((num_cores_enabled != num_cores_total) ||
- (mali_dvfs_threshold[currentStep].freq_index != mali_dvfs_threshold[lastStep].freq_index))
- schedule_work(&wq_work);
-#ifdef CONFIG_MALI400_PROFILING
- else
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
- MALI_PROFILING_EVENT_CHANNEL_GPU |
- MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
- get_current_frequency(),
- 0, 0, 0, 0);
-#endif
-}
-
-static void reset_mali_scaling_stat(void)
-{
- if (scaling_mode == MALI_TURBO_MODE)
- currentStep = mali_clock_turbo_index;
- else
- currentStep = max_mali_clock;
- enable_max_num_cores();
- schedule_work(&wq_work);
-}
-
-u32 get_max_pp_num(void)
-{
- return num_cores_total;
-}
-u32 set_max_pp_num(u32 num)
-{
- if (num < min_pp_num)
- return -1;
- num_cores_total = num;
- if (num_cores_enabled > num_cores_total) {
- num_cores_enabled = num_cores_total;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-u32 get_min_pp_num(void)
-{
- return min_pp_num;
-}
-u32 set_min_pp_num(u32 num)
-{
- if (num > num_cores_total)
- return -1;
- min_pp_num = num;
- if (num_cores_enabled < min_pp_num) {
- num_cores_enabled = min_pp_num;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-u32 get_max_mali_freq(void)
-{
- return max_mali_clock;
-}
-u32 set_max_mali_freq(u32 idx)
-{
- if (idx >= mali_clock_turbo_index || idx < min_mali_clock )
- return -1;
- max_mali_clock = idx;
- if (currentStep > max_mali_clock) {
- currentStep = max_mali_clock;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-u32 get_min_mali_freq(void)
-{
- return min_mali_clock;
-}
-u32 set_min_mali_freq(u32 idx)
-{
- if (idx > max_mali_clock)
- return -1;
- min_mali_clock = idx;
- if (currentStep < min_mali_clock) {
- currentStep = min_mali_clock;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-void mali_plat_preheat(void)
-{
- //printk(" aml mali test*************\n");
- int ret;
- ret = enable_max_num_cores();
- if (ret)
- schedule_work(&wq_work);
-}
-
-void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
-{
- switch (scaling_mode) {
- case MALI_PP_FS_SCALING:
- mali_pp_fs_scaling_update(data);
- break;
- case MALI_PP_SCALING:
- mali_pp_scaling_update(data);
- break;
- default:
- break;
- }
-}
-
-u32 get_mali_schel_mode(void)
-{
- return scaling_mode;
-}
-
-void set_mali_schel_mode(u32 mode)
-{
- MALI_DEBUG_ASSERT(mode < MALI_SCALING_MODE_MAX);
- if (mode >= MALI_SCALING_MODE_MAX)return;
- scaling_mode = mode;
- reset_mali_scaling_stat();
-}
-
-u32 get_current_frequency(void)
-{
- return get_mali_freq(currentStep);
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2013 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
- *
- * A copy of the licence is included with the program, and can also be obtained from Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/**
- * @file arm_core_scaling.c
- * Example core scaling policy.
- */
-#include <linux/workqueue.h>
-#include <linux/mali/mali_utgard.h>
-#include "mali_kernel_common.h"
-#include "common/mali_osk_profiling.h"
-#include "common/mali_kernel_utilization.h"
-#include "common/mali_pp_scheduler.h"
-
-#include <meson_main.h>
-
-#define MALI_TABLE_SIZE 6
-
-#define LOG_MALI_SCALING 0
-#define LOG_SCALING_CHANGE 0
-#if LOG_SCALING_CHANGE
-# define TRACE_STAY() MALI_DEBUG_PRINT(2, ("[SCALING]stay_count:%d\n", stay_count));
-#else
-# define TRACE_STAY()
-#endif
-
-static int num_cores_total;
-static int num_cores_enabled;
-static int currentStep;
-static int lastStep;
-static struct work_struct wq_work;
-
-unsigned int min_mali_clock = 0;
-unsigned int max_mali_clock = 3;
-unsigned int min_pp_num = 1;
-
-/* Configure dvfs mode */
-enum mali_scale_mode_t {
- MALI_PP_SCALING = 0,
- MALI_PP_FS_SCALING,
- MALI_SCALING_DISABLE,
- MALI_TURBO_MODE,
- MALI_SCALING_MODE_MAX
-};
-
-static int scaling_mode = MALI_PP_FS_SCALING;
-
-enum enum_threshold_t {
- THRESHOLD_20,
- THRESHOLD_30,
- THRESHOLD_40,
- THRESHOLD_50,
- THRESHOLD_60,
- THRESHOLD_80,
- THRESHOLD_90,
- THRESHOLD_MAX,
-};
-static u32 mali_threshold [] = {
- 51, /* 20% */
- 77, /* 30% */
- 102, /* 40% */
- 128, /* 50% */
- 154, /* 60% */
- 205, /* 80% */
- 230, /* 90% */
-};
-
-static u32 mali_dvfs_table_size = MALI_TABLE_SIZE;
-
-static struct mali_dvfs_threshold_table mali_dvfs_threshold[MALI_TABLE_SIZE]={
- { 0, 0, 5, 0 , 180}, /* for 255 */
- { 1, 1, 5, 152, 205}, /* for 364 */
- { 2, 2, 5, 180, 212}, /* for 425 */
- { 3, 3, 5, 205, 236}, /* for 510 */
- { 4, 4, 5, 230, 256}, /* for 637 */
- { 0, 0, 5, 0, 0}
-};
-
-u32 set_mali_dvfs_tbl_size(u32 size)
-{
- if (size <= 0 && size > MALI_TABLE_SIZE) return -1;
- mali_dvfs_table_size = size;
- return 0;
-}
-
-u32 get_max_dvfs_tbl_size(void)
-{
- return MALI_TABLE_SIZE;
-}
-
-uint32_t* get_mali_dvfs_tbl_addr(void)
-{
- return (uint32_t*)mali_dvfs_threshold;
-}
-
-static void do_scaling(struct work_struct *work)
-{
- int err = mali_perf_set_num_pp_cores(num_cores_enabled);
-
- if (mali_pm_statue == 0) {
- printk("skip none clock test.\n");
- return;
- }
- MALI_DEBUG_ASSERT(0 == err);
- MALI_IGNORE(err);
- if (mali_dvfs_threshold[currentStep].freq_index != mali_dvfs_threshold[lastStep].freq_index) {
- mali_dev_pause();
- mali_clock_set(mali_dvfs_threshold[currentStep].freq_index);
- mali_dev_resume();
- lastStep = currentStep;
- }
-#ifdef CONFIG_MALI400_PROFILING
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
- MALI_PROFILING_EVENT_CHANNEL_GPU |
- MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
- get_current_frequency(),
- 0, 0, 0, 0);
-#endif
-}
-
-void flush_scaling_job(void)
-{
- cancel_work_sync(&wq_work);
-}
-
-static u32 enable_one_core(void)
-{
- u32 ret = 0;
- if (num_cores_enabled < num_cores_total)
- {
- ++num_cores_enabled;
- ret = 1;
- MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
- }
-
- MALI_DEBUG_ASSERT( 1 <= num_cores_enabled);
- MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
- return ret;
-}
-
-static u32 disable_one_core(void)
-{
- u32 ret = 0;
- if (min_pp_num < num_cores_enabled)
- {
- --num_cores_enabled;
- ret = 1;
- MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
- }
-
- MALI_DEBUG_ASSERT(min_pp_num <= num_cores_enabled);
- MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
- return ret;
-}
-
-static u32 enable_max_num_cores(void)
-{
- u32 ret = 0;
- if (num_cores_enabled < num_cores_total)
- {
- num_cores_enabled = num_cores_total;
- ret = 1;
- MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
- }
-
- MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
- return ret;
-}
-
-void mali_core_scaling_init(int pp, int clock_idx)
-{
- INIT_WORK(&wq_work, do_scaling);
-
- num_cores_total = pp;
- num_cores_enabled = num_cores_total;
-
- currentStep = clock_idx;
- lastStep = currentStep;
- /* NOTE: Mali is not fully initialized at this point. */
-}
-
-void mali_core_scaling_term(void)
-{
- flush_scheduled_work();
-}
-
-void mali_pp_scaling_update(struct mali_gpu_utilization_data *data)
-{
- int ret = 0;
- currentStep = mali_up_clock_idx;
-
- MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, data->utilization_pp, num_cores_enabled, num_cores_total));
-
- /* NOTE: this function is normally called directly from the utilization callback which is in
- * timer context. */
-
- if (mali_threshold[THRESHOLD_90] < data->utilization_pp)
- {
- ret = enable_max_num_cores();
- }
- else if (mali_threshold[THRESHOLD_50]< data->utilization_pp)
- {
- ret = enable_one_core();
- }
- else if (mali_threshold[THRESHOLD_40]< data->utilization_pp)
- {
- #if 0
- currentStep = MALI_CLOCK_425;
- schedule_work(&wq_work);
- #endif
- }
- else if (0 < data->utilization_pp)
- {
- ret = disable_one_core();
- }
- else
- {
- /* do nothing */
- }
- if (ret == 1)
- schedule_work(&wq_work);
-}
-
-#if LOG_MALI_SCALING
-void trace_utilization(struct mali_gpu_utilization_data *data, u32 current_idx,
- u32 next, u32 count)
-{
- char direction;
- if (next > current_idx)
- direction = '>';
- else if ((current_idx > min_mali_clock) && (current_idx < next))
- direction = '<';
- else
- direction = '~';
-
- if (count == 0) {
- MALI_DEBUG_PRINT(2, ("[SCALING]%c (%1d-->%1d)@%d{%3d - %3d}. pp:%d\n",
- direction,
- current_idx,
- next,
- data->utilization_gpu,
- mali_dvfs_threshold[lastStep].downthreshold,
- mali_dvfs_threshold[lastStep].upthreshold,
- num_cores_enabled));
- }
-}
-#endif
-
-static void mali_decide_next_status(struct mali_gpu_utilization_data *data, int* next_fs_idx,
- int* pp_change_flag)
-{
- u32 utilization, mali_up_limit, decided_fs_idx;
- u32 ld_left, ld_right;
-
- utilization = data->utilization_gpu;
- mali_up_limit = scaling_mode == MALI_TURBO_MODE? mali_clock_turbo_index : max_mali_clock;
- decided_fs_idx = currentStep;
- *pp_change_flag = 0;
-
- if (utilization >= mali_dvfs_threshold[currentStep].upthreshold) {
- if (utilization < mali_threshold[THRESHOLD_80] && currentStep < mali_up_limit)
- decided_fs_idx++;
- else
- decided_fs_idx = mali_up_limit;
-
- *pp_change_flag = 1;
- } else if ((utilization < mali_dvfs_threshold[currentStep].downthreshold) &&
- (currentStep > min_mali_clock)) {
- decided_fs_idx--;
- } else if (num_cores_enabled > 1) {
- ld_left = data->utilization_pp * num_cores_enabled;
- ld_right = (mali_dvfs_threshold[currentStep].upthreshold) * (num_cores_enabled - 1);
-
- if ((ld_left < ld_right) && (num_cores_enabled > min_pp_num))
- *pp_change_flag = -1;
- }
- *next_fs_idx = decided_fs_idx;
-}
-
-void mali_pp_fs_scaling_update(struct mali_gpu_utilization_data *data)
-{
- static int stay_count = 0;
- int ret = 0;
- int pp_change_flag = 0;
- u32 next_idx = 0;
-
- mali_decide_next_status(data, &next_idx, &pp_change_flag);
-
- if (pp_change_flag == 1)
- ret = enable_max_num_cores();
-
- if (next_idx > currentStep) {
- ret = 1;
- currentStep = next_idx;
- stay_count = mali_dvfs_threshold[currentStep].keep_count;
- }
-
-#if LOG_MALI_SCALING
- trace_utilization(data, currentStep, next_idx, stay_count);
-#endif
-
- if((next_idx <= currentStep) || (pp_change_flag == -1)) {
- if (stay_count == 0) {
- if (pp_change_flag == -1) {
- ret = disable_one_core();
- stay_count = mali_dvfs_threshold[currentStep].keep_count;
- }
-
- if (next_idx < currentStep) {
- ret = 1;
- currentStep = next_idx;
- stay_count = mali_dvfs_threshold[next_idx].keep_count;
- }
- } else {
- stay_count--;
- }
- }
-
- TRACE_STAY()
- if (ret == 1)
- schedule_work(&wq_work);
-#ifdef CONFIG_MALI400_PROFILING
- else
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
- MALI_PROFILING_EVENT_CHANNEL_GPU |
- MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE,
- get_current_frequency(),
- 0, 0, 0, 0);
-#endif
-}
-
-static void reset_mali_scaling_stat(void)
-{
- if (scaling_mode == MALI_TURBO_MODE)
- currentStep = mali_clock_turbo_index;
- else
- currentStep = max_mali_clock;
- enable_max_num_cores();
- schedule_work(&wq_work);
-}
-
-u32 get_max_pp_num(void)
-{
- return num_cores_total;
-}
-u32 set_max_pp_num(u32 num)
-{
- if (num < min_pp_num)
- return -1;
- num_cores_total = num;
- if (num_cores_enabled > num_cores_total) {
- num_cores_enabled = num_cores_total;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-u32 get_min_pp_num(void)
-{
- return min_pp_num;
-}
-u32 set_min_pp_num(u32 num)
-{
- if (num > num_cores_total)
- return -1;
- min_pp_num = num;
- if (num_cores_enabled < min_pp_num) {
- num_cores_enabled = min_pp_num;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-u32 get_max_mali_freq(void)
-{
- return max_mali_clock;
-}
-u32 set_max_mali_freq(u32 idx)
-{
- if (idx >= mali_clock_turbo_index || idx < min_mali_clock )
- return -1;
- max_mali_clock = idx;
- if (currentStep > max_mali_clock) {
- currentStep = max_mali_clock;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-u32 get_min_mali_freq(void)
-{
- return min_mali_clock;
-}
-u32 set_min_mali_freq(u32 idx)
-{
- if (idx > max_mali_clock)
- return -1;
- min_mali_clock = idx;
- if (currentStep < min_mali_clock) {
- currentStep = min_mali_clock;
- schedule_work(&wq_work);
- }
-
- return 0;
-}
-
-void mali_plat_preheat(void)
-{
- int ret1, ret2 = 0;
-#if 0
- printk(" aml mali test*************\n");
-#endif
- if (currentStep < mali_default_clock_idx) {
- ret2 = 1;
- currentStep = mali_default_clock_idx;
- }
- ret1 = enable_max_num_cores();
- if (ret1 || ret2)
- schedule_work(&wq_work);
-}
-
-void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
-{
-
- if (mali_pm_statue == 0) {
- printk("skip none clock scaling.\n");
- return;
- }
- switch (scaling_mode) {
- case MALI_PP_FS_SCALING:
- mali_pp_fs_scaling_update(data);
- break;
- case MALI_PP_SCALING:
- mali_pp_scaling_update(data);
- break;
- default:
- break;
- }
-}
-
-u32 get_mali_schel_mode(void)
-{
- return scaling_mode;
-}
-
-void set_mali_schel_mode(u32 mode)
-{
- MALI_DEBUG_ASSERT(mode < MALI_SCALING_MODE_MAX);
- if (mode >= MALI_SCALING_MODE_MAX)return;
- scaling_mode = mode;
- reset_mali_scaling_stat();
-}
-
-u32 get_current_frequency(void)
-{
- return get_mali_freq(currentStep);
-}
#include "common/mali_pmu.h"
#include "common/mali_osk_profiling.h"
-static void mali_platform_device_release(struct device *device);
int mali_pm_statue = 1;
+
static struct mali_gpu_device_data mali_gpu_data =
{
.shared_mem_size = 1024 * 1024 * 1024,
.pmu_domain_config = {0x1, 0x2, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x1, 0x2, 0x8},
};
+static void mali_platform_device_release(struct device *device);
static struct platform_device mali_gpu_device =
{
.name = MALI_GPU_NAME_UTGARD,
struct device_node *child;
u32 prop_value;
int err;
- mali_dvfs_threshold_table_t* tbl = NULL;
- u32 tbl_size;
- u32 tbl_size_in_byte;
for_each_child_of_node(cfg_node, child) {
- err = of_property_read_u32(child, "shared_memory", &prop_value);
- if (err == 0) {
- MALI_DEBUG_PRINT(2, ("shared_memory configurate %d\n", prop_value));
- mali_gpu_data.shared_mem_size = prop_value * 1024 * 1024;
- }
-
- err = of_property_read_u32(child, "dvfs_size", &prop_value);
- if (err != 0 || prop_value < 0 || prop_value > get_max_dvfs_tbl_size()) {
- MALI_DEBUG_PRINT(2, ("invalid recorde_number is.\n"));
- goto def_start;
- }
-
- tbl_size = sizeof(mali_dvfs_threshold_table_t) * prop_value;
- tbl_size_in_byte = tbl_size / sizeof(u32);
- tbl = kzalloc(tbl_size, GFP_KERNEL);
- if (!tbl)
- goto def_start;
-
- err = of_property_read_u32_array(child,
- "dvfs_table",
- (u32*)tbl,
- tbl_size_in_byte);
+ err = of_property_read_u32(child, "shared_memory", &prop_value);
if (err == 0) {
- memcpy(get_mali_dvfs_tbl_addr(), tbl, tbl_size);
- set_mali_dvfs_tbl_size(prop_value);
- kfree(tbl);
+ MALI_DEBUG_PRINT(2, ("shared_memory configurate %d\n", prop_value));
+ mali_gpu_data.shared_mem_size = prop_value * 1024 * 1024;
}
}
-def_start:
err = mali_pdev_pre_init(mali_gpu_device);
if (err == 0)
mali_pdev_post_init(mali_gpu_device);
MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
}
-static int dbg_parm = 0;
-module_param(dbg_parm, int, 0664);
-MODULE_PARM_DESC(dbg_parm, "Internal debug");
#include "mali_clock.h"
extern struct device_type mali_pm_device;
-extern u32 mali_dvfs_clk[];
-extern u32 mali_dvfs_clk_sample[];
-extern u32 mali_clock_turbo_index;
-extern u32 mali_default_clock_idx;
-extern u32 mali_up_clock_idx;
-extern u32 set_max_mali_freq(u32 idx);
-extern u32 get_max_mali_freq(void);
-extern u32 get_mali_tbl_size(void);
-extern int mali_pm_statue;
+
+u32 set_max_mali_freq(u32 idx);
+u32 get_max_mali_freq(void);
int mali_meson_init_start(struct platform_device* ptr_plt_dev);
int mali_meson_init_finish(struct platform_device* ptr_plt_dev);
}
#if MESON_CPU_TYPE > MESON_CPU_TYPE_MESON6TVD
-static ssize_t mpgpu_read(struct class *class,
- struct class_attribute *attr, char *buf)
-{
- return 0;
-}
-
#define PREHEAT_CMD "preheat"
+#define PLL2_CMD "mpl2" /* mpl2 [11] or [0xxxxxxx] */
+#define SCMPP_CMD "scmpp" /* scmpp [number of pp your want in most of time]. */
+#define BSTGPU_CMD "bstgpu" /* bstgpu [0-256] */
+#define BSTPP_CMD "bstpp" /* bstpp [0-256] */
+#define LIMIT_CMD "lmt" /* lmt [0 or 1] */
+#define MAX_TOKEN 20
+#define FULL_UTILIZATION 256
static ssize_t mpgpu_write(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
- if(!strncmp(buf,PREHEAT_CMD,strlen(PREHEAT_CMD)))
- mali_plat_preheat();
+ char *pstart, *cprt = NULL;
+ u32 val = 0;
+ mali_plat_info_t* pmali_plat = get_mali_plat_data();
+
+ cprt = skip_spaces(buf);
+ pstart = strsep(&cprt," ");
+ if (strlen(pstart) < 1)
+ goto quit;
+
+ if(!strncmp(pstart, PREHEAT_CMD, MAX_TOKEN)) {
+ if (pmali_plat->plat_preheat) {
+ pmali_plat->plat_preheat();
+ }
+ } else if (!strncmp(pstart, PLL2_CMD, MAX_TOKEN)) {
+ int base = 10;
+ if ((strlen(cprt) > 2) && (cprt[0] == '0') &&
+ (cprt[1] == 'x' || cprt[1] == 'X'))
+ base = 16;
+ if (kstrtouint(cprt, base, &val) <0)
+ goto quit;
+ set_str_src(val);
+ } else if (!strncmp(pstart, SCMPP_CMD, MAX_TOKEN)) {
+ if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL)
+ goto quit;
+ if ((val > 0) && (val < pmali_plat->cfg_pp)) {
+ pmali_plat->sc_mpp = val;
+ }
+ } else if (!strncmp(pstart, BSTGPU_CMD, MAX_TOKEN)) {
+ if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL)
+ goto quit;
+ if ((val > 0) && (val < FULL_UTILIZATION)) {
+ pmali_plat->bst_gpu = val;
+ }
+ } else if (!strncmp(pstart, BSTPP_CMD, MAX_TOKEN)) {
+ if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL)
+ goto quit;
+ if ((val > 0) && (val < FULL_UTILIZATION)) {
+ pmali_plat->bst_pp = val;
+ }
+ } else if (!strncmp(pstart, LIMIT_CMD, MAX_TOKEN)) {
+ if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL)
+ goto quit;
+
+ if (val < 2) {
+ pmali_plat->limit_on = val;
+ if (val == 0) {
+ pmali_plat->scale_info.maxclk = pmali_plat->cfg_clock;
+ pmali_plat->scale_info.maxpp = pmali_plat->cfg_pp;
+ revise_mali_rt();
+ }
+ }
+ }
+quit:
return count;
}
{
return -EINVAL;
}
+
set_mali_schel_mode(val);
return count;
static ssize_t max_pp_read(struct class *class,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", get_max_pp_num());
+ mali_plat_info_t* pmali_plat = get_mali_plat_data();
+ return sprintf(buf, "%d\n", pmali_plat->scale_info.maxpp);
}
static ssize_t max_pp_write(struct class *class,
{
int ret;
unsigned int val;
+ mali_plat_info_t* pmali_plat;
+ mali_scale_info_t* pinfo;
+
+ pmali_plat = get_mali_plat_data();
+ pinfo = &pmali_plat->scale_info;
ret = kstrtouint(buf, 10, &val);
- if (0 != ret)
- {
+ if ((0 != ret) || (val > pmali_plat->cfg_pp) || (val < pinfo->minpp))
return -EINVAL;
- }
- ret = set_max_pp_num(val);
+
+ pinfo->maxpp = val;
+ revise_mali_rt();
return count;
}
static ssize_t min_pp_read(struct class *class,
struct class_attribute *attr, char *buf)
{
-
- return sprintf(buf, "%d\n", get_min_pp_num());
+ mali_plat_info_t* pmali_plat = get_mali_plat_data();
+ return sprintf(buf, "%d\n", pmali_plat->scale_info.minpp);
}
static ssize_t min_pp_write(struct class *class,
{
int ret;
unsigned int val;
+ mali_plat_info_t* pmali_plat;
+ mali_scale_info_t* pinfo;
+
+ pmali_plat = get_mali_plat_data();
+ pinfo = &pmali_plat->scale_info;
ret = kstrtouint(buf, 10, &val);
- if (0 != ret)
- {
+ if ((0 != ret) || (val > pinfo->maxpp) || (val < 1))
return -EINVAL;
- }
- ret = set_min_pp_num(val);
+
+ pinfo->minpp = val;
+ revise_mali_rt();
return count;
}
static ssize_t max_freq_read(struct class *class,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", get_max_mali_freq());
+ mali_plat_info_t* pmali_plat = get_mali_plat_data();
+ return sprintf(buf, "%d\n", pmali_plat->scale_info.maxclk);
}
static ssize_t max_freq_write(struct class *class,
{
int ret;
unsigned int val;
+ mali_plat_info_t* pmali_plat;
+ mali_scale_info_t* pinfo;
+
+ pmali_plat = get_mali_plat_data();
+ pinfo = &pmali_plat->scale_info;
ret = kstrtouint(buf, 10, &val);
- if (0 != ret)
- {
+ if ((0 != ret) || (val > pmali_plat->cfg_clock) || (val < pinfo->minclk))
return -EINVAL;
- }
- ret = set_max_mali_freq(val);
+
+ pinfo->maxclk = val;
+ revise_mali_rt();
return count;
}
static ssize_t min_freq_read(struct class *class,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", get_min_mali_freq());
+ mali_plat_info_t* pmali_plat = get_mali_plat_data();
+ return sprintf(buf, "%d\n", pmali_plat->scale_info.minclk);
}
static ssize_t min_freq_write(struct class *class,
{
int ret;
unsigned int val;
+ mali_plat_info_t* pmali_plat;
+ mali_scale_info_t* pinfo;
+
+ pmali_plat = get_mali_plat_data();
+ pinfo = &pmali_plat->scale_info;
+
+ ret = kstrtouint(buf, 10, &val);
+ if ((0 != ret) || (val > pinfo->maxclk))
+ return -EINVAL;
+
+ pinfo->minclk = val;
+ revise_mali_rt();
+
+ return count;
+}
+
+static ssize_t freq_read(struct class *class,
+ struct class_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", get_current_frequency());
+}
+
+static ssize_t freq_write(struct class *class,
+ struct class_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ unsigned int val;
+ u32 clk, pp;
+ get_mali_rt_clkpp(&clk, &pp);
ret = kstrtouint(buf, 10, &val);
if (0 != ret)
- {
return -EINVAL;
- }
- ret = set_min_mali_freq(val);
+
+ set_mali_rt_clkpp(val, pp, 1);
return count;
}
-static ssize_t read_extr_src(struct class *class,
+static ssize_t current_pp_read(struct class *class,
struct class_attribute *attr, char *buf)
{
- return sprintf(buf, "usage echo 0(restore), 1(set fix src), xxx user mode\n");
+ u32 clk, pp;
+ get_mali_rt_clkpp(&clk, &pp);
+ return sprintf(buf, "%d\n", pp);
}
-static ssize_t write_extr_src(struct class *class,
+static ssize_t current_pp_write(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int ret;
unsigned int val;
+ u32 clk, pp;
+ get_mali_rt_clkpp(&clk, &pp);
ret = kstrtouint(buf, 10, &val);
if (0 != ret)
{
return -EINVAL;
}
- set_str_src(val);
+ ret = kstrtouint(buf, 10, &val);
+ if (0 != ret)
+ return -EINVAL;
+
+ set_mali_rt_clkpp(clk, val, 1);
return count;
}
+
#endif
static struct class_attribute mali_class_attrs[] = {
- __ATTR(domain_stat, 0644, domain_stat_read, NULL),
#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
- __ATTR(mpgpucmd, 0644, mpgpu_read, mpgpu_write),
+ __ATTR(domain_stat, 0644, domain_stat_read, NULL),
+ __ATTR(mpgpucmd, 0644, NULL, mpgpu_write),
__ATTR(scale_mode, 0644, scale_mode_read, scale_mode_write),
__ATTR(min_freq, 0644, min_freq_read, min_freq_write),
__ATTR(max_freq, 0644, max_freq_read, max_freq_write),
__ATTR(min_pp, 0644, min_pp_read, min_pp_write),
__ATTR(max_pp, 0644, max_pp_read, max_pp_write),
- __ATTR(extr_src, 0644, read_extr_src, write_extr_src),
+ __ATTR(cur_freq, 0644, freq_read, freq_write),
+ __ATTR(cur_pp, 0644, current_pp_read, current_pp_write),
#endif
};
class_unregister(&mpgpu_class);
}
-#if 0
-static int __init mpgpu_init(void)
-{
- return mpgpu_class_init();
-}
-
-static void __exit mpgpu_exit(void)
-{
- mpgpu_class_exit();
-}
-
-fs_initcall(mpgpu_init);
-module_exit(mpgpu_exit);
-
-MODULE_DESCRIPTION("AMLOGIC mpgpu driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("aml-sh <kasin.li@amlogic.com>");
-#endif
-
-