aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2018-02-01 13:13:56 -0500
committerBen Skeggs <bskeggs@redhat.com>2018-02-02 00:24:08 -0500
commit1bab09acc9b165c5cd87dc46bc983372e103ae5d (patch)
tree464ae445bcd33d13cfbc4f93134a2bc3055dea01 /drivers/gpu
parentb138eca661ccee2b43f8ef3cfd952a5c71c1dc90 (diff)
drm/nouveau: Add support for BLCG on Kepler1
This enables BLCG optimization for kepler1. When using clockgating, nvidia's firmware has a set of registers which are initially programmed by the vbios with various engine delays and other mysterious settings that are safe enough to bring up the GPU. However, the values used by the vbios are more power hungry then they need to be, so the nvidia driver writes it's own more optimized set of BLCG settings before enabling CG_CTRL. This adds support for programming the optimized BLCG values during engine/subdev init, which enables rather significant power savings. This introduces the nvkm_therm_clkgate_init() helper, which we use to program the optimized BLCG settings before enabling clockgating with nvkm_therm_clkgate_enable. As well, this commit shares a lot more code with Fermi since BLCG is mostly the same there as far as we can tell. In the future, it's likely we'll reformat the clkgate_packs for kepler1 so that they share a list of mmio packs with Fermi. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Martin Peres <martin.peres@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c207
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c47
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c58
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h6
14 files changed, 442 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
index 240b19bb4667..9398d9f09339 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
@@ -46,6 +46,16 @@ enum nvkm_therm_attr_type {
46 NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST = 17, 46 NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST = 17,
47}; 47};
48 48
49struct nvkm_therm_clkgate_init {
50 u32 addr;
51 u8 count;
52 u32 data;
53};
54
55struct nvkm_therm_clkgate_pack {
56 const struct nvkm_therm_clkgate_init *init;
57};
58
49struct nvkm_therm { 59struct nvkm_therm {
50 const struct nvkm_therm_func *func; 60 const struct nvkm_therm_func *func;
51 struct nvkm_subdev subdev; 61 struct nvkm_subdev subdev;
@@ -92,6 +102,8 @@ struct nvkm_therm {
92int nvkm_therm_temp_get(struct nvkm_therm *); 102int nvkm_therm_temp_get(struct nvkm_therm *);
93int nvkm_therm_fan_sense(struct nvkm_therm *); 103int nvkm_therm_fan_sense(struct nvkm_therm *);
94int nvkm_therm_cstate(struct nvkm_therm *, int, int); 104int nvkm_therm_cstate(struct nvkm_therm *, int, int);
105void nvkm_therm_clkgate_init(struct nvkm_therm *,
106 const struct nvkm_therm_clkgate_pack *);
95void nvkm_therm_clkgate_enable(struct nvkm_therm *); 107void nvkm_therm_clkgate_enable(struct nvkm_therm *);
96void nvkm_therm_clkgate_fini(struct nvkm_therm *, bool); 108void nvkm_therm_clkgate_fini(struct nvkm_therm *, bool);
97 109
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
index d7c2adb9b543..c8ec3fd97155 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
@@ -137,6 +137,7 @@ struct gf100_gr_func {
137 int (*rops)(struct gf100_gr *); 137 int (*rops)(struct gf100_gr *);
138 int ppc_nr; 138 int ppc_nr;
139 const struct gf100_grctx_func *grctx; 139 const struct gf100_grctx_func *grctx;
140 const struct nvkm_therm_clkgate_pack *clkgate_pack;
140 struct nvkm_sclass sclass[]; 141 struct nvkm_sclass sclass[];
141}; 142};
142 143
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
index 5e82f94c2245..1b52fcb2c49a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
@@ -22,6 +22,7 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24#include "gf100.h" 24#include "gf100.h"
25#include "gk104.h"
25#include "ctxgf100.h" 26#include "ctxgf100.h"
26 27
27#include <nvif/class.h> 28#include <nvif/class.h>
@@ -173,6 +174,208 @@ gk104_gr_pack_mmio[] = {
173 {} 174 {}
174}; 175};
175 176
177const struct nvkm_therm_clkgate_init
178gk104_clkgate_blcg_init_main_0[] = {
179 { 0x4041f0, 1, 0x00004046 },
180 { 0x409890, 1, 0x00000045 },
181 { 0x4098b0, 1, 0x0000007f },
182 {}
183};
184
185const struct nvkm_therm_clkgate_init
186gk104_clkgate_blcg_init_rstr2d_0[] = {
187 { 0x4078c0, 1, 0x00000042 },
188 {}
189};
190
191const struct nvkm_therm_clkgate_init
192gk104_clkgate_blcg_init_unk_0[] = {
193 { 0x406000, 1, 0x00004044 },
194 { 0x405860, 1, 0x00004042 },
195 { 0x40590c, 1, 0x00004042 },
196 {}
197};
198
199const struct nvkm_therm_clkgate_init
200gk104_clkgate_blcg_init_gcc_0[] = {
201 { 0x408040, 1, 0x00004044 },
202 {}
203};
204
205const struct nvkm_therm_clkgate_init
206gk104_clkgate_blcg_init_sked_0[] = {
207 { 0x407000, 1, 0x00004044 },
208 {}
209};
210
211const struct nvkm_therm_clkgate_init
212gk104_clkgate_blcg_init_unk_1[] = {
213 { 0x405bf0, 1, 0x00004044 },
214 {}
215};
216
217const struct nvkm_therm_clkgate_init
218gk104_clkgate_blcg_init_gpc_ctxctl_0[] = {
219 { 0x41a890, 1, 0x00000042 },
220 { 0x41a8b0, 1, 0x0000007f },
221 {}
222};
223
224const struct nvkm_therm_clkgate_init
225gk104_clkgate_blcg_init_gpc_unk_0[] = {
226 { 0x418500, 1, 0x00004042 },
227 { 0x418608, 1, 0x00004042 },
228 { 0x418688, 1, 0x00004042 },
229 { 0x418718, 1, 0x00000042 },
230 {}
231};
232
233const struct nvkm_therm_clkgate_init
234gk104_clkgate_blcg_init_gpc_esetup_0[] = {
235 { 0x418828, 1, 0x00000044 },
236 {}
237};
238
239const struct nvkm_therm_clkgate_init
240gk104_clkgate_blcg_init_gpc_tpbus_0[] = {
241 { 0x418bbc, 1, 0x00004042 },
242 {}
243};
244
245const struct nvkm_therm_clkgate_init
246gk104_clkgate_blcg_init_gpc_zcull_0[] = {
247 { 0x418970, 1, 0x00004042 },
248 {}
249};
250
251const struct nvkm_therm_clkgate_init
252gk104_clkgate_blcg_init_gpc_tpconf_0[] = {
253 { 0x418c70, 1, 0x00004042 },
254 {}
255};
256
257const struct nvkm_therm_clkgate_init
258gk104_clkgate_blcg_init_gpc_unk_1[] = {
259 { 0x418cf0, 1, 0x00004042 },
260 { 0x418d70, 1, 0x00004042 },
261 { 0x418f0c, 1, 0x00004042 },
262 { 0x418e0c, 1, 0x00004042 },
263 {}
264};
265
266const struct nvkm_therm_clkgate_init
267gk104_clkgate_blcg_init_gpc_gcc_0[] = {
268 { 0x419020, 1, 0x00004042 },
269 { 0x419038, 1, 0x00000042 },
270 {}
271};
272
273const struct nvkm_therm_clkgate_init
274gk104_clkgate_blcg_init_gpc_ffb_0[] = {
275 { 0x418898, 1, 0x00000042 },
276 {}
277};
278
279const struct nvkm_therm_clkgate_init
280gk104_clkgate_blcg_init_gpc_tex_0[] = {
281 { 0x419a40, 9, 0x00004042 },
282 { 0x419acc, 1, 0x00004047 },
283 {}
284};
285
286const struct nvkm_therm_clkgate_init
287gk104_clkgate_blcg_init_gpc_poly_0[] = {
288 { 0x419868, 1, 0x00000042 },
289 {}
290};
291
292const struct nvkm_therm_clkgate_init
293gk104_clkgate_blcg_init_gpc_l1c_0[] = {
294 { 0x419ccc, 3, 0x00000042 },
295 {}
296};
297
298const struct nvkm_therm_clkgate_init
299gk104_clkgate_blcg_init_gpc_unk_2[] = {
300 { 0x419c70, 1, 0x00004045 },
301 {}
302};
303
304const struct nvkm_therm_clkgate_init
305gk104_clkgate_blcg_init_gpc_mp_0[] = {
306 { 0x419fd0, 1, 0x00004043 },
307 { 0x419fd8, 1, 0x00004049 },
308 { 0x419fe0, 2, 0x00004042 },
309 { 0x419ff0, 1, 0x00004046 },
310 { 0x419ff8, 1, 0x00004042 },
311 {}
312};
313
314const struct nvkm_therm_clkgate_init
315gk104_clkgate_blcg_init_gpc_ppc_0[] = {
316 { 0x41be28, 1, 0x00000042 },
317 { 0x41bfe8, 1, 0x00004042 },
318 { 0x41bed0, 1, 0x00004042 },
319 {}
320};
321
322const struct nvkm_therm_clkgate_init
323gk104_clkgate_blcg_init_rop_zrop_0[] = {
324 { 0x408810, 2, 0x00004042 },
325 {}
326};
327
328const struct nvkm_therm_clkgate_init
329gk104_clkgate_blcg_init_rop_0[] = {
330 { 0x408a80, 6, 0x00004042 },
331 {}
332};
333
334const struct nvkm_therm_clkgate_init
335gk104_clkgate_blcg_init_rop_crop_0[] = {
336 { 0x4089a8, 1, 0x00004042 },
337 { 0x4089b0, 1, 0x00000042 },
338 { 0x4089b8, 1, 0x00004042 },
339 {}
340};
341
342const struct nvkm_therm_clkgate_init
343gk104_clkgate_blcg_init_pxbar_0[] = {
344 { 0x13c820, 1, 0x0001007f },
345 { 0x13cbe0, 1, 0x00000042 },
346 {}
347};
348
349static const struct nvkm_therm_clkgate_pack
350gk104_clkgate_pack[] = {
351 { gk104_clkgate_blcg_init_main_0 },
352 { gk104_clkgate_blcg_init_rstr2d_0 },
353 { gk104_clkgate_blcg_init_unk_0 },
354 { gk104_clkgate_blcg_init_gcc_0 },
355 { gk104_clkgate_blcg_init_sked_0 },
356 { gk104_clkgate_blcg_init_unk_1 },
357 { gk104_clkgate_blcg_init_gpc_ctxctl_0 },
358 { gk104_clkgate_blcg_init_gpc_unk_0 },
359 { gk104_clkgate_blcg_init_gpc_esetup_0 },
360 { gk104_clkgate_blcg_init_gpc_tpbus_0 },
361 { gk104_clkgate_blcg_init_gpc_zcull_0 },
362 { gk104_clkgate_blcg_init_gpc_tpconf_0 },
363 { gk104_clkgate_blcg_init_gpc_unk_1 },
364 { gk104_clkgate_blcg_init_gpc_gcc_0 },
365 { gk104_clkgate_blcg_init_gpc_ffb_0 },
366 { gk104_clkgate_blcg_init_gpc_tex_0 },
367 { gk104_clkgate_blcg_init_gpc_poly_0 },
368 { gk104_clkgate_blcg_init_gpc_l1c_0 },
369 { gk104_clkgate_blcg_init_gpc_unk_2 },
370 { gk104_clkgate_blcg_init_gpc_mp_0 },
371 { gk104_clkgate_blcg_init_gpc_ppc_0 },
372 { gk104_clkgate_blcg_init_rop_zrop_0 },
373 { gk104_clkgate_blcg_init_rop_0 },
374 { gk104_clkgate_blcg_init_rop_crop_0 },
375 { gk104_clkgate_blcg_init_pxbar_0 },
376 {}
377};
378
176/******************************************************************************* 379/*******************************************************************************
177 * PGRAPH engine/subdev functions 380 * PGRAPH engine/subdev functions
178 ******************************************************************************/ 381 ******************************************************************************/
@@ -214,6 +417,9 @@ gk104_gr_init(struct gf100_gr *gr)
214 gr->func->init_gpc_mmu(gr); 417 gr->func->init_gpc_mmu(gr);
215 418
216 gf100_gr_mmio(gr, gr->func->mmio); 419 gf100_gr_mmio(gr, gr->func->mmio);
420 if (gr->func->clkgate_pack)
421 nvkm_therm_clkgate_init(gr->base.engine.subdev.device->therm,
422 gr->func->clkgate_pack);
217 423
218 nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001); 424 nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001);
219 425
@@ -338,6 +544,7 @@ gk104_gr = {
338 .rops = gf100_gr_rops, 544 .rops = gf100_gr_rops,
339 .ppc_nr = 1, 545 .ppc_nr = 1,
340 .grctx = &gk104_grctx, 546 .grctx = &gk104_grctx,
547 .clkgate_pack = gk104_clkgate_pack,
341 .sclass = { 548 .sclass = {
342 { -1, -1, FERMI_TWOD_A }, 549 { -1, -1, FERMI_TWOD_A },
343 { -1, -1, KEPLER_INLINE_TO_MEMORY_A }, 550 { -1, -1, KEPLER_INLINE_TO_MEMORY_A },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h
new file mode 100644
index 000000000000..a24c177365d1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h
@@ -0,0 +1,55 @@
1/*
2 * Copyright 2018 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Lyude Paul <lyude@redhat.com>
23 */
24#ifndef __GK104_GR_H__
25#define __GK104_GR_H__
26
27#include <subdev/therm.h>
28
29extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_main_0[];
30extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rstr2d_0[];
31extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_unk_0[];
32extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gcc_0[];
33extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_sked_0[];
34extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_unk_1[];
35extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ctxctl_0[];
36extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_0[];
37extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_esetup_0[];
38extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tpbus_0[];
39extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_zcull_0[];
40extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tpconf_0[];
41extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_1[];
42extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_gcc_0[];
43extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ffb_0[];
44extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tex_0[];
45extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_poly_0[];
46extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_l1c_0[];
47extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_2[];
48extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_mp_0[];
49extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ppc_0[];
50extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_zrop_0[];
51extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_0[];
52extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_crop_0[];
53extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_pxbar_0[];
54
55#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
index 47d28c279707..cdc4e0a2cc6b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
@@ -26,6 +26,7 @@
26 26
27#include <core/memory.h> 27#include <core/memory.h>
28#include <core/option.h> 28#include <core/option.h>
29#include <subdev/therm.h>
29 30
30void 31void
31gf100_fb_intr(struct nvkm_fb *base) 32gf100_fb_intr(struct nvkm_fb *base)
@@ -92,6 +93,11 @@ gf100_fb_init(struct nvkm_fb *base)
92 93
93 if (fb->r100c10_page) 94 if (fb->r100c10_page)
94 nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); 95 nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);
96
97 if (base->func->clkgate_pack) {
98 nvkm_therm_clkgate_init(device->therm,
99 base->func->clkgate_pack);
100 }
95} 101}
96 102
97void * 103void *
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
index 0a6e8eaad42c..48fd98e08baa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
@@ -20,10 +20,56 @@
20 * OTHER DEALINGS IN THE SOFTWARE. 20 * OTHER DEALINGS IN THE SOFTWARE.
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 * Lyude Paul
23 */ 24 */
25#include "gk104.h"
24#include "gf100.h" 26#include "gf100.h"
25#include "ram.h" 27#include "ram.h"
26 28
29/*
30 *******************************************************************************
31 * PGRAPH registers for clockgating
32 *******************************************************************************
33 */
34const struct nvkm_therm_clkgate_init
35gk104_fb_clkgate_blcg_init_unk_0[] = {
36 { 0x100d10, 1, 0x0000c244 },
37 { 0x100d30, 1, 0x0000c242 },
38 { 0x100d3c, 1, 0x00000242 },
39 { 0x100d48, 1, 0x00000242 },
40 { 0x100d1c, 1, 0x00000042 },
41 {}
42};
43
44const struct nvkm_therm_clkgate_init
45gk104_fb_clkgate_blcg_init_vm_0[] = {
46 { 0x100c98, 1, 0x00000242 },
47 {}
48};
49
50const struct nvkm_therm_clkgate_init
51gk104_fb_clkgate_blcg_init_main_0[] = {
52 { 0x10f000, 1, 0x00000042 },
53 { 0x17e030, 1, 0x00000044 },
54 { 0x17e040, 1, 0x00000044 },
55 {}
56};
57
58const struct nvkm_therm_clkgate_init
59gk104_fb_clkgate_blcg_init_bcast_0[] = {
60 { 0x17ea60, 4, 0x00000044 },
61 {}
62};
63
64static const struct nvkm_therm_clkgate_pack
65gk104_fb_clkgate_pack[] = {
66 { gk104_fb_clkgate_blcg_init_unk_0 },
67 { gk104_fb_clkgate_blcg_init_vm_0 },
68 { gk104_fb_clkgate_blcg_init_main_0 },
69 { gk104_fb_clkgate_blcg_init_bcast_0 },
70 {}
71};
72
27static const struct nvkm_fb_func 73static const struct nvkm_fb_func
28gk104_fb = { 74gk104_fb = {
29 .dtor = gf100_fb_dtor, 75 .dtor = gf100_fb_dtor,
@@ -33,6 +79,7 @@ gk104_fb = {
33 .intr = gf100_fb_intr, 79 .intr = gf100_fb_intr,
34 .ram_new = gk104_ram_new, 80 .ram_new = gk104_ram_new,
35 .default_bigpage = 17, 81 .default_bigpage = 17,
82 .clkgate_pack = gk104_fb_clkgate_pack,
36}; 83};
37 84
38int 85int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h
new file mode 100644
index 000000000000..b3c78e4ff706
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright 2018 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Lyude Paul
23 */
24
25#ifndef __GK104_FB_H__
26#define __GK104_FB_H__
27
28#include <subdev/therm.h>
29
30extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_unk_0[];
31extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_vm_0[];
32extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_main_0[];
33extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_bcast_0[];
34
35#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
index 9351188d5d76..414a423e0e55 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
@@ -3,6 +3,7 @@
3#define __NVKM_FB_PRIV_H__ 3#define __NVKM_FB_PRIV_H__
4#define nvkm_fb(p) container_of((p), struct nvkm_fb, subdev) 4#define nvkm_fb(p) container_of((p), struct nvkm_fb, subdev)
5#include <subdev/fb.h> 5#include <subdev/fb.h>
6#include <subdev/therm.h>
6struct nvkm_bios; 7struct nvkm_bios;
7 8
8struct nvkm_fb_func { 9struct nvkm_fb_func {
@@ -27,6 +28,7 @@ struct nvkm_fb_func {
27 int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); 28 int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **);
28 29
29 u8 default_bigpage; 30 u8 default_bigpage;
31 const struct nvkm_therm_clkgate_pack *clkgate_pack;
30}; 32};
31 33
32void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, 34void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
index 4bac4772d8ed..550702eab0b1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
@@ -9,6 +9,7 @@ nvkm-y += nvkm/subdev/therm/nv40.o
9nvkm-y += nvkm/subdev/therm/nv50.o 9nvkm-y += nvkm/subdev/therm/nv50.o
10nvkm-y += nvkm/subdev/therm/g84.o 10nvkm-y += nvkm/subdev/therm/g84.o
11nvkm-y += nvkm/subdev/therm/gt215.o 11nvkm-y += nvkm/subdev/therm/gt215.o
12nvkm-y += nvkm/subdev/therm/gf100.o
12nvkm-y += nvkm/subdev/therm/gf119.o 13nvkm-y += nvkm/subdev/therm/gf119.o
13nvkm-y += nvkm/subdev/therm/gk104.o 14nvkm-y += nvkm/subdev/therm/gk104.o
14nvkm-y += nvkm/subdev/therm/gm107.o 15nvkm-y += nvkm/subdev/therm/gm107.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index cf1d5af30f5f..de07bc07abdb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -391,6 +391,16 @@ nvkm_therm_init(struct nvkm_subdev *subdev)
391 return 0; 391 return 0;
392} 392}
393 393
394void
395nvkm_therm_clkgate_init(struct nvkm_therm *therm,
396 const struct nvkm_therm_clkgate_pack *p)
397{
398 if (!therm->func->clkgate_init || !therm->clkgating_enabled)
399 return;
400
401 therm->func->clkgate_init(therm, p);
402}
403
394static void * 404static void *
395nvkm_therm_dtor(struct nvkm_subdev *subdev) 405nvkm_therm_dtor(struct nvkm_subdev *subdev)
396{ 406{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c
new file mode 100644
index 000000000000..5ae6913320e8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright 2018 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Lyude Paul
23 */
24#include <core/device.h>
25
26#include "priv.h"
27
28#define pack_for_each_init(init, pack, head) \
29 for (pack = head; pack && pack->init; pack++) \
30 for (init = pack->init; init && init->count; init++)
31void
32gf100_clkgate_init(struct nvkm_therm *therm,
33 const struct nvkm_therm_clkgate_pack *p)
34{
35 struct nvkm_device *device = therm->subdev.device;
36 const struct nvkm_therm_clkgate_pack *pack;
37 const struct nvkm_therm_clkgate_init *init;
38 u32 next, addr;
39
40 pack_for_each_init(init, pack, p) {
41 next = init->addr + init->count * 8;
42 addr = init->addr;
43
44 nvkm_trace(&therm->subdev, "{ 0x%06x, %d, 0x%08x }\n",
45 init->addr, init->count, init->data);
46 while (addr < next) {
47 nvkm_trace(&therm->subdev, "\t0x%06x = 0x%08x\n",
48 addr, init->data);
49 nvkm_wr32(device, addr, init->data);
50 addr += 8;
51 }
52 }
53}
54
55/*
56 * TODO: Fermi clockgating isn't understood fully yet, so we don't specify any
57 * clockgate functions to use
58 */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c
index 79806a757893..4e03971d2e3d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c
@@ -100,6 +100,7 @@ gk104_therm_func = {
100 .temp_get = g84_temp_get, 100 .temp_get = g84_temp_get,
101 .fan_sense = gt215_therm_fan_sense, 101 .fan_sense = gt215_therm_fan_sense,
102 .program_alarms = nvkm_therm_program_alarms_polling, 102 .program_alarms = nvkm_therm_program_alarms_polling,
103 .clkgate_init = gf100_clkgate_init,
103 .clkgate_enable = gk104_clkgate_enable, 104 .clkgate_enable = gk104_clkgate_enable,
104 .clkgate_fini = gk104_clkgate_fini, 105 .clkgate_fini = gk104_clkgate_fini,
105}; 106};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c
index c08097f2aff5..4caf401d001a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c
@@ -36,7 +36,7 @@ gt215_therm_fan_sense(struct nvkm_therm *therm)
36 return -ENODEV; 36 return -ENODEV;
37} 37}
38 38
39static void 39void
40gt215_therm_init(struct nvkm_therm *therm) 40gt215_therm_init(struct nvkm_therm *therm)
41{ 41{
42 struct nvkm_device *device = therm->subdev.device; 42 struct nvkm_device *device = therm->subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h
index f30202dd88e7..21659daf1864 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h
@@ -97,6 +97,8 @@ struct nvkm_therm_func {
97 97
98 void (*program_alarms)(struct nvkm_therm *); 98 void (*program_alarms)(struct nvkm_therm *);
99 99
100 void (*clkgate_init)(struct nvkm_therm *,
101 const struct nvkm_therm_clkgate_pack *);
100 void (*clkgate_enable)(struct nvkm_therm *); 102 void (*clkgate_enable)(struct nvkm_therm *);
101 void (*clkgate_fini)(struct nvkm_therm *, bool); 103 void (*clkgate_fini)(struct nvkm_therm *, bool);
102}; 104};
@@ -114,6 +116,9 @@ void g84_therm_fini(struct nvkm_therm *);
114 116
115int gt215_therm_fan_sense(struct nvkm_therm *); 117int gt215_therm_fan_sense(struct nvkm_therm *);
116 118
119void gf100_clkgate_init(struct nvkm_therm *,
120 const struct nvkm_therm_clkgate_pack *);
121
117void g84_therm_init(struct nvkm_therm *); 122void g84_therm_init(struct nvkm_therm *);
118 123
119int gf119_fan_pwm_ctrl(struct nvkm_therm *, int, bool); 124int gf119_fan_pwm_ctrl(struct nvkm_therm *, int, bool);
@@ -122,6 +127,7 @@ int gf119_fan_pwm_set(struct nvkm_therm *, int, u32, u32);
122int gf119_fan_pwm_clock(struct nvkm_therm *, int); 127int gf119_fan_pwm_clock(struct nvkm_therm *, int);
123void gf119_therm_init(struct nvkm_therm *); 128void gf119_therm_init(struct nvkm_therm *);
124 129
130void gk104_therm_init(struct nvkm_therm *);
125void gk104_clkgate_enable(struct nvkm_therm *); 131void gk104_clkgate_enable(struct nvkm_therm *);
126void gk104_clkgate_fini(struct nvkm_therm *, bool); 132void gk104_clkgate_fini(struct nvkm_therm *, bool);
127 133