gf100.c 48.6 KB
Newer Older
1
/*
2
 * Copyright 2012 Red Hat Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs
 */
24 25 26 27 28 29 30 31 32 33 34 35 36 37
#include "gf100.h"
#include "ctxgf100.h"
#include "fuc/os.h"

#include <core/client.h>
#include <core/handle.h>
#include <core/option.h>
#include <engine/fifo.h>
#include <subdev/fb.h>
#include <subdev/mc.h>
#include <subdev/timer.h>

#include <nvif/class.h>
#include <nvif/unpack.h>
38

39 40 41 42 43
/*******************************************************************************
 * Zero Bandwidth Clear
 ******************************************************************************/

static void
B
Ben Skeggs 已提交
44
gf100_gr_zbc_clear_color(struct gf100_gr *gr, int zbc)
45
{
46
	struct nvkm_device *device = gr->base.engine.subdev.device;
B
Ben Skeggs 已提交
47
	if (gr->zbc_color[zbc].format) {
48 49 50 51 52 53 54 55
		nvkm_wr32(device, 0x405804, gr->zbc_color[zbc].ds[0]);
		nvkm_wr32(device, 0x405808, gr->zbc_color[zbc].ds[1]);
		nvkm_wr32(device, 0x40580c, gr->zbc_color[zbc].ds[2]);
		nvkm_wr32(device, 0x405810, gr->zbc_color[zbc].ds[3]);
	}
	nvkm_wr32(device, 0x405814, gr->zbc_color[zbc].format);
	nvkm_wr32(device, 0x405820, zbc);
	nvkm_wr32(device, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */
56 57 58
}

static int
B
Ben Skeggs 已提交
59
gf100_gr_zbc_color_get(struct gf100_gr *gr, int format,
60
		       const u32 ds[4], const u32 l2[4])
61
{
B
Ben Skeggs 已提交
62
	struct nvkm_ltc *ltc = nvkm_ltc(gr);
63 64 65
	int zbc = -ENOSPC, i;

	for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
B
Ben Skeggs 已提交
66 67
		if (gr->zbc_color[i].format) {
			if (gr->zbc_color[i].format != format)
68
				continue;
B
Ben Skeggs 已提交
69 70
			if (memcmp(gr->zbc_color[i].ds, ds, sizeof(
				   gr->zbc_color[i].ds)))
71
				continue;
B
Ben Skeggs 已提交
72 73
			if (memcmp(gr->zbc_color[i].l2, l2, sizeof(
				   gr->zbc_color[i].l2))) {
74 75 76 77 78 79 80 81 82
				WARN_ON(1);
				return -EINVAL;
			}
			return i;
		} else {
			zbc = (zbc < 0) ? i : zbc;
		}
	}

83 84 85
	if (zbc < 0)
		return zbc;

B
Ben Skeggs 已提交
86 87 88
	memcpy(gr->zbc_color[zbc].ds, ds, sizeof(gr->zbc_color[zbc].ds));
	memcpy(gr->zbc_color[zbc].l2, l2, sizeof(gr->zbc_color[zbc].l2));
	gr->zbc_color[zbc].format = format;
89
	ltc->zbc_color_get(ltc, zbc, l2);
B
Ben Skeggs 已提交
90
	gf100_gr_zbc_clear_color(gr, zbc);
91 92 93 94
	return zbc;
}

static void
B
Ben Skeggs 已提交
95
gf100_gr_zbc_clear_depth(struct gf100_gr *gr, int zbc)
96
{
97
	struct nvkm_device *device = gr->base.engine.subdev.device;
B
Ben Skeggs 已提交
98
	if (gr->zbc_depth[zbc].format)
99 100 101 102
		nvkm_wr32(device, 0x405818, gr->zbc_depth[zbc].ds);
	nvkm_wr32(device, 0x40581c, gr->zbc_depth[zbc].format);
	nvkm_wr32(device, 0x405820, zbc);
	nvkm_wr32(device, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */
103 104 105
}

static int
B
Ben Skeggs 已提交
106
gf100_gr_zbc_depth_get(struct gf100_gr *gr, int format,
107
		       const u32 ds, const u32 l2)
108
{
B
Ben Skeggs 已提交
109
	struct nvkm_ltc *ltc = nvkm_ltc(gr);
110 111 112
	int zbc = -ENOSPC, i;

	for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
B
Ben Skeggs 已提交
113 114
		if (gr->zbc_depth[i].format) {
			if (gr->zbc_depth[i].format != format)
115
				continue;
B
Ben Skeggs 已提交
116
			if (gr->zbc_depth[i].ds != ds)
117
				continue;
B
Ben Skeggs 已提交
118
			if (gr->zbc_depth[i].l2 != l2) {
119 120 121 122 123 124 125 126 127
				WARN_ON(1);
				return -EINVAL;
			}
			return i;
		} else {
			zbc = (zbc < 0) ? i : zbc;
		}
	}

128 129 130
	if (zbc < 0)
		return zbc;

B
Ben Skeggs 已提交
131 132 133
	gr->zbc_depth[zbc].format = format;
	gr->zbc_depth[zbc].ds = ds;
	gr->zbc_depth[zbc].l2 = l2;
134
	ltc->zbc_depth_get(ltc, zbc, l2);
B
Ben Skeggs 已提交
135
	gf100_gr_zbc_clear_depth(gr, zbc);
136 137 138
	return zbc;
}

139 140 141 142
/*******************************************************************************
 * Graphics object classes
 ******************************************************************************/

143
static int
144
gf100_fermi_mthd_zbc_color(struct nvkm_object *object, void *data, u32 size)
145
{
B
Ben Skeggs 已提交
146
	struct gf100_gr *gr = (void *)object->engine;
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
	union {
		struct fermi_a_zbc_color_v0 v0;
	} *args = data;
	int ret;

	if (nvif_unpack(args->v0, 0, 0, false)) {
		switch (args->v0.format) {
		case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
		case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
		case FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32:
		case FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16:
		case FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16:
		case FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16:
		case FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16:
		case FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16:
		case FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8:
		case FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8:
		case FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10:
		case FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10:
		case FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8:
		case FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8:
		case FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8:
		case FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8:
		case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8:
		case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10:
		case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11:
B
Ben Skeggs 已提交
173
			ret = gf100_gr_zbc_color_get(gr, args->v0.format,
174 175
							   args->v0.ds,
							   args->v0.l2);
176 177 178 179 180 181 182 183 184 185 186 187 188 189
			if (ret >= 0) {
				args->v0.index = ret;
				return 0;
			}
			break;
		default:
			return -EINVAL;
		}
	}

	return ret;
}

static int
190
gf100_fermi_mthd_zbc_depth(struct nvkm_object *object, void *data, u32 size)
191
{
B
Ben Skeggs 已提交
192
	struct gf100_gr *gr = (void *)object->engine;
193 194 195 196 197 198 199 200
	union {
		struct fermi_a_zbc_depth_v0 v0;
	} *args = data;
	int ret;

	if (nvif_unpack(args->v0, 0, 0, false)) {
		switch (args->v0.format) {
		case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
B
Ben Skeggs 已提交
201
			ret = gf100_gr_zbc_depth_get(gr, args->v0.format,
202 203
							   args->v0.ds,
							   args->v0.l2);
204 205 206 207 208 209 210 211 212 213
			return (ret >= 0) ? 0 : -ENOSPC;
		default:
			return -EINVAL;
		}
	}

	return ret;
}

static int
214
gf100_fermi_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
215 216 217
{
	switch (mthd) {
	case FERMI_A_ZBC_COLOR:
218
		return gf100_fermi_mthd_zbc_color(object, data, size);
219
	case FERMI_A_ZBC_DEPTH:
220
		return gf100_fermi_mthd_zbc_depth(object, data, size);
221 222 223 224 225 226
	default:
		break;
	}
	return -EINVAL;
}

227 228 229 230
struct nvkm_ofuncs
gf100_fermi_ofuncs = {
	.ctor = _nvkm_object_ctor,
	.dtor = nvkm_object_destroy,
231 232
	.init = _nvkm_object_init,
	.fini = _nvkm_object_fini,
233
	.mthd = gf100_fermi_mthd,
234 235
};

236
static int
237 238
gf100_gr_set_shader_exceptions(struct nvkm_object *object, u32 mthd,
			       void *pdata, u32 size)
239
{
B
Ben Skeggs 已提交
240
	struct gf100_gr *gr = (void *)object->engine;
241
	struct nvkm_device *device = gr->base.engine.subdev.device;
242 243
	if (size >= sizeof(u32)) {
		u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
244 245
		nvkm_wr32(device, 0x419e44, data);
		nvkm_wr32(device, 0x419e4c, data);
246 247 248 249 250
		return 0;
	}
	return -EINVAL;
}

251 252 253
struct nvkm_omthds
gf100_gr_9097_omthds[] = {
	{ 0x1528, 0x1528, gf100_gr_set_shader_exceptions },
254 255 256
	{}
};

257 258 259
struct nvkm_omthds
gf100_gr_90c0_omthds[] = {
	{ 0x1528, 0x1528, gf100_gr_set_shader_exceptions },
260 261 262
	{}
};

