You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2723 lines
76 KiB

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