]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
539d4c72f192eb6bda3ff3385c4895854b8d95a8
[~shefty/rdma-dev.git] / drivers / gpu / drm / nouveau / core / engine / graph / nve0.c
1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24
25 #include "nvc0.h"
26 #include "fuc/hubnve0.fuc.h"
27 #include "fuc/gpcnve0.fuc.h"
28
29 /*******************************************************************************
30  * Graphics object classes
31  ******************************************************************************/
32
33 static struct nouveau_oclass
34 nve0_graph_sclass[] = {
35         { 0x902d, &nouveau_object_ofuncs },
36         { 0xa040, &nouveau_object_ofuncs },
37         { 0xa097, &nouveau_object_ofuncs },
38         { 0xa0c0, &nouveau_object_ofuncs },
39         { 0xa0b5, &nouveau_object_ofuncs },
40         {}
41 };
42
43 /*******************************************************************************
44  * PGRAPH context
45  ******************************************************************************/
46
47 static struct nouveau_oclass
48 nve0_graph_cclass = {
49         .handle = NV_ENGCTX(GR, 0xe0),
50         .ofuncs = &(struct nouveau_ofuncs) {
51                 .ctor = nvc0_graph_context_ctor,
52                 .dtor = nvc0_graph_context_dtor,
53                 .init = _nouveau_graph_context_init,
54                 .fini = _nouveau_graph_context_fini,
55                 .rd32 = _nouveau_graph_context_rd32,
56                 .wr32 = _nouveau_graph_context_wr32,
57         },
58 };
59
60 /*******************************************************************************
61  * PGRAPH engine/subdev functions
62  ******************************************************************************/
63
64 static void
65 nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
66 {
67         u32 ustat = nv_rd32(priv, 0x409c18);
68
69         if (ustat & 0x00000001)
70                 nv_error(priv, "CTXCTRL ucode error\n");
71         if (ustat & 0x00080000)
72                 nv_error(priv, "CTXCTRL watchdog timeout\n");
73         if (ustat & ~0x00080001)
74                 nv_error(priv, "CTXCTRL 0x%08x\n", ustat);
75
76         nvc0_graph_ctxctl_debug(priv);
77         nv_wr32(priv, 0x409c20, ustat);
78 }
79
80 static void
81 nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst)
82 {
83         u32 trap = nv_rd32(priv, 0x400108);
84         int rop;
85
86         if (trap & 0x00000001) {
87                 u32 stat = nv_rd32(priv, 0x404000);
88                 nv_error(priv, "DISPATCH ch %d [0x%010llx] 0x%08x\n",
89                          chid, inst, stat);
90                 nv_wr32(priv, 0x404000, 0xc0000000);
91                 nv_wr32(priv, 0x400108, 0x00000001);
92                 trap &= ~0x00000001;
93         }
94
95         if (trap & 0x00000010) {
96                 u32 stat = nv_rd32(priv, 0x405840);
97                 nv_error(priv, "SHADER ch %d [0x%010llx] 0x%08x\n",
98                          chid, inst, stat);
99                 nv_wr32(priv, 0x405840, 0xc0000000);
100                 nv_wr32(priv, 0x400108, 0x00000010);
101                 trap &= ~0x00000010;
102         }
103
104         if (trap & 0x02000000) {
105                 for (rop = 0; rop < priv->rop_nr; rop++) {
106                         u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070));
107                         u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144));
108                         nv_error(priv, "ROP%d ch %d [0x%010llx] 0x%08x 0x%08x\n",
109                                  rop, chid, inst, statz, statc);
110                         nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
111                         nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
112                 }
113                 nv_wr32(priv, 0x400108, 0x02000000);
114                 trap &= ~0x02000000;
115         }
116
117         if (trap) {
118                 nv_error(priv, "TRAP ch %d [0x%010llx] 0x%08x\n",
119                          chid, inst, trap);
120                 nv_wr32(priv, 0x400108, trap);
121         }
122 }
123
124 static void
125 nve0_graph_intr(struct nouveau_subdev *subdev)
126 {
127         struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
128         struct nouveau_engine *engine = nv_engine(subdev);
129         struct nouveau_object *engctx;
130         struct nouveau_handle *handle;
131         struct nvc0_graph_priv *priv = (void *)subdev;
132         u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff;
133         u32 stat = nv_rd32(priv, 0x400100);
134         u32 addr = nv_rd32(priv, 0x400704);
135         u32 mthd = (addr & 0x00003ffc);
136         u32 subc = (addr & 0x00070000) >> 16;
137         u32 data = nv_rd32(priv, 0x400708);
138         u32 code = nv_rd32(priv, 0x400110);
139         u32 class = nv_rd32(priv, 0x404200 + (subc * 4));
140         int chid;
141
142         engctx = nouveau_engctx_get(engine, inst);
143         chid   = pfifo->chid(pfifo, engctx);
144
145         if (stat & 0x00000010) {
146                 handle = nouveau_handle_get_class(engctx, class);
147                 if (!handle || nv_call(handle->object, mthd, data)) {
148                         nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] "
149                                      "subc %d class 0x%04x mthd 0x%04x "
150                                      "data 0x%08x\n",
151                                  chid, inst, subc, class, mthd, data);
152                 }
153                 nouveau_handle_put(handle);
154                 nv_wr32(priv, 0x400100, 0x00000010);
155                 stat &= ~0x00000010;
156         }
157
158         if (stat & 0x00000020) {
159                 nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d "
160                              "class 0x%04x mthd 0x%04x data 0x%08x\n",
161                          chid, inst, subc, class, mthd, data);
162                 nv_wr32(priv, 0x400100, 0x00000020);
163                 stat &= ~0x00000020;
164         }
165
166         if (stat & 0x00100000) {
167                 nv_error(priv, "DATA_ERROR [");
168                 nouveau_enum_print(nv50_data_error_names, code);
169                 printk("] ch %d [0x%010llx] subc %d class 0x%04x "
170                        "mthd 0x%04x data 0x%08x\n",
171                        chid, inst, subc, class, mthd, data);
172                 nv_wr32(priv, 0x400100, 0x00100000);
173                 stat &= ~0x00100000;
174         }
175
176         if (stat & 0x00200000) {
177                 nve0_graph_trap_isr(priv, chid, inst);
178                 nv_wr32(priv, 0x400100, 0x00200000);
179                 stat &= ~0x00200000;
180         }
181
182         if (stat & 0x00080000) {
183                 nve0_graph_ctxctl_isr(priv);
184                 nv_wr32(priv, 0x400100, 0x00080000);
185                 stat &= ~0x00080000;
186         }
187
188         if (stat) {
189                 nv_error(priv, "unknown stat 0x%08x\n", stat);
190                 nv_wr32(priv, 0x400100, stat);
191         }
192
193         nv_wr32(priv, 0x400500, 0x00010001);
194         nouveau_engctx_put(engctx);
195 }
196
197 static int
198 nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
199                struct nouveau_oclass *oclass, void *data, u32 size,
200                struct nouveau_object **pobject)
201 {
202         struct nouveau_device *device = nv_device(parent);
203         struct nvc0_graph_priv *priv;
204         int ret, i;
205
206         ret = nouveau_graph_create(parent, engine, oclass, false, &priv);
207         *pobject = nv_object(priv);
208         if (ret)
209                 return ret;
210
211         nv_subdev(priv)->unit = 0x18001000;
212         nv_subdev(priv)->intr = nve0_graph_intr;
213         nv_engine(priv)->cclass = &nve0_graph_cclass;
214         nv_engine(priv)->sclass = nve0_graph_sclass;
215
216         if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) {
217                 nv_info(priv, "using external firmware\n");
218                 if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||
219                     nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) ||
220                     nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) ||
221                     nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad))
222                         return -EINVAL;
223                 priv->firmware = true;
224         }
225
226         ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4);
227         if (ret)
228                 return ret;
229
230         ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8);
231         if (ret)
232                 return ret;
233
234         for (i = 0; i < 0x1000; i += 4) {
235                 nv_wo32(priv->unk4188b4, i, 0x00000010);
236                 nv_wo32(priv->unk4188b8, i, 0x00000010);
237         }
238
239         priv->gpc_nr =  nv_rd32(priv, 0x409604) & 0x0000001f;
240         priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16;
241         for (i = 0; i < priv->gpc_nr; i++) {
242                 priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608));
243                 priv->tpc_total += priv->tpc_nr[i];
244         }
245
246         switch (nv_device(priv)->chipset) {
247         case 0xe4:
248                 if (priv->tpc_total == 8)
249                         priv->magic_not_rop_nr = 3;
250                 else
251                 if (priv->tpc_total == 7)
252                         priv->magic_not_rop_nr = 1;
253                 break;
254         case 0xe7:
255                 priv->magic_not_rop_nr = 1;
256                 break;
257         default:
258                 break;
259         }
260
261         return 0;
262 }
263
264 static void
265 nve0_graph_init_obj418880(struct nvc0_graph_priv *priv)
266 {
267         int i;
268
269         nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
270         nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000);
271         for (i = 0; i < 4; i++)
272                 nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
273         nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
274         nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
275 }
276
277 static void
278 nve0_graph_init_regs(struct nvc0_graph_priv *priv)
279 {
280         nv_wr32(priv, 0x400080, 0x003083c2);
281         nv_wr32(priv, 0x400088, 0x0001ffe7);
282         nv_wr32(priv, 0x40008c, 0x00000000);
283         nv_wr32(priv, 0x400090, 0x00000030);
284         nv_wr32(priv, 0x40013c, 0x003901f7);
285         nv_wr32(priv, 0x400140, 0x00000100);
286         nv_wr32(priv, 0x400144, 0x00000000);
287         nv_wr32(priv, 0x400148, 0x00000110);
288         nv_wr32(priv, 0x400138, 0x00000000);
289         nv_wr32(priv, 0x400130, 0x00000000);
290         nv_wr32(priv, 0x400134, 0x00000000);
291         nv_wr32(priv, 0x400124, 0x00000002);
292 }
293
294 static void
295 nve0_graph_init_units(struct nvc0_graph_priv *priv)
296 {
297         nv_wr32(priv, 0x409ffc, 0x00000000);
298         nv_wr32(priv, 0x409c14, 0x00003e3e);
299         nv_wr32(priv, 0x409c24, 0x000f0000);
300
301         nv_wr32(priv, 0x404000, 0xc0000000);
302         nv_wr32(priv, 0x404600, 0xc0000000);
303         nv_wr32(priv, 0x408030, 0xc0000000);
304         nv_wr32(priv, 0x404490, 0xc0000000);
305         nv_wr32(priv, 0x406018, 0xc0000000);
306         nv_wr32(priv, 0x407020, 0xc0000000);
307         nv_wr32(priv, 0x405840, 0xc0000000);
308         nv_wr32(priv, 0x405844, 0x00ffffff);
309
310         nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
311         nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000);
312
313 }
314
315 static void
316 nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv)
317 {
318         const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
319         u32 data[TPC_MAX / 8];
320         u8  tpcnr[GPC_MAX];
321         int i, gpc, tpc;
322
323         nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
324
325         memset(data, 0x00, sizeof(data));
326         memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
327         for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
328                 do {
329                         gpc = (gpc + 1) % priv->gpc_nr;
330                 } while (!tpcnr[gpc]);
331                 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
332
333                 data[i / 8] |= tpc << ((i % 8) * 4);
334         }
335
336         nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
337         nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
338         nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
339         nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
340
341         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
342                 nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
343                                                   priv->tpc_nr[gpc]);
344                 nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total);
345                 nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
346         }
347
348         nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918);
349         nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
350 }
351
352 static void
353 nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv)
354 {
355         int gpc, tpc;
356
357         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
358                 nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000);
359                 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
360                 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
361                 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
362                 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
363                 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
364                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
365                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
366                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
367                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
368                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
369                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
370                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
371                 }
372                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
373                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
374         }
375 }
376
377 static void
378 nve0_graph_init_rop(struct nvc0_graph_priv *priv)
379 {
380         int rop;
381
382         for (rop = 0; rop < priv->rop_nr; rop++) {
383                 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
384                 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
385                 nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
386                 nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
387         }
388 }
389
390 static int
391 nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
392 {
393         u32 r000260;
394         int i;
395
396         if (priv->firmware) {
397                 /* load fuc microcode */
398                 r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
399                 nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d);
400                 nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
401                 nv_wr32(priv, 0x000260, r000260);
402
403                 /* start both of them running */
404                 nv_wr32(priv, 0x409840, 0xffffffff);
405                 nv_wr32(priv, 0x41a10c, 0x00000000);
406                 nv_wr32(priv, 0x40910c, 0x00000000);
407                 nv_wr32(priv, 0x41a100, 0x00000002);
408                 nv_wr32(priv, 0x409100, 0x00000002);
409                 if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001))
410                         nv_error(priv, "0x409800 wait failed\n");
411
412                 nv_wr32(priv, 0x409840, 0xffffffff);
413                 nv_wr32(priv, 0x409500, 0x7fffffff);
414                 nv_wr32(priv, 0x409504, 0x00000021);
415
416                 nv_wr32(priv, 0x409840, 0xffffffff);
417                 nv_wr32(priv, 0x409500, 0x00000000);
418                 nv_wr32(priv, 0x409504, 0x00000010);
419                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
420                         nv_error(priv, "fuc09 req 0x10 timeout\n");
421                         return -EBUSY;
422                 }
423                 priv->size = nv_rd32(priv, 0x409800);
424
425                 nv_wr32(priv, 0x409840, 0xffffffff);
426                 nv_wr32(priv, 0x409500, 0x00000000);
427                 nv_wr32(priv, 0x409504, 0x00000016);
428                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
429                         nv_error(priv, "fuc09 req 0x16 timeout\n");
430                         return -EBUSY;
431                 }
432
433                 nv_wr32(priv, 0x409840, 0xffffffff);
434                 nv_wr32(priv, 0x409500, 0x00000000);
435                 nv_wr32(priv, 0x409504, 0x00000025);
436                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
437                         nv_error(priv, "fuc09 req 0x25 timeout\n");
438                         return -EBUSY;
439                 }
440
441                 nv_wr32(priv, 0x409800, 0x00000000);
442                 nv_wr32(priv, 0x409500, 0x00000001);
443                 nv_wr32(priv, 0x409504, 0x00000030);
444                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
445                         nv_error(priv, "fuc09 req 0x30 timeout\n");
446                         return -EBUSY;
447                 }
448
449                 nv_wr32(priv, 0x409810, 0xb00095c8);
450                 nv_wr32(priv, 0x409800, 0x00000000);
451                 nv_wr32(priv, 0x409500, 0x00000001);
452                 nv_wr32(priv, 0x409504, 0x00000031);
453                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
454                         nv_error(priv, "fuc09 req 0x31 timeout\n");
455                         return -EBUSY;
456                 }
457
458                 nv_wr32(priv, 0x409810, 0x00080420);
459                 nv_wr32(priv, 0x409800, 0x00000000);
460                 nv_wr32(priv, 0x409500, 0x00000001);
461                 nv_wr32(priv, 0x409504, 0x00000032);
462                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
463                         nv_error(priv, "fuc09 req 0x32 timeout\n");
464                         return -EBUSY;
465                 }
466
467                 nv_wr32(priv, 0x409614, 0x00000070);
468                 nv_wr32(priv, 0x409614, 0x00000770);
469                 nv_wr32(priv, 0x40802c, 0x00000001);
470
471                 if (priv->data == NULL) {
472                         int ret = nve0_grctx_generate(priv);
473                         if (ret) {
474                                 nv_error(priv, "failed to construct context\n");
475                                 return ret;
476                         }
477                 }
478
479                 return 0;
480         }
481
482         /* load HUB microcode */
483         r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
484         nv_wr32(priv, 0x4091c0, 0x01000000);
485         for (i = 0; i < sizeof(nve0_grhub_data) / 4; i++)
486                 nv_wr32(priv, 0x4091c4, nve0_grhub_data[i]);
487
488         nv_wr32(priv, 0x409180, 0x01000000);
489         for (i = 0; i < sizeof(nve0_grhub_code) / 4; i++) {
490                 if ((i & 0x3f) == 0)
491                         nv_wr32(priv, 0x409188, i >> 6);
492                 nv_wr32(priv, 0x409184, nve0_grhub_code[i]);
493         }
494
495         /* load GPC microcode */
496         nv_wr32(priv, 0x41a1c0, 0x01000000);
497         for (i = 0; i < sizeof(nve0_grgpc_data) / 4; i++)
498                 nv_wr32(priv, 0x41a1c4, nve0_grgpc_data[i]);
499
500         nv_wr32(priv, 0x41a180, 0x01000000);
501         for (i = 0; i < sizeof(nve0_grgpc_code) / 4; i++) {
502                 if ((i & 0x3f) == 0)
503                         nv_wr32(priv, 0x41a188, i >> 6);
504                 nv_wr32(priv, 0x41a184, nve0_grgpc_code[i]);
505         }
506         nv_wr32(priv, 0x000260, r000260);
507
508         /* start HUB ucode running, it'll init the GPCs */
509         nv_wr32(priv, 0x409800, nv_device(priv)->chipset);
510         nv_wr32(priv, 0x40910c, 0x00000000);
511         nv_wr32(priv, 0x409100, 0x00000002);
512         if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) {
513                 nv_error(priv, "HUB_INIT timed out\n");
514                 nvc0_graph_ctxctl_debug(priv);
515                 return -EBUSY;
516         }
517
518         priv->size = nv_rd32(priv, 0x409804);
519         if (priv->data == NULL) {
520                 int ret = nve0_grctx_generate(priv);
521                 if (ret) {
522                         nv_error(priv, "failed to construct context\n");
523                         return ret;
524                 }
525         }
526
527         return 0;
528 }
529
530 static int
531 nve0_graph_init(struct nouveau_object *object)
532 {
533         struct nvc0_graph_priv *priv = (void *)object;
534         int ret;
535
536         ret = nouveau_graph_init(&priv->base);
537         if (ret)
538                 return ret;
539
540         nve0_graph_init_obj418880(priv);
541         nve0_graph_init_regs(priv);
542         nve0_graph_init_gpc_0(priv);
543
544         nv_wr32(priv, 0x400500, 0x00010001);
545         nv_wr32(priv, 0x400100, 0xffffffff);
546         nv_wr32(priv, 0x40013c, 0xffffffff);
547
548         nve0_graph_init_units(priv);
549         nve0_graph_init_gpc_1(priv);
550         nve0_graph_init_rop(priv);
551
552         nv_wr32(priv, 0x400108, 0xffffffff);
553         nv_wr32(priv, 0x400138, 0xffffffff);
554         nv_wr32(priv, 0x400118, 0xffffffff);
555         nv_wr32(priv, 0x400130, 0xffffffff);
556         nv_wr32(priv, 0x40011c, 0xffffffff);
557         nv_wr32(priv, 0x400134, 0xffffffff);
558         nv_wr32(priv, 0x400054, 0x34ce3464);
559
560         ret = nve0_graph_init_ctxctl(priv);
561         if (ret)
562                 return ret;
563
564         return 0;
565 }
566
567 struct nouveau_oclass
568 nve0_graph_oclass = {
569         .handle = NV_ENGINE(GR, 0xe0),
570         .ofuncs = &(struct nouveau_ofuncs) {
571                 .ctor = nve0_graph_ctor,
572                 .dtor = nvc0_graph_dtor,
573                 .init = nve0_graph_init,
574                 .fini = _nouveau_graph_fini,
575         },
576 };