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