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),)
#include <mach/io.h>
#include <plat/io.h>
#include <asm/io.h>
-#include <linux/mali/mali_utgard.h>
-#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);
}
#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;
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_ */
--- /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 "mali_scaling.h"
+
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+
+#include <linux/workqueue.h>
+#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;
+ }
+
+}
--- /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.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__ */
#include <linux/mali/mali_utgard.h>
#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);
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"));
#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;
}
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);
}
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)