gf100.c 47.1 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 231 232 233
struct nvkm_ofuncs
gf100_fermi_ofuncs = {
	.ctor = _nvkm_object_ctor,
	.dtor = nvkm_object_destroy,
	.init = nvkm_object_init,
	.fini = nvkm_object_fini,
	.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 287
	int ret, i;

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

296 297 298 299
	/* 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.
	 */
300 301
	ret = nvkm_gpuobj_new(nv_object(chan), NULL, 0x1000, 0x100, 0,
			      &chan->mmio);
302 303 304
	if (ret)
		return ret;

305 306 307
	ret = nvkm_gpuobj_map_vm(nv_gpuobj(chan->mmio), vm,
				 NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS,
				 &chan->mmio_vma);
308 309 310
	if (ret)
		return ret;

311
	/* allocate buffers referenced by mmio list */
B
Ben Skeggs 已提交
312
	for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) {
313 314
		ret = nvkm_gpuobj_new(nv_object(chan), NULL, data->size,
				      data->align, 0, &chan->data[i].mem);
315 316
		if (ret)
			return ret;
317

318 319
		ret = nvkm_gpuobj_map_vm(chan->data[i].mem, vm, data->access,
					 &chan->data[i].vma);
320 321
		if (ret)
			return ret;
322

323
		data++;
324 325
	}

326
	/* finally, fill in the mmio list and point the context at it */
B
Ben Skeggs 已提交
327
	for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) {
328 329
		u32 addr = mmio->addr;
		u32 data = mmio->data;
330

331
		if (mmio->buffer >= 0) {
332
			u64 info = chan->data[mmio->buffer].vma.offset;
333 334
			data |= info >> mmio->shift;
		}
335

336 337
		nv_wo32(chan->mmio, chan->mmio_nr++ * 4, addr);
		nv_wo32(chan->mmio, chan->mmio_nr++ * 4, data);
338 339
		mmio++;
	}
340

B
Ben Skeggs 已提交
341 342
	for (i = 0; i < gr->size; i += 4)
		nv_wo32(chan, i, gr->data[i / 4]);
343

B
Ben Skeggs 已提交
344
	if (!gr->firmware) {
345 346
		nv_wo32(chan, 0x00, chan->mmio_nr / 2);
		nv_wo32(chan, 0x04, chan->mmio_vma.offset >> 8);
347
	} else {
348 349 350 351 352 353 354 355 356
		nv_wo32(chan, 0xf4, 0);
		nv_wo32(chan, 0xf8, 0);
		nv_wo32(chan, 0x10, chan->mmio_nr / 2);
		nv_wo32(chan, 0x14, lower_32_bits(chan->mmio_vma.offset));
		nv_wo32(chan, 0x18, upper_32_bits(chan->mmio_vma.offset));
		nv_wo32(chan, 0x1c, 1);
		nv_wo32(chan, 0x20, 0);
		nv_wo32(chan, 0x28, 0);
		nv_wo32(chan, 0x2c, 0);
357
	}
358

359
	return 0;
360 361
}

362
void
363
gf100_gr_context_dtor(struct nvkm_object *object)
364
{
365
	struct gf100_gr_chan *chan = (void *)object;
366 367
	int i;

368
	for (i = 0; i < ARRAY_SIZE(chan->data); i++) {
369 370
		nvkm_gpuobj_unmap(&chan->data[i].vma);
		nvkm_gpuobj_ref(NULL, &chan->data[i].mem);
371
	}
372

373 374
	nvkm_gpuobj_unmap(&chan->mmio_vma);
	nvkm_gpuobj_ref(NULL, &chan->mmio);
375

376
	nvkm_gr_context_destroy(&chan->base);
377 378
}

379
/*******************************************************************************
380
 * PGRAPH register lists
381 382
 ******************************************************************************/

383 384
const struct gf100_gr_init
gf100_gr_init_main_0[] = {
385 386 387 388 389 390 391 392 393 394 395 396 397 398
	{ 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 },
	{}
};

399 400
const struct gf100_gr_init
gf100_gr_init_fe_0[] = {
401 402 403 404 405
	{ 0x40415c,   1, 0x04, 0x00000000 },
	{ 0x404170,   1, 0x04, 0x00000000 },
	{}
};

406 407
const struct gf100_gr_init
gf100_gr_init_pri_0[] = {
408 409 410 411
	{ 0x404488,   2, 0x04, 0x00000000 },
	{}
};

412 413
const struct gf100_gr_init
gf100_gr_init_rstr2d_0[] = {
414 415 416 417
	{ 0x407808,   1, 0x04, 0x00000000 },
	{}
};

418 419
const struct gf100_gr_init
gf100_gr_init_pd_0[] = {
420 421 422 423
	{ 0x406024,   1, 0x04, 0x00000000 },
	{}
};

424 425
const struct gf100_gr_init
gf100_gr_init_ds_0[] = {
426 427 428 429 430 431
	{ 0x405844,   1, 0x04, 0x00ffffff },
	{ 0x405850,   1, 0x04, 0x00000000 },
	{ 0x405908,   1, 0x04, 0x00000000 },
	{}
};

432 433
const struct gf100_gr_init
gf100_gr_init_scc_0[] = {
434 435 436 437
	{ 0x40803c,   1, 0x04, 0x00000000 },
	{}
};

438 439
const struct gf100_gr_init
gf100_gr_init_prop_0[] = {
440
	{ 0x4184a0,   1, 0x04, 0x00000000 },
441 442 443
	{}
};

444 445
const struct gf100_gr_init
gf100_gr_init_gpc_unk_0[] = {
446 447 448 449
	{ 0x418604,   1, 0x04, 0x00000000 },
	{ 0x418680,   1, 0x04, 0x00000000 },
	{ 0x418714,   1, 0x04, 0x80000000 },
	{ 0x418384,   1, 0x04, 0x00000000 },
450 451 452
	{}
};

453 454
const struct gf100_gr_init
gf100_gr_init_setup_0[] = {
455
	{ 0x418814,   3, 0x04, 0x00000000 },
456 457 458
	{}
};

459 460
const struct gf100_gr_init
gf100_gr_init_crstr_0[] = {
461
	{ 0x418b04,   1, 0x04, 0x00000000 },
462 463 464
	{}
};

465 466
const struct gf100_gr_init
gf100_gr_init_setup_1[] = {
467 468 469 470
	{ 0x4188c8,   1, 0x04, 0x80000000 },
	{ 0x4188cc,   1, 0x04, 0x00000000 },
	{ 0x4188d0,   1, 0x04, 0x00010000 },
	{ 0x4188d4,   1, 0x04, 0x00000001 },
471 472 473
	{}
};

474 475
const struct gf100_gr_init
gf100_gr_init_zcull_0[] = {
476 477 478 479 480
	{ 0x418910,   1, 0x04, 0x00010001 },
	{ 0x418914,   1, 0x04, 0x00000301 },
	{ 0x418918,   1, 0x04, 0x00800000 },
	{ 0x418980,   1, 0x04, 0x77777770 },
	{ 0x418984,   3, 0x04, 0x77777777 },
481 482 483
	{}
};

