drm/nouveau/fifo: remove dependence on namedb/engctx lookup
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nvkm / engine / gr / gf100.c
CommitLineData
4b223eef 1/*
ebb945a9 2 * Copyright 2012 Red Hat Inc.
4b223eef
BS
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: Ben Skeggs
23 */
e3c71eb2
BS
24#include "gf100.h"
25#include "ctxgf100.h"
26#include "fuc/os.h"
27
28#include <core/client.h>
e3c71eb2
BS
29#include <core/handle.h>
30#include <core/option.h>
31#include <engine/fifo.h>
32#include <subdev/fb.h>
33#include <subdev/mc.h>
34#include <subdev/timer.h>
35
36#include <nvif/class.h>
37#include <nvif/unpack.h>
0411de85 38
ac9738bb
BS
39/*******************************************************************************
40 * Zero Bandwidth Clear
41 ******************************************************************************/
42
43static void
bfee3f3d 44gf100_gr_zbc_clear_color(struct gf100_gr *gr, int zbc)
ac9738bb 45{
276836d4 46 struct nvkm_device *device = gr->base.engine.subdev.device;
bfee3f3d 47 if (gr->zbc_color[zbc].format) {
276836d4
BS
48 nvkm_wr32(device, 0x405804, gr->zbc_color[zbc].ds[0]);
49 nvkm_wr32(device, 0x405808, gr->zbc_color[zbc].ds[1]);
50 nvkm_wr32(device, 0x40580c, gr->zbc_color[zbc].ds[2]);
51 nvkm_wr32(device, 0x405810, gr->zbc_color[zbc].ds[3]);
52 }
53 nvkm_wr32(device, 0x405814, gr->zbc_color[zbc].format);
54 nvkm_wr32(device, 0x405820, zbc);
55 nvkm_wr32(device, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */
ac9738bb
BS
56}
57
58static int
bfee3f3d 59gf100_gr_zbc_color_get(struct gf100_gr *gr, int format,
e3c71eb2 60 const u32 ds[4], const u32 l2[4])
ac9738bb 61{
bfee3f3d 62 struct nvkm_ltc *ltc = nvkm_ltc(gr);
ac9738bb
BS
63 int zbc = -ENOSPC, i;
64
65 for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
bfee3f3d
BS
66 if (gr->zbc_color[i].format) {
67 if (gr->zbc_color[i].format != format)
ac9738bb 68 continue;
bfee3f3d
BS
69 if (memcmp(gr->zbc_color[i].ds, ds, sizeof(
70 gr->zbc_color[i].ds)))
ac9738bb 71 continue;
bfee3f3d
BS
72 if (memcmp(gr->zbc_color[i].l2, l2, sizeof(
73 gr->zbc_color[i].l2))) {
ac9738bb
BS
74 WARN_ON(1);
75 return -EINVAL;
76 }
77 return i;
78 } else {
79 zbc = (zbc < 0) ? i : zbc;
80 }
81 }
82
da7c74ea
BS
83 if (zbc < 0)
84 return zbc;
85
bfee3f3d
BS
86 memcpy(gr->zbc_color[zbc].ds, ds, sizeof(gr->zbc_color[zbc].ds));
87 memcpy(gr->zbc_color[zbc].l2, l2, sizeof(gr->zbc_color[zbc].l2));
88 gr->zbc_color[zbc].format = format;
ac9738bb 89 ltc->zbc_color_get(ltc, zbc, l2);
bfee3f3d 90 gf100_gr_zbc_clear_color(gr, zbc);
ac9738bb
BS
91 return zbc;
92}
93
94static void
bfee3f3d 95gf100_gr_zbc_clear_depth(struct gf100_gr *gr, int zbc)
ac9738bb 96{
276836d4 97 struct nvkm_device *device = gr->base.engine.subdev.device;
bfee3f3d 98 if (gr->zbc_depth[zbc].format)
276836d4
BS
99 nvkm_wr32(device, 0x405818, gr->zbc_depth[zbc].ds);
100 nvkm_wr32(device, 0x40581c, gr->zbc_depth[zbc].format);
101 nvkm_wr32(device, 0x405820, zbc);
102 nvkm_wr32(device, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */
ac9738bb
BS
103}
104
105static int
bfee3f3d 106gf100_gr_zbc_depth_get(struct gf100_gr *gr, int format,
e3c71eb2 107 const u32 ds, const u32 l2)
ac9738bb 108{
bfee3f3d 109 struct nvkm_ltc *ltc = nvkm_ltc(gr);
ac9738bb
BS
110 int zbc = -ENOSPC, i;
111
112 for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
bfee3f3d
BS
113 if (gr->zbc_depth[i].format) {
114 if (gr->zbc_depth[i].format != format)
ac9738bb 115 continue;
bfee3f3d 116 if (gr->zbc_depth[i].ds != ds)
ac9738bb 117 continue;
bfee3f3d 118 if (gr->zbc_depth[i].l2 != l2) {
ac9738bb
BS
119 WARN_ON(1);
120 return -EINVAL;
121 }
122 return i;
123 } else {
124 zbc = (zbc < 0) ? i : zbc;
125 }
126 }
127
da7c74ea
BS
128 if (zbc < 0)
129 return zbc;
130
bfee3f3d
BS
131 gr->zbc_depth[zbc].format = format;
132 gr->zbc_depth[zbc].ds = ds;
133 gr->zbc_depth[zbc].l2 = l2;
ac9738bb 134 ltc->zbc_depth_get(ltc, zbc, l2);
bfee3f3d 135 gf100_gr_zbc_clear_depth(gr, zbc);
ac9738bb
BS
136 return zbc;
137}
138
ebb945a9
BS
139/*******************************************************************************
140 * Graphics object classes
141 ******************************************************************************/
142
ac9738bb 143static int
e3c71eb2 144gf100_fermi_mthd_zbc_color(struct nvkm_object *object, void *data, u32 size)
ac9738bb 145{
bfee3f3d 146 struct gf100_gr *gr = (void *)object->engine;
ac9738bb
BS
147 union {
148 struct fermi_a_zbc_color_v0 v0;
149 } *args = data;
150 int ret;
151
152 if (nvif_unpack(args->v0, 0, 0, false)) {
153 switch (args->v0.format) {
154 case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
155 case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
156 case FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32:
157 case FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16:
158 case FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16:
159 case FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16:
160 case FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16:
161 case FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16:
162 case FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8:
163 case FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8:
164 case FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10:
165 case FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10:
166 case FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8:
167 case FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8:
168 case FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8:
169 case FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8:
170 case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8:
171 case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10:
172 case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11:
bfee3f3d 173 ret = gf100_gr_zbc_color_get(gr, args->v0.format,
e3c71eb2
BS
174 args->v0.ds,
175 args->v0.l2);
ac9738bb
BS
176 if (ret >= 0) {
177 args->v0.index = ret;
178 return 0;
179 }
180 break;
181 default:
182 return -EINVAL;
183 }
184 }
185
186 return ret;
187}
188
189static int
e3c71eb2 190gf100_fermi_mthd_zbc_depth(struct nvkm_object *object, void *data, u32 size)
ac9738bb 191{
bfee3f3d 192 struct gf100_gr *gr = (void *)object->engine;
ac9738bb
BS
193 union {
194 struct fermi_a_zbc_depth_v0 v0;
195 } *args = data;
196 int ret;
197
198 if (nvif_unpack(args->v0, 0, 0, false)) {
199 switch (args->v0.format) {
200 case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
bfee3f3d 201 ret = gf100_gr_zbc_depth_get(gr, args->v0.format,
e3c71eb2
BS
202 args->v0.ds,
203 args->v0.l2);
ac9738bb
BS
204 return (ret >= 0) ? 0 : -ENOSPC;
205 default:
206 return -EINVAL;
207 }
208 }
209
210 return ret;
211}
212
213static int
e3c71eb2 214gf100_fermi_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
ac9738bb
BS
215{
216 switch (mthd) {
217 case FERMI_A_ZBC_COLOR:
e3c71eb2 218 return gf100_fermi_mthd_zbc_color(object, data, size);
ac9738bb 219 case FERMI_A_ZBC_DEPTH:
e3c71eb2 220 return gf100_fermi_mthd_zbc_depth(object, data, size);
ac9738bb
BS
221 default:
222 break;
223 }
224 return -EINVAL;
225}
226
e3c71eb2
BS
227struct nvkm_ofuncs
228gf100_fermi_ofuncs = {
229 .ctor = _nvkm_object_ctor,
230 .dtor = nvkm_object_destroy,
aa35888f
BS
231 .init = _nvkm_object_init,
232 .fini = _nvkm_object_fini,
e3c71eb2 233 .mthd = gf100_fermi_mthd,
ac9738bb
BS
234};
235
d6bd3803 236static int
e3c71eb2
BS
237gf100_gr_set_shader_exceptions(struct nvkm_object *object, u32 mthd,
238 void *pdata, u32 size)
d6bd3803 239{
bfee3f3d 240 struct gf100_gr *gr = (void *)object->engine;
276836d4 241 struct nvkm_device *device = gr->base.engine.subdev.device;
d6bd3803
BS
242 if (size >= sizeof(u32)) {
243 u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
276836d4
BS
244 nvkm_wr32(device, 0x419e44, data);
245 nvkm_wr32(device, 0x419e4c, data);
d6bd3803
BS
246 return 0;
247 }
248 return -EINVAL;
249}
250
e3c71eb2
BS
251struct nvkm_omthds
252gf100_gr_9097_omthds[] = {
253 { 0x1528, 0x1528, gf100_gr_set_shader_exceptions },
d6bd3803
BS
254 {}
255};
256
e3c71eb2
BS
257struct nvkm_omthds
258gf100_gr_90c0_omthds[] = {
259 { 0x1528, 0x1528, gf100_gr_set_shader_exceptions },
d6bd3803
BS
260 {}
261};
262
e3c71eb2
BS
263struct nvkm_oclass
264gf100_gr_sclass[] = {
3740c825
BS
265 { FERMI_TWOD_A, &nvkm_object_ofuncs },
266 { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs },
e3c71eb2
BS
267 { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
268 { FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
ebb945a9
BS
269 {}
270};
271
ebb945a9
BS
272/*******************************************************************************
273 * PGRAPH context
274 ******************************************************************************/
966a5b7d 275
ac1499d9 276int
e3c71eb2
BS
277gf100_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
278 struct nvkm_oclass *oclass, void *args, u32 size,
279 struct nvkm_object **pobject)
966a5b7d 280{
e3c71eb2 281 struct nvkm_vm *vm = nvkm_client(parent)->vm;
bfee3f3d
BS
282 struct gf100_gr *gr = (void *)engine;
283 struct gf100_gr_data *data = gr->mmio_data;
284 struct gf100_gr_mmio *mmio = gr->mmio_list;
e3c71eb2 285 struct gf100_gr_chan *chan;
227c95d9 286 struct nvkm_device *device = gr->base.engine.subdev.device;
142ea05f 287 struct nvkm_gpuobj *image;
966a5b7d 288 int ret, i;
966a5b7d 289
ebb945a9 290 /* allocate memory for context, and fill with default values */
e3c71eb2 291 ret = nvkm_gr_context_create(parent, engine, oclass, NULL,
bfee3f3d 292 gr->size, 0x100,
e3c71eb2 293 NVOBJ_FLAG_ZERO_ALLOC, &chan);
ebb945a9 294 *pobject = nv_object(chan);
966a5b7d
BS
295 if (ret)
296 return ret;
297
ac1499d9
BS
298 /* allocate memory for a "mmio list" buffer that's used by the HUB
299 * fuc to modify some per-context register settings on first load
300 * of the context.
301 */
227c95d9
BS
302 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x100,
303 false, &chan->mmio);
73a60c0d
BS
304 if (ret)
305 return ret;
306
227c95d9
BS
307 ret = nvkm_vm_get(vm, 0x1000, 12, NV_MEM_ACCESS_RW |
308 NV_MEM_ACCESS_SYS, &chan->mmio_vma);
73a60c0d
BS
309 if (ret)
310 return ret;
311
227c95d9
BS
312 nvkm_memory_map(chan->mmio, &chan->mmio_vma, 0);
313
ac1499d9 314 /* allocate buffers referenced by mmio list */
bfee3f3d 315 for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) {
227c95d9
BS
316 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
317 data->size, data->align, false,
318 &chan->data[i].mem);
ac1499d9
BS
319 if (ret)
320 return ret;
73a60c0d 321
227c95d9
BS
322 ret = nvkm_vm_get(vm, nvkm_memory_size(chan->data[i].mem),
323 12, data->access, &chan->data[i].vma);
ac1499d9
BS
324 if (ret)
325 return ret;
966a5b7d 326
227c95d9 327 nvkm_memory_map(chan->data[i].mem, &chan->data[i].vma, 0);
ac1499d9 328 data++;
966a5b7d
BS
329 }
330
ac1499d9 331 /* finally, fill in the mmio list and point the context at it */
142ea05f 332 nvkm_kmap(chan->mmio);
bfee3f3d 333 for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) {
ac1499d9
BS
334 u32 addr = mmio->addr;
335 u32 data = mmio->data;
966a5b7d 336
694c6caf 337 if (mmio->buffer >= 0) {
ebb945a9 338 u64 info = chan->data[mmio->buffer].vma.offset;
ac1499d9
BS
339 data |= info >> mmio->shift;
340 }
73a60c0d 341
142ea05f
BS
342 nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr);
343 nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data);
ac1499d9
BS
344 mmio++;
345 }
142ea05f 346 nvkm_done(chan->mmio);
73a60c0d 347
142ea05f
BS
348 image = &chan->base.base.gpuobj;
349 nvkm_kmap(image);
bfee3f3d 350 for (i = 0; i < gr->size; i += 4)
142ea05f 351 nvkm_wo32(image, i, gr->data[i / 4]);
966a5b7d 352
bfee3f3d 353 if (!gr->firmware) {
142ea05f
BS
354 nvkm_wo32(image, 0x00, chan->mmio_nr / 2);
355 nvkm_wo32(image, 0x04, chan->mmio_vma.offset >> 8);
0411de85 356 } else {
142ea05f
BS
357 nvkm_wo32(image, 0xf4, 0);
358 nvkm_wo32(image, 0xf8, 0);
359 nvkm_wo32(image, 0x10, chan->mmio_nr / 2);
360 nvkm_wo32(image, 0x14, lower_32_bits(chan->mmio_vma.offset));
361 nvkm_wo32(image, 0x18, upper_32_bits(chan->mmio_vma.offset));
362 nvkm_wo32(image, 0x1c, 1);
363 nvkm_wo32(image, 0x20, 0);
364 nvkm_wo32(image, 0x28, 0);
365 nvkm_wo32(image, 0x2c, 0);
0411de85 366 }
142ea05f 367 nvkm_done(image);
966a5b7d 368
ebb945a9 369 return 0;
4b223eef
BS
370}
371
ac1499d9 372void
e3c71eb2 373gf100_gr_context_dtor(struct nvkm_object *object)
4b223eef 374{
e3c71eb2 375 struct gf100_gr_chan *chan = (void *)object;
ac1499d9
BS
376 int i;
377
ebb945a9 378 for (i = 0; i < ARRAY_SIZE(chan->data); i++) {
227c95d9
BS
379 if (chan->data[i].vma.node) {
380 nvkm_vm_unmap(&chan->data[i].vma);
381 nvkm_vm_put(&chan->data[i].vma);
382 }
383 nvkm_memory_del(&chan->data[i].mem);
ac1499d9 384 }
966a5b7d 385
227c95d9
BS
386 if (chan->mmio_vma.node) {
387 nvkm_vm_unmap(&chan->mmio_vma);
388 nvkm_vm_put(&chan->mmio_vma);
389 }
390 nvkm_memory_del(&chan->mmio);
ac1499d9 391
e3c71eb2 392 nvkm_gr_context_destroy(&chan->base);
4b223eef
BS
393}
394
ebb945a9 395/*******************************************************************************
c33b1e8c 396 * PGRAPH register lists
ebb945a9
BS
397 ******************************************************************************/
398
e3c71eb2
BS
399const struct gf100_gr_init
400gf100_gr_init_main_0[] = {
30f4e087
BS
401 { 0x400080, 1, 0x04, 0x003083c2 },
402 { 0x400088, 1, 0x04, 0x00006fe7 },
403 { 0x40008c, 1, 0x04, 0x00000000 },
404 { 0x400090, 1, 0x04, 0x00000030 },
405 { 0x40013c, 1, 0x04, 0x013901f7 },
406 { 0x400140, 1, 0x04, 0x00000100 },
407 { 0x400144, 1, 0x04, 0x00000000 },
408 { 0x400148, 1, 0x04, 0x00000110 },
409 { 0x400138, 1, 0x04, 0x00000000 },
410 { 0x400130, 2, 0x04, 0x00000000 },
411 { 0x400124, 1, 0x04, 0x00000002 },
412 {}
413};
414
e3c71eb2
BS
415const struct gf100_gr_init
416gf100_gr_init_fe_0[] = {
30f4e087
BS
417 { 0x40415c, 1, 0x04, 0x00000000 },
418 { 0x404170, 1, 0x04, 0x00000000 },
419 {}
420};
421
e3c71eb2
BS
422const struct gf100_gr_init
423gf100_gr_init_pri_0[] = {
30f4e087
BS
424 { 0x404488, 2, 0x04, 0x00000000 },
425 {}
426};
427
e3c71eb2
BS
428const struct gf100_gr_init
429gf100_gr_init_rstr2d_0[] = {
30f4e087
BS
430 { 0x407808, 1, 0x04, 0x00000000 },
431 {}
432};
433
e3c71eb2
BS
434const struct gf100_gr_init
435gf100_gr_init_pd_0[] = {
30f4e087
BS
436 { 0x406024, 1, 0x04, 0x00000000 },
437 {}
438};
439
e3c71eb2
BS
440const struct gf100_gr_init
441gf100_gr_init_ds_0[] = {
30f4e087
BS
442 { 0x405844, 1, 0x04, 0x00ffffff },
443 { 0x405850, 1, 0x04, 0x00000000 },
444 { 0x405908, 1, 0x04, 0x00000000 },
445 {}
446};
447
e3c71eb2
BS
448const struct gf100_gr_init
449gf100_gr_init_scc_0[] = {
30f4e087
BS
450 { 0x40803c, 1, 0x04, 0x00000000 },
451 {}
452};
453
e3c71eb2
BS
454const struct gf100_gr_init
455gf100_gr_init_prop_0[] = {
30f4e087 456 { 0x4184a0, 1, 0x04, 0x00000000 },
97af71fa
BS
457 {}
458};
459
e3c71eb2
BS
460const struct gf100_gr_init
461gf100_gr_init_gpc_unk_0[] = {
30f4e087
BS
462 { 0x418604, 1, 0x04, 0x00000000 },
463 { 0x418680, 1, 0x04, 0x00000000 },
464 { 0x418714, 1, 0x04, 0x80000000 },
465 { 0x418384, 1, 0x04, 0x00000000 },
97af71fa
BS
466 {}
467};
468
e3c71eb2
BS
469const struct gf100_gr_init
470gf100_gr_init_setup_0[] = {
30f4e087 471 { 0x418814, 3, 0x04, 0x00000000 },
97af71fa
BS
472 {}
473};
474
e3c71eb2
BS
475const struct gf100_gr_init
476gf100_gr_init_crstr_0[] = {
30f4e087 477 { 0x418b04, 1, 0x04, 0x00000000 },
97af71fa
BS
478 {}
479};
480
e3c71eb2
BS
481const struct gf100_gr_init
482gf100_gr_init_setup_1[] = {
30f4e087
BS
483 { 0x4188c8, 1, 0x04, 0x80000000 },
484 { 0x4188cc, 1, 0x04, 0x00000000 },
485 { 0x4188d0, 1, 0x04, 0x00010000 },
486 { 0x4188d4, 1, 0x04, 0x00000001 },
97af71fa
BS
487 {}
488};
489
e3c71eb2
BS
490const struct gf100_gr_init
491gf100_gr_init_zcull_0[] = {
30f4e087
BS
492 { 0x418910, 1, 0x04, 0x00010001 },
493 { 0x418914, 1, 0x04, 0x00000301 },
494 { 0x418918, 1, 0x04, 0x00800000 },
495 { 0x418980, 1, 0x04, 0x77777770 },
496 { 0x418984, 3, 0x04, 0x77777777 },
97af71fa
BS
497 {}
498};
499
e3c71eb2
BS
500const struct gf100_gr_init
501gf100_gr_init_gpm_0[] = {
30f4e087
BS
502 { 0x418c04, 1, 0x04, 0x00000000 },
503 { 0x418c88, 1, 0x04, 0x00000000 },
97af71fa
BS
504 {}
505};
506
e3c71eb2
BS
507const struct gf100_gr_init
508gf100_gr_init_gpc_unk_1[] = {
30f4e087
BS
509 { 0x418d00, 1, 0x04, 0x00000000 },
510 { 0x418f08, 1, 0x04, 0x00000000 },
511 { 0x418e00, 1, 0x04, 0x00000050 },
512 { 0x418e08, 1, 0x04, 0x00000000 },
97af71fa
BS
513 {}
514};
515
e3c71eb2
BS
516const struct gf100_gr_init
517gf100_gr_init_gcc_0[] = {
30f4e087
BS
518 { 0x41900c, 1, 0x04, 0x00000000 },
519 { 0x419018, 1, 0x04, 0x00000000 },
520 {}
521};
522
e3c71eb2
BS
523const struct gf100_gr_init
524gf100_gr_init_tpccs_0[] = {
30f4e087
BS
525 { 0x419d08, 2, 0x04, 0x00000000 },
526 { 0x419d10, 1, 0x04, 0x00000014 },
7e194533
BS
527 {}
528};
529
e3c71eb2
BS
530const struct gf100_gr_init
531gf100_gr_init_tex_0[] = {
30f4e087
BS
532 { 0x419ab0, 1, 0x04, 0x00000000 },
533 { 0x419ab8, 1, 0x04, 0x000000e7 },
534 { 0x419abc, 2, 0x04, 0x00000000 },
7e194533
BS
535 {}
536};
537
e3c71eb2
BS
538const struct gf100_gr_init
539gf100_gr_init_pe_0[] = {
30f4e087
BS
540 { 0x41980c, 3, 0x04, 0x00000000 },
541 { 0x419844, 1, 0x04, 0x00000000 },
542 { 0x41984c, 1, 0x04, 0x00005bc5 },
543 { 0x419850, 4, 0x04, 0x00000000 },
7e194533
BS
544 {}
545};
546
e3c71eb2
BS
547const struct gf100_gr_init
548gf100_gr_init_l1c_0[] = {
30f4e087
BS
549 { 0x419c98, 1, 0x04, 0x00000000 },
550 { 0x419ca8, 1, 0x04, 0x80000000 },
551 { 0x419cb4, 1, 0x04, 0x00000000 },
552 { 0x419cb8, 1, 0x04, 0x00008bf4 },
553 { 0x419cbc, 1, 0x04, 0x28137606 },
554 { 0x419cc0, 2, 0x04, 0x00000000 },
7e194533
BS
555 {}
556};
557
e3c71eb2
BS
558const struct gf100_gr_init
559gf100_gr_init_wwdx_0[] = {
30f4e087
BS
560 { 0x419bd4, 1, 0x04, 0x00800000 },
561 { 0x419bdc, 1, 0x04, 0x00000000 },
7e194533
BS
562 {}
563};
564
e3c71eb2
BS
565const struct gf100_gr_init
566gf100_gr_init_tpccs_1[] = {
30f4e087 567 { 0x419d2c, 1, 0x04, 0x00000000 },
7e194533
BS
568 {}
569};
570
e3c71eb2
BS
571const struct gf100_gr_init
572gf100_gr_init_mpc_0[] = {
30f4e087 573 { 0x419c0c, 1, 0x04, 0x00000000 },
7e194533
BS
574 {}
575};
576
e3c71eb2
BS
577static const struct gf100_gr_init
578gf100_gr_init_sm_0[] = {
30f4e087
BS
579 { 0x419e00, 1, 0x04, 0x00000000 },
580 { 0x419ea0, 1, 0x04, 0x00000000 },
581 { 0x419ea4, 1, 0x04, 0x00000100 },
582 { 0x419ea8, 1, 0x04, 0x00001100 },
583 { 0x419eac, 1, 0x04, 0x11100702 },
584 { 0x419eb0, 1, 0x04, 0x00000003 },
585 { 0x419eb4, 4, 0x04, 0x00000000 },
586 { 0x419ec8, 1, 0x04, 0x06060618 },
587 { 0x419ed0, 1, 0x04, 0x0eff0e38 },
588 { 0x419ed4, 1, 0x04, 0x011104f1 },
589 { 0x419edc, 1, 0x04, 0x00000000 },
590 { 0x419f00, 1, 0x04, 0x00000000 },
591 { 0x419f2c, 1, 0x04, 0x00000000 },
592 {}
593};
594
e3c71eb2
BS
595const struct gf100_gr_init
596gf100_gr_init_be_0[] = {
30f4e087
BS
597 { 0x40880c, 1, 0x04, 0x00000000 },
598 { 0x408910, 9, 0x04, 0x00000000 },
599 { 0x408950, 1, 0x04, 0x00000000 },
600 { 0x408954, 1, 0x04, 0x0000ffff },
601 { 0x408984, 1, 0x04, 0x00000000 },
602 { 0x408988, 1, 0x04, 0x08040201 },
603 { 0x40898c, 1, 0x04, 0x80402010 },
604 {}
605};
606
e3c71eb2
BS
607const struct gf100_gr_init
608gf100_gr_init_fe_1[] = {
c33b1e8c
BS
609 { 0x4040f0, 1, 0x04, 0x00000000 },
610 {}
611};
612
e3c71eb2
BS
613const struct gf100_gr_init
614gf100_gr_init_pe_1[] = {
c33b1e8c
BS
615 { 0x419880, 1, 0x04, 0x00000002 },
616 {}
617};
618
e3c71eb2
BS
619static const struct gf100_gr_pack
620gf100_gr_pack_mmio[] = {
621 { gf100_gr_init_main_0 },
622 { gf100_gr_init_fe_0 },
623 { gf100_gr_init_pri_0 },
624 { gf100_gr_init_rstr2d_0 },
625 { gf100_gr_init_pd_0 },
626 { gf100_gr_init_ds_0 },
627 { gf100_gr_init_scc_0 },
628 { gf100_gr_init_prop_0 },
629 { gf100_gr_init_gpc_unk_0 },
630 { gf100_gr_init_setup_0 },
631 { gf100_gr_init_crstr_0 },
632 { gf100_gr_init_setup_1 },
633 { gf100_gr_init_zcull_0 },
634 { gf100_gr_init_gpm_0 },
635 { gf100_gr_init_gpc_unk_1 },
636 { gf100_gr_init_gcc_0 },
637 { gf100_gr_init_tpccs_0 },
638 { gf100_gr_init_tex_0 },
639 { gf100_gr_init_pe_0 },
640 { gf100_gr_init_l1c_0 },
641 { gf100_gr_init_wwdx_0 },
642 { gf100_gr_init_tpccs_1 },
643 { gf100_gr_init_mpc_0 },
644 { gf100_gr_init_sm_0 },
645 { gf100_gr_init_be_0 },
646 { gf100_gr_init_fe_1 },
647 { gf100_gr_init_pe_1 },
26410c67
ML
648 {}
649};
650
c33b1e8c
BS
651/*******************************************************************************
652 * PGRAPH engine/subdev functions
653 ******************************************************************************/
654
ac9738bb 655void
bfee3f3d 656gf100_gr_zbc_init(struct gf100_gr *gr)
ac9738bb
BS
657{
658 const u32 zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
659 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
660 const u32 one[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
661 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
662 const u32 f32_0[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
663 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
664 const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
665 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
bfee3f3d 666 struct nvkm_ltc *ltc = nvkm_ltc(gr);
ac9738bb
BS
667 int index;
668
bfee3f3d
BS
669 if (!gr->zbc_color[0].format) {
670 gf100_gr_zbc_color_get(gr, 1, & zero[0], &zero[4]);
671 gf100_gr_zbc_color_get(gr, 2, & one[0], &one[4]);
672 gf100_gr_zbc_color_get(gr, 4, &f32_0[0], &f32_0[4]);
673 gf100_gr_zbc_color_get(gr, 4, &f32_1[0], &f32_1[4]);
674 gf100_gr_zbc_depth_get(gr, 1, 0x00000000, 0x00000000);
675 gf100_gr_zbc_depth_get(gr, 1, 0x3f800000, 0x3f800000);
ac9738bb
BS
676 }
677
678 for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
bfee3f3d 679 gf100_gr_zbc_clear_color(gr, index);
ac9738bb 680 for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
bfee3f3d 681 gf100_gr_zbc_clear_depth(gr, index);
ac9738bb
BS
682}
683
4a8cf451
AC
684/**
685 * Wait until GR goes idle. GR is considered idle if it is disabled by the
686 * MC (0x200) register, or GR is not busy and a context switch is not in
687 * progress.
688 */
689int
bfee3f3d 690gf100_gr_wait_idle(struct gf100_gr *gr)
4a8cf451 691{
109c2f2f
BS
692 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
693 struct nvkm_device *device = subdev->device;
4a8cf451
AC
694 unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000);
695 bool gr_enabled, ctxsw_active, gr_busy;
696
697 do {
698 /*
699 * required to make sure FIFO_ENGINE_STATUS (0x2640) is
700 * up-to-date
701 */
276836d4 702 nvkm_rd32(device, 0x400700);
4a8cf451 703
276836d4
BS
704 gr_enabled = nvkm_rd32(device, 0x200) & 0x1000;
705 ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000;
706 gr_busy = nvkm_rd32(device, 0x40060c) & 0x1;
4a8cf451
AC
707
708 if (!gr_enabled || (!gr_busy && !ctxsw_active))
709 return 0;
710 } while (time_before(jiffies, end_jiffies));
711
109c2f2f
BS
712 nvkm_error(subdev,
713 "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
714 gr_enabled, ctxsw_active, gr_busy);
4a8cf451
AC
715 return -EAGAIN;
716}
717
30f4e087 718void
bfee3f3d 719gf100_gr_mmio(struct gf100_gr *gr, const struct gf100_gr_pack *p)
4b223eef 720{
276836d4 721 struct nvkm_device *device = gr->base.engine.subdev.device;
e3c71eb2
BS
722 const struct gf100_gr_pack *pack;
723 const struct gf100_gr_init *init;
c33b1e8c
BS
724
725 pack_for_each_init(init, pack, p) {
726 u32 next = init->addr + init->count * init->pitch;
727 u32 addr = init->addr;
728 while (addr < next) {
276836d4 729 nvkm_wr32(device, addr, init->data);
30f4e087
BS
730 addr += init->pitch;
731 }
732 }
ebb945a9
BS
733}
734
735void
bfee3f3d 736gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
ebb945a9 737{
276836d4 738 struct nvkm_device *device = gr->base.engine.subdev.device;
e3c71eb2
BS
739 const struct gf100_gr_pack *pack;
740 const struct gf100_gr_init *init;
c33b1e8c 741 u32 data = 0;
30f4e087 742
276836d4 743 nvkm_wr32(device, 0x400208, 0x80000000);
c33b1e8c
BS
744
745 pack_for_each_init(init, pack, p) {
746 u32 next = init->addr + init->count * init->pitch;
747 u32 addr = init->addr;
748
749 if ((pack == p && init == p->init) || data != init->data) {
276836d4 750 nvkm_wr32(device, 0x400204, init->data);
30f4e087
BS
751 data = init->data;
752 }
ebb945a9 753
c33b1e8c 754 while (addr < next) {
276836d4 755 nvkm_wr32(device, 0x400200, addr);
4a8cf451
AC
756 /**
757 * Wait for GR to go idle after submitting a
758 * GO_IDLE bundle
759 */
760 if ((addr & 0xffff) == 0xe100)
bfee3f3d 761 gf100_gr_wait_idle(gr);
c4584adc
BS
762 nvkm_msec(device, 2000,
763 if (!(nvkm_rd32(device, 0x400700) & 0x00000004))
764 break;
765 );
30f4e087 766 addr += init->pitch;
30f4e087
BS
767 }
768 }
c33b1e8c 769
276836d4 770 nvkm_wr32(device, 0x400208, 0x00000000);
30f4e087
BS
771}
772
773void
bfee3f3d 774gf100_gr_mthd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
30f4e087 775{
276836d4 776 struct nvkm_device *device = gr->base.engine.subdev.device;
e3c71eb2
BS
777 const struct gf100_gr_pack *pack;
778 const struct gf100_gr_init *init;
c33b1e8c 779 u32 data = 0;
30f4e087 780
c33b1e8c
BS
781 pack_for_each_init(init, pack, p) {
782 u32 ctrl = 0x80000000 | pack->type;
783 u32 next = init->addr + init->count * init->pitch;
784 u32 addr = init->addr;
785
786 if ((pack == p && init == p->init) || data != init->data) {
276836d4 787 nvkm_wr32(device, 0x40448c, init->data);
c33b1e8c
BS
788 data = init->data;
789 }
790
791 while (addr < next) {
276836d4 792 nvkm_wr32(device, 0x404488, ctrl | (addr << 14));
c33b1e8c 793 addr += init->pitch;
30f4e087
BS
794 }
795 }
796}
797
798u64
bfee3f3d 799gf100_gr_units(struct nvkm_gr *obj)
30f4e087 800{
bfee3f3d 801 struct gf100_gr *gr = container_of(obj, typeof(*gr), base);
30f4e087
BS
802 u64 cfg;
803
bfee3f3d
BS
804 cfg = (u32)gr->gpc_nr;
805 cfg |= (u32)gr->tpc_total << 8;
806 cfg |= (u64)gr->rop_nr << 32;
30f4e087
BS
807
808 return cfg;
ebb945a9
BS
809}
810
109c2f2f
BS
811static const struct nvkm_bitfield gk104_sked_error[] = {
812 { 0x00000080, "CONSTANT_BUFFER_SIZE" },
813 { 0x00000200, "LOCAL_MEMORY_SIZE_POS" },
814 { 0x00000400, "LOCAL_MEMORY_SIZE_NEG" },
815 { 0x00000800, "WARP_CSTACK_SIZE" },
816 { 0x00001000, "TOTAL_TEMP_SIZE" },
817 { 0x00002000, "REGISTER_COUNT" },
818 { 0x00040000, "TOTAL_THREADS" },
819 { 0x00100000, "PROGRAM_OFFSET" },
820 { 0x00200000, "SHARED_MEMORY_SIZE" },
821 { 0x02000000, "SHARED_CONFIG_TOO_SMALL" },
822 { 0x04000000, "TOTAL_REGISTER_COUNT" },
30f4e087
BS
823 {}
824};
825
109c2f2f
BS
826static const struct nvkm_bitfield gf100_gpc_rop_error[] = {
827 { 0x00000002, "RT_PITCH_OVERRUN" },
828 { 0x00000010, "RT_WIDTH_OVERRUN" },
829 { 0x00000020, "RT_HEIGHT_OVERRUN" },
830 { 0x00000080, "ZETA_STORAGE_TYPE_MISMATCH" },
831 { 0x00000100, "RT_STORAGE_TYPE_MISMATCH" },
832 { 0x00000400, "RT_LINEAR_MISMATCH" },
30f4e087
BS
833 {}
834};
835
ebb945a9 836static void
bfee3f3d 837gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc)
ebb945a9 838{
109c2f2f
BS
839 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
840 struct nvkm_device *device = subdev->device;
841 char error[128];
30f4e087 842 u32 trap[4];
ebb945a9 843
109c2f2f 844 trap[0] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0420)) & 0x3fffffff;
276836d4
BS
845 trap[1] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0434));
846 trap[2] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0438));
847 trap[3] = nvkm_rd32(device, GPC_UNIT(gpc, 0x043c));
ebb945a9 848
109c2f2f 849 nvkm_snprintbf(error, sizeof(error), gf100_gpc_rop_error, trap[0]);
30f4e087 850
109c2f2f
BS
851 nvkm_error(subdev, "GPC%d/PROP trap: %08x [%s] x = %u, y = %u, "
852 "format = %x, storage type = %x\n",
853 gpc, trap[0], error, trap[1] & 0xffff, trap[1] >> 16,
854 (trap[2] >> 8) & 0x3f, trap[3] & 0xff);
276836d4 855 nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
ebb945a9
BS
856}
857
e3c71eb2 858static const struct nvkm_enum gf100_mp_warp_error[] = {
fec43a72
BS
859 { 0x00, "NO_ERROR" },
860 { 0x01, "STACK_MISMATCH" },
861 { 0x05, "MISALIGNED_PC" },
862 { 0x08, "MISALIGNED_GPR" },
863 { 0x09, "INVALID_OPCODE" },
864 { 0x0d, "GPR_OUT_OF_BOUNDS" },
865 { 0x0e, "MEM_OUT_OF_BOUNDS" },
866 { 0x0f, "UNALIGNED_MEM_ACCESS" },
867 { 0x11, "INVALID_PARAM" },
868 {}
869};
870
e3c71eb2 871static const struct nvkm_bitfield gf100_mp_global_error[] = {
fec43a72
BS
872 { 0x00000004, "MULTIPLE_WARP_ERRORS" },
873 { 0x00000008, "OUT_OF_STACK_SPACE" },
874 {}
875};
876
877static void
bfee3f3d 878gf100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc)
fec43a72 879{
109c2f2f
BS
880 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
881 struct nvkm_device *device = subdev->device;
276836d4
BS
882 u32 werr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x648));
883 u32 gerr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x650));
109c2f2f
BS
884 const struct nvkm_enum *warp;
885 char glob[128];
fec43a72 886
109c2f2f
BS
887 nvkm_snprintbf(glob, sizeof(glob), gf100_mp_global_error, gerr);
888 warp = nvkm_enum_find(gf100_mp_warp_error, werr & 0xffff);
889
890 nvkm_error(subdev, "GPC%i/TPC%i/MP trap: "
891 "global %08x [%s] warp %04x [%s]\n",
892 gpc, tpc, gerr, glob, werr, warp ? warp->name : "");
fec43a72 893
276836d4
BS
894 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x648), 0x00000000);
895 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x650), gerr);
fec43a72
BS
896}
897
f73221e4 898static void
bfee3f3d 899gf100_gr_trap_tpc(struct gf100_gr *gr, int gpc, int tpc)
f73221e4 900{
109c2f2f
BS
901 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
902 struct nvkm_device *device = subdev->device;
276836d4 903 u32 stat = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0508));
f73221e4
BS
904
905 if (stat & 0x00000001) {
276836d4 906 u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0224));
109c2f2f 907 nvkm_error(subdev, "GPC%d/TPC%d/TEX: %08x\n", gpc, tpc, trap);
276836d4 908 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000);
f73221e4
BS
909 stat &= ~0x00000001;
910 }
911
912 if (stat & 0x00000002) {
bfee3f3d 913 gf100_gr_trap_mp(gr, gpc, tpc);
f73221e4
BS
914 stat &= ~0x00000002;
915 }
916
917 if (stat & 0x00000004) {
276836d4 918 u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0084));
109c2f2f 919 nvkm_error(subdev, "GPC%d/TPC%d/POLY: %08x\n", gpc, tpc, trap);
276836d4 920 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000);
f73221e4
BS
921 stat &= ~0x00000004;
922 }
923
924 if (stat & 0x00000008) {
276836d4 925 u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x048c));
109c2f2f 926 nvkm_error(subdev, "GPC%d/TPC%d/L1C: %08x\n", gpc, tpc, trap);
276836d4 927 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000);
f73221e4
BS
928 stat &= ~0x00000008;
929 }
930
931 if (stat) {
109c2f2f 932 nvkm_error(subdev, "GPC%d/TPC%d/%08x: unknown\n", gpc, tpc, stat);
f73221e4
BS
933 }
934}
935
936static void
bfee3f3d 937gf100_gr_trap_gpc(struct gf100_gr *gr, int gpc)
f73221e4 938{
109c2f2f
BS
939 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
940 struct nvkm_device *device = subdev->device;
276836d4 941 u32 stat = nvkm_rd32(device, GPC_UNIT(gpc, 0x2c90));
f73221e4
BS
942 int tpc;
943
944 if (stat & 0x00000001) {
bfee3f3d 945 gf100_gr_trap_gpc_rop(gr, gpc);
f73221e4
BS
946 stat &= ~0x00000001;
947 }
948
949 if (stat & 0x00000002) {
276836d4 950 u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0900));
109c2f2f 951 nvkm_error(subdev, "GPC%d/ZCULL: %08x\n", gpc, trap);
276836d4 952 nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
f73221e4
BS
953 stat &= ~0x00000002;
954 }
955
956 if (stat & 0x00000004) {
276836d4 957 u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x1028));
109c2f2f 958 nvkm_error(subdev, "GPC%d/CCACHE: %08x\n", gpc, trap);
276836d4 959 nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
f73221e4
BS
960 stat &= ~0x00000004;
961 }
962
963 if (stat & 0x00000008) {
276836d4 964 u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0824));
109c2f2f 965 nvkm_error(subdev, "GPC%d/ESETUP: %08x\n", gpc, trap);
276836d4 966 nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000);
f73221e4
BS
967 stat &= ~0x00000009;
968 }
969
bfee3f3d 970 for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
f73221e4
BS
971 u32 mask = 0x00010000 << tpc;
972 if (stat & mask) {
bfee3f3d 973 gf100_gr_trap_tpc(gr, gpc, tpc);
276836d4 974 nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), mask);
f73221e4
BS
975 stat &= ~mask;
976 }
977 }
978
979 if (stat) {
109c2f2f 980 nvkm_error(subdev, "GPC%d/%08x: unknown\n", gpc, stat);
f73221e4
BS
981 }
982}
983
984static void
bfee3f3d 985gf100_gr_trap_intr(struct gf100_gr *gr)
f73221e4 986{
109c2f2f
BS
987 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
988 struct nvkm_device *device = subdev->device;
276836d4 989 u32 trap = nvkm_rd32(device, 0x400108);
109c2f2f 990 int rop, gpc;
f73221e4
BS
991
992 if (trap & 0x00000001) {
276836d4 993 u32 stat = nvkm_rd32(device, 0x404000);
109c2f2f 994 nvkm_error(subdev, "DISPATCH %08x\n", stat);
276836d4
BS
995 nvkm_wr32(device, 0x404000, 0xc0000000);
996 nvkm_wr32(device, 0x400108, 0x00000001);
f73221e4
BS
997 trap &= ~0x00000001;
998 }
999
1000 if (trap & 0x00000002) {
276836d4 1001 u32 stat = nvkm_rd32(device, 0x404600);
109c2f2f 1002 nvkm_error(subdev, "M2MF %08x\n", stat);
276836d4
BS
1003 nvkm_wr32(device, 0x404600, 0xc0000000);
1004 nvkm_wr32(device, 0x400108, 0x00000002);
f73221e4
BS
1005 trap &= ~0x00000002;
1006 }
1007
1008 if (trap & 0x00000008) {
276836d4 1009 u32 stat = nvkm_rd32(device, 0x408030);
109c2f2f 1010 nvkm_error(subdev, "CCACHE %08x\n", stat);
276836d4
BS
1011 nvkm_wr32(device, 0x408030, 0xc0000000);
1012 nvkm_wr32(device, 0x400108, 0x00000008);
f73221e4
BS
1013 trap &= ~0x00000008;
1014 }
1015
1016 if (trap & 0x00000010) {
276836d4 1017 u32 stat = nvkm_rd32(device, 0x405840);
109c2f2f 1018 nvkm_error(subdev, "SHADER %08x\n", stat);
276836d4
BS
1019 nvkm_wr32(device, 0x405840, 0xc0000000);
1020 nvkm_wr32(device, 0x400108, 0x00000010);
f73221e4
BS
1021 trap &= ~0x00000010;
1022 }
1023
1024 if (trap & 0x00000040) {
276836d4 1025 u32 stat = nvkm_rd32(device, 0x40601c);
109c2f2f 1026 nvkm_error(subdev, "UNK6 %08x\n", stat);
276836d4
BS
1027 nvkm_wr32(device, 0x40601c, 0xc0000000);
1028 nvkm_wr32(device, 0x400108, 0x00000040);
f73221e4
BS
1029 trap &= ~0x00000040;
1030 }
1031
1032 if (trap & 0x00000080) {
276836d4 1033 u32 stat = nvkm_rd32(device, 0x404490);
109c2f2f 1034 nvkm_error(subdev, "MACRO %08x\n", stat);
276836d4
BS
1035 nvkm_wr32(device, 0x404490, 0xc0000000);
1036 nvkm_wr32(device, 0x400108, 0x00000080);
f73221e4
BS
1037 trap &= ~0x00000080;
1038 }
1039
30f4e087 1040 if (trap & 0x00000100) {
109c2f2f
BS
1041 u32 stat = nvkm_rd32(device, 0x407020) & 0x3fffffff;
1042 char sked[128];
30f4e087 1043
109c2f2f
BS
1044 nvkm_snprintbf(sked, sizeof(sked), gk104_sked_error, stat);
1045 nvkm_error(subdev, "SKED: %08x [%s]\n", stat, sked);
30f4e087 1046
109c2f2f 1047 if (stat)
276836d4
BS
1048 nvkm_wr32(device, 0x407020, 0x40000000);
1049 nvkm_wr32(device, 0x400108, 0x00000100);
30f4e087
BS
1050 trap &= ~0x00000100;
1051 }
1052
f73221e4 1053 if (trap & 0x01000000) {
276836d4 1054 u32 stat = nvkm_rd32(device, 0x400118);
bfee3f3d 1055 for (gpc = 0; stat && gpc < gr->gpc_nr; gpc++) {
f73221e4
BS
1056 u32 mask = 0x00000001 << gpc;
1057 if (stat & mask) {
bfee3f3d 1058 gf100_gr_trap_gpc(gr, gpc);
276836d4 1059 nvkm_wr32(device, 0x400118, mask);
f73221e4
BS
1060 stat &= ~mask;
1061 }
1062 }
276836d4 1063 nvkm_wr32(device, 0x400108, 0x01000000);
f73221e4
BS
1064 trap &= ~0x01000000;
1065 }
1066
1067 if (trap & 0x02000000) {
bfee3f3d 1068 for (rop = 0; rop < gr->rop_nr; rop++) {
276836d4
BS
1069 u32 statz = nvkm_rd32(device, ROP_UNIT(rop, 0x070));
1070 u32 statc = nvkm_rd32(device, ROP_UNIT(rop, 0x144));
109c2f2f 1071 nvkm_error(subdev, "ROP%d %08x %08x\n",
f73221e4 1072 rop, statz, statc);
276836d4
BS
1073 nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000);
1074 nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000);
f73221e4 1075 }
276836d4 1076 nvkm_wr32(device, 0x400108, 0x02000000);
f73221e4
BS
1077 trap &= ~0x02000000;
1078 }
1079
1080 if (trap) {
109c2f2f 1081 nvkm_error(subdev, "TRAP UNHANDLED %08x\n", trap);
276836d4 1082 nvkm_wr32(device, 0x400108, trap);
f73221e4
BS
1083 }
1084}
1085
30f4e087 1086static void
bfee3f3d 1087gf100_gr_ctxctl_debug_unit(struct gf100_gr *gr, u32 base)
30f4e087 1088{
109c2f2f
BS
1089 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1090 struct nvkm_device *device = subdev->device;
1091 nvkm_error(subdev, "%06x - done %08x\n", base,
1092 nvkm_rd32(device, base + 0x400));
1093 nvkm_error(subdev, "%06x - stat %08x %08x %08x %08x\n", base,
1094 nvkm_rd32(device, base + 0x800),
1095 nvkm_rd32(device, base + 0x804),
1096 nvkm_rd32(device, base + 0x808),
1097 nvkm_rd32(device, base + 0x80c));
1098 nvkm_error(subdev, "%06x - stat %08x %08x %08x %08x\n", base,
1099 nvkm_rd32(device, base + 0x810),
1100 nvkm_rd32(device, base + 0x814),
1101 nvkm_rd32(device, base + 0x818),
1102 nvkm_rd32(device, base + 0x81c));
30f4e087
BS
1103}
1104
1105void
bfee3f3d 1106gf100_gr_ctxctl_debug(struct gf100_gr *gr)
30f4e087 1107{
276836d4
BS
1108 struct nvkm_device *device = gr->base.engine.subdev.device;
1109 u32 gpcnr = nvkm_rd32(device, 0x409604) & 0xffff;
30f4e087
BS
1110 u32 gpc;
1111
bfee3f3d 1112 gf100_gr_ctxctl_debug_unit(gr, 0x409000);
30f4e087 1113 for (gpc = 0; gpc < gpcnr; gpc++)
bfee3f3d 1114 gf100_gr_ctxctl_debug_unit(gr, 0x502000 + (gpc * 0x8000));
30f4e087
BS
1115}
1116
1117static void
bfee3f3d 1118gf100_gr_ctxctl_isr(struct gf100_gr *gr)
30f4e087 1119{
109c2f2f
BS
1120 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1121 struct nvkm_device *device = subdev->device;
276836d4 1122 u32 stat = nvkm_rd32(device, 0x409c18);
30f4e087 1123
23f67841 1124 if (stat & 0x00000001) {
276836d4 1125 u32 code = nvkm_rd32(device, 0x409814);
23f67841 1126 if (code == E_BAD_FWMTHD) {
276836d4
BS
1127 u32 class = nvkm_rd32(device, 0x409808);
1128 u32 addr = nvkm_rd32(device, 0x40980c);
23f67841
BS
1129 u32 subc = (addr & 0x00070000) >> 16;
1130 u32 mthd = (addr & 0x00003ffc);
276836d4 1131 u32 data = nvkm_rd32(device, 0x409810);
23f67841 1132
109c2f2f
BS
1133 nvkm_error(subdev, "FECS MTHD subc %d class %04x "
1134 "mthd %04x data %08x\n",
1135 subc, class, mthd, data);
23f67841 1136
276836d4 1137 nvkm_wr32(device, 0x409c20, 0x00000001);
23f67841
BS
1138 stat &= ~0x00000001;
1139 } else {
109c2f2f 1140 nvkm_error(subdev, "FECS ucode error %d\n", code);
23f67841
BS
1141 }
1142 }
30f4e087 1143
23f67841 1144 if (stat & 0x00080000) {
109c2f2f 1145 nvkm_error(subdev, "FECS watchdog timeout\n");
bfee3f3d 1146 gf100_gr_ctxctl_debug(gr);
276836d4 1147 nvkm_wr32(device, 0x409c20, 0x00080000);
23f67841
BS
1148 stat &= ~0x00080000;
1149 }
1150
1151 if (stat) {
109c2f2f 1152 nvkm_error(subdev, "FECS %08x\n", stat);
bfee3f3d 1153 gf100_gr_ctxctl_debug(gr);
276836d4 1154 nvkm_wr32(device, 0x409c20, stat);
23f67841 1155 }
30f4e087
BS
1156}
1157
ebb945a9 1158static void
e3c71eb2 1159gf100_gr_intr(struct nvkm_subdev *subdev)
ebb945a9 1160{
276836d4
BS
1161 struct gf100_gr *gr = (void *)subdev;
1162 struct nvkm_device *device = gr->base.engine.subdev.device;
1163 struct nvkm_fifo *fifo = device->fifo;
e3c71eb2
BS
1164 struct nvkm_engine *engine = nv_engine(subdev);
1165 struct nvkm_object *engctx;
1166 struct nvkm_handle *handle;
276836d4
BS
1167 u64 inst = nvkm_rd32(device, 0x409b00) & 0x0fffffff;
1168 u32 stat = nvkm_rd32(device, 0x400100);
1169 u32 addr = nvkm_rd32(device, 0x400704);
ebb945a9
BS
1170 u32 mthd = (addr & 0x00003ffc);
1171 u32 subc = (addr & 0x00070000) >> 16;
276836d4
BS
1172 u32 data = nvkm_rd32(device, 0x400708);
1173 u32 code = nvkm_rd32(device, 0x400110);
91c772ec 1174 u32 class;
72a14827
BS
1175 int chid;
1176
bfee3f3d 1177 if (nv_device(gr)->card_type < NV_E0 || subc < 4)
276836d4 1178 class = nvkm_rd32(device, 0x404200 + (subc * 4));
91c772ec
BS
1179 else
1180 class = 0x0000;
1181
e3c71eb2 1182 engctx = nvkm_engctx_get(engine, inst);
6189f1b0 1183 chid = fifo->chid(fifo, engctx);
ebb945a9 1184
c6a7b026
LP
1185 if (stat & 0x00000001) {
1186 /*
1187 * notifier interrupt, only needed for cyclestats
1188 * can be safely ignored
1189 */
276836d4 1190 nvkm_wr32(device, 0x400100, 0x00000001);
c6a7b026
LP
1191 stat &= ~0x00000001;
1192 }
1193
ebb945a9 1194 if (stat & 0x00000010) {
e3c71eb2 1195 handle = nvkm_handle_get_class(engctx, class);
ebb945a9 1196 if (!handle || nv_call(handle->object, mthd, data)) {
109c2f2f
BS
1197 nvkm_error(subdev, "ILLEGAL_MTHD ch %d [%010llx %s] "
1198 "subc %d class %04x mthd %04x data %08x\n",
1199 chid, inst << 12, nvkm_client_name(engctx),
1200 subc, class, mthd, data);
ebb945a9 1201 }
e3c71eb2 1202 nvkm_handle_put(handle);
276836d4 1203 nvkm_wr32(device, 0x400100, 0x00000010);
ebb945a9
BS
1204 stat &= ~0x00000010;
1205 }
1206
1207 if (stat & 0x00000020) {
109c2f2f
BS
1208 nvkm_error(subdev, "ILLEGAL_CLASS ch %d [%010llx %s] "
1209 "subc %d class %04x mthd %04x data %08x\n",
1210 chid, inst << 12, nvkm_client_name(engctx), subc,
1211 class, mthd, data);
276836d4 1212 nvkm_wr32(device, 0x400100, 0x00000020);
ebb945a9
BS
1213 stat &= ~0x00000020;
1214 }
1215
1216 if (stat & 0x00100000) {
109c2f2f
BS
1217 const struct nvkm_enum *en =
1218 nvkm_enum_find(nv50_data_error_names, code);
1219 nvkm_error(subdev, "DATA_ERROR %08x [%s] ch %d [%010llx %s] "
1220 "subc %d class %04x mthd %04x data %08x\n",
1221 code, en ? en->name : "", chid, inst << 12,
1222 nvkm_client_name(engctx), subc, class, mthd, data);
276836d4 1223 nvkm_wr32(device, 0x400100, 0x00100000);
ebb945a9
BS
1224 stat &= ~0x00100000;
1225 }
1226
1227 if (stat & 0x00200000) {
109c2f2f
BS
1228 nvkm_error(subdev, "TRAP ch %d [%010llx %s]\n",
1229 chid, inst << 12,
1230 nvkm_client_name(engctx));
bfee3f3d 1231 gf100_gr_trap_intr(gr);
276836d4 1232 nvkm_wr32(device, 0x400100, 0x00200000);
ebb945a9
BS
1233 stat &= ~0x00200000;
1234 }
1235
1236 if (stat & 0x00080000) {
bfee3f3d 1237 gf100_gr_ctxctl_isr(gr);
276836d4 1238 nvkm_wr32(device, 0x400100, 0x00080000);
ebb945a9
BS
1239 stat &= ~0x00080000;
1240 }
1241
1242 if (stat) {
109c2f2f 1243 nvkm_error(subdev, "intr %08x\n", stat);
276836d4 1244 nvkm_wr32(device, 0x400100, stat);
ebb945a9
BS
1245 }
1246
276836d4 1247 nvkm_wr32(device, 0x400500, 0x00010001);
e3c71eb2 1248 nvkm_engctx_put(engctx);
ebb945a9
BS
1249}
1250
30f4e087 1251void
bfee3f3d 1252gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
e3c71eb2 1253 struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
ebb945a9 1254{
276836d4 1255 struct nvkm_device *device = gr->base.engine.subdev.device;
30f4e087 1256 int i;
ebb945a9 1257
276836d4 1258 nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000);
30f4e087 1259 for (i = 0; i < data->size / 4; i++)
276836d4 1260 nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]);
ebb945a9 1261
276836d4 1262 nvkm_wr32(device, fuc_base + 0x0180, 0x01000000);
30f4e087
BS
1263 for (i = 0; i < code->size / 4; i++) {
1264 if ((i & 0x3f) == 0)
276836d4
BS
1265 nvkm_wr32(device, fuc_base + 0x0188, i >> 6);
1266 nvkm_wr32(device, fuc_base + 0x0184, code->data[i]);
30f4e087 1267 }
370eec76
AC
1268
1269 /* code must be padded to 0x40 words */
1270 for (; i & 0x3f; i++)
276836d4 1271 nvkm_wr32(device, fuc_base + 0x0184, 0);
966a5b7d
BS
1272}
1273
a32b2ffb 1274static void
bfee3f3d 1275gf100_gr_init_csdata(struct gf100_gr *gr,
e3c71eb2
BS
1276 const struct gf100_gr_pack *pack,
1277 u32 falcon, u32 starstar, u32 base)
a32b2ffb 1278{
276836d4 1279 struct nvkm_device *device = gr->base.engine.subdev.device;
e3c71eb2
BS
1280 const struct gf100_gr_pack *iter;
1281 const struct gf100_gr_init *init;
c33b1e8c 1282 u32 addr = ~0, prev = ~0, xfer = 0;
a32b2ffb
BS
1283 u32 star, temp;
1284
276836d4
BS
1285 nvkm_wr32(device, falcon + 0x01c0, 0x02000000 + starstar);
1286 star = nvkm_rd32(device, falcon + 0x01c4);
1287 temp = nvkm_rd32(device, falcon + 0x01c4);
a32b2ffb
BS
1288 if (temp > star)
1289 star = temp;
276836d4 1290 nvkm_wr32(device, falcon + 0x01c0, 0x01000000 + star);
a32b2ffb 1291
c33b1e8c
BS
1292 pack_for_each_init(init, iter, pack) {
1293 u32 head = init->addr - base;
1294 u32 tail = head + init->count * init->pitch;
1295 while (head < tail) {
1296 if (head != prev + 4 || xfer >= 32) {
1297 if (xfer) {
1298 u32 data = ((--xfer << 26) | addr);
276836d4 1299 nvkm_wr32(device, falcon + 0x01c4, data);
c33b1e8c
BS
1300 star += 4;
1301 }
1302 addr = head;
1303 xfer = 0;
a32b2ffb 1304 }
c33b1e8c
BS
1305 prev = head;
1306 xfer = xfer + 1;
1307 head = head + init->pitch;
a32b2ffb 1308 }
c33b1e8c 1309 }
a32b2ffb 1310
276836d4
BS
1311 nvkm_wr32(device, falcon + 0x01c4, (--xfer << 26) | addr);
1312 nvkm_wr32(device, falcon + 0x01c0, 0x01000004 + starstar);
1313 nvkm_wr32(device, falcon + 0x01c4, star + 4);
a32b2ffb
BS
1314}
1315
30f4e087 1316int
bfee3f3d 1317gf100_gr_init_ctxctl(struct gf100_gr *gr)
966a5b7d 1318{
109c2f2f
BS
1319 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1320 struct nvkm_device *device = subdev->device;
bfee3f3d
BS
1321 struct gf100_gr_oclass *oclass = (void *)nv_object(gr)->oclass;
1322 struct gf100_grctx_oclass *cclass = (void *)nv_engine(gr)->cclass;
30f4e087 1323 int i;
ebb945a9 1324
bfee3f3d 1325 if (gr->firmware) {
30f4e087 1326 /* load fuc microcode */
bfee3f3d
BS
1327 nvkm_mc(gr)->unk260(nvkm_mc(gr), 0);
1328 gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c,
1329 &gr->fuc409d);
1330 gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac,
1331 &gr->fuc41ad);
1332 nvkm_mc(gr)->unk260(nvkm_mc(gr), 1);
ebb945a9 1333
30f4e087 1334 /* start both of them running */
276836d4
BS
1335 nvkm_wr32(device, 0x409840, 0xffffffff);
1336 nvkm_wr32(device, 0x41a10c, 0x00000000);
1337 nvkm_wr32(device, 0x40910c, 0x00000000);
1338 nvkm_wr32(device, 0x41a100, 0x00000002);
1339 nvkm_wr32(device, 0x409100, 0x00000002);
c4584adc
BS
1340 if (nvkm_msec(device, 2000,
1341 if (nvkm_rd32(device, 0x409800) & 0x00000001)
1342 break;
1343 ) < 0)
1344 return -EBUSY;
bfee3f3d 1345
276836d4
BS
1346 nvkm_wr32(device, 0x409840, 0xffffffff);
1347 nvkm_wr32(device, 0x409500, 0x7fffffff);
1348 nvkm_wr32(device, 0x409504, 0x00000021);
bfee3f3d 1349
276836d4
BS
1350 nvkm_wr32(device, 0x409840, 0xffffffff);
1351 nvkm_wr32(device, 0x409500, 0x00000000);
1352 nvkm_wr32(device, 0x409504, 0x00000010);
c4584adc
BS
1353 if (nvkm_msec(device, 2000,
1354 if ((gr->size = nvkm_rd32(device, 0x409800)))
1355 break;
1356 ) < 0)
30f4e087 1357 return -EBUSY;
0411de85 1358
276836d4
BS
1359 nvkm_wr32(device, 0x409840, 0xffffffff);
1360 nvkm_wr32(device, 0x409500, 0x00000000);
1361 nvkm_wr32(device, 0x409504, 0x00000016);
c4584adc
BS
1362 if (nvkm_msec(device, 2000,
1363 if (nvkm_rd32(device, 0x409800))
1364 break;
1365 ) < 0)
ac1499d9 1366 return -EBUSY;
ac1499d9 1367
276836d4
BS
1368 nvkm_wr32(device, 0x409840, 0xffffffff);
1369 nvkm_wr32(device, 0x409500, 0x00000000);
1370 nvkm_wr32(device, 0x409504, 0x00000025);
c4584adc
BS
1371 if (nvkm_msec(device, 2000,
1372 if (nvkm_rd32(device, 0x409800))
1373 break;
1374 ) < 0)
ac1499d9 1375 return -EBUSY;
ac1499d9 1376
bfee3f3d 1377 if (nv_device(gr)->chipset >= 0xe0) {
276836d4
BS
1378 nvkm_wr32(device, 0x409800, 0x00000000);
1379 nvkm_wr32(device, 0x409500, 0x00000001);
1380 nvkm_wr32(device, 0x409504, 0x00000030);
c4584adc
BS
1381 if (nvkm_msec(device, 2000,
1382 if (nvkm_rd32(device, 0x409800))
1383 break;
1384 ) < 0)
30f4e087 1385 return -EBUSY;
30f4e087 1386
276836d4
BS
1387 nvkm_wr32(device, 0x409810, 0xb00095c8);
1388 nvkm_wr32(device, 0x409800, 0x00000000);
1389 nvkm_wr32(device, 0x409500, 0x00000001);
1390 nvkm_wr32(device, 0x409504, 0x00000031);
c4584adc
BS
1391 if (nvkm_msec(device, 2000,
1392 if (nvkm_rd32(device, 0x409800))
1393 break;
1394 ) < 0)
30f4e087 1395 return -EBUSY;
30f4e087 1396
276836d4
BS
1397 nvkm_wr32(device, 0x409810, 0x00080420);
1398 nvkm_wr32(device, 0x409800, 0x00000000);
1399 nvkm_wr32(device, 0x409500, 0x00000001);
1400 nvkm_wr32(device, 0x409504, 0x00000032);
c4584adc
BS
1401 if (nvkm_msec(device, 2000,
1402 if (nvkm_rd32(device, 0x409800))
1403 break;
1404 ) < 0)
30f4e087 1405 return -EBUSY;
30f4e087 1406
276836d4
BS
1407 nvkm_wr32(device, 0x409614, 0x00000070);
1408 nvkm_wr32(device, 0x409614, 0x00000770);
1409 nvkm_wr32(device, 0x40802c, 0x00000001);
30f4e087
BS
1410 }
1411
bfee3f3d
BS
1412 if (gr->data == NULL) {
1413 int ret = gf100_grctx_generate(gr);
ebb945a9 1414 if (ret) {
109c2f2f 1415 nvkm_error(subdev, "failed to construct context\n");
ebb945a9
BS
1416 return ret;
1417 }
1418 }
1419
1420 return 0;
96616b4c
BS
1421 } else
1422 if (!oclass->fecs.ucode) {
1423 return -ENOSYS;
0411de85 1424 }
966a5b7d 1425
ac1499d9 1426 /* load HUB microcode */
bfee3f3d 1427 nvkm_mc(gr)->unk260(nvkm_mc(gr), 0);
276836d4 1428 nvkm_wr32(device, 0x4091c0, 0x01000000);
30f4e087 1429 for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
276836d4 1430 nvkm_wr32(device, 0x4091c4, oclass->fecs.ucode->data.data[i]);
ac1499d9 1431
276836d4 1432 nvkm_wr32(device, 0x409180, 0x01000000);
30f4e087 1433 for (i = 0; i < oclass->fecs.ucode->code.size / 4; i++) {
ac1499d9 1434 if ((i & 0x3f) == 0)
276836d4
BS
1435 nvkm_wr32(device, 0x409188, i >> 6);
1436 nvkm_wr32(device, 0x409184, oclass->fecs.ucode->code.data[i]);
ac1499d9
BS
1437 }
1438
1439 /* load GPC microcode */
276836d4 1440 nvkm_wr32(device, 0x41a1c0, 0x01000000);
30f4e087 1441 for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++)
276836d4 1442 nvkm_wr32(device, 0x41a1c4, oclass->gpccs.ucode->data.data[i]);
ac1499d9 1443
276836d4 1444 nvkm_wr32(device, 0x41a180, 0x01000000);
30f4e087 1445 for (i = 0; i < oclass->gpccs.ucode->code.size / 4; i++) {
ac1499d9 1446 if ((i & 0x3f) == 0)
276836d4
BS
1447 nvkm_wr32(device, 0x41a188, i >> 6);
1448 nvkm_wr32(device, 0x41a184, oclass->gpccs.ucode->code.data[i]);
ac1499d9 1449 }
bfee3f3d 1450 nvkm_mc(gr)->unk260(nvkm_mc(gr), 1);
966a5b7d 1451
c33b1e8c 1452 /* load register lists */
bfee3f3d
BS
1453 gf100_gr_init_csdata(gr, cclass->hub, 0x409000, 0x000, 0x000000);
1454 gf100_gr_init_csdata(gr, cclass->gpc, 0x41a000, 0x000, 0x418000);
1455 gf100_gr_init_csdata(gr, cclass->tpc, 0x41a000, 0x004, 0x419800);
1456 gf100_gr_init_csdata(gr, cclass->ppc, 0x41a000, 0x008, 0x41be00);
a32b2ffb 1457
ac1499d9 1458 /* start HUB ucode running, it'll init the GPCs */
276836d4
BS
1459 nvkm_wr32(device, 0x40910c, 0x00000000);
1460 nvkm_wr32(device, 0x409100, 0x00000002);
c4584adc
BS
1461 if (nvkm_msec(device, 2000,
1462 if (nvkm_rd32(device, 0x409800) & 0x80000000)
1463 break;
1464 ) < 0) {
bfee3f3d 1465 gf100_gr_ctxctl_debug(gr);
966a5b7d
BS
1466 return -EBUSY;
1467 }
966a5b7d 1468
276836d4 1469 gr->size = nvkm_rd32(device, 0x409804);
bfee3f3d
BS
1470 if (gr->data == NULL) {
1471 int ret = gf100_grctx_generate(gr);
ac1499d9 1472 if (ret) {
109c2f2f 1473 nvkm_error(subdev, "failed to construct context\n");
ac1499d9
BS
1474 return ret;
1475 }
966a5b7d
BS
1476 }
1477
1478 return 0;
4b223eef
BS
1479}
1480
30f4e087 1481int
e3c71eb2 1482gf100_gr_init(struct nvkm_object *object)
4b223eef 1483{
bfee3f3d 1484 struct gf100_gr *gr = (void *)object;
276836d4
BS
1485 struct nvkm_device *device = gr->base.engine.subdev.device;
1486 struct gf100_gr_oclass *oclass = (void *)object->oclass;
bfee3f3d 1487 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
30f4e087
BS
1488 u32 data[TPC_MAX / 8] = {};
1489 u8 tpcnr[GPC_MAX];
1490 int gpc, tpc, rop;
1491 int ret, i;
966a5b7d 1492
bfee3f3d 1493 ret = nvkm_gr_init(&gr->base);
ebb945a9
BS
1494 if (ret)
1495 return ret;
1496
276836d4
BS
1497 nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000);
1498 nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000);
1499 nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000);
1500 nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000);
1501 nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
1502 nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
227c95d9
BS
1503 nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8);
1504 nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8);
30f4e087 1505
bfee3f3d 1506 gf100_gr_mmio(gr, oclass->mmio);
30f4e087 1507
bfee3f3d
BS
1508 memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr));
1509 for (i = 0, gpc = -1; i < gr->tpc_total; i++) {
30f4e087 1510 do {
bfee3f3d 1511 gpc = (gpc + 1) % gr->gpc_nr;
30f4e087 1512 } while (!tpcnr[gpc]);
bfee3f3d 1513 tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--;
30f4e087
BS
1514
1515 data[i / 8] |= tpc << ((i % 8) * 4);
1516 }
1517
276836d4
BS
1518 nvkm_wr32(device, GPC_BCAST(0x0980), data[0]);
1519 nvkm_wr32(device, GPC_BCAST(0x0984), data[1]);
1520 nvkm_wr32(device, GPC_BCAST(0x0988), data[2]);
1521 nvkm_wr32(device, GPC_BCAST(0x098c), data[3]);
30f4e087 1522
bfee3f3d 1523 for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
276836d4 1524 nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
bfee3f3d 1525 gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
276836d4 1526 nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
bfee3f3d 1527 gr->tpc_total);
276836d4 1528 nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
30f4e087
BS
1529 }
1530
bfee3f3d 1531 if (nv_device(gr)->chipset != 0xd7)
276836d4 1532 nvkm_wr32(device, GPC_BCAST(0x1bd4), magicgpc918);
26410c67 1533 else
276836d4 1534 nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918);
bfee3f3d 1535
276836d4 1536 nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800));
bfee3f3d 1537
276836d4 1538 nvkm_wr32(device, 0x400500, 0x00010001);
bfee3f3d 1539
276836d4
BS
1540 nvkm_wr32(device, 0x400100, 0xffffffff);
1541 nvkm_wr32(device, 0x40013c, 0xffffffff);
bfee3f3d 1542
276836d4
BS
1543 nvkm_wr32(device, 0x409c24, 0x000f0000);
1544 nvkm_wr32(device, 0x404000, 0xc0000000);
1545 nvkm_wr32(device, 0x404600, 0xc0000000);
1546 nvkm_wr32(device, 0x408030, 0xc0000000);
1547 nvkm_wr32(device, 0x40601c, 0xc0000000);
1548 nvkm_wr32(device, 0x404490, 0xc0000000);
1549 nvkm_wr32(device, 0x406018, 0xc0000000);
1550 nvkm_wr32(device, 0x405840, 0xc0000000);
1551 nvkm_wr32(device, 0x405844, 0x00ffffff);
1552 nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008);
1553 nvkm_mask(device, 0x419eb4, 0x00001000, 0x00001000);
bfee3f3d
BS
1554
1555 for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
276836d4
BS
1556 nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
1557 nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
1558 nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
1559 nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000);
bfee3f3d 1560 for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
276836d4
BS
1561 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
1562 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
1563 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
1564 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
1565 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
1566 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
1567 nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
30f4e087 1568 }
276836d4
BS
1569 nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
1570 nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
30f4e087
BS
1571 }
1572
bfee3f3d 1573 for (rop = 0; rop < gr->rop_nr; rop++) {
276836d4
BS
1574 nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000);
1575 nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000);
1576 nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff);
1577 nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff);
30f4e087 1578 }
ebb945a9 1579
276836d4
BS
1580 nvkm_wr32(device, 0x400108, 0xffffffff);
1581 nvkm_wr32(device, 0x400138, 0xffffffff);
1582 nvkm_wr32(device, 0x400118, 0xffffffff);
1583 nvkm_wr32(device, 0x400130, 0xffffffff);
1584 nvkm_wr32(device, 0x40011c, 0xffffffff);
1585 nvkm_wr32(device, 0x400134, 0xffffffff);
30f4e087 1586
276836d4 1587 nvkm_wr32(device, 0x400054, 0x34ce3464);
ac9738bb 1588
bfee3f3d 1589 gf100_gr_zbc_init(gr);
ac9738bb 1590
bfee3f3d 1591 return gf100_gr_init_ctxctl(gr);
30f4e087
BS
1592}
1593
c4d0f8f6 1594void
e3c71eb2 1595gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc)
30f4e087
BS
1596{
1597 kfree(fuc->data);
1598 fuc->data = NULL;
1599}
1600
1601int
bfee3f3d 1602gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
e3c71eb2 1603 struct gf100_gr_fuc *fuc)
30f4e087 1604{
109c2f2f
BS
1605 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1606 struct nvkm_device *device = subdev->device;
30f4e087 1607 const struct firmware *fw;
8539b37a
AC
1608 char f[64];
1609 char cname[16];
30f4e087 1610 int ret;
8539b37a
AC
1611 int i;
1612
1613 /* Convert device name to lowercase */
6cf813fb 1614 strncpy(cname, device->chip->name, sizeof(cname));
8539b37a
AC
1615 cname[sizeof(cname) - 1] = '\0';
1616 i = strlen(cname);
1617 while (i) {
1618 --i;
1619 cname[i] = tolower(cname[i]);
1620 }
30f4e087 1621
8539b37a 1622 snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
420b9469 1623 ret = request_firmware(&fw, f, nv_device_base(device));
30f4e087 1624 if (ret) {
109c2f2f 1625 nvkm_error(subdev, "failed to load %s\n", fwname);
8539b37a 1626 return ret;
30f4e087
BS
1627 }
1628
1629 fuc->size = fw->size;
1630 fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
1631 release_firmware(fw);
1632 return (fuc->data != NULL) ? 0 : -ENOMEM;
1633}
1634
1635void
e3c71eb2 1636gf100_gr_dtor(struct nvkm_object *object)
30f4e087 1637{
bfee3f3d 1638 struct gf100_gr *gr = (void *)object;
30f4e087 1639
bfee3f3d 1640 kfree(gr->data);
30f4e087 1641
bfee3f3d
BS
1642 gf100_gr_dtor_fw(&gr->fuc409c);
1643 gf100_gr_dtor_fw(&gr->fuc409d);
1644 gf100_gr_dtor_fw(&gr->fuc41ac);
1645 gf100_gr_dtor_fw(&gr->fuc41ad);
30f4e087 1646
227c95d9
BS
1647 nvkm_memory_del(&gr->unk4188b8);
1648 nvkm_memory_del(&gr->unk4188b4);
30f4e087 1649
bfee3f3d 1650 nvkm_gr_destroy(&gr->base);
30f4e087
BS
1651}
1652
1653int
e3c71eb2
BS
1654gf100_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
1655 struct nvkm_oclass *bclass, void *data, u32 size,
1656 struct nvkm_object **pobject)
30f4e087 1657{
e3c71eb2 1658 struct gf100_gr_oclass *oclass = (void *)bclass;
109c2f2f 1659 struct nvkm_device *device = (void *)parent;
bfee3f3d 1660 struct gf100_gr *gr;
b7c852a6 1661 bool use_ext_fw, enable;
b81146b0 1662 int ret, i, j;
30f4e087 1663
e3c71eb2
BS
1664 use_ext_fw = nvkm_boolopt(device->cfgopt, "NvGrUseFW",
1665 oclass->fecs.ucode == NULL);
b7c852a6
AC
1666 enable = use_ext_fw || oclass->fecs.ucode != NULL;
1667
bfee3f3d
BS
1668 ret = nvkm_gr_create(parent, engine, bclass, enable, &gr);
1669 *pobject = nv_object(gr);
30f4e087
BS
1670 if (ret)
1671 return ret;
1672
bfee3f3d
BS
1673 nv_subdev(gr)->unit = 0x08001000;
1674 nv_subdev(gr)->intr = gf100_gr_intr;
30f4e087 1675
bfee3f3d 1676 gr->base.units = gf100_gr_units;
30f4e087 1677
b7c852a6 1678 if (use_ext_fw) {
109c2f2f 1679 nvkm_info(&gr->base.engine.subdev, "using external firmware\n");
bfee3f3d
BS
1680 if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fuc409c) ||
1681 gf100_gr_ctor_fw(gr, "fecs_data", &gr->fuc409d) ||
1682 gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->fuc41ac) ||
1683 gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad))
c6f37e0c 1684 return -ENODEV;
bfee3f3d 1685 gr->firmware = true;
30f4e087
BS
1686 }
1687
227c95d9 1688 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false,
bfee3f3d 1689 &gr->unk4188b4);
30f4e087
BS
1690 if (ret)
1691 return ret;
ebb945a9 1692
227c95d9 1693 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false,
bfee3f3d 1694 &gr->unk4188b8);
b10f20d5 1695 if (ret)
a82dd49f
BS
1696 return ret;
1697
142ea05f
BS
1698 nvkm_kmap(gr->unk4188b4);
1699 for (i = 0; i < 0x1000; i += 4)
1700 nvkm_wo32(gr->unk4188b4, i, 0x00000010);
1701 nvkm_done(gr->unk4188b4);
1702
1703 nvkm_kmap(gr->unk4188b8);
1704 for (i = 0; i < 0x1000; i += 4)
1705 nvkm_wo32(gr->unk4188b8, i, 0x00000010);
1706 nvkm_done(gr->unk4188b8);
bfee3f3d 1707
276836d4
BS
1708 gr->rop_nr = (nvkm_rd32(device, 0x409604) & 0x001f0000) >> 16;
1709 gr->gpc_nr = nvkm_rd32(device, 0x409604) & 0x0000001f;
bfee3f3d 1710 for (i = 0; i < gr->gpc_nr; i++) {
276836d4 1711 gr->tpc_nr[i] = nvkm_rd32(device, GPC_UNIT(i, 0x2608));
bfee3f3d
BS
1712 gr->tpc_total += gr->tpc_nr[i];
1713 gr->ppc_nr[i] = oclass->ppc_nr;
1714 for (j = 0; j < gr->ppc_nr[i]; j++) {
276836d4 1715 u8 mask = nvkm_rd32(device, GPC_UNIT(i, 0x0c30 + (j * 4)));
bfee3f3d 1716 gr->ppc_tpc_nr[i][j] = hweight8(mask);
b81146b0 1717 }
30f4e087
BS
1718 }
1719
1720 /*XXX: these need figuring out... though it might not even matter */
bfee3f3d 1721 switch (nv_device(gr)->chipset) {
30f4e087 1722 case 0xc0:
bfee3f3d
BS
1723 if (gr->tpc_total == 11) { /* 465, 3/4/4/0, 4 */
1724 gr->magic_not_rop_nr = 0x07;
30f4e087 1725 } else
bfee3f3d
BS
1726 if (gr->tpc_total == 14) { /* 470, 3/3/4/4, 5 */
1727 gr->magic_not_rop_nr = 0x05;
30f4e087 1728 } else
bfee3f3d
BS
1729 if (gr->tpc_total == 15) { /* 480, 3/4/4/4, 6 */
1730 gr->magic_not_rop_nr = 0x06;
30f4e087
BS
1731 }
1732 break;
1733 case 0xc3: /* 450, 4/0/0/0, 2 */
bfee3f3d 1734 gr->magic_not_rop_nr = 0x03;
30f4e087
BS
1735 break;
1736 case 0xc4: /* 460, 3/4/0/0, 4 */
bfee3f3d 1737 gr->magic_not_rop_nr = 0x01;
30f4e087
BS
1738 break;
1739 case 0xc1: /* 2/0/0/0, 1 */
bfee3f3d 1740 gr->magic_not_rop_nr = 0x01;
30f4e087
BS
1741 break;
1742 case 0xc8: /* 4/4/3/4, 5 */
bfee3f3d 1743 gr->magic_not_rop_nr = 0x06;
30f4e087
BS
1744 break;
1745 case 0xce: /* 4/4/0/0, 4 */
bfee3f3d 1746 gr->magic_not_rop_nr = 0x03;
30f4e087
BS
1747 break;
1748 case 0xcf: /* 4/0/0/0, 3 */
bfee3f3d 1749 gr->magic_not_rop_nr = 0x03;
30f4e087 1750 break;
26410c67 1751 case 0xd7:
30f4e087 1752 case 0xd9: /* 1/0/0/0, 1 */
c4d0f8f6 1753 case 0xea: /* gk20a */
a032fb9d 1754 case 0x12b: /* gm20b */
bfee3f3d 1755 gr->magic_not_rop_nr = 0x01;
30f4e087
BS
1756 break;
1757 }
1758
bfee3f3d
BS
1759 nv_engine(gr)->cclass = *oclass->cclass;
1760 nv_engine(gr)->sclass = oclass->sclass;
4b223eef
BS
1761 return 0;
1762}
1763
e3c71eb2 1764#include "fuc/hubgf100.fuc3.h"
30f4e087 1765
e3c71eb2
BS
1766struct gf100_gr_ucode
1767gf100_gr_fecs_ucode = {
1768 .code.data = gf100_grhub_code,
1769 .code.size = sizeof(gf100_grhub_code),
1770 .data.data = gf100_grhub_data,
1771 .data.size = sizeof(gf100_grhub_data),
30f4e087
BS
1772};
1773
e3c71eb2 1774#include "fuc/gpcgf100.fuc3.h"
30f4e087 1775
e3c71eb2
BS
1776struct gf100_gr_ucode
1777gf100_gr_gpccs_ucode = {
1778 .code.data = gf100_grgpc_code,
1779 .code.size = sizeof(gf100_grgpc_code),
1780 .data.data = gf100_grgpc_data,
1781 .data.size = sizeof(gf100_grgpc_data),
30f4e087
BS
1782};
1783
e3c71eb2
BS
1784struct nvkm_oclass *
1785gf100_gr_oclass = &(struct gf100_gr_oclass) {
30f4e087 1786 .base.handle = NV_ENGINE(GR, 0xc0),
e3c71eb2
BS
1787 .base.ofuncs = &(struct nvkm_ofuncs) {
1788 .ctor = gf100_gr_ctor,
1789 .dtor = gf100_gr_dtor,
1790 .init = gf100_gr_init,
1791 .fini = _nvkm_gr_fini,
ebb945a9 1792 },
e3c71eb2
BS
1793 .cclass = &gf100_grctx_oclass,
1794 .sclass = gf100_gr_sclass,
1795 .mmio = gf100_gr_pack_mmio,
1796 .fecs.ucode = &gf100_gr_fecs_ucode,
1797 .gpccs.ucode = &gf100_gr_gpccs_ucode,
30f4e087 1798}.base;
This page took 0.607671 seconds and 5 git commands to generate.