summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeshendra Gadagottu <sgadagottu@nvidia.com>2015-10-13 14:39:43 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2015-11-19 17:31:49 -0500
commitacde16dd16012004efa1edb9dc9813f0c62622e4 (patch)
tree415603313667448d1325fe610b41d49c564c49c1
parentd3cf5811996388a1d7501da72fff46ee19e5e7c7 (diff)
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>
-rw-r--r--drivers/gpu/nvgpu/Kconfig2
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_scale.c36
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_scale.h4
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a.h12
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c57
5 files changed, 90 insertions, 21 deletions
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
36 decrease frequency if idle). 36 decrease frequency if idle).
37 37
38config GK20A_DEVFREQ 38config GK20A_DEVFREQ
39 depends on TEGRA_CLK_FRAMEWORK 39 depends on TEGRA_CLK_FRAMEWORK || COMMON_CLK
40 bool "Use Devfreq" 40 bool "Use Devfreq"
41 help 41 help
42 Select this to use devfreq based scaling. 42 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,
56 56
57 /* get the frequency requirement. if devfreq is enabled, check if it 57 /* get the frequency requirement. if devfreq is enabled, check if it
58 * has higher demand than qos */ 58 * has higher demand than qos */
59 freq = gk20a_clk_round_rate(g, pm_qos_request(platform->qos_id)); 59 freq = platform->clk_round_rate(profile->pdev,
60 pm_qos_request(platform->qos_id));
60 if (g->devfreq) 61 if (g->devfreq)
61 freq = max(g->devfreq->previous_freq, freq); 62 freq = max(g->devfreq->previous_freq, freq);
62 63
@@ -76,17 +77,13 @@ static int gk20a_scale_qos_notify(struct notifier_block *nb,
76 77
77static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile) 78static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile)
78{ 79{
79 struct gk20a *g = get_gk20a(profile->pdev); 80 struct gk20a_platform *platform = platform_get_drvdata(profile->pdev);
80 unsigned long *freqs;
81 int num_freqs, err; 81 int num_freqs, err;
82 unsigned long *freqs;
82 83
83 /* make sure the clock is available */ 84 /* get gpu frequency table */
84 if (!gk20a_clk_get(g)) 85 err = platform->get_clk_freqs(profile->pdev, &freqs,
85 return -ENOSYS; 86 &num_freqs);
86
87 /* get gpu dvfs table */
88 err = tegra_dvfs_get_freqs(clk_get_parent(g->clk.tegra_clk),
89 &freqs, &num_freqs);
90 if (err) 87 if (err)
91 return -ENOSYS; 88 return -ENOSYS;
92 89
@@ -105,23 +102,23 @@ static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile)
105static int gk20a_scale_target(struct device *dev, unsigned long *freq, 102static int gk20a_scale_target(struct device *dev, unsigned long *freq,
106 u32 flags) 103 u32 flags)
107{ 104{
108 struct gk20a *g = get_gk20a(to_platform_device(dev));
109 struct gk20a_platform *platform = dev_get_drvdata(dev); 105 struct gk20a_platform *platform = dev_get_drvdata(dev);
110 struct gk20a_scale_profile *profile = g->scale_profile; 106 struct platform_device *pdev = to_platform_device(dev);
111 unsigned long rounded_rate = gk20a_clk_round_rate(g, *freq); 107 unsigned long rounded_rate =
108 platform->clk_round_rate(pdev, *freq);
112 109
113 if (gk20a_clk_get_rate(g) == rounded_rate) 110 if (platform->clk_get_rate(pdev) == rounded_rate)
114 *freq = rounded_rate; 111 *freq = rounded_rate;
115 else { 112 else {
116 gk20a_clk_set_rate(g, rounded_rate); 113 platform->clk_set_rate(pdev, rounded_rate);
117 *freq = gk20a_clk_get_rate(g); 114 *freq = platform->clk_get_rate(pdev);
118 } 115 }
119 116
120 /* postscale will only scale emc (dram clock) if evaluating 117 /* postscale will only scale emc (dram clock) if evaluating
121 * gk20a_tegra_get_emc_rate() produces a new or different emc 118 * gk20a_tegra_get_emc_rate() produces a new or different emc
122 * target because the load or_and gpufreq has changed */ 119 * target because the load or_and gpufreq has changed */
123 if (platform->postscale) 120 if (platform->postscale)
124 platform->postscale(profile->pdev, rounded_rate); 121 platform->postscale(pdev, rounded_rate);
125 122
126 return 0; 123 return 0;
127} 124}
@@ -237,9 +234,12 @@ static int gk20a_scale_get_dev_status(struct device *dev,
237{ 234{
238 struct gk20a *g = get_gk20a(to_platform_device(dev)); 235 struct gk20a *g = get_gk20a(to_platform_device(dev));
239 struct gk20a_scale_profile *profile = g->scale_profile; 236 struct gk20a_scale_profile *profile = g->scale_profile;
237 struct platform_device *pdev = to_platform_device(dev);
238 struct gk20a_platform *platform = platform_get_drvdata(pdev);
240 239
241 /* Make sure there are correct values for the current frequency */ 240 /* Make sure there are correct values for the current frequency */
242 profile->dev_stat.current_frequency = gk20a_clk_get_rate(g); 241 profile->dev_stat.current_frequency =
242 platform->clk_get_rate(profile->pdev);
243 243
244 /* Update load estimate */ 244 /* Update load estimate */
245 update_load_estimate_gpmu(to_platform_device(dev)); 245 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 @@
1/* 1/*
2 * gk20a clock scaling profile 2 * gk20a clock scaling profile
3 * 3 *
4 * Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2013-2015, NVIDIA Corporation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -38,7 +38,7 @@ void gk20a_scale_init(struct platform_device *);
38void gk20a_scale_exit(struct platform_device *); 38void gk20a_scale_exit(struct platform_device *);
39void gk20a_scale_hw_init(struct platform_device *pdev); 39void gk20a_scale_hw_init(struct platform_device *pdev);
40 40
41#ifdef CONFIG_GK20A_DEVFREQ 41#if defined(CONFIG_GK20A_DEVFREQ)
42/* 42/*
43 * call when performing submit to notify scaling mechanism that the module is 43 * call when performing submit to notify scaling mechanism that the module is
44 * in use 44 * 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 {
154 /* Called to check state of device */ 154 /* Called to check state of device */
155 bool (*is_railgated)(struct platform_device *dev); 155 bool (*is_railgated)(struct platform_device *dev);
156 156
157 /* get supported frequency list */
158 int (*get_clk_freqs)(struct platform_device *pdev,
159 unsigned long **freqs, int *num_freqs);
160
161 /* clk related supported functions */
162 unsigned long (*clk_get_rate)(struct platform_device *pdev);
163 long (*clk_round_rate)(struct platform_device *pdev,
164 unsigned long rate);
165 int (*clk_set_rate)(struct platform_device *pdev,
166 unsigned long rate);
167
168
157 /* Postscale callback is called after frequency change */ 169 /* Postscale callback is called after frequency change */
158 void (*postscale)(struct platform_device *pdev, 170 void (*postscale)(struct platform_device *pdev,
159 unsigned long freq); 171 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)
800 return 0; 800 return 0;
801} 801}
802 802
803#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
804static unsigned long gk20a_get_clk_rate(struct platform_device *dev)
805{
806 struct gk20a_platform *platform = gk20a_get_platform(dev);
807 struct gk20a *g = platform->g;
808
809 return gk20a_clk_get_rate(g);
810
811}
812
813static long gk20a_round_clk_rate(struct platform_device *dev,
814 unsigned long rate)
815{
816 struct gk20a_platform *platform = gk20a_get_platform(dev);
817 struct gk20a *g = platform->g;
818
819 return gk20a_clk_round_rate(g, rate);
820}
821
822int gk20a_set_clk_rate(struct platform_device *dev, unsigned long rate)
823{
824 struct gk20a_platform *platform = gk20a_get_platform(dev);
825 struct gk20a *g = platform->g;
826
827 return gk20a_clk_set_rate(g, rate);
828}
829
830static int gk20a_clk_get_freqs(struct platform_device *dev,
831 unsigned long **freqs, int *num_freqs)
832{
833 struct gk20a_platform *platform = gk20a_get_platform(dev);
834 struct gk20a *g = platform->g;
835
836 /* make sure the clock is available */
837 if (!gk20a_clk_get(g))
838 return -ENOSYS;
839
840 return tegra_dvfs_get_freqs(clk_get_parent(g->clk.tegra_clk),
841 freqs, num_freqs);
842}
843#endif
844
845
803struct gk20a_platform gk20a_tegra_platform = { 846struct gk20a_platform gk20a_tegra_platform = {
804 .has_syncpoints = true, 847 .has_syncpoints = true,
805 848
@@ -838,6 +881,13 @@ struct gk20a_platform gk20a_tegra_platform = {
838 .reset_assert = gk20a_tegra_reset_assert, 881 .reset_assert = gk20a_tegra_reset_assert,
839 .reset_deassert = gk20a_tegra_reset_deassert, 882 .reset_deassert = gk20a_tegra_reset_deassert,
840 883
884#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
885 .clk_get_rate = gk20a_get_clk_rate,
886 .clk_round_rate = gk20a_round_clk_rate,
887 .clk_set_rate = gk20a_set_clk_rate,
888 .get_clk_freqs = gk20a_clk_get_freqs,
889#endif
890
841 /* frequency scaling configuration */ 891 /* frequency scaling configuration */
842 .prescale = gk20a_tegra_prescale, 892 .prescale = gk20a_tegra_prescale,
843 .postscale = gk20a_tegra_postscale, 893 .postscale = gk20a_tegra_postscale,
@@ -887,6 +937,13 @@ struct gk20a_platform gm20b_tegra_platform = {
887 .reset_assert = gm20b_tegra_reset_assert, 937 .reset_assert = gm20b_tegra_reset_assert,
888 .reset_deassert = gk20a_tegra_reset_deassert, 938 .reset_deassert = gk20a_tegra_reset_deassert,
889 939
940#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
941 .clk_get_rate = gk20a_get_clk_rate,
942 .clk_round_rate = gk20a_round_clk_rate,
943 .clk_set_rate = gk20a_set_clk_rate,
944 .get_clk_freqs = gk20a_clk_get_freqs,
945#endif
946
890 /* frequency scaling configuration */ 947 /* frequency scaling configuration */
891 .prescale = gk20a_tegra_prescale, 948 .prescale = gk20a_tegra_prescale,
892 .postscale = gk20a_tegra_postscale, 949 .postscale = gk20a_tegra_postscale,