2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "fuc/hubnvc0.fuc.h"
27 #include "fuc/gpcnvc0.fuc.h"
29 /*******************************************************************************
30 * Graphics object classes
31 ******************************************************************************/
33 static struct nouveau_oclass
34 nvc0_graph_sclass
[] = {
35 { 0x902d, &nouveau_object_ofuncs
},
36 { 0x9039, &nouveau_object_ofuncs
},
37 { 0x9097, &nouveau_object_ofuncs
},
38 { 0x90c0, &nouveau_object_ofuncs
},
42 static struct nouveau_oclass
43 nvc1_graph_sclass
[] = {
44 { 0x902d, &nouveau_object_ofuncs
},
45 { 0x9039, &nouveau_object_ofuncs
},
46 { 0x9097, &nouveau_object_ofuncs
},
47 { 0x90c0, &nouveau_object_ofuncs
},
48 { 0x9197, &nouveau_object_ofuncs
},
52 static struct nouveau_oclass
53 nvc8_graph_sclass
[] = {
54 { 0x902d, &nouveau_object_ofuncs
},
55 { 0x9039, &nouveau_object_ofuncs
},
56 { 0x9097, &nouveau_object_ofuncs
},
57 { 0x90c0, &nouveau_object_ofuncs
},
58 { 0x9197, &nouveau_object_ofuncs
},
59 { 0x9297, &nouveau_object_ofuncs
},
64 nvc0_graph_units(struct nouveau_graph
*graph
)
66 struct nvc0_graph_priv
*priv
= (void *)graph
;
69 cfg
= (u32
)priv
->gpc_nr
;
70 cfg
|= (u32
)priv
->tpc_total
<< 8;
71 cfg
|= (u64
)priv
->rop_nr
<< 32;
76 /*******************************************************************************
78 ******************************************************************************/
81 nvc0_graph_context_ctor(struct nouveau_object
*parent
,
82 struct nouveau_object
*engine
,
83 struct nouveau_oclass
*oclass
, void *args
, u32 size
,
84 struct nouveau_object
**pobject
)
86 struct nouveau_vm
*vm
= nouveau_client(parent
)->vm
;
87 struct nvc0_graph_priv
*priv
= (void *)engine
;
88 struct nvc0_graph_data
*data
= priv
->mmio_data
;
89 struct nvc0_graph_mmio
*mmio
= priv
->mmio_list
;
90 struct nvc0_graph_chan
*chan
;
93 /* allocate memory for context, and fill with default values */
94 ret
= nouveau_graph_context_create(parent
, engine
, oclass
, NULL
,
96 NVOBJ_FLAG_ZERO_ALLOC
, &chan
);
97 *pobject
= nv_object(chan
);
101 /* allocate memory for a "mmio list" buffer that's used by the HUB
102 * fuc to modify some per-context register settings on first load
105 ret
= nouveau_gpuobj_new(nv_object(chan
), NULL
, 0x1000, 0x100, 0,
110 ret
= nouveau_gpuobj_map_vm(nv_gpuobj(chan
->mmio
), vm
,
111 NV_MEM_ACCESS_RW
| NV_MEM_ACCESS_SYS
,
116 /* allocate buffers referenced by mmio list */
117 for (i
= 0; data
->size
&& i
< ARRAY_SIZE(priv
->mmio_data
); i
++) {
118 ret
= nouveau_gpuobj_new(nv_object(chan
), NULL
, data
->size
,
119 data
->align
, 0, &chan
->data
[i
].mem
);
123 ret
= nouveau_gpuobj_map_vm(chan
->data
[i
].mem
, vm
, data
->access
,
131 /* finally, fill in the mmio list and point the context at it */
132 for (i
= 0; mmio
->addr
&& i
< ARRAY_SIZE(priv
->mmio_list
); i
++) {
133 u32 addr
= mmio
->addr
;
134 u32 data
= mmio
->data
;
137 u64 info
= chan
->data
[mmio
->buffer
].vma
.offset
;
138 data
|= info
>> mmio
->shift
;
141 nv_wo32(chan
->mmio
, chan
->mmio_nr
++ * 4, addr
);
142 nv_wo32(chan
->mmio
, chan
->mmio_nr
++ * 4, data
);
146 for (i
= 0; i
< priv
->size
; i
+= 4)
147 nv_wo32(chan
, i
, priv
->data
[i
/ 4]);
149 if (!priv
->firmware
) {
150 nv_wo32(chan
, 0x00, chan
->mmio_nr
/ 2);
151 nv_wo32(chan
, 0x04, chan
->mmio_vma
.offset
>> 8);
153 nv_wo32(chan
, 0xf4, 0);
154 nv_wo32(chan
, 0xf8, 0);
155 nv_wo32(chan
, 0x10, chan
->mmio_nr
/ 2);
156 nv_wo32(chan
, 0x14, lower_32_bits(chan
->mmio_vma
.offset
));
157 nv_wo32(chan
, 0x18, upper_32_bits(chan
->mmio_vma
.offset
));
158 nv_wo32(chan
, 0x1c, 1);
159 nv_wo32(chan
, 0x20, 0);
160 nv_wo32(chan
, 0x28, 0);
161 nv_wo32(chan
, 0x2c, 0);
168 nvc0_graph_context_dtor(struct nouveau_object
*object
)
170 struct nvc0_graph_chan
*chan
= (void *)object
;
173 for (i
= 0; i
< ARRAY_SIZE(chan
->data
); i
++) {
174 nouveau_gpuobj_unmap(&chan
->data
[i
].vma
);
175 nouveau_gpuobj_ref(NULL
, &chan
->data
[i
].mem
);
178 nouveau_gpuobj_unmap(&chan
->mmio_vma
);
179 nouveau_gpuobj_ref(NULL
, &chan
->mmio
);
181 nouveau_graph_context_destroy(&chan
->base
);
184 static struct nouveau_oclass
185 nvc0_graph_cclass
= {
186 .ofuncs
= &(struct nouveau_ofuncs
) {
187 .ctor
= nvc0_graph_context_ctor
,
188 .dtor
= nvc0_graph_context_dtor
,
189 .init
= _nouveau_graph_context_init
,
190 .fini
= _nouveau_graph_context_fini
,
191 .rd32
= _nouveau_graph_context_rd32
,
192 .wr32
= _nouveau_graph_context_wr32
,
196 /*******************************************************************************
197 * PGRAPH engine/subdev functions
198 ******************************************************************************/
201 nvc0_graph_ctxctl_debug_unit(struct nvc0_graph_priv
*priv
, u32 base
)
203 nv_error(priv
, "%06x - done 0x%08x\n", base
,
204 nv_rd32(priv
, base
+ 0x400));
205 nv_error(priv
, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base
,
206 nv_rd32(priv
, base
+ 0x800), nv_rd32(priv
, base
+ 0x804),
207 nv_rd32(priv
, base
+ 0x808), nv_rd32(priv
, base
+ 0x80c));
208 nv_error(priv
, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base
,
209 nv_rd32(priv
, base
+ 0x810), nv_rd32(priv
, base
+ 0x814),
210 nv_rd32(priv
, base
+ 0x818), nv_rd32(priv
, base
+ 0x81c));
214 nvc0_graph_ctxctl_debug(struct nvc0_graph_priv
*priv
)
216 u32 gpcnr
= nv_rd32(priv
, 0x409604) & 0xffff;
219 nvc0_graph_ctxctl_debug_unit(priv
, 0x409000);
220 for (gpc
= 0; gpc
< gpcnr
; gpc
++)
221 nvc0_graph_ctxctl_debug_unit(priv
, 0x502000 + (gpc
* 0x8000));
225 nvc0_graph_ctxctl_isr(struct nvc0_graph_priv
*priv
)
227 u32 ustat
= nv_rd32(priv
, 0x409c18);
229 if (ustat
& 0x00000001)
230 nv_error(priv
, "CTXCTRL ucode error\n");
231 if (ustat
& 0x00080000)
232 nv_error(priv
, "CTXCTRL watchdog timeout\n");
233 if (ustat
& ~0x00080001)
234 nv_error(priv
, "CTXCTRL 0x%08x\n", ustat
);
236 nvc0_graph_ctxctl_debug(priv
);
237 nv_wr32(priv
, 0x409c20, ustat
);
240 static const struct nouveau_enum nvc0_mp_warp_error
[] = {
241 { 0x00, "NO_ERROR" },
242 { 0x01, "STACK_MISMATCH" },
243 { 0x05, "MISALIGNED_PC" },
244 { 0x08, "MISALIGNED_GPR" },
245 { 0x09, "INVALID_OPCODE" },
246 { 0x0d, "GPR_OUT_OF_BOUNDS" },
247 { 0x0e, "MEM_OUT_OF_BOUNDS" },
248 { 0x0f, "UNALIGNED_MEM_ACCESS" },
249 { 0x11, "INVALID_PARAM" },
253 static const struct nouveau_bitfield nvc0_mp_global_error
[] = {
254 { 0x00000004, "MULTIPLE_WARP_ERRORS" },
255 { 0x00000008, "OUT_OF_STACK_SPACE" },
260 nvc0_graph_trap_mp(struct nvc0_graph_priv
*priv
, int gpc
, int tpc
)
262 u32 werr
= nv_rd32(priv
, TPC_UNIT(gpc
, tpc
, 0x648));
263 u32 gerr
= nv_rd32(priv
, TPC_UNIT(gpc
, tpc
, 0x650));
265 nv_error(priv
, "GPC%i/TPC%i/MP trap:", gpc
, tpc
);
266 nouveau_bitfield_print(nvc0_mp_global_error
, gerr
);
269 nouveau_enum_print(nvc0_mp_warp_error
, werr
& 0xffff);
273 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x648), 0x00000000);
274 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x650), gerr
);
278 nvc0_graph_trap_tpc(struct nvc0_graph_priv
*priv
, int gpc
, int tpc
)
280 u32 stat
= nv_rd32(priv
, TPC_UNIT(gpc
, tpc
, 0x0508));
282 if (stat
& 0x00000001) {
283 u32 trap
= nv_rd32(priv
, TPC_UNIT(gpc
, tpc
, 0x0224));
284 nv_error(priv
, "GPC%d/TPC%d/TEX: 0x%08x\n", gpc
, tpc
, trap
);
285 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0224), 0xc0000000);
286 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0508), 0x00000001);
290 if (stat
& 0x00000002) {
291 nvc0_graph_trap_mp(priv
, gpc
, tpc
);
292 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0508), 0x00000002);
296 if (stat
& 0x00000004) {
297 u32 trap
= nv_rd32(priv
, TPC_UNIT(gpc
, tpc
, 0x0084));
298 nv_error(priv
, "GPC%d/TPC%d/POLY: 0x%08x\n", gpc
, tpc
, trap
);
299 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0084), 0xc0000000);
300 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0508), 0x00000004);
304 if (stat
& 0x00000008) {
305 u32 trap
= nv_rd32(priv
, TPC_UNIT(gpc
, tpc
, 0x048c));
306 nv_error(priv
, "GPC%d/TPC%d/L1C: 0x%08x\n", gpc
, tpc
, trap
);
307 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x048c), 0xc0000000);
308 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0508), 0x00000008);
313 nv_error(priv
, "GPC%d/TPC%d/0x%08x: unknown\n", gpc
, tpc
, stat
);
314 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x0508), stat
);
319 nvc0_graph_trap_gpc(struct nvc0_graph_priv
*priv
, int gpc
)
321 u32 stat
= nv_rd32(priv
, GPC_UNIT(gpc
, 0x2c90));
324 if (stat
& 0x00000001) {
325 u32 trap
= nv_rd32(priv
, GPC_UNIT(gpc
, 0x0420));
326 nv_error(priv
, "GPC%d/PROP: 0x%08x\n", gpc
, trap
);
327 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0420), 0xc0000000);
328 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), 0x00000001);
332 if (stat
& 0x00000002) {
333 u32 trap
= nv_rd32(priv
, GPC_UNIT(gpc
, 0x0900));
334 nv_error(priv
, "GPC%d/ZCULL: 0x%08x\n", gpc
, trap
);
335 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0900), 0xc0000000);
336 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), 0x00000002);
340 if (stat
& 0x00000004) {
341 u32 trap
= nv_rd32(priv
, GPC_UNIT(gpc
, 0x1028));
342 nv_error(priv
, "GPC%d/CCACHE: 0x%08x\n", gpc
, trap
);
343 nv_wr32(priv
, GPC_UNIT(gpc
, 0x1028), 0xc0000000);
344 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), 0x00000004);
348 if (stat
& 0x00000008) {
349 u32 trap
= nv_rd32(priv
, GPC_UNIT(gpc
, 0x0824));
350 nv_error(priv
, "GPC%d/ESETUP: 0x%08x\n", gpc
, trap
);
351 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0824), 0xc0000000);
352 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), 0x00000008);
356 for (tpc
= 0; tpc
< priv
->tpc_nr
[gpc
]; tpc
++) {
357 u32 mask
= 0x00010000 << tpc
;
359 nvc0_graph_trap_tpc(priv
, gpc
, tpc
);
360 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), mask
);
366 nv_error(priv
, "GPC%d/0x%08x: unknown\n", gpc
, stat
);
367 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), stat
);
372 nvc0_graph_trap_intr(struct nvc0_graph_priv
*priv
)
374 u32 trap
= nv_rd32(priv
, 0x400108);
377 if (trap
& 0x00000001) {
378 u32 stat
= nv_rd32(priv
, 0x404000);
379 nv_error(priv
, "DISPATCH 0x%08x\n", stat
);
380 nv_wr32(priv
, 0x404000, 0xc0000000);
381 nv_wr32(priv
, 0x400108, 0x00000001);
385 if (trap
& 0x00000002) {
386 u32 stat
= nv_rd32(priv
, 0x404600);
387 nv_error(priv
, "M2MF 0x%08x\n", stat
);
388 nv_wr32(priv
, 0x404600, 0xc0000000);
389 nv_wr32(priv
, 0x400108, 0x00000002);
393 if (trap
& 0x00000008) {
394 u32 stat
= nv_rd32(priv
, 0x408030);
395 nv_error(priv
, "CCACHE 0x%08x\n", stat
);
396 nv_wr32(priv
, 0x408030, 0xc0000000);
397 nv_wr32(priv
, 0x400108, 0x00000008);
401 if (trap
& 0x00000010) {
402 u32 stat
= nv_rd32(priv
, 0x405840);
403 nv_error(priv
, "SHADER 0x%08x\n", stat
);
404 nv_wr32(priv
, 0x405840, 0xc0000000);
405 nv_wr32(priv
, 0x400108, 0x00000010);
409 if (trap
& 0x00000040) {
410 u32 stat
= nv_rd32(priv
, 0x40601c);
411 nv_error(priv
, "UNK6 0x%08x\n", stat
);
412 nv_wr32(priv
, 0x40601c, 0xc0000000);
413 nv_wr32(priv
, 0x400108, 0x00000040);
417 if (trap
& 0x00000080) {
418 u32 stat
= nv_rd32(priv
, 0x404490);
419 nv_error(priv
, "MACRO 0x%08x\n", stat
);
420 nv_wr32(priv
, 0x404490, 0xc0000000);
421 nv_wr32(priv
, 0x400108, 0x00000080);
425 if (trap
& 0x01000000) {
426 u32 stat
= nv_rd32(priv
, 0x400118);
427 for (gpc
= 0; stat
&& gpc
< priv
->gpc_nr
; gpc
++) {
428 u32 mask
= 0x00000001 << gpc
;
430 nvc0_graph_trap_gpc(priv
, gpc
);
431 nv_wr32(priv
, 0x400118, mask
);
435 nv_wr32(priv
, 0x400108, 0x01000000);
439 if (trap
& 0x02000000) {
440 for (rop
= 0; rop
< priv
->rop_nr
; rop
++) {
441 u32 statz
= nv_rd32(priv
, ROP_UNIT(rop
, 0x070));
442 u32 statc
= nv_rd32(priv
, ROP_UNIT(rop
, 0x144));
443 nv_error(priv
, "ROP%d 0x%08x 0x%08x\n",
445 nv_wr32(priv
, ROP_UNIT(rop
, 0x070), 0xc0000000);
446 nv_wr32(priv
, ROP_UNIT(rop
, 0x144), 0xc0000000);
448 nv_wr32(priv
, 0x400108, 0x02000000);
453 nv_error(priv
, "TRAP UNHANDLED 0x%08x\n", trap
);
454 nv_wr32(priv
, 0x400108, trap
);
459 nvc0_graph_intr(struct nouveau_subdev
*subdev
)
461 struct nouveau_fifo
*pfifo
= nouveau_fifo(subdev
);
462 struct nouveau_engine
*engine
= nv_engine(subdev
);
463 struct nouveau_object
*engctx
;
464 struct nouveau_handle
*handle
;
465 struct nvc0_graph_priv
*priv
= (void *)subdev
;
466 u64 inst
= nv_rd32(priv
, 0x409b00) & 0x0fffffff;
467 u32 stat
= nv_rd32(priv
, 0x400100);
468 u32 addr
= nv_rd32(priv
, 0x400704);
469 u32 mthd
= (addr
& 0x00003ffc);
470 u32 subc
= (addr
& 0x00070000) >> 16;
471 u32 data
= nv_rd32(priv
, 0x400708);
472 u32 code
= nv_rd32(priv
, 0x400110);
473 u32
class = nv_rd32(priv
, 0x404200 + (subc
* 4));
476 engctx
= nouveau_engctx_get(engine
, inst
);
477 chid
= pfifo
->chid(pfifo
, engctx
);
479 if (stat
& 0x00000010) {
480 handle
= nouveau_handle_get_class(engctx
, class);
481 if (!handle
|| nv_call(handle
->object
, mthd
, data
)) {
483 "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
484 chid
, inst
<< 12, nouveau_client_name(engctx
),
485 subc
, class, mthd
, data
);
487 nouveau_handle_put(handle
);
488 nv_wr32(priv
, 0x400100, 0x00000010);
492 if (stat
& 0x00000020) {
494 "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
495 chid
, inst
<< 12, nouveau_client_name(engctx
), subc
,
497 nv_wr32(priv
, 0x400100, 0x00000020);
501 if (stat
& 0x00100000) {
502 nv_error(priv
, "DATA_ERROR [");
503 nouveau_enum_print(nv50_data_error_names
, code
);
504 pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
505 chid
, inst
<< 12, nouveau_client_name(engctx
), subc
,
507 nv_wr32(priv
, 0x400100, 0x00100000);
511 if (stat
& 0x00200000) {
512 nv_error(priv
, "TRAP ch %d [0x%010llx %s]\n", chid
, inst
<< 12,
513 nouveau_client_name(engctx
));
514 nvc0_graph_trap_intr(priv
);
515 nv_wr32(priv
, 0x400100, 0x00200000);
519 if (stat
& 0x00080000) {
520 nvc0_graph_ctxctl_isr(priv
);
521 nv_wr32(priv
, 0x400100, 0x00080000);
526 nv_error(priv
, "unknown stat 0x%08x\n", stat
);
527 nv_wr32(priv
, 0x400100, stat
);
530 nv_wr32(priv
, 0x400500, 0x00010001);
531 nouveau_engctx_put(engctx
);
535 nvc0_graph_ctor_fw(struct nvc0_graph_priv
*priv
, const char *fwname
,
536 struct nvc0_graph_fuc
*fuc
)
538 struct nouveau_device
*device
= nv_device(priv
);
539 const struct firmware
*fw
;
543 snprintf(f
, sizeof(f
), "nouveau/nv%02x_%s", device
->chipset
, fwname
);
544 ret
= request_firmware(&fw
, f
, &device
->pdev
->dev
);
546 snprintf(f
, sizeof(f
), "nouveau/%s", fwname
);
547 ret
= request_firmware(&fw
, f
, &device
->pdev
->dev
);
549 nv_error(priv
, "failed to load %s\n", fwname
);
554 fuc
->size
= fw
->size
;
555 fuc
->data
= kmemdup(fw
->data
, fuc
->size
, GFP_KERNEL
);
556 release_firmware(fw
);
557 return (fuc
->data
!= NULL
) ? 0 : -ENOMEM
;
561 nvc0_graph_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
562 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
563 struct nouveau_object
**pobject
)
565 struct nouveau_device
*device
= nv_device(parent
);
566 struct nvc0_graph_priv
*priv
;
567 bool enable
= device
->chipset
!= 0xd7;
570 ret
= nouveau_graph_create(parent
, engine
, oclass
, enable
, &priv
);
571 *pobject
= nv_object(priv
);
575 nv_subdev(priv
)->unit
= 0x18001000;
576 nv_subdev(priv
)->intr
= nvc0_graph_intr
;
577 nv_engine(priv
)->cclass
= &nvc0_graph_cclass
;
579 priv
->base
.units
= nvc0_graph_units
;
581 if (nouveau_boolopt(device
->cfgopt
, "NvGrUseFW", false)) {
582 nv_info(priv
, "using external firmware\n");
583 if (nvc0_graph_ctor_fw(priv
, "fuc409c", &priv
->fuc409c
) ||
584 nvc0_graph_ctor_fw(priv
, "fuc409d", &priv
->fuc409d
) ||
585 nvc0_graph_ctor_fw(priv
, "fuc41ac", &priv
->fuc41ac
) ||
586 nvc0_graph_ctor_fw(priv
, "fuc41ad", &priv
->fuc41ad
))
588 priv
->firmware
= true;
591 switch (nvc0_graph_class(priv
)) {
593 nv_engine(priv
)->sclass
= nvc0_graph_sclass
;
596 nv_engine(priv
)->sclass
= nvc1_graph_sclass
;
599 nv_engine(priv
)->sclass
= nvc8_graph_sclass
;
603 ret
= nouveau_gpuobj_new(nv_object(priv
), NULL
, 0x1000, 256, 0,
608 ret
= nouveau_gpuobj_new(nv_object(priv
), NULL
, 0x1000, 256, 0,
613 for (i
= 0; i
< 0x1000; i
+= 4) {
614 nv_wo32(priv
->unk4188b4
, i
, 0x00000010);
615 nv_wo32(priv
->unk4188b8
, i
, 0x00000010);
618 priv
->rop_nr
= (nv_rd32(priv
, 0x409604) & 0x001f0000) >> 16;
619 priv
->gpc_nr
= nv_rd32(priv
, 0x409604) & 0x0000001f;
620 for (i
= 0; i
< priv
->gpc_nr
; i
++) {
621 priv
->tpc_nr
[i
] = nv_rd32(priv
, GPC_UNIT(i
, 0x2608));
622 priv
->tpc_total
+= priv
->tpc_nr
[i
];
625 /*XXX: these need figuring out... though it might not even matter */
626 switch (nv_device(priv
)->chipset
) {
628 if (priv
->tpc_total
== 11) { /* 465, 3/4/4/0, 4 */
629 priv
->magic_not_rop_nr
= 0x07;
631 if (priv
->tpc_total
== 14) { /* 470, 3/3/4/4, 5 */
632 priv
->magic_not_rop_nr
= 0x05;
634 if (priv
->tpc_total
== 15) { /* 480, 3/4/4/4, 6 */
635 priv
->magic_not_rop_nr
= 0x06;
638 case 0xc3: /* 450, 4/0/0/0, 2 */
639 priv
->magic_not_rop_nr
= 0x03;
641 case 0xc4: /* 460, 3/4/0/0, 4 */
642 priv
->magic_not_rop_nr
= 0x01;
644 case 0xc1: /* 2/0/0/0, 1 */
645 priv
->magic_not_rop_nr
= 0x01;
647 case 0xc8: /* 4/4/3/4, 5 */
648 priv
->magic_not_rop_nr
= 0x06;
650 case 0xce: /* 4/4/0/0, 4 */
651 priv
->magic_not_rop_nr
= 0x03;
653 case 0xcf: /* 4/0/0/0, 3 */
654 priv
->magic_not_rop_nr
= 0x03;
656 case 0xd9: /* 1/0/0/0, 1 */
657 priv
->magic_not_rop_nr
= 0x01;
665 nvc0_graph_dtor_fw(struct nvc0_graph_fuc
*fuc
)
672 nvc0_graph_dtor(struct nouveau_object
*object
)
674 struct nvc0_graph_priv
*priv
= (void *)object
;
678 nvc0_graph_dtor_fw(&priv
->fuc409c
);
679 nvc0_graph_dtor_fw(&priv
->fuc409d
);
680 nvc0_graph_dtor_fw(&priv
->fuc41ac
);
681 nvc0_graph_dtor_fw(&priv
->fuc41ad
);
683 nouveau_gpuobj_ref(NULL
, &priv
->unk4188b8
);
684 nouveau_gpuobj_ref(NULL
, &priv
->unk4188b4
);
686 nouveau_graph_destroy(&priv
->base
);
690 nvc0_graph_init_obj418880(struct nvc0_graph_priv
*priv
)
694 nv_wr32(priv
, GPC_BCAST(0x0880), 0x00000000);
695 nv_wr32(priv
, GPC_BCAST(0x08a4), 0x00000000);
696 for (i
= 0; i
< 4; i
++)
697 nv_wr32(priv
, GPC_BCAST(0x0888) + (i
* 4), 0x00000000);
698 nv_wr32(priv
, GPC_BCAST(0x08b4), priv
->unk4188b4
->addr
>> 8);
699 nv_wr32(priv
, GPC_BCAST(0x08b8), priv
->unk4188b8
->addr
>> 8);
703 nvc0_graph_init_regs(struct nvc0_graph_priv
*priv
)
705 nv_wr32(priv
, 0x400080, 0x003083c2);
706 nv_wr32(priv
, 0x400088, 0x00006fe7);
707 nv_wr32(priv
, 0x40008c, 0x00000000);
708 nv_wr32(priv
, 0x400090, 0x00000030);
709 nv_wr32(priv
, 0x40013c, 0x013901f7);
710 nv_wr32(priv
, 0x400140, 0x00000100);
711 nv_wr32(priv
, 0x400144, 0x00000000);
712 nv_wr32(priv
, 0x400148, 0x00000110);
713 nv_wr32(priv
, 0x400138, 0x00000000);
714 nv_wr32(priv
, 0x400130, 0x00000000);
715 nv_wr32(priv
, 0x400134, 0x00000000);
716 nv_wr32(priv
, 0x400124, 0x00000002);
720 nvc0_graph_init_unk40xx(struct nvc0_graph_priv
*priv
)
722 nv_wr32(priv
, 0x40415c, 0x00000000);
723 nv_wr32(priv
, 0x404170, 0x00000000);
727 nvc0_graph_init_unk44xx(struct nvc0_graph_priv
*priv
)
729 nv_wr32(priv
, 0x404488, 0x00000000);
730 nv_wr32(priv
, 0x40448c, 0x00000000);
734 nvc0_graph_init_unk78xx(struct nvc0_graph_priv
*priv
)
736 nv_wr32(priv
, 0x407808, 0x00000000);
740 nvc0_graph_init_unk60xx(struct nvc0_graph_priv
*priv
)
742 nv_wr32(priv
, 0x406024, 0x00000000);
746 nvc0_graph_init_unk64xx(struct nvc0_graph_priv
*priv
)
748 switch (nv_device(priv
)->chipset
) {
751 nv_wr32(priv
, 0x4064f0, 0x00000000);
752 nv_wr32(priv
, 0x4064f4, 0x00000000);
753 nv_wr32(priv
, 0x4064f8, 0x00000000);
770 nvc0_graph_init_unk58xx(struct nvc0_graph_priv
*priv
)
772 nv_wr32(priv
, 0x405844, 0x00ffffff);
773 nv_wr32(priv
, 0x405850, 0x00000000);
774 switch (nv_device(priv
)->chipset
) {
782 nv_wr32(priv
, 0x405900, 0x00002834);
791 nv_wr32(priv
, 0x405908, 0x00000000);
792 switch (nv_device(priv
)->chipset
) {
795 nv_wr32(priv
, 0x405928, 0x00000000);
796 nv_wr32(priv
, 0x40592c, 0x00000000);
813 nvc0_graph_init_unk80xx(struct nvc0_graph_priv
*priv
)
815 nv_wr32(priv
, 0x40803c, 0x00000000);
819 nvc0_graph_init_gpc(struct nvc0_graph_priv
*priv
)
821 switch (nv_device(priv
)->chipset
) {
824 nv_wr32(priv
, 0x418408, 0x00000000);
838 nv_wr32(priv
, 0x4184a0, 0x00000000);
839 switch (nv_device(priv
)->chipset
) {
842 nv_wr32(priv
, 0x4184a4, 0x00000000);
843 nv_wr32(priv
, 0x4184a8, 0x00000000);
857 nv_wr32(priv
, 0x418604, 0x00000000);
858 nv_wr32(priv
, 0x418680, 0x00000000);
859 switch (nv_device(priv
)->chipset
) {
863 nv_wr32(priv
, 0x418714, 0x00000000);
871 nv_wr32(priv
, 0x418714, 0x80000000);
877 nv_wr32(priv
, 0x418384, 0x00000000);
878 nv_wr32(priv
, 0x418814, 0x00000000);
879 nv_wr32(priv
, 0x418818, 0x00000000);
880 nv_wr32(priv
, 0x41881c, 0x00000000);
881 nv_wr32(priv
, 0x418b04, 0x00000000);
882 switch (nv_device(priv
)->chipset
) {
887 nv_wr32(priv
, 0x4188c8, 0x00000000);
894 nv_wr32(priv
, 0x4188c8, 0x80000000);
900 nv_wr32(priv
, 0x4188cc, 0x00000000);
901 nv_wr32(priv
, 0x4188d0, 0x00010000);
902 nv_wr32(priv
, 0x4188d4, 0x00000001);
903 nv_wr32(priv
, 0x418910, 0x00010001);
904 nv_wr32(priv
, 0x418914, 0x00000301);
905 nv_wr32(priv
, 0x418918, 0x00800000);
906 nv_wr32(priv
, 0x418980, 0x77777770);
907 nv_wr32(priv
, 0x418984, 0x77777777);
908 nv_wr32(priv
, 0x418988, 0x77777777);
909 nv_wr32(priv
, 0x41898c, 0x77777777);
910 nv_wr32(priv
, 0x418c04, 0x00000000);
911 switch (nv_device(priv
)->chipset
) {
914 nv_wr32(priv
, 0x418c64, 0x00000000);
915 nv_wr32(priv
, 0x418c68, 0x00000000);
929 nv_wr32(priv
, 0x418c88, 0x00000000);
930 switch (nv_device(priv
)->chipset
) {
933 nv_wr32(priv
, 0x418cb4, 0x00000000);
934 nv_wr32(priv
, 0x418cb8, 0x00000000);
948 nv_wr32(priv
, 0x418d00, 0x00000000);
949 switch (nv_device(priv
)->chipset
) {
952 nv_wr32(priv
, 0x418d28, 0x00000000);
953 nv_wr32(priv
, 0x418d2c, 0x00000000);
954 nv_wr32(priv
, 0x418f00, 0x00000000);
968 nv_wr32(priv
, 0x418f08, 0x00000000);
969 switch (nv_device(priv
)->chipset
) {
972 nv_wr32(priv
, 0x418f20, 0x00000000);
973 nv_wr32(priv
, 0x418f24, 0x00000000);
976 nv_wr32(priv
, 0x418e00, 0x00000003);
984 nv_wr32(priv
, 0x418e00, 0x00000050);
990 nv_wr32(priv
, 0x418e08, 0x00000000);
991 switch (nv_device(priv
)->chipset
) {
994 nv_wr32(priv
, 0x418e1c, 0x00000000);
995 nv_wr32(priv
, 0x418e20, 0x00000000);
1009 nv_wr32(priv
, 0x41900c, 0x00000000);
1010 nv_wr32(priv
, 0x419018, 0x00000000);
1014 nvc0_graph_init_tpc(struct nvc0_graph_priv
*priv
)
1016 nv_wr32(priv
, 0x419d08, 0x00000000);
1017 nv_wr32(priv
, 0x419d0c, 0x00000000);
1018 nv_wr32(priv
, 0x419d10, 0x00000014);
1019 nv_wr32(priv
, 0x419ab0, 0x00000000);
1020 switch (nv_device(priv
)->chipset
) {
1028 nv_wr32(priv
, 0x419ac8, 0x00000000);
1037 nv_wr32(priv
, 0x419ab8, 0x000000e7);
1038 nv_wr32(priv
, 0x419abc, 0x00000000);
1039 nv_wr32(priv
, 0x419ac0, 0x00000000);
1040 switch (nv_device(priv
)->chipset
) {
1043 nv_wr32(priv
, 0x419ab4, 0x00000000);
1044 nv_wr32(priv
, 0x41980c, 0x00000010);
1053 nv_wr32(priv
, 0x41980c, 0x00000000);
1059 nv_wr32(priv
, 0x419810, 0x00000000);
1060 switch (nv_device(priv
)->chipset
) {
1064 nv_wr32(priv
, 0x419814, 0x00000004);
1072 nv_wr32(priv
, 0x419814, 0x00000000);
1078 nv_wr32(priv
, 0x419844, 0x00000000);
1079 switch (nv_device(priv
)->chipset
) {
1082 nv_wr32(priv
, 0x41984c, 0x0000a918);
1091 nv_wr32(priv
, 0x41984c, 0x00005bc5);
1097 nv_wr32(priv
, 0x419850, 0x00000000);
1098 nv_wr32(priv
, 0x419854, 0x00000000);
1099 nv_wr32(priv
, 0x419858, 0x00000000);
1100 nv_wr32(priv
, 0x41985c, 0x00000000);
1101 switch (nv_device(priv
)->chipset
) {
1109 nv_wr32(priv
, 0x419880, 0x00000002);
1118 nv_wr32(priv
, 0x419c98, 0x00000000);
1119 nv_wr32(priv
, 0x419ca8, 0x80000000);
1120 nv_wr32(priv
, 0x419cb4, 0x00000000);
1121 nv_wr32(priv
, 0x419cb8, 0x00008bf4);
1122 nv_wr32(priv
, 0x419cbc, 0x28137606);
1123 nv_wr32(priv
, 0x419cc0, 0x00000000);
1124 nv_wr32(priv
, 0x419cc4, 0x00000000);
1125 nv_wr32(priv
, 0x419bd4, 0x00800000);
1126 nv_wr32(priv
, 0x419bdc, 0x00000000);
1127 switch (nv_device(priv
)->chipset
) {
1130 nv_wr32(priv
, 0x419bf8, 0x00000000);
1131 nv_wr32(priv
, 0x419bfc, 0x00000000);
1145 nv_wr32(priv
, 0x419d2c, 0x00000000);
1146 switch (nv_device(priv
)->chipset
) {
1149 nv_wr32(priv
, 0x419d48, 0x00000000);
1150 nv_wr32(priv
, 0x419d4c, 0x00000000);
1164 nv_wr32(priv
, 0x419c0c, 0x00000000);
1165 nv_wr32(priv
, 0x419e00, 0x00000000);
1166 nv_wr32(priv
, 0x419ea0, 0x00000000);
1167 nv_wr32(priv
, 0x419ea4, 0x00000100);
1168 switch (nv_device(priv
)->chipset
) {
1171 nv_wr32(priv
, 0x419ea8, 0x02001100);
1180 nv_wr32(priv
, 0x419ea8, 0x00001100);
1187 switch (nv_device(priv
)->chipset
) {
1189 nv_wr32(priv
, 0x419eac, 0x11100f02);
1199 nv_wr32(priv
, 0x419eac, 0x11100702);
1205 nv_wr32(priv
, 0x419eb0, 0x00000003);
1206 nv_wr32(priv
, 0x419eb4, 0x00000000);
1207 nv_wr32(priv
, 0x419eb8, 0x00000000);
1208 nv_wr32(priv
, 0x419ebc, 0x00000000);
1209 nv_wr32(priv
, 0x419ec0, 0x00000000);
1210 switch (nv_device(priv
)->chipset
) {
1218 nv_wr32(priv
, 0x419ec8, 0x0e063818);
1219 nv_wr32(priv
, 0x419ecc, 0x0e060e06);
1220 nv_wr32(priv
, 0x419ed0, 0x00003818);
1224 nv_wr32(priv
, 0x419ec8, 0x06060618);
1225 nv_wr32(priv
, 0x419ed0, 0x0eff0e38);
1231 nv_wr32(priv
, 0x419ed4, 0x011104f1);
1232 nv_wr32(priv
, 0x419edc, 0x00000000);
1233 nv_wr32(priv
, 0x419f00, 0x00000000);
1234 nv_wr32(priv
, 0x419f2c, 0x00000000);
1238 nvc0_graph_init_unk88xx(struct nvc0_graph_priv
*priv
)
1240 nv_wr32(priv
, 0x40880c, 0x00000000);
1241 nv_wr32(priv
, 0x408910, 0x00000000);
1242 nv_wr32(priv
, 0x408914, 0x00000000);
1243 nv_wr32(priv
, 0x408918, 0x00000000);
1244 nv_wr32(priv
, 0x40891c, 0x00000000);
1245 nv_wr32(priv
, 0x408920, 0x00000000);
1246 nv_wr32(priv
, 0x408924, 0x00000000);
1247 nv_wr32(priv
, 0x408928, 0x00000000);
1248 nv_wr32(priv
, 0x40892c, 0x00000000);
1249 nv_wr32(priv
, 0x408930, 0x00000000);
1250 nv_wr32(priv
, 0x408950, 0x00000000);
1251 nv_wr32(priv
, 0x408954, 0x0000ffff);
1252 nv_wr32(priv
, 0x408984, 0x00000000);
1253 nv_wr32(priv
, 0x408988, 0x08040201);
1254 nv_wr32(priv
, 0x40898c, 0x80402010);
1258 nvc0_graph_init_gpc_0(struct nvc0_graph_priv
*priv
)
1260 const u32 magicgpc918
= DIV_ROUND_UP(0x00800000, priv
->tpc_total
);
1261 u32 data
[TPC_MAX
/ 8];
1265 nv_wr32(priv
, TPC_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */
1268 * TP ROP UNKVAL(magic_not_rop_nr)
1276 memset(data
, 0x00, sizeof(data
));
1277 memcpy(tpcnr
, priv
->tpc_nr
, sizeof(priv
->tpc_nr
));
1278 for (i
= 0, gpc
= -1; i
< priv
->tpc_total
; i
++) {
1280 gpc
= (gpc
+ 1) % priv
->gpc_nr
;
1281 } while (!tpcnr
[gpc
]);
1282 tpc
= priv
->tpc_nr
[gpc
] - tpcnr
[gpc
]--;
1284 data
[i
/ 8] |= tpc
<< ((i
% 8) * 4);
1287 nv_wr32(priv
, GPC_BCAST(0x0980), data
[0]);
1288 nv_wr32(priv
, GPC_BCAST(0x0984), data
[1]);
1289 nv_wr32(priv
, GPC_BCAST(0x0988), data
[2]);
1290 nv_wr32(priv
, GPC_BCAST(0x098c), data
[3]);
1292 for (gpc
= 0; gpc
< priv
->gpc_nr
; gpc
++) {
1293 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0914), priv
->magic_not_rop_nr
<< 8 |
1295 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0910), 0x00040000 | priv
->tpc_total
);
1296 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0918), magicgpc918
);
1299 nv_wr32(priv
, GPC_BCAST(0x1bd4), magicgpc918
);
1300 nv_wr32(priv
, GPC_BCAST(0x08ac), nv_rd32(priv
, 0x100800));
1304 nvc0_graph_init_units(struct nvc0_graph_priv
*priv
)
1306 nv_wr32(priv
, 0x409c24, 0x000f0000);
1307 nv_wr32(priv
, 0x404000, 0xc0000000); /* DISPATCH */
1308 nv_wr32(priv
, 0x404600, 0xc0000000); /* M2MF */
1309 nv_wr32(priv
, 0x408030, 0xc0000000);
1310 nv_wr32(priv
, 0x40601c, 0xc0000000);
1311 nv_wr32(priv
, 0x404490, 0xc0000000); /* MACRO */
1312 nv_wr32(priv
, 0x406018, 0xc0000000);
1313 nv_wr32(priv
, 0x405840, 0xc0000000);
1314 nv_wr32(priv
, 0x405844, 0x00ffffff);
1315 nv_mask(priv
, 0x419cc0, 0x00000008, 0x00000008);
1316 nv_mask(priv
, 0x419eb4, 0x00001000, 0x00001000);
1320 nvc0_graph_init_gpc_1(struct nvc0_graph_priv
*priv
)
1324 for (gpc
= 0; gpc
< priv
->gpc_nr
; gpc
++) {
1325 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0420), 0xc0000000);
1326 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0900), 0xc0000000);
1327 nv_wr32(priv
, GPC_UNIT(gpc
, 0x1028), 0xc0000000);
1328 nv_wr32(priv
, GPC_UNIT(gpc
, 0x0824), 0xc0000000);
1329 for (tpc
= 0; tpc
< priv
->tpc_nr
[gpc
]; tpc
++) {
1330 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x508), 0xffffffff);
1331 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x50c), 0xffffffff);
1332 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x224), 0xc0000000);
1333 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x48c), 0xc0000000);
1334 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x084), 0xc0000000);
1335 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x644), 0x001ffffe);
1336 nv_wr32(priv
, TPC_UNIT(gpc
, tpc
, 0x64c), 0x0000000f);
1338 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c90), 0xffffffff);
1339 nv_wr32(priv
, GPC_UNIT(gpc
, 0x2c94), 0xffffffff);
1344 nvc0_graph_init_rop(struct nvc0_graph_priv
*priv
)
1348 for (rop
= 0; rop
< priv
->rop_nr
; rop
++) {
1349 nv_wr32(priv
, ROP_UNIT(rop
, 0x144), 0xc0000000);
1350 nv_wr32(priv
, ROP_UNIT(rop
, 0x070), 0xc0000000);
1351 nv_wr32(priv
, ROP_UNIT(rop
, 0x204), 0xffffffff);
1352 nv_wr32(priv
, ROP_UNIT(rop
, 0x208), 0xffffffff);
1357 nvc0_graph_init_fw(struct nvc0_graph_priv
*priv
, u32 fuc_base
,
1358 struct nvc0_graph_fuc
*code
, struct nvc0_graph_fuc
*data
)
1362 nv_wr32(priv
, fuc_base
+ 0x01c0, 0x01000000);
1363 for (i
= 0; i
< data
->size
/ 4; i
++)
1364 nv_wr32(priv
, fuc_base
+ 0x01c4, data
->data
[i
]);
1366 nv_wr32(priv
, fuc_base
+ 0x0180, 0x01000000);
1367 for (i
= 0; i
< code
->size
/ 4; i
++) {
1368 if ((i
& 0x3f) == 0)
1369 nv_wr32(priv
, fuc_base
+ 0x0188, i
>> 6);
1370 nv_wr32(priv
, fuc_base
+ 0x0184, code
->data
[i
]);
1375 nvc0_graph_init_ctxctl(struct nvc0_graph_priv
*priv
)
1380 if (priv
->firmware
) {
1381 /* load fuc microcode */
1382 r000260
= nv_mask(priv
, 0x000260, 0x00000001, 0x00000000);
1383 nvc0_graph_init_fw(priv
, 0x409000, &priv
->fuc409c
,
1385 nvc0_graph_init_fw(priv
, 0x41a000, &priv
->fuc41ac
,
1387 nv_wr32(priv
, 0x000260, r000260
);
1389 /* start both of them running */
1390 nv_wr32(priv
, 0x409840, 0xffffffff);
1391 nv_wr32(priv
, 0x41a10c, 0x00000000);
1392 nv_wr32(priv
, 0x40910c, 0x00000000);
1393 nv_wr32(priv
, 0x41a100, 0x00000002);
1394 nv_wr32(priv
, 0x409100, 0x00000002);
1395 if (!nv_wait(priv
, 0x409800, 0x00000001, 0x00000001))
1396 nv_warn(priv
, "0x409800 wait failed\n");
1398 nv_wr32(priv
, 0x409840, 0xffffffff);
1399 nv_wr32(priv
, 0x409500, 0x7fffffff);
1400 nv_wr32(priv
, 0x409504, 0x00000021);
1402 nv_wr32(priv
, 0x409840, 0xffffffff);
1403 nv_wr32(priv
, 0x409500, 0x00000000);
1404 nv_wr32(priv
, 0x409504, 0x00000010);
1405 if (!nv_wait_ne(priv
, 0x409800, 0xffffffff, 0x00000000)) {
1406 nv_error(priv
, "fuc09 req 0x10 timeout\n");
1409 priv
->size
= nv_rd32(priv
, 0x409800);
1411 nv_wr32(priv
, 0x409840, 0xffffffff);
1412 nv_wr32(priv
, 0x409500, 0x00000000);
1413 nv_wr32(priv
, 0x409504, 0x00000016);
1414 if (!nv_wait_ne(priv
, 0x409800, 0xffffffff, 0x00000000)) {
1415 nv_error(priv
, "fuc09 req 0x16 timeout\n");
1419 nv_wr32(priv
, 0x409840, 0xffffffff);
1420 nv_wr32(priv
, 0x409500, 0x00000000);
1421 nv_wr32(priv
, 0x409504, 0x00000025);
1422 if (!nv_wait_ne(priv
, 0x409800, 0xffffffff, 0x00000000)) {
1423 nv_error(priv
, "fuc09 req 0x25 timeout\n");
1427 if (priv
->data
== NULL
) {
1428 int ret
= nvc0_grctx_generate(priv
);
1430 nv_error(priv
, "failed to construct context\n");
1438 /* load HUB microcode */
1439 r000260
= nv_mask(priv
, 0x000260, 0x00000001, 0x00000000);
1440 nv_wr32(priv
, 0x4091c0, 0x01000000);
1441 for (i
= 0; i
< sizeof(nvc0_grhub_data
) / 4; i
++)
1442 nv_wr32(priv
, 0x4091c4, nvc0_grhub_data
[i
]);
1444 nv_wr32(priv
, 0x409180, 0x01000000);
1445 for (i
= 0; i
< sizeof(nvc0_grhub_code
) / 4; i
++) {
1446 if ((i
& 0x3f) == 0)
1447 nv_wr32(priv
, 0x409188, i
>> 6);
1448 nv_wr32(priv
, 0x409184, nvc0_grhub_code
[i
]);
1451 /* load GPC microcode */
1452 nv_wr32(priv
, 0x41a1c0, 0x01000000);
1453 for (i
= 0; i
< sizeof(nvc0_grgpc_data
) / 4; i
++)
1454 nv_wr32(priv
, 0x41a1c4, nvc0_grgpc_data
[i
]);
1456 nv_wr32(priv
, 0x41a180, 0x01000000);
1457 for (i
= 0; i
< sizeof(nvc0_grgpc_code
) / 4; i
++) {
1458 if ((i
& 0x3f) == 0)
1459 nv_wr32(priv
, 0x41a188, i
>> 6);
1460 nv_wr32(priv
, 0x41a184, nvc0_grgpc_code
[i
]);
1462 nv_wr32(priv
, 0x000260, r000260
);
1464 /* start HUB ucode running, it'll init the GPCs */
1465 nv_wr32(priv
, 0x409800, nv_device(priv
)->chipset
);
1466 nv_wr32(priv
, 0x40910c, 0x00000000);
1467 nv_wr32(priv
, 0x409100, 0x00000002);
1468 if (!nv_wait(priv
, 0x409800, 0x80000000, 0x80000000)) {
1469 nv_error(priv
, "HUB_INIT timed out\n");
1470 nvc0_graph_ctxctl_debug(priv
);
1474 priv
->size
= nv_rd32(priv
, 0x409804);
1475 if (priv
->data
== NULL
) {
1476 int ret
= nvc0_grctx_generate(priv
);
1478 nv_error(priv
, "failed to construct context\n");
1487 nvc0_graph_init(struct nouveau_object
*object
)
1489 struct nvc0_graph_priv
*priv
= (void *)object
;
1492 ret
= nouveau_graph_init(&priv
->base
);
1496 nvc0_graph_init_obj418880(priv
);
1497 nvc0_graph_init_regs(priv
);
1498 nvc0_graph_init_unk40xx(priv
);
1499 nvc0_graph_init_unk44xx(priv
);
1500 nvc0_graph_init_unk78xx(priv
);
1501 nvc0_graph_init_unk60xx(priv
);
1502 nvc0_graph_init_unk64xx(priv
);
1503 nvc0_graph_init_unk58xx(priv
);
1504 nvc0_graph_init_unk80xx(priv
);
1505 nvc0_graph_init_gpc(priv
);
1506 nvc0_graph_init_tpc(priv
);
1507 nvc0_graph_init_unk88xx(priv
);
1508 nvc0_graph_init_gpc_0(priv
);
1509 /*nvc0_graph_init_unitplemented_c242(priv);*/
1511 nv_wr32(priv
, 0x400500, 0x00010001);
1512 nv_wr32(priv
, 0x400100, 0xffffffff);
1513 nv_wr32(priv
, 0x40013c, 0xffffffff);
1515 nvc0_graph_init_units(priv
);
1516 nvc0_graph_init_gpc_1(priv
);
1517 nvc0_graph_init_rop(priv
);
1519 nv_wr32(priv
, 0x400108, 0xffffffff);
1520 nv_wr32(priv
, 0x400138, 0xffffffff);
1521 nv_wr32(priv
, 0x400118, 0xffffffff);
1522 nv_wr32(priv
, 0x400130, 0xffffffff);
1523 nv_wr32(priv
, 0x40011c, 0xffffffff);
1524 nv_wr32(priv
, 0x400134, 0xffffffff);
1525 nv_wr32(priv
, 0x400054, 0x34ce3464);
1527 ret
= nvc0_graph_init_ctxctl(priv
);
1534 struct nouveau_oclass
1535 nvc0_graph_oclass
= {
1536 .handle
= NV_ENGINE(GR
, 0xc0),
1537 .ofuncs
= &(struct nouveau_ofuncs
) {
1538 .ctor
= nvc0_graph_ctor
,
1539 .dtor
= nvc0_graph_dtor
,
1540 .init
= nvc0_graph_init
,
1541 .fini
= _nouveau_graph_fini
,