263 264
struct nvkm_oclass
gf100_gr_sclass[] = {
265 266
	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
	{ FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs },
267 268
	{ FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
	{ FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
269 270 271 272 273 274
	{}
};

/*******************************************************************************
 * PGRAPH context
 ******************************************************************************/
275

276
int
277 278 279
gf100_gr_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
		      struct nvkm_oclass *oclass, void *args, u32 size,
		      struct nvkm_object **pobject)
280
{
281
	struct nvkm_vm *vm = nvkm_client(parent)->vm;
B
Ben Skeggs 已提交
282 283 284
	struct gf100_gr *gr = (void *)engine;
	struct gf100_gr_data *data = gr->mmio_data;
	struct gf100_gr_mmio *mmio = gr->mmio_list;
285
	struct gf100_gr_chan *chan;
286
	struct nvkm_device *device = gr->base.engine.subdev.device;
287
	struct nvkm_gpuobj *image;
288 289
	int ret, i;

290
	/* allocate memory for context, and fill with default values */
291
	ret = nvkm_gr_context_create(parent, engine, oclass, NULL,
B
Ben Skeggs 已提交
292
				     gr->size, 0x100,
293
				     NVOBJ_FLAG_ZERO_ALLOC, &chan);
294
	*pobject = nv_object(chan);
295 296 297
	if (ret)
		return ret;

298 299 300 301
	/* allocate memory for a "mmio list" buffer that's used by the HUB
	 * fuc to modify some per-context register settings on first load
	 * of the context.
	 */
302 303
	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x100,
			      false, &chan->mmio);
304 305 306
	if (ret)
		return ret;

307 308
	ret = nvkm_vm_get(vm, 0x1000, 12, NV_MEM_ACCESS_RW |
			  NV_MEM_ACCESS_SYS, &chan->mmio_vma);
309 310 311
	if (ret)
		return ret;

312 313
	nvkm_memory_map(chan->mmio, &chan->mmio_vma, 0);

314
	/* allocate buffers referenced by mmio list */
B
Ben Skeggs 已提交
315
	for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) {
316 317 318
		ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
				      data->size, data->align, false,
				      &chan->data[i].mem);
319 320
		if (ret)
			return ret;
321

322 323
		ret = nvkm_vm_get(vm, nvkm_memory_size(chan->data[i].mem),
				  12, data->access, &chan->data[i].vma);
324 325
		if (ret)
			return ret;
326

327
		nvkm_memory_map(chan->data[i].mem, &chan->data[i].vma, 0);
328
		data++;
329 330
	}

331
	/* finally, fill in the mmio list and point the context at it */
332
	nvkm_kmap(chan->mmio);
B
Ben Skeggs 已提交
333
	for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) {
334 335
		u32 addr = mmio->addr;
		u32 data = mmio->data;
336

337
		if (mmio->buffer >= 0) {
338
			u64 info = chan->data[mmio->buffer].vma.offset;
339 340
			data |= info >> mmio->shift;
		}
341

342 343
		nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr);
		nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data);
344 345
		mmio++;
	}
346
	nvkm_done(chan->mmio);
347

348 349
	image = &chan->base.base.gpuobj;
	nvkm_kmap(image);
B
Ben Skeggs 已提交
350
	for (i = 0; i < gr->size; i += 4)
351
		nvkm_wo32(image, i, gr->data[i / 4]);
352

B
Ben Skeggs 已提交
353
	if (!gr->firmware) {
354 355
		nvkm_wo32(image, 0x00, chan->mmio_nr / 2);
		nvkm_wo32(image, 0x04, chan->mmio_vma.offset >> 8);
356
	} else {
357 358 359 360 361 362 363 364 365
		nvkm_wo32(image, 0xf4, 0);
		nvkm_wo32(image, 0xf8, 0);
		nvkm_wo32(image, 0x10, chan->mmio_nr / 2);
		nvkm_wo32(image, 0x14, lower_32_bits(chan->mmio_vma.offset));
		nvkm_wo32(image, 0x18, upper_32_bits(chan->mmio_vma.offset));
		nvkm_wo32(image, 0x1c, 1);
		nvkm_wo32(image, 0x20, 0);
		nvkm_wo32(image, 0x28, 0);
		nvkm_wo32(image, 0x2c, 0);
366
	}
367
	nvkm_done(image);
368

369
	return 0;
370 371
}

372
void
373
gf100_gr_context_dtor(struct nvkm_object *object)
374
{
375
	struct gf100_gr_chan *chan = (void *)object;
376 377
	int i;

378
	for (i = 0; i < ARRAY_SIZE(chan->data); i++) {
379 380 381 382 383
		if (chan->data[i].vma.node) {
			nvkm_vm_unmap(&chan->data[i].vma);
			nvkm_vm_put(&chan->data[i].vma);
		}
		nvkm_memory_del(&chan->data[i].mem);
384
	}
385

386 387 388 389 390
	if (chan->mmio_vma.node) {
		nvkm_vm_unmap(&chan->mmio_vma);
		nvkm_vm_put(&chan->mmio_vma);
	}
	nvkm_memory_del(&chan->mmio);
391

392
	nvkm_gr_context_destroy(&chan->base);
393 394
}

395
/*******************************************************************************
396
 * PGRAPH register lists
397 398
 ******************************************************************************/

399 400
const struct gf100_gr_init
gf100_gr_init_main_0[] = {
401 402 403 404 405 406 407 408 409 410 411 412 413 414
	{ 0x400080,   1, 0x04, 0x003083c2 },
	{ 0x400088,   1, 0x04, 0x00006fe7 },
	{ 0x40008c,   1, 0x04, 0x00000000 },
	{ 0x400090,   1, 0x04, 0x00000030 },
	{ 0x40013c,   1, 0x04, 0x013901f7 },
	{ 0x400140,   1, 0x04, 0x00000100 },
	{ 0x400144,   1, 0x04, 0x00000000 },
	{ 0x400148,   1, 0x04, 0x00000110 },
	{ 0x400138,   1, 0x04, 0x00000000 },
	{ 0x400130,   2, 0x04, 0x00000000 },
	{ 0x400124,   1, 0x04, 0x00000002 },
	{}
};

415 416
const struct gf100_gr_init
gf100_gr_init_fe_0[] = {
417 418 419 420 421
	{ 0x40415c,   1, 0x04, 0x00000000 },
	{ 0x404170,   1, 0x04, 0x00000000 },
	{}
};

422 423
const struct gf100_gr_init
gf100_gr_init_pri_0[] = {
424 425 426 427
	{ 0x404488,   2, 0x04, 0x00000000 },
	{}
};

428 429
const struct gf100_gr_init
gf100_gr_init_rstr2d_0[] = {
430 431 432 433
	{ 0x407808,   1, 0x04, 0x00000000 },
	{}
};

434 435
const struct gf100_gr_init
gf100_gr_init_pd_0[] = {
436 437 438 439
	{ 0x406024,   1, 0x04, 0x00000000 },
	{}
};

440 441
const struct gf100_gr_init
gf100_gr_init_ds_0[] = {
442 443 444 445 446 447
	{ 0x405844,   1, 0x04, 0x00ffffff },
	{ 0x405850,   1, 0x04, 0x00000000 },
	{ 0x405908,   1, 0x04, 0x00000000 },
	{}
};

448 449
const struct gf100_gr_init
gf100_gr_init_scc_0[] = {
450 451 452 453
	{ 0x40803c,   1, 0x04, 0x00000000 },
	{}
};

454 455
const struct gf100_gr_init
gf100_gr_init_prop_0[] = {
456
	{ 0x4184a0,   1, 0x04, 0x00000000 },
457 458 459
	{}
};

460 461
const struct gf100_gr_init
gf100_gr_init_gpc_unk_0[] = {
462 463 464 465
	{ 0x418604,   1, 0x04, 0x00000000 },
	{ 0x418680,   1, 0x04, 0x00000000 },
	{ 0x418714,   1, 0x04, 0x80000000 },
	{ 0x418384,   1, 0x04, 0x00000000 },
466 467 468
	{}
};

469 470
const struct gf100_gr_init
gf100_gr_init_setup_0[] = {
471
	{ 0x418814,   3, 0x04, 0x00000000 },
472 473 474
	{}
};

475 476
const struct gf100_gr_init
gf100_gr_init_crstr_0[] = {
477
	{ 0x418b04,   1, 0x04, 0x00000000 },
478 479 480
	{}
};

481 482
const struct gf100_gr_init
gf100_gr_init_setup_1[] = {
483 484 485 486
	{ 0x4188c8,   1, 0x04, 0x80000000 },
	{ 0x4188cc,   1, 0x04, 0x00000000 },
	{ 0x4188d0,   1, 0x04, 0x00010000 },
	{ 0x4188d4,   1, 0x04, 0x00000001 },
487 488 489
	{}
};

490 491
const struct gf100_gr_init
gf100_gr_init_zcull_0[] = {
492 493 494 495 496
	{ 0x418910,   1, 0x04, 0x00010001 },
	{ 0x418914,   1, 0x04, 0x00000301 },
	{ 0x418918,   1, 0x04, 0x00800000 },
	{ 0x418980,   1, 0x04, 0x77777770 },
	{ 0x418984,   3, 0x04, 0x77777777 },
497 498 499
	{}
};

500 501
const struct gf100_gr_init
gf100_gr_init_gpm_0[] = {
502 503
	{ 0x418c04,   1, 0x04, 0x00000000 },
	{ 0x418c88,   1, 0x04, 0x00000000 },
504 505 506
	{}
};

507 508
const struct gf100_gr_init
gf100_gr_init_gpc_unk_1[] = {
509 510 511 512
	{ 0x418d00,   1, 0x04, 0x00000000 },
	{ 0x418f08,   1, 0x04, 0x00000000 },
	{ 0x418e00,   1, 0x04, 0x00000050 },
	{ 0x418e08,   1, 0x04, 0x00000000 },
513 514 515
	{}
};