484 485
const struct gf100_gr_init
gf100_gr_init_gpm_0[] = {
486 487
	{ 0x418c04,   1, 0x04, 0x00000000 },
	{ 0x418c88,   1, 0x04, 0x00000000 },
488 489 490
	{}
};

491 492
const struct gf100_gr_init
gf100_gr_init_gpc_unk_1[] = {
493 494 495 496
	{ 0x418d00,   1, 0x04, 0x00000000 },
	{ 0x418f08,   1, 0x04, 0x00000000 },
	{ 0x418e00,   1, 0x04, 0x00000050 },
	{ 0x418e08,   1, 0x04, 0x00000000 },
497 498 499
	{}
};

500 501
const struct gf100_gr_init
gf100_gr_init_gcc_0[] = {
502 503 504 505 506
	{ 0x41900c,   1, 0x04, 0x00000000 },
	{ 0x419018,   1, 0x04, 0x00000000 },
	{}
};

507 508
const struct gf100_gr_init
gf100_gr_init_tpccs_0[] = {
509 510
	{ 0x419d08,   2, 0x04, 0x00000000 },
	{ 0x419d10,   1, 0x04, 0x00000014 },
511 512 513
	{}
};

514 515
const struct gf100_gr_init
gf100_gr_init_tex_0[] = {
516 517 518
	{ 0x419ab0,   1, 0x04, 0x00000000 },
	{ 0x419ab8,   1, 0x04, 0x000000e7 },
	{ 0x419abc,   2, 0x04, 0x00000000 },
519 520 521
	{}
};

522 523
const struct gf100_gr_init
gf100_gr_init_pe_0[] = {
524 525 526 527
	{ 0x41980c,   3, 0x04, 0x00000000 },
	{ 0x419844,   1, 0x04, 0x00000000 },
	{ 0x41984c,   1, 0x04, 0x00005bc5 },
	{ 0x419850,   4, 0x04, 0x00000000 },
528 529 530
	{}
};

531 532
const struct gf100_gr_init
gf100_gr_init_l1c_0[] = {
533 534 535 536 537 538
	{ 0x419c98,   1, 0x04, 0x00000000 },
	{ 0x419ca8,   1, 0x04, 0x80000000 },
	{ 0x419cb4,   1, 0x04, 0x00000000 },
	{ 0x419cb8,   1, 0x04, 0x00008bf4 },
	{ 0x419cbc,   1, 0x04, 0x28137606 },
	{ 0x419cc0,   2, 0x04, 0x00000000 },
539 540 541
	{}
};

542 543
const struct gf100_gr_init
gf100_gr_init_wwdx_0[] = {
544 545
	{ 0x419bd4,   1, 0x04, 0x00800000 },
	{ 0x419bdc,   1, 0x04, 0x00000000 },
546 547 548
	{}
};

549 550
const struct gf100_gr_init
gf100_gr_init_tpccs_1[] = {
551
	{ 0x419d2c,   1, 0x04, 0x00000000 },
552 553 554
	{}
};

555 556
const struct gf100_gr_init
gf100_gr_init_mpc_0[] = {
557
	{ 0x419c0c,   1, 0x04, 0x00000000 },
558 559 560
	{}
};

561 562
static const struct gf100_gr_init
gf100_gr_init_sm_0[] = {
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
	{ 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 },
	{}
};

579 580
const struct gf100_gr_init
gf100_gr_init_be_0[] = {
581 582 583 584 585 586 587 588 589 590
	{ 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 },
	{}
};

591 592
const struct gf100_gr_init
gf100_gr_init_fe_1[] = {
593 594 595 596
	{ 0x4040f0,   1, 0x04, 0x00000000 },
	{}
};

597 598
const struct gf100_gr_init
gf100_gr_init_pe_1[] = {
599 600 601 602
	{ 0x419880,   1, 0x04, 0x00000002 },
	{}
};

603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
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 已提交
632 633 634
	{}
};

635 636 637 638
/*******************************************************************************
 * PGRAPH engine/subdev functions
 ******************************************************************************/

639
void
B
Ben Skeggs 已提交
640
gf100_gr_zbc_init(struct gf100_gr *gr)
641 642 643 644 645 646 647 648 649
{
	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 已提交
650
	struct nvkm_ltc *ltc = nvkm_ltc(gr);
651 652
	int index;

B
Ben Skeggs 已提交
653 654 655 656 657 658 659
	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);
660 661 662
	}

	for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
B
Ben Skeggs 已提交
663
		gf100_gr_zbc_clear_color(gr, index);
664
	for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
B
Ben Skeggs 已提交
665
		gf100_gr_zbc_clear_depth(gr, index);
666 667
}

668 669 670 671 672 673
/**
 * 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 已提交
674
gf100_gr_wait_idle(struct gf100_gr *gr)
675
{
676
	struct nvkm_device *device = gr->base.engine.subdev.device;
677 678 679 680 681 682 683 684
	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
		 */
685
		nvkm_rd32(device, 0x400700);
686

687 688 689
		gr_enabled = nvkm_rd32(device, 0x200) & 0x1000;
		ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000;
		gr_busy = nvkm_rd32(device, 0x40060c) & 0x1;
690 691 692 693 694

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

B
Ben Skeggs 已提交
695
	nv_error(gr, "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
696 697 698 699
		 gr_enabled, ctxsw_active, gr_busy);
	return -EAGAIN;
}

700
void
B
Ben Skeggs 已提交
701
gf100_gr_mmio(struct gf100_gr *gr, const struct gf100_gr_pack *p)
702
{
703
	struct nvkm_device *device = gr->base.engine.subdev.device;
704 705
	const struct gf100_gr_pack *pack;
	const struct gf100_gr_init *init;
706 707 708 709 710

	pack_for_each_init(init, pack, p) {
		u32 next = init->addr + init->count * init->pitch;
		u32 addr = init->addr;
		while (addr < next) {
711
			nvkm_wr32(device, addr, init->data);
712 713 714
			addr += init->pitch;
		}
	}
715 716 717
}

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

725
	nvkm_wr32(device, 0x400208, 0x80000000);
726 727 728 729 730 731

	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) {
732
			nvkm_wr32(device, 0x400204, init->data);
733 734
			data = init->data;
		}
735

736
		while (addr < next) {
737
			nvkm_wr32(device, 0x400200, addr);
738 739 740 741 742
			/**
			 * Wait for GR to go idle after submitting a
			 * GO_IDLE bundle
			 */
			if ((addr & 0xffff) == 0xe100)
B
Ben Skeggs 已提交
743
				gf100_gr_wait_idle(gr);
744 745 746 747
			nvkm_msec(device, 2000,
				if (!(nvkm_rd32(device, 0x400700) & 0x00000004))
					break;
			);
748 749 750
			addr += init->pitch;
		}
	}
751

752
	nvkm_wr32(device, 0x400208, 0x00000000);
753 754 755
}

