diff options
Diffstat (limited to 'drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c')
-rwxr-xr-x[-rw-r--r--] | drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c | 236 |
1 files changed, 43 insertions, 193 deletions
diff --git a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c index bcf7971a5fdb..9514daf42a8a 100644..100755 --- a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c @@ -14,12 +14,9 @@ #include <mali_kbase.h> #include <mali_kbase_defs.h> #include <mali_kbase_config.h> -#include <backend/gpu/mali_kbase_pm_internal.h> #include <linux/pm_runtime.h> #include <linux/suspend.h> -#include <linux/of.h> -#include <linux/delay.h> #include "mali_kbase_rk.h" @@ -42,54 +39,18 @@ /*---------------------------------------------------------------------------*/ -#ifdef CONFIG_REGULATOR static int rk_pm_enable_regulator(struct kbase_device *kbdev); + static void rk_pm_disable_regulator(struct kbase_device *kbdev); -#else -static inline int rk_pm_enable_regulator(struct kbase_device *kbdev) -{ - return 0; -} -static inline void rk_pm_disable_regulator(struct kbase_device *kbdev) -{ -} -#endif static int rk_pm_enable_clk(struct kbase_device *kbdev); static void rk_pm_disable_clk(struct kbase_device *kbdev); -static int kbase_platform_rk_create_sysfs_files(struct device *dev); - -static void kbase_platform_rk_remove_sysfs_files(struct device *dev); - /*---------------------------------------------------------------------------*/ -static void rk_pm_power_off_delay_work(struct work_struct *work) -{ - struct rk_context *platform = - container_of(to_delayed_work(work), struct rk_context, work); - struct kbase_device *kbdev = platform->kbdev; - - if (!platform->is_powered) { - D("mali_dev is already powered off."); - return; - } - - if (pm_runtime_enabled(kbdev->dev)) { - D("to put_sync_suspend mali_dev."); - pm_runtime_put_sync_suspend(kbdev->dev); - } - - rk_pm_disable_regulator(kbdev); - - platform->is_powered = false; - KBASE_TIMELINE_GPU_POWER(kbdev, 0); -} - static int kbase_platform_rk_init(struct kbase_device *kbdev) { - int ret = 0; struct rk_context *platform; platform = kzalloc(sizeof(*platform), GFP_KERNEL); @@ -99,49 +60,14 @@ static int kbase_platform_rk_init(struct kbase_device *kbdev) } platform->is_powered = false; - platform->kbdev = kbdev; - - platform->delay_ms = 200; - if (of_property_read_u32(kbdev->dev->of_node, "power-off-delay-ms", - &platform->delay_ms)) - W("power-off-delay-ms not available."); - - platform->power_off_wq = create_freezable_workqueue("gpu_power_off_wq"); - if (!platform->power_off_wq) { - E("couldn't create workqueue"); - return -ENOMEM; - } - INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work); - platform->utilisation_period = DEFAULT_UTILISATION_PERIOD_IN_MS; - - ret = kbase_platform_rk_create_sysfs_files(kbdev->dev); - if (ret) { - E("fail to create sysfs_files. ret = %d.", ret); - goto EXIT; - } kbdev->platform_context = (void *)platform; - pm_runtime_enable(kbdev->dev); -EXIT: - return ret; + return 0; } static void kbase_platform_rk_term(struct kbase_device *kbdev) { - struct rk_context *platform = - (struct rk_context *)kbdev->platform_context; - - pm_runtime_disable(kbdev->dev); - kbdev->platform_context = NULL; - - if (platform) { - destroy_workqueue(platform->power_off_wq); - platform->is_powered = false; - platform->kbdev = NULL; - kfree(platform); - } - kbase_platform_rk_remove_sysfs_files(kbdev->dev); } struct kbase_platform_funcs_conf platform_funcs = { @@ -164,21 +90,16 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) { int ret = 1; /* Assume GPU has been powered off */ int err = 0; - struct rk_context *platform = get_rk_context(kbdev); - - cancel_delayed_work_sync(&platform->work); - - err = rk_pm_enable_clk(kbdev); - if (err) { - E("failed to enable clk: %d", err); - return err; - } + struct rk_context *platform; + platform = (struct rk_context *)kbdev->platform_context; if (platform->is_powered) { - D("mali_device is already powered."); + W("mali_device is already powered."); return 0; } + D("powering on."); + /* we must enable vdd_gpu before pd_gpu_in_chip. */ err = rk_pm_enable_regulator(kbdev); if (err) { @@ -202,6 +123,12 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) } } + err = rk_pm_enable_clk(kbdev); /* clk is not relative to pd. */ + if (err) { + E("failed to enable clk: %d", err); + return err; + } + platform->is_powered = true; KBASE_TIMELINE_GPU_POWER(kbdev, 1); @@ -210,20 +137,47 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) static void rk_pm_callback_power_off(struct kbase_device *kbdev) { - struct rk_context *platform = get_rk_context(kbdev); + struct rk_context *platform = + (struct rk_context *)kbdev->platform_context; + + if (!platform->is_powered) { + W("mali_dev is already powered off."); + return; + } + + D("powering off."); + + platform->is_powered = false; + KBASE_TIMELINE_GPU_POWER(kbdev, 0); rk_pm_disable_clk(kbdev); - queue_delayed_work(platform->power_off_wq, &platform->work, - msecs_to_jiffies(platform->delay_ms)); + + if (pm_runtime_enabled(kbdev->dev)) { + pm_runtime_mark_last_busy(kbdev->dev); + D("to put_sync_suspend mali_dev."); + pm_runtime_put_sync_suspend(kbdev->dev); + } + + rk_pm_disable_regulator(kbdev); } int rk_kbase_device_runtime_init(struct kbase_device *kbdev) { + pm_runtime_set_autosuspend_delay(kbdev->dev, 200); + pm_runtime_use_autosuspend(kbdev->dev); + + /* no need to call pm_runtime_set_active here. */ + + D("to enable pm_runtime."); + pm_runtime_enable(kbdev->dev); + return 0; } void rk_kbase_device_runtime_disable(struct kbase_device *kbdev) { + D("to disable pm_runtime."); + pm_runtime_disable(kbdev->dev); } struct kbase_pm_callback_conf pm_callbacks = { @@ -250,15 +204,6 @@ int kbase_platform_early_init(void) /*---------------------------------------------------------------------------*/ -void kbase_platform_rk_shutdown(struct kbase_device *kbdev) -{ - I("to make vdd_gpu enabled for turning off pd_gpu in pm_framework."); - rk_pm_enable_regulator(kbdev); -} - -/*---------------------------------------------------------------------------*/ - -#ifdef CONFIG_REGULATOR static int rk_pm_enable_regulator(struct kbase_device *kbdev) { int ret = 0; @@ -289,7 +234,6 @@ static void rk_pm_disable_regulator(struct kbase_device *kbdev) D("to disable regulator."); regulator_disable(kbdev->regulator); } -#endif static int rk_pm_enable_clk(struct kbase_device *kbdev) { @@ -317,97 +261,3 @@ static void rk_pm_disable_clk(struct kbase_device *kbdev) } } -/*---------------------------------------------------------------------------*/ - -static ssize_t utilisation_period_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct kbase_device *kbdev = dev_get_drvdata(dev); - struct rk_context *platform = get_rk_context(kbdev); - ssize_t ret = 0; - - ret += snprintf(buf, PAGE_SIZE, "%u\n", platform->utilisation_period); - - return ret; -} - -static ssize_t utilisation_period_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct kbase_device *kbdev = dev_get_drvdata(dev); - struct rk_context *platform = get_rk_context(kbdev); - int ret = 0; - - ret = kstrtouint(buf, 0, &platform->utilisation_period); - if (ret) { - E("invalid input period : %s.", buf); - return ret; - } - D("set utilisation_period to '%d'.", platform->utilisation_period); - - return count; -} - -static ssize_t utilisation_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct kbase_device *kbdev = dev_get_drvdata(dev); - struct rk_context *platform = get_rk_context(kbdev); - ssize_t ret = 0; - unsigned long period_in_us = platform->utilisation_period * 1000; - unsigned long total_time; - unsigned long busy_time; - unsigned long utilisation; - - kbase_pm_reset_dvfs_utilisation(kbdev); - usleep_range(period_in_us, period_in_us + 100); - kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time); - /* 'devfreq_dev_profile' instance registered to devfreq - * also uses kbase_pm_reset_dvfs_utilisation - * and kbase_pm_get_dvfs_utilisation. - * it's better to cat this file when DVFS is disabled. - */ - D("total_time : %lu, busy_time : %lu.", total_time, busy_time); - - utilisation = busy_time * 100 / total_time; - ret += snprintf(buf, PAGE_SIZE, "%ld\n", utilisation); - - return ret; -} - -static DEVICE_ATTR_RW(utilisation_period); -static DEVICE_ATTR_RO(utilisation); - -static int kbase_platform_rk_create_sysfs_files(struct device *dev) -{ - int ret = 0; - - ret = device_create_file(dev, &dev_attr_utilisation_period); - if (ret) { - E("fail to create sysfs file 'utilisation_period'."); - goto out; - } - - ret = device_create_file(dev, &dev_attr_utilisation); - if (ret) { - E("fail to create sysfs file 'utilisation'."); - goto remove_utilisation_period; - } - - return 0; - -remove_utilisation_period: - device_remove_file(dev, &dev_attr_utilisation_period); -out: - return ret; -} - -static void kbase_platform_rk_remove_sysfs_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_utilisation_period); - device_remove_file(dev, &dev_attr_utilisation); -} |