516 517
const struct gf100_gr_init
gf100_gr_init_gcc_0[] = {
518 519 520 521 522
	{ 0x41900c,   1, 0x04, 0x00000000 },
	{ 0x419018,   1, 0x04, 0x00000000 },
	{}
};

523 524
const struct gf100_gr_init
gf100_gr_init_tpccs_0[] = {
525 526
	{ 0x419d08,   2, 0x04, 0x00000000 },
	{ 0x419d10,   1, 0x04, 0x00000014 },
527 528 529
	{}
};

530 531
const struct gf100_gr_init
gf100_gr_init_tex_0[] = {
532 533 534
	{ 0x419ab0,   1, 0x04, 0x00000000 },
	{ 0x419ab8,   1, 0x04, 0x000000e7 },
	{ 0x419abc,   2, 0x04, 0x00000000 },
535 536 537
	{}
};

538 539
const struct gf100_gr_init
gf100_gr_init_pe_0[] = {
540 541 542 543
	{ 0x41980c,   3, 0x04, 0x00000000 },
	{ 0x419844,   1, 0x04, 0x00000000 },
	{ 0x41984c,   1, 0x04, 0x00005bc5 },
	{ 0x419850,   4, 0x04, 0x00000000 },
544 545 546
	{}
};

547 548
const struct gf100_gr_init
gf100_gr_init_l1c_0[] = {
549 550 551 552 553 554
	{ 0x419c98,   1, 0x04, 0x00000000 },
	{ 0x419ca8,   1, 0x04, 0x80000000 },
	{ 0x419cb4,   1, 0x04, 0x00000000 },
	{ 0x419cb8,   1, 0x04, 0x00008bf4 },
	{ 0x419cbc,   1, 0x04, 0x28137606 },
	{ 0x419cc0,   2, 0x04, 0x00000000 },
555 556 557
	{}
};

558 559
const struct gf100_gr_init
gf100_gr_init_wwdx_0[] = {
560 561
	{ 0x419bd4,   1, 0x04, 0x00800000 },
	{ 0x419bdc,   1, 0x04, 0x00000000 },
562 563 564
	{}
};

565 566
const struct gf100_gr_init
gf100_gr_init_tpccs_1[] = {
567
	{ 0x419d2c,   1, 0x04, 0x00000000 },
568 569 570
	{}
};

571 572
const struct gf100_gr_init
gf100_gr_init_mpc_0[] = {
573
	{ 0x419c0c,   1, 0x04, 0x00000000 },
574 575 576
	{}
};

577 578
static const struct gf100_gr_init
gf100_gr_init_sm_0[] = {
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
	{ 0x419e00,   1, 0x04, 0x00000000 },
	{ 0x419ea0,   1, 0x04, 0x00000000 },
	{ 0x419ea4,   1, 0x04, 0x00000100 },
	{ 0x419ea8,   1, 0x04, 0x00001100 },
	{ 0x419eac,   1, 0x04, 0x11100702 },
	{ 0x419eb0,   1, 0x04, 0x00000003 },
	{ 0x419eb4,   4, 0x04, 0x00000000 },
	{ 0x419ec8,   1, 0x04, 0x06060618 },
	{ 0x419ed0,   1, 0x04, 0x0eff0e38 },
	{ 0x419ed4,   1, 0x04, 0x011104f1 },
	{ 0x419edc,   1, 0x04, 0x00000000 },
	{ 0x419f00,   1, 0x04, 0x00000000 },
	{ 0x419f2c,   1, 0x04, 0x00000000 },
	{}
};

595 596
const struct gf100_gr_init
gf100_gr_init_be_0[] = {
597 598 599 600 601 602 603 604 605 606
	{ 0x40880c,   1, 0x04, 0x00000000 },
	{ 0x408910,   9, 0x04, 0x00000000 },
	{ 0x408950,   1, 0x04, 0x00000000 },
	{ 0x408954,   1, 0x04, 0x0000ffff },
	{ 0x408984,   1, 0x04, 0x00000000 },
	{ 0x408988,   1, 0x04, 0x08040201 },
	{ 0x40898c,   1, 0x04, 0x80402010 },
	{}
};

607 608
const struct gf100_gr_init
gf100_gr_init_fe_1[] = {
609 610 611 612
	{ 0x4040f0,   1, 0x04, 0x00000000 },
	{}
};

613 614
const struct gf100_gr_init
gf100_gr_init_pe_1[] = {
615 616 617 618
	{ 0x419880,   1, 0x04, 0x00000002 },
	{}
};

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
static const struct gf100_gr_pack
gf100_gr_pack_mmio[] = {
	{ gf100_gr_init_main_0 },
	{ gf100_gr_init_fe_0 },
	{ gf100_gr_init_pri_0 },
	{ gf100_gr_init_rstr2d_0 },
	{ gf100_gr_init_pd_0 },
	{ gf100_gr_init_ds_0 },
	{ gf100_gr_init_scc_0 },
	{ gf100_gr_init_prop_0 },
	{ gf100_gr_init_gpc_unk_0 },
	{ gf100_gr_init_setup_0 },
	{ gf100_gr_init_crstr_0 },
	{ gf100_gr_init_setup_1 },
	{ gf100_gr_init_zcull_0 },
	{ gf100_gr_init_gpm_0 },
	{ gf100_gr_init_gpc_unk_1 },
	{ gf100_gr_init_gcc_0 },
	{ gf100_gr_init_tpccs_0 },
	{ gf100_gr_init_tex_0 },
	{ gf100_gr_init_pe_0 },
	{ gf100_gr_init_l1c_0 },
	{ gf100_gr_init_wwdx_0 },
	{ gf100_gr_init_tpccs_1 },
	{ gf100_gr_init_mpc_0 },
	{ gf100_gr_init_sm_0 },
	{ gf100_gr_init_be_0 },
	{ gf100_gr_init_fe_1 },
	{ gf100_gr_init_pe_1 },
M
Maarten Lankhorst 已提交
648 649 650
	{}
};

651 652 653 654
/*******************************************************************************
 * PGRAPH engine/subdev functions
 ******************************************************************************/

655
void
B
Ben Skeggs 已提交
656
gf100_gr_zbc_init(struct gf100_gr *gr)
657 658 659 660 661 662 663 664 665
{
	const u32  zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
			      0x00000000, 0x00000000, 0x00000000, 0x00000000 };
	const u32   one[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
			      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
	const u32 f32_0[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
			      0x00000000, 0x00000000, 0x00000000, 0x00000000 };
	const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
			      0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
B
Ben Skeggs 已提交
666
	struct nvkm_ltc *ltc = nvkm_ltc(gr);
667 668
	int index;

B
Ben Skeggs 已提交
669 670 671 672 673 674 675
	if (!gr->zbc_color[0].format) {
		gf100_gr_zbc_color_get(gr, 1,  & zero[0],   &zero[4]);
		gf100_gr_zbc_color_get(gr, 2,  &  one[0],    &one[4]);
		gf100_gr_zbc_color_get(gr, 4,  &f32_0[0],  &f32_0[4]);
		gf100_gr_zbc_color_get(gr, 4,  &f32_1[0],  &f32_1[4]);
		gf100_gr_zbc_depth_get(gr, 1, 0x00000000, 0x00000000);
		gf100_gr_zbc_depth_get(gr, 1, 0x3f800000, 0x3f800000);
676 677 678
	}

	for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
B
Ben Skeggs 已提交
679
		gf100_gr_zbc_clear_color(gr, index);
680
	for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
B
Ben Skeggs 已提交
681
		gf100_gr_zbc_clear_depth(gr, index);
682 683
}

684 685 686 687 688 689
/**
 * Wait until GR goes idle. GR is considered idle if it is disabled by the
 * MC (0x200) register, or GR is not busy and a context switch is not in
 * progress.
 */
int
B
Ben Skeggs 已提交
690
gf100_gr_wait_idle(struct gf100_gr *gr)
691
{
692 693
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
694 695 696 697 698 699 700 701
	unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000);
	bool gr_enabled, ctxsw_active, gr_busy;

	do {
		/*
		 * required to make sure FIFO_ENGINE_STATUS (0x2640) is
		 * up-to-date
		 */
702
		nvkm_rd32(device, 0x400700);
703

704 705 706
		gr_enabled = nvkm_rd32(device, 0x200) & 0x1000;
		ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000;
		gr_busy = nvkm_rd32(device, 0x40060c) & 0x1;
707 708 709 710 711

		if (!gr_enabled || (!gr_busy && !ctxsw_active))
			return 0;
	} while (time_before(jiffies, end_jiffies));

712 713 714
	nvkm_error(subdev,
		   "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
		   gr_enabled, ctxsw_active, gr_busy);
715 716 717
	return -EAGAIN;
}

718
void
B
Ben Skeggs 已提交
719
gf100_gr_mmio(struct gf100_gr *gr, const struct gf100_gr_pack *p)
720
{
721
	struct nvkm_device *device = gr->base.engine.subdev.device;
722 723
	const struct gf100_gr_pack *pack;
	const struct gf100_gr_init *init;
724 725 726 727 728

	pack_for_each_init(init, pack, p) {
		u32 next = init->addr + init->count * init->pitch;
		u32 addr = init->addr;
		while (addr < next) {
729
			nvkm_wr32(device, addr, init->data);
730 731 732
			addr += init->pitch;
		}
	}
733 734 735
}