void
B
Ben Skeggs 已提交
756
gf100_gr_mthd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
757
{
758
	struct nvkm_device *device = gr->base.engine.subdev.device;
759 760
	const struct gf100_gr_pack *pack;
	const struct gf100_gr_init *init;
761
	u32 data = 0;
762

763 764 765 766 767 768
	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) {
769
			nvkm_wr32(device, 0x40448c, init->data);
770 771 772 773
			data = init->data;
		}

		while (addr < next) {
774
			nvkm_wr32(device, 0x404488, ctrl | (addr << 14));
775
			addr += init->pitch;
776 777 778 779 780
		}
	}
}

u64
B
Ben Skeggs 已提交
781
gf100_gr_units(struct nvkm_gr *obj)
782
{
B
Ben Skeggs 已提交
783
	struct gf100_gr *gr = container_of(obj, typeof(*gr), base);
784 785
	u64 cfg;

B
Ben Skeggs 已提交
786 787 788
	cfg  = (u32)gr->gpc_nr;
	cfg |= (u32)gr->tpc_total << 8;
	cfg |= (u64)gr->rop_nr << 32;
789 790

	return cfg;
791 792
}

793
static const struct nvkm_enum gk104_sked_error[] = {
794 795 796 797 798 799 800 801 802 803 804 805 806 807
	{ 7, "CONSTANT_BUFFER_SIZE" },
	{ 9, "LOCAL_MEMORY_SIZE_POS" },
	{ 10, "LOCAL_MEMORY_SIZE_NEG" },
	{ 11, "WARP_CSTACK_SIZE" },
	{ 12, "TOTAL_TEMP_SIZE" },
	{ 13, "REGISTER_COUNT" },
	{ 18, "TOTAL_THREADS" },
	{ 20, "PROGRAM_OFFSET" },
	{ 21, "SHARED_MEMORY_SIZE" },
	{ 25, "SHARED_CONFIG_TOO_SMALL" },
	{ 26, "TOTAL_REGISTER_COUNT" },
	{}
};

808
static const struct nvkm_enum gf100_gpc_rop_error[] = {
809 810 811 812 813 814 815 816 817
	{ 1, "RT_PITCH_OVERRUN" },
	{ 4, "RT_WIDTH_OVERRUN" },
	{ 5, "RT_HEIGHT_OVERRUN" },
	{ 7, "ZETA_STORAGE_TYPE_MISMATCH" },
	{ 8, "RT_STORAGE_TYPE_MISMATCH" },
	{ 10, "RT_LINEAR_MISMATCH" },
	{}
};

818
static void
B
Ben Skeggs 已提交
819
gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc)
820
{
821
	struct nvkm_device *device = gr->base.engine.subdev.device;
822 823
	u32 trap[4];
	int i;
824

825 826 827 828
	trap[0] = nvkm_rd32(device, GPC_UNIT(gpc, 0x0420));
	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));
829

B
Ben Skeggs 已提交
830
	nv_error(gr, "GPC%d/PROP trap:", gpc);
831 832 833 834
	for (i = 0; i <= 29; ++i) {
		if (!(trap[0] & (1 << i)))
			continue;
		pr_cont(" ");
835
		nvkm_enum_print(gf100_gpc_rop_error, i);
836 837 838
	}
	pr_cont("\n");

B
Ben Skeggs 已提交
839
	nv_error(gr, "x = %u, y = %u, format = %x, storage type = %x\n",
840 841
		 trap[1] & 0xffff, trap[1] >> 16, (trap[2] >> 8) & 0x3f,
		 trap[3] & 0xff);
842
	nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
843 844
}

845
static const struct nvkm_enum gf100_mp_warp_error[] = {
846 847 848 849 850 851 852 853 854 855 856 857
	{ 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" },
	{}
};

858
static const struct nvkm_bitfield gf100_mp_global_error[] = {
859 860 861 862 863 864
	{ 0x00000004, "MULTIPLE_WARP_ERRORS" },
	{ 0x00000008, "OUT_OF_STACK_SPACE" },
	{}
};

static void
B
Ben Skeggs 已提交
865
gf100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc)
866
{
867 868 869
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 werr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x648));
	u32 gerr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x650));
870

B
Ben Skeggs 已提交
871
	nv_error(gr, "GPC%i/TPC%i/MP trap:", gpc, tpc);
872
	nvkm_bitfield_print(gf100_mp_global_error, gerr);
873 874
	if (werr) {
		pr_cont(" ");
875
		nvkm_enum_print(gf100_mp_warp_error, werr & 0xffff);
876 877 878
	}
	pr_cont("\n");

879 880
	nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x648), 0x00000000);
	nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x650), gerr);
881 882
}

883
static void
B
Ben Skeggs 已提交
884
gf100_gr_trap_tpc(struct gf100_gr *gr, int gpc, int tpc)
885
{
886 887
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 stat = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0508));
888 889

	if (stat & 0x00000001) {
890
		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0224));
B
Ben Skeggs 已提交
891
		nv_error(gr, "GPC%d/TPC%d/TEX: 0x%08x\n", gpc, tpc, trap);
892
		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000);
893 894 895 896
		stat &= ~0x00000001;
	}

	if (stat & 0x00000002) {
B
Ben Skeggs 已提交
897
		gf100_gr_trap_mp(gr, gpc, tpc);
898 899 900 901
		stat &= ~0x00000002;
	}

	if (stat & 0x00000004) {
902
		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0084));
B
Ben Skeggs 已提交
903
		nv_error(gr, "GPC%d/TPC%d/POLY: 0x%08x\n", gpc, tpc, trap);
904
		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000);
905 906 907 908
		stat &= ~0x00000004;
	}

	if (stat & 0x00000008) {
909
		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x048c));
B
Ben Skeggs 已提交
910
		nv_error(gr, "GPC%d/TPC%d/L1C: 0x%08x\n", gpc, tpc, trap);
911
		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000);
912 913 914 915
		stat &= ~0x00000008;
	}

	if (stat) {
B
Ben Skeggs 已提交
916
		nv_error(gr, "GPC%d/TPC%d/0x%08x: unknown\n", gpc, tpc, stat);
917 918 919 920
	}
}

static void
B
Ben Skeggs 已提交
921
gf100_gr_trap_gpc(struct gf100_gr *gr, int gpc)
922
{
923 924
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 stat = nvkm_rd32(device, GPC_UNIT(gpc, 0x2c90));
925 926 927
	int tpc;

	if (stat & 0x00000001) {
B
Ben Skeggs 已提交
928
		gf100_gr_trap_gpc_rop(gr, gpc);
929 930 931 932
		stat &= ~0x00000001;
	}

	if (stat & 0x00000002) {
933
		u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0900));
B
Ben Skeggs 已提交
934
		nv_error(gr, "GPC%d/ZCULL: 0x%08x\n", gpc, trap);
935
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
936 937 938 939
		stat &= ~0x00000002;
	}

	if (stat & 0x00000004) {
940
		u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x1028));
B
Ben Skeggs 已提交
941
		nv_error(gr, "GPC%d/CCACHE: 0x%08x\n", gpc, trap);
