]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
drm/nouveau: initial support for GK106
[~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         case 0xe6:
256                 priv->magic_not_rop_nr = 1;
257                 break;
258         default:
259                 break;
260         }
261
262         return 0;
263 }
264
265 static void
266 nve0_graph_init_obj418880(struct nvc0_graph_priv *priv)
267 {
268         int i;
269
270         nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
271         nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000);
272         for (i = 0; i < 4; i++)
273                 nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
274         nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
275         nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
276 }
277
278 static void
279 nve0_graph_init_regs(struct nvc0_graph_priv *priv)
280 {
281         nv_wr32(priv, 0x400080, 0x003083c2);
282         nv_wr32(priv, 0x400088, 0x0001ffe7);
283         nv_wr32(priv, 0x40008c, 0x00000000);
284         nv_wr32(priv, 0x400090, 0x00000030);
285         nv_wr32(priv, 0x40013c, 0x003901f7);
286         nv_wr32(priv, 0x400140, 0x00000100);
287         nv_wr32(priv, 0x400144, 0x00000000);
288         nv_wr32(priv, 0x400148, 0x00000110);
289         nv_wr32(priv, 0x400138, 0x00000000);
290         nv_wr32(priv, 0x400130, 0x00000000);
291         nv_wr32(priv, 0x400134, 0x00000000);
292         nv_wr32(priv, 0x400124, 0x00000002);
293 }
294
295 static void
296 nve0_graph_init_units(struct nvc0_graph_priv *priv)
297 {
298         nv_wr32(priv, 0x409ffc, 0x00000000);
299         nv_wr32(priv, 0x409c14, 0x00003e3e);
300         nv_wr32(priv, 0x409c24, 0x000f0000);
301
302         nv_wr32(priv, 0x404000, 0xc0000000);
303         nv_wr32(priv, 0x404600, 0xc0000000);
304         nv_wr32(priv, 0x408030, 0xc0000000);
305         nv_wr32(priv, 0x404490, 0xc0000000);
306         nv_wr32(priv, 0x406018, 0xc0000000);
307         nv_wr32(priv, 0x407020, 0xc0000000);
308         nv_wr32(priv, 0x405840, 0xc0000000);
309         nv_wr32(priv, 0x405844, 0x00ffffff);
310
311         nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
312         nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000);
313
314 }
315
316 static void
317 nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv)
318 {
319         const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
320         u32 data[TPC_MAX / 8];
321         u8  tpcnr[GPC_MAX];
322         int i, gpc, tpc;
323
324         nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
325
326         memset(data, 0x00, sizeof(data));
327         memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
328         for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
329                 do {
330                         gpc = (gpc + 1) % priv->gpc_nr;
331                 } while (!tpcnr[gpc]);
332                 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
333
334                 data[i / 8] |= tpc << ((i % 8) * 4);
335         }
336
337         nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
338         nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
339         nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
340         nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
341
342         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
343                 nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
344                                                   priv->tpc_nr[gpc]);
345                 nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total);
346                 nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
347         }
348
349         nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918);
350         nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
351 }
352
353 static void
354 nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv)
355 {
356         int gpc, tpc;
357
358         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
359                 nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000);
360                 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
361                 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
362                 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
363                 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
364                 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
365                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
366                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
367                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
368                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
369                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
370                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
371                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
372                 }
373                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
374                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
375         }
376 }
377
378 static void
379 nve0_graph_init_rop(struct nvc0_graph_priv *priv)
380 {
381         int rop;
382
383         for (rop = 0; rop < priv->rop_nr; rop++) {
384                 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
385                 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
386                 nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
387                 nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
388         }
389 }
390
391 static int
392 nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
393 {
394         u32 r000260;
395         int i;
396
397         if (priv->firmware) {
398                 /* load fuc microcode */
399                 r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
400                 nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d);
401                 nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
402                 nv_wr32(priv, 0x000260, r000260);
403
404                 /* start both of them running */
405                 nv_wr32(priv, 0x409840, 0xffffffff);
406                 nv_wr32(priv, 0x41a10c, 0x00000000);
407                 nv_wr32(priv, 0x40910c, 0x00000000);
408                 nv_wr32(priv, 0x41a100, 0x00000002);
409                 nv_wr32(priv, 0x409100, 0x00000002);
410                 if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001))
411                         nv_error(priv, "0x409800 wait failed\n");
412
413                 nv_wr32(priv, 0x409840, 0xffffffff);
414                 nv_wr32(priv, 0x409500, 0x7fffffff);
415                 nv_wr32(priv, 0x409504, 0x00000021);
416
417                 nv_wr32(priv, 0x409840, 0xffffffff);
418                 nv_wr32(priv, 0x409500, 0x00000000);
419                 nv_wr32(priv, 0x409504, 0x00000010);
420                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
421                         nv_error(priv, "fuc09 req 0x10 timeout\n");
422                         return -EBUSY;
423                 }
424                 priv->size = nv_rd32(priv, 0x409800);
425
426                 nv_wr32(priv, 0x409840, 0xffffffff);
427                 nv_wr32(priv, 0x409500, 0x00000000);
428                 nv_wr32(priv, 0x409504, 0x00000016);
429                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
430                         nv_error(priv, "fuc09 req 0x16 timeout\n");
431                         return -EBUSY;
432                 }
433
434                 nv_wr32(priv, 0x409840, 0xffffffff);
435                 nv_wr32(priv, 0x409500, 0x00000000);
436                 nv_wr32(priv, 0x409504, 0x00000025);
437                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
438                         nv_error(priv, "fuc09 req 0x25 timeout\n");
439                         return -EBUSY;
440                 }
441
442                 nv_wr32(priv, 0x409800, 0x00000000);
443                 nv_wr32(priv, 0x409500, 0x00000001);
444                 nv_wr32(priv, 0x409504, 0x00000030);
445                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
446                         nv_error(priv, "fuc09 req 0x30 timeout\n");
447                         return -EBUSY;
448                 }
449
450                 nv_wr32(priv, 0x409810, 0xb00095c8);
451                 nv_wr32(priv, 0x409800, 0x00000000);
452                 nv_wr32(priv, 0x409500, 0x00000001);
453                 nv_wr32(priv, 0x409504, 0x00000031);
454                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
455                         nv_error(priv, "fuc09 req 0x31 timeout\n");
456                         return -EBUSY;
457                 }
458
459                 nv_wr32(priv, 0x409810, 0x00080420);
460                 nv_wr32(priv, 0x409800, 0x00000000);
461                 nv_wr32(priv, 0x409500, 0x00000001);
462                 nv_wr32(priv, 0x409504, 0x00000032);
463                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
464                         nv_error(priv, "fuc09 req 0x32 timeout\n");
465                         return -EBUSY;
466                 }
467
468                 nv_wr32(priv, 0x409614, 0x00000070);
469                 nv_wr32(priv, 0x409614, 0x00000770);
470                 nv_wr32(priv, 0x40802c, 0x00000001);
471
472                 if (priv->data == NULL) {
473                         int ret = nve0_grctx_generate(priv);
474                         if (ret) {
475                                 nv_error(priv, "failed to construct context\n");
476                                 return ret;
477                         }
478                 }
479
480                 return 0;
481         }
482
483         /* load HUB microcode */
484         r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
485         nv_wr32(priv, 0x4091c0, 0x01000000);
486         for (i = 0; i < sizeof(nve0_grhub_data) / 4; i++)
487                 nv_wr32(priv, 0x4091c4, nve0_grhub_data[i]);
488
489         nv_wr32(priv, 0x409180, 0x01000000);
490         for (i = 0; i < sizeof(nve0_grhub_code) / 4; i++) {
491                 if ((i & 0x3f) == 0)
492                         nv_wr32(priv, 0x409188, i >> 6);
493                 nv_wr32(priv, 0x409184, nve0_grhub_code[i]);
494         }
495
496         /* load GPC microcode */
497         nv_wr32(priv, 0x41a1c0, 0x01000000);
498         for (i = 0; i < sizeof(nve0_grgpc_data) / 4; i++)
499                 nv_wr32(priv, 0x41a1c4, nve0_grgpc_data[i]);
500
501         nv_wr32(priv, 0x41a180, 0x01000000);
502         for (i = 0; i < sizeof(nve0_grgpc_code) / 4; i++) {
503                 if ((i & 0x3f) == 0)
504                         nv_wr32(priv, 0x41a188, i >> 6);
505                 nv_wr32(priv, 0x41a184, nve0_grgpc_code[i]);
506         }
507         nv_wr32(priv, 0x000260, r000260);
508
509         /* start HUB ucode running, it'll init the GPCs */
510         nv_wr32(priv, 0x409800, nv_device(priv)->chipset);
511         nv_wr32(priv, 0x40910c, 0x00000000);
512         nv_wr32(priv, 0x409100, 0x00000002);
513         if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) {
514                 nv_error(priv, "HUB_INIT timed out\n");
515                 nvc0_graph_ctxctl_debug(priv);
516                 return -EBUSY;
517         }
518
519         priv->size = nv_rd32(priv, 0x409804);
520         if (priv->data == NULL) {
521                 int ret = nve0_grctx_generate(priv);
522                 if (ret) {
523                         nv_error(priv, "failed to construct context\n");
524                         return ret;
525                 }
526         }
527
528         return 0;
529 }
530
531 static int
532 nve0_graph_init(struct nouveau_object *object)
533 {
534         struct nvc0_graph_priv *priv = (void *)object;
535         int ret;
536
537         ret = nouveau_graph_init(&priv->base);
538         if (ret)
539                 return ret;
540
541         nve0_graph_init_obj418880(priv);
542         nve0_graph_init_regs(priv);
543         nve0_graph_init_gpc_0(priv);
544
545         nv_wr32(priv, 0x400500, 0x00010001);
546         nv_wr32(priv, 0x400100, 0xffffffff);
547         nv_wr32(priv, 0x40013c, 0xffffffff);
548
549         nve0_graph_init_units(priv);
550         nve0_graph_init_gpc_1(priv);
551         nve0_graph_init_rop(priv);
552
553         nv_wr32(priv, 0x400108, 0xffffffff);
554         nv_wr32(priv, 0x400138, 0xffffffff);
555         nv_wr32(priv, 0x400118, 0xffffffff);
556         nv_wr32(priv, 0x400130, 0xffffffff);
557         nv_wr32(priv, 0x40011c, 0xffffffff);
558         nv_wr32(priv, 0x400134, 0xffffffff);
559         nv_wr32(priv, 0x400054, 0x34ce3464);
560
561         ret = nve0_graph_init_ctxctl(priv);
562         if (ret)
563                 return ret;
564
565         return 0;
566 }
567
568 struct nouveau_oclass
569 nve0_graph_oclass = {
570         .handle = NV_ENGINE(GR, 0xe0),
571         .ofuncs = &(struct nouveau_ofuncs) {
572                 .ctor = nve0_graph_ctor,
573                 .dtor = nvc0_graph_dtor,
574                 .init = nve0_graph_init,
575                 .fini = _nouveau_graph_fini,
576         },
577 };