void
B
Ben Skeggs 已提交
736
gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
737
{
738
	struct nvkm_device *device = gr->base.engine.subdev.device;
739 740
	const struct gf100_gr_pack *pack;
	const struct gf100_gr_init *init;
741
	u32 data = 0;
742

743
	nvkm_wr32(device, 0x400208, 0x80000000);
744 745 746 747 748 749

	pack_for_each_init(init, pack, p) {
		u32 next = init->addr + init->count * init->pitch;
		u32 addr = init->addr;

		if ((pack == p && init == p->init) || data != init->data) {
750
			nvkm_wr32(device, 0x400204, init->data);
751 752
			data = init->data;
		}
753

754
		while (addr < next) {
755
			nvkm_wr32(device, 0x400200, addr);
756 757 758 759 760
			/**
			 * Wait for GR to go idle after submitting a
			 * GO_IDLE bundle
			 */
			if ((addr & 0xffff) == 0xe100)
B
Ben Skeggs 已提交
761
				gf100_gr_wait_idle(gr);
762 763 764 765
			nvkm_msec(device, 2000,
				if (!(nvkm_rd32(device, 0x400700) & 0x00000004))
					break;
			);
766 767 768
			addr += init->pitch;
		}
	}
769

770
	nvkm_wr32(device, 0x400208, 0x00000000);
771 772 773
}

void
B
Ben Skeggs 已提交
774
gf100_gr_mthd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
775
{
776
	struct nvkm_device *device = gr->base.engine.subdev.device;
777 778
	const struct gf100_gr_pack *pack;
	const struct gf100_gr_init *init;
779
	u32 data = 0;
780

781 782 783 784 785 786
	pack_for_each_init(init, pack, p) {
		u32 ctrl = 0x80000000 | pack->type;
		u32 next = init->addr + init->count * init->pitch;
		u32 addr = init->addr;

		if ((pack == p && init == p->init) || data != init->data) {
787
			nvkm_wr32(device, 0x40448c, init->data);
788 789 790 791
			data = init->data;
		}

		while (addr < next) {
792
			nvkm_wr32(device, 0x404488, ctrl | (addr << 14));
793
			addr += init->pitch;
794 795 796 797 798
		}
	}
}

u64
B
Ben Skeggs 已提交
799
gf100_gr_units(struct nvkm_gr *obj)
800
{
B
Ben Skeggs 已提交
801
	struct gf100_gr *gr = container_of(obj, typeof(*gr), base);
802 803
	u64 cfg;

B
Ben Skeggs 已提交
804 805 806
	cfg  = (u32)gr->gpc_nr;
	cfg |= (u32)gr->tpc_total << 8;
	cfg |= (u64)gr->rop_nr << 32;
807 808

	return cfg;
809 810
}

811 812 813 814 815 816 817 818 819 820 821 822
static const struct nvkm_bitfield gk104_sked_error[] = {
	{ 0x00000080, "CONSTANT_BUFFER_SIZE" },
	{ 0x00000200, "LOCAL_MEMORY_SIZE_POS" },
	{ 0x00000400, "LOCAL_MEMORY_SIZE_NEG" },
	{ 0x00000800, "WARP_CSTACK_SIZE" },
	{ 0x00001000, "TOTAL_TEMP_SIZE" },
	{ 0x00002000, "REGISTER_COUNT" },
	{ 0x00040000, "TOTAL_THREADS" },
	{ 0x00100000, "PROGRAM_OFFSET" },
	{ 0x00200000, "SHARED_MEMORY_SIZE" },
	{ 0x02000000, "SHARED_CONFIG_TOO_SMALL" },
	{ 0x04000000, "TOTAL_REGISTER_COUNT" },
823 824 825
	{}
};

826 827 828 829 830 831 832
static const struct nvkm_bitfield gf100_gpc_rop_error[] = {
	{ 0x00000002, "RT_PITCH_OVERRUN" },
	{ 0x00000010, "RT_WIDTH_OVERRUN" },
	{ 0x00000020, "RT_HEIGHT_OVERRUN" },
	{ 0x00000080, "ZETA_STORAGE_TYPE_MISMATCH" },
	{ 0x00000100, "RT_STORAGE_TYPE_MISMATCH" },
	{ 0x00000400, "RT_LINEAR_MISMATCH" },
833 834 835
	{}
};

836
static void
B
Ben Skeggs 已提交
837
gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc)
838
{
839 840 841
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	char error[128];
842
	u32 trap[4];
843

844
	trap[0] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0420)) & 0x3fffffff;
845 846 847
	trap[1] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0434));
	trap[2] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0438));
	trap[3] = nvkm_rd32(device, GPC_UNIT(gpc, 0x043c));
848

849
	nvkm_snprintbf(error, sizeof(error), gf100_gpc_rop_error, trap[0]);
850

851 852 853 854
	nvkm_error(subdev, "GPC%d/PROP trap: %08x [%s] x = %u, y = %u, "
			   "format = %x, storage type = %x\n",
		   gpc, trap[0], error, trap[1] & 0xffff, trap[1] >> 16,
		   (trap[2] >> 8) & 0x3f, trap[3] & 0xff);
855
	nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
856 857
}

858
static const struct nvkm_enum gf100_mp_warp_error[] = {
859 860 861 862 863 864 865 866 867 868 869 870
	{ 0x00, "NO_ERROR" },
	{ 0x01, "STACK_MISMATCH" },
	{ 0x05, "MISALIGNED_PC" },
	{ 0x08, "MISALIGNED_GPR" },
	{ 0x09, "INVALID_OPCODE" },
	{ 0x0d, "GPR_OUT_OF_BOUNDS" },
	{ 0x0e, "MEM_OUT_OF_BOUNDS" },
	{ 0x0f, "UNALIGNED_MEM_ACCESS" },
	{ 0x11, "INVALID_PARAM" },
	{}
};

871
static const struct nvkm_bitfield gf100_mp_global_error[] = {
872 873 874 875 876 877
	{ 0x00000004, "MULTIPLE_WARP_ERRORS" },
	{ 0x00000008, "OUT_OF_STACK_SPACE" },
	{}
};

static void
B
Ben Skeggs 已提交
878
gf100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc)
879
{
880 881
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
882 883
	u32 werr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x648));
	u32 gerr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x650));
884 885
	const struct nvkm_enum *warp;
	char glob[128];
886

887 888 889 890 891 892
	nvkm_snprintbf(glob, sizeof(glob), gf100_mp_global_error, gerr);
	warp = nvkm_enum_find(gf100_mp_warp_error, werr & 0xffff);

	nvkm_error(subdev, "GPC%i/TPC%i/MP trap: "
			   "global %08x [%s] warp %04x [%s]\n",
		   gpc, tpc, gerr, glob, werr, warp ? warp->name : "");
893

894 895
	nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x648), 0x00000000);
	nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x650), gerr);
896 897
}

898
static void
B
Ben Skeggs 已提交
899
gf100_gr_trap_tpc(struct gf100_gr *gr, int gpc, int tpc)
900
{
901 902
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
903
	u32 stat = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0508));
904 905

	if (stat & 0x00000001) {
906
		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0224));
907
		nvkm_error(subdev, "GPC%d/TPC%d/TEX: %08x\n", gpc, tpc, trap);
908
		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000);
909 910 911 912
		stat &= ~0x00000001;
	}

	if (stat & 0x00000002) {
B
Ben Skeggs 已提交
913
		gf100_gr_trap_mp(gr, gpc, tpc);
914 915 916 917
		stat &= ~0x00000002;
	}

	if (stat & 0x00000004) {
918
		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0084));
919
		nvkm_error(subdev, "GPC%d/TPC%d/POLY: %08x\n", gpc, tpc, trap);
920
		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000);
921 922 923 924
		stat &= ~0x00000004;
	}

	if (stat & 0x00000008) {
925
		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x048c));
926
		nvkm_error(subdev, "GPC%d/TPC%d/L1C: %08x\n", gpc, tpc, trap);
927
		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000);
928 929 930 931
		stat &= ~0x00000008;
	}

	if (stat) {
932
		nvkm_error(subdev, "GPC%d/TPC%d/%08x: unknown\n", gpc, tpc, stat);
933 934 935 936
	}
}

static void
B
Ben Skeggs 已提交
937
gf100_gr_trap_gpc(struct gf100_gr *gr, int gpc)
938
{
939 940
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
941
	u32 stat = nvkm_rd32(device, GPC_UNIT(gpc, 0x2c90));
942 943 944
	int tpc;

	if (stat & 0x00000001) {
B
Ben Skeggs 已提交
945
		gf100_gr_trap_gpc_rop(gr, gpc);
946 947 948 949
		stat &= ~0x00000001;
	}

	if (stat & 0x00000002) {
950
		u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0900));
951
		nvkm_error(subdev, "GPC%d/ZCULL: %08x\n", gpc, trap);
952
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
953 954 955 956
		stat &= ~0x00000002;
	}

	if (stat & 0x00000004) {
957
		u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x1028));
958
		nvkm_error(subdev, "GPC%d/CCACHE: %08x\n", gpc, trap);
959
		nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
960 961 962 963
		stat &= ~0x00000004;
	}

	if (stat & 0x00000008) {
964
		u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0824));
965
		nvkm_error(subdev, "GPC%d/ESETUP: %08x\n", gpc, trap);
