Merge branch 'nfs-for-next' of git://linux-nfs.org/~trondmy/nfs-2.6 into for-3.10
[platform/adaptation/renesas_rcar/renesas_kernel.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                 struct nouveau_object *engctx)
83 {
84         u32 trap = nv_rd32(priv, 0x400108);
85         int rop;
86
87         if (trap & 0x00000001) {
88                 u32 stat = nv_rd32(priv, 0x404000);
89                 nv_error(priv, "DISPATCH ch %d [0x%010llx %s] 0x%08x\n",
90                          chid, inst, nouveau_client_name(engctx), stat);
91                 nv_wr32(priv, 0x404000, 0xc0000000);
92                 nv_wr32(priv, 0x400108, 0x00000001);
93                 trap &= ~0x00000001;
94         }
95
96         if (trap & 0x00000010) {
97                 u32 stat = nv_rd32(priv, 0x405840);
98                 nv_error(priv, "SHADER ch %d [0x%010llx %s] 0x%08x\n",
99                          chid, inst, nouveau_client_name(engctx), stat);
100                 nv_wr32(priv, 0x405840, 0xc0000000);
101                 nv_wr32(priv, 0x400108, 0x00000010);
102                 trap &= ~0x00000010;
103         }
104
105         if (trap & 0x02000000) {
106                 for (rop = 0; rop < priv->rop_nr; rop++) {
107                         u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070));
108                         u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144));
109                         nv_error(priv,
110                                  "ROP%d ch %d [0x%010llx %s] 0x%08x 0x%08x\n",
111                                  rop, chid, inst, nouveau_client_name(engctx),
112                                  statz, statc);
113                         nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
114                         nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
115                 }
116                 nv_wr32(priv, 0x400108, 0x02000000);
117                 trap &= ~0x02000000;
118         }
119
120         if (trap) {
121                 nv_error(priv, "TRAP ch %d [0x%010llx %s] 0x%08x\n",
122                          chid, inst, nouveau_client_name(engctx), trap);
123                 nv_wr32(priv, 0x400108, trap);
124         }
125 }
126
127 static void
128 nve0_graph_intr(struct nouveau_subdev *subdev)
129 {
130         struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
131         struct nouveau_engine *engine = nv_engine(subdev);
132         struct nouveau_object *engctx;
133         struct nouveau_handle *handle;
134         struct nvc0_graph_priv *priv = (void *)subdev;
135         u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff;
136         u32 stat = nv_rd32(priv, 0x400100);
137         u32 addr = nv_rd32(priv, 0x400704);
138         u32 mthd = (addr & 0x00003ffc);
139         u32 subc = (addr & 0x00070000) >> 16;
140         u32 data = nv_rd32(priv, 0x400708);
141         u32 code = nv_rd32(priv, 0x400110);
142         u32 class = nv_rd32(priv, 0x404200 + (subc * 4));
143         int chid;
144
145         engctx = nouveau_engctx_get(engine, inst);
146         chid   = pfifo->chid(pfifo, engctx);
147
148         if (stat & 0x00000010) {
149                 handle = nouveau_handle_get_class(engctx, class);
150                 if (!handle || nv_call(handle->object, mthd, data)) {
151                         nv_error(priv,
152                                  "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
153                                  chid, inst, nouveau_client_name(engctx), subc,
154                                  class, mthd, data);
155                 }
156                 nouveau_handle_put(handle);
157                 nv_wr32(priv, 0x400100, 0x00000010);
158                 stat &= ~0x00000010;
159         }
160
161         if (stat & 0x00000020) {
162                 nv_error(priv,
163                          "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
164                          chid, inst, nouveau_client_name(engctx), subc, class,
165                          mthd, data);
166                 nv_wr32(priv, 0x400100, 0x00000020);
167                 stat &= ~0x00000020;
168         }
169
170         if (stat & 0x00100000) {
171                 nv_error(priv, "DATA_ERROR [");
172                 nouveau_enum_print(nv50_data_error_names, code);
173                 pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
174                         chid, inst, nouveau_client_name(engctx), subc, class,
175                         mthd, data);
176                 nv_wr32(priv, 0x400100, 0x00100000);
177                 stat &= ~0x00100000;
178         }
179
180         if (stat & 0x00200000) {
181                 nve0_graph_trap_isr(priv, chid, inst, engctx);
182                 nv_wr32(priv, 0x400100, 0x00200000);
183                 stat &= ~0x00200000;
184         }
185
186         if (stat & 0x00080000) {
187                 nve0_graph_ctxctl_isr(priv);
188                 nv_wr32(priv, 0x400100, 0x00080000);
189                 stat &= ~0x00080000;
190         }
191
192         if (stat) {
193                 nv_error(priv, "unknown stat 0x%08x\n", stat);
194                 nv_wr32(priv, 0x400100, stat);
195         }
196
197         nv_wr32(priv, 0x400500, 0x00010001);
198         nouveau_engctx_put(engctx);
199 }
200
201 static int
202 nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
203                struct nouveau_oclass *oclass, void *data, u32 size,
204                struct nouveau_object **pobject)
205 {
206         struct nouveau_device *device = nv_device(parent);
207         struct nvc0_graph_priv *priv;
208         int ret, i;
209
210         ret = nouveau_graph_create(parent, engine, oclass, true, &priv);
211         *pobject = nv_object(priv);
212         if (ret)
213                 return ret;
214
215         nv_subdev(priv)->unit = 0x18001000;
216         nv_subdev(priv)->intr = nve0_graph_intr;
217         nv_engine(priv)->cclass = &nve0_graph_cclass;
218         nv_engine(priv)->sclass = nve0_graph_sclass;
219
220         if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) {
221                 nv_info(priv, "using external firmware\n");
222                 if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||
223                     nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) ||
224                     nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) ||
225                     nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad))
226                         return -EINVAL;
227                 priv->firmware = true;
228         }
229
230         ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4);
231         if (ret)
232                 return ret;
233
234         ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8);
235         if (ret)
236                 return ret;
237
238         for (i = 0; i < 0x1000; i += 4) {
239                 nv_wo32(priv->unk4188b4, i, 0x00000010);
240                 nv_wo32(priv->unk4188b8, i, 0x00000010);
241         }
242
243         priv->gpc_nr =  nv_rd32(priv, 0x409604) & 0x0000001f;
244         priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16;
245         for (i = 0; i < priv->gpc_nr; i++) {
246                 priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608));
247                 priv->tpc_total += priv->tpc_nr[i];
248         }
249
250         switch (nv_device(priv)->chipset) {
251         case 0xe4:
252                 if (priv->tpc_total == 8)
253                         priv->magic_not_rop_nr = 3;
254                 else
255                 if (priv->tpc_total == 7)
256                         priv->magic_not_rop_nr = 1;
257                 break;
258         case 0xe7:
259         case 0xe6:
260                 priv->magic_not_rop_nr = 1;
261                 break;
262         default:
263                 break;
264         }
265
266         return 0;
267 }
268
269 static void
270 nve0_graph_init_obj418880(struct nvc0_graph_priv *priv)
271 {
272         int i;
273
274         nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
275         nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000);
276         for (i = 0; i < 4; i++)
277                 nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
278         nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
279         nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
280 }
281
282 static void
283 nve0_graph_init_regs(struct nvc0_graph_priv *priv)
284 {
285         nv_wr32(priv, 0x400080, 0x003083c2);
286         nv_wr32(priv, 0x400088, 0x0001ffe7);
287         nv_wr32(priv, 0x40008c, 0x00000000);
288         nv_wr32(priv, 0x400090, 0x00000030);
289         nv_wr32(priv, 0x40013c, 0x003901f7);
290         nv_wr32(priv, 0x400140, 0x00000100);
291         nv_wr32(priv, 0x400144, 0x00000000);
292         nv_wr32(priv, 0x400148, 0x00000110);
293         nv_wr32(priv, 0x400138, 0x00000000);
294         nv_wr32(priv, 0x400130, 0x00000000);
295         nv_wr32(priv, 0x400134, 0x00000000);
296         nv_wr32(priv, 0x400124, 0x00000002);
297 }
298
299 static void
300 nve0_graph_init_units(struct nvc0_graph_priv *priv)
301 {
302         nv_wr32(priv, 0x409ffc, 0x00000000);
303         nv_wr32(priv, 0x409c14, 0x00003e3e);
304         nv_wr32(priv, 0x409c24, 0x000f0000);
305
306         nv_wr32(priv, 0x404000, 0xc0000000);
307         nv_wr32(priv, 0x404600, 0xc0000000);
308         nv_wr32(priv, 0x408030, 0xc0000000);
309         nv_wr32(priv, 0x404490, 0xc0000000);
310         nv_wr32(priv, 0x406018, 0xc0000000);
311         nv_wr32(priv, 0x407020, 0xc0000000);
312         nv_wr32(priv, 0x405840, 0xc0000000);
313         nv_wr32(priv, 0x405844, 0x00ffffff);
314
315         nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
316         nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000);
317
318 }
319
320 static void
321 nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv)
322 {
323         const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
324         u32 data[TPC_MAX / 8];
325         u8  tpcnr[GPC_MAX];
326         int i, gpc, tpc;
327
328         nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
329
330         memset(data, 0x00, sizeof(data));
331         memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
332         for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
333                 do {
334                         gpc = (gpc + 1) % priv->gpc_nr;
335                 } while (!tpcnr[gpc]);
336                 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
337
338                 data[i / 8] |= tpc << ((i % 8) * 4);
339         }
340
341         nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
342         nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
343         nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
344         nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
345
346         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
347                 nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
348                                                   priv->tpc_nr[gpc]);
349                 nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total);
350                 nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
351         }
352
353         nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
354         nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
355 }
356
357 static void
358 nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv)
359 {
360         int gpc, tpc;
361
362         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
363                 nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000);
364                 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
365                 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
366                 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
367                 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
368                 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
369                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
370                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
371                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
372                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
373                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
374                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
375                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
376                 }
377                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
378                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
379         }
380 }
381
382 static void
383 nve0_graph_init_rop(struct nvc0_graph_priv *priv)
384 {
385         int rop;
386
387         for (rop = 0; rop < priv->rop_nr; rop++) {
388                 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
389                 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
390                 nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
391                 nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
392         }
393 }
394
395 static int
396 nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
397 {
398         u32 r000260;
399         int i;
400
401         if (priv->firmware) {
402                 /* load fuc microcode */
403                 r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
404                 nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d);
405                 nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
406                 nv_wr32(priv, 0x000260, r000260);
407
408                 /* start both of them running */
409                 nv_wr32(priv, 0x409840, 0xffffffff);
410                 nv_wr32(priv, 0x41a10c, 0x00000000);
411                 nv_wr32(priv, 0x40910c, 0x00000000);
412                 nv_wr32(priv, 0x41a100, 0x00000002);
413                 nv_wr32(priv, 0x409100, 0x00000002);
414                 if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001))
415                         nv_error(priv, "0x409800 wait failed\n");
416
417                 nv_wr32(priv, 0x409840, 0xffffffff);
418                 nv_wr32(priv, 0x409500, 0x7fffffff);
419                 nv_wr32(priv, 0x409504, 0x00000021);
420
421                 nv_wr32(priv, 0x409840, 0xffffffff);
422                 nv_wr32(priv, 0x409500, 0x00000000);
423                 nv_wr32(priv, 0x409504, 0x00000010);
424                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
425                         nv_error(priv, "fuc09 req 0x10 timeout\n");
426                         return -EBUSY;
427                 }
428                 priv->size = nv_rd32(priv, 0x409800);
429
430                 nv_wr32(priv, 0x409840, 0xffffffff);
431                 nv_wr32(priv, 0x409500, 0x00000000);
432                 nv_wr32(priv, 0x409504, 0x00000016);
433                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
434                         nv_error(priv, "fuc09 req 0x16 timeout\n");
435                         return -EBUSY;
436                 }
437
438                 nv_wr32(priv, 0x409840, 0xffffffff);
439                 nv_wr32(priv, 0x409500, 0x00000000);
440                 nv_wr32(priv, 0x409504, 0x00000025);
441                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
442                         nv_error(priv, "fuc09 req 0x25 timeout\n");
443                         return -EBUSY;
444                 }
445
446                 nv_wr32(priv, 0x409800, 0x00000000);
447                 nv_wr32(priv, 0x409500, 0x00000001);
448                 nv_wr32(priv, 0x409504, 0x00000030);
449                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
450                         nv_error(priv, "fuc09 req 0x30 timeout\n");
451                         return -EBUSY;
452                 }
453
454                 nv_wr32(priv, 0x409810, 0xb00095c8);
455                 nv_wr32(priv, 0x409800, 0x00000000);
456                 nv_wr32(priv, 0x409500, 0x00000001);
457                 nv_wr32(priv, 0x409504, 0x00000031);
458                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
459                         nv_error(priv, "fuc09 req 0x31 timeout\n");
460                         return -EBUSY;
461                 }
462
463                 nv_wr32(priv, 0x409810, 0x00080420);
464                 nv_wr32(priv, 0x409800, 0x00000000);
465                 nv_wr32(priv, 0x409500, 0x00000001);
466                 nv_wr32(priv, 0x409504, 0x00000032);
467                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
468                         nv_error(priv, "fuc09 req 0x32 timeout\n");
469                         return -EBUSY;
470                 }
471
472                 nv_wr32(priv, 0x409614, 0x00000070);
473                 nv_wr32(priv, 0x409614, 0x00000770);
474                 nv_wr32(priv, 0x40802c, 0x00000001);
475
476                 if (priv->data == NULL) {
477                         int ret = nve0_grctx_generate(priv);
478                         if (ret) {
479                                 nv_error(priv, "failed to construct context\n");
480                                 return ret;
481                         }
482                 }
483
484                 return 0;
485         }
486
487         /* load HUB microcode */
488         r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
489         nv_wr32(priv, 0x4091c0, 0x01000000);
490         for (i = 0; i < sizeof(nve0_grhub_data) / 4; i++)
491                 nv_wr32(priv, 0x4091c4, nve0_grhub_data[i]);
492
493         nv_wr32(priv, 0x409180, 0x01000000);
494         for (i = 0; i < sizeof(nve0_grhub_code) / 4; i++) {
495                 if ((i & 0x3f) == 0)
496                         nv_wr32(priv, 0x409188, i >> 6);
497                 nv_wr32(priv, 0x409184, nve0_grhub_code[i]);
498         }
499
500         /* load GPC microcode */
501         nv_wr32(priv, 0x41a1c0, 0x01000000);
502         for (i = 0; i < sizeof(nve0_grgpc_data) / 4; i++)
503                 nv_wr32(priv, 0x41a1c4, nve0_grgpc_data[i]);
504
505         nv_wr32(priv, 0x41a180, 0x01000000);
506         for (i = 0; i < sizeof(nve0_grgpc_code) / 4; i++) {
507                 if ((i & 0x3f) == 0)
508                         nv_wr32(priv, 0x41a188, i >> 6);
509                 nv_wr32(priv, 0x41a184, nve0_grgpc_code[i]);
510         }
511         nv_wr32(priv, 0x000260, r000260);
512
513         /* start HUB ucode running, it'll init the GPCs */
514         nv_wr32(priv, 0x409800, nv_device(priv)->chipset);
515         nv_wr32(priv, 0x40910c, 0x00000000);
516         nv_wr32(priv, 0x409100, 0x00000002);
517         if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) {
518                 nv_error(priv, "HUB_INIT timed out\n");
519                 nvc0_graph_ctxctl_debug(priv);
520                 return -EBUSY;
521         }
522
523         priv->size = nv_rd32(priv, 0x409804);
524         if (priv->data == NULL) {
525                 int ret = nve0_grctx_generate(priv);
526                 if (ret) {
527                         nv_error(priv, "failed to construct context\n");
528                         return ret;
529                 }
530         }
531
532         return 0;
533 }
534
535 static int
536 nve0_graph_init(struct nouveau_object *object)
537 {
538         struct nvc0_graph_priv *priv = (void *)object;
539         int ret;
540
541         ret = nouveau_graph_init(&priv->base);
542         if (ret)
543                 return ret;
544
545         nve0_graph_init_obj418880(priv);
546         nve0_graph_init_regs(priv);
547         nve0_graph_init_gpc_0(priv);
548
549         nv_wr32(priv, 0x400500, 0x00010001);
550         nv_wr32(priv, 0x400100, 0xffffffff);
551         nv_wr32(priv, 0x40013c, 0xffffffff);
552
553         nve0_graph_init_units(priv);
554         nve0_graph_init_gpc_1(priv);
555         nve0_graph_init_rop(priv);
556
557         nv_wr32(priv, 0x400108, 0xffffffff);
558         nv_wr32(priv, 0x400138, 0xffffffff);
559         nv_wr32(priv, 0x400118, 0xffffffff);
560         nv_wr32(priv, 0x400130, 0xffffffff);
561         nv_wr32(priv, 0x40011c, 0xffffffff);
562         nv_wr32(priv, 0x400134, 0xffffffff);
563         nv_wr32(priv, 0x400054, 0x34ce3464);
564
565         ret = nve0_graph_init_ctxctl(priv);
566         if (ret)
567                 return ret;
568
569         return 0;
570 }
571
572 struct nouveau_oclass
573 nve0_graph_oclass = {
574         .handle = NV_ENGINE(GR, 0xe0),
575         .ofuncs = &(struct nouveau_ofuncs) {
576                 .ctor = nve0_graph_ctor,
577                 .dtor = nvc0_graph_dtor,
578                 .init = nve0_graph_init,
579                 .fini = _nouveau_graph_fini,
580         },
581 };