From f5c72fe89f38107ca85ba5fa7310d818022ce8ca Mon Sep 17 00:00:00 2001 From: Kasin Lee Date: Sat, 14 Sep 2013 03:52:36 +0800 Subject: [PATCH] first version of clock scaling & pp scaling. --- mali/Kbuild | 5 +- mali/platform/meson8/mali_clock.c | 66 +---------- mali/platform/meson8/mali_clock.h | 34 +++--- mali/platform/meson8/mali_scaling.c | 176 ++++++++++++++++++++++++++++ mali/platform/meson8/mali_scaling.h | 42 +++++++ mali/platform/meson8/meson_main.c | 11 +- 6 files changed, 250 insertions(+), 84 deletions(-) create mode 100755 mali/platform/meson8/mali_scaling.c create mode 100755 mali/platform/meson8/mali_scaling.h diff --git a/mali/Kbuild b/mali/Kbuild index d3cd4e4..25dae8f 100644 --- a/mali/Kbuild +++ b/mali/Kbuild @@ -132,8 +132,9 @@ MALI_PLATFORM_FILES:= platform/meson6pre/mali_fix.c \ endif ifeq ($(TARGET_PLATFORM),meson8) -MALI_PLATFORM_FILES:= platform/meson8/arm_core_scaling.c \ - platform/meson8/meson_main.c +MALI_PLATFORM_FILES:= platform/meson8/mali_scaling.c \ + platform/meson8/meson_main.c \ + platform/meson8/mali_clock.c endif ifneq ($(MALI_PLATFORM_FILES),) diff --git a/mali/platform/meson8/mali_clock.c b/mali/platform/meson8/mali_clock.c index 925e6d6..99ff554 100644 --- a/mali/platform/meson8/mali_clock.c +++ b/mali/platform/meson8/mali_clock.c @@ -7,71 +7,13 @@ #include #include #include -#include -#include "mali_kernel_common.h" - -#include "arm_core_scaling.h" #include "mali_clock.h" -static DEFINE_SPINLOCK(lock); - -/* fclk is 2550Mhz. */ -#define FCLK_DEV3 (6 << 9) /* 850 Mhz */ -#define FCLK_DEV4 (5 << 9) /* 637.5 Mhz */ -#define FCLK_DEV5 (7 << 9) /* 510 Mhz */ -#define FCLK_DEV7 (4 << 9) /* 364.3 Mhz */ - -unsigned int mali_dvfs_clk[MALI_DVFS_STEPS] = { - FCLK_DEV7 | 3, /* 91 Mhz */ - FCLK_DEV7 | 1, /* 182.1 Mhz */ - FCLK_DEV4 | 1, /* 318.7 Mhz */ - FCLK_DEV3 | 1, /* 425 Mhz */ - FCLK_DEV4 | 0, /* 637.5 Mhz */ -}; - -mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ - {0, 180}, //0%-70% - {154, 230}, //%60-90% - {218, 230}, //%85-%90 - {218, 230}, //%85-%90 - {243, 256} //%95-%100 -}; - -int top_clk_limit = 4; - -void set_mali_clock(unsigned int utilization_pp) -{ - static int currentStep = MALI_DVFS_STEPS; - static int lastStep = MALI_DVFS_STEPS; - - if (utilization_pp > mali_dvfs_threshold[currentStep].upthreshold) { - currentStep = MALI_DVFS_STEPS - 1; - } else if (utilization_pp < mali_dvfs_threshold[currentStep].downthreshold && currentStep > 0) { - currentStep--; - } else { - return; - } - - if (currentStep != lastStep) { - int current_indx; - - if (currentStep > top_clk_limit && top_clk_limit >= 0 && top_clk_limit < MALI_DVFS_STEPS) { - current_indx = top_clk_limit; - } else { - current_indx = currentStep; - } - mali_clock_set (current_indx); - lastStep = currentStep; - } -} +unsigned int mali_default_clock_step = MALI_CLOCK_637; -int inline mali_clock_set(int index) { - unsigned long flags; - - spin_lock_irqsave(&lock, flags); +int mali_clock_set(unsigned int clock) { clrbits_le32(P_HHI_MALI_CLK_CNTL, 1 << 8); - writel(mali_dvfs_clk[index], P_HHI_MALI_CLK_CNTL); /* set clock to 333MHZ.*/ - readl(P_HHI_MALI_CLK_CNTL); + clrbits_le32(P_HHI_MALI_CLK_CNTL, (0x7F | (0x7 << 9))); + writel(clock, P_HHI_MALI_CLK_CNTL | (1 << 8)); /* set clock to 333MHZ.*/ setbits_le32(P_HHI_MALI_CLK_CNTL, 1 << 8); - spin_unlock_irqrestore(&lock, flags); } diff --git a/mali/platform/meson8/mali_clock.h b/mali/platform/meson8/mali_clock.h index 8fe6f8e..96eeae5 100644 --- a/mali/platform/meson8/mali_clock.h +++ b/mali/platform/meson8/mali_clock.h @@ -1,18 +1,6 @@ #ifndef _MALI_CLOCK_H_ #define _MALI_CLOCK_H_ -enum mali_clock_rate { - MALI_CLOCK_91, - MALI_CLOCK_182, - MALI_CLOCK_318, - MALI_CLOCK_425, - MALI_CLOCK_637, - - MALI_CLOCK_INDX_MAX -}; - -#define MALI_DVFS_STEPS 5 - typedef struct mali_dvfs_Tag{ unsigned int step; unsigned int mali_clk; @@ -23,9 +11,25 @@ typedef struct mali_dvfs_thresholdTag{ unsigned int upthreshold; }mali_dvfs_threshold_table; -void set_mali_clock(unsigned int utilization_pp); +/* fclk is 2550Mhz. */ +#define FCLK_DEV3 (6 << 9) /* 850 Mhz */ +#define FCLK_DEV4 (5 << 9) /* 637.5 Mhz */ +#define FCLK_DEV5 (7 << 9) /* 510 Mhz */ +#define FCLK_DEV7 (4 << 9) /* 364.3 Mhz */ + +enum mali_clock_rate { +// MALI_CLOCK_91, + MALI_CLOCK_182 = 0, + MALI_CLOCK_318, + MALI_CLOCK_425, + MALI_CLOCK_637, + + MALI_CLOCK_INDX_MAX +}; + +extern unsigned int mali_default_clock_step; +extern unsigned int mali_dvfs_clk[]; -extern unsigned int mali_clock_table; -extern int mali_clock_set(int index); +extern int mali_clock_set(unsigned int index); #endif /* _MALI_CLOCK_H_ */ diff --git a/mali/platform/meson8/mali_scaling.c b/mali/platform/meson8/mali_scaling.c new file mode 100755 index 0000000..cc8abd7 --- /dev/null +++ b/mali/platform/meson8/mali_scaling.c @@ -0,0 +1,176 @@ +/* + * 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 "mali_scaling.h" + +#include +#include "mali_kernel_common.h" + +#include +#include "mali_clock.h" + +static int num_cores_total; +static int num_cores_enabled; +static int currentStep; +static int lastStep; +static struct work_struct wq_work; +unsigned int utilization; + + +unsigned int mali_dvfs_clk[] = { +// FCLK_DEV7 | 3, /* 91 Mhz */ + FCLK_DEV7 | 1, /* 182.1 Mhz */ + FCLK_DEV4 | 1, /* 318.7 Mhz */ + FCLK_DEV3 | 1, /* 425 Mhz */ + FCLK_DEV4 | 0, /* 637.5 Mhz */ +}; + +mali_dvfs_threshold_table mali_dvfs_threshold[]={ + { 0 , 43 * 256 / 100 }, + { 40 * 256 / 100, 53 * 256 / 100 }, + { 50 * 256 / 100, 92 * 256 / 100 }, + { 87 * 256 / 100, 256 } +}; + +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 (currentStep != lastStep) { + mali_dev_pause(); + mali_clock_set (mali_dvfs_clk[currentStep]); + mali_dev_resume(); + lastStep = currentStep; + } +} + +static void enable_one_core(void) +{ + if (num_cores_enabled < num_cores_total) + { + ++num_cores_enabled; + schedule_work(&wq_work); + 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); +} + +static void disable_one_core(void) +{ + if (1 < num_cores_enabled) + { + --num_cores_enabled; + schedule_work(&wq_work); + MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n")); + } + + MALI_DEBUG_ASSERT( 1 <= num_cores_enabled); + MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled); +} + +static void enable_max_num_cores(void) +{ + if (num_cores_enabled < num_cores_total) + { + num_cores_enabled = num_cores_total; + schedule_work(&wq_work); + MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n")); + } + + MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled); +} + +void mali_core_scaling_init(int num_pp_cores, int clock_rate_index) +{ + INIT_WORK(&wq_work, do_scaling); + + num_cores_total = num_pp_cores; + num_cores_enabled = num_pp_cores; + + currentStep = clock_rate_index; + lastStep = currentStep; + /* NOTE: Mali is not fully initialized at this point. */ +} + +void mali_core_scaling_term(void) +{ + flush_scheduled_work(); +} + +#define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5)) + +void mali_core_scaling_update(struct mali_gpu_utilization_data *data) +{ + /* + * This function implements a very trivial PP core scaling algorithm. + * + * It is _NOT_ of production quality. + * The only intention behind this algorithm is to exercise and test the + * core scaling functionality of the driver. + * It is _NOT_ tuned for neither power saving nor performance! + * + * Other metrics than PP utilization need to be considered as well + * in order to make a good core scaling algorithm. + */ + + 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 (PERCENT_OF(90, 256) < data->utilization_pp) + { + enable_max_num_cores(); + } + else if (PERCENT_OF(50, 256) < data->utilization_pp) + { + enable_one_core(); + } + else if (PERCENT_OF(40, 256) < data->utilization_pp) + { + /* do nothing */ + } + else if (PERCENT_OF( 0, 256) < data->utilization_pp) + { + disable_one_core(); + } + else + { + /* do nothing */ + } +} + +void mali_scaling_update(struct mali_gpu_utilization_data *data) +{ + MALI_DEBUG_PRINT(2, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, data->utilization_pp, num_cores_enabled, num_cores_total)); + MALI_DEBUG_PRINT(2, (" %d \n", currentStep)); + utilization = data->utilization_gpu; + + if (utilization > mali_dvfs_threshold[currentStep].upthreshold) { + currentStep = MALI_CLOCK_637; + enable_max_num_cores(); + } else if (utilization < mali_dvfs_threshold[currentStep].downthreshold && currentStep > 0) { + currentStep--; + MALI_DEBUG_PRINT(2, ("Mali clock set %d..\n",currentStep)); + } else { + if (data->utilization_pp < mali_dvfs_threshold[0].upthreshold) + disable_one_core(); + return; + } + +} diff --git a/mali/platform/meson8/mali_scaling.h b/mali/platform/meson8/mali_scaling.h new file mode 100755 index 0000000..6911254 --- /dev/null +++ b/mali/platform/meson8/mali_scaling.h @@ -0,0 +1,42 @@ +/* + * 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.h + * Example core scaling policy. + */ + +#ifndef __ARM_CORE_SCALING_H__ +#define __ARM_CORE_SCALING_H__ + +struct mali_gpu_utilization_data; + +/** + * Initialize core scaling policy. + * + * @note The core scaling policy will assume that all PP cores are on initially. + * + * @param num_pp_cores Total number of PP cores. + */ +void mali_core_scaling_init(int num_pp_cores, int clock_rate_index); + +/** + * Terminate core scaling policy. + */ +void mali_core_scaling_term(void); + +/** + * Update core scaling policy with new utilization data. + * + * @param data Utilization data. + */ +void mali_scaling_update(struct mali_gpu_utilization_data *data); + +#endif /* __ARM_CORE_SCALING_H__ */ diff --git a/mali/platform/meson8/meson_main.c b/mali/platform/meson8/meson_main.c index 5883fde..7b9c306 100755 --- a/mali/platform/meson8/meson_main.c +++ b/mali/platform/meson8/meson_main.c @@ -21,7 +21,7 @@ #include #include "mali_kernel_common.h" -#include "arm_core_scaling.h" +#include "mali_scaling.h" #include "mali_clock.h" static void mali_platform_device_release(struct device *device); @@ -109,7 +109,8 @@ int mali_platform_device_register(void) int err = -1; int num_pp_cores = MALI_PP_NUMBER; - mali_clock_set(MALI_CLOCK_637); + mali_clock_set(mali_dvfs_clk[mali_default_clock_step]); + printk(" %x \n", mali_dvfs_clk[mali_default_clock_step]); if (mali_gpu_data.shared_mem_size < 10) { MALI_DEBUG_PRINT(2, ("mali os memory didn't configered, set to default(512M)\n")); @@ -136,8 +137,9 @@ int mali_platform_device_register(void) #endif pm_runtime_enable(&(mali_gpu_device.dev)); #endif + MALI_DEBUG_ASSERT(0 < num_pp_cores); - mali_core_scaling_init(num_pp_cores, MALI_CLOCK_637); + mali_core_scaling_init(num_pp_cores, mali_default_clock_step); return 0; } @@ -151,7 +153,6 @@ int mali_platform_device_register(void) void mali_platform_device_unregister(void) { MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n")); - mali_core_scaling_term(); platform_device_unregister(&mali_gpu_device); } @@ -163,7 +164,7 @@ static void mali_platform_device_release(struct device *device) void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data) { - mali_core_scaling_update(data); + mali_scaling_update(data); } static int mali_os_suspend(struct device *device) -- 2.20.1