966
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000);
967 968 969
		stat &= ~0x00000009;
	}

B
Ben Skeggs 已提交
970
	for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
971 972
		u32 mask = 0x00010000 << tpc;
		if (stat & mask) {
B
Ben Skeggs 已提交
973
			gf100_gr_trap_tpc(gr, gpc, tpc);
974
			nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), mask);
975 976 977 978 979
			stat &= ~mask;
		}
	}

	if (stat) {
980
		nvkm_error(subdev, "GPC%d/%08x: unknown\n", gpc, stat);
981 982 983 984
	}
}

static void
B
Ben Skeggs 已提交
985
gf100_gr_trap_intr(struct gf100_gr *gr)
986
{
987 988
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
989
	u32 trap = nvkm_rd32(device, 0x400108);
990
	int rop, gpc;
991 992

	if (trap & 0x00000001) {
993
		u32 stat = nvkm_rd32(device, 0x404000);
994
		nvkm_error(subdev, "DISPATCH %08x\n", stat);
995 996
		nvkm_wr32(device, 0x404000, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000001);
997 998 999 1000
		trap &= ~0x00000001;
	}

	if (trap & 0x00000002) {
1001
		u32 stat = nvkm_rd32(device, 0x404600);
1002
		nvkm_error(subdev, "M2MF %08x\n", stat);
1003 1004
		nvkm_wr32(device, 0x404600, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000002);
1005 1006 1007 1008
		trap &= ~0x00000002;
	}

	if (trap & 0x00000008) {
1009
		u32 stat = nvkm_rd32(device, 0x408030);
1010
		nvkm_error(subdev, "CCACHE %08x\n", stat);
1011 1012
		nvkm_wr32(device, 0x408030, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000008);
1013 1014 1015 1016
		trap &= ~0x00000008;
	}

	if (trap & 0x00000010) {
1017
		u32 stat = nvkm_rd32(device, 0x405840);
1018
		nvkm_error(subdev, "SHADER %08x\n", stat);
1019 1020
		nvkm_wr32(device, 0x405840, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000010);
1021 1022 1023 1024
		trap &= ~0x00000010;
	}

	if (trap & 0x00000040) {
1025
		u32 stat = nvkm_rd32(device, 0x40601c);
1026
		nvkm_error(subdev, "UNK6 %08x\n", stat);
1027 1028
		nvkm_wr32(device, 0x40601c, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000040);
1029 1030 1031 1032
		trap &= ~0x00000040;
	}

	if (trap & 0x00000080) {
1033
		u32 stat = nvkm_rd32(device, 0x404490);
1034
		nvkm_error(subdev, "MACRO %08x\n", stat);
1035 1036
		nvkm_wr32(device, 0x404490, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000080);
1037 1038 1039
		trap &= ~0x00000080;
	}

1040
	if (trap & 0x00000100) {
1041 1042
		u32 stat = nvkm_rd32(device, 0x407020) & 0x3fffffff;
		char sked[128];
1043

1044 1045
		nvkm_snprintbf(sked, sizeof(sked), gk104_sked_error, stat);
		nvkm_error(subdev, "SKED: %08x [%s]\n", stat, sked);
1046

1047
		if (stat)
1048 1049
			nvkm_wr32(device, 0x407020, 0x40000000);
		nvkm_wr32(device, 0x400108, 0x00000100);
1050 1051 1052
		trap &= ~0x00000100;
	}

1053
	if (trap & 0x01000000) {
1054
		u32 stat = nvkm_rd32(device, 0x400118);
B
Ben Skeggs 已提交
1055
		for (gpc = 0; stat && gpc < gr->gpc_nr; gpc++) {
1056 1057
			u32 mask = 0x00000001 << gpc;
			if (stat & mask) {
B
Ben Skeggs 已提交
1058
				gf100_gr_trap_gpc(gr, gpc);
1059
				nvkm_wr32(device, 0x400118, mask);
1060 1061 1062
				stat &= ~mask;
			}
		}
1063
		nvkm_wr32(device, 0x400108, 0x01000000);
1064 1065 1066 1067
		trap &= ~0x01000000;
	}

	if (trap & 0x02000000) {
B
Ben Skeggs 已提交
1068
		for (rop = 0; rop < gr->rop_nr; rop++) {
1069 1070
			u32 statz = nvkm_rd32(device, ROP_UNIT(rop, 0x070));
			u32 statc = nvkm_rd32(device, ROP_UNIT(rop, 0x144));
1071
			nvkm_error(subdev, "ROP%d %08x %08x\n",
1072
				 rop, statz, statc);
1073 1074
			nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000);
			nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000);
1075
		}
1076
		nvkm_wr32(device, 0x400108, 0x02000000);
1077 1078 1079 1080
		trap &= ~0x02000000;
	}

	if (trap) {
1081
		nvkm_error(subdev, "TRAP UNHANDLED %08x\n", trap);
1082
		nvkm_wr32(device, 0x400108, trap);
1083 1084 1085
	}
}

1086
static void
B
Ben Skeggs 已提交
1087
gf100_gr_ctxctl_debug_unit(struct gf100_gr *gr, u32 base)
1088
{
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	nvkm_error(subdev, "%06x - done %08x\n", base,
		   nvkm_rd32(device, base + 0x400));
	nvkm_error(subdev, "%06x - stat %08x %08x %08x %08x\n", base,
		   nvkm_rd32(device, base + 0x800),
		   nvkm_rd32(device, base + 0x804),
		   nvkm_rd32(device, base + 0x808),
		   nvkm_rd32(device, base + 0x80c));
	nvkm_error(subdev, "%06x - stat %08x %08x %08x %08x\n", base,
		   nvkm_rd32(device, base + 0x810),
		   nvkm_rd32(device, base + 0x814),
		   nvkm_rd32(device, base + 0x818),
		   nvkm_rd32(device, base + 0x81c));
1103 1104 1105
}

void
B
Ben Skeggs 已提交
1106
gf100_gr_ctxctl_debug(struct gf100_gr *gr)
1107
{
1108 1109
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 gpcnr = nvkm_rd32(device, 0x409604) & 0xffff;
1110 1111
	u32 gpc;

B
Ben Skeggs 已提交
1112
	gf100_gr_ctxctl_debug_unit(gr, 0x409000);
1113
	for (gpc = 0; gpc < gpcnr; gpc++)
B
Ben Skeggs 已提交
1114
		gf100_gr_ctxctl_debug_unit(gr, 0x502000 + (gpc * 0x8000));
1115 1116 1117
}

static void
B
Ben Skeggs 已提交
1118
gf100_gr_ctxctl_isr(struct gf100_gr *gr)
1119
{
1120 1121
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
1122
	u32 stat = nvkm_rd32(device, 0x409c18);
1123

1124
	if (stat & 0x00000001) {
1125
		u32 code = nvkm_rd32(device, 0x409814);
1126
		if (code == E_BAD_FWMTHD) {
1127 1128
			u32 class = nvkm_rd32(device, 0x409808);
			u32  addr = nvkm_rd32(device, 0x40980c);
1129 1130
			u32  subc = (addr & 0x00070000) >> 16;
			u32  mthd = (addr & 0x00003ffc);
1131
			u32  data = nvkm_rd32(device, 0x409810);
1132

1133 1134 1135
			nvkm_error(subdev, "FECS MTHD subc %d class %04x "
					   "mthd %04x data %08x\n",
				   subc, class, mthd, data);
1136

1137
			nvkm_wr32(device, 0x409c20, 0x00000001);
1138 1139
			stat &= ~0x00000001;
		} else {
1140
			nvkm_error(subdev, "FECS ucode error %d\n", code);
1141 1142
		}
	}
1143

1144
	if (stat & 0x00080000) {
1145
		nvkm_error(subdev, "FECS watchdog timeout\n");
B
Ben Skeggs 已提交
1146
		gf100_gr_ctxctl_debug(gr);
1147
		nvkm_wr32(device, 0x409c20, 0x00080000);
1148 1149 1150 1151
		stat &= ~0x00080000;
	}

	if (stat) {
1152
		nvkm_error(subdev, "FECS %08x\n", stat);
B
Ben Skeggs 已提交
1153
		gf100_gr_ctxctl_debug(gr);
1154
		nvkm_wr32(device, 0x409c20, stat);
1155
	}
1156 1157
}