942
		nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
943 944 945 946
		stat &= ~0x00000004;
	}

	if (stat & 0x00000008) {
947
		u32 trap = nvkm_rd32(device, GPC_UNIT(gpc, 0x0824));
B
Ben Skeggs 已提交
948
		nv_error(gr, "GPC%d/ESETUP: 0x%08x\n", gpc, trap);
949
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0824), 0xc0000000);
950 951 952
		stat &= ~0x00000009;
	}

B
Ben Skeggs 已提交
953
	for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
954 955
		u32 mask = 0x00010000 << tpc;
		if (stat & mask) {
B
Ben Skeggs 已提交
956
			gf100_gr_trap_tpc(gr, gpc, tpc);
957
			nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), mask);
958 959 960 961 962
			stat &= ~mask;
		}
	}

	if (stat) {
B
Ben Skeggs 已提交
963
		nv_error(gr, "GPC%d/0x%08x: unknown\n", gpc, stat);
964 965 966 967
	}
}

static void
B
Ben Skeggs 已提交
968
gf100_gr_trap_intr(struct gf100_gr *gr)
969
{
970 971
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 trap = nvkm_rd32(device, 0x400108);
972
	int rop, gpc, i;
973 974

	if (trap & 0x00000001) {
975
		u32 stat = nvkm_rd32(device, 0x404000);
B
Ben Skeggs 已提交
976
		nv_error(gr, "DISPATCH 0x%08x\n", stat);
977 978
		nvkm_wr32(device, 0x404000, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000001);
979 980 981 982
		trap &= ~0x00000001;
	}

	if (trap & 0x00000002) {
983
		u32 stat = nvkm_rd32(device, 0x404600);
B
Ben Skeggs 已提交
984
		nv_error(gr, "M2MF 0x%08x\n", stat);
985 986
		nvkm_wr32(device, 0x404600, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000002);
987 988 989 990
		trap &= ~0x00000002;
	}

	if (trap & 0x00000008) {
991
		u32 stat = nvkm_rd32(device, 0x408030);
B
Ben Skeggs 已提交
992
		nv_error(gr, "CCACHE 0x%08x\n", stat);
993 994
		nvkm_wr32(device, 0x408030, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000008);
995 996 997 998
		trap &= ~0x00000008;
	}

	if (trap & 0x00000010) {
999
		u32 stat = nvkm_rd32(device, 0x405840);
B
Ben Skeggs 已提交
1000
		nv_error(gr, "SHADER 0x%08x\n", stat);
1001 1002
		nvkm_wr32(device, 0x405840, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000010);
1003 1004 1005 1006
		trap &= ~0x00000010;
	}

	if (trap & 0x00000040) {
1007
		u32 stat = nvkm_rd32(device, 0x40601c);
B
Ben Skeggs 已提交
1008
		nv_error(gr, "UNK6 0x%08x\n", stat);
1009 1010
		nvkm_wr32(device, 0x40601c, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000040);
1011 1012 1013 1014
		trap &= ~0x00000040;
	}

	if (trap & 0x00000080) {
1015
		u32 stat = nvkm_rd32(device, 0x404490);
B
Ben Skeggs 已提交
1016
		nv_error(gr, "MACRO 0x%08x\n", stat);
1017 1018
		nvkm_wr32(device, 0x404490, 0xc0000000);
		nvkm_wr32(device, 0x400108, 0x00000080);
1019 1020 1021
		trap &= ~0x00000080;
	}

1022
	if (trap & 0x00000100) {
1023
		u32 stat = nvkm_rd32(device, 0x407020);
1024

B
Ben Skeggs 已提交
1025
		nv_error(gr, "SKED:");
1026 1027 1028 1029
		for (i = 0; i <= 29; ++i) {
			if (!(stat & (1 << i)))
				continue;
			pr_cont(" ");
1030
			nvkm_enum_print(gk104_sked_error, i);
1031 1032 1033 1034
		}
		pr_cont("\n");

		if (stat & 0x3fffffff)
1035 1036
			nvkm_wr32(device, 0x407020, 0x40000000);
		nvkm_wr32(device, 0x400108, 0x00000100);
1037 1038 1039
		trap &= ~0x00000100;
	}

1040
	if (trap & 0x01000000) {
1041
		u32 stat = nvkm_rd32(device, 0x400118);
B
Ben Skeggs 已提交
1042
		for (gpc = 0; stat && gpc < gr->gpc_nr; gpc++) {
1043 1044
			u32 mask = 0x00000001 << gpc;
			if (stat & mask) {
B
Ben Skeggs 已提交
1045
				gf100_gr_trap_gpc(gr, gpc);
1046
				nvkm_wr32(device, 0x400118, mask);
1047 1048 1049
				stat &= ~mask;
			}
		}
1050
		nvkm_wr32(device, 0x400108, 0x01000000);
1051 1052 1053 1054
		trap &= ~0x01000000;
	}

	if (trap & 0x02000000) {
B
Ben Skeggs 已提交
1055
		for (rop = 0; rop < gr->rop_nr; rop++) {
1056 1057
			u32 statz = nvkm_rd32(device, ROP_UNIT(rop, 0x070));
			u32 statc = nvkm_rd32(device, ROP_UNIT(rop, 0x144));
B
Ben Skeggs 已提交
1058
			nv_error(gr, "ROP%d 0x%08x 0x%08x\n",
1059
				 rop, statz, statc);
1060 1061
			nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0xc0000000);
			nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0xc0000000);
1062
		}
1063
		nvkm_wr32(device, 0x400108, 0x02000000);
1064 1065 1066 1067
		trap &= ~0x02000000;
	}

	if (trap) {
B
Ben Skeggs 已提交
1068
		nv_error(gr, "TRAP UNHANDLED 0x%08x\n", trap);
1069
		nvkm_wr32(device, 0x400108, trap);
1070 1071 1072
	}
}

1073
static void
B
Ben Skeggs 已提交
1074
gf100_gr_ctxctl_debug_unit(struct gf100_gr *gr, u32 base)
1075
{
1076
	struct nvkm_device *device = gr->base.engine.subdev.device;
B
Ben Skeggs 已提交
1077
	nv_error(gr, "%06x - done 0x%08x\n", base,
1078
		 nvkm_rd32(device, base + 0x400));
B
Ben Skeggs 已提交
1079
	nv_error(gr, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
1080 1081
		 nvkm_rd32(device, base + 0x800), nvkm_rd32(device, base + 0x804),
		 nvkm_rd32(device, base + 0x808), nvkm_rd32(device, base + 0x80c));
B
Ben Skeggs 已提交
1082
	nv_error(gr, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
1083 1084
		 nvkm_rd32(device, base + 0x810), nvkm_rd32(device, base + 0x814),
		 nvkm_rd32(device, base + 0x818), nvkm_rd32(device, base + 0x81c));
1085 1086 1087
}

