diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 1158 |
1 files changed, 0 insertions, 1158 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c deleted file mode 100644 index 225b98e4..00000000 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ /dev/null | |||
@@ -1,1158 +0,0 @@ | |||
1 | /* | ||
2 | * GK20A Tegra Platform Interface | ||
3 | * | ||
4 | * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
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, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/version.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/nvhost.h> | ||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/platform_data/tegra_edp.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <uapi/linux/nvgpu.h> | ||
23 | #include <linux/dma-buf.h> | ||
24 | #include <linux/nvmap.h> | ||
25 | #include <linux/reset.h> | ||
26 | #include <linux/tegra_soctherm.h> | ||
27 | #include <linux/platform/tegra/clock.h> | ||
28 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) | ||
29 | #include <linux/platform/tegra/dvfs.h> | ||
30 | #endif | ||
31 | #include <linux/platform/tegra/common.h> | ||
32 | #include <linux/platform/tegra/mc.h> | ||
33 | #include <linux/clk/tegra.h> | ||
34 | #if defined(CONFIG_COMMON_CLK) | ||
35 | #include <soc/tegra/tegra-dvfs.h> | ||
36 | #endif | ||
37 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) | ||
38 | #include <soc/tegra/fuse.h> | ||
39 | #endif | ||
40 | #ifdef CONFIG_TEGRA_BWMGR | ||
41 | #include <linux/platform/tegra/emc_bwmgr.h> | ||
42 | #endif | ||
43 | |||
44 | #include <linux/platform/tegra/tegra_emc.h> | ||
45 | |||
46 | #include "gk20a.h" | ||
47 | #include "hal_gk20a.h" | ||
48 | #include "platform_gk20a.h" | ||
49 | #include "gk20a_scale.h" | ||
50 | #include "gm20b/clk_gm20b.h" | ||
51 | |||
52 | #define TEGRA_GK20A_BW_PER_FREQ 32 | ||
53 | #define TEGRA_GM20B_BW_PER_FREQ 64 | ||
54 | #define TEGRA_DDR3_BW_PER_FREQ 16 | ||
55 | #define TEGRA_DDR4_BW_PER_FREQ 16 | ||
56 | #define MC_CLIENT_GPU 34 | ||
57 | #define PMC_GPU_RG_CNTRL_0 0x2d4 | ||
58 | |||
59 | #ifdef CONFIG_COMMON_CLK | ||
60 | #define GPU_RAIL_NAME "vdd-gpu" | ||
61 | #else | ||
62 | #define GPU_RAIL_NAME "vdd_gpu" | ||
63 | #endif | ||
64 | |||
65 | extern struct device tegra_vpr_dev; | ||
66 | |||
67 | #ifdef CONFIG_TEGRA_BWMGR | ||
68 | struct gk20a_emc_params { | ||
69 | unsigned long bw_ratio; | ||
70 | unsigned long freq_last_set; | ||
71 | struct tegra_bwmgr_client *bwmgr_cl; | ||
72 | }; | ||
73 | #else | ||
74 | struct gk20a_emc_params { | ||
75 | unsigned long bw_ratio; | ||
76 | unsigned long freq_last_set; | ||
77 | }; | ||
78 | #endif | ||
79 | |||
80 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); | ||
81 | static inline u32 __maybe_unused pmc_read(unsigned long reg) | ||
82 | { | ||
83 | return readl(pmc + reg); | ||
84 | } | ||
85 | |||
86 | static inline void __maybe_unused pmc_write(u32 val, unsigned long reg) | ||
87 | { | ||
88 | writel_relaxed(val, pmc + reg); | ||
89 | } | ||
90 | #define MHZ_TO_HZ(x) ((x) * 1000000) | ||
91 | #define HZ_TO_MHZ(x) ((x) / 1000000) | ||
92 | |||
93 | static void gk20a_tegra_secure_page_destroy(struct device *dev, | ||
94 | struct secure_page_buffer *secure_buffer) | ||
95 | { | ||
96 | dma_free_attrs(&tegra_vpr_dev, secure_buffer->size, | ||
97 | (void *)(uintptr_t)secure_buffer->iova, | ||
98 | secure_buffer->iova, &secure_buffer->attrs); | ||
99 | } | ||
100 | |||
101 | int gk20a_tegra_secure_page_alloc(struct device *dev) | ||
102 | { | ||
103 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
104 | struct secure_page_buffer *secure_buffer = &platform->secure_buffer; | ||
105 | DEFINE_DMA_ATTRS(attrs); | ||
106 | dma_addr_t iova; | ||
107 | size_t size = PAGE_SIZE; | ||
108 | |||
109 | if (platform->is_fmodel) | ||
110 | return -EINVAL; | ||
111 | |||
112 | (void)dma_alloc_attrs(&tegra_vpr_dev, size, &iova, | ||
113 | DMA_MEMORY_NOMAP, &attrs); | ||
114 | if (dma_mapping_error(&tegra_vpr_dev, iova)) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | secure_buffer->size = size; | ||
118 | secure_buffer->iova = iova; | ||
119 | secure_buffer->attrs = attrs; | ||
120 | secure_buffer->destroy = gk20a_tegra_secure_page_destroy; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static void gk20a_tegra_secure_destroy(struct gk20a *g, | ||
126 | struct gr_ctx_buffer_desc *desc) | ||
127 | { | ||
128 | DEFINE_DMA_ATTRS(attrs); | ||
129 | |||
130 | if (desc->mem.sgt) { | ||
131 | phys_addr_t pa = sg_phys(desc->mem.sgt->sgl); | ||
132 | dma_free_attrs(&tegra_vpr_dev, desc->mem.size, | ||
133 | (void *)(uintptr_t)pa, | ||
134 | pa, &attrs); | ||
135 | gk20a_free_sgtable(&desc->mem.sgt); | ||
136 | desc->mem.sgt = NULL; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | int gk20a_tegra_secure_alloc(struct device *dev, | ||
141 | struct gr_ctx_buffer_desc *desc, | ||
142 | size_t size) | ||
143 | { | ||
144 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
145 | DEFINE_DMA_ATTRS(attrs); | ||
146 | dma_addr_t iova; | ||
147 | struct sg_table *sgt; | ||
148 | struct page *page; | ||
149 | int err = 0; | ||
150 | |||
151 | if (!platform->secure_alloc_ready) | ||
152 | return -EINVAL; | ||
153 | |||
154 | (void)dma_alloc_attrs(&tegra_vpr_dev, size, &iova, | ||
155 | DMA_MEMORY_NOMAP, &attrs); | ||
156 | if (dma_mapping_error(&tegra_vpr_dev, iova)) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); | ||
160 | if (!sgt) { | ||
161 | gk20a_err(dev, "failed to allocate memory\n"); | ||
162 | goto fail; | ||
163 | } | ||
164 | err = sg_alloc_table(sgt, 1, GFP_KERNEL); | ||
165 | if (err) { | ||
166 | gk20a_err(dev, "failed to allocate sg_table\n"); | ||
167 | goto fail_sgt; | ||
168 | } | ||
169 | page = phys_to_page(iova); | ||
170 | sg_set_page(sgt->sgl, page, size, 0); | ||
171 | /* This bypasses SMMU for VPR during gmmu_map. */ | ||
172 | sg_dma_address(sgt->sgl) = 0; | ||
173 | |||
174 | desc->destroy = gk20a_tegra_secure_destroy; | ||
175 | |||
176 | desc->mem.sgt = sgt; | ||
177 | desc->mem.size = size; | ||
178 | desc->mem.aperture = APERTURE_SYSMEM; | ||
179 | |||
180 | return err; | ||
181 | |||
182 | fail_sgt: | ||
183 | kfree(sgt); | ||
184 | fail: | ||
185 | dma_free_attrs(&tegra_vpr_dev, desc->mem.size, | ||
186 | (void *)(uintptr_t)iova, iova, &attrs); | ||
187 | return err; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * gk20a_tegra_get_emc_rate() | ||
192 | * | ||
193 | * This function returns the minimum emc clock based on gpu frequency | ||
194 | */ | ||
195 | |||
196 | static unsigned long gk20a_tegra_get_emc_rate(struct gk20a *g, | ||
197 | struct gk20a_emc_params *emc_params) | ||
198 | { | ||
199 | unsigned long gpu_freq, gpu_fmax_at_vmin; | ||
200 | unsigned long emc_rate, emc_scale; | ||
201 | |||
202 | gpu_freq = clk_get_rate(g->clk.tegra_clk); | ||
203 | gpu_fmax_at_vmin = tegra_dvfs_get_fmax_at_vmin_safe_t( | ||
204 | clk_get_parent(g->clk.tegra_clk)); | ||
205 | |||
206 | /* When scaling emc, account for the gpu load when the | ||
207 | * gpu frequency is less than or equal to fmax@vmin. */ | ||
208 | if (gpu_freq <= gpu_fmax_at_vmin) | ||
209 | emc_scale = min(g->pmu.load_avg, g->emc3d_ratio); | ||
210 | else | ||
211 | emc_scale = g->emc3d_ratio; | ||
212 | |||
213 | emc_rate = | ||
214 | (HZ_TO_MHZ(gpu_freq) * emc_params->bw_ratio * emc_scale) / 1000; | ||
215 | |||
216 | return MHZ_TO_HZ(emc_rate); | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * gk20a_tegra_postscale(profile, freq) | ||
221 | * | ||
222 | * This function sets emc frequency based on current gpu frequency | ||
223 | */ | ||
224 | |||
225 | static void gk20a_tegra_postscale(struct device *dev, | ||
226 | unsigned long freq) | ||
227 | { | ||
228 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
229 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
230 | struct gk20a_emc_params *emc_params = profile->private_data; | ||
231 | struct gk20a *g = get_gk20a(dev); | ||
232 | struct clk *emc_clk = platform->clk[2]; | ||
233 | enum tegra_chipid chip_id = tegra_get_chip_id(); | ||
234 | unsigned long emc_target; | ||
235 | unsigned long emc_freq_lower, emc_freq_upper, emc_freq_rounded; | ||
236 | |||
237 | emc_target = gk20a_tegra_get_emc_rate(g, emc_params); | ||
238 | |||
239 | switch (chip_id) { | ||
240 | case TEGRA124: | ||
241 | case TEGRA132: | ||
242 | /* T124 and T132 don't apply any rounding. The resulting | ||
243 | * emc frequency gets implicitly rounded up after issuing | ||
244 | * the clock_set_request. | ||
245 | * So explicitly round up the emc target here to achieve | ||
246 | * the same outcome. */ | ||
247 | emc_freq_rounded = | ||
248 | tegra_emc_round_rate_updown(emc_target, true); | ||
249 | break; | ||
250 | |||
251 | case TEGRA210: | ||
252 | emc_freq_lower = (unsigned long) | ||
253 | tegra_emc_round_rate_updown(emc_target, false); | ||
254 | emc_freq_upper = (unsigned long) | ||
255 | tegra_emc_round_rate_updown(emc_target, true); | ||
256 | |||
257 | /* round to the nearest frequency step */ | ||
258 | if (emc_target < (emc_freq_lower + emc_freq_upper) / 2) | ||
259 | emc_freq_rounded = emc_freq_lower; | ||
260 | else | ||
261 | emc_freq_rounded = emc_freq_upper; | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | /* a proper rounding function needs to be implemented | ||
266 | * for emc in t18x */ | ||
267 | emc_freq_rounded = clk_round_rate(emc_clk, emc_target); | ||
268 | break; | ||
269 | } | ||
270 | |||
271 | /* only change the emc clock if new rounded frequency is different | ||
272 | * from previously set emc rate */ | ||
273 | if (emc_freq_rounded != emc_params->freq_last_set) { | ||
274 | clk_set_rate(emc_clk, emc_freq_rounded); | ||
275 | emc_params->freq_last_set = emc_freq_rounded; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * gk20a_tegra_prescale(profile, freq) | ||
281 | * | ||
282 | * This function informs EDP about changed constraints. | ||
283 | */ | ||
284 | |||
285 | static void gk20a_tegra_prescale(struct device *dev) | ||
286 | { | ||
287 | struct gk20a *g = get_gk20a(dev); | ||
288 | u32 avg = 0; | ||
289 | |||
290 | gk20a_pmu_load_norm(g, &avg); | ||
291 | tegra_edp_notify_gpu_load(avg, clk_get_rate(g->clk.tegra_clk)); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * gk20a_tegra_calibrate_emc() | ||
296 | * | ||
297 | */ | ||
298 | |||
299 | static void gk20a_tegra_calibrate_emc(struct device *dev, | ||
300 | struct gk20a_emc_params *emc_params) | ||
301 | { | ||
302 | enum tegra_chipid cid = tegra_get_chip_id(); | ||
303 | long gpu_bw, emc_bw; | ||
304 | |||
305 | /* store gpu bw based on soc */ | ||
306 | switch (cid) { | ||
307 | case TEGRA210: | ||
308 | gpu_bw = TEGRA_GM20B_BW_PER_FREQ; | ||
309 | break; | ||
310 | case TEGRA124: | ||
311 | case TEGRA132: | ||
312 | gpu_bw = TEGRA_GK20A_BW_PER_FREQ; | ||
313 | break; | ||
314 | default: | ||
315 | gpu_bw = 0; | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | /* TODO detect DDR type. | ||
320 | * Okay for now since DDR3 and DDR4 have the same BW ratio */ | ||
321 | emc_bw = TEGRA_DDR3_BW_PER_FREQ; | ||
322 | |||
323 | /* Calculate the bandwidth ratio of gpu_freq <-> emc_freq | ||
324 | * NOTE the ratio must come out as an integer */ | ||
325 | emc_params->bw_ratio = (gpu_bw / emc_bw); | ||
326 | } | ||
327 | |||
328 | #ifdef CONFIG_TEGRA_BWMGR | ||
329 | void gm20b_bwmgr_set_rate(struct gk20a_platform *platform, bool enb) | ||
330 | { | ||
331 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
332 | struct gk20a_emc_params *params; | ||
333 | unsigned long rate; | ||
334 | |||
335 | if (!profile || !profile->private_data) | ||
336 | return; | ||
337 | |||
338 | params = (struct gk20a_emc_params *)profile->private_data; | ||
339 | rate = (enb) ? params->freq_last_set : 0; | ||
340 | tegra_bwmgr_set_emc(params->bwmgr_cl, rate, TEGRA_BWMGR_SET_EMC_FLOOR); | ||
341 | } | ||
342 | |||
343 | static void gm20b_tegra_postscale(struct device *dev, unsigned long freq) | ||
344 | { | ||
345 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
346 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
347 | struct gk20a_emc_params *emc_params; | ||
348 | unsigned long emc_rate; | ||
349 | |||
350 | if (!profile) | ||
351 | return; | ||
352 | |||
353 | emc_params = profile->private_data; | ||
354 | emc_rate = gk20a_tegra_get_emc_rate(get_gk20a(dev), emc_params); | ||
355 | |||
356 | if (emc_rate > tegra_bwmgr_get_max_emc_rate()) | ||
357 | emc_rate = tegra_bwmgr_get_max_emc_rate(); | ||
358 | |||
359 | emc_params->freq_last_set = emc_rate; | ||
360 | nvgpu_mutex_acquire(&platform->railgate_lock); | ||
361 | if (platform->is_railgated && !platform->is_railgated(dev)) | ||
362 | goto done; | ||
363 | |||
364 | tegra_bwmgr_set_emc(emc_params->bwmgr_cl, emc_rate, | ||
365 | TEGRA_BWMGR_SET_EMC_FLOOR); | ||
366 | |||
367 | done: | ||
368 | nvgpu_mutex_release(&platform->railgate_lock); | ||
369 | } | ||
370 | |||
371 | #endif | ||
372 | |||
373 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
374 | /* | ||
375 | * gk20a_tegra_railgate() | ||
376 | * | ||
377 | * Gate (disable) gk20a power rail | ||
378 | */ | ||
379 | |||
380 | static int gk20a_tegra_railgate(struct device *dev) | ||
381 | { | ||
382 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
383 | int ret = 0; | ||
384 | |||
385 | if (platform->is_fmodel || | ||
386 | !tegra_dvfs_is_rail_up(platform->gpu_rail)) | ||
387 | return 0; | ||
388 | |||
389 | tegra_mc_flush(MC_CLIENT_GPU); | ||
390 | |||
391 | udelay(10); | ||
392 | |||
393 | /* enable clamp */ | ||
394 | pmc_write(0x1, PMC_GPU_RG_CNTRL_0); | ||
395 | pmc_read(PMC_GPU_RG_CNTRL_0); | ||
396 | |||
397 | udelay(10); | ||
398 | |||
399 | platform->reset_assert(dev); | ||
400 | |||
401 | udelay(10); | ||
402 | |||
403 | /* | ||
404 | * GPCPLL is already disabled before entering this function; reference | ||
405 | * clocks are enabled until now - disable them just before rail gating | ||
406 | */ | ||
407 | clk_disable(platform->clk[0]); | ||
408 | clk_disable(platform->clk[1]); | ||
409 | |||
410 | udelay(10); | ||
411 | |||
412 | if (tegra_dvfs_is_rail_up(platform->gpu_rail)) { | ||
413 | ret = tegra_dvfs_rail_power_down(platform->gpu_rail); | ||
414 | if (ret) | ||
415 | goto err_power_off; | ||
416 | } else | ||
417 | pr_info("No GPU regulator?\n"); | ||
418 | |||
419 | return 0; | ||
420 | |||
421 | err_power_off: | ||
422 | gk20a_err(dev, "Could not railgate GPU"); | ||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | |||
427 | /* | ||
428 | * gk20a_tegra_unrailgate() | ||
429 | * | ||
430 | * Ungate (enable) gk20a power rail | ||
431 | */ | ||
432 | |||
433 | static int gk20a_tegra_unrailgate(struct device *dev) | ||
434 | { | ||
435 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
436 | int ret = 0; | ||
437 | bool first = false; | ||
438 | |||
439 | if (platform->is_fmodel) | ||
440 | return 0; | ||
441 | |||
442 | if (!platform->gpu_rail) { | ||
443 | platform->gpu_rail = tegra_dvfs_get_rail_by_name("vdd_gpu"); | ||
444 | if (IS_ERR_OR_NULL(platform->gpu_rail)) { | ||
445 | WARN(1, "No GPU regulator?\n"); | ||
446 | return -EINVAL; | ||
447 | } | ||
448 | first = true; | ||
449 | } | ||
450 | |||
451 | ret = tegra_dvfs_rail_power_up(platform->gpu_rail); | ||
452 | if (ret) | ||
453 | return ret; | ||
454 | |||
455 | if (!first) { | ||
456 | ret = clk_enable(platform->clk[0]); | ||
457 | if (ret) { | ||
458 | gk20a_err(dev, "could not turn on gpu pll"); | ||
459 | goto err_clk_on; | ||
460 | } | ||
461 | ret = clk_enable(platform->clk[1]); | ||
462 | if (ret) { | ||
463 | gk20a_err(dev, "could not turn on pwr clock"); | ||
464 | goto err_clk_on; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | udelay(10); | ||
469 | |||
470 | platform->reset_assert(dev); | ||
471 | |||
472 | udelay(10); | ||
473 | |||
474 | pmc_write(0, PMC_GPU_RG_CNTRL_0); | ||
475 | pmc_read(PMC_GPU_RG_CNTRL_0); | ||
476 | |||
477 | udelay(10); | ||
478 | |||
479 | platform->reset_deassert(dev); | ||
480 | |||
481 | /* Flush MC after boot/railgate/SC7 */ | ||
482 | tegra_mc_flush(MC_CLIENT_GPU); | ||
483 | |||
484 | udelay(10); | ||
485 | |||
486 | tegra_mc_flush_done(MC_CLIENT_GPU); | ||
487 | |||
488 | udelay(10); | ||
489 | |||
490 | return 0; | ||
491 | |||
492 | err_clk_on: | ||
493 | tegra_dvfs_rail_power_down(platform->gpu_rail); | ||
494 | |||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | #endif | ||
499 | |||
500 | |||
501 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_TEGRA_DVFS) | ||
502 | /* | ||
503 | * gk20a_tegra_is_railgated() | ||
504 | * | ||
505 | * Check status of gk20a power rail | ||
506 | */ | ||
507 | |||
508 | static bool gk20a_tegra_is_railgated(struct device *dev) | ||
509 | { | ||
510 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
511 | bool ret = false; | ||
512 | |||
513 | if (!platform->is_fmodel) | ||
514 | ret = !tegra_dvfs_is_rail_up(platform->gpu_rail); | ||
515 | |||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * gm20b_tegra_railgate() | ||
521 | * | ||
522 | * Gate (disable) gm20b power rail | ||
523 | */ | ||
524 | |||
525 | static int gm20b_tegra_railgate(struct device *dev) | ||
526 | { | ||
527 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
528 | int ret = 0; | ||
529 | |||
530 | if (platform->is_fmodel || | ||
531 | !tegra_dvfs_is_rail_up(platform->gpu_rail)) | ||
532 | return 0; | ||
533 | |||
534 | tegra_mc_flush(MC_CLIENT_GPU); | ||
535 | |||
536 | udelay(10); | ||
537 | |||
538 | /* enable clamp */ | ||
539 | pmc_write(0x1, PMC_GPU_RG_CNTRL_0); | ||
540 | pmc_read(PMC_GPU_RG_CNTRL_0); | ||
541 | |||
542 | udelay(10); | ||
543 | |||
544 | platform->reset_assert(dev); | ||
545 | |||
546 | udelay(10); | ||
547 | |||
548 | /* | ||
549 | * GPCPLL is already disabled before entering this function; reference | ||
550 | * clocks are enabled until now - disable them just before rail gating | ||
551 | */ | ||
552 | clk_disable_unprepare(platform->clk_reset); | ||
553 | clk_disable_unprepare(platform->clk[0]); | ||
554 | clk_disable_unprepare(platform->clk[1]); | ||
555 | if (platform->clk[3]) | ||
556 | clk_disable_unprepare(platform->clk[3]); | ||
557 | |||
558 | udelay(10); | ||
559 | |||
560 | tegra_soctherm_gpu_tsens_invalidate(1); | ||
561 | |||
562 | if (tegra_dvfs_is_rail_up(platform->gpu_rail)) { | ||
563 | ret = tegra_dvfs_rail_power_down(platform->gpu_rail); | ||
564 | if (ret) | ||
565 | goto err_power_off; | ||
566 | } else | ||
567 | pr_info("No GPU regulator?\n"); | ||
568 | |||
569 | #ifdef CONFIG_TEGRA_BWMGR | ||
570 | gm20b_bwmgr_set_rate(platform, false); | ||
571 | #endif | ||
572 | |||
573 | return 0; | ||
574 | |||
575 | err_power_off: | ||
576 | gk20a_err(dev, "Could not railgate GPU"); | ||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | |||
581 | /* | ||
582 | * gm20b_tegra_unrailgate() | ||
583 | * | ||
584 | * Ungate (enable) gm20b power rail | ||
585 | */ | ||
586 | |||
587 | static int gm20b_tegra_unrailgate(struct device *dev) | ||
588 | { | ||
589 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
590 | int ret = 0; | ||
591 | bool first = false; | ||
592 | |||
593 | if (platform->is_fmodel) | ||
594 | return 0; | ||
595 | |||
596 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
597 | if (!platform->gpu_rail) { | ||
598 | platform->gpu_rail = tegra_dvfs_get_rail_by_name(GPU_RAIL_NAME); | ||
599 | if (IS_ERR_OR_NULL(platform->gpu_rail)) { | ||
600 | WARN(1, "No GPU regulator?\n"); | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | first = true; | ||
604 | } | ||
605 | #endif | ||
606 | |||
607 | ret = tegra_dvfs_rail_power_up(platform->gpu_rail); | ||
608 | if (ret) | ||
609 | return ret; | ||
610 | |||
611 | #ifdef CONFIG_TEGRA_BWMGR | ||
612 | gm20b_bwmgr_set_rate(platform, true); | ||
613 | #endif | ||
614 | |||
615 | tegra_soctherm_gpu_tsens_invalidate(0); | ||
616 | |||
617 | if (!platform->clk_reset) { | ||
618 | platform->clk_reset = clk_get(dev, "gpu_gate"); | ||
619 | if (IS_ERR(platform->clk_reset)) { | ||
620 | gk20a_err(dev, "fail to get gpu reset clk\n"); | ||
621 | goto err_clk_on; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | if (!first) { | ||
626 | ret = clk_prepare_enable(platform->clk_reset); | ||
627 | if (ret) { | ||
628 | gk20a_err(dev, "could not turn on gpu_gate"); | ||
629 | goto err_clk_on; | ||
630 | } | ||
631 | |||
632 | ret = clk_prepare_enable(platform->clk[0]); | ||
633 | if (ret) { | ||
634 | gk20a_err(dev, "could not turn on gpu pll"); | ||
635 | goto err_clk_on; | ||
636 | } | ||
637 | ret = clk_prepare_enable(platform->clk[1]); | ||
638 | if (ret) { | ||
639 | gk20a_err(dev, "could not turn on pwr clock"); | ||
640 | goto err_clk_on; | ||
641 | } | ||
642 | |||
643 | if (platform->clk[3]) { | ||
644 | ret = clk_prepare_enable(platform->clk[3]); | ||
645 | if (ret) { | ||
646 | gk20a_err(dev, "could not turn on fuse clock"); | ||
647 | goto err_clk_on; | ||
648 | } | ||
649 | } | ||
650 | } | ||
651 | |||
652 | udelay(10); | ||
653 | |||
654 | platform->reset_assert(dev); | ||
655 | |||
656 | udelay(10); | ||
657 | |||
658 | pmc_write(0, PMC_GPU_RG_CNTRL_0); | ||
659 | pmc_read(PMC_GPU_RG_CNTRL_0); | ||
660 | |||
661 | udelay(10); | ||
662 | |||
663 | clk_disable(platform->clk_reset); | ||
664 | platform->reset_deassert(dev); | ||
665 | clk_enable(platform->clk_reset); | ||
666 | |||
667 | /* Flush MC after boot/railgate/SC7 */ | ||
668 | tegra_mc_flush(MC_CLIENT_GPU); | ||
669 | |||
670 | udelay(10); | ||
671 | |||
672 | tegra_mc_flush_done(MC_CLIENT_GPU); | ||
673 | |||
674 | udelay(10); | ||
675 | |||
676 | return 0; | ||
677 | |||
678 | err_clk_on: | ||
679 | tegra_dvfs_rail_power_down(platform->gpu_rail); | ||
680 | |||
681 | return ret; | ||
682 | } | ||
683 | #endif | ||
684 | |||
685 | |||
686 | static struct { | ||
687 | char *name; | ||
688 | unsigned long default_rate; | ||
689 | } tegra_gk20a_clocks[] = { | ||
690 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
691 | {"PLLG_ref", UINT_MAX}, | ||
692 | {"pwr", 204000000}, | ||
693 | {"emc", UINT_MAX}, | ||
694 | #elif defined(CONFIG_COMMON_CLK) | ||
695 | {"gpu_ref", UINT_MAX}, | ||
696 | {"pll_p_out5", 204000000}, | ||
697 | {"emc", UINT_MAX}, | ||
698 | {"fuse", UINT_MAX}, | ||
699 | #endif | ||
700 | }; | ||
701 | |||
702 | |||
703 | |||
704 | /* | ||
705 | * gk20a_tegra_get_clocks() | ||
706 | * | ||
707 | * This function finds clocks in tegra platform and populates | ||
708 | * the clock information to gk20a platform data. | ||
709 | */ | ||
710 | |||
711 | static int gk20a_tegra_get_clocks(struct device *dev) | ||
712 | { | ||
713 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
714 | char devname[16]; | ||
715 | unsigned int i; | ||
716 | int ret = 0; | ||
717 | |||
718 | BUG_ON(GK20A_CLKS_MAX < ARRAY_SIZE(tegra_gk20a_clocks)); | ||
719 | |||
720 | snprintf(devname, sizeof(devname), "tegra_%s", dev_name(dev)); | ||
721 | |||
722 | platform->num_clks = 0; | ||
723 | for (i = 0; i < ARRAY_SIZE(tegra_gk20a_clocks); i++) { | ||
724 | long rate = tegra_gk20a_clocks[i].default_rate; | ||
725 | struct clk *c; | ||
726 | |||
727 | c = clk_get_sys(devname, tegra_gk20a_clocks[i].name); | ||
728 | if (IS_ERR(c)) { | ||
729 | ret = PTR_ERR(c); | ||
730 | goto err_get_clock; | ||
731 | } | ||
732 | rate = clk_round_rate(c, rate); | ||
733 | clk_set_rate(c, rate); | ||
734 | platform->clk[i] = c; | ||
735 | } | ||
736 | platform->num_clks = i; | ||
737 | |||
738 | return 0; | ||
739 | |||
740 | err_get_clock: | ||
741 | |||
742 | while (i--) | ||
743 | clk_put(platform->clk[i]); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static int gk20a_tegra_reset_assert(struct device *dev) | ||
748 | { | ||
749 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
750 | |||
751 | if (!platform->clk_reset) | ||
752 | platform->clk_reset = platform->clk[0]; | ||
753 | |||
754 | tegra_periph_reset_assert(platform->clk_reset); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static int gk20a_tegra_reset_deassert(struct device *dev) | ||
760 | { | ||
761 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
762 | |||
763 | if (!platform->clk_reset) | ||
764 | return -EINVAL; | ||
765 | |||
766 | tegra_periph_reset_deassert(platform->clk_reset); | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | #if defined(CONFIG_RESET_CONTROLLER) && defined(CONFIG_COMMON_CLK) | ||
772 | static int gm20b_tegra_reset_assert(struct device *dev) | ||
773 | { | ||
774 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
775 | |||
776 | if (!platform->reset_control) { | ||
777 | WARN(1, "Reset control not initialized\n"); | ||
778 | return -ENOSYS; | ||
779 | } | ||
780 | |||
781 | return reset_control_assert(platform->reset_control); | ||
782 | } | ||
783 | |||
784 | static int gm20b_tegra_reset_deassert(struct device *dev) | ||
785 | { | ||
786 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
787 | |||
788 | if (!platform->reset_control) { | ||
789 | WARN(1, "Reset control not initialized\n"); | ||
790 | return -ENOSYS; | ||
791 | } | ||
792 | |||
793 | return reset_control_deassert(platform->reset_control); | ||
794 | } | ||
795 | #endif | ||
796 | |||
797 | static void gk20a_tegra_scale_init(struct device *dev) | ||
798 | { | ||
799 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
800 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
801 | struct gk20a_emc_params *emc_params; | ||
802 | |||
803 | if (!profile) | ||
804 | return; | ||
805 | |||
806 | emc_params = kzalloc(sizeof(*emc_params), GFP_KERNEL); | ||
807 | if (!emc_params) | ||
808 | return; | ||
809 | |||
810 | emc_params->freq_last_set = -1; | ||
811 | gk20a_tegra_calibrate_emc(dev, emc_params); | ||
812 | |||
813 | #ifdef CONFIG_TEGRA_BWMGR | ||
814 | emc_params->bwmgr_cl = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_GPU); | ||
815 | if (!emc_params->bwmgr_cl) { | ||
816 | gk20a_dbg_info("%s Missing GPU BWMGR client\n", __func__); | ||
817 | return; | ||
818 | } | ||
819 | #endif | ||
820 | |||
821 | profile->private_data = emc_params; | ||
822 | } | ||
823 | |||
824 | static void gk20a_tegra_scale_exit(struct device *dev) | ||
825 | { | ||
826 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
827 | struct gk20a_scale_profile *profile = platform->g->scale_profile; | ||
828 | struct gk20a_emc_params *emc_params; | ||
829 | |||
830 | if (!profile) | ||
831 | return; | ||
832 | |||
833 | emc_params = profile->private_data; | ||
834 | #ifdef CONFIG_TEGRA_BWMGR | ||
835 | tegra_bwmgr_unregister(emc_params->bwmgr_cl); | ||
836 | #endif | ||
837 | |||
838 | kfree(profile->private_data); | ||
839 | } | ||
840 | |||
841 | void gk20a_tegra_debug_dump(struct device *dev) | ||
842 | { | ||
843 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
844 | struct gk20a *g = platform->g; | ||
845 | |||
846 | if (g->host1x_dev) | ||
847 | nvhost_debug_dump_device(g->host1x_dev); | ||
848 | } | ||
849 | |||
850 | int gk20a_tegra_busy(struct device *dev) | ||
851 | { | ||
852 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
853 | struct gk20a *g = platform->g; | ||
854 | |||
855 | if (g->host1x_dev) | ||
856 | return nvhost_module_busy_ext(g->host1x_dev); | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | void gk20a_tegra_idle(struct device *dev) | ||
861 | { | ||
862 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
863 | struct gk20a *g = platform->g; | ||
864 | |||
865 | if (g->host1x_dev) | ||
866 | nvhost_module_idle_ext(g->host1x_dev); | ||
867 | } | ||
868 | |||
869 | static int gk20a_tegra_probe(struct device *dev) | ||
870 | { | ||
871 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
872 | struct device_node *np = dev->of_node; | ||
873 | const __be32 *host1x_ptr; | ||
874 | struct platform_device *host1x_pdev = NULL; | ||
875 | bool joint_xpu_rail = false; | ||
876 | int ret; | ||
877 | |||
878 | #ifdef CONFIG_COMMON_CLK | ||
879 | /* DVFS is not guaranteed to be initialized at the time of probe on | ||
880 | * kernels with Common Clock Framework enabled. | ||
881 | */ | ||
882 | if (!platform->gpu_rail) { | ||
883 | platform->gpu_rail = tegra_dvfs_get_rail_by_name(GPU_RAIL_NAME); | ||
884 | if (!platform->gpu_rail) { | ||
885 | gk20a_dbg_info("deferring probe no gpu_rail\n"); | ||
886 | return -EPROBE_DEFER; | ||
887 | } | ||
888 | } | ||
889 | |||
890 | if (!tegra_dvfs_is_rail_ready(platform->gpu_rail)) { | ||
891 | gk20a_dbg_info("deferring probe gpu_rail not ready\n"); | ||
892 | return -EPROBE_DEFER; | ||
893 | } | ||
894 | #endif | ||
895 | |||
896 | host1x_ptr = of_get_property(np, "nvidia,host1x", NULL); | ||
897 | if (host1x_ptr) { | ||
898 | struct device_node *host1x_node = | ||
899 | of_find_node_by_phandle(be32_to_cpup(host1x_ptr)); | ||
900 | |||
901 | host1x_pdev = of_find_device_by_node(host1x_node); | ||
902 | if (!host1x_pdev) { | ||
903 | dev_warn(dev, "host1x device not available"); | ||
904 | return -EPROBE_DEFER; | ||
905 | } | ||
906 | |||
907 | } else { | ||
908 | host1x_pdev = to_platform_device(dev->parent); | ||
909 | dev_warn(dev, "host1x reference not found. assuming host1x to be parent"); | ||
910 | } | ||
911 | |||
912 | platform->g->host1x_dev = host1x_pdev; | ||
913 | |||
914 | #ifdef CONFIG_OF | ||
915 | joint_xpu_rail = of_property_read_bool(of_chosen, | ||
916 | "nvidia,tegra-joint_xpu_rail"); | ||
917 | #endif | ||
918 | |||
919 | if (joint_xpu_rail) { | ||
920 | gk20a_dbg_info("XPU rails are joint\n"); | ||
921 | platform->can_railgate = false; | ||
922 | } | ||
923 | |||
924 | /* WAR for bug 1547668: Disable railgating and scaling irrespective of | ||
925 | * platform data if the rework has not been made. */ | ||
926 | |||
927 | if (tegra_get_chip_id() == TEGRA210) { | ||
928 | np = of_find_node_by_path("/gpu-dvfs-rework"); | ||
929 | if (!(np && of_device_is_available(np))) { | ||
930 | platform->devfreq_governor = ""; | ||
931 | dev_warn(dev, "board does not support scaling"); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | if (tegra_get_chip_id() == TEGRA132) | ||
936 | platform->soc_name = "tegra13x"; | ||
937 | |||
938 | platform->g->mm.vidmem_is_vidmem = platform->vidmem_is_vidmem; | ||
939 | |||
940 | gk20a_tegra_get_clocks(dev); | ||
941 | |||
942 | if (platform->clk_register) { | ||
943 | ret = platform->clk_register(platform->g); | ||
944 | if (ret) | ||
945 | return ret; | ||
946 | } | ||
947 | |||
948 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) | ||
949 | pmc = ioremap(TEGRA_PMC_BASE, 4096); | ||
950 | #endif | ||
951 | |||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | static int gk20a_tegra_late_probe(struct device *dev) | ||
956 | { | ||
957 | /* Initialise tegra specific scaling quirks */ | ||
958 | gk20a_tegra_scale_init(dev); | ||
959 | |||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | static int gk20a_tegra_remove(struct device *dev) | ||
964 | { | ||
965 | /* deinitialise tegra specific scaling quirks */ | ||
966 | gk20a_tegra_scale_exit(dev); | ||
967 | |||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static int gk20a_tegra_suspend(struct device *dev) | ||
972 | { | ||
973 | tegra_edp_notify_gpu_load(0, 0); | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_COMMON_CLK) | ||
978 | static unsigned long gk20a_get_clk_rate(struct device *dev) | ||
979 | { | ||
980 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
981 | struct gk20a *g = platform->g; | ||
982 | |||
983 | return gk20a_clk_get_rate(g); | ||
984 | |||
985 | } | ||
986 | |||
987 | static long gk20a_round_clk_rate(struct device *dev, unsigned long rate) | ||
988 | { | ||
989 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
990 | struct gk20a *g = platform->g; | ||
991 | |||
992 | return gk20a_clk_round_rate(g, rate); | ||
993 | } | ||
994 | |||
995 | static int gk20a_set_clk_rate(struct device *dev, unsigned long rate) | ||
996 | { | ||
997 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
998 | struct gk20a *g = platform->g; | ||
999 | |||
1000 | return gk20a_clk_set_rate(g, rate); | ||
1001 | } | ||
1002 | |||
1003 | static int gk20a_clk_get_freqs(struct device *dev, | ||
1004 | unsigned long **freqs, int *num_freqs) | ||
1005 | { | ||
1006 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
1007 | struct gk20a *g = platform->g; | ||
1008 | |||
1009 | /* make sure the clock is available */ | ||
1010 | if (!gk20a_clk_get(g)) | ||
1011 | return -ENOSYS; | ||
1012 | |||
1013 | return tegra_dvfs_get_freqs(clk_get_parent(g->clk.tegra_clk), | ||
1014 | freqs, num_freqs); | ||
1015 | } | ||
1016 | #endif | ||
1017 | |||
1018 | |||
1019 | struct gk20a_platform gk20a_tegra_platform = { | ||
1020 | .has_syncpoints = true, | ||
1021 | .aggressive_sync_destroy_thresh = 64, | ||
1022 | |||
1023 | /* power management configuration */ | ||
1024 | .railgate_delay = 500, | ||
1025 | .can_railgate = true, | ||
1026 | .can_elpg = true, | ||
1027 | .enable_slcg = true, | ||
1028 | .enable_blcg = true, | ||
1029 | .enable_elcg = true, | ||
1030 | .enable_elpg = true, | ||
1031 | .enable_aelpg = true, | ||
1032 | .ptimer_src_freq = 12000000, | ||
1033 | |||
1034 | .force_reset_in_do_idle = false, | ||
1035 | |||
1036 | .default_big_page_size = SZ_128K, | ||
1037 | |||
1038 | .ch_wdt_timeout_ms = 7000, | ||
1039 | |||
1040 | .probe = gk20a_tegra_probe, | ||
1041 | .late_probe = gk20a_tegra_late_probe, | ||
1042 | .remove = gk20a_tegra_remove, | ||
1043 | |||
1044 | /* power management callbacks */ | ||
1045 | .suspend = gk20a_tegra_suspend, | ||
1046 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
1047 | .railgate = gk20a_tegra_railgate, | ||
1048 | .unrailgate = gk20a_tegra_unrailgate, | ||
1049 | .is_railgated = gk20a_tegra_is_railgated, | ||
1050 | #endif | ||
1051 | |||
1052 | .busy = gk20a_tegra_busy, | ||
1053 | .idle = gk20a_tegra_idle, | ||
1054 | |||
1055 | .reset_assert = gk20a_tegra_reset_assert, | ||
1056 | .reset_deassert = gk20a_tegra_reset_deassert, | ||
1057 | |||
1058 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
1059 | .clk_get_rate = gk20a_get_clk_rate, | ||
1060 | .clk_round_rate = gk20a_round_clk_rate, | ||
1061 | .clk_set_rate = gk20a_set_clk_rate, | ||
1062 | .get_clk_freqs = gk20a_clk_get_freqs, | ||
1063 | #endif | ||
1064 | |||
1065 | /* frequency scaling configuration */ | ||
1066 | .prescale = gk20a_tegra_prescale, | ||
1067 | .postscale = gk20a_tegra_postscale, | ||
1068 | .devfreq_governor = "nvhost_podgov", | ||
1069 | .qos_notify = gk20a_scale_qos_notify, | ||
1070 | |||
1071 | .secure_alloc = gk20a_tegra_secure_alloc, | ||
1072 | .secure_page_alloc = gk20a_tegra_secure_page_alloc, | ||
1073 | .dump_platform_dependencies = gk20a_tegra_debug_dump, | ||
1074 | |||
1075 | .has_ce = true, | ||
1076 | |||
1077 | .soc_name = "tegra12x", | ||
1078 | |||
1079 | .vidmem_is_vidmem = false, | ||
1080 | }; | ||
1081 | |||
1082 | struct gk20a_platform gm20b_tegra_platform = { | ||
1083 | .has_syncpoints = true, | ||
1084 | .aggressive_sync_destroy_thresh = 64, | ||
1085 | |||
1086 | /* power management configuration */ | ||
1087 | .railgate_delay = 500, | ||
1088 | .can_railgate = true, | ||
1089 | .can_elpg = true, | ||
1090 | .enable_slcg = true, | ||
1091 | .enable_blcg = true, | ||
1092 | .enable_elcg = true, | ||
1093 | .enable_elpg = true, | ||
1094 | .enable_aelpg = true, | ||
1095 | .ptimer_src_freq = 19200000, | ||
1096 | |||
1097 | .force_reset_in_do_idle = false, | ||
1098 | |||
1099 | .default_big_page_size = SZ_128K, | ||
1100 | |||
1101 | .ch_wdt_timeout_ms = 5000, | ||
1102 | |||
1103 | .probe = gk20a_tegra_probe, | ||
1104 | .late_probe = gk20a_tegra_late_probe, | ||
1105 | .remove = gk20a_tegra_remove, | ||
1106 | /* power management callbacks */ | ||
1107 | .suspend = gk20a_tegra_suspend, | ||
1108 | |||
1109 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_TEGRA_DVFS) | ||
1110 | .railgate = gm20b_tegra_railgate, | ||
1111 | .unrailgate = gm20b_tegra_unrailgate, | ||
1112 | .is_railgated = gk20a_tegra_is_railgated, | ||
1113 | #endif | ||
1114 | |||
1115 | .busy = gk20a_tegra_busy, | ||
1116 | .idle = gk20a_tegra_idle, | ||
1117 | |||
1118 | #if defined(CONFIG_RESET_CONTROLLER) && defined(CONFIG_COMMON_CLK) | ||
1119 | .reset_assert = gm20b_tegra_reset_assert, | ||
1120 | .reset_deassert = gm20b_tegra_reset_deassert, | ||
1121 | #else | ||
1122 | .reset_assert = gk20a_tegra_reset_assert, | ||
1123 | .reset_deassert = gk20a_tegra_reset_deassert, | ||
1124 | #endif | ||
1125 | |||
1126 | #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_COMMON_CLK) | ||
1127 | .clk_get_rate = gk20a_get_clk_rate, | ||
1128 | .clk_round_rate = gk20a_round_clk_rate, | ||
1129 | .clk_set_rate = gk20a_set_clk_rate, | ||
1130 | .get_clk_freqs = gk20a_clk_get_freqs, | ||
1131 | #endif | ||
1132 | |||
1133 | #ifdef CONFIG_COMMON_CLK | ||
1134 | .clk_register = gm20b_register_gpcclk, | ||
1135 | #endif | ||
1136 | |||
1137 | /* frequency scaling configuration */ | ||
1138 | .prescale = gk20a_tegra_prescale, | ||
1139 | #ifdef CONFIG_TEGRA_BWMGR | ||
1140 | .postscale = gm20b_tegra_postscale, | ||
1141 | #else | ||
1142 | .postscale = gk20a_tegra_postscale, | ||
1143 | #endif | ||
1144 | .devfreq_governor = "nvhost_podgov", | ||
1145 | .qos_notify = gk20a_scale_qos_notify, | ||
1146 | |||
1147 | .secure_alloc = gk20a_tegra_secure_alloc, | ||
1148 | .secure_page_alloc = gk20a_tegra_secure_page_alloc, | ||
1149 | .dump_platform_dependencies = gk20a_tegra_debug_dump, | ||
1150 | |||
1151 | .has_cde = true, | ||
1152 | |||
1153 | .has_ce = true, | ||
1154 | |||
1155 | .soc_name = "tegra21x", | ||
1156 | |||
1157 | .vidmem_is_vidmem = false, | ||
1158 | }; | ||