1158
static void
1159
gf100_gr_intr(struct nvkm_subdev *subdev)
1160
{
1161 1162 1163
	struct gf100_gr *gr = (void *)subdev;
	struct nvkm_device *device = gr->base.engine.subdev.device;
	struct nvkm_fifo *fifo = device->fifo;
1164 1165 1166
	struct nvkm_engine *engine = nv_engine(subdev);
	struct nvkm_object *engctx;
	struct nvkm_handle *handle;
1167 1168 1169
	u64 inst = nvkm_rd32(device, 0x409b00) & 0x0fffffff;
	u32 stat = nvkm_rd32(device, 0x400100);
	u32 addr = nvkm_rd32(device, 0x400704);
1170 1171
	u32 mthd = (addr & 0x00003ffc);
	u32 subc = (addr & 0x00070000) >> 16;
1172 1173
	u32 data = nvkm_rd32(device, 0x400708);
	u32 code = nvkm_rd32(device, 0x400110);
1174
	u32 class;
1175 1176
	int chid;

B
Ben Skeggs 已提交
1177
	if (nv_device(gr)->card_type < NV_E0 || subc < 4)
1178
		class = nvkm_rd32(device, 0x404200 + (subc * 4));
1179 1180 1181
	else
		class = 0x0000;

1182
	engctx = nvkm_engctx_get(engine, inst);
B
Ben Skeggs 已提交
1183
	chid   = fifo->chid(fifo, engctx);
1184

1185 1186 1187 1188 1189
	if (stat & 0x00000001) {
		/*
		 * notifier interrupt, only needed for cyclestats
		 * can be safely ignored
		 */
1190
		nvkm_wr32(device, 0x400100, 0x00000001);
1191 1192 1193
		stat &= ~0x00000001;
	}

1194
	if (stat & 0x00000010) {
1195
		handle = nvkm_handle_get_class(engctx, class);
1196
		if (!handle || nv_call(handle->object, mthd, data)) {
1197 1198 1199 1200
			nvkm_error(subdev, "ILLEGAL_MTHD ch %d [%010llx %s] "
				   "subc %d class %04x mthd %04x data %08x\n",
				   chid, inst << 12, nvkm_client_name(engctx),
				   subc, class, mthd, data);
1201
		}
1202
		nvkm_handle_put(handle);
1203
		nvkm_wr32(device, 0x400100, 0x00000010);
1204 1205 1206 1207
		stat &= ~0x00000010;
	}

	if (stat & 0x00000020) {
1208 1209 1210 1211
		nvkm_error(subdev, "ILLEGAL_CLASS ch %d [%010llx %s] "
			   "subc %d class %04x mthd %04x data %08x\n",
			   chid, inst << 12, nvkm_client_name(engctx), subc,
			   class, mthd, data);
1212
		nvkm_wr32(device, 0x400100, 0x00000020);
1213 1214 1215 1216
		stat &= ~0x00000020;
	}

	if (stat & 0x00100000) {
1217 1218 1219 1220 1221 1222
		const struct nvkm_enum *en =
			nvkm_enum_find(nv50_data_error_names, code);
		nvkm_error(subdev, "DATA_ERROR %08x [%s] ch %d [%010llx %s] "
				   "subc %d class %04x mthd %04x data %08x\n",
			   code, en ? en->name : "", chid, inst << 12,
			   nvkm_client_name(engctx), subc, class, mthd, data);
1223
		nvkm_wr32(device, 0x400100, 0x00100000);
1224 1225 1226 1227
		stat &= ~0x00100000;
	}

	if (stat & 0x00200000) {
1228 1229 1230
		nvkm_error(subdev, "TRAP ch %d [%010llx %s]\n",
			   chid, inst << 12,
			   nvkm_client_name(engctx));
B
Ben Skeggs 已提交
1231
		gf100_gr_trap_intr(gr);
1232
		nvkm_wr32(device, 0x400100, 0x00200000);
1233 1234 1235 1236
		stat &= ~0x00200000;
	}

	if (stat & 0x00080000) {
B
Ben Skeggs 已提交
1237
		gf100_gr_ctxctl_isr(gr);
1238
		nvkm_wr32(device, 0x400100, 0x00080000);
1239 1240 1241 1242
		stat &= ~0x00080000;
	}

	if (stat) {
1243
		nvkm_error(subdev, "intr %08x\n", stat);
1244
		nvkm_wr32(device, 0x400100, stat);
1245 1246
	}

1247
	nvkm_wr32(device, 0x400500, 0x00010001);
1248
	nvkm_engctx_put(engctx);
1249 1250
}

1251
void
B
Ben Skeggs 已提交
1252
gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
1253
		 struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
1254
{
1255
	struct nvkm_device *device = gr->base.engine.subdev.device;
1256
	int i;
1257

1258
	nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000);
1259
	for (i = 0; i < data->size / 4; i++)
1260
		nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]);
1261

1262
	nvkm_wr32(device, fuc_base + 0x0180, 0x01000000);
1263 1264
	for (i = 0; i < code->size / 4; i++) {
		if ((i & 0x3f) == 0)
1265 1266
			nvkm_wr32(device, fuc_base + 0x0188, i >> 6);
		nvkm_wr32(device, fuc_base + 0x0184, code->data[i]);
1267
	}
1268 1269 1270

	/* code must be padded to 0x40 words */
	for (; i & 0x3f; i++)
1271
		nvkm_wr32(device, fuc_base + 0x0184, 0);
1272 1273
}

1274
static void
B
Ben Skeggs 已提交
1275
gf100_gr_init_csdata(struct gf100_gr *gr,
1276 1277
		     const struct gf100_gr_pack *pack,
		     u32 falcon, u32 starstar, u32 base)
1278
{
1279
	struct nvkm_device *device = gr->base.engine.subdev.device;
1280 1281
	const struct gf100_gr_pack *iter;
	const struct gf100_gr_init *init;
1282
	u32 addr = ~0, prev = ~0, xfer = 0;
1283 1284
	u32 star, temp;

1285 1286 1287
	nvkm_wr32(device, falcon + 0x01c0, 0x02000000 + starstar);
	star = nvkm_rd32(device, falcon + 0x01c4);
	temp = nvkm_rd32(device, falcon + 0x01c4);
1288 1289
	if (temp > star)
		star = temp;
1290
	nvkm_wr32(device, falcon + 0x01c0, 0x01000000 + star);
1291

1292 1293 1294 1295 1296 1297 1298
	pack_for_each_init(init, iter, pack) {
		u32 head = init->addr - base;
		u32 tail = head + init->count * init->pitch;
		while (head < tail) {
			if (head != prev + 4 || xfer >= 32) {
				if (xfer) {
					u32 data = ((--xfer << 26) | addr);
1299
					nvkm_wr32(device, falcon + 0x01c4, data);
1300 1301 1302 1303
					star += 4;
				}
				addr = head;
				xfer = 0;
1304
			}
1305 1306 1307
			prev = head;
			xfer = xfer + 1;
			head = head + init->pitch;
1308
		}
1309
	}
1310

1311 1312 1313
	nvkm_wr32(device, falcon + 0x01c4, (--xfer << 26) | addr);
	nvkm_wr32(device, falcon + 0x01c0, 0x01000004 + starstar);
	nvkm_wr32(device, falcon + 0x01c4, star + 4);
1314 1315
}

1316
int
B
Ben Skeggs 已提交
1317
gf100_gr_init_ctxctl(struct gf100_gr *gr)
1318
{
1319 1320
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
B
Ben Skeggs 已提交
1321 1322
	struct gf100_gr_oclass *oclass = (void *)nv_object(gr)->oclass;
	struct gf100_grctx_oclass *cclass = (void *)nv_engine(gr)->cclass;
1323
	int i;
1324

B
Ben Skeggs 已提交
1325
	if (gr->firmware) {
1326
		/* load fuc microcode */
B
Ben Skeggs 已提交
1327 1328 1329 1330 1331 1332
		nvkm_mc(gr)->unk260(nvkm_mc(gr), 0);
		gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c,
						 &gr->fuc409d);
		gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac,
						 &gr->fuc41ad);
		nvkm_mc(gr)->unk260(nvkm_mc(gr), 1);
1333

1334
		/* start both of them running */
1335 1336 1337 1338 1339
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x41a10c, 0x00000000);
		nvkm_wr32(device, 0x40910c, 0x00000000);
		nvkm_wr32(device, 0x41a100, 0x00000002);
		nvkm_wr32(device, 0x409100, 0x00000002);
1340 1341 1342 1343 1344
		if (nvkm_msec(device, 2000,
			if (nvkm_rd32(device, 0x409800) & 0x00000001)
				break;
		) < 0)
			return -EBUSY;
B
Ben Skeggs 已提交
1345

1346 1347 1348
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x7fffffff);
		nvkm_wr32(device, 0x409504, 0x00000021);
B
Ben Skeggs 已提交
1349

1350 1351 1352
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x00000000);
		nvkm_wr32(device, 0x409504, 0x00000010);
1353 1354 1355 1356
		if (nvkm_msec(device, 2000,
			if ((gr->size = nvkm_rd32(device, 0x409800)))
				break;
		) < 0)
1357
			return -EBUSY;
1358

1359 1360 1361
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x00000000);
		nvkm_wr32(device, 0x409504, 0x00000016);
1362 1363 1364 1365
		if (nvkm_msec(device, 2000,
			if (nvkm_rd32(device, 0x409800))
				break;
		) < 0)
1366 1367
			return -EBUSY;

1368 1369 1370
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x00000000);
		nvkm_wr32(device, 0x409504, 0x00000025);
1371 1372 1373 1374
		if (nvkm_msec(device, 2000,
			if (nvkm_rd32(device, 0x409800))
				break;
		) < 0)
1375 1376
			return -EBUSY;

