diff options
-rw-r--r-- | drivers/gpu/arm/mali/Kconfig | 7 | ||||
-rwxr-xr-x | drivers/gpu/arm/mali/Makefile | 11 | ||||
-rw-r--r-- | drivers/gpu/arm/mali/linux/mali_kernel_devfreq.c | 188 | ||||
-rw-r--r-- | drivers/gpu/arm/mali/linux/mali_kernel_devfreq.h | 51 | ||||
-rw-r--r-- | drivers/gpu/arm/mali/linux/mali_kernel_pm.c | 10 | ||||
-rw-r--r-- | drivers/gpu/arm/mali/platform/default/mali_platform.c | 5 | ||||
-rw-r--r-- | drivers/gpu/arm/mali/platform/mali_platform.h | 8 |
7 files changed, 279 insertions, 1 deletions
diff --git a/drivers/gpu/arm/mali/Kconfig b/drivers/gpu/arm/mali/Kconfig index 1404f59d3de..41110eb7270 100644 --- a/drivers/gpu/arm/mali/Kconfig +++ b/drivers/gpu/arm/mali/Kconfig @@ -39,6 +39,13 @@ config USING_GPU_UTILIZATION ---help--- This enables GPU utilization information. +config USING_GPU_DEVFREQ + bool "GPU devfreq" + depends on MALI400MP && USING_GPU_UTILIZATION + default n + ---help--- + This enables GPU devfreq. + config USING_MALI_RUN_TIME_PM bool "Using Run time Power Management" depends on MALI400MP diff --git a/drivers/gpu/arm/mali/Makefile b/drivers/gpu/arm/mali/Makefile index 263e076a4a9..0e3d29d9b04 100755 --- a/drivers/gpu/arm/mali/Makefile +++ b/drivers/gpu/arm/mali/Makefile @@ -47,6 +47,10 @@ ifeq ($(CONFIG_USING_GPU_UTILIZATION),y) USING_GPU_UTILIZATION =1 endif +ifeq ($(CONFIG_USING_GPU_DEVFREQ),y) +USING_GPU_DEVFREQ =1 +endif + ifeq ($(CONFIG_USING_MALI_RUN_TIME_PM),y) USING_MALI_RUN_TIME_PM =1 endif @@ -66,6 +70,7 @@ USING_UMP ?= 0 USING_OS_MEMORY ?= 0 USING_PMM ?= 0 USING_GPU_UTILIZATION ?= 0 +USING_GPU_DEVFREQ ?= 0 USING_MALI_RUN_TIME_PM ?= 0 USING_MALI_PMM_TESTSUITE ?= 0 OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 6 @@ -109,6 +114,7 @@ endif DEFINES += -DUSING_MALI_PMM=$(USING_PMM) DEFINES += -DMALI_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) +DEFINES += -DMALI_GPU_DEVFREQ=$(USING_GPU_DEVFREQ) ifeq ($(CONFIG_DEBUG_BUILD),y) DEFINES += -DDEBUG @@ -213,9 +219,14 @@ mali-y += \ endif ifeq ($(USING_GPU_UTILIZATION),1) +ifeq ($(USING_GPU_DEVFREQ),1) +mali-y += \ + linux/mali_kernel_devfreq.o +else mali-y += \ common/mali_kernel_utilization.o endif +endif ifneq ($(call submodule_enabled, $M, MALI400PP),0) # Mali-400 PP in use diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_devfreq.c b/drivers/gpu/arm/mali/linux/mali_kernel_devfreq.c new file mode 100644 index 00000000000..1213e7bc694 --- /dev/null +++ b/drivers/gpu/arm/mali/linux/mali_kernel_devfreq.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2010-2011 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. + */ + +#include <linux/devfreq.h> +#include <linux/platform_device.h> +#include "mali_kernel_devfreq.h" +#include "mali_osk.h" +#include "mali_platform.h" +#include "mali_linux_pm.h" + +#define MALI_GPU_UTILIZATION_PERIOD 500 + +static _mali_osk_lock_t *time_data_lock; + +static _mali_osk_atomic_t num_running_cores; + +static u64 period_start_time = 0; +static u64 work_start_time = 0; +static u64 accumulated_work_time = 0; +static mali_bool timer_running = MALI_FALSE; + +static struct devfreq *mali_devfreq; + +static int mali_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat) +{ + u64 time_now; + u64 time_period; + + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + if (accumulated_work_time == 0 && work_start_time == 0) + { + /* No work done for this period, report zero usage */ + stat->total_time = 0; + stat->busy_time = 0; + stat->current_frequency = get_mali_platform_cur_freq(); + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + return 0; + } + + time_now = _mali_osk_time_get_ns(); + time_period = time_now - period_start_time; + + /* If we are currently busy, update working period up to now */ + if (work_start_time != 0) + { + accumulated_work_time += (time_now - work_start_time); + work_start_time = time_now; + } + + stat->total_time = time_period; + stat->busy_time = accumulated_work_time; + stat->current_frequency = get_mali_platform_cur_freq(); + + accumulated_work_time = 0; + /* start a new period */ + period_start_time = time_now; + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + return 0; +} + +static int mali_set_target_freq(struct device *dev, + unsigned long *freq, + u32 flags) +{ + mali_gpu_utilization_handler(*freq); + return 0; +} + +static int mali_get_cur_freq(struct device *dev, unsigned long *freq) +{ + *freq = get_mali_platform_cur_freq(); + return 0; +} + +static struct devfreq_dev_profile mali_devfreq_profile = { + .polling_ms = MALI_GPU_UTILIZATION_PERIOD, + .initial_freq = 0, + .target = mali_set_target_freq, + .get_dev_status = mali_get_dev_status, + .get_cur_freq = mali_get_cur_freq, +}; + +_mali_osk_errcode_t mali_utilization_init(void) +{ + /* Register mali devfreq with ondemand governor */ + mali_devfreq = devfreq_add_device(&mali_gpu_device.dev, + &mali_devfreq_profile, + &devfreq_simple_ondemand, + NULL); + if (NULL == mali_devfreq) + { + return _MALI_OSK_ERR_FAULT; + } + + time_data_lock = _mali_osk_lock_init( 0, 0, 0 ); + if (NULL == time_data_lock) + { + return _MALI_OSK_ERR_FAULT; + } + + _mali_osk_atomic_init(&num_running_cores, 0); + + return _MALI_OSK_ERR_OK; +} + +void mali_utilization_suspend(void) +{ + if (timer_running == MALI_TRUE) + { + devfreq_suspend_device(mali_devfreq); + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + timer_running = MALI_FALSE; + work_start_time = 0; + period_start_time = 0; + accumulated_work_time = 0; + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} + +void mali_utilization_resume(void) +{ + devfreq_resume_device(mali_devfreq); +} + +void mali_utilization_term(void) +{ + devfreq_remove_device(mali_devfreq); + mali_devfreq = NULL; + + timer_running = MALI_FALSE; + + _mali_osk_atomic_term(&num_running_cores); + + _mali_osk_lock_term(time_data_lock); +} + +void mali_utilization_core_start(void) +{ + if (_mali_osk_atomic_inc_return(&num_running_cores) == 1) + { + /* + * We went from zero cores working, to one core working, + * we now consider the entire GPU for being busy + */ + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + work_start_time = _mali_osk_time_get_ns(); + + if (timer_running != MALI_TRUE) + { + timer_running = MALI_TRUE; + period_start_time = work_start_time; + } + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} + +void mali_utilization_core_end(void) +{ + if (_mali_osk_atomic_dec_return(&num_running_cores) == 0) + { + /* + * No more cores are working, so accumulate the time we was busy. + */ + u64 time_now; + + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + + time_now = _mali_osk_time_get_ns(); + accumulated_work_time += (time_now - work_start_time); + work_start_time = 0; + + _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW); + } +} diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_devfreq.h b/drivers/gpu/arm/mali/linux/mali_kernel_devfreq.h new file mode 100644 index 00000000000..e0a76dcbb35 --- /dev/null +++ b/drivers/gpu/arm/mali/linux/mali_kernel_devfreq.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010-2011 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. + */ + +#ifndef __MALI_KERNEL_DEVFREQ_H__ +#define __MALI_KERNEL_DEVFREQ_H__ + +#include "mali_osk.h" + +/** + * Initialize/start the Mali GPU utilization metrics reporting. + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t mali_utilization_init(void); + +/** + * Terminate the Mali GPU utilization metrics reporting + */ +void mali_utilization_term(void); + +/** + * Should be called when a job is about to execute a job + */ +void mali_utilization_core_start(void); + +/** + * Should be called to suspend the utilization monitoring during + * system suspend or device pm-runtime suspend + */ +void mali_utilization_suspend(void); + +/** + * Should be called to resume the utilization monitoring during + * system resume or device pm-runtime resume + */ +void mali_utilization_resume(void); + +/** + * Should be called when a job has completed executing a job + */ +void mali_utilization_core_end(void); + + +#endif /* __MALI_KERNEL_DEVFREQ_H__ */ diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_pm.c b/drivers/gpu/arm/mali/linux/mali_kernel_pm.c index ea92368ccae..99ce009c03c 100644 --- a/drivers/gpu/arm/mali/linux/mali_kernel_pm.c +++ b/drivers/gpu/arm/mali/linux/mali_kernel_pm.c @@ -41,6 +41,10 @@ #include "mali_kernel_utilization.h" #endif /* MALI_GPU_UTILIZATION */ +#if MALI_GPU_DEVFREQ +#include "mali_kernel_devfreq.h" +#endif /* MALI_GPU_DEVFREQ */ + #if MALI_POWER_MGMT_TEST_SUITE #ifdef CONFIG_PM #include "mali_linux_pm_testsuite.h" @@ -419,6 +423,9 @@ static int mali_pm_os_resume_on_hibernation(struct device *dev) */ static int mali_device_runtime_suspend(struct device *dev) { +#if MALI_GPU_DEVFREQ + mali_utilization_suspend(); +#endif /* MALI_GPU_DEVFREQ */ MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time suspended \n" )); return 0; } @@ -427,6 +434,9 @@ static int mali_device_runtime_suspend(struct device *dev) */ static int mali_device_runtime_resume(struct device *dev) { +#if MALI_GPU_DEVFREQ + mali_utilization_resume(); +#endif /* MALI_GPU_DEVFREQ */ MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time Resumed \n" )); return 0; } diff --git a/drivers/gpu/arm/mali/platform/default/mali_platform.c b/drivers/gpu/arm/mali/platform/default/mali_platform.c index d966f25f6c4..824785620ac 100644 --- a/drivers/gpu/arm/mali/platform/default/mali_platform.c +++ b/drivers/gpu/arm/mali/platform/default/mali_platform.c @@ -40,4 +40,7 @@ void set_mali_parent_power_domain(void* dev) { } - +unsigned long get_mali_platform_cur_freq(void) +{ + return 0; +} diff --git a/drivers/gpu/arm/mali/platform/mali_platform.h b/drivers/gpu/arm/mali/platform/mali_platform.h index 078bcefa11b..f1bb2b5c7ad 100644 --- a/drivers/gpu/arm/mali/platform/mali_platform.h +++ b/drivers/gpu/arm/mali/platform/mali_platform.h @@ -93,6 +93,14 @@ void mali_gpu_utilization_handler(u32 utilization); */ void set_mali_parent_power_domain(void* dev); +/** @brief Get MALI current running frequency + * + * This function gets the current running frequency of MALI + * + * @return frequency in Hz + */ +unsigned long get_mali_platform_cur_freq(void); + #ifdef __cplusplus } #endif |