void
B
Ben Skeggs 已提交
1088
gf100_gr_ctxctl_debug(struct gf100_gr *gr)
1089
{
1090 1091
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 gpcnr = nvkm_rd32(device, 0x409604) & 0xffff;
1092 1093
	u32 gpc;

B
Ben Skeggs 已提交
1094
	gf100_gr_ctxctl_debug_unit(gr, 0x409000);
1095
	for (gpc = 0; gpc < gpcnr; gpc++)
B
Ben Skeggs 已提交
1096
		gf100_gr_ctxctl_debug_unit(gr, 0x502000 + (gpc * 0x8000));
1097 1098 1099
}

static void
B
Ben Skeggs 已提交
1100
gf100_gr_ctxctl_isr(struct gf100_gr *gr)
1101
{
1102 1103
	struct nvkm_device *device = gr->base.engine.subdev.device;
	u32 stat = nvkm_rd32(device, 0x409c18);
1104

1105
	if (stat & 0x00000001) {
1106
		u32 code = nvkm_rd32(device, 0x409814);
1107
		if (code == E_BAD_FWMTHD) {
1108 1109
			u32 class = nvkm_rd32(device, 0x409808);
			u32  addr = nvkm_rd32(device, 0x40980c);
1110 1111
			u32  subc = (addr & 0x00070000) >> 16;
			u32  mthd = (addr & 0x00003ffc);
1112
			u32  data = nvkm_rd32(device, 0x409810);
1113

B
Ben Skeggs 已提交
1114
			nv_error(gr, "FECS MTHD subc %d class 0x%04x "
1115 1116 1117
				       "mthd 0x%04x data 0x%08x\n",
				 subc, class, mthd, data);

1118
			nvkm_wr32(device, 0x409c20, 0x00000001);
1119 1120
			stat &= ~0x00000001;
		} else {
B
Ben Skeggs 已提交
1121
			nv_error(gr, "FECS ucode error %d\n", code);
1122 1123
		}
	}
1124

1125
	if (stat & 0x00080000) {
B
Ben Skeggs 已提交
1126 1127
		nv_error(gr, "FECS watchdog timeout\n");
		gf100_gr_ctxctl_debug(gr);
1128
		nvkm_wr32(device, 0x409c20, 0x00080000);
1129 1130 1131 1132
		stat &= ~0x00080000;
	}

	if (stat) {
B
Ben Skeggs 已提交
1133 1134
		nv_error(gr, "FECS 0x%08x\n", stat);
		gf100_gr_ctxctl_debug(gr);
1135
		nvkm_wr32(device, 0x409c20, stat);
1136
	}
1137 1138
}

1139
static void
1140
gf100_gr_intr(struct nvkm_subdev *subdev)
1141
{
1142 1143 1144
	struct gf100_gr *gr = (void *)subdev;
	struct nvkm_device *device = gr->base.engine.subdev.device;
	struct nvkm_fifo *fifo = device->fifo;
1145 1146 1147
	struct nvkm_engine *engine = nv_engine(subdev);
	struct nvkm_object *engctx;
	struct nvkm_handle *handle;
1148 1149 1150
	u64 inst = nvkm_rd32(device, 0x409b00) & 0x0fffffff;
	u32 stat = nvkm_rd32(device, 0x400100);
	u32 addr = nvkm_rd32(device, 0x400704);
1151 1152
	u32 mthd = (addr & 0x00003ffc);
	u32 subc = (addr & 0x00070000) >> 16;
1153 1154
	u32 data = nvkm_rd32(device, 0x400708);
	u32 code = nvkm_rd32(device, 0x400110);
1155
	u32 class;
1156 1157
	int chid;

B
Ben Skeggs 已提交
1158
	if (nv_device(gr)->card_type < NV_E0 || subc < 4)
1159
		class = nvkm_rd32(device, 0x404200 + (subc * 4));
1160 1161 1162
	else
		class = 0x0000;

1163
	engctx = nvkm_engctx_get(engine, inst);
B
Ben Skeggs 已提交
1164
	chid   = fifo->chid(fifo, engctx);
1165

1166 1167 1168 1169 1170
	if (stat & 0x00000001) {
		/*
		 * notifier interrupt, only needed for cyclestats
		 * can be safely ignored
		 */
1171
		nvkm_wr32(device, 0x400100, 0x00000001);
1172 1173 1174
		stat &= ~0x00000001;
	}

1175
	if (stat & 0x00000010) {
1176
		handle = nvkm_handle_get_class(engctx, class);
1177
		if (!handle || nv_call(handle->object, mthd, data)) {
B
Ben Skeggs 已提交
1178
			nv_error(gr,
1179
				 "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1180
				 chid, inst << 12, nvkm_client_name(engctx),
1181
				 subc, class, mthd, data);
1182
		}
1183
		nvkm_handle_put(handle);
1184
		nvkm_wr32(device, 0x400100, 0x00000010);
1185 1186 1187 1188
		stat &= ~0x00000010;
	}

	if (stat & 0x00000020) {
B
Ben Skeggs 已提交
1189
		nv_error(gr,
1190
			 "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1191
			 chid, inst << 12, nvkm_client_name(engctx), subc,
1192
			 class, mthd, data);
1193
		nvkm_wr32(device, 0x400100, 0x00000020);
1194 1195 1196 1197
		stat &= ~0x00000020;
	}

	if (stat & 0x00100000) {
B
Ben Skeggs 已提交
1198
		nv_error(gr, "DATA_ERROR [");
1199
		nvkm_enum_print(nv50_data_error_names, code);
1200
		pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1201
			chid, inst << 12, nvkm_client_name(engctx), subc,
1202
			class, mthd, data);
1203
		nvkm_wr32(device, 0x400100, 0x00100000);
1204 1205 1206 1207
		stat &= ~0x00100000;
	}

	if (stat & 0x00200000) {
B
Ben Skeggs 已提交
1208
		nv_error(gr, "TRAP ch %d [0x%010llx %s]\n", chid, inst << 12,
1209
			 nvkm_client_name(engctx));
B
Ben Skeggs 已提交
1210
		gf100_gr_trap_intr(gr);
1211
		nvkm_wr32(device, 0x400100, 0x00200000);
1212 1213 1214 1215
		stat &= ~0x00200000;
	}

	if (stat & 0x00080000) {
B
Ben Skeggs 已提交
1216
		gf100_gr_ctxctl_isr(gr);
1217
		nvkm_wr32(device, 0x400100, 0x00080000);
1218 1219 1220 1221
		stat &= ~0x00080000;
	}

	if (stat) {
B
Ben Skeggs 已提交
1222
		nv_error(gr, "unknown stat 0x%08x\n", stat);
1223
		nvkm_wr32(device, 0x400100, stat);
1224 1225
	}

1226
	nvkm_wr32(device, 0x400500, 0x00010001);
1227
	nvkm_engctx_put(engctx);
1228 1229
}

1230
void
B
Ben Skeggs 已提交
1231
gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
1232
		 struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
1233
{
1234
	struct nvkm_device *device = gr->base.engine.subdev.device;
1235
	int i;
1236

1237
	nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000);
1238
	for (i = 0; i < data->size / 4; i++)
1239
		nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]);
1240