B
Ben Skeggs 已提交
1377
		if (nv_device(gr)->chipset >= 0xe0) {
1378 1379 1380
			nvkm_wr32(device, 0x409800, 0x00000000);
			nvkm_wr32(device, 0x409500, 0x00000001);
			nvkm_wr32(device, 0x409504, 0x00000030);
1381 1382 1383 1384
			if (nvkm_msec(device, 2000,
				if (nvkm_rd32(device, 0x409800))
					break;
			) < 0)
1385 1386
				return -EBUSY;

1387 1388 1389 1390
			nvkm_wr32(device, 0x409810, 0xb00095c8);
			nvkm_wr32(device, 0x409800, 0x00000000);
			nvkm_wr32(device, 0x409500, 0x00000001);
			nvkm_wr32(device, 0x409504, 0x00000031);
1391 1392 1393 1394
			if (nvkm_msec(device, 2000,
				if (nvkm_rd32(device, 0x409800))
					break;
			) < 0)
1395 1396
				return -EBUSY;

1397 1398 1399 1400
			nvkm_wr32(device, 0x409810, 0x00080420);
			nvkm_wr32(device, 0x409800, 0x00000000);
			nvkm_wr32(device, 0x409500, 0x00000001);
			nvkm_wr32(device, 0x409504, 0x00000032);
1401 1402 1403 1404
			if (nvkm_msec(device, 2000,
				if (nvkm_rd32(device, 0x409800))
					break;
			) < 0)
1405 1406
				return -EBUSY;

1407 1408 1409
			nvkm_wr32(device, 0x409614, 0x00000070);
			nvkm_wr32(device, 0x409614, 0x00000770);
			nvkm_wr32(device, 0x40802c, 0x00000001);
1410 1411
		}

B
Ben Skeggs 已提交
1412 1413
		if (gr->data == NULL) {
			int ret = gf100_grctx_generate(gr);
1414
			if (ret) {
1415
				nvkm_error(subdev, "failed to construct context\n");
1416 1417 1418 1419 1420
				return ret;
			}
		}

		return 0;
1421 1422 1423
	} else
	if (!oclass->fecs.ucode) {
		return -ENOSYS;
1424
	}
1425

1426
	/* load HUB microcode */
B
Ben Skeggs 已提交
1427
	nvkm_mc(gr)->unk260(nvkm_mc(gr), 0);
1428
	nvkm_wr32(device, 0x4091c0, 0x01000000);
1429
	for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
1430
		nvkm_wr32(device, 0x4091c4, oclass->fecs.ucode->data.data[i]);
1431

1432
	nvkm_wr32(device, 0x409180, 0x01000000);
1433
	for (i = 0; i < oclass->fecs.ucode->code.size / 4; i++) {
1434
		if ((i & 0x3f) == 0)
1435 1436
			nvkm_wr32(device, 0x409188, i >> 6);
		nvkm_wr32(device, 0x409184, oclass->fecs.ucode->code.data[i]);
1437 1438 1439
	}

	/* load GPC microcode */
1440
	nvkm_wr32(device, 0x41a1c0, 0x01000000);
1441
	for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++)
1442
		nvkm_wr32(device, 0x41a1c4, oclass->gpccs.ucode->data.data[i]);
1443

1444
	nvkm_wr32(device, 0x41a180, 0x01000000);
1445
	for (i = 0; i < oclass->gpccs.ucode->code.size / 4; i++) {
1446
		if ((i & 0x3f) == 0)
1447 1448
			nvkm_wr32(device, 0x41a188, i >> 6);
		nvkm_wr32(device, 0x41a184, oclass->gpccs.ucode->code.data[i]);
1449
	}
B
Ben Skeggs 已提交
1450
	nvkm_mc(gr)->unk260(nvkm_mc(gr), 1);
1451

1452
	/* load register lists */
B
Ben Skeggs 已提交
1453 1454 1455 1456
	gf100_gr_init_csdata(gr, cclass->hub, 0x409000, 0x000, 0x000000);
	gf100_gr_init_csdata(gr, cclass->gpc, 0x41a000, 0x000, 0x418000);
	gf100_gr_init_csdata(gr, cclass->tpc, 0x41a000, 0x004, 0x419800);
	gf100_gr_init_csdata(gr, cclass->ppc, 0x41a000, 0x008, 0x41be00);
1457

1458
	/* start HUB ucode running, it'll init the GPCs */
1459 1460
	nvkm_wr32(device, 0x40910c, 0x00000000);
	nvkm_wr32(device, 0x409100, 0x00000002);
1461 1462 1463 1464
	if (nvkm_msec(device, 2000,
		if (nvkm_rd32(device, 0x409800) & 0x80000000)
			break;
	) < 0) {
B
Ben Skeggs 已提交
1465
		gf100_gr_ctxctl_debug(gr);
1466 1467 1468
		return -EBUSY;
	}

1469
	gr->size = nvkm_rd32(device, 0x409804);
B
Ben Skeggs 已提交
1470 1471
	if (gr->data == NULL) {
		int ret = gf100_grctx_generate(gr);
1472
		if (ret) {
1473
			nvkm_error(subdev, "failed to construct context\n");
1474 1475
			return ret;
		}
1476 1477 1478
	}

	return 0;
1479 1480
}

1481
int
1482
gf100_gr_init(struct nvkm_object *object)
1483
{
B
Ben Skeggs 已提交
1484
	struct gf100_gr *gr = (void *)object;
1485 1486
	struct nvkm_device *device = gr->base.engine.subdev.device;
	struct gf100_gr_oclass *oclass = (void *)object->oclass;
B
Ben Skeggs 已提交
1487
	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
1488 1489 1490 1491
	u32 data[TPC_MAX / 8] = {};
	u8  tpcnr[GPC_MAX];
	int gpc, tpc, rop;
	int ret, i;
1492

B
Ben Skeggs 已提交
1493
	ret = nvkm_gr_init(&gr->base);
1494 1495 1496
	if (ret)
		return ret;

1497 1498 1499 1500 1501 1502
	nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000);
	nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000);
	nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000);
	nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000);
	nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
	nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
1503 1504
	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8);
	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8);
1505

B
Ben Skeggs 已提交
1506
	gf100_gr_mmio(gr, oclass->mmio);
1507

B
Ben Skeggs 已提交
1508 1509
	memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr));
	for (i = 0, gpc = -1; i < gr->tpc_total; i++) {
1510
		do {
B
Ben Skeggs 已提交
1511
			gpc = (gpc + 1) % gr->gpc_nr;
1512
		} while (!tpcnr[gpc]);
B
Ben Skeggs 已提交
1513
		tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--;
1514 1515 1516 1517

		data[i / 8] |= tpc << ((i % 8) * 4);
	}

1518 1519 1520 1521
	nvkm_wr32(device, GPC_BCAST(0x0980), data[0]);
	nvkm_wr32(device, GPC_BCAST(0x0984), data[1]);
	nvkm_wr32(device, GPC_BCAST(0x0988), data[2]);
	nvkm_wr32(device, GPC_BCAST(0x098c), data[3]);
1522

B
Ben Skeggs 已提交
1523
	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
1524
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
B
Ben Skeggs 已提交
1525
			gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
1526
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
B
Ben Skeggs 已提交
1527
			gr->tpc_total);
1528
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
1529 1530
	}

B
Ben Skeggs 已提交
1531
	if (nv_device(gr)->chipset != 0xd7)
1532
		nvkm_wr32(device, GPC_BCAST(0x1bd4), magicgpc918);
M
Maarten Lankhorst 已提交
1533
	else
1534
		nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918);
B
Ben Skeggs 已提交
1535

1536
	nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800));
B
Ben Skeggs 已提交
1537

1538
	nvkm_wr32(device, 0x400500, 0x00010001);
B
Ben Skeggs 已提交
1539

1540 1541
	nvkm_wr32(device, 0x400100, 0xffffffff);
	nvkm_wr32(device, 0x40013c, 0xffffffff);
B
Ben Skeggs 已提交
1542

1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
	nvkm_wr32(device, 0x409c24, 0x000f0000);
	nvkm_wr32(device, 0x404000, 0xc0000000);
	nvkm_wr32(device, 0x404600, 0xc0000000);
	nvkm_wr32(device, 0x408030, 0xc0000000);
	nvkm_wr32(device, 0x40601c, 0xc0000000);
	nvkm_wr32(device, 0x404490, 0xc0000000);
	nvkm_wr32(device, 0x406018, 0xc0000000);
	nvkm_wr32(device, 0x405840, 0xc0000000);
	nvkm_wr32(device, 0x405844, 0x00ffffff);
	nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008);
	nvkm_mask(device, 0x419eb4, 0x00001000, 0x00001000);
B
Ben Skeggs 已提交
1554 1555

	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
1556 1557 1558 1559
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
		nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000);
B
Ben Skeggs 已提交
1560
		for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
1561 1562 1563 1564 1565 1566 1567
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
			nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
1568
		}
1569 1570
		nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
		nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
1571 1572
	}

B
Ben Skeggs 已提交
1573
	for (rop = 0; rop < gr->rop_nr; rop++) {
1574 1575 1576 1577
		nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000);
		nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000);
		nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff);
		nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff);
1578
	}
1579

1580 1581 1582 1583 1584 1585
	nvkm_wr32(device, 0x400108, 0xffffffff);
	nvkm_wr32(device, 0x400138, 0xffffffff);
	nvkm_wr32(device, 0x400118, 0xffffffff);
	nvkm_wr32(device, 0x400130, 0xffffffff);
	nvkm_wr32(device, 0x40011c, 0xffffffff);
	nvkm_wr32(device, 0x400134, 0xffffffff);
1586

1587
	nvkm_wr32(device, 0x400054, 0x34ce3464);
1588

B
Ben Skeggs 已提交
1589
	gf100_gr_zbc_init(gr);
1590

B
Ben Skeggs 已提交
1591
	return gf100_gr_init_ctxctl(gr);
1592 1593
}

1594
void
1595
gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc)
1596 1597 1598 1599 1600 1601
{
	kfree(fuc->data);
	fuc->data = NULL;
}

int
B
Ben Skeggs 已提交
1602
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
1603
		 struct gf100_gr_fuc *fuc)
