From 4d330bafa3b4cba7d5e6d7db0fa04171a23fafc5 Mon Sep 17 00:00:00 2001
From: aosp <aosp@no-replay.net>
Date: Thu, 1 Mar 2018 12:09:19 +0100
Subject: [PATCH] hi3798mv200 support

---
 .../driver/src/devicedrv/mali/Kbuild               |  31 +-
 .../driver/src/devicedrv/mali/Kconfig              |  14 +-
 .../driver/src/devicedrv/mali/MALI_CONFIGURATION   |  18 +
 .../driver/src/devicedrv/mali/Makefile             |  18 +-
 .../src/devicedrv/mali/common/mali_executor.c      |   3 +-
 .../src/devicedrv/mali/common/mali_executor.h      |   2 +
 .../driver/src/devicedrv/mali/common/mali_gp_job.c |   2 +-
 .../src/devicedrv/mali/common/mali_pm_metrics.c    |  58 ++
 .../src/devicedrv/mali/common/mali_pm_metrics.h    |   6 +
 .../src/devicedrv/mali/common/mali_soft_job.c      |   4 +
 .../driver/src/devicedrv/mali/kbuild_flags         | 111 ++++
 .../driver/src/devicedrv/mali/linux/mali_devfreq.c |  27 +
 .../src/devicedrv/mali/linux/mali_kernel_linux.c   |  19 +
 .../src/devicedrv/mali/linux/mali_linux_trace.h    |   2 +
 .../src/devicedrv/mali/platform/dt/drv_gpu_ext.h   |  17 +
 .../src/devicedrv/mali/platform/dt/hi_drv_module.h |  57 ++
 .../src/devicedrv/mali/platform/dt/hi_module.h     | 182 ++++++
 .../src/devicedrv/mali/platform/dt/hi_type.h       | 142 +++++
 .../src/devicedrv/mali/platform/dt/mali4xx_cfg.h   |  25 +
 .../src/devicedrv/mali/platform/dt/mali4xx_dt.c    | 652 +++++++++++++++++++++
 .../src/devicedrv/mali/platform/dt/mali4xx_dt.h    |  41 ++
 .../src/devicedrv/mali/platform/dt/mali4xx_opp.c   | 270 +++++++++
 .../src/devicedrv/mali/platform/dt/mali4xx_opp.h   |  29 +
 .../src/devicedrv/mali/platform/dt/mali4xx_proc.c  | 384 ++++++++++++
 .../src/devicedrv/mali/platform/dt/mali4xx_proc.h  |  15 +
 .../devicedrv/mali/platform/dt/mali4xx_scaling.c   | 118 ++++
 .../devicedrv/mali/platform/dt/mali4xx_scaling.h   |  31 +
 27 files changed, 2249 insertions(+), 29 deletions(-)
 create mode 100755 driver/src/devicedrv/mali/MALI_CONFIGURATION
 create mode 100755 driver/src/devicedrv/mali/kbuild_flags
 create mode 100755 driver/src/devicedrv/mali/platform/dt/drv_gpu_ext.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/hi_drv_module.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/hi_module.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/hi_type.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_cfg.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_dt.c
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_dt.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_opp.c
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_opp.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_proc.c
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_proc.h
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.c
 create mode 100755 driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.h

diff --git a/driver/src/devicedrv/mali/Kbuild b/driver/src/devicedrv/mali/Kbuild
index 37cdeb9..7412e9e
--- a/driver/src/devicedrv/mali/Kbuild
+++ b/driver/src/devicedrv/mali/Kbuild
@@ -11,9 +11,10 @@
 # This file is called by the Linux build system.
 
 # set up defaults if not defined by the user
+include $(src)/kbuild_flags
 TIMESTAMP ?= default
 OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16
-USING_GPU_UTILIZATION ?= 0
+USING_GPU_UTILIZATION ?= 1
 PROFILING_SKIP_PP_JOBS ?= 0
 PROFILING_SKIP_PP_AND_GP_JOBS ?= 0
 MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0
@@ -25,21 +26,21 @@ MALI_ENABLE_CPU_CYCLES ?= 0
 # For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases:
 # The ARM proprietary product will only include the license/proprietary directory
 # The GPL product will only include the license/gpl directory
