diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c index e1a96e4c..27274e95 100644 --- a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c | |||
@@ -29,16 +29,23 @@ | |||
29 | #include <linux/hashtable.h> | 29 | #include <linux/hashtable.h> |
30 | #include "gk20a/platform_gk20a.h" | 30 | #include "gk20a/platform_gk20a.h" |
31 | #include "gk20a/gk20a.h" | 31 | #include "gk20a/gk20a.h" |
32 | #include "gk20a/gk20a_scale.h" | ||
32 | #include "platform_tegra.h" | 33 | #include "platform_tegra.h" |
33 | #include "gr_gp10b.h" | 34 | #include "gr_gp10b.h" |
34 | #include "ltc_gp10b.h" | 35 | #include "ltc_gp10b.h" |
35 | #include "hw_gr_gp10b.h" | 36 | #include "hw_gr_gp10b.h" |
36 | #include "hw_ltc_gp10b.h" | 37 | #include "hw_ltc_gp10b.h" |
37 | #include "gp10b_sysfs.h" | 38 | #include "gp10b_sysfs.h" |
39 | #include <linux/platform/tegra/emc_bwmgr.h> | ||
38 | 40 | ||
39 | #define GP10B_MAX_SUPPORTED_FREQS 11 | 41 | #define GP10B_MAX_SUPPORTED_FREQS 11 |
40 | static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; | 42 | static unsigned long gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS]; |
41 | 43 | ||
44 | #define TEGRA_GP10B_BW_PER_FREQ 64 | ||
45 | #define TEGRA_DDR4_BW_PER_FREQ 16 | ||
46 | |||
47 | #define EMC_BW_RATIO (TEGRA_GP10B_BW_PER_FREQ / TEGRA_DDR4_BW_PER_FREQ) | ||
48 | |||
42 | static struct { | 49 | static struct { |
43 | char *name; | 50 | char *name; |
44 | unsigned long default_rate; | 51 | unsigned long default_rate; |
@@ -84,6 +91,30 @@ static int gp10b_tegra_get_clocks(struct platform_device *pdev) | |||
84 | return 0; | 91 | return 0; |
85 | } | 92 | } |
86 | 93 | ||
94 | static void gp10b_tegra_scale_init(struct platform_device *pdev) | ||
95 | { | ||
96 | struct gk20a_platform *platform = gk20a_get_platform(pdev); | ||
97 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
98 | struct tegra_bwmgr_client *bwmgr_handle; | ||
99 | |||
100 | bwmgr_handle = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_GPU); | ||
101 | if (!bwmgr_handle) | ||
102 | return; | ||
103 | |||
104 | profile->private_data = (void *)bwmgr_handle; | ||
105 | } | ||
106 | |||
107 | static void gp10b_tegra_scale_exit(struct platform_device *pdev) | ||
108 | { | ||
109 | struct gk20a_platform *platform = gk20a_get_platform(pdev); | ||
110 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
111 | |||
112 | if (profile) | ||
113 | tegra_bwmgr_unregister( | ||
114 | (struct tegra_bwmgr_client *)profile->private_data); | ||
115 | } | ||
116 | |||
117 | |||
87 | static int gp10b_tegra_probe(struct platform_device *pdev) | 118 | static int gp10b_tegra_probe(struct platform_device *pdev) |
88 | { | 119 | { |
89 | struct gk20a_platform *platform = gk20a_get_platform(pdev); | 120 | struct gk20a_platform *platform = gk20a_get_platform(pdev); |
@@ -145,6 +176,9 @@ static int gp10b_tegra_late_probe(struct platform_device *pdev) | |||
145 | nvhost_register_client_domain(dev_to_genpd(&pdev->dev)); | 176 | nvhost_register_client_domain(dev_to_genpd(&pdev->dev)); |
146 | /*Create GP10B specific sysfs*/ | 177 | /*Create GP10B specific sysfs*/ |
147 | gp10b_create_sysfs(pdev); | 178 | gp10b_create_sysfs(pdev); |
179 | |||
180 | /* Initialise tegra specific scaling quirks */ | ||
181 | gp10b_tegra_scale_init(pdev); | ||
148 | return 0; | 182 | return 0; |
149 | } | 183 | } |
150 | 184 | ||
@@ -155,6 +189,10 @@ static int gp10b_tegra_remove(struct platform_device *pdev) | |||
155 | gr_gp10b_remove_sysfs(&pdev->dev); | 189 | gr_gp10b_remove_sysfs(&pdev->dev); |
156 | /*Remove GP10B specific sysfs*/ | 190 | /*Remove GP10B specific sysfs*/ |
157 | gp10b_remove_sysfs(&pdev->dev); | 191 | gp10b_remove_sysfs(&pdev->dev); |
192 | |||
193 | /* deinitialise tegra specific scaling quirks */ | ||
194 | gp10b_tegra_scale_exit(pdev); | ||
195 | |||
158 | return 0; | 196 | return 0; |
159 | 197 | ||
160 | } | 198 | } |
@@ -240,7 +278,6 @@ static void gp10b_tegra_prescale(struct platform_device *pdev) | |||
240 | gk20a_dbg_fn(""); | 278 | gk20a_dbg_fn(""); |
241 | 279 | ||
242 | gk20a_pmu_load_norm(g, &avg); | 280 | gk20a_pmu_load_norm(g, &avg); |
243 | /* TBD - Notify EDP about changed constrains */ | ||
244 | 281 | ||
245 | gk20a_dbg_fn("done"); | 282 | gk20a_dbg_fn("done"); |
246 | } | 283 | } |
@@ -248,8 +285,23 @@ static void gp10b_tegra_prescale(struct platform_device *pdev) | |||
248 | static void gp10b_tegra_postscale(struct platform_device *pdev, | 285 | static void gp10b_tegra_postscale(struct platform_device *pdev, |
249 | unsigned long freq) | 286 | unsigned long freq) |
250 | { | 287 | { |
251 | /* TBD - notify EMC about frequency change */ | 288 | struct gk20a_platform *platform = gk20a_get_platform(pdev); |
289 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
290 | struct gk20a *g = get_gk20a(pdev); | ||
291 | unsigned long emc_rate; | ||
292 | |||
252 | gk20a_dbg_fn(""); | 293 | gk20a_dbg_fn(""); |
294 | if (profile) { | ||
295 | emc_rate = (freq * EMC_BW_RATIO * g->emc3d_ratio) / 1000; | ||
296 | |||
297 | if (emc_rate > tegra_bwmgr_get_max_emc_rate()) | ||
298 | emc_rate = tegra_bwmgr_get_max_emc_rate(); | ||
299 | |||
300 | tegra_bwmgr_set_emc( | ||
301 | (struct tegra_bwmgr_client *)profile->private_data, | ||
302 | emc_rate, TEGRA_BWMGR_SET_EMC_FLOOR); | ||
303 | } | ||
304 | gk20a_dbg_fn("done"); | ||
253 | } | 305 | } |
254 | 306 | ||
255 | static unsigned long gp10b_get_clk_rate(struct platform_device *dev) | 307 | static unsigned long gp10b_get_clk_rate(struct platform_device *dev) |