1604
{
1605 1606
	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
1607
	const struct firmware *fw;
1608 1609
	char f[64];
	char cname[16];
1610
	int ret;
1611 1612 1613
	int i;

	/* Convert device name to lowercase */
1614
	strncpy(cname, device->chip->name, sizeof(cname));
1615 1616 1617 1618 1619 1620
	cname[sizeof(cname) - 1] = '\0';
	i = strlen(cname);
	while (i) {
		--i;
		cname[i] = tolower(cname[i]);
	}
1621

1622
	snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
A
Alexandre Courbot 已提交
1623
	ret = request_firmware(&fw, f, nv_device_base(device));
1624
	if (ret) {
1625
		nvkm_error(subdev, "failed to load %s\n", fwname);
1626
		return ret;
1627 1628 1629 1630 1631 1632 1633 1634 1635
	}

	fuc->size = fw->size;
	fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
	release_firmware(fw);
	return (fuc->data != NULL) ? 0 : -ENOMEM;
}

void
1636
gf100_gr_dtor(struct nvkm_object *object)
1637
{
B
Ben Skeggs 已提交
1638
	struct gf100_gr *gr = (void *)object;
1639

B
Ben Skeggs 已提交
1640
	kfree(gr->data);
1641

B
Ben Skeggs 已提交
1642 1643 1644 1645
	gf100_gr_dtor_fw(&gr->fuc409c);
	gf100_gr_dtor_fw(&gr->fuc409d);
	gf100_gr_dtor_fw(&gr->fuc41ac);
	gf100_gr_dtor_fw(&gr->fuc41ad);
1646

1647 1648
	nvkm_memory_del(&gr->unk4188b8);
	nvkm_memory_del(&gr->unk4188b4);
1649

B
Ben Skeggs 已提交
1650
	nvkm_gr_destroy(&gr->base);
1651 1652 1653
}

int
1654 1655 1656
gf100_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
	      struct nvkm_oclass *bclass, void *data, u32 size,
	      struct nvkm_object **pobject)
1657
{
1658
	struct gf100_gr_oclass *oclass = (void *)bclass;
1659
	struct nvkm_device *device = (void *)parent;
B
Ben Skeggs 已提交
1660
	struct gf100_gr *gr;
1661
	bool use_ext_fw, enable;
1662
	int ret, i, j;
1663

1664 1665
	use_ext_fw = nvkm_boolopt(device->cfgopt, "NvGrUseFW",
				  oclass->fecs.ucode == NULL);
1666 1667
	enable = use_ext_fw || oclass->fecs.ucode != NULL;

B
Ben Skeggs 已提交
1668 1669
	ret = nvkm_gr_create(parent, engine, bclass, enable, &gr);
	*pobject = nv_object(gr);
1670 1671 1672
	if (ret)
		return ret;

B
Ben Skeggs 已提交
1673 1674
	nv_subdev(gr)->unit = 0x08001000;
	nv_subdev(gr)->intr = gf100_gr_intr;
1675

B
Ben Skeggs 已提交
1676
	gr->base.units = gf100_gr_units;
1677

1678
	if (use_ext_fw) {
1679
		nvkm_info(&gr->base.engine.subdev, "using external firmware\n");
B
Ben Skeggs 已提交
1680 1681 1682 1683
		if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fuc409c) ||
		    gf100_gr_ctor_fw(gr, "fecs_data", &gr->fuc409d) ||
		    gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->fuc41ac) ||
		    gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad))
1684
			return -ENODEV;
B
Ben Skeggs 已提交
1685
		gr->firmware = true;
1686 1687
	}

1688
	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false,
B
Ben Skeggs 已提交
1689
			      &gr->unk4188b4);
1690 1691
	if (ret)
		return ret;
1692

1693
	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false,
B
Ben Skeggs 已提交
1694
			      &gr->unk4188b8);
1695
	if (ret)
1696 1697
		return ret;

1698 1699 1700 1701 1702 1703 1704 1705 1706
	nvkm_kmap(gr->unk4188b4);
	for (i = 0; i < 0x1000; i += 4)
		nvkm_wo32(gr->unk4188b4, i, 0x00000010);
	nvkm_done(gr->unk4188b4);

	nvkm_kmap(gr->unk4188b8);
	for (i = 0; i < 0x1000; i += 4)
		nvkm_wo32(gr->unk4188b8, i, 0x00000010);
	nvkm_done(gr->unk4188b8);
B
Ben Skeggs 已提交
1707

1708 1709
	gr->rop_nr = (nvkm_rd32(device, 0x409604) & 0x001f0000) >> 16;
	gr->gpc_nr =  nvkm_rd32(device, 0x409604) & 0x0000001f;
B
Ben Skeggs 已提交
1710
	for (i = 0; i < gr->gpc_nr; i++) {
1711
		gr->tpc_nr[i]  = nvkm_rd32(device, GPC_UNIT(i, 0x2608));
B
Ben Skeggs 已提交
1712 1713 1714
		gr->tpc_total += gr->tpc_nr[i];
		gr->ppc_nr[i]  = oclass->ppc_nr;
		for (j = 0; j < gr->ppc_nr[i]; j++) {
1715
			u8 mask = nvkm_rd32(device, GPC_UNIT(i, 0x0c30 + (j * 4)));
B
Ben Skeggs 已提交
1716
			gr->ppc_tpc_nr[i][j] = hweight8(mask);
1717
		}
1718 1719 1720
	}

	/*XXX: these need figuring out... though it might not even matter */
B
Ben Skeggs 已提交
1721
	switch (nv_device(gr)->chipset) {
1722
	case 0xc0:
B
Ben Skeggs 已提交
1723 1724
		if (gr->tpc_total == 11) { /* 465, 3/4/4/0, 4 */
			gr->magic_not_rop_nr = 0x07;
1725
		} else
B
Ben Skeggs 已提交
1726 1727
		if (gr->tpc_total == 14) { /* 470, 3/3/4/4, 5 */
			gr->magic_not_rop_nr = 0x05;
1728
		} else
B
Ben Skeggs 已提交
1729 1730
		if (gr->tpc_total == 15) { /* 480, 3/4/4/4, 6 */
			gr->magic_not_rop_nr = 0x06;
1731 1732 1733
		}
		break;
	case 0xc3: /* 450, 4/0/0/0, 2 */
B
Ben Skeggs 已提交
1734
		gr->magic_not_rop_nr = 0x03;
1735 1736
		break;
	case 0xc4: /* 460, 3/4/0/0, 4 */
B
Ben Skeggs 已提交
1737
		gr->magic_not_rop_nr = 0x01;
1738 1739
		break;
	case 0xc1: /* 2/0/0/0, 1 */
B
Ben Skeggs 已提交
1740
		gr->magic_not_rop_nr = 0x01;
1741 1742
		break;
	case 0xc8: /* 4/4/3/4, 5 */
B
Ben Skeggs 已提交
1743
		gr->magic_not_rop_nr = 0x06;
1744 1745
		break;
	case 0xce: /* 4/4/0/0, 4 */
B
Ben Skeggs 已提交
1746
		gr->magic_not_rop_nr = 0x03;
1747 1748
		break;
	case 0xcf: /* 4/0/0/0, 3 */
B
Ben Skeggs 已提交
1749
		gr->magic_not_rop_nr = 0x03;
1750
		break;
M
Maarten Lankhorst 已提交
1751
	case 0xd7:
1752
	case 0xd9: /* 1/0/0/0, 1 */
1753
	case 0xea: /* gk20a */
1754
	case 0x12b: /* gm20b */
B
Ben Skeggs 已提交
1755
		gr->magic_not_rop_nr = 0x01;
1756 1757 1758
		break;
	}

B
Ben Skeggs 已提交
1759 1760
	nv_engine(gr)->cclass = *oclass->cclass;
	nv_engine(gr)->sclass =  oclass->sclass;
1761 1762 1763
	return 0;
}

1764
#include "fuc/hubgf100.fuc3.h"
1765

1766 1767 1768 1769 1770 1771
struct gf100_gr_ucode
gf100_gr_fecs_ucode = {
	.code.data = gf100_grhub_code,
	.code.size = sizeof(gf100_grhub_code),
	.data.data = gf100_grhub_data,
	.data.size = sizeof(gf100_grhub_data),
1772 1773
};

1774
#include "fuc/gpcgf100.fuc3.h"
1775

1776 1777 1778 1779 1780 1781
struct gf100_gr_ucode
gf100_gr_gpccs_ucode = {
	.code.data = gf100_grgpc_code,
	.code.size = sizeof(gf100_grgpc_code),
	.data.data = gf100_grgpc_data,
	.data.size = sizeof(gf100_grgpc_data),
1782 1783
};

1784 1785
struct nvkm_oclass *
gf100_gr_oclass = &(struct gf100_gr_oclass) {
1786
	.base.handle = NV_ENGINE(GR, 0xc0),
1787 1788 1789 1790 1791
	.base.ofuncs = &(struct nvkm_ofuncs) {
		.ctor = gf100_gr_ctor,
		.dtor = gf100_gr_dtor,
		.init = gf100_gr_init,
		.fini = _nvkm_gr_fini,
1792
	},
1793 1794 1795 1796 1797
	.cclass = &gf100_grctx_oclass,
	.sclass =  gf100_gr_sclass,
	.mmio = gf100_gr_pack_mmio,
	.fecs.ucode = &gf100_gr_fecs_ucode,
	.gpccs.ucode = &gf100_gr_gpccs_ucode,
1798
}.base;