current stat
authorKasin Lee <kasin.li@amlogic.com>
Sat, 14 Sep 2013 16:32:42 +0000 (00:32 +0800)
committerKasin Lee <kasin.li@amlogic.com>
Sat, 14 Sep 2013 16:32:42 +0000 (00:32 +0800)
12 files changed:
mali/Kbuild
mali/common/mali_pmu.c
mali/common/mali_pmu.h
mali/linux/mali_kernel_linux.c
mali/linux/mali_kernel_sysfs.c
mali/platform/meson8/arm_core_scaling.c
mali/platform/meson8/arm_core_scaling.h
mali/platform/meson8/mali_clock.c [new file with mode: 0644]
mali/platform/meson8/mali_clock.h [new file with mode: 0644]
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 c052289c483d079585f8e7d5c9dae2722757e415..8d79e6cadc25ce9db20df57292508580408fccd9 100755 (executable)
@@ -403,3 +403,16 @@ static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches)
 
        return mask;
 }
+
+
+/* 
+ * 
+ * kasin.li@amlogic.com. 
+ **/
+
+u32 mali_pmu_get_status(struct mali_pmu_core * pmu)
+{
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       return mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+       
+}
index 6dd3c38fefc1c4f27c2ad93e6638aca9f759ca24..20d0dc4b69fa8826bbff013cc80253e509053fb0 100755 (executable)
@@ -109,5 +109,9 @@ _mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu);
  * @return The Mali PMU object, or NULL if no PMU exists.
  */
 struct mali_pmu_core *mali_pmu_get_global_pmu_core(void);
-
+/** @brief Retrieves the Mali Power Domain status.
+ *
+ * @return the Mali Power Domain status 1 off, 0 on.
+ */
+extern u32 mali_pmu_get_status(struct mali_pmu_core * pmu);
 #endif /* __MALI_PMU_H__ */
index da71d63d3a4dc69bea30f5f4b23369ee8fe450d8..ae748d67c0d782b3891c49f9a990baedadc7a454 100755 (executable)
@@ -189,10 +189,6 @@ struct file_operations mali_fops =
 };
 
 