1241
	nvkm_wr32(device, fuc_base + 0x0180, 0x01000000);
1242 1243
	for (i = 0; i < code->size / 4; i++) {
		if ((i & 0x3f) == 0)
1244 1245
			nvkm_wr32(device, fuc_base + 0x0188, i >> 6);
		nvkm_wr32(device, fuc_base + 0x0184, code->data[i]);
1246
	}
1247 1248 1249

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

1253
static void
B
Ben Skeggs 已提交
1254
gf100_gr_init_csdata(struct gf100_gr *gr,
1255 1256
		     const struct gf100_gr_pack *pack,
		     u32 falcon, u32 starstar, u32 base)
1257
{
1258
	struct nvkm_device *device = gr->base.engine.subdev.device;
1259 1260
	const struct gf100_gr_pack *iter;
	const struct gf100_gr_init *init;
1261
	u32 addr = ~0, prev = ~0, xfer = 0;
1262 1263
	u32 star, temp;

1264 1265 1266
	nvkm_wr32(device, falcon + 0x01c0, 0x02000000 + starstar);
	star = nvkm_rd32(device, falcon + 0x01c4);
	temp = nvkm_rd32(device, falcon + 0x01c4);
1267 1268
	if (temp > star)
		star = temp;
1269
	nvkm_wr32(device, falcon + 0x01c0, 0x01000000 + star);
1270

1271 1272 1273 1274 1275 1276 1277
	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);
1278
					nvkm_wr32(device, falcon + 0x01c4, data);
1279 1280 1281 1282
					star += 4;
				}
				addr = head;
				xfer = 0;
1283
			}
1284 1285 1286
			prev = head;
			xfer = xfer + 1;
			head = head + init->pitch;
1287
		}
1288
	}
1289

1290 1291 1292
	nvkm_wr32(device, falcon + 0x01c4, (--xfer << 26) | addr);
	nvkm_wr32(device, falcon + 0x01c0, 0x01000004 + starstar);
	nvkm_wr32(device, falcon + 0x01c4, star + 4);
1293 1294
}

1295
int
B
Ben Skeggs 已提交
1296
gf100_gr_init_ctxctl(struct gf100_gr *gr)
1297
{
1298
	struct nvkm_device *device = gr->base.engine.subdev.device;
B
Ben Skeggs 已提交
1299 1300
	struct gf100_gr_oclass *oclass = (void *)nv_object(gr)->oclass;
	struct gf100_grctx_oclass *cclass = (void *)nv_engine(gr)->cclass;
1301
	int i;
1302

B
Ben Skeggs 已提交
1303
	if (gr->firmware) {
1304
		/* load fuc microcode */
B
Ben Skeggs 已提交
1305 1306 1307 1308 1309 1310
		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);
1311

1312
		/* start both of them running */
1313 1314 1315 1316 1317
		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);
1318 1319 1320 1321 1322
		if (nvkm_msec(device, 2000,
			if (nvkm_rd32(device, 0x409800) & 0x00000001)
				break;
		) < 0)
			return -EBUSY;
B
Ben Skeggs 已提交
1323

1324 1325 1326
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x7fffffff);
		nvkm_wr32(device, 0x409504, 0x00000021);
B
Ben Skeggs 已提交
1327

1328 1329 1330
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x00000000);
		nvkm_wr32(device, 0x409504, 0x00000010);
1331 1332 1333 1334
		if (nvkm_msec(device, 2000,
			if ((gr->size = nvkm_rd32(device, 0x409800)))
				break;
		) < 0)
1335
			return -EBUSY;
1336

1337 1338 1339
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x00000000);
		nvkm_wr32(device, 0x409504, 0x00000016);
1340 1341 1342 1343
		if (nvkm_msec(device, 2000,
			if (nvkm_rd32(device, 0x409800))
				break;
		) < 0)
1344 1345
			return -EBUSY;

1346 1347 1348
		nvkm_wr32(device, 0x409840, 0xffffffff);
		nvkm_wr32(device, 0x409500, 0x00000000);
		nvkm_wr32(device, 0x409504, 0x00000025);
1349 1350 1351 1352
		if (nvkm_msec(device, 2000,
			if (nvkm_rd32(device, 0x409800))
				break;
		) < 0)
1353 1354
			return -EBUSY;

B
Ben Skeggs 已提交
1355
		if (nv_device(gr)->chipset >= 0xe0) {
1356 1357 1358
			nvkm_wr32(device, 0x409800, 0x00000000);
			nvkm_wr32(device, 0x409500, 0x00000001);
			nvkm_wr32(device, 0x409504, 0x00000030);
1359 1360 1361 1362
			if (nvkm_msec(device, 2000,
				if (nvkm_rd32(device, 0x409800))
					break;
			) < 0)
1363 1364
				return -EBUSY;

1365 1366 1367 1368
			nvkm_wr32(device, 0x409810, 0xb00095c8);
			nvkm_wr32(device, 0x409800, 0x00000000);
			nvkm_wr32(device, 0x409500, 0x00000001);
			nvkm_wr32(device, 0x409504, 0x00000031);
1369 1370 1371 1372
			if (nvkm_msec(device, 2000,
				if (nvkm_rd32(device, 0x409800))
					break;
			) < 0)
1373 1374
				return -EBUSY;

1375 1376 1377 1378
			nvkm_wr32(device, 0x409810, 0x00080420);
			nvkm_wr32(device, 0x409800, 0x00000000);
			nvkm_wr32(device, 0x409500, 0x00000001);
			nvkm_wr32(device, 0x409504, 0x00000032);
1379 1380 1381 1382
			if (nvkm_msec(device, 2000,
				if (nvkm_rd32(device, 0x409800))
					break;
			) < 0)
1383 1384
				return -EBUSY;

1385 1386 1387
			nvkm_wr32(device, 0x409614, 0x00000070);
			nvkm_wr32(device, 0x409614, 0x00000770);
			nvkm_wr32(device, 0x40802c, 0x00000001);
1388 1389
		}

B
Ben Skeggs 已提交
1390 1391
		if (gr->data == NULL) {
			int ret = gf100_grctx_generate(gr);
1392
			if (ret) {
B
Ben Skeggs 已提交
1393
				nv_error(gr, "failed to construct context\n");
1394 1395 1396 1397 1398
				return ret;
			}
		}

		return 0;
1399 1400 1401
	} else
	if (!oclass->fecs.ucode) {
		return -ENOSYS;
1402
	}
1403

1404
	/* load HUB microcode */
B
Ben Skeggs 已提交
1405
	nvkm_mc(gr)->unk260(nvkm_mc(gr), 0);
1406
	nvkm_wr32(device, 0x4091c0, 0x01000000);
1407
	for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
1408
		nvkm_wr32(device, 0x4091c4, oclass->fecs.ucode->data.data[i]);
1409

1410
	nvkm_wr32(device, 0x409180, 0x01000000);
