]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
drm/nouveau/tmr: convert to new-style nvkm_subdev
[mirror_ubuntu-eoan-kernel.git] / drivers / gpu / drm / nouveau / nvkm / engine / gr / nv50.c
CommitLineData
6ee73861 1/*
ebb945a9 2 * Copyright 2012 Red Hat Inc.
6ee73861 3 *
ebb945a9
BS
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:
6ee73861 10 *
ebb945a9
BS
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
6ee73861 13 *
ebb945a9
BS
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.
6ee73861 21 *
ebb945a9 22 * Authors: Ben Skeggs
6ee73861 23 */
e3c71eb2 24#include "nv50.h"
6ee73861 25
93260d3c 26#include <core/client.h>
e3c71eb2 27#include <subdev/timer.h>
a65955e1 28#include <engine/fifo.h>
304424e1 29
7e22e71e 30static u64
e3c71eb2 31nv50_gr_units(struct nvkm_gr *gr)
7e22e71e 32{
276836d4 33 return nvkm_rd32(gr->engine.subdev.device, 0x1540);
7e22e71e
CB
34}
35
ebb945a9
BS
36/*******************************************************************************
37 * Graphics object classes
38 ******************************************************************************/
562af10c 39
ebb945a9 40static int
27f3d6cf
BS
41nv50_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
42 int align, struct nvkm_gpuobj **pgpuobj)
ebb945a9 43{
27f3d6cf
BS
44 int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16,
45 align, false, parent, pgpuobj);
46 if (ret == 0) {
47 nvkm_kmap(*pgpuobj);
48 nvkm_wo32(*pgpuobj, 0x00, object->oclass_name);
49 nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
50 nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
51 nvkm_wo32(*pgpuobj, 0x0c, 0x00000000);
52 nvkm_done(*pgpuobj);
53 }
54 return ret;
6ee73861
BS
55}
56
27f3d6cf
BS
57static const struct nvkm_object_func
58nv50_gr_object = {
59 .bind = nv50_gr_object_bind,
ebb945a9 60};
6ee73861 61
27f3d6cf
BS
62static int
63nv50_gr_object_get(struct nvkm_gr *base, int index, struct nvkm_sclass *sclass)
64{
65 struct nv50_gr *gr = nv50_gr(base);
66 int c = 0;
6ee73861 67
27f3d6cf
BS
68 while (gr->func->sclass[c].oclass) {
69 if (c++ == index) {
70 *sclass = gr->func->sclass[index];
71 return index;
72 }
73 }
2703c21a 74
27f3d6cf
BS
75 return c;
76}
6ee73861 77
ebb945a9
BS
78/*******************************************************************************
79 * PGRAPH context
80 ******************************************************************************/
6ee73861
BS
81
82static int
27f3d6cf
BS
83nv50_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
84 int align, struct nvkm_gpuobj **pgpuobj)
4ea52f89 85{
27f3d6cf
BS
86 struct nv50_gr *gr = nv50_gr_chan(object)->gr;
87 int ret = nvkm_gpuobj_new(gr->base.engine.subdev.device, gr->size,
88 align, true, parent, pgpuobj);
89 if (ret == 0) {
90 nvkm_kmap(*pgpuobj);
91 nv50_grctx_fill(gr->base.engine.subdev.device, *pgpuobj);
92 nvkm_done(*pgpuobj);
93 }
94 return ret;
95}
4ea52f89 96
27f3d6cf
BS
97static const struct nvkm_object_func
98nv50_gr_chan = {
99 .bind = nv50_gr_chan_bind,
100};
4ea52f89 101
27f3d6cf
BS
102static int
103nv50_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
104 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
105{
106 struct nv50_gr *gr = nv50_gr(base);
107 struct nv50_gr_chan *chan;
108
109 if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
110 return -ENOMEM;
111 nvkm_object_ctor(&nv50_gr_chan, oclass, &chan->object);
112 chan->gr = gr;
113 *pobject = &chan->object;
ebb945a9 114 return 0;
4ea52f89
BS
115}
116
ebb945a9
BS
117/*******************************************************************************
118 * PGRAPH engine/subdev functions
119 ******************************************************************************/
120
bfee3f3d 121static const struct nvkm_bitfield nv50_gr_status[] = {
d432a2db
MS
122 { 0x00000001, "BUSY" }, /* set when any bit is set */
123 { 0x00000002, "DISPATCH" },
124 { 0x00000004, "UNK2" },
125 { 0x00000008, "UNK3" },
126 { 0x00000010, "UNK4" },
127 { 0x00000020, "UNK5" },
128 { 0x00000040, "M2MF" },
129 { 0x00000080, "UNK7" },
130 { 0x00000100, "CTXPROG" },
131 { 0x00000200, "VFETCH" },
4ac1b1a2
IM
132 { 0x00000400, "CCACHE_PREGEOM" },
133 { 0x00000800, "STRMOUT_VATTR_POSTGEOM" },
134 { 0x00001000, "VCLIP" },
135 { 0x00002000, "RATTR_APLANE" },
136 { 0x00004000, "TRAST" },
d432a2db
MS
137 { 0x00008000, "CLIPID" },
138 { 0x00010000, "ZCULL" },
139 { 0x00020000, "ENG2D" },
4ac1b1a2
IM
140 { 0x00040000, "RMASK" },
141 { 0x00080000, "TPC_RAST" },
142 { 0x00100000, "TPC_PROP" },
143 { 0x00200000, "TPC_TEX" },
144 { 0x00400000, "TPC_GEOM" },
145 { 0x00800000, "TPC_MP" },
d432a2db
MS
146 { 0x01000000, "ROP" },
147 {}
148};
149
109c2f2f
BS
150static const struct nvkm_bitfield
151nv50_gr_vstatus_0[] = {
152 { 0x01, "VFETCH" },
153 { 0x02, "CCACHE" },
154 { 0x04, "PREGEOM" },
155 { 0x08, "POSTGEOM" },
156 { 0x10, "VATTR" },
157 { 0x20, "STRMOUT" },
158 { 0x40, "VCLIP" },
159 {}
d432a2db
MS
160};
161
109c2f2f
BS
162static const struct nvkm_bitfield
163nv50_gr_vstatus_1[] = {
164 { 0x01, "TPC_RAST" },
165 { 0x02, "TPC_PROP" },
166 { 0x04, "TPC_TEX" },
167 { 0x08, "TPC_GEOM" },
168 { 0x10, "TPC_MP" },
169 {}
d432a2db
MS
170};
171
109c2f2f
BS
172static const struct nvkm_bitfield
173nv50_gr_vstatus_2[] = {
174 { 0x01, "RATTR" },
175 { 0x02, "APLANE" },
176 { 0x04, "TRAST" },
177 { 0x08, "CLIPID" },
178 { 0x10, "ZCULL" },
179 { 0x20, "ENG2D" },
180 { 0x40, "RMASK" },
181 { 0x80, "ROP" },
182 {}
d432a2db
MS
183};
184
e3c71eb2 185static void
bfee3f3d 186nvkm_gr_vstatus_print(struct nv50_gr *gr, int r,
109c2f2f 187 const struct nvkm_bitfield *units, u32 status)
d432a2db 188{
109c2f2f
BS
189 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
190 u32 stat = status;
191 u8 mask = 0x00;
192 char msg[64];
d432a2db
MS
193 int i;
194
109c2f2f 195 for (i = 0; units[i].name && status; i++) {
d432a2db 196 if ((status & 7) == 1)
109c2f2f 197 mask |= (1 << i);
d432a2db
MS
198 status >>= 3;
199 }
109c2f2f
BS
200
201 nvkm_snprintbf(msg, sizeof(msg), units, mask);
202 nvkm_error(subdev, "PGRAPH_VSTATUS%d: %08x [%s]\n", r, stat, msg);
d432a2db
MS
203}
204
ebb945a9 205static int
e3c71eb2 206g84_gr_tlb_flush(struct nvkm_engine *engine)
56ac7475 207{
bfee3f3d 208 struct nv50_gr *gr = (void *)engine;
109c2f2f
BS
209 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
210 struct nvkm_device *device = subdev->device;
276836d4 211 struct nvkm_timer *tmr = device->timer;
56ac7475
BS
212 bool idle, timeout = false;
213 unsigned long flags;
109c2f2f 214 char status[128];
56ac7475
BS
215 u64 start;
216 u32 tmp;
217
bfee3f3d 218 spin_lock_irqsave(&gr->lock, flags);
276836d4 219 nvkm_mask(device, 0x400500, 0x00000001, 0x00000000);
56ac7475 220
31649ecf 221 start = nvkm_timer_read(tmr);
56ac7475
BS
222 do {
223 idle = true;
224
276836d4 225 for (tmp = nvkm_rd32(device, 0x400380); tmp && idle; tmp >>= 3) {
56ac7475
BS
226 if ((tmp & 7) == 1)
227 idle = false;
228 }
229
276836d4 230 for (tmp = nvkm_rd32(device, 0x400384); tmp && idle; tmp >>= 3) {
56ac7475
BS
231 if ((tmp & 7) == 1)
232 idle = false;
233 }
234
276836d4 235 for (tmp = nvkm_rd32(device, 0x400388); tmp && idle; tmp >>= 3) {
56ac7475
BS
236 if ((tmp & 7) == 1)
237 idle = false;
238 }
ebb945a9 239 } while (!idle &&
31649ecf 240 !(timeout = nvkm_timer_read(tmr) - start > 2000000000));
56ac7475
BS
241
242 if (timeout) {
109c2f2f 243 nvkm_error(subdev, "PGRAPH TLB flush idle timeout fail\n");
d432a2db 244
276836d4 245 tmp = nvkm_rd32(device, 0x400700);
109c2f2f
BS
246 nvkm_snprintbf(status, sizeof(status), nv50_gr_status, tmp);
247 nvkm_error(subdev, "PGRAPH_STATUS %08x [%s]\n", tmp, status);
d432a2db 248
bfee3f3d 249 nvkm_gr_vstatus_print(gr, 0, nv50_gr_vstatus_0,
276836d4 250 nvkm_rd32(device, 0x400380));
bfee3f3d 251 nvkm_gr_vstatus_print(gr, 1, nv50_gr_vstatus_1,
276836d4 252 nvkm_rd32(device, 0x400384));
bfee3f3d 253 nvkm_gr_vstatus_print(gr, 2, nv50_gr_vstatus_2,
276836d4 254 nvkm_rd32(device, 0x400388));
56ac7475
BS
255 }
256
56ac7475 257
276836d4 258 nvkm_wr32(device, 0x100c80, 0x00000001);
c4584adc
BS
259 nvkm_msec(device, 2000,
260 if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
261 break;
262 );
276836d4 263 nvkm_mask(device, 0x400500, 0x00000001, 0x00000001);
bfee3f3d 264 spin_unlock_irqrestore(&gr->lock, flags);
ebb945a9 265 return timeout ? -EBUSY : 0;
56ac7475 266}
274fec93 267
e3c71eb2 268static const struct nvkm_bitfield nv50_mp_exec_errors[] = {
f750ecc9
IM
269 { 0x01, "STACK_UNDERFLOW" },
270 { 0x02, "STACK_MISMATCH" },
271 { 0x04, "QUADON_ACTIVE" },
272 { 0x08, "TIMEOUT" },
273 { 0x10, "INVALID_OPCODE" },
274 { 0x20, "PM_OVERFLOW" },
275 { 0x40, "BREAKPOINT" },
274fec93
BS
276 {}
277};
278
e3c71eb2 279static const struct nvkm_bitfield nv50_mpc_traps[] = {
ea7dce90
IM
280 { 0x0000001, "LOCAL_LIMIT_READ" },
281 { 0x0000010, "LOCAL_LIMIT_WRITE" },
282 { 0x0000040, "STACK_LIMIT" },
283 { 0x0000100, "GLOBAL_LIMIT_READ" },
284 { 0x0001000, "GLOBAL_LIMIT_WRITE" },
285 { 0x0010000, "MP0" },
286 { 0x0020000, "MP1" },
287 { 0x0040000, "GLOBAL_LIMIT_RED" },
288 { 0x0400000, "GLOBAL_LIMIT_ATOM" },
289 { 0x4000000, "MP2" },
290 {}
291};
292
e3c71eb2 293static const struct nvkm_bitfield nv50_tex_traps[] = {
46a7b625
IM
294 { 0x00000001, "" }, /* any bit set? */
295 { 0x00000002, "FAULT" },
296 { 0x00000004, "STORAGE_TYPE_MISMATCH" },
297 { 0x00000008, "LINEAR_MISMATCH" },
298 { 0x00000020, "WRONG_MEMTYPE" },
299 {}
300};
301
e3c71eb2 302static const struct nvkm_bitfield nv50_gr_trap_m2mf[] = {
274fec93
BS
303 { 0x00000001, "NOTIFY" },
304 { 0x00000002, "IN" },
305 { 0x00000004, "OUT" },
306 {}
307};
308
e3c71eb2 309static const struct nvkm_bitfield nv50_gr_trap_vfetch[] = {
274fec93
BS
310 { 0x00000001, "FAULT" },
311 {}
312};
313
e3c71eb2 314static const struct nvkm_bitfield nv50_gr_trap_strmout[] = {
274fec93
BS
315 { 0x00000001, "FAULT" },
316 {}
317};
318
e3c71eb2 319static const struct nvkm_bitfield nv50_gr_trap_ccache[] = {
274fec93
BS
320 { 0x00000001, "FAULT" },
321 {}
322};
323
324/* There must be a *lot* of these. Will take some time to gather them up. */
e3c71eb2 325const struct nvkm_enum nv50_data_error_names[] = {
887cd788 326 { 0x00000003, "INVALID_OPERATION", NULL },
bb9b18a3
BS
327 { 0x00000004, "INVALID_VALUE", NULL },
328 { 0x00000005, "INVALID_ENUM", NULL },
329 { 0x00000008, "INVALID_OBJECT", NULL },
330 { 0x00000009, "READ_ONLY_OBJECT", NULL },
331 { 0x0000000a, "SUPERVISOR_OBJECT", NULL },
332 { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
333 { 0x0000000c, "INVALID_BITFIELD", NULL },
334 { 0x0000000d, "BEGIN_END_ACTIVE", NULL },
335 { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
336 { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
337 { 0x00000010, "RT_DOUBLE_BIND", NULL },
338 { 0x00000011, "RT_TYPES_MISMATCH", NULL },
339 { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
340 { 0x00000015, "FP_TOO_FEW_REGS", NULL },
341 { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
342 { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
343 { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
344 { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
345 { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
346 { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
347 { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
348 { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
349 { 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
350 { 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
351 { 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
547e6c7f 352 { 0x00000024, "VP_ZERO_INPUTS", NULL },
bb9b18a3
BS
353 { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
354 { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
355 { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
356 { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
357 { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
358 { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
359 { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
360 { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
361 { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
362 { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
363 { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
364 { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
365 { 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
366 { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
367 { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
274fec93
BS
368 {}
369};
370
e3c71eb2 371static const struct nvkm_bitfield nv50_gr_intr_name[] = {
274fec93
BS
372 { 0x00000001, "NOTIFY" },
373 { 0x00000002, "COMPUTE_QUERY" },
374 { 0x00000010, "ILLEGAL_MTHD" },
375 { 0x00000020, "ILLEGAL_CLASS" },
376 { 0x00000040, "DOUBLE_NOTIFY" },
377 { 0x00001000, "CONTEXT_SWITCH" },
378 { 0x00010000, "BUFFER_NOTIFY" },
379 { 0x00100000, "DATA_ERROR" },
380 { 0x00200000, "TRAP" },
381 { 0x01000000, "SINGLE_STEP" },
382 {}
383};
384
e3c71eb2 385static const struct nvkm_bitfield nv50_gr_trap_prop[] = {
e2dd003d
IM
386 { 0x00000004, "SURF_WIDTH_OVERRUN" },
387 { 0x00000008, "SURF_HEIGHT_OVERRUN" },
388 { 0x00000010, "DST2D_FAULT" },
389 { 0x00000020, "ZETA_FAULT" },
390 { 0x00000040, "RT_FAULT" },
391 { 0x00000080, "CUDA_FAULT" },
392 { 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
393 { 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
394 { 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
395 { 0x00000800, "DST2D_LINEAR_MISMATCH" },
396 { 0x00001000, "RT_LINEAR_MISMATCH" },
397 {}
398};
399
400static void
109c2f2f 401nv50_gr_prop_trap(struct nv50_gr *gr, u32 ustatus_addr, u32 ustatus, u32 tp)
e2dd003d 402{
109c2f2f
BS
403 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
404 struct nvkm_device *device = subdev->device;
276836d4
BS
405 u32 e0c = nvkm_rd32(device, ustatus_addr + 0x04);
406 u32 e10 = nvkm_rd32(device, ustatus_addr + 0x08);
407 u32 e14 = nvkm_rd32(device, ustatus_addr + 0x0c);
408 u32 e18 = nvkm_rd32(device, ustatus_addr + 0x10);
409 u32 e1c = nvkm_rd32(device, ustatus_addr + 0x14);
410 u32 e20 = nvkm_rd32(device, ustatus_addr + 0x18);
411 u32 e24 = nvkm_rd32(device, ustatus_addr + 0x1c);
109c2f2f 412 char msg[128];
e2dd003d
IM
413
414 /* CUDA memory: l[], g[] or stack. */
415 if (ustatus & 0x00000080) {
416 if (e18 & 0x80000000) {
417 /* g[] read fault? */
109c2f2f 418 nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
e2dd003d
IM
419 tp, e14, e10 | ((e18 >> 24) & 0x1f));
420 e18 &= ~0x1f000000;
421 } else if (e18 & 0xc) {
422 /* g[] write fault? */
109c2f2f 423 nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
e2dd003d
IM
424 tp, e14, e10 | ((e18 >> 7) & 0x1f));
425 e18 &= ~0x00000f80;
426 } else {
109c2f2f 427 nvkm_error(subdev, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
e2dd003d
IM
428 tp, e14, e10);
429 }
430 ustatus &= ~0x00000080;
431 }
432 if (ustatus) {
109c2f2f
BS
433 nvkm_snprintbf(msg, sizeof(msg), nv50_gr_trap_prop, ustatus);
434 nvkm_error(subdev, "TRAP_PROP - TP %d - %08x [%s] - "
435 "Address %02x%08x\n",
436 tp, ustatus, msg, e14, e10);
e2dd003d 437 }
109c2f2f 438 nvkm_error(subdev, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
e2dd003d
IM
439 tp, e0c, e18, e1c, e20, e24);
440}
441
274fec93 442static void
bfee3f3d 443nv50_gr_mp_trap(struct nv50_gr *gr, int tpid, int display)
274fec93 444{
109c2f2f
BS
445 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
446 struct nvkm_device *device = subdev->device;
276836d4 447 u32 units = nvkm_rd32(device, 0x1540);
ebb945a9 448 u32 addr, mp10, status, pc, oplow, ophigh;
109c2f2f 449 char msg[128];
274fec93
BS
450 int i;
451 int mps = 0;
452 for (i = 0; i < 4; i++) {
453 if (!(units & 1 << (i+24)))
454 continue;
bfee3f3d 455 if (nv_device(gr)->chipset < 0xa0)
274fec93
BS
456 addr = 0x408200 + (tpid << 12) + (i << 7);
457 else
458 addr = 0x408100 + (tpid << 11) + (i << 7);
276836d4
BS
459 mp10 = nvkm_rd32(device, addr + 0x10);
460 status = nvkm_rd32(device, addr + 0x14);
274fec93
BS
461 if (!status)
462 continue;
463 if (display) {
276836d4
BS
464 nvkm_rd32(device, addr + 0x20);
465 pc = nvkm_rd32(device, addr + 0x24);
466 oplow = nvkm_rd32(device, addr + 0x70);
467 ophigh = nvkm_rd32(device, addr + 0x74);
109c2f2f
BS
468 nvkm_snprintbf(msg, sizeof(msg),
469 nv50_mp_exec_errors, status);
470 nvkm_error(subdev, "TRAP_MP_EXEC - TP %d MP %d: "
471 "%08x [%s] at %06x warp %d, "
472 "opcode %08x %08x\n",
473 tpid, i, status, msg, pc & 0xffffff,
474 pc >> 24, oplow, ophigh);
274fec93 475 }
276836d4
BS
476 nvkm_wr32(device, addr + 0x10, mp10);
477 nvkm_wr32(device, addr + 0x14, 0);
274fec93
BS
478 mps++;
479 }
480 if (!mps && display)
109c2f2f 481 nvkm_error(subdev, "TRAP_MP_EXEC - TP %d: "
274fec93
BS
482 "No MPs claiming errors?\n", tpid);
483}
484
485static void
bfee3f3d 486nv50_gr_tp_trap(struct nv50_gr *gr, int type, u32 ustatus_old,
e3c71eb2 487 u32 ustatus_new, int display, const char *name)
274fec93 488{
109c2f2f
BS
489 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
490 struct nvkm_device *device = subdev->device;
276836d4 491 u32 units = nvkm_rd32(device, 0x1540);
274fec93 492 int tps = 0;
274fec93 493 int i, r;
109c2f2f 494 char msg[128];
ebb945a9 495 u32 ustatus_addr, ustatus;
274fec93
BS
496 for (i = 0; i < 16; i++) {
497 if (!(units & (1 << i)))
498 continue;
bfee3f3d 499 if (nv_device(gr)->chipset < 0xa0)
274fec93
BS
500 ustatus_addr = ustatus_old + (i << 12);
501 else
502 ustatus_addr = ustatus_new + (i << 11);
276836d4 503 ustatus = nvkm_rd32(device, ustatus_addr) & 0x7fffffff;
274fec93
BS
504 if (!ustatus)
505 continue;
506 tps++;
507 switch (type) {
508 case 6: /* texture error... unknown for now */
274fec93 509 if (display) {
109c2f2f 510 nvkm_error(subdev, "magic set %d:\n", i);
274fec93 511 for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
109c2f2f
BS
512 nvkm_error(subdev, "\t%08x: %08x\n", r,
513 nvkm_rd32(device, r));
46a7b625 514 if (ustatus) {
109c2f2f
BS
515 nvkm_snprintbf(msg, sizeof(msg),
516 nv50_tex_traps, ustatus);
517 nvkm_error(subdev,
518 "%s - TP%d: %08x [%s]\n",
519 name, i, ustatus, msg);
46a7b625
IM
520 ustatus = 0;
521 }
274fec93
BS
522 }
523 break;
524 case 7: /* MP error */
c983e6f6 525 if (ustatus & 0x04030000) {
bfee3f3d 526 nv50_gr_mp_trap(gr, i, display);
c983e6f6 527 ustatus &= ~0x04030000;
274fec93 528 }
ea7dce90 529 if (ustatus && display) {
109c2f2f
BS
530 nvkm_snprintbf(msg, sizeof(msg),
531 nv50_mpc_traps, ustatus);
532 nvkm_error(subdev, "%s - TP%d: %08x [%s]\n",
533 name, i, ustatus, msg);
ea7dce90
IM
534 ustatus = 0;
535 }
274fec93 536 break;
e2dd003d
IM
537 case 8: /* PROP error */
538 if (display)
bfee3f3d
BS
539 nv50_gr_prop_trap(
540 gr, ustatus_addr, ustatus, i);
e2dd003d 541 ustatus = 0;
274fec93
BS
542 break;
543 }
544 if (ustatus) {
545 if (display)
109c2f2f 546 nvkm_error(subdev, "%s - TP%d: Unhandled ustatus %08x\n", name, i, ustatus);
274fec93 547 }
276836d4 548 nvkm_wr32(device, ustatus_addr, 0xc0000000);
274fec93
BS
549 }
550
551 if (!tps && display)
109c2f2f 552 nvkm_warn(subdev, "%s - No TPs claiming errors?\n", name);
274fec93
BS
553}
554
555static int
bfee3f3d 556nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
8f0649b5 557 int chid, u64 inst, const char *name)
274fec93 558{
109c2f2f
BS
559 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
560 struct nvkm_device *device = subdev->device;
276836d4 561 u32 status = nvkm_rd32(device, 0x400108);
274fec93 562 u32 ustatus;
109c2f2f 563 char msg[128];
274fec93
BS
564
565 if (!status && display) {
109c2f2f 566 nvkm_error(subdev, "TRAP: no units reporting traps?\n");
274fec93
BS
567 return 1;
568 }
569
570 /* DISPATCH: Relays commands to other units and handles NOTIFY,
571 * COND, QUERY. If you get a trap from it, the command is still stuck
572 * in DISPATCH and you need to do something about it. */
573 if (status & 0x001) {
276836d4 574 ustatus = nvkm_rd32(device, 0x400804) & 0x7fffffff;
274fec93 575 if (!ustatus && display) {
109c2f2f 576 nvkm_error(subdev, "TRAP_DISPATCH - no ustatus?\n");
274fec93
BS
577 }
578
276836d4 579 nvkm_wr32(device, 0x400500, 0x00000000);
274fec93
BS
580
581 /* Known to be triggered by screwed up NOTIFY and COND... */
582 if (ustatus & 0x00000001) {
276836d4 583 u32 addr = nvkm_rd32(device, 0x400808);
274fec93
BS
584 u32 subc = (addr & 0x00070000) >> 16;
585 u32 mthd = (addr & 0x00001ffc);
276836d4
BS
586 u32 datal = nvkm_rd32(device, 0x40080c);
587 u32 datah = nvkm_rd32(device, 0x400810);
588 u32 class = nvkm_rd32(device, 0x400814);
589 u32 r848 = nvkm_rd32(device, 0x400848);
274fec93 590
109c2f2f 591 nvkm_error(subdev, "TRAP DISPATCH_FAULT\n");
274fec93 592 if (display && (addr & 0x80000000)) {
109c2f2f
BS
593 nvkm_error(subdev,
594 "ch %d [%010llx %s] subc %d "
595 "class %04x mthd %04x data %08x%08x "
596 "400808 %08x 400848 %08x\n",
8f0649b5 597 chid, inst, name, subc, class, mthd,
109c2f2f 598 datah, datal, addr, r848);
274fec93
BS
599 } else
600 if (display) {
109c2f2f 601 nvkm_error(subdev, "no stuck command?\n");
274fec93
BS
602 }
603
276836d4
BS
604 nvkm_wr32(device, 0x400808, 0);
605 nvkm_wr32(device, 0x4008e8, nvkm_rd32(device, 0x4008e8) & 3);
606 nvkm_wr32(device, 0x400848, 0);
274fec93
BS
607 ustatus &= ~0x00000001;
608 }
609
610 if (ustatus & 0x00000002) {
276836d4 611 u32 addr = nvkm_rd32(device, 0x40084c);
274fec93
BS
612 u32 subc = (addr & 0x00070000) >> 16;
613 u32 mthd = (addr & 0x00001ffc);
276836d4
BS
614 u32 data = nvkm_rd32(device, 0x40085c);
615 u32 class = nvkm_rd32(device, 0x400814);
274fec93 616
109c2f2f 617 nvkm_error(subdev, "TRAP DISPATCH_QUERY\n");
274fec93 618 if (display && (addr & 0x80000000)) {
109c2f2f
BS
619 nvkm_error(subdev,
620 "ch %d [%010llx %s] subc %d "
621 "class %04x mthd %04x data %08x "
8f0649b5
BS
622 "40084c %08x\n", chid, inst, name,
623 subc, class, mthd, data, addr);
274fec93
BS
624 } else
625 if (display) {
109c2f2f 626 nvkm_error(subdev, "no stuck command?\n");
274fec93
BS
627 }
628
276836d4 629 nvkm_wr32(device, 0x40084c, 0);
274fec93
BS
630 ustatus &= ~0x00000002;
631 }
632
633 if (ustatus && display) {
109c2f2f
BS
634 nvkm_error(subdev, "TRAP_DISPATCH "
635 "(unknown %08x)\n", ustatus);
274fec93
BS
636 }
637
276836d4
BS
638 nvkm_wr32(device, 0x400804, 0xc0000000);
639 nvkm_wr32(device, 0x400108, 0x001);
274fec93
BS
640 status &= ~0x001;
641 if (!status)
642 return 0;
643 }
644
645 /* M2MF: Memory to memory copy engine. */
646 if (status & 0x002) {
276836d4 647 u32 ustatus = nvkm_rd32(device, 0x406800) & 0x7fffffff;
274fec93 648 if (display) {
109c2f2f
BS
649 nvkm_snprintbf(msg, sizeof(msg),
650 nv50_gr_trap_m2mf, ustatus);
651 nvkm_error(subdev, "TRAP_M2MF %08x [%s]\n",
652 ustatus, msg);
653 nvkm_error(subdev, "TRAP_M2MF %08x %08x %08x %08x\n",
654 nvkm_rd32(device, 0x406804),
655 nvkm_rd32(device, 0x406808),
656 nvkm_rd32(device, 0x40680c),
657 nvkm_rd32(device, 0x406810));
274fec93
BS
658 }
659
660 /* No sane way found yet -- just reset the bugger. */
276836d4
BS
661 nvkm_wr32(device, 0x400040, 2);
662 nvkm_wr32(device, 0x400040, 0);
663 nvkm_wr32(device, 0x406800, 0xc0000000);
664 nvkm_wr32(device, 0x400108, 0x002);
274fec93
BS
665 status &= ~0x002;
666 }
667
668 /* VFETCH: Fetches data from vertex buffers. */
669 if (status & 0x004) {
276836d4 670 u32 ustatus = nvkm_rd32(device, 0x400c04) & 0x7fffffff;
274fec93 671 if (display) {
109c2f2f
BS
672 nvkm_snprintbf(msg, sizeof(msg),
673 nv50_gr_trap_vfetch, ustatus);
674 nvkm_error(subdev, "TRAP_VFETCH %08x [%s]\n",
675 ustatus, msg);
676 nvkm_error(subdev, "TRAP_VFETCH %08x %08x %08x %08x\n",
677 nvkm_rd32(device, 0x400c00),
678 nvkm_rd32(device, 0x400c08),
679 nvkm_rd32(device, 0x400c0c),
680 nvkm_rd32(device, 0x400c10));
274fec93
BS
681 }
682
276836d4
BS
683 nvkm_wr32(device, 0x400c04, 0xc0000000);
684 nvkm_wr32(device, 0x400108, 0x004);
274fec93
BS
685 status &= ~0x004;
686 }
687
688 /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
689 if (status & 0x008) {
276836d4 690 ustatus = nvkm_rd32(device, 0x401800) & 0x7fffffff;
274fec93 691 if (display) {
109c2f2f
BS
692 nvkm_snprintbf(msg, sizeof(msg),
693 nv50_gr_trap_strmout, ustatus);
694 nvkm_error(subdev, "TRAP_STRMOUT %08x [%s]\n",
695 ustatus, msg);
696 nvkm_error(subdev, "TRAP_STRMOUT %08x %08x %08x %08x\n",
697 nvkm_rd32(device, 0x401804),
698 nvkm_rd32(device, 0x401808),
699 nvkm_rd32(device, 0x40180c),
700 nvkm_rd32(device, 0x401810));
274fec93
BS
701 }
702
703 /* No sane way found yet -- just reset the bugger. */
276836d4
BS
704 nvkm_wr32(device, 0x400040, 0x80);
705 nvkm_wr32(device, 0x400040, 0);
706 nvkm_wr32(device, 0x401800, 0xc0000000);
707 nvkm_wr32(device, 0x400108, 0x008);
274fec93
BS
708 status &= ~0x008;
709 }
710
711 /* CCACHE: Handles code and c[] caches and fills them. */
712 if (status & 0x010) {
276836d4 713 ustatus = nvkm_rd32(device, 0x405018) & 0x7fffffff;
274fec93 714 if (display) {
109c2f2f
BS
715 nvkm_snprintbf(msg, sizeof(msg),
716 nv50_gr_trap_ccache, ustatus);
717 nvkm_error(subdev, "TRAP_CCACHE %08x [%s]\n",
718 ustatus, msg);
719 nvkm_error(subdev, "TRAP_CCACHE %08x %08x %08x %08x "
720 "%08x %08x %08x\n",
721 nvkm_rd32(device, 0x405000),
722 nvkm_rd32(device, 0x405004),
723 nvkm_rd32(device, 0x405008),
724 nvkm_rd32(device, 0x40500c),
725 nvkm_rd32(device, 0x405010),
726 nvkm_rd32(device, 0x405014),
727 nvkm_rd32(device, 0x40501c));
274fec93
BS
728 }
729
276836d4
BS
730 nvkm_wr32(device, 0x405018, 0xc0000000);
731 nvkm_wr32(device, 0x400108, 0x010);
274fec93
BS
732 status &= ~0x010;
733 }
734
735 /* Unknown, not seen yet... 0x402000 is the only trap status reg
736 * remaining, so try to handle it anyway. Perhaps related to that
737 * unknown DMA slot on tesla? */
738 if (status & 0x20) {
276836d4 739 ustatus = nvkm_rd32(device, 0x402000) & 0x7fffffff;
274fec93 740 if (display)
109c2f2f 741 nvkm_error(subdev, "TRAP_UNKC04 %08x\n", ustatus);
276836d4 742 nvkm_wr32(device, 0x402000, 0xc0000000);
274fec93
BS
743 /* no status modifiction on purpose */
744 }
745
746 /* TEXTURE: CUDA texturing units */
747 if (status & 0x040) {
bfee3f3d 748 nv50_gr_tp_trap(gr, 6, 0x408900, 0x408600, display,
ebb945a9 749 "TRAP_TEXTURE");
276836d4 750 nvkm_wr32(device, 0x400108, 0x040);
274fec93
BS
751 status &= ~0x040;
752 }
753
754 /* MP: CUDA execution engines. */
755 if (status & 0x080) {
bfee3f3d 756 nv50_gr_tp_trap(gr, 7, 0x408314, 0x40831c, display,
ebb945a9 757 "TRAP_MP");
276836d4 758 nvkm_wr32(device, 0x400108, 0x080);
274fec93
BS
759 status &= ~0x080;
760 }
761
e2dd003d 762 /* PROP: Handles TP-initiated uncached memory accesses:
274fec93
BS
763 * l[], g[], stack, 2d surfaces, render targets. */
764 if (status & 0x100) {
bfee3f3d 765 nv50_gr_tp_trap(gr, 8, 0x408e08, 0x408708, display,
e2dd003d 766 "TRAP_PROP");
276836d4 767 nvkm_wr32(device, 0x400108, 0x100);
274fec93
BS
768 status &= ~0x100;
769 }
770
771 if (status) {
772 if (display)
109c2f2f 773 nvkm_error(subdev, "TRAP: unknown %08x\n", status);
276836d4 774 nvkm_wr32(device, 0x400108, status);
274fec93
BS
775 }
776
777 return 1;
778}
779
ebb945a9 780static void
e3c71eb2 781nv50_gr_intr(struct nvkm_subdev *subdev)
274fec93 782{
276836d4
BS
783 struct nv50_gr *gr = (void *)subdev;
784 struct nvkm_device *device = gr->base.engine.subdev.device;
a65955e1 785 struct nvkm_fifo_chan *chan;
276836d4
BS
786 u32 stat = nvkm_rd32(device, 0x400100);
787 u32 inst = nvkm_rd32(device, 0x40032c) & 0x0fffffff;
788 u32 addr = nvkm_rd32(device, 0x400704);
ebb945a9
BS
789 u32 subc = (addr & 0x00070000) >> 16;
790 u32 mthd = (addr & 0x00001ffc);
276836d4
BS
791 u32 data = nvkm_rd32(device, 0x400708);
792 u32 class = nvkm_rd32(device, 0x400814);
e2dd003d 793 u32 show = stat, show_bitfield = stat;
109c2f2f 794 const struct nvkm_enum *en;
a65955e1 795 unsigned long flags;
8f0649b5 796 const char *name = "unknown";
109c2f2f 797 char msg[128];
8f0649b5 798 int chid = -1;
72a14827 799
a65955e1 800 chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
8f0649b5
BS
801 if (chan) {
802 name = chan->object.client->name;
803 chid = chan->chid;
804 }
274fec93 805
ebb945a9 806 if (show & 0x00100000) {
276836d4 807 u32 ecode = nvkm_rd32(device, 0x400110);
109c2f2f
BS
808 en = nvkm_enum_find(nv50_data_error_names, ecode);
809 nvkm_error(subdev, "DATA_ERROR %08x [%s]\n",
810 ecode, en ? en->name : "");
e2dd003d 811 show_bitfield &= ~0x00100000;
ebb945a9 812 }
274fec93 813
ebb945a9 814 if (stat & 0x00200000) {
8f0649b5 815 if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, name))
ebb945a9 816 show &= ~0x00200000;
e2dd003d 817 show_bitfield &= ~0x00200000;
ebb945a9
BS
818 }
819
276836d4
BS
820 nvkm_wr32(device, 0x400100, stat);
821 nvkm_wr32(device, 0x400500, 0x00010001);
ebb945a9
BS
822
823 if (show) {
e2dd003d 824 show &= show_bitfield;
109c2f2f
BS
825 nvkm_snprintbf(msg, sizeof(msg), nv50_gr_intr_name, show);
826 nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] subc %d "
827 "class %04x mthd %04x data %08x\n",
8f0649b5
BS
828 stat, msg, chid, (u64)inst << 12, name,
829 subc, class, mthd, data);
274fec93 830 }
ebb945a9 831
276836d4
BS
832 if (nvkm_rd32(device, 0x400824) & (1 << 31))
833 nvkm_wr32(device, 0x400824, nvkm_rd32(device, 0x400824) & ~(1 << 31));
72a14827 834
a65955e1 835 nvkm_fifo_chan_put(device->fifo, flags, &chan);
274fec93
BS
836}
837
27f3d6cf
BS
838static const struct nv50_gr_func
839nv50_gr = {
840 .sclass = {
841 { -1, -1, 0x0030, &nv50_gr_object },
842 { -1, -1, 0x502d, &nv50_gr_object },
843 { -1, -1, 0x5039, &nv50_gr_object },
844 { -1, -1, 0x5097, &nv50_gr_object },
845 { -1, -1, 0x50c0, &nv50_gr_object },
846 {}
847 }
848};
849
850static const struct nv50_gr_func
851g84_gr = {
852 .sclass = {
853 { -1, -1, 0x0030, &nv50_gr_object },
854 { -1, -1, 0x502d, &nv50_gr_object },
855 { -1, -1, 0x5039, &nv50_gr_object },
856 { -1, -1, 0x50c0, &nv50_gr_object },
857 { -1, -1, 0x8297, &nv50_gr_object },
858 {}
859 }
860};
861
862static const struct nv50_gr_func
863gt200_gr = {
864 .sclass = {
865 { -1, -1, 0x0030, &nv50_gr_object },
866 { -1, -1, 0x502d, &nv50_gr_object },
867 { -1, -1, 0x5039, &nv50_gr_object },
868 { -1, -1, 0x50c0, &nv50_gr_object },
869 { -1, -1, 0x8397, &nv50_gr_object },
870 {}
871 }
872};
873
874static const struct nv50_gr_func
875gt215_gr = {
876 .sclass = {
877 { -1, -1, 0x0030, &nv50_gr_object },
878 { -1, -1, 0x502d, &nv50_gr_object },
879 { -1, -1, 0x5039, &nv50_gr_object },
880 { -1, -1, 0x50c0, &nv50_gr_object },
881 { -1, -1, 0x8597, &nv50_gr_object },
882 { -1, -1, 0x85c0, &nv50_gr_object },
883 {}
884 }
885};
886
887static const struct nv50_gr_func
888mcp89_gr = {
889 .sclass = {
890 { -1, -1, 0x0030, &nv50_gr_object },
891 { -1, -1, 0x502d, &nv50_gr_object },
892 { -1, -1, 0x5039, &nv50_gr_object },
893 { -1, -1, 0x50c0, &nv50_gr_object },
894 { -1, -1, 0x85c0, &nv50_gr_object },
895 { -1, -1, 0x8697, &nv50_gr_object },
896 {}
897 }
898};
899
900static const struct nvkm_gr_func
901nv50_gr_ = {
902 .chan_new = nv50_gr_chan_new,
903 .object_get = nv50_gr_object_get,
904};
905
ebb945a9 906static int
e3c71eb2
BS
907nv50_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
908 struct nvkm_oclass *oclass, void *data, u32 size,
909 struct nvkm_object **pobject)
274fec93 910{
bfee3f3d 911 struct nv50_gr *gr;
ebb945a9 912 int ret;
274fec93 913
bfee3f3d
BS
914 ret = nvkm_gr_create(parent, engine, oclass, true, &gr);
915 *pobject = nv_object(gr);
ebb945a9
BS
916 if (ret)
917 return ret;
274fec93 918
bfee3f3d
BS
919 nv_subdev(gr)->unit = 0x00201000;
920 nv_subdev(gr)->intr = nv50_gr_intr;
274fec93 921
27f3d6cf 922 gr->base.func = &nv50_gr_;
bfee3f3d 923 gr->base.units = nv50_gr_units;
7e22e71e 924
bfee3f3d 925 switch (nv_device(gr)->chipset) {
ebb945a9 926 case 0x50:
27f3d6cf 927 gr->func = &nv50_gr;
ebb945a9
BS
928 break;
929 case 0x84:
930 case 0x86:
931 case 0x92:
932 case 0x94:
933 case 0x96:
934 case 0x98:
27f3d6cf 935 gr->func = &g84_gr;
ebb945a9
BS
936 break;
937 case 0xa0:
938 case 0xaa:
939 case 0xac:
27f3d6cf 940 gr->func = &gt200_gr;
ebb945a9
BS
941 break;
942 case 0xa3:
943 case 0xa5:
944 case 0xa8:
27f3d6cf 945 gr->func = &gt215_gr;
ebb945a9
BS
946 break;
947 case 0xaf:
27f3d6cf 948 gr->func = &mcp89_gr;
ebb945a9 949 break;
10d9b4ed 950 }
274fec93 951
464d636b 952 /* unfortunate hw bug workaround... */
bfee3f3d
BS
953 if (nv_device(gr)->chipset != 0x50 &&
954 nv_device(gr)->chipset != 0xac)
955 nv_engine(gr)->tlb_flush = g84_gr_tlb_flush;
274fec93 956
bfee3f3d 957 spin_lock_init(&gr->lock);
ebb945a9 958 return 0;
274fec93 959}
2703c21a 960
ebb945a9 961static int
e3c71eb2 962nv50_gr_init(struct nvkm_object *object)
2703c21a 963{
bfee3f3d 964 struct nv50_gr *gr = (void *)object;
276836d4 965 struct nvkm_device *device = gr->base.engine.subdev.device;
ebb945a9 966 int ret, units, i;
2703c21a 967
bfee3f3d 968 ret = nvkm_gr_init(&gr->base);
ebb945a9
BS
969 if (ret)
970 return ret;
2703c21a 971
ebb945a9 972 /* NV_PGRAPH_DEBUG_3_HW_CTX_SWITCH_ENABLED */
276836d4 973 nvkm_wr32(device, 0x40008c, 0x00000004);
2703c21a 974
ebb945a9 975 /* reset/enable traps and interrupts */
276836d4
BS
976 nvkm_wr32(device, 0x400804, 0xc0000000);
977 nvkm_wr32(device, 0x406800, 0xc0000000);
978 nvkm_wr32(device, 0x400c04, 0xc0000000);
979 nvkm_wr32(device, 0x401800, 0xc0000000);
980 nvkm_wr32(device, 0x405018, 0xc0000000);
981 nvkm_wr32(device, 0x402000, 0xc0000000);
982
983 units = nvkm_rd32(device, 0x001540);
ebb945a9
BS
984 for (i = 0; i < 16; i++) {
985 if (!(units & (1 << i)))
986 continue;
2703c21a 987
bfee3f3d 988 if (nv_device(gr)->chipset < 0xa0) {
276836d4
BS
989 nvkm_wr32(device, 0x408900 + (i << 12), 0xc0000000);
990 nvkm_wr32(device, 0x408e08 + (i << 12), 0xc0000000);
991 nvkm_wr32(device, 0x408314 + (i << 12), 0xc0000000);
ebb945a9 992 } else {
276836d4
BS
993 nvkm_wr32(device, 0x408600 + (i << 11), 0xc0000000);
994 nvkm_wr32(device, 0x408708 + (i << 11), 0xc0000000);
995 nvkm_wr32(device, 0x40831c + (i << 11), 0xc0000000);
ebb945a9 996 }
2703c21a
BS
997 }
998
276836d4
BS
999 nvkm_wr32(device, 0x400108, 0xffffffff);
1000 nvkm_wr32(device, 0x400138, 0xffffffff);
1001 nvkm_wr32(device, 0x400100, 0xffffffff);
1002 nvkm_wr32(device, 0x40013c, 0xffffffff);
1003 nvkm_wr32(device, 0x400500, 0x00010001);
2703c21a 1004
ebb945a9 1005 /* upload context program, initialise ctxctl defaults */
bfee3f3d 1006 ret = nv50_grctx_init(nv_device(gr), &gr->size);
ebb945a9
BS
1007 if (ret)
1008 return ret;
2703c21a 1009
276836d4
BS
1010 nvkm_wr32(device, 0x400824, 0x00000000);
1011 nvkm_wr32(device, 0x400828, 0x00000000);
1012 nvkm_wr32(device, 0x40082c, 0x00000000);
1013 nvkm_wr32(device, 0x400830, 0x00000000);
1014 nvkm_wr32(device, 0x40032c, 0x00000000);
1015 nvkm_wr32(device, 0x400330, 0x00000000);
2703c21a 1016
ebb945a9 1017 /* some unknown zcull magic */
bfee3f3d 1018 switch (nv_device(gr)->chipset & 0xf0) {
ebb945a9
BS
1019 case 0x50:
1020 case 0x80:
1021 case 0x90:
276836d4 1022 nvkm_wr32(device, 0x402ca8, 0x00000800);
ebb945a9
BS
1023 break;
1024 case 0xa0:
1025 default:
bfee3f3d
BS
1026 if (nv_device(gr)->chipset == 0xa0 ||
1027 nv_device(gr)->chipset == 0xaa ||
1028 nv_device(gr)->chipset == 0xac) {
276836d4 1029 nvkm_wr32(device, 0x402ca8, 0x00000802);
ebb945a9 1030 } else {
276836d4
BS
1031 nvkm_wr32(device, 0x402cc0, 0x00000000);
1032 nvkm_wr32(device, 0x402ca8, 0x00000002);
2703c21a 1033 }
2703c21a 1034
ebb945a9
BS
1035 break;
1036 }
2703c21a 1037
ebb945a9
BS
1038 /* zero out zcull regions */
1039 for (i = 0; i < 8; i++) {
276836d4
BS
1040 nvkm_wr32(device, 0x402c20 + (i * 0x10), 0x00000000);
1041 nvkm_wr32(device, 0x402c24 + (i * 0x10), 0x00000000);
1042 nvkm_wr32(device, 0x402c28 + (i * 0x10), 0x00000000);
1043 nvkm_wr32(device, 0x402c2c + (i * 0x10), 0x00000000);
ebb945a9 1044 }
2703c21a
BS
1045 return 0;
1046}
ebb945a9 1047
e3c71eb2 1048struct nvkm_oclass
b8bf04e1 1049nv50_gr_oclass = {
ebb945a9 1050 .handle = NV_ENGINE(GR, 0x50),
e3c71eb2 1051 .ofuncs = &(struct nvkm_ofuncs) {
b8bf04e1 1052 .ctor = nv50_gr_ctor,
e3c71eb2 1053 .dtor = _nvkm_gr_dtor,
b8bf04e1 1054 .init = nv50_gr_init,
e3c71eb2 1055 .fini = _nvkm_gr_fini,
ebb945a9
BS
1056 },
1057};