-
-
-
-
 int mali_module_init(void)
 {
        int err = 0;
index ab8248c915c09702cc35c19aeb36db197128a9bf..5c6753d292aac057bb24b40d6196464df2c74b1e 100755 (executable)
@@ -53,6 +53,7 @@
 #define POWER_BUFFER_SIZE 3
 
 static struct dentry *mali_debugfs_dir = NULL;
+static struct dentry *mali_classfs_dir = NULL;
 
 typedef enum
 {
@@ -1453,7 +1454,162 @@ static const struct file_operations pp_num_cores_total_fops = {
        .owner = THIS_MODULE,
        .read = pp_num_cores_total_read,
 };
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8
+extern u32 get_mali_def_freq_idx(void);
+extern void set_mali_freq_idx(u32 idx);
+extern u32 get_mali_qq_for_sched(void);
+extern void set_mali_qq_for_sched(u32 pp_num);
+extern u32 get_mali_schel_mode(void);
+extern void set_mali_schel_mode(u32 mode);
 
+static ssize_t pp_for_sched_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+       r = sprintf(buffer, "%d\n", get_mali_qq_for_sched());
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static ssize_t pp_for_sched_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+
+       if (count >= sizeof(buffer))
+       {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count))
+       {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret)
+       {
+               return -EINVAL;
+       }
+
+       set_mali_qq_for_sched(val);
+
+       *offp += count;
+       return count;
+}
+
+static const struct file_operations pp_for_sched_fops = {
+       .owner = THIS_MODULE,
+       .read = pp_for_sched_read,
+       .write = pp_for_sched_write,
+};
+
+static ssize_t cur_freq_read (struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+       r = sprintf(buffer, "%d\n", get_mali_def_freq_idx());
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static ssize_t cur_freq_write (struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+
+       if (count >= sizeof(buffer))
+       {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count))
+       {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret)
+       {
+               return -EINVAL;
+       }
+
+       set_mali_freq_idx(val);
+
+       *offp += count;
+       return count;
+}
+
+static const struct file_operations cur_freq_fops = {
+       .owner = THIS_MODULE,
+       .read = cur_freq_read,
+       .write = cur_freq_write,
+};
+
+static ssize_t scale_mode_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+       r = sprintf(buffer, "%d\n", get_mali_schel_mode());
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static ssize_t scale_mode_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+
+       if (count >= sizeof(buffer))
+       {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count))
+       {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret)
+       {
+               return -EINVAL;
+       }
+
+       set_mali_schel_mode(val);
+
+       *offp += count;
+       return count;
+}
+
+static const struct file_operations scale_mode_fops = {
+       .owner = THIS_MODULE,
+       .read = scale_mode_read,
+       .write = scale_mode_write
+};
+
+static ssize_t domain_stat_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       struct mali_pmu_core *pmu;
+       int r;
+       char buffer[64];
+       pmu = mali_pmu_get_global_pmu_core();
+       r = sprintf(buffer, "%x\n", mali_pmu_get_status(pmu));
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static const struct file_operations domain_stat_fops = {
+       .owner = THIS_MODULE,
+       .read = domain_stat_read,
+};
+#endif /* MESON_CPU_TYPE_MESON8 */
 
 static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
 {
@@ -1669,6 +1825,20 @@ int mali_sysfs_register(const char *mali_dev_name)
                        debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
 #endif
 
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8
+                       /* kasin.li@amlogic.com. misc setting. */
+                       {
+                               struct dentry *mali_misc_setting_dir = debugfs_create_dir("misc", mali_debugfs_dir);
+                               if (mali_misc_setting_dir != NULL)
+                               {
+                                       debugfs_create_file("pp_for_sched", 0600, mali_misc_setting_dir, NULL, &pp_for_sched_fops);
+                                       debugfs_create_file("cur_freq", 0600, mali_misc_setting_dir, NULL, &cur_freq_fops);
+                                       debugfs_create_file("scale_mode", 0600, mali_misc_setting_dir, NULL, &scale_mode_fops);
+                                       debugfs_create_file("domain_stat", 0600, mali_misc_setting_dir, NULL, &domain_stat_fops);
+                               }
+                       }
+#endif /* MESON_CPU_TYPE_MESON8 */
+
                        if (mali_sysfs_user_settings_register())
                        {
                                /* Failed to create the debugfs entries for the user settings DB. */
index d7930a4d6012ee65e1e2f960c3d94c8991c5cc49..0df72bd6217e3d2579d8bcab4c505280ac1e6bda 100755 (executable)
 #include "mali_kernel_common.h"
 
 #include <linux/workqueue.h>
+#include "mali_clock.h"
 
 static int num_cores_total;
 static int num_cores_enabled;
+static current_mali_clock_index;
 
 static struct work_struct wq_work;
 
@@ -70,13 +72,14 @@ static void enable_max_num_cores(void)
        MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
 }
 
-void mali_core_scaling_init(int num_pp_cores)
+void mali_core_scaling_init(int num_pp_cores, int clock_rate_index)
 {
        INIT_WORK(&wq_work, set_num_cores);
 
        num_cores_total   = num_pp_cores;
        num_cores_enabled = num_pp_cores;
 
+       current_mali_clock_index = clock_rate_index;
        /* NOTE: Mali is not fully initialized at this point. */
 }
 
@@ -106,7 +109,7 @@ void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
        /* NOTE: this function is normally called directly from the utilization callback which is in
         * timer context. */
 
-       if (     PERCENT_OF(90, 256) < data->utilization_pp)
+       if (PERCENT_OF(90, 256) < data->utilization_pp)
        {
                enable_max_num_cores();
        }
index 5c5def6063591901a3cc43c2f00fea3ea2dd067a..e06171569c962fda55569339b7414c48ebc1731e 100755 (executable)
@@ -25,7 +25,7 @@ struct mali_gpu_utilization_data;
  *
  * @param num_pp_cores Total number of PP cores.
  */
-void mali_core_scaling_init(int num_pp_cores);
+void mali_core_scaling_init(int num_pp_cores, int clock_rate_index);
 
 /**
  * Terminate core scaling policy.
diff --git a/mali/platform/meson8/mali_clock.c b/mali/platform/meson8/mali_clock.c
new file mode 100644 (file)
index 0000000..99ff554
--- /dev/null
@@ -0,0 +1,19 @@
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#include <mach/register.h>
+#include <mach/irqs.h>
+#include <linux/io.h>
+#include <mach/io.h>
+#include <plat/io.h>
+#include <asm/io.h>
+#include "mali_clock.h"
+
+unsigned int mali_default_clock_step = MALI_CLOCK_637;
+
+int mali_clock_set(unsigned int  clock) {
+       clrbits_le32(P_HHI_MALI_CLK_CNTL, 1 << 8);
+       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);
+}
diff --git a/mali/platform/meson8/mali_clock.h b/mali/platform/meson8/mali_clock.h
new file mode 100644 (file)
index 0000000..96eeae5
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _MALI_CLOCK_H_
+#define _MALI_CLOCK_H_
+
+typedef struct mali_dvfs_Tag{
+       unsigned int step;
+       unsigned int mali_clk;
+}mali_dvfs_table;
+
+typedef struct mali_dvfs_thresholdTag{
+       unsigned int downthreshold;
+       unsigned int upthreshold;
+}mali_dvfs_threshold_table;
+
+/* 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 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..156b4dd
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * 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 "mali_scaling.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_pp_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_pp_fs_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;
+               if (data->utilization_pp > 230) // 90%
+                       enable_max_num_cores();
+               else
+                       enable_one_core();
+       } 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;
+       }
+
+}
+
+void reset_mali_scaling_stat(void)
+{
+       printk(" ****** scaling mode reset to default.*****\n");
+       currentStep = mali_default_clock_step;
+       enable_max_num_cores();
+}
+
+void mali_fs_scaling_update(struct mali_gpu_utilization_data *data)
+{
+       
+       utilization = data->utilization_gpu;
+
+       if (utilization > mali_dvfs_threshold[currentStep].upthreshold) {
+               currentStep = MALI_CLOCK_637;
+       } else if (utilization < mali_dvfs_threshold[currentStep].downthreshold && currentStep > 0) {
+               currentStep--;
+               MALI_DEBUG_PRINT(2, ("Mali clock set %d..\n",currentStep));
+       } 
+}
+
+u32 get_mali_def_freq_idx(void)
+{
+       return mali_default_clock_step;
+}
+
+void set_mali_freq_idx(u32 idx)
+{
+       MALI_DEBUG_ASSERT(clock_rate_index < MALI_CLOCK_INDX_MAX);
+       currentStep = idx;
+       lastStep = MALI_CLOCK_INDX_MAX;
+       mali_default_clock_step = currentStep;
+       schedule_work(&wq_work);
+       /* NOTE: Mali is not fully initialized at this point. */
+}
+
+void set_mali_qq_for_sched(u32 pp_num)
+{
+       num_cores_total   = pp_num;
+       num_cores_enabled = pp_num;
+       schedule_work(&wq_work);
+}
+
+u32 get_mali_qq_for_sched(void)
+{
+       return num_cores_total; 
+}
diff --git a/mali/platform/meson8/mali_scaling.h b/mali/platform/meson8/mali_scaling.h
new file mode 100755 (executable)
index 0000000..e153bfd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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__
+
+#define MALI_PP_NUMBER 6
+
+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.
+ */
+extern void mali_pp_fs_scaling_update(struct mali_gpu_utilization_data *data);
+extern void mali_pp_scaling_update(struct mali_gpu_utilization_data *data);
+extern void mali_fs_scaling_update(struct mali_gpu_utilization_data *data);
+extern void reset_mali_scaling_stat(void);
+#endif /* __ARM_CORE_SCALING_H__ */
index 2db55735afb384502e2d009739ee1d360059d035..a49b9da2fb0032d5447999c45b66ee2c6a0c3cb2 100755 (executable)
 #include <linux/platform_device.h>
 #include <linux/version.h>
 #include <linux/pm.h>