1411
	for (i = 0; i < oclass->fecs.ucode->code.size / 4; i++) {
1412
		if ((i & 0x3f) == 0)
1413 1414
			nvkm_wr32(device, 0x409188, i >> 6);
		nvkm_wr32(device, 0x409184, oclass->fecs.ucode->code.data[i]);
1415 1416 1417
	}

	/* load GPC microcode */
1418
	nvkm_wr32(device, 0x41a1c0, 0x01000000);
1419
	for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++)
1420
		nvkm_wr32(device, 0x41a1c4, oclass->gpccs.ucode->data.data[i]);
1421

1422
	nvkm_wr32(device, 0x41a180, 0x01000000);
1423
	for (i = 0; i < oclass->gpccs.ucode->code.size / 4; i++) {
1424
		if ((i & 0x3f) == 0)
1425 1426
			nvkm_wr32(device, 0x41a188, i >> 6);
		nvkm_wr32(device, 0x41a184, oclass->gpccs.ucode->code.data[i]);
1427
	}
B
Ben Skeggs 已提交
1428
	nvkm_mc(gr)->unk260(nvkm_mc(gr), 1);
1429

1430
	/* load register lists */
B
Ben Skeggs 已提交
1431 1432 1433 1434
	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);
1435

1436
	/* start HUB ucode running, it'll init the GPCs */
1437 1438
	nvkm_wr32(device, 0x40910c, 0x00000000);
	nvkm_wr32(device, 0x409100, 0x00000002);
1439 1440 1441 1442
	if (nvkm_msec(device, 2000,
		if (nvkm_rd32(device, 0x409800) & 0x80000000)
			break;
	) < 0) {
B
Ben Skeggs 已提交
1443
		gf100_gr_ctxctl_debug(gr);
1444 1445 1446
		return -EBUSY;
	}

1447
	gr->size = nvkm_rd32(device, 0x409804);
B
Ben Skeggs 已提交
1448 1449
	if (gr->data == NULL) {
		int ret = gf100_grctx_generate(gr);
1450
		if (ret) {
B
Ben Skeggs 已提交
1451
			nv_error(gr, "failed to construct context\n");
1452 1453
			return ret;
		}
1454 1455 1456
	}

	return 0;
1457 1458
}

1459
int
1460
gf100_gr_init(struct nvkm_object *object)
1461
{
B
Ben Skeggs 已提交
1462
	struct gf100_gr *gr = (void *)object;
1463 1464
	struct nvkm_device *device = gr->base.engine.subdev.device;
	struct gf100_gr_oclass *oclass = (void *)object->oclass;
B
Ben Skeggs 已提交
1465
	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
1466 1467 1468 1469
	u32 data[TPC_MAX / 8] = {};
	u8  tpcnr[GPC_MAX];
	int gpc, tpc, rop;
	int ret, i;
1470

B
Ben Skeggs 已提交
1471
	ret = nvkm_gr_init(&gr->base);
1472 1473 1474
	if (ret)
		return ret;

1475 1476 1477 1478 1479 1480 1481 1482
	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);
	nvkm_wr32(device, GPC_BCAST(0x08b4), gr->unk4188b4->addr >> 8);
	nvkm_wr32(device, GPC_BCAST(0x08b8), gr->unk4188b8->addr >> 8);
1483

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

B
Ben Skeggs 已提交
1486 1487
	memcpy(tpcnr, gr->tpc_nr, sizeof(gr->tpc_nr));
	for (i = 0, gpc = -1; i < gr->tpc_total; i++) {
1488
		do {
B
Ben Skeggs 已提交
1489
			gpc = (gpc + 1) % gr->gpc_nr;
1490
		} while (!tpcnr[gpc]);
B
Ben Skeggs 已提交
1491
		tpc = gr->tpc_nr[gpc] - tpcnr[gpc]--;
1492 1493 1494 1495

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

1496 1497 1498 1499
	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]);
1500

B
Ben Skeggs 已提交
1501
	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
1502
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
B
Ben Skeggs 已提交
1503
			gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
1504
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
B
Ben Skeggs 已提交
1505
			gr->tpc_total);
1506
		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
1507 1508
	}

B
Ben Skeggs 已提交
1509
	if (nv_device(gr)->chipset != 0xd7)
1510
		nvkm_wr32(device, GPC_BCAST(0x1bd4), magicgpc918);
M
Maarten Lankhorst 已提交
1511
	else
1512
		nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918);
B
Ben Skeggs 已提交
1513

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

1516
	nvkm_wr32(device, 0x400500, 0x00010001);
B
Ben Skeggs 已提交
1517

1518 1519
	nvkm_wr32(device, 0x400100, 0xffffffff);
	nvkm_wr32(device, 0x40013c, 0xffffffff);
B
Ben Skeggs 已提交
1520

1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
	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 已提交
1532 1533

	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
1534 1535 1536 1537
		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 已提交
1538
		for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
1539 1540 1541 1542 1543 1544 1545
			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);
1546
		}
1547 1548
		nvkm_wr32(device, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
		nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
1549 1550
	}

B
Ben Skeggs 已提交
1551
	for (rop = 0; rop < gr->rop_nr; rop++) {
1552 1553 1554 1555
		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);
1556
	}
1557

1558 1559 1560 1561 1562 1563
	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);
1564

1565
	nvkm_wr32(device, 0x400054, 0x34ce3464);
1566

B
Ben Skeggs 已提交
1567
	gf100_gr_zbc_init(gr);
1568

B
Ben Skeggs 已提交
1569
	return gf100_gr_init_ctxctl(gr);
1570 1571
}

1572
void
1573
gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc)
1574 1575 1576 1577 1578 1579
{
	kfree(fuc->data);
	fuc->data = NULL;
}

int
B
Ben Skeggs 已提交
1580
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
1581
		 struct gf100_gr_fuc *fuc)
1582
{
B
Ben Skeggs 已提交
1583
	struct nvkm_device *device = nv_device(gr);
1584
	const struct firmware *fw;
1585 1586
	char f[64];
	char cname[16];
1587
	int ret;
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597
	int i;

	/* Convert device name to lowercase */
	strncpy(cname, device->cname, sizeof(cname));
	cname[sizeof(cname) - 1] = '\0';
	i = strlen(cname);
	while (i) {
		--i;
		cname[i] = tolower(cname[i]);
	}
1598

1599
	snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
A
Alexandre Courbot 已提交
1600
	ret = request_firmware(&fw, f, nv_device_base(device));
1601
	if (ret) {
B
Ben Skeggs 已提交
1602
		nv_error(gr, "failed to load %s\n", fwname);
1603
		return ret;
1604 1605 1606 1607 1608 1609 1610 1611 1612
	}

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

void
1613
gf100_gr_dtor(struct nvkm_object *object)
1614
{
B
Ben Skeggs 已提交
1615
	struct gf100_gr *gr = (void *)object;
1616

B
Ben Skeggs 已提交
1617
	kfree(gr->data);
1618

B
Ben Skeggs 已提交
1619 1620 1621 1622
	gf100_gr_dtor_fw(&gr->fuc409c);
	gf100_gr_dtor_fw(&gr->fuc409d);
	gf100_gr_dtor_fw(&gr->fuc41ac);
	gf100_gr_dtor_fw(&gr->fuc41ad);
1623

B
Ben Skeggs 已提交
1624 1625
	nvkm_gpuobj_ref(NULL, &gr->unk4188b8);
	nvkm_gpuobj_ref(NULL, &gr->unk4188b4);
1626

B
Ben Skeggs 已提交
1627
	nvkm_gr_destroy(&gr->base);
1628 1629 1630
}

int
1631 1632 1633
gf100_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
	      struct nvkm_oclass *bclass, void *data, u32 size,
	      struct nvkm_object **pobject)
