diff options
author | Seshendra Gadagottu <sgadagottu@nvidia.com> | 2015-10-13 14:39:43 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-11-19 17:31:49 -0500 |
commit | acde16dd16012004efa1edb9dc9813f0c62622e4 (patch) | |
tree | 415603313667448d1325fe610b41d49c564c49c1 /drivers | |
parent | d3cf5811996388a1d7501da72fff46ee19e5e7c7 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_scale.c | 36 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_scale.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a.h | 12 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 57 |
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 | ||
38 | config GK20A_DEVFREQ | 38 | config 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 | ||
77 | static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile) | 78 | static 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) | |||
105 | static int gk20a_scale_target(struct device *dev, unsigned long *freq, | 102 | static 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 *); | |||
38 | void gk20a_scale_exit(struct platform_device *); | 38 | void gk20a_scale_exit(struct platform_device *); |
39 | void gk20a_scale_hw_init(struct platform_device *pdev); | 39 | void 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 | ||
804 | static 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 | |||
813 | static 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 | |||
822 | int 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 | |||
830 | static 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 | |||
803 | struct gk20a_platform gk20a_tegra_platform = { | 846 | struct 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, |