first version of clock scaling & pp scaling.
authorKasin Lee <kasin.li@amlogic.com>
Fri, 13 Sep 2013 19:52:36 +0000 (03:52 +0800)
committerKasin Lee <kasin.li@amlogic.com>
Fri, 13 Sep 2013 19:52:36 +0000 (03:52 +0800)
mali/Kbuild
mali/platform/meson8/mali_clock.c
mali/platform/meson8/mali_clock.h
mali/platform/meson8/mali_scaling.c [new file with mode: 0755]
mali/platform/meson8/mali_scaling.h [new file with mode: 0755]
mali/platform/meson8/meson_main.c

index d3cd4e46c0f4d8bbff2b61e8e0465e1f4bdf9adc..25dae8f1ad7bab3c4e8ad1b2134e0494041b6376 100644 (file)
@@ -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),)
index 925e6d611ca78e5a37ce69f8dc4687cd2c03017f..99ff554e662334d037cb9a8c904cf8cb7acb1f10 100644 (file)
@@ -7,71 +7,13 @@
 #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);
 }
index 8fe6f8e9b3c8fc888ec60f059222ec31f0bdc870..96eeae5e2221a5ac038cd08f4a39f9a9beb4a75a 100644 (file)
@@ -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 (executable)
index 0000000..cc8abd7
--- /dev/null
@@ -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 <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;
+       }
+
+}
diff --git a/mali/platform/meson8/mali_scaling.h b/mali/platform/meson8/mali_scaling.h
new file mode 100755 (executable)
index 0000000..6911254
--- /dev/null
@@ -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__ */
index 5883fdec17ee910cb15cc72ef5c401223e39614a..7b9c306213535f952805e91f7cc3be752d6eb4c8 100755 (executable)
@@ -21,7 +21,7 @@
 #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);
@@ -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)