1634
{
1635 1636
	struct gf100_gr_oclass *oclass = (void *)bclass;
	struct nvkm_device *device = nv_device(parent);
B
Ben Skeggs 已提交
1637
	struct gf100_gr *gr;
1638
	bool use_ext_fw, enable;
1639
	int ret, i, j;
1640

1641 1642
	use_ext_fw = nvkm_boolopt(device->cfgopt, "NvGrUseFW",
				  oclass->fecs.ucode == NULL);
1643 1644
	enable = use_ext_fw || oclass->fecs.ucode != NULL;

B
Ben Skeggs 已提交
1645 1646
	ret = nvkm_gr_create(parent, engine, bclass, enable, &gr);
	*pobject = nv_object(gr);
1647 1648 1649
	if (ret)
		return ret;

B
Ben Skeggs 已提交
1650 1651
	nv_subdev(gr)->unit = 0x08001000;
	nv_subdev(gr)->intr = gf100_gr_intr;
1652

B
Ben Skeggs 已提交
1653
	gr->base.units = gf100_gr_units;
1654

1655
	if (use_ext_fw) {
B
Ben Skeggs 已提交
1656 1657 1658 1659 1660
		nv_info(gr, "using external firmware\n");
		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))
1661
			return -ENODEV;
B
Ben Skeggs 已提交
1662
		gr->firmware = true;
1663 1664
	}

B
Ben Skeggs 已提交
1665 1666
	ret = nvkm_gpuobj_new(nv_object(gr), NULL, 0x1000, 256, 0,
			      &gr->unk4188b4);
1667 1668
	if (ret)
		return ret;
1669

B
Ben Skeggs 已提交
1670 1671
	ret = nvkm_gpuobj_new(nv_object(gr), NULL, 0x1000, 256, 0,
			      &gr->unk4188b8);
1672
	if (ret)
1673 1674
		return ret;

1675
	for (i = 0; i < 0x1000; i += 4) {
B
Ben Skeggs 已提交
1676 1677 1678 1679
		nv_wo32(gr->unk4188b4, i, 0x00000010);
		nv_wo32(gr->unk4188b8, i, 0x00000010);
	}

1680 1681
	gr->rop_nr = (nvkm_rd32(device, 0x409604) & 0x001f0000) >> 16;
	gr->gpc_nr =  nvkm_rd32(device, 0x409604) & 0x0000001f;
B
Ben Skeggs 已提交
1682
	for (i = 0; i < gr->gpc_nr; i++) {
1683
		gr->tpc_nr[i]  = nvkm_rd32(device, GPC_UNIT(i, 0x2608));
B
Ben Skeggs 已提交
1684 1685 1686
		gr->tpc_total += gr->tpc_nr[i];
		gr->ppc_nr[i]  = oclass->ppc_nr;
		for (j = 0; j < gr->ppc_nr[i]; j++) {
1687
			u8 mask = nvkm_rd32(device, GPC_UNIT(i, 0x0c30 + (j * 4)));
B
Ben Skeggs 已提交
1688
			gr->ppc_tpc_nr[i][j] = hweight8(mask);
1689
		}
1690 1691 1692
	}

	/*XXX: these need figuring out... though it might not even matter */
B
Ben Skeggs 已提交
1693
	switch (nv_device(gr)->chipset) {
1694
	case 0xc0:
B
Ben Skeggs 已提交
1695 1696
		if (gr->tpc_total == 11) { /* 465, 3/4/4/0, 4 */
			gr->magic_not_rop_nr = 0x07;
1697
		} else
B
Ben Skeggs 已提交
1698 1699
		if (gr->tpc_total == 14) { /* 470, 3/3/4/4, 5 */
			gr->magic_not_rop_nr = 0x05;
1700
		} else
B
Ben Skeggs 已提交
1701 1702
		if (gr->tpc_total == 15) { /* 480, 3/4/4/4, 6 */
			gr->magic_not_rop_nr = 0x06;
1703 1704 1705
		}
		break;
	case 0xc3: /* 450, 4/0/0/0, 2 */
B
Ben Skeggs 已提交
1706
		gr->magic_not_rop_nr = 0x03;
1707 1708
		break;
	case 0xc4: /* 460, 3/4/0/0, 4 */
B
Ben Skeggs 已提交
1709
		gr->magic_not_rop_nr = 0x01;
1710 1711
		break;
	case 0xc1: /* 2/0/0/0, 1 */
B
Ben Skeggs 已提交
1712
		gr->magic_not_rop_nr = 0x01;
1713 1714
		break;
	case 0xc8: /* 4/4/3/4, 5 */
B
Ben Skeggs 已提交
1715
		gr->magic_not_rop_nr = 0x06;
1716 1717
		break;
	case 0xce: /* 4/4/0/0, 4 */
B
Ben Skeggs 已提交
1718
		gr->magic_not_rop_nr = 0x03;
1719 1720
		break;
	case 0xcf: /* 4/0/0/0, 3 */
B
Ben Skeggs 已提交
1721
		gr->magic_not_rop_nr = 0x03;
1722
		break;
M
Maarten Lankhorst 已提交
1723
	case 0xd7:
1724
	case 0xd9: /* 1/0/0/0, 1 */
1725
	case 0xea: /* gk20a */
1726
	case 0x12b: /* gm20b */
B
Ben Skeggs 已提交
1727
		gr->magic_not_rop_nr = 0x01;
1728 1729 1730
		break;
	}

B
Ben Skeggs 已提交
1731 1732
	nv_engine(gr)->cclass = *oclass->cclass;
	nv_engine(gr)->sclass =  oclass->sclass;
1733 1734 1735
	return 0;
}

1736
#include "fuc/hubgf100.fuc3.h"
1737

1738 1739 1740 1741 1742 1743
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),
1744 1745
};

1746
#include "fuc/gpcgf100.fuc3.h"
1747

1748 1749 1750 1751 1752 1753
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),
1754 1755
};

1756 1757
struct nvkm_oclass *
gf100_gr_oclass = &(struct gf100_gr_oclass) {
1758
	.base.handle = NV_ENGINE(GR, 0xc0),
1759 1760 1761 1762 1763
	.base.ofuncs = &(struct nvkm_ofuncs) {
		.ctor = gf100_gr_ctor,
		.dtor = gf100_gr_dtor,
		.init = gf100_gr_init,
		.fini = _nvkm_gr_fini,
1764
	},
1765 1766 1767 1768 1769
	.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,
1770
}.base;