gpu: nvgpu: scaling driver update

Update scaling driver to support to differnt
clock frameworks.

Bug 200147662

Reviewed-on: http://git-master/r/816929
(cherry picked from commit cbd4cb575fb2d27870089797ff2a8f22540b87e8)

Change-Id: Ie50304b4a593d74bd43b271005cc9616fdb52a6e
Signed-off-by: Seshendra Gadagottu <sgadagottu@nvidia.com>
Reviewed-on: http://git-master/r/834748
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Seshendra Gadagottu
2015-10-13 11:39:43 -07:00
committed by Terje Bergstrom
parent d3cf581199
commit acde16dd16
5 changed files with 90 additions and 21 deletions

View File

@@ -36,7 +36,7 @@ config GK20A_PERFMON
decrease frequency if idle).
config GK20A_DEVFREQ
depends on TEGRA_CLK_FRAMEWORK
depends on TEGRA_CLK_FRAMEWORK || COMMON_CLK
bool "Use Devfreq"
help
Select this to use devfreq based scaling.

View File

@@ -56,7 +56,8 @@ static int gk20a_scale_qos_notify(struct notifier_block *nb,
/* get the frequency requirement. if devfreq is enabled, check if it
* has higher demand than qos */
freq = gk20a_clk_round_rate(g, pm_qos_request(platform->qos_id));
freq = platform->clk_round_rate(profile->pdev,
pm_qos_request(platform->qos_id));
if (g->devfreq)
freq = max(g->devfreq->previous_freq, freq);
@@ -76,17 +77,13 @@ static int gk20a_scale_qos_notify(struct notifier_block *nb,
static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile)
{
struct gk20a *g = get_gk20a(profile->pdev);
unsigned long *freqs;
struct gk20a_platform *platform = platform_get_drvdata(profile->pdev);
int num_freqs, err;
unsigned long *freqs;
/* make sure the clock is available */
if (!gk20a_clk_get(g))
return -ENOSYS;
/* get gpu dvfs table */
err = tegra_dvfs_get_freqs(clk_get_parent(g->clk.tegra_clk),
&freqs, &num_freqs);
/* get gpu frequency table */
err = platform->get_clk_freqs(profile->pdev, &freqs,
&num_freqs);
if (err)
return -ENOSYS;
@@ -105,23 +102,23 @@ static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile)
static int gk20a_scale_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct gk20a *g = get_gk20a(to_platform_device(dev));
struct gk20a_platform *platform = dev_get_drvdata(dev);
struct gk20a_scale_profile *profile = g->scale_profile;
unsigned long rounded_rate = gk20a_clk_round_rate(g, *freq);
struct platform_device *pdev = to_platform_device(dev);
unsigned long rounded_rate =
platform->clk_round_rate(pdev, *freq);
if (gk20a_clk_get_rate(g) == rounded_rate)
if (platform->clk_get_rate(pdev) == rounded_rate)
*freq = rounded_rate;
else {
gk20a_clk_set_rate(g, rounded_rate);
*freq = gk20a_clk_get_rate(g);
platform->clk_set_rate(pdev, rounded_rate);
*freq = platform->clk_get_rate(pdev);
}
/* postscale will only scale emc (dram clock) if evaluating
* gk20a_tegra_get_emc_rate() produces a new or different emc
* target because the load or_and gpufreq has changed */
if (platform->postscale)
platform->postscale(profile->pdev, rounded_rate);
platform->postscale(pdev, rounded_rate);
return 0;
}
@@ -237,9 +234,12 @@ static int gk20a_scale_get_dev_status(struct device *dev,
{
struct gk20a *g = get_gk20a(to_platform_device(dev));
struct gk20a_scale_profile *profile = g->scale_profile;
struct platform_device *pdev = to_platform_device(dev);
struct gk20a_platform *platform = platform_get_drvdata(pdev);
/* Make sure there are correct values for the current frequency */
profile->dev_stat.current_frequency = gk20a_clk_get_rate(g);
profile->dev_stat.current_frequency =
platform->clk_get_rate(profile->pdev);
/* Update load estimate */
update_load_estimate_gpmu(to_platform_device(dev));

View File

@@ -1,7 +1,7 @@
/*
* gk20a clock scaling profile
*
* Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved.
* Copyright (c) 2013-2015, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -38,7 +38,7 @@ void gk20a_scale_init(struct platform_device *);
void gk20a_scale_exit(struct platform_device *);
void gk20a_scale_hw_init(struct platform_device *pdev);
#ifdef CONFIG_GK20A_DEVFREQ
#if defined(CONFIG_GK20A_DEVFREQ)
/*
* call when performing submit to notify scaling mechanism that the module is
* in use

View File

@@ -154,6 +154,18 @@ struct gk20a_platform {
/* Called to check state of device */
bool (*is_railgated)(struct platform_device *dev);
/* get supported frequency list */
int (*get_clk_freqs)(struct platform_device *pdev,
unsigned long **freqs, int *num_freqs);
/* clk related supported functions */
unsigned long (*clk_get_rate)(struct platform_device *pdev);
long (*clk_round_rate)(struct platform_device *pdev,
unsigned long rate);
int (*clk_set_rate)(struct platform_device *pdev,
unsigned long rate);
/* Postscale callback is called after frequency change */
void (*postscale)(struct platform_device *pdev,
unsigned long freq);

View File

@@ -800,6 +800,49 @@ static int gk20a_tegra_suspend(struct device *dev)
return 0;
}
#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
static unsigned long gk20a_get_clk_rate(struct platform_device *dev)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
return gk20a_clk_get_rate(g);
}
static long gk20a_round_clk_rate(struct platform_device *dev,
unsigned long rate)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
return gk20a_clk_round_rate(g, rate);
}
int gk20a_set_clk_rate(struct platform_device *dev, unsigned long rate)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
return gk20a_clk_set_rate(g, rate);
}
static int gk20a_clk_get_freqs(struct platform_device *dev,
unsigned long **freqs, int *num_freqs)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
/* make sure the clock is available */
if (!gk20a_clk_get(g))
return -ENOSYS;
return tegra_dvfs_get_freqs(clk_get_parent(g->clk.tegra_clk),
freqs, num_freqs);
}
#endif
struct gk20a_platform gk20a_tegra_platform = {
.has_syncpoints = true,
@@ -838,6 +881,13 @@ struct gk20a_platform gk20a_tegra_platform = {
.reset_assert = gk20a_tegra_reset_assert,
.reset_deassert = gk20a_tegra_reset_deassert,
#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
.clk_get_rate = gk20a_get_clk_rate,
.clk_round_rate = gk20a_round_clk_rate,
.clk_set_rate = gk20a_set_clk_rate,
.get_clk_freqs = gk20a_clk_get_freqs,
#endif
/* frequency scaling configuration */
.prescale = gk20a_tegra_prescale,
.postscale = gk20a_tegra_postscale,
@@ -887,6 +937,13 @@ struct gk20a_platform gm20b_tegra_platform = {
.reset_assert = gm20b_tegra_reset_assert,
.reset_deassert = gk20a_tegra_reset_deassert,
#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
.clk_get_rate = gk20a_get_clk_rate,
.clk_round_rate = gk20a_round_clk_rate,
.clk_set_rate = gk20a_set_clk_rate,
.get_clk_freqs = gk20a_clk_get_freqs,
#endif
/* frequency scaling configuration */
.prescale = gk20a_tegra_prescale,
.postscale = gk20a_tegra_postscale,