From acde16dd16012004efa1edb9dc9813f0c62622e4 Mon Sep 17 00:00:00 2001 From: Seshendra Gadagottu Date: Tue, 13 Oct 2015 11:39:43 -0700 Subject: 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 Reviewed-on: http://git-master/r/834748 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/Kconfig | 2 +- drivers/gpu/nvgpu/gk20a/gk20a_scale.c | 36 ++++++++-------- drivers/gpu/nvgpu/gk20a/gk20a_scale.h | 4 +- drivers/gpu/nvgpu/gk20a/platform_gk20a.h | 12 ++++++ drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 57 ++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/Kconfig b/drivers/gpu/nvgpu/Kconfig index 75aed3f6..bef9f0c2 100644 --- a/drivers/gpu/nvgpu/Kconfig +++ b/drivers/gpu/nvgpu/Kconfig @@ -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. diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_scale.c b/drivers/gpu/nvgpu/gk20a/gk20a_scale.c index c3affe83..0411e2fa 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_scale.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_scale.c @@ -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)); diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_scale.h b/drivers/gpu/nvgpu/gk20a/gk20a_scale.h index 5a9eff97..889a3973 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_scale.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a_scale.h @@ -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 diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h index c1444985..7314d09d 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h @@ -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); diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c index 8733f356..dee42476 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c @@ -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, -- cgit v1.2.2