+#include <linux/module.h>            /* kernel module definitions */
+#include <linux/ioport.h>            /* request_mem_region */
 #include <mach/register.h>
 #include <mach/irqs.h>
-#include <linux/io.h>
 #include <mach/io.h>
-#include <plat/io.h>
 #ifdef CONFIG_PM_RUNTIME
 #include <linux/pm_runtime.h>
 #endif
 #include <linux/mali/mali_utgard.h>
 #include "mali_kernel_common.h"
 
-#include "arm_core_scaling.h"
+#include "mali_scaling.h"
+#include "mali_clock.h"
+
+/* Configure dvfs mode */
+enum mali_scale_mode_t {
+       MALI_PP_SCALING,
+       MALI_FS_SCALING,
+       MALI_PP_FS_SCALING,
+       MALI_SCALING_DISABLE,
+       MALI_SCALING_MODE_MAX
+};
+
+static int  scaling_mode = MALI_PP_FS_SCALING;
+module_param(scaling_mode, int, 0664); 
+MODULE_PARM_DESC(scaling_mode, "0 disable, 1 pp, 2 fs, 4 double");
+static int last_scaling_mode;
 
 static void mali_platform_device_release(struct device *device);
 static void mali_platform_device_release(struct device *device);
@@ -36,9 +51,6 @@ static int mali_runtime_suspend(struct device *device);
 static int mali_runtime_resume(struct device *device);
 static int mali_runtime_idle(struct device *device);
 #endif
-
-static DEFINE_SPINLOCK(lock);
-
 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
 
 static struct resource mali_gpu_resources_m450[] =
@@ -108,16 +120,11 @@ static struct mali_gpu_device_data mali_gpu_data =
 
 int mali_platform_device_register(void)
 {
-       unsigned long flags;
        int err = -1;
-       int num_pp_cores = 6;
+       int num_pp_cores = MALI_PP_NUMBER;
 
-       spin_lock_irqsave(&lock, flags);
-       clrbits_le32(P_HHI_MALI_CLK_CNTL, 1 << 8);
-       writel((5 << 9 | 0), P_HHI_MALI_CLK_CNTL); /* set clock to 333MHZ.*/
-       readl(P_HHI_MALI_CLK_CNTL);
-       setbits_le32(P_HHI_MALI_CLK_CNTL, 1 << 8);
-       spin_unlock_irqrestore(&lock, flags);
+       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"));
@@ -144,8 +151,10 @@ 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_core_scaling_init(num_pp_cores, mali_default_clock_step);
+                               last_scaling_mode = scaling_mode;
 
                                return 0;
                        }
@@ -159,7 +168,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);
 }
@@ -171,7 +179,33 @@ 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);
+       if (last_scaling_mode != scaling_mode) {
+               reset_mali_scaling_stat();
+               last_scaling_mode = scaling_mode;
+       }
+       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;
+       case MALI_FS_SCALING:
+               mali_fs_scaling_update(data);
+               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();
 }
 
 static int mali_os_suspend(struct device *device)