-ifeq ($(wildcard $(src)/linux/license/gpl/*),)
-    ccflags-y += -I$(src)/linux/license/proprietary
-    ifeq ($(CONFIG_MALI400_PROFILING),y)
-        $(error Profiling is incompatible with non-GPL license)
-    endif
-    ifeq ($(CONFIG_PM_RUNTIME),y)
-        $(error Runtime PM is incompatible with non-GPL license)
-    endif
-    ifeq ($(CONFIG_DMA_SHARED_BUFFER),y)
-        $(error DMA-BUF is incompatible with non-GPL license)
-    endif
-    $(error Linux Device integration is incompatible with non-GPL license)
-else
+#ifeq ($(wildcard $(src)/linux/license/gpl/*),)
+#    ccflags-y += -I$(src)/linux/license/proprietary
+#    ifeq ($(CONFIG_MALI400_PROFILING),y)
+#        $(error Profiling is incompatible with non-GPL license)
+#    endif
+#    ifeq ($(CONFIG_PM_RUNTIME),y)
+#        $(error Runtime PM is incompatible with non-GPL license)
+#    endif
+#    ifeq ($(CONFIG_DMA_SHARED_BUFFER),y)
+#        $(error DMA-BUF is incompatible with non-GPL license)
+#    endif
+#    $(error Linux Device integration is incompatible with non-GPL license)
+#else
     ccflags-y += -I$(src)/linux/license/gpl
-endif
+#endif
 
 ifeq ($(USING_GPU_UTILIZATION), 1)
     ifeq ($(USING_DVFS), 1)
diff --git a/driver/src/devicedrv/mali/Kconfig b/driver/src/devicedrv/mali/Kconfig
index 7b4e9fb..18fd377
--- a/driver/src/devicedrv/mali/Kconfig
+++ b/driver/src/devicedrv/mali/Kconfig
@@ -69,7 +69,7 @@ config MALI_DMA_BUF_MAP_ON_ATTACH
 config MALI_SHARED_INTERRUPTS
 	bool "Support for shared interrupts"
 	depends on MALI400
-	default n
+	default y
 	---help---
 	  Adds functionality required to properly support shared interrupts.  Without this support,
 	  the device driver will fail during insmod if it detects shared interrupts.  This also
@@ -115,3 +115,15 @@ config MALI_QUIET
 	  This forces the Mali driver to never print any messages.
 
 	  If unsure, say N.
+config GPU_MAX_SHARE_MEM_SIZE
+	hex "Mali400 and OS maximal shared memory size"
+	depends on MALI400
+	default "0x10000000"
+	---help---
+	  This constricts the maximal memory GPU could get from os memory.
+config GPU_DVFS_ENABLE
+	bool "Enable GPU DVFS"
+	depends on MALI400
+	default n
+	---help---
+	  This enables GPU DVFS function.
diff --git a/driver/src/devicedrv/mali/MALI_CONFIGURATION b/driver/src/devicedrv/mali/MALI_CONFIGURATION
new file mode 100644
index 0000000..be93771
--- /dev/null
+++ b/driver/src/devicedrv/mali/MALI_CONFIGURATION
@@ -0,0 +1,12 @@
+include kbuild_flags
+#===============================================================================
+# export variables
+#===============================================================================
+USING_UMP:=0
+MALI_SHARED_INTERRUPTS:=1
+
+# Location of default kernels
+KDIR-$(TARGET_PLATFORM):=$(LINUX_DIR)
+
+# Name of platform directory with platform specific code (should be built into kernel on a real system) 
+MALI_PLATFORM-$(TARGET_PLATFORM)=mali450
diff --git a/driver/src/devicedrv/mali/Makefile b/driver/src/devicedrv/mali/Makefile
old mode 100755
new mode 100644
index f39ae4d..5a27cd4
--- a/driver/src/devicedrv/mali/Makefile
+++ b/driver/src/devicedrv/mali/Makefile
@@ -10,8 +10,8 @@
 
 USE_UMPV2=0
 USING_PROFILING ?= 1
-USING_INTERNAL_PROFILING ?= 0
-USING_DVFS ?= 1
+USING_INTERNAL_PROFILING ?= 1
+USING_DVFS ?= 0
 USING_DMA_BUF_FENCE ?= 0
 MALI_HEATMAPS_ENABLED ?= 0
 MALI_DMA_BUF_MAP_ON_ATTACH ?= 1
@@ -52,7 +52,7 @@ $(warning "You have specified the CPU variable which is no longer in used. Use T
 endif
 
 # Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM
--include MALI_CONFIGURATION
+include MALI_CONFIGURATION
 export KDIR ?= $(KDIR-$(TARGET_PLATFORM))
 export MALI_PLATFORM ?= $(MALI_PLATFORM-$(TARGET_PLATFORM))
 
@@ -89,7 +89,6 @@ endif
 KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build
 
 include $(KDIR)/.config
-
 ifeq ($(ARCH), arm)
 # when compiling for ARM we're cross compiling
 export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-)
@@ -103,13 +102,11 @@ $(warning MALI_PLATFORM $(MALI_PLATFORM))
 endif
 
 # Set up build config
-export CONFIG_MALI400=m
-export CONFIG_MALI450=y
-export CONFIG_MALI470=y
+#export CONFIG_MALI400=m
+#export CONFIG_MALI450=y
 
-export EXTRA_DEFINES += -DCONFIG_MALI400=1
-export EXTRA_DEFINES += -DCONFIG_MALI450=1
-export EXTRA_DEFINES += -DCONFIG_MALI470=1
+#export EXTRA_DEFINES += -DCONFIG_MALI400=1
+#export EXTRA_DEFINES += -DCONFIG_MALI450=1
 
 ifneq ($(MALI_PLATFORM),)
 export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1
@@ -122,6 +119,7 @@ $(warning CONFIG_TRACEPOINTS required for profiling)
 else
 export CONFIG_MALI400_PROFILING=y
 export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1
+
 ifeq ($(USING_INTERNAL_PROFILING),1)
 export CONFIG_MALI400_INTERNAL_PROFILING=y
 export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1
diff --git a/driver/src/devicedrv/mali/common/mali_executor.c b/driver/src/devicedrv/mali/common/mali_executor.c
old mode 100755
new mode 100644
index 21acccc..45186e3
--- a/driver/src/devicedrv/mali/common/mali_executor.c
+++ b/driver/src/devicedrv/mali/common/mali_executor.c
@@ -125,7 +125,6 @@ static void mali_executor_disable_empty_virtual(void);
 static mali_bool mali_executor_physical_rejoin_virtual(struct mali_group *group);
 static mali_bool mali_executor_has_virtual_group(void);
 static mali_bool mali_executor_virtual_group_is_usable(void);
-static void mali_executor_schedule(void);
 static void mali_executor_wq_schedule(void *arg);
 static void mali_executor_send_gp_oom_to_user(struct mali_gp_job *job);
 static void mali_executor_complete_group(struct mali_group *group,
@@ -1556,7 +1555,7 @@ static mali_bool mali_executor_schedule_is_early_out(mali_bool *gpu_secure_mode_
 /*
  * This is where jobs are actually started.
  */
-static void mali_executor_schedule(void)
+void mali_executor_schedule(void)
 {
 	u32 i;
 	u32 num_physical_needed = 0;
diff --git a/driver/src/devicedrv/mali/common/mali_executor.h b/driver/src/devicedrv/mali/common/mali_executor.h
old mode 100755
new mode 100644
index 1d69dc3..780f472
--- a/driver/src/devicedrv/mali/common/mali_executor.h
+++ b/driver/src/devicedrv/mali/common/mali_executor.h
@@ -40,6 +40,8 @@ void mali_executor_depopulate(void);
 void mali_executor_suspend(void);
 void mali_executor_resume(void);
 
+void mali_executor_schedule(void);
+
 u32 mali_executor_get_num_cores_total(void);
 u32 mali_executor_get_num_cores_enabled(void);
 struct mali_pp_core *mali_executor_get_virtual_pp(void);
diff --git a/driver/src/devicedrv/mali/common/mali_gp_job.c b/driver/src/devicedrv/mali/common/mali_gp_job.c
old mode 100755
new mode 100644
index 00a2d1e..fb8dcd8
--- a/driver/src/devicedrv/mali/common/mali_gp_job.c
+++ b/driver/src/devicedrv/mali/common/mali_gp_job.c
@@ -133,7 +133,7 @@ struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_
 				goto fail1;
 			}
 
-			memory_list = (u32 __user *)(uintptr_t)uargs->deferred_mem_list;
+			memory_list = (u32 __user *)(uintptr_t)job->uargs.deferred_mem_list;
 
 			if (0 != _mali_osk_copy_from_user(job->varying_list, memory_list, sizeof(u32) * job->uargs.deferred_mem_num)) {
 				MALI_PRINT_ERROR(("Mali GP job: Failed to copy varying list from user space!\n"));
diff --git a/driver/src/devicedrv/mali/common/mali_pm_metrics.c b/driver/src/devicedrv/mali/common/mali_pm_metrics.c
old mode 100755
new mode 100644
index 981ec81..5439a47
--- a/driver/src/devicedrv/mali/common/mali_pm_metrics.c
+++ b/driver/src/devicedrv/mali/common/mali_pm_metrics.c
@@ -174,15 +174,45 @@ void mali_pm_record_gpu_active(mali_bool is_gp)
 static void mali_pm_get_dvfs_utilisation_calc(struct mali_device *mdev, ktime_t now)
 {
 	ktime_t diff;
+#if defined(UTGARD_HISILICON_PLUGIN)
+	ktime_t diff_gp, diff_pp;
+#endif
 
 	MALI_DEBUG_ASSERT(mdev != NULL);
 
 	diff = ktime_sub(now, mdev->mali_metrics.time_period_start);
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+	diff_gp = ktime_sub(now, mdev->mali_metrics.time_period_start_gp);
+	diff_pp = ktime_sub(now, mdev->mali_metrics.time_period_start_pp);
+#endif
+
 	if (mdev->mali_metrics.gpu_active) {
 		mdev->mali_metrics.time_busy += (u64)(ktime_to_ns(diff) >> MALI_PM_TIME_SHIFT);
+
+#if defined(UTGARD_HISILICON_PLUGIN)
+	if(1 == mdev->mali_metrics.num_running_gp_cores)
+	{
+		mdev->mali_metrics.time_busy_gp += (u64)(ktime_to_ns(diff_gp) >> MALI_PM_TIME_SHIFT);
+	}
+	else
+	{
+		mdev->mali_metrics.time_busy_pp[0] += (u64)(ktime_to_ns(diff_pp) >> MALI_PM_TIME_SHIFT);
+	}
+#endif
 	} else {
 		mdev->mali_metrics.time_idle += (u64)(ktime_to_ns(diff) >> MALI_PM_TIME_SHIFT);
+
+#if defined(UTGARD_HISILICON_PLUGIN)
+	if(1 == mdev->mali_metrics.num_running_gp_cores)
+	{
+		mdev->mali_metrics.time_idle_gp += (u64)(ktime_to_ns(diff_gp) >> MALI_PM_TIME_SHIFT);
+	}
+	else
+	{
+		mdev->mali_metrics.time_idle_pp[0] += (u64)(ktime_to_ns(diff_pp) >> MALI_PM_TIME_SHIFT);
+	}
+#endif
 	}
 }
 
@@ -193,6 +223,13 @@ static void mali_pm_reset_dvfs_utilisation_unlocked(struct mali_device *mdev, kt
 	mdev->mali_metrics.prev_idle = mdev->mali_metrics.time_idle;
 	mdev->mali_metrics.prev_busy = mdev->mali_metrics.time_busy;
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+	mdev->mali_metrics.prev_idle_gp = mdev->mali_metrics.time_idle_gp;
+	mdev->mali_metrics.prev_busy_gp = mdev->mali_metrics.time_busy_gp;
+	mdev->mali_metrics.prev_idle_pp[0] = mdev->mali_metrics.time_idle_pp[0];
+	mdev->mali_metrics.prev_busy_pp[0] = mdev->mali_metrics.time_busy_pp[0];
+#endif
+
 	/* Reset current values */
 	mdev->mali_metrics.time_period_start = now;
 	mdev->mali_metrics.time_period_start_gp = now;
@@ -220,6 +257,11 @@ void mali_pm_get_dvfs_utilisation(struct mali_device *mdev,
 	u64 busy = 0;
 	u64 total = 0;
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+	u64 busy_gp = 0, total_gp = 0;
+	u64 busy_pp = 0, total_pp = 0;
+#endif
+
 	_mali_osk_spinlock_irq_lock(mdev->mali_metrics.lock);
 
 	mali_pm_get_dvfs_utilisation_calc(mdev, now);
@@ -227,6 +269,13 @@ void mali_pm_get_dvfs_utilisation(struct mali_device *mdev,
 	busy = mdev->mali_metrics.time_busy;
 	total = busy + mdev->mali_metrics.time_idle;
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+	busy_gp = mdev->mali_metrics.time_busy_gp;
+	total_gp = busy_gp + mdev->mali_metrics.time_idle_gp;
+	busy_pp = mdev->mali_metrics.time_busy_pp[0];
+	total_pp = busy_pp + mdev->mali_metrics.time_idle_pp[0];
+#endif
+
 	/* Reset stats if older than MALI_UTILIZATION_MAX_PERIOD (default
 	 * 100ms) */
 	if (total >= MALI_UTILIZATION_MAX_PERIOD) {
@@ -235,6 +284,15 @@ void mali_pm_get_dvfs_utilisation(struct mali_device *mdev,
 		total += mdev->mali_metrics.prev_idle +
 			 mdev->mali_metrics.prev_busy;
 		busy += mdev->mali_metrics.prev_busy;
+
+#if defined(UTGARD_HISILICON_PLUGIN)
+		total_gp += mdev->mali_metrics.prev_idle_gp +
+             mdev->mali_metrics.prev_busy_gp;
+		busy_gp += mdev->mali_metrics.prev_busy_gp;
+		total_pp += mdev->mali_metrics.prev_idle_pp[0] +
+             mdev->mali_metrics.prev_busy_pp[0];
+		busy_pp += mdev->mali_metrics.prev_busy_pp[0];
+#endif
 	}
 
 	*total_out = (unsigned long)total;
diff --git a/driver/src/devicedrv/mali/common/mali_pm_metrics.h b/driver/src/devicedrv/mali/common/mali_pm_metrics.h
old mode 100755
new mode 100644
index 256f448..88283e8
--- a/driver/src/devicedrv/mali/common/mali_pm_metrics.h
+++ b/driver/src/devicedrv/mali/common/mali_pm_metrics.h
@@ -31,9 +31,15 @@ struct mali_pm_metrics_data {
 	ktime_t time_period_start_gp;
 	u64 time_busy_gp;
 	u64 time_idle_gp;
+	u64 prev_busy_gp;
+	u64 prev_idle_gp;
+
 	ktime_t time_period_start_pp;
 	u64 time_busy_pp[MALI_MAX_NUMBER_OF_PHYSICAL_PP_GROUPS];
 	u64 time_idle_pp[MALI_MAX_NUMBER_OF_PHYSICAL_PP_GROUPS];
+	u64 prev_busy_pp[MALI_MAX_NUMBER_OF_PHYSICAL_PP_GROUPS];
+	u64 prev_idle_pp[MALI_MAX_NUMBER_OF_PHYSICAL_PP_GROUPS];
+
 	mali_bool gpu_active;
 	_mali_osk_spinlock_irq_t *lock;
 };
diff --git a/driver/src/devicedrv/mali/common/mali_soft_job.c b/driver/src/devicedrv/mali/common/mali_soft_job.c
old mode 100755
new mode 100644
index c76d1fe..2798435
--- a/driver/src/devicedrv/mali/common/mali_soft_job.c
+++ b/driver/src/devicedrv/mali/common/mali_soft_job.c
@@ -435,4 +435,8 @@ void mali_soft_job_system_abort(struct mali_soft_job_system *system)
 
 		mali_soft_job_destroy(job);
 	}
+
+	mali_executor_lock();
+	mali_executor_schedule();
+	mali_executor_unlock();
 }
diff --git a/driver/src/devicedrv/mali/kbuild_flags b/driver/src/devicedrv/mali/kbuild_flags
new file mode 100644
index 0000000..8daeb3f
--- /dev/null
+++ b/driver/src/devicedrv/mali/kbuild_flags
@@ -0,0 +1,111 @@
+#===============================================================================
+# export variables
+#===============================================================================
+
+#SDK include header files
+export EXTRA_CFLAGS += -I$(COMMON_UNF_INCLUDE)                 \
+                -I$(COMMON_DRV_INCLUDE)                 \
+                -I$(MSP_DRV_INCLUDE)                
+
+#build in or not
+export CONFIG_MALI400=$(HI_DRV_BUILDTYPE)
+
+export CONFIG_MALI450=$(HI_DRV_BUILDTYPE)
+
+export EXTRA_DEFINES += -DCONFIG_MALI450=1
+export TARGET_PLATFORM=mali450
+
+#SDK flags  
+export EXTRA_DEFINES += $(CFG_HI_KMOD_CFLAGS)
+
+#if use pmu, we need i2c driver
+ifeq ($(CFG_HI_PMU_DEVICE_SELECT),y)
+export EXTRA_DEFINES += -DCONFIG_HI_PMU_DEVICE_SELECT
+export EXTRA_DEFINES += -I$(COMMON_UNF_INCLUDE) -I$(COMMON_DRV_INCLUDE) -I$(MSP_DRV_INCLUDE)
+endif
+
+# Max GPU and OS shared memory size
+export EXTRA_DEFINES += -DCONFIG_GPU_MAX_SHARE_MEM_SIZE=0x20000000
+
+# Enable DMA Buffer map on attach
+export CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y
+export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH
+
+#whether enable dvfs or not
+export CONFIG_GPU_DVFS_ENABLE=y
+export EXTRA_DEFINES += -DCONFIG_GPU_DVFS_ENABLE
+
+#whether enable avs or not
+ifeq ($(CFG_HI_AVS_SUPPORT),y)
+export CONFIG_GPU_AVS_ENABLE=y
+export EXTRA_DEFINES += -DCONFIG_GPU_AVS_ENABLE
+endif
+
+#if buildin, we should enable share interrupt and FAKE Driver here
+export CONFIG_MALI_SHARED_INTERRUPTS=y
+export EXTRA_DEFINES += -DCONFIG_MALI_SHARED_INTERRUPTS
+
+#debug or release
+ifeq ($(CONFIG_MALI400_DEBUG),y)
+BUILD=debug
+else
+BUILD=release
+endif
+
+HI_GPU_PROFILING=y
+HI_GPU_INTERNAL_PROFILING=n
+
+#profiling
+ifeq ($(CFG_HI_ADVCA_SUPPORT), y)
+HI_GPU_PROFILING=n
+HI_GPU_INTERNAL_PROFILING=n
+endif
+
+ifeq ($(CONFIG_MALI_QUIET),y)
+export EXTRA_DEFINES += -DCONFIG_MALI_QUIET
+endif
+
+ifeq ($(HI_GPU_PROFILING), y)
+USING_PROFILING=1
+export CONFIG_MALI400_PROFILING=y
+export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1
+else
+USING_PROFILING=0
+endif
+
+#internal profiling
+ifeq ($(HI_GPU_INTERNAL_PROFILING), y)
+USING_INTERNAL_PROFILING=1
+export CONFIG_MALI400_INTERNAL_PROFILING=y
+export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1
+else
+USING_INTERNAL_PROFILING=0
+endif
+
+ifeq ($(CFG_HI_TEMP_CTRL_CONFIG), y)
+export EXTRA_DEFINES += -DCFG_TEMP_CTRL_CONFIG=1
+export EXTRA_DEFINES += -DCFG_TEMP_CTRL_DOWN_THRESHOLD=$(CFG_HI_TEMP_CTRL_DOWN_THRESHOLD)
+export EXTRA_DEFINES += -DCFG_TEMP_CTRL_UP_THRESHOLD=$(CFG_HI_TEMP_CTRL_UP_THRESHOLD)
+endif
+
+#device tree
+
+export CONFIG_MALI_DT=y
+export EXTRA_DEFINES += -DCONFIG_MALI_DT=1
+export EXTRA_DEFINES += -DUTGARD_HISILICON_PLUGIN=1
+#hisi integration
+export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1
+
+export CONFIG_MALI_DT=y
+export EXTRA_DEFINES += -DCONFIG_MALI_DT=1
+export CONFIG_MALI_DEVFREQ=y
+export EXTRA_DEFINES += -DCONFIG_MALI_DEVFREQ=1
+export MALI_PLATFORM_FILES = platform/dt/mali4xx_dt.c \
+                             platform/dt/mali4xx_proc.c \
+                             platform/dt/mali4xx_scaling.c \
+                             platform/dt/mali4xx_opp.c
+
+
+
+
+
diff --git a/driver/src/devicedrv/mali/linux/mali_devfreq.c b/driver/src/devicedrv/mali/linux/mali_devfreq.c
old mode 100755
new mode 100644
index 0b0ba14..407f588
--- a/driver/src/devicedrv/mali/linux/mali_devfreq.c
+++ b/driver/src/devicedrv/mali/linux/mali_devfreq.c
@@ -36,6 +36,12 @@
 
 #include "mali_pm_metrics.h"
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+#include "platform/dt/mali4xx_dt.h"
+#include "platform/dt/mali4xx_opp.h"
+#include "platform/dt/mali4xx_cfg.h"
+#endif
+
 static int
 mali_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
 {
@@ -121,10 +127,17 @@ mali_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
 
 	stat->current_frequency = mdev->current_freq;
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+	stat->private_data = mali_adp_get_configuration(mdev);
+
+	mali_pm_get_dvfs_utilisation(mdev,
+				     &stat->total_time, &stat->busy_time);
+#else
 	mali_pm_get_dvfs_utilisation(mdev,
 				     &stat->total_time, &stat->busy_time);
 
 	stat->private_data = NULL;
+#endif
 
 #ifdef CONFIG_DEVFREQ_THERMAL
 	memcpy(&mdev->devfreq->last_status, stat, sizeof(*stat));
@@ -133,6 +146,9 @@ mali_devfreq_status(struct device *dev, struct devfreq_dev_status *stat)
 	return 0;
 }
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+
+#else
 /* setup platform specific opp in platform.c*/
 int __weak setup_opps(void)
 {
@@ -144,6 +160,7 @@ int __weak term_opps(struct device *dev)
 {
 	return 0;
 }
+#endif
 
 static int mali_devfreq_init_freq_table(struct mali_device *mdev,
 					struct devfreq_dev_profile *dp)
@@ -153,7 +170,11 @@ static int mali_devfreq_init_freq_table(struct mali_device *mdev,
 	unsigned long freq = 0;
 	struct dev_pm_opp *opp;
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+    err = setup_opps(mdev->dev);
+#else
 	err = setup_opps();
+#endif
 	if (err)
 		return err;
 
@@ -235,8 +256,14 @@ int mali_devfreq_init(struct mali_device *mdev)
 	if (mali_devfreq_init_freq_table(mdev, dp))
 		return -EFAULT;
 
+#if defined(UTGARD_HISILICON_PLUGIN)
+	mdev->devfreq = devfreq_add_device(mdev->dev, dp,
+					   "gpu_ondemand", NULL);
+#else
 	mdev->devfreq = devfreq_add_device(mdev->dev, dp,
 					   "simple_ondemand", NULL);
+#endif
+
 	if (IS_ERR(mdev->devfreq)) {
 		mali_devfreq_term_freq_table(mdev);
 		return PTR_ERR(mdev->devfreq);
diff --git a/driver/src/devicedrv/mali/linux/mali_kernel_linux.c b/driver/src/devicedrv/mali/linux/mali_kernel_linux.c
old mode 100755
new mode 100644
index 9bfa2bd..6a98adc
--- a/driver/src/devicedrv/mali/linux/mali_kernel_linux.c
+++ b/driver/src/devicedrv/mali/linux/mali_kernel_linux.c
@@ -561,7 +561,12 @@ static int mali_probe(struct platform_device *pdev)
 		mdev->clock = NULL;
 		/* Allow probe to continue without clock. */
 	} else {
+#if defined(UTGARD_HISILICON_PLUGIN)
+		err = clk_prepare(mdev->clock);
+		err |= clk_enable(mdev->clock);
+#else
 		err = clk_prepare_enable(mdev->clock);
+#endif
 		if (err) {
 			MALI_PRINT_ERROR(("Failed to prepare and enable clock (%d)\n", err));
 			goto clock_prepare_failed;
@@ -593,6 +598,10 @@ static int mali_probe(struct platform_device *pdev)
 				if (0 == err) {
 					MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name));
 
+#if defined(UTGARD_HISILICON_PLUGIN) && defined(CONFIG_MALI_DEVFREQ)
+					/* Disable clock, for make the count to be 0, and the power change function can enable the clock */
+					clk_disable(mdev->clock);
+#endif
 					return 0;
 				} else {
 					MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries"));
@@ -613,7 +622,12 @@ static int mali_probe(struct platform_device *pdev)
 devfreq_init_failed:
 	mali_pm_metrics_term(mdev);
 pm_metrics_init_failed:
+#if defined(UTGARD_HISILICON_PLUGIN)
+	clk_disable(mdev->clock);
+	clk_unprepare(mdev->clock);
+#else
 	clk_disable_unprepare(mdev->clock);
+#endif
 clock_prepare_failed:
 	clk_put(mdev->clock);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(CONFIG_OF) \
@@ -653,7 +667,12 @@ static int mali_remove(struct platform_device *pdev)
 	mali_pm_metrics_term(mdev);
 
 	if (mdev->clock) {
+#if defined(UTGARD_HISILICON_PLUGIN)
+		/* Because the power change fucntion had already disable the clock */
+		clk_unprepare(mdev->clock);
+#else
 		clk_disable_unprepare(mdev->clock);
+#endif
 		clk_put(mdev->clock);
 		mdev->clock = NULL;
 	}
diff --git a/driver/src/devicedrv/mali/linux/mali_linux_trace.h b/driver/src/devicedrv/mali/linux/mali_linux_trace.h
old mode 100755
new mode 100644
index 2c91ddc..ecf9bf7
--- a/driver/src/devicedrv/mali/linux/mali_linux_trace.h
+++ b/driver/src/devicedrv/mali/linux/mali_linux_trace.h
@@ -18,7 +18,9 @@
 
 #undef  TRACE_SYSTEM
 #define TRACE_SYSTEM mali
+#ifndef TRACEPOINTS_ENABLED
 #define TRACE_SYSTEM_STRING __stringfy(TRACE_SYSTEM)
+#endif
 
 #define TRACE_INCLUDE_PATH .
 #define TRACE_INCLUDE_FILE mali_linux_trace
diff --git a/driver/src/devicedrv/mali/platform/dt/drv_gpu_ext.h b/driver/src/devicedrv/mali/platform/dt/drv_gpu_ext.h
new file mode 100644
index 0000000..a2908bb
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/drv_gpu_ext.h
@@ -0,0 +1,17 @@
+#ifndef __DRV_GPU_EXT_H__
+#define __DRV_GPU_EXT_H__
+
+#include "hi_drv_module.h"
+#include "hi_module.h"
+#include "hi_type.h"
+
+typedef HI_S32 (*FN_GPU_Set_Freq_And_Volt)(HI_S32 s32Freq, HI_S32 s32Volt, HI_S32 s32DvfsEnable);
+typedef HI_S32 (*FN_GPU_Set_Max_Freq)(HI_S32 s32Freq);
+typedef struct
+{
+    FN_GPU_Set_Freq_And_Volt	pfnGPUSetFreqAndVolt;
+    FN_GPU_Set_Max_Freq		pfnGPUSetMaxFreq;
+}GPU_EXT_FUNC_S;
+
+#endif /* __DRV_GPU_EXT_H__ */
+
diff --git a/driver/src/devicedrv/mali/platform/dt/hi_drv_module.h b/driver/src/devicedrv/mali/platform/dt/hi_drv_module.h
new file mode 100644
index 0000000..55330d5
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/hi_drv_module.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+Copyright (C), 2012-2014, Hisilicon Tech. Co., Ltd.
+******************************************************************************
+File Name     : hi_drv_module.h
+Version       : V1.0 Initial Draft
+Author        : sdk
+Created       : 2012/6/19
+Last Modified :
+Description   : The module manager.
+Function List : None.
+History       :
+******************************************************************************/
+
+#ifndef __HI_DRV_MODULE_H__
+#define __HI_DRV_MODULE_H__
+
+#include "hi_type.h"
+
+#ifdef __cplusplus
+ #if __cplusplus
+extern "C" {
+ #endif
+#endif /* __cplusplus */
+
+#define HI_KMODULE_MAX_COUNT      (256)
+#define HI_KMODULE_MEM_MAX_COUNT  (256*256)
+
+#define HI_FATAL_MODULE(fmt...)    HI_FATAL_PRINT(HI_ID_MODULE, fmt)
+#define HI_ERR_MODULE(fmt...)      HI_ERR_PRINT(HI_ID_MODULE, fmt)
+#define HI_WARN_MODULE(fmt...)     HI_WARN_PRINT(HI_ID_MODULE, fmt)
+#define HI_INFO_MODULE(fmt...)     HI_INFO_PRINT(HI_ID_MODULE, fmt)
+
+HI_S32  HI_DRV_MMNGR_Init(HI_U32 u32ModuleCount, HI_U32 u32ModuleMemCount);
+HI_VOID HI_DRV_MMNGR_Exit(HI_VOID);
+
+HI_S32 HI_DRV_MODULE_AllocId(HI_U8* pu8ModuleName, HI_U32 *pu32ModuleID, HI_S32 *ps32Status);
+HI_S32 HI_DRV_MODULE_Register(HI_U32 u32ModuleID, const HI_U8* pu8ModuleName, HI_VOID* pFunc);
+HI_S32 HI_DRV_MODULE_UnRegister(HI_U32 u32ModuleID);
+
+#ifdef CMN_MMGR_SUPPORT
+HI_U8* HI_DRV_MODULE_GetNameByID(HI_U32 u32ModuleID);
+HI_U32 HI_DRV_MODULE_GetIDByName(HI_U8* pu8Name);
+#endif
+
+HI_S32 HI_DRV_MODULE_GetFunction(HI_U32 u32ModuleID, HI_VOID** ppFunc);
+
+HI_S32  MMNGR_DRV_ModInit(HI_U32 u32ModuleCount, HI_U32 u32ModuleMemCount);
+HI_VOID MMNGR_DRV_ModExit(HI_VOID);
+
+#ifdef __cplusplus
+ #if __cplusplus
+}
+ #endif
+#endif /* __cplusplus */
+
+#endif /* __HI_DRV_MODULE_H__ */
+
diff --git a/driver/src/devicedrv/mali/platform/dt/hi_module.h b/driver/src/devicedrv/mali/platform/dt/hi_module.h
new file mode 100755
index 0000000..3300708
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/hi_module.h
@@ -0,0 +1,182 @@
+/******************************************************************************
+Copyright (C), 2012-2014, Hisilicon Tech. Co., Ltd.
+******************************************************************************
+File Name     : hi_module.h
+Version       : V1.0 Initial Draft
+Author        : sdk
+Created       : 2012/6/19
+Last Modified :
+Description   : The module name definition for all the MODULES
+Function List : None.
+History       :
+******************************************************************************/
+/** @addtogroup   MODULES  */
+/** @{ */  /** <!-- [MODULES] */
+#ifndef __HI_MODULE_H__
+#define __HI_MODULE_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+#define HI_INVALID_MODULE_ID        (0xffffffff)
+#define HI_MAX_USER_MODULE_NUMBER   (256)
+
+/** Module ID flags */
+typedef enum hiMOD_ID_E
+{
+    HI_ID_STB         = 0,
+
+    /**< common. */ /**< CNcomment: ϵͳͨ��ö�����ݳ��� */
+    HI_ID_SYS         = 1,
+    HI_ID_MODULE      ,
+    HI_ID_LOG         ,
+    HI_ID_PROC        ,
+    HI_ID_MEM         ,
+    HI_ID_STAT        ,
+    HI_ID_PDM         ,
+    HI_ID_MEMDEV      ,
+
+    HI_ID_DEMUX       = 0x0A,
+    HI_ID_TSIO,
+
+    /**< audio. */ /**< CNcomment: ��Ƶ���ֳ����� */
+    HI_ID_ADEC        = 0x10,
+    HI_ID_AO          ,
+    HI_ID_SIO_AI      ,
+    HI_ID_SIO_AO      ,
+    HI_ID_SIO         ,
+    HI_ID_AI          ,
+    HI_ID_AENC        ,
+    HI_ID_SRC         ,
+    HI_ID_AIAO        ,
+    HI_ID_AFLT        ,
+    HI_ID_ADSP        ,
+    HI_ID_AMP         ,
+    HI_ID_SIF         ,
+
+    /**< video. */ /**< CNcomment: ��Ƶ���ֳ����� */
+    HI_ID_VFMW        = 0x20,
+    HI_ID_SVDEC       ,
+    HI_ID_DISP        ,
+    HI_ID_HDMI        ,
+    HI_ID_VO          ,
+    HI_ID_VPSS        ,
+    HI_ID_VDEC        ,
+    HI_ID_VI          ,
+    HI_ID_VENC        ,
+    HI_ID_PQ         ,
+    HI_ID_EDID,
+    HI_ID_VICAP       ,
+    HI_ID_HDMIRX      ,
+    /**< graphics. */ /**< CNcomment: ͼ�β��ֳ����� */
+    HI_ID_TDE         = 0x30,
+    HI_ID_JPGDEC      ,
+    HI_ID_JPGENC      ,
+    HI_ID_FB          ,
+    HI_ID_PNG         ,
+    HI_ID_HIGO        ,
+    HI_ID_GFX2D       ,
+
+    /**< player. */ /**< CNcomment: ������ز��ֳ����� */
+    HI_ID_PVR         = 0x40,
+    HI_ID_AVPLAY      ,
+    HI_ID_SYNC        ,
+    HI_ID_VSYNC       ,
+    HI_ID_ASYNC       ,
+    HI_ID_FASTPLAY ,
+
+    /**< ecs. */ /**< CNcomment: ���貿�ֳ����� */
+    HI_ID_FLASH       = 0x50,
+    HI_ID_IR          ,
+    HI_ID_RTC         ,
+    HI_ID_I2C         ,
+    HI_ID_SCI         ,
+    HI_ID_ETH         ,
+    HI_ID_USB_PROTECT ,
+    HI_ID_WDG         = 0x57,   /* watch dog used 'W' */
+    HI_ID_GPIO        ,
+    HI_ID_GPIO_I2C    ,
+    HI_ID_DMAC        ,
+    HI_ID_PMOC        ,
+    HI_ID_TUNER       ,
+    HI_ID_KEYLED      ,
+    HI_ID_E2PROM      ,
+    HI_ID_CIPHER      ,
+    HI_ID_OTP         = 0x60,
+    HI_ID_CA          ,
+    HI_ID_PM          ,
+    HI_ID_CI          ,
+    HI_ID_CIMAXPLUS   ,
+    HI_ID_TVP5150     ,
+    HI_ID_SIL9293     ,
+    HI_ID_PWM         ,
+    HI_ID_SPI         ,
+    HI_ID_PLCIPHER    ,//0x69
+    HI_ID_CERT        ,//0x6A
+
+    /**< voip, bluetooth,alsa. */ /**<  CNcomment: VOIP���������ֳ�����*/
+    HI_ID_VOIP_HME    = 0x80,
+    HI_ID_NDPT        ,
+    HI_ID_AUDADP      ,
+    HI_ID_BT          ,
+    HI_ID_ALSA        ,
+    HI_ID_3G          ,
+    HI_ID_KARAOKE     ,
+
+    /**< vp. */ /**<  CNcomment: VP������*/
+    HI_ID_VP          = 0x90,
+    HI_ID_HDCP        ,
+
+    /**< subtitle. */ /**<  CNcomment: ��Ļ������*/
+    HI_ID_SUBT        = 0x98,
+    HI_ID_TTX         ,
+    HI_ID_CC          ,
+
+    /**< loader. */ /**< CNcomment: loader */
+    HI_ID_LOADER      = 0xA0,
+
+    /**< opentv5. */ /**<  CNcomment: opentv5*/
+    HI_ID_O5          = 0xA1,
+    HI_ID_O5_AUDDEC,
+    HI_ID_O5_CRYPTO,
+    HI_ID_O5_DMX,
+    HI_ID_O5_FPCHAR,
+    HI_ID_O5_HDMI,
+    HI_ID_O5_INJECT,
+    HI_ID_O5_LED,
+    HI_ID_O5_LINKER,
+    HI_ID_O5_NOCS,
+    HI_ID_O5_PD_WRITER,
+    HI_ID_O5_RFMOD,
+    HI_ID_O5_SCART,
+    HI_ID_O5_SMARTCARD,
+    HI_ID_O5_STB,
+    HI_ID_O5_TUNER,
+    HI_ID_O5_VIDDEC,
+    HI_ID_O5_VIDENC,
+    HI_ID_O5_SOC,
+    HI_ID_O5_ENDDEF  = 0xB4,
+
+    /**<GPU. */ /**< CNcomment:GPU*/
+    HI_ID_GPU        = 0xB8,
+
+    /**< user definition. */ /**< CNcomment: Ϊ�����������Զ����� */
+    HI_ID_USR_START   = 0xC0,
+    HI_ID_USR_END     = 0xFE,
+
+    HI_ID_BUTT        = 0xFF
+} HI_MOD_ID_E;
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif
+
+/** @} */  /** <!-- ==== group Definition end ==== */
+
diff --git a/driver/src/devicedrv/mali/platform/dt/hi_type.h b/driver/src/devicedrv/mali/platform/dt/hi_type.h
new file mode 100644
index 0000000..24fa2fe
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/hi_type.h
@@ -0,0 +1,142 @@
+/******************************************************************************
+ Copyright (C), 2001-2011, Hisilicon Tech. Co., Ltd.
+******************************************************************************
+File Name     : hi_type.h
+Version       : Initial Draft
+Author        : Hisilicon multimedia software group
+Created       : 2005/4/23
+Last Modified :
+Description   : Common data types of the system.
+                CNcomment: ϵͳ���õ��������Ͷ��� CNend
+Function List :
+History       :
+******************************************************************************/
+#ifndef __HI_TYPE_H__
+#define __HI_TYPE_H__
+
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C"{
+#endif
+#endif /* __cplusplus */
+
+/*--------------------------------------------------------------------------------------------------------------*
+ * Defintion of basic data types. The data types are applicable to both the application layer and kernel codes. *
+ * CNcomment: �����������Ͷ��壬Ӧ�ò���ں˴����ʹ��  CNend                                                   *
+ *--------------------------------------------------------------------------------------------------------------*/
+/*************************** Structure Definition ****************************/
+/** \addtogroup      Common_TYPE */
+/** @{ */  /** <!-- [Common_TYPE] */
+
+typedef unsigned char           HI_U8;
+typedef unsigned char           HI_UCHAR;
+typedef unsigned short          HI_U16;
+typedef unsigned int            HI_U32;
+typedef unsigned long           HI_ULONG;
+
+typedef signed char             HI_S8;
+typedef short                   HI_S16;
+typedef int                     HI_S32;
+typedef long                    HI_SLONG;
+
+#ifndef _M_IX86
+typedef unsigned long long      HI_U64;
+typedef long long               HI_S64;
+#else
+typedef __int64                 HI_U64;
+typedef __int64                 HI_S64;
+#endif
+
+typedef char                    HI_CHAR;
+typedef char*                   HI_PCHAR;
+
+typedef float                   HI_FLOAT;
+typedef double                  HI_DOUBLE;
+/*typedef void                    HI_VOID;*/
+#define HI_VOID         void
+
+typedef unsigned long           HI_SIZE_T;
+typedef unsigned long           HI_LENGTH_T;
+
+typedef HI_U32                  HI_HANDLE;
+
+typedef unsigned int            HI_PHYS_ADDR_T;
+
+#ifdef CONFIG_ARCH_LP64_MODE
+typedef unsigned long long      HI_VIRT_ADDR_T;
+#else
+typedef unsigned int            HI_VIRT_ADDR_T;
+#endif
+
+/** Constant Definition */
+/** CNcomment: �������� */
+typedef enum
+{
+    HI_FALSE    = 0,
+    HI_TRUE     = 1,
+} HI_BOOL;
+
+#ifndef NULL
+#define NULL                0L
+#endif
+
+#define HI_NULL             0L
+#define HI_NULL_PTR         0L
+
+#define HI_SUCCESS          0
+#define HI_FAILURE          (-1)
+
+#define HI_INVALID_HANDLE   (0xffffffff)
+
+#define HI_INVALID_PTS      (0xffffffff)
+#define HI_INVALID_TIME     (0xffffffff)
+
+#define HI_OS_LINUX     0xabcd
+#define HI_OS_WIN32     0xcdef
+
+#ifdef _WIN32
+#define HI_OS_TYPE      HI_OS_WIN32
+#else
+#define __OS_LINUX__
+#define HI_OS_TYPE      HI_OS_LINUX
+#endif
+
+#ifdef HI_ADVCA_SUPPORT
+#define __INIT__
+#define __EXIT__
+#else
+#define __INIT__  __init
+#define __EXIT__  __exit
+#endif
+
+/**
+
+define of HI_HANDLE :
+bit31                                                           bit0
+  |<----   16bit --------->|<---   8bit    --->|<---  8bit   --->|
+  |--------------------------------------------------------------|
+  |      HI_MOD_ID_E       |  mod defined data |     chnID       |
+  |--------------------------------------------------------------|
+
+mod defined data: private data define by each module(for example: sub-mod id), usually, set to 0.
+*/
+
+#define HI_HANDLE_MAKEHANDLE(mod, privatedata, chnid)  (HI_HANDLE)( (((mod)& 0xffff) << 16) | ((((privatedata)& 0xff) << 8) ) | (((chnid) & 0xff)) )
+
+#define HI_HANDLE_GET_MODID(handle)     (((handle) >> 16) & 0xffff)
+#define HI_HANDLE_GET_PriDATA(handle)   (((handle) >> 8) & 0xff)
+#define HI_HANDLE_GET_CHNID(handle)     (((handle)) & 0xff)
+
+#define HI_UNUSED(x) ((x)=(x))
+
+/** @} */  /** <!-- ==== Structure Definition end ==== */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif /* __HI_TYPE_H__ */
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_cfg.h b/driver/src/devicedrv/mali/platform/dt/mali4xx_cfg.h
new file mode 100644
index 0000000..7cec556
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_cfg.h
@@ -0,0 +1,25 @@
+
+
+#ifndef __MALI4XX_CFG__
+#define __MALI4XX_CFG__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GPU_DVFS_ENABLE
+#define GPU_MAXFREQ_CONFIG_SUPPORT
+#define GPU_SUPPORT_SVB
+#define GPU_SECURE_SUPPORT
+
+#define HISI_ERROR_INFO() \
+    printk("func = %s, line = %d\n", __FUNCTION__, __LINE__);
+
+#define HISI_DEBUG 0
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_dt.c b/driver/src/devicedrv/mali/platform/dt/mali4xx_dt.c
new file mode 100644
index 0000000..fce5e3d
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_dt.c
@@ -0,0 +1,652 @@
+
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+
+/* After 3.19.0 kenrel droped CONFIG_PM_RUNTIME define,define by ourself */
+#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+#define CONFIG_PM_RUNTIME 1
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+ #include <linux/pm_runtime.h>
+#endif
+#include <asm/io.h>
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/regulator/driver.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include "mali4xx_dt.h"
+#include "mali4xx_scaling.h"
+#include "mali4xx_opp.h"
+#include "mali4xx_proc.h"
+#include "mali4xx_cfg.h"
+
+#include "drv_gpu_ext.h"
+
+typedef enum
+{
+    SEC_REG_ADDR_BASE = 0xF9230200,
+    SEC_REG_ADDR_SIZE = 0x0100,
+
+    SEC_REG_OFFSET_SWITCH  = 0x0,
+    SEC_REG_OFFSET_IDLES_COUNT = 0x4,
+    SEC_REG_OFFSET_STATUS = 0x8,
+} sec_reg_addr;
+
+typedef enum
+{
+    TEMP_REG_ADDR_BASE = 0xF80000b4,
+    TEMP_REG_ADDR_SIZE = 0x0100,
+
+    TEMP_REG_VALUE_CONCTRL = 0x22222222,
+} temp_reg_addr;
+
+typedef enum
+{
+    MALI_POWER_MODE_ON,
+    MALI_POWER_MODE_LIGHT_SLEEP,
+    MALI_POWER_MODE_DEEP_SLEEP,
+} mali_power_mode;
+
+#if CONFIG_GPU_DVFS_ENABLE
+static int mali_dvfs_enable = 1;
+#else
+int mali_dvfs_enable = 0;
+#endif
+module_param(mali_dvfs_enable, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dvfs_enable, "enable dvfs");
+
+#ifdef GPU_MAXFREQ_CONFIG_SUPPORT
+static unsigned int mali_dvfs_max_frequency = 0;
+module_param(mali_dvfs_max_frequency, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dvfs_max_frequency, "max frequency");
+
+static unsigned int mali_dvfs_min_frequency = 0;
+module_param(mali_dvfs_min_frequency, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dvfs_min_frequency, "min frequency");
+#endif
+
+static int mali_dvfs_max_utilization = 0;
+module_param(mali_dvfs_max_utilization, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dvfs_max_utilization, "max utilization");
+
+static int mali_dvfs_min_utilization = 0;
+module_param(mali_dvfs_min_utilization, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dvfs_min_utilization, "min utilization");
+
+static u32 s_PowerOff = 1;
+
+static struct device *s_MaliDevice = NULL;
+
+static struct mali_config s_MaliConfiguration;
+
+static struct mali_hw_core *s_SecCore = NULL;
+static struct mali_hw_core *s_TempCore = NULL;
+
+static int	mali_adp_suspend(struct device *device);
+static int	mali_adp_resume(struct device *device);
+static int	mali_adp_freeze(struct device *device);
+static int	mali_adp_thaw(struct device *device);
+#ifdef CONFIG_PM_RUNTIME
+static int	mali_adp_runtime_suspend(struct device *device);
+static int	mali_adp_runtime_resume(struct device *device);
+static int	mali_adp_runtime_idle(struct device *device);
+#endif
+
+int mali_adp_secure_init(void);
+void mali_adp_secure_deinit(void);
+int mali_adp_secure_enable(void);
+int mali_adp_secure_disable(void);
+
+_mali_osk_errcode_t mali_adp_platform_init(struct device *device);
+_mali_osk_errcode_t mali_adp_platform_deinit(struct device *device);
+
+static struct dev_pm_ops mali_device_dev_pm_ops =
+{
+    .suspend         = mali_adp_suspend,
+    .resume          = mali_adp_resume,
+    .freeze          = mali_adp_freeze,
+    .thaw            = mali_adp_thaw,
+    .restore         = mali_adp_thaw,
+#ifdef CONFIG_PM_RUNTIME
+    .runtime_suspend = mali_adp_runtime_suspend,
+    .runtime_resume  = mali_adp_runtime_resume,
+    .runtime_idle    = mali_adp_runtime_idle,
+#endif
+};
+
+static struct device_type mali_device_device_type =
+{
+    .pm = &mali_device_dev_pm_ops,
+};
+
+static GPU_EXT_FUNC_S mali_export_function =
+{
+    .pfnGPUSetFreqAndVolt = mali_ext_set_freq_and_volt,
+    .pfnGPUSetMaxFreq = mali_ext_set_max_freq,
+};
+
+static struct mali_gpu_device_data mali_device_data =
+{
+    .shared_mem_size      = CONFIG_GPU_MAX_SHARE_MEM_SIZE,
+    .fb_start             = 0x00000000,
+    .fb_size              = 0x80000000,
+    .dedicated_mem_start  = 0x0,
+    .dedicated_mem_size   = 0x0,
+    .control_interval     = 50,          /*50ms*/
+    .utilization_callback = NULL,
+    .max_job_runtime      = 5000,        /* 5 seconds */
+    .get_clock_info       = NULL,
+    .get_freq             = NULL,
+    .set_freq             = NULL,
+    .secure_mode_init                   = mali_adp_secure_init,
+    .secure_mode_deinit                 = mali_adp_secure_deinit,
+    .gpu_reset_and_secure_mode_enable   = mali_adp_secure_enable,
+    .gpu_reset_and_secure_mode_disable  = mali_adp_secure_disable,
+};
+
+int mali_platform_device_init(struct platform_device *device)
+{
+    int err = -1;
+    int num_pp_cores = 2;
+
+    mali_adp_platform_init(&(device->dev));
+
+#ifdef CONFIG_PM_RUNTIME
+    atomic_set(&device->dev.power.usage_count, 0);
+#endif
+
+    if (!device->dev.dma_mask)
+    {
+        device->dev.dma_mask = &device->dev.coherent_dma_mask;
+    }
+
+    device->dev.type = &mali_device_device_type;
+
+    err = platform_device_add_data(device, &mali_device_data, sizeof(mali_device_data));
+
+    if (0 == err)
+    {
+#ifdef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+        pm_runtime_set_autosuspend_delay(&(device->dev), 1000);
+        pm_runtime_use_autosuspend(&(device->dev));
+#endif
+        pm_runtime_enable(&(device->dev));
+#endif
+        MALI_DEBUG_ASSERT(0 < num_pp_cores);
+        mali_core_scaling_init(num_pp_cores);
+    }
+
+    return err;
+}
+
+int mali_platform_device_deinit(struct platform_device *device)
+{
+    MALI_IGNORE(device);
+
+    mali_core_scaling_term();
+
+#ifdef CONFIG_PM_RUNTIME
+    pm_runtime_disable(&(device->dev));
+#endif
+
+    mali_adp_platform_deinit(&(device->dev));
+
+    return 0;
+}
+
+static struct mali_hw_core * mali_adp_core_create(u32 phys_addr, u32 size, char* description)
+{
+    struct mali_hw_core *hwcore = (struct mali_hw_core *)_mali_osk_malloc(sizeof(struct mali_hw_core));
+
+    if (NULL == hwcore)
+    {
+        HISI_ERROR_INFO();
+        return NULL;
+    }
+
+    hwcore->phys_addr = phys_addr;
+    hwcore->size = size;
+    hwcore->description = NULL;
+    hwcore->mapped_registers = _mali_osk_mem_mapioregion(hwcore->phys_addr, hwcore->size, hwcore->description);
+
+    if (NULL == hwcore->mapped_registers)
+    {
+        HISI_ERROR_INFO();
+        _mali_osk_free(hwcore);
+        hwcore = NULL;
+        return NULL;
+    }
+
+    return hwcore;
+}
+
+static void mali_adp_core_destroy(struct mali_hw_core *hwcore)
+{
+    if (NULL == hwcore)
+    {
+        HISI_ERROR_INFO();
+        return;
+    }
+
+    _mali_osk_mem_unmapioregion(hwcore->phys_addr, hwcore->size, hwcore->mapped_registers);
+
+    _mali_osk_free(hwcore);
+}
+
+void mali_adp_platform_hw_core_create(void)
+{
+    s_SecCore = mali_adp_core_create(SEC_REG_ADDR_BASE, SEC_REG_ADDR_SIZE, "hisi_sec");
+
+    if (NULL == s_SecCore)
+    {
+        HISI_ERROR_INFO();
+    }
+
+    s_TempCore = mali_adp_core_create(TEMP_REG_ADDR_BASE, TEMP_REG_ADDR_SIZE, "hisi_temp");
+
+    if (NULL == s_TempCore)
+    {
+        HISI_ERROR_INFO();
+    }
+}
+
+void mali_adp_platform_hw_core_destroy(void)
+{
+    mali_adp_core_destroy(s_SecCore);
+
+    s_SecCore = NULL;
+
+    mali_adp_core_destroy(s_TempCore);
+
+    s_TempCore = NULL;
+}
+
+_mali_osk_errcode_t mali_adp_platform_init(struct device *device)
+{
+    mali_adp_platform_hw_core_create();
+
+    s_MaliDevice = device;
+
+#ifdef GPU_PROC_SUPPORT
+    gpu_proc_create();
+#endif
+
+    HI_DRV_MODULE_Register(HI_ID_GPU, "MALI", (HI_VOID*)&mali_export_function);
+
+    MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_adp_platform_deinit(struct device *device)
+{
+#ifdef GPU_PROC_SUPPORT
+    gpu_proc_destroy();
+#endif
+
+    mali_adp_platform_hw_core_destroy();
+
+    s_MaliDevice = NULL;
+
+    HI_DRV_MODULE_UnRegister(HI_ID_GPU);
+
+    MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_adp_power_mode_change(struct device *device, mali_power_mode power_mode, mali_bool isruntime)
+{
+    struct mali_device *mdev = dev_get_drvdata(device);
+    unsigned long d_freq, d_volt;
+
+    d_volt = opps_get_default_volt();
+    d_freq = opps_get_default_freq();
+
+    switch (power_mode)
+    {
+        case MALI_POWER_MODE_ON:
+            if (s_PowerOff == 1)
+            {
+                clk_enable(mdev->clock);
+
+                s_PowerOff = 0;
+            }
+            break;
+        case MALI_POWER_MODE_LIGHT_SLEEP:
+        case MALI_POWER_MODE_DEEP_SLEEP:
+            if (s_PowerOff == 0)
+            {
+                if(mali_dvfs_enable == 1)
+                {
+                    regulator_set_voltage(mdev->regulator, d_volt, d_volt);
+                    clk_set_rate(mdev->clock, d_freq);
+                    mdev->current_voltage = d_volt;
+                    mdev->current_freq = d_freq;
+                }
+
+                clk_disable(mdev->clock);
+
+                s_PowerOff = 1;
+            }
+            break;
+    }
+
+    if(HISI_DEBUG)
+        printk("mali_adp_power_mode_change@ power_mode = %d\n", power_mode);
+
+    MALI_SUCCESS;
+}
+
+static int mali_adp_suspend(struct device *device)
+{
+    int ret = 0;
+
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->suspend))
+    {
+        ret = device->driver->pm->suspend(device);
+    }
+
+    if(0 == ret)
+    {
+        mali_adp_power_mode_change(device, MALI_POWER_MODE_DEEP_SLEEP, MALI_FALSE);
+    }
+
+    return ret;
+}
+
+static int mali_adp_resume(struct device *device)
+{
+    int ret = 0;
+
+    mali_adp_power_mode_change(device, MALI_POWER_MODE_ON, MALI_FALSE);
+
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->resume))
+    {
+        ret = device->driver->pm->resume(device);
+    }
+
+    return ret;
+}
+
+static int mali_adp_freeze(struct device *device)
+{
+    int ret = 0;
+
+    mali_adp_power_mode_change(device, MALI_POWER_MODE_ON, MALI_FALSE);
+
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->freeze))
+    {
+        ret = device->driver->pm->freeze(device);
+    }
+
+    if(0 == ret)
+    {
+        mali_adp_power_mode_change(device, MALI_POWER_MODE_DEEP_SLEEP, MALI_FALSE);
+    }
+
+    return ret;
+}
+
+static int mali_adp_thaw(struct device *device)
+{
+    int ret = 0;
+
+    mali_adp_power_mode_change(device, MALI_POWER_MODE_ON, MALI_FALSE);
+
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->thaw))
+    {
+        ret = device->driver->pm->thaw(device);
+    }
+
+    return ret;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int mali_adp_runtime_suspend(struct device *device)
+{
+    int ret = 0;
+
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->runtime_suspend))
+    {
+        ret = device->driver->pm->runtime_suspend(device);
+    }
+
+    if(0 == ret)
+    {
+        mali_adp_power_mode_change(device, MALI_POWER_MODE_LIGHT_SLEEP, MALI_TRUE);
+    }
+
+    return ret;
+}
+
+static int mali_adp_runtime_resume(struct device *device)
+{
+    int ret = 0;
+
+    mali_adp_power_mode_change(device, MALI_POWER_MODE_ON, MALI_TRUE);
+
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->runtime_resume))
+    {
+        ret = device->driver->pm->runtime_resume(device);
+    }
+
+    return ret;
+}
+
+static int mali_adp_runtime_idle(struct device *device)
+{
+    if ((NULL != device->driver)
+        && (NULL != device->driver->pm)
+        && (NULL != device->driver->pm->runtime_idle))
+    {
+        int ret = device->driver->pm->runtime_idle(device);
+        if (0 != ret)
+        {
+            return ret;
+        }
+    }
+
+    pm_runtime_suspend(device);
+
+    return 0;
+}
+
+#endif
+
+void mali_adp_secure_reset_request(void)
+{
+#ifdef GPU_SECURE_SUPPORT
+	int value ;
+
+    mali_hw_core_register_write(s_SecCore, SEC_REG_OFFSET_IDLES_COUNT, 0x1ff);
+
+    value = mali_hw_core_register_read(s_SecCore, SEC_REG_OFFSET_SWITCH);
+    value = value | 0x1;
+
+    mali_hw_core_register_write(s_SecCore, SEC_REG_OFFSET_SWITCH, value);
+
+    value = 0 ;
+    while(!value)
+    {
+        value = mali_hw_core_register_read(s_SecCore, SEC_REG_OFFSET_STATUS);
+    }
+#endif
+}
+
+void mali_adp_secure_reset_cancel(void)
+{
+#ifdef GPU_SECURE_SUPPORT
+	int value ;
+
+    mali_hw_core_register_write(s_SecCore, SEC_REG_OFFSET_IDLES_COUNT, 0x1ff);
+
+    value = mali_hw_core_register_read(s_SecCore, SEC_REG_OFFSET_SWITCH);
+    value = value & 0xfffffffe;
+
+    mali_hw_core_register_write(s_SecCore, SEC_REG_OFFSET_SWITCH, value);
+
+    value = 0 ;
+    while(!value)
+    {
+        value = mali_hw_core_register_read(s_SecCore, SEC_REG_OFFSET_STATUS);
+    }
+#endif
+}
+
+int mali_adp_secure_init(void)
+{
+    mali_adp_secure_reset_cancel() ;
+
+    return 0 ;
+}
+
+void mali_adp_secure_deinit(void)
+{
+    mali_adp_secure_reset_cancel() ;
+
+    return;
+}
+
+int mali_adp_secure_enable(void)
+{
+	mali_adp_secure_reset_request() ;
+
+	return 0 ;
+}
+
+int mali_adp_secure_disable(void)
+{
+	mali_adp_secure_reset_cancel() ;
+
+	return 0 ;
+}
+
+struct device * mali_adp_get_device(void)
+{
+    return s_MaliDevice;
+}
+
+int mali_adp_get_powerstatus(void)
+{
+    return s_PowerOff;
+}
+
+int mali_adp_get_dvfsstatus(void)
+{
+    return mali_dvfs_enable;
+}
+
+unsigned int mali_adp_get_temp_ctrl(void)
+{
+    /* 1: disable dvfs, configure min frequency
+       0: enable dvfs */
+
+#ifdef CFG_TEMP_CTRL_CONFIG
+    unsigned int value = mali_hw_core_register_read(s_TempCore, 0);
+
+    if(value == TEMP_REG_VALUE_CONCTRL)
+    {
+        if(HISI_DEBUG)
+            printk("mali_adp_get_temp_ctrl@ disable dvfs\n");
+
+        return 1;
+    }
+#endif
+
+    return 0;
+}
+
+void* mali_adp_get_configuration(struct mali_device *mdev)
+{
+    if(mali_dvfs_max_frequency == 0)
+    {
+        mali_dvfs_max_frequency = (unsigned int)opps_get_max_freq()/1000;
+    }
+
+    if(mali_dvfs_min_frequency == 0)
+    {
+        mali_dvfs_min_frequency = (unsigned int)opps_get_min_freq()/1000;
+    }
+
+    if(mali_dvfs_max_utilization == 0)
+    {
+        mali_dvfs_max_utilization = opps_get_max_utilization();
+    }
+
+    if(mali_dvfs_min_utilization == 0)
+    {
+        mali_dvfs_min_utilization = opps_get_min_utilization();
+    }
+
+    s_MaliConfiguration.dvfs_enable = mali_dvfs_enable;
+    s_MaliConfiguration.max_frequency = mali_dvfs_max_frequency * 1000;
+    s_MaliConfiguration.min_frequency = mali_dvfs_min_frequency * 1000;
+    s_MaliConfiguration.max_utilization = mali_dvfs_max_utilization;
+    s_MaliConfiguration.min_utilization = mali_dvfs_min_utilization;
+
+    s_MaliConfiguration.time_busy_gp = mdev->mali_metrics.time_busy_gp;
+    s_MaliConfiguration.time_idle_gp = mdev->mali_metrics.time_idle_gp;
+    s_MaliConfiguration.time_busy_pp = mdev->mali_metrics.time_busy_pp[0];
+    s_MaliConfiguration.time_idle_pp = mdev->mali_metrics.time_idle_pp[0];
+
+    s_MaliConfiguration.temp_ctrl = mali_adp_get_temp_ctrl();
+
+    return (void*)(&s_MaliConfiguration);
+}
+
+int mali_ext_set_freq_and_volt(int freq, int volt, int dvfs_enable)
+{
+    struct mali_device *mdev = dev_get_drvdata(mali_adp_get_device());
+
+    mali_dvfs_enable = dvfs_enable;
+
+    mdelay(1000);
+
+    if((freq == 0) && (volt == 0))
+    {
+        HISI_ERROR_INFO();
+    }
+    else if(freq == 0)
+    {
+        regulator_set_voltage(mdev->regulator, volt*1000, volt*1000);
+    }
+    else if(volt == 0)
+    {
+        clk_set_rate(mdev->clock, freq*1000);
+    }
+    else
+    {
+        regulator_set_voltage(mdev->regulator, volt*1000, volt*1000);
+        clk_set_rate(mdev->clock, freq*1000);
+    }
+
+    return 0;
+}
+
+int mali_ext_set_max_freq(int freq)
+{
+    mali_dvfs_max_frequency = freq;
+
+    return 0;
+}
+
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_dt.h b/driver/src/devicedrv/mali/platform/dt/mali4xx_dt.h
new file mode 100644
index 0000000..c3d3979
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_dt.h
@@ -0,0 +1,41 @@
+
+
+#ifndef __MALI4XX_DT__
+#define __MALI4XX_DT__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct mali_config{
+    int dvfs_enable;
+    unsigned long max_frequency;
+    unsigned long min_frequency;
+    unsigned int max_utilization;
+    unsigned int min_utilization;
+
+    unsigned int temp_ctrl;
+
+    unsigned long long time_busy_gp;
+    unsigned long long time_idle_gp;
+    unsigned long long time_busy_pp;
+    unsigned long long time_idle_pp;
+}mali_config;
+
+struct device * mali_adp_get_device(void);
+
+int mali_adp_get_powerstatus(void);
+
+int mali_adp_get_dvfsstatus(void);
+
+void* mali_adp_get_configuration(struct mali_device *mdev);
+
+int mali_ext_set_freq_and_volt(int freq, int volt, int dvfs_enable);
+
+int mali_ext_set_max_freq(int freq);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_opp.c b/driver/src/devicedrv/mali/platform/dt/mali4xx_opp.c
new file mode 100644
index 0000000..d209954
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_opp.c
@@ -0,0 +1,270 @@
+
+
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <linux/regulator/driver.h>
+
+#include "mali_osk_mali.h"
+#include "mali4xx_cfg.h"
+
+static unsigned long s_DefaultFreq = 0;
+static unsigned long s_DefaultVolt = 0;
+static unsigned long s_MaxFreq = 0;
+static unsigned long s_MinFreq = 0;
+static unsigned long s_MaxUtil = 0;
+static unsigned long s_MinUtil = 0;
+
+#ifdef GPU_SUPPORT_SVB
+
+typedef enum{
+    SVB_REG_ADDR_BASE = 0xf8000000,
+    SVB_REG_ADDR_SIZE = 0x100,
+    SVB_REG_OFFSET_REGISTER1 = 0xc4, /*about: type - ff - ss*/
+    SVB_REG_OFFSET_REGISTER2 = 0xc8, /*about: tt*/
+}svb_reg_addr;
+
+typedef enum{
+	SVB_CHIP_TYPE_FF = 1,
+	SVB_CHIP_TYPE_TT = 2,
+	SVB_CHIP_TYPE_SS = 3,
+}svb_chip_type;
+
+static char *clock_table[3] = {"operating-points-ff", "operating-points-tt", "operating-points-ss"};
+
+static char *clock_table_98mv300[3] = {"operating-points-ff-98mv300", "operating-points-tt-98mv300", "operating-points-ss-98mv300"};
+static char *clock_table_youtube[3] = {"operating-points-ff-youtube", "operating-points-tt-youtube", "operating-points-ss-youtube"};
+
+char* opps_get_svb_type(void)
+{
+    volatile u32* pu32SVBBase = (u32*)ioremap_nocache(SVB_REG_ADDR_BASE,  SVB_REG_ADDR_SIZE);
+    int svb_type, svb_corner[3];
+    int reg1, reg2;
+
+    if(pu32SVBBase == NULL)
+    {
+        HISI_ERROR_INFO();
+        return NULL;
+    }
+
+    reg1 = *(pu32SVBBase +  (SVB_REG_OFFSET_REGISTER1 >> 2));
+    reg2 = *(pu32SVBBase +  (SVB_REG_OFFSET_REGISTER2 >> 2));
+
+    svb_type = (reg1 >> 24) & 0xff;
+    svb_corner[0] = (reg1 >> 16) & 0xff;	/*ff*/
+    svb_corner[1] = (reg1 >> 8) & 0xff;	    /*tt*/
+    svb_corner[2] = reg1 & 0xff;		    /*ss*/
+
+    iounmap(pu32SVBBase);
+
+    if((svb_type != SVB_CHIP_TYPE_FF) && (svb_type != SVB_CHIP_TYPE_TT) && (svb_type != SVB_CHIP_TYPE_SS))
+    {
+        svb_type = SVB_CHIP_TYPE_SS;
+    }
+
+    /* (3)98mv200 non-youtube mode : Max freq is 750M, it can be 800M in some BenchMark */
+    s_MaxFreq = 750000000;
+
+    return clock_table[svb_type - 1];
+}
+
+#endif
+
+unsigned long opps_get_default_freq(void)
+{
+    return s_DefaultFreq;
+}
+
+unsigned long opps_get_default_volt(void)
+{
+    return s_DefaultVolt;
+}
+
+unsigned long opps_get_max_freq(void)
+{
+    return s_MaxFreq;
+}
+
+unsigned long opps_get_min_freq(void)
+{
+    return s_MinFreq;
+}
+
+unsigned int opps_get_max_utilization(void)
+{
+    return s_MaxUtil;
+}
+
+unsigned int opps_get_min_utilization(void)
+{
+    return s_MinUtil;
+}
+
+int setup_opps(struct device *dev)
+{
+    struct mali_device *mdev = dev_get_drvdata(dev);
+    const struct property *prop;
+    const __be32 *val;
+    int nr;
+    char *operating_points;
+    unsigned long core_vol;
+
+    /* (1) Get Default Frequency */
+    prop = of_find_property(dev->of_node, "default-frequency", NULL);
+    if(!prop || !prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    s_DefaultFreq = be32_to_cpup(prop->value);
+
+    /* (2) Get Max/Min Frequency */
+    prop = of_find_property(dev->of_node, "max-frequency", NULL);
+    if(!prop || !prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    s_MaxFreq = be32_to_cpup(prop->value);
+
+    prop = of_find_property(dev->of_node, "min-frequency", NULL);
+    if(!prop || !prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    s_MinFreq = be32_to_cpup(prop->value);
+
+    /* (3) Get Max/Min Utilization */
+    prop = of_find_property(dev->of_node, "max-utilization", NULL);
+    if(!prop || !prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    s_MaxUtil = be32_to_cpup(prop->value);
+
+    prop = of_find_property(dev->of_node, "min-utilization", NULL);
+    if(!prop || !prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    s_MinUtil = be32_to_cpup(prop->value);
+
+    if(HISI_DEBUG)
+        printk("setup_opps@ DefaultFreq = %ld, MaxFreq = %ld, MinFreq = %ld, MaxUtil = %ld, MinUtil = %ld\n",
+            s_DefaultFreq, s_MaxFreq, s_MinFreq, s_MaxUtil, s_MinUtil);
+
+    /* (4) Get Operating-points */
+#ifdef GPU_SUPPORT_SVB
+    operating_points = opps_get_svb_type();
+#else
+    operating_points = "operating-points";
+#endif
+
+    if(HISI_DEBUG)
+        printk("setup_opps@ vmin table is %s\n", operating_points);
+
+    prop = of_find_property(dev->of_node, operating_points, NULL);
+    if(!prop || !prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    nr = prop->length / sizeof(u32);
+    if (nr % 2)
+    {
+        HISI_ERROR_INFO();
+        return -EINVAL;
+    }
+
+    val = prop->value;
+
+    /* (4) add vmin table */
+    core_vol = (unsigned int)regulator_get_voltage(mdev->regulator);
+
+    while (nr)
+    {
+        unsigned long freq = be32_to_cpup(val++) ;
+        unsigned long volt = be32_to_cpup(val++) ;
+
+#ifdef GPU_SUPPORT_SVB
+        if(volt < core_vol)            /* gpu vmin could not be lower than core vmin */
+        {
+            volt = core_vol;
+        }
+#endif
+
+        if(s_DefaultFreq == freq)
+        {
+            s_DefaultVolt = volt;
+        }
+
+        if(HISI_DEBUG)
+            printk("setup_opps@ add opps ~ Freq = %ld, Volt = %ld\n", freq, volt);
+
+        dev_pm_opp_add(dev, freq, volt);
+
+        nr -= 2;
+    }
+
+	return 0;
+}
+
+int term_opps(struct device *dev)
+{
+    const struct property *prop;
+    const __be32 *val;
+    int nr;
+    char *operating_points;
+
+#ifdef GPU_SUPPORT_SVB
+    operating_points = opps_get_svb_type();
+#else
+    operating_points = "operating-points";
+#endif
+
+    prop = of_find_property(dev->of_node, operating_points, NULL);
+    if(!prop)
+    {
+        HISI_ERROR_INFO();
+        return -ENODEV;
+    }
+    if(!prop->value)
+    {
+        HISI_ERROR_INFO();
+        return -ENODATA;
+    }
+
+    nr = prop->length / sizeof(u32);
+    if (nr % 2)
+    {
+        HISI_ERROR_INFO();
+        return -EINVAL;
+    }
+
+    val = prop->value;
+
+    while (nr)
+    {
+        unsigned long freq = be32_to_cpup(val);
+
+        dev_pm_opp_remove(dev, freq);
+
+        val += 2;
+        nr -= 2;
+    }
+
+    if(HISI_DEBUG)
+        printk("term_opps@\n");
+
+	return 0;
+}
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_opp.h b/driver/src/devicedrv/mali/platform/dt/mali4xx_opp.h
new file mode 100644
index 0000000..eb02294
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_opp.h
@@ -0,0 +1,29 @@
+
+#ifndef __MALI4XX_OPP__
+#define __MALI4XX_OPP__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned long opps_get_default_freq(void);
+
+unsigned long opps_get_default_volt(void);
+
+unsigned long opps_get_max_freq(void);
+
+unsigned long opps_get_min_freq(void);
+
+unsigned int opps_get_max_utilization(void);
+
+unsigned int opps_get_min_utilization(void);
+
+int setup_opps(struct device *dev);
+
+int term_opps(struct device *dev);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_proc.c b/driver/src/devicedrv/mali/platform/dt/mali4xx_proc.c
new file mode 100644
index 0000000..c5ef2ad
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_proc.c
@@ -0,0 +1,384 @@
+#ifdef GPU_PROC_SUPPORT
+
+#include <linux/clkdev.h>
+#include <asm/clkdev.h>
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#ifdef CONFIG_PROC_FS
+ #include <linux/proc_fs.h>
+#endif
+#include <linux/seq_file.h>
+
+#include <linux/regulator/driver.h>
+#include <linux/clk.h>
+
+#include "mali_kernel_common.h"
+#include "mali_osk_mali.h"
+#include "mali_pm_metrics.h"
+
+#include "hi_drv_proc.h"
+#include "hi_osal.h"
+
+#include "mali4xx_scaling.h"
+#include "mali4xx_dt.h"
+
+#define GPU_CMD_MAX_NUM (2)
+#define GPU_CMD_MAX_CMD_LEN (32)
+#define GPU_CMD_MAX_VLAUE_LEN (32)
+#define GPU_CMD_ON "on"
+#define GPU_CMD_OFF "off"
+#define GPU_CMD_VOLT "volt"
+#define GPU_CMD_FREQ "freq"
+#define GPU_CMD_HELP "help"
+#define GPU_CMD_WAKEUPRESET "reset"
+#define GPU_CMD_DEBUG "debug"
+#define GPU_CMD_ENTERSMARTSTANDBY "entersmart"
+#define GPU_CMD_QUITSMARTSTANDBY "quitsmart"
+
+typedef struct tagGPU_CMD_DATA_S
+{
+    HI_U8 aszCmd[GPU_CMD_MAX_CMD_LEN];
+    HI_U8 aszValue[GPU_CMD_MAX_VLAUE_LEN];
+} GPU_CMD_DATA_S;
+
+static GPU_CMD_DATA_S g_astGPUProcCmd[GPU_CMD_MAX_NUM];
+
+unsigned int mali_proc_get_gp_utilization(void)
+{
+    struct mali_device *mdev = dev_get_drvdata(mali_adp_get_device());
+    struct mali_config *mali_valuable;
+    unsigned int busy = 0, total = 0;
+
+    mali_valuable = (struct mali_config*)mdev->devfreq->last_status.private_data;
+
+    if(mali_valuable == NULL)
+    {
+        return 0;
+    }
+
+    busy = (unsigned int)(mali_valuable->time_busy_gp) >> 10;
+
+    total = (unsigned int)(mali_valuable->time_busy_gp + mali_valuable->time_idle_gp) >> 10;
+
+    return 100 * busy / (total + 1);
+}
+
+unsigned int mali_proc_get_pp_utilization(void)
+{
+    struct mali_device *mdev = dev_get_drvdata(mali_adp_get_device());
+    struct mali_config *mali_valuable;
+    unsigned int busy = 0, total = 0;
+
+    mali_valuable = (struct mali_config*)mdev->devfreq->last_status.private_data;
+
+    if(mali_valuable == NULL)
+    {
+        return 0;
+    }
+
+    busy = (unsigned int)(mali_valuable->time_busy_pp) >> 10;
+
+    total = (unsigned int)(mali_valuable->time_busy_pp + mali_valuable->time_idle_pp) >> 10;
+
+    return 100 * busy / (total + 1);
+}
+
+HI_U32 GPUParseValue(HI_U8* pu8Value)
+{
+    if (strlen(pu8Value) < 2)
+    {
+        return (HI_U32)simple_strtoul(pu8Value, HI_NULL, 10);
+    }
+    else
+    {
+        if ((pu8Value[0] == '0') && ((pu8Value[1] == 'x') || (pu8Value[1] == 'X')))
+        {
+            return (HI_U32)simple_strtoul(pu8Value, HI_NULL, 16);
+        }
+        else
+        {
+            return (HI_U32)simple_strtoul(pu8Value, HI_NULL, 10);
+        }
+    }
+}
+
+HI_S32 GPUParseCmd(HI_U8* pu8Cmd, HI_U32 u32Len, GPU_CMD_DATA_S** pstCmd, HI_U32* pu32Num)
+{
+    HI_U32 u32Pos = 0;
+    HI_U32 u32SavePos = 0;
+    HI_U32 u32CmdNum = 0;
+    HI_BOOL bIsCmd   = HI_TRUE;
+    HI_U8 u8LastChar = ' ';
+
+    if ((HI_NULL == pu8Cmd) || (0 == u32Len) || (HI_NULL == pstCmd) || (HI_NULL == pu32Num))
+    {
+        MALI_PRINT_ERROR(("Invalid.\n"));
+        return HI_FAILURE;
+    }
+
+    u32CmdNum = 0;
+    memset(g_astGPUProcCmd, 0, sizeof(g_astGPUProcCmd));
+
+    while ((u32Pos < u32Len) && (pu8Cmd[u32Pos]))
+    {
+        switch (pu8Cmd[u32Pos])
+        {
+        case '\0':
+        case '\n':
+        case '\t':
+            break;
+
+        case '=':
+            if (bIsCmd)
+            {
+                bIsCmd = HI_FALSE;
+                u32SavePos = 0;
+            }
+
+            break;
+        case ' ':
+            if (!((' ' == u8LastChar) || ('=' == u8LastChar)))
+            {
+                bIsCmd = !bIsCmd;
+                u32SavePos = 0;
+                if (bIsCmd)
+                {
+                    if (u32CmdNum < GPU_CMD_MAX_NUM - 1)
+                    {
+                        u32CmdNum++;
+                    }
+                    else
+                    {
+                        goto out;
+                    }
+                }
+            }
+
+            break;
+        default:
+            if (bIsCmd)
+            {
+                if (u32SavePos < GPU_CMD_MAX_CMD_LEN)
+                {
+                    g_astGPUProcCmd[u32CmdNum].aszCmd[u32SavePos++] = pu8Cmd[u32Pos];
+                }
+            }
+            else
+            {
+                if (u32SavePos < GPU_CMD_MAX_VLAUE_LEN)
+                {
+                    g_astGPUProcCmd[u32CmdNum].aszValue[u32SavePos++] = pu8Cmd[u32Pos];
+                }
+            }
+
+            break;
+        }
+
+        u8LastChar = pu8Cmd[u32Pos];
+        u32Pos++;
+    }
+
+out:
+    if (strlen(g_astGPUProcCmd[u32CmdNum].aszCmd) > 0)
+    {
+        u32CmdNum += 1;
+    }
+
+    *pstCmd  = g_astGPUProcCmd;
+    *pu32Num = u32CmdNum;
+    return HI_SUCCESS;
+}
+
+HI_S32 GPUDebugCtrl(HI_U32 u32Para1, HI_U32 u32Para2)
+{
+    HI_U32 u32CpuCurFreq = 0;
+    struct mali_device *mdev = dev_get_drvdata(mali_adp_get_device());
+
+    MALI_DEBUG_PRINT(2, ("\n gpu freq = 0x%x, voltage = 0x%x \n", u32Para1, u32Para2));
+
+    if ((0 == u32Para1) && (0 == u32Para2))
+    {
+        MALI_PRINT_ERROR(("plese set the valid value \n"));
+        return HI_SUCCESS;
+    }
+
+    if (0 == u32Para2)
+    {
+        clk_set_rate(mdev->clock, u32Para1*1000);
+        mdev->current_freq = u32Para1*1000;
+
+        return HI_SUCCESS;
+    }
+
+    if (0 == u32Para1)
+    {
+        regulator_set_voltage(mdev->regulator, u32Para2*1000, u32Para2*1000);
+        mdev->current_voltage = u32Para2*1000;
+
+        return HI_SUCCESS;
+    }
+
+    u32CpuCurFreq = (HI_U32)clk_get_rate(mdev->clock);
+    if (u32Para1 > u32CpuCurFreq)
+    {
+        regulator_set_voltage(mdev->regulator, u32Para2*1000, u32Para2*1000);
+        clk_set_rate(mdev->clock, u32Para1*1000);
+    }
+    else
+    {
+        clk_set_rate(mdev->clock, u32Para1*1000);
+        regulator_set_voltage(mdev->regulator, u32Para2*1000, u32Para2*1000);
+    }
+
+    mdev->current_voltage = u32Para2*1000;
+    mdev->current_freq = u32Para1*1000;
+
+    return HI_SUCCESS;
+}
+
+static HI_S32 GPUProcRead(struct seq_file *p, HI_VOID *v)
+{
+    struct mali_device *mdev = dev_get_drvdata(mali_adp_get_device());
+
+    PROC_PRINT(p,     "---------Hisilicon GPU Info---------\n");
+    PROC_PRINT(p,     "Frequency                :%d(kHz)\n",(HI_U32)clk_get_rate(mdev->clock)/1000);
+    PROC_PRINT(p,     "Voltage                  :%d(mv)\n",(HI_U32)regulator_get_voltage(mdev->regulator)/1000);
+    PROC_PRINT(p,     "GP_utilization           :%d(percent)\n",mali_proc_get_gp_utilization());
+    PROC_PRINT(p,     "PP_utilization           :%d(percent)\n",mali_proc_get_pp_utilization());
+
+    if (1 == mali_adp_get_powerstatus())
+    {
+        PROC_PRINT(p, "Power_status             :power down\n");
+    }
+    else
+    {
+        PROC_PRINT(p, "Power_status             :power up\n");
+    }
+
+    PROC_PRINT(p,     "Shared_mem_size          :%d(MB)\n",CONFIG_GPU_MAX_SHARE_MEM_SIZE/1024/1024);
+
+    if (1 == mali_adp_get_dvfsstatus())
+    {
+        PROC_PRINT(p, "DVFS_enable              :enable\n");
+    }
+    else
+    {
+        PROC_PRINT(p, "DVFS_enable              :disable\n");
+    }
+
+    return 0;
+}
+
+static HI_VOID GPUProcHelper(HI_VOID)
+{
+    HI_DRV_PROC_EchoHelper(
+        "echo volt=1080 > /proc/hisi/msp/pm_gpu, set gpu volt in mv.\n"
+        "echo freq=432000 > /proc/hisi/msp/pm_gpu, set gpu freq in kHz.\n"
+        "echo avs on/off > /proc/hisi/msp/pm_gpu, open/close gpu avs.\n"
+        "echo freq=432000 volt=1080 > /proc/hisi/msp/pm_gpu, set gpu volt and freq simultaneity.\n"
+    );
+
+    return;
+}
+
+static HI_S32 GPUProcWrite(struct file * file,
+                           const char __user * buf, size_t count, loff_t *ppos)
+{
+    HI_CHAR ProcPara[64] = {0};
+    HI_S32 s32Ret;
+    HI_U32 u32CmdNum = 0;
+    GPU_CMD_DATA_S* pstCmd = HI_NULL;
+
+    if(count > sizeof(ProcPara))
+    {
+        return -EFAULT;
+    }
+
+    if (copy_from_user(ProcPara, buf, count))
+    {
+        return -EFAULT;
+    }
+
+    s32Ret = GPUParseCmd(ProcPara, count, &pstCmd, &u32CmdNum);
+    if (HI_SUCCESS != s32Ret)
+    {
+        goto err;
+    }
+
+    if (1 == u32CmdNum)
+    {
+        /* Only set GPU volt */
+        if (0 == HI_OSAL_Strncasecmp(GPU_CMD_VOLT, pstCmd[0].aszCmd, strlen(pstCmd[0].aszCmd)))
+        {
+            GPUDebugCtrl(0, GPUParseValue(pstCmd[0].aszValue));
+        }
+        /* Only set GPU freq */
+        else if (0 == HI_OSAL_Strncasecmp(GPU_CMD_FREQ, pstCmd[0].aszCmd, strlen(pstCmd[0].aszCmd)))
+        {
+            GPUDebugCtrl(GPUParseValue(pstCmd[0].aszValue), 0);
+        }
+        /* Help */
+        else if (0 == HI_OSAL_Strncasecmp(GPU_CMD_HELP, pstCmd[0].aszCmd, strlen(pstCmd[0].aszCmd)))
+        {
+            GPUProcHelper();
+        }
+        /* Support 0xXXX 0xXXX command */
+        else /*if (('0' == pstCmd[0].aszCmd[0]) && ('0' == pstCmd[0].aszValue[0]))*/
+        {
+            GPUDebugCtrl(GPUParseValue(pstCmd[0].aszCmd), GPUParseValue(pstCmd[0].aszValue));
+        }
+    }
+    else if (2 == u32CmdNum)
+    {
+        if ((0 == HI_OSAL_Strncasecmp(GPU_CMD_VOLT, pstCmd[0].aszCmd, strlen(pstCmd[0].aszCmd)))
+            && (0 == HI_OSAL_Strncasecmp(GPU_CMD_FREQ, pstCmd[1].aszCmd, strlen(pstCmd[1].aszCmd))))
+        {
+            GPUDebugCtrl(GPUParseValue(pstCmd[1].aszValue), GPUParseValue(pstCmd[0].aszValue));
+        }
+        else if ((0 == HI_OSAL_Strncasecmp(GPU_CMD_FREQ, pstCmd[0].aszCmd, strlen(pstCmd[0].aszCmd)))
+                 && (0 == HI_OSAL_Strncasecmp(GPU_CMD_VOLT, pstCmd[1].aszCmd, strlen(pstCmd[1].aszCmd))))
+        {
+            GPUDebugCtrl(GPUParseValue(pstCmd[0].aszValue), GPUParseValue(pstCmd[1].aszValue));
+        }
+        else
+        {
+            goto err;
+        }
+    }
+    else
+    {
+        goto err;
+    }
+
+    return count;
+
+err:
+    HI_DRV_PROC_EchoHelper("Invaid parameter.\n");
+    GPUProcHelper();
+    return count;
+}
+
+int gpu_proc_create(void)
+{
+    DRV_PROC_ITEM_S *item;
+
+    item = HI_DRV_PROC_AddModule("pm_gpu", NULL, NULL);
+    if (!item)
+    {
+        MALI_PRINT_ERROR(("add GPU proc module failed\n"));
+        return -1;
+    }
+
+    item->read  = GPUProcRead;
+    item->write = GPUProcWrite;
+    return 0;
+}
+
+int gpu_proc_destroy(void)
+{
+    HI_DRV_PROC_RemoveModule("pm_gpu");
+    return 0;
+}
+
+#endif
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_proc.h b/driver/src/devicedrv/mali/platform/dt/mali4xx_proc.h
new file mode 100644
index 0000000..d8cda87
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_proc.h
@@ -0,0 +1,15 @@
+#ifndef __S40V200_GPU_PROC_H__
+#define __S40V200_GPU_PROC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int gpu_proc_create(void);
+int gpu_proc_destroy(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.c b/driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.c
new file mode 100644
index 0000000..4972951
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.c
@@ -0,0 +1,118 @@
+/*
+ * 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/mali/mali_utgard.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+
+#include "mali_kernel_common.h"
+
+#include "mali4xx_scaling.h"
+#include "mali4xx_cfg.h"
+
+static int num_cores_total;
+static int num_cores_enabled;
+
+static struct work_struct wq_work;
+
+static unsigned int utilization_gp_value;
+static unsigned int utilization_pp_value;
+
+#ifdef GPU_PP_SCALING_ENABLE
+unsigned int mali_pp_scale_cores = 0;
+module_param(mali_pp_scale_cores, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_pp_scale_cores, "pp scaling");
+#endif
+
+static void set_num_cores(struct work_struct *work)
+{
+    int err = mali_perf_set_num_pp_cores(num_cores_enabled);
+
+    MALI_DEBUG_ASSERT(0 == err);
+    MALI_IGNORE(err);
+}
+
+static void enable_fix_num_cores(unsigned int num)
+{
+	if(num > 0 && num <= num_cores_total)
+	{
+		num_cores_enabled = num ;
+		schedule_work(&wq_work);
+		MALI_DEBUG_PRINT(3, ("Core scaling: Enabling %d cores\n", num_cores_enabled));
+	}
+}
+
+unsigned int gpu_get_pp_scale_cores(void)
+{
+	return num_cores_enabled ;
+}
+
+unsigned int gpu_set_pp_scale_cores(unsigned int num)
+{
+	if(num > num_cores_total)
+	{
+		num = num_cores_total ;
+	}
+	else if(num < 1)
+	{
+		num = 1;
+	}
+
+	enable_fix_num_cores(num);
+
+    return num ;
+}
+
+void mali_core_scaling_init(int num_pp_cores)
+{
+    INIT_WORK(&wq_work, set_num_cores);
+
+    num_cores_total   = num_pp_cores;
+    num_cores_enabled = num_pp_cores;
+}
+
+void mali_core_scaling_term(void)
+{
+    flush_scheduled_work();
+}
+
+void mali_init_pp_scale_cores(unsigned int num)
+{
+#ifdef GPU_PP_SCALING_ENABLE
+	mali_pp_scale_cores = num ;
+#endif
+}
+
+void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
+{
+#ifdef GPU_PP_SCALING_ENABLE
+	if( mali_pp_scale_cores != gpu_get_pp_scale_cores() )
+	{
+		mali_pp_scale_cores = gpu_set_pp_scale_cores(mali_pp_scale_cores);
+		if( mali_pp_scale_cores == gpu_get_pp_scale_cores() )
+		{
+			MALI_DEBUG_PRINT(2, ("pp scale success, cores = %d\n", mali_pp_scale_cores));
+		}
+		else
+		{
+			MALI_DEBUG_PRINT(2, ("pp scale failed\n"));
+		}
+	}
+#endif
+
+    utilization_gp_value = data->utilization_gp;
+    utilization_pp_value = data->utilization_pp;
+}
+
diff --git a/driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.h b/driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.h
new file mode 100644
index 0000000..3419762
--- /dev/null
+++ b/driver/src/devicedrv/mali/platform/dt/mali4xx_scaling.h
@@ -0,0 +1,31 @@
+/*
+ * 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__
+
+void         mali_core_scaling_init(int num_pp_cores);
+
+void         mali_core_scaling_term(void);
+
+void mali_init_pp_scale_cores(unsigned int num);
+
+void         mali_core_scaling_update(struct mali_gpu_utilization_data *data);
+
+unsigned int gpu_get_gp_utilization(void);
+
+unsigned int gpu_get_pp_utilization(void);
+
+#endif /* __ARM_CORE_SCALING_H__ */
-- 
2.7.4