Commit | Line | Data |
---|---|---|
ab394543 | 1 | /* |
ebb945a9 | 2 | * Copyright 2012 Red Hat Inc. |
ab394543 BS |
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 | ||
c4afbe74 | 25 | #include "nvc0.h" |
ab394543 | 26 | |
ebb945a9 BS |
27 | /******************************************************************************* |
28 | * Graphics object classes | |
29 | ******************************************************************************/ | |
30 | ||
31 | static struct nouveau_oclass | |
32 | nve0_graph_sclass[] = { | |
33 | { 0x902d, &nouveau_object_ofuncs }, | |
34 | { 0xa040, &nouveau_object_ofuncs }, | |
35 | { 0xa097, &nouveau_object_ofuncs }, | |
36 | { 0xa0c0, &nouveau_object_ofuncs }, | |
37 | { 0xa0b5, &nouveau_object_ofuncs }, | |
38 | {} | |
39 | }; | |
40 | ||
41 | /******************************************************************************* | |
42 | * PGRAPH context | |
43 | ******************************************************************************/ | |
44 | ||
45 | static struct nouveau_oclass | |
46 | nve0_graph_cclass = { | |
47 | .handle = NV_ENGCTX(GR, 0xe0), | |
48 | .ofuncs = &(struct nouveau_ofuncs) { | |
49 | .ctor = nvc0_graph_context_ctor, | |
50 | .dtor = nvc0_graph_context_dtor, | |
51 | .init = _nouveau_graph_context_init, | |
52 | .fini = _nouveau_graph_context_fini, | |
53 | .rd32 = _nouveau_graph_context_rd32, | |
54 | .wr32 = _nouveau_graph_context_wr32, | |
55 | }, | |
56 | }; | |
57 | ||
58 | /******************************************************************************* | |
59 | * PGRAPH engine/subdev functions | |
60 | ******************************************************************************/ | |
61 | ||
ab394543 | 62 | static void |
ebb945a9 | 63 | nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) |
ab394543 | 64 | { |
ebb945a9 BS |
65 | u32 ustat = nv_rd32(priv, 0x409c18); |
66 | ||
67 | if (ustat & 0x00000001) | |
68 | nv_error(priv, "CTXCTRL ucode error\n"); | |
69 | if (ustat & 0x00080000) | |
70 | nv_error(priv, "CTXCTRL watchdog timeout\n"); | |
71 | if (ustat & ~0x00080001) | |
72 | nv_error(priv, "CTXCTRL 0x%08x\n", ustat); | |
73 | ||
74 | nvc0_graph_ctxctl_debug(priv); | |
75 | nv_wr32(priv, 0x409c20, ustat); | |
ab394543 BS |
76 | } |
77 | ||
78 | static void | |
ebb945a9 | 79 | nve0_graph_trap_isr(struct nvc0_graph_priv *priv, u64 inst) |
ab394543 | 80 | { |
ebb945a9 BS |
81 | u32 trap = nv_rd32(priv, 0x400108); |
82 | int rop; | |
83 | ||
84 | if (trap & 0x00000001) { | |
85 | u32 stat = nv_rd32(priv, 0x404000); | |
86 | nv_error(priv, "DISPATCH ch 0x%010llx 0x%08x\n", inst, stat); | |
87 | nv_wr32(priv, 0x404000, 0xc0000000); | |
88 | nv_wr32(priv, 0x400108, 0x00000001); | |
89 | trap &= ~0x00000001; | |
90 | } | |
ab394543 | 91 | |
ebb945a9 BS |
92 | if (trap & 0x00000010) { |
93 | u32 stat = nv_rd32(priv, 0x405840); | |
94 | nv_error(priv, "SHADER ch 0x%010llx 0x%08x\n", inst, stat); | |
95 | nv_wr32(priv, 0x405840, 0xc0000000); | |
96 | nv_wr32(priv, 0x400108, 0x00000010); | |
97 | trap &= ~0x00000010; | |
98 | } | |
99 | ||
100 | if (trap & 0x02000000) { | |
101 | for (rop = 0; rop < priv->rop_nr; rop++) { | |
102 | u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); | |
103 | u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); | |
104 | nv_error(priv, "ROP%d ch 0x%010llx 0x%08x 0x%08x\n", | |
105 | rop, inst, statz, statc); | |
106 | nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); | |
107 | nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); | |
108 | } | |
109 | nv_wr32(priv, 0x400108, 0x02000000); | |
110 | trap &= ~0x02000000; | |
111 | } | |
112 | ||
113 | if (trap) { | |
114 | nv_error(priv, "TRAP ch 0x%010llx 0x%08x\n", inst, trap); | |
115 | nv_wr32(priv, 0x400108, trap); | |
116 | } | |
ab394543 BS |
117 | } |
118 | ||
ebb945a9 BS |
119 | static void |
120 | nve0_graph_intr(struct nouveau_subdev *subdev) | |
ab394543 | 121 | { |
ebb945a9 BS |
122 | struct nvc0_graph_priv *priv = (void *)subdev; |
123 | struct nouveau_engine *engine = nv_engine(subdev); | |
124 | struct nouveau_handle *handle = NULL; | |
125 | u64 inst = (u64)(nv_rd32(priv, 0x409b00) & 0x0fffffff) << 12; | |
126 | u32 stat = nv_rd32(priv, 0x400100); | |
127 | u32 addr = nv_rd32(priv, 0x400704); | |
128 | u32 mthd = (addr & 0x00003ffc); | |
129 | u32 subc = (addr & 0x00070000) >> 16; | |
130 | u32 data = nv_rd32(priv, 0x400708); | |
131 | u32 code = nv_rd32(priv, 0x400110); | |
132 | u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); | |
133 | ||
134 | if (stat & 0x00000010) { | |
135 | handle = nouveau_engctx_lookup_class(engine, inst, class); | |
136 | if (!handle || nv_call(handle->object, mthd, data)) { | |
137 | nv_error(priv, "ILLEGAL_MTHD ch 0x%010llx " | |
138 | "subc %d class 0x%04x mthd 0x%04x " | |
139 | "data 0x%08x\n", | |
140 | inst, subc, class, mthd, data); | |
141 | } | |
142 | nouveau_engctx_handle_put(handle); | |
143 | nv_wr32(priv, 0x400100, 0x00000010); | |
144 | stat &= ~0x00000010; | |
145 | } | |
146 | ||
147 | if (stat & 0x00000020) { | |
148 | nv_error(priv, "ILLEGAL_CLASS ch 0x%010llx subc %d " | |
149 | "class 0x%04x mthd 0x%04x data 0x%08x\n", | |
150 | inst, subc, class, mthd, data); | |
151 | nv_wr32(priv, 0x400100, 0x00000020); | |
152 | stat &= ~0x00000020; | |
153 | } | |
154 | ||
155 | if (stat & 0x00100000) { | |
156 | nv_error(priv, "DATA_ERROR ["); | |
157 | nouveau_enum_print(nv50_data_error_names, code); | |
158 | printk("] ch 0x%010llx subc %d class 0x%04x " | |
159 | "mthd 0x%04x data 0x%08x\n", | |
160 | inst, subc, class, mthd, data); | |
161 | nv_wr32(priv, 0x400100, 0x00100000); | |
162 | stat &= ~0x00100000; | |
163 | } | |
164 | ||
165 | if (stat & 0x00200000) { | |
166 | nve0_graph_trap_isr(priv, inst); | |
167 | nv_wr32(priv, 0x400100, 0x00200000); | |
168 | stat &= ~0x00200000; | |
169 | } | |
170 | ||
171 | if (stat & 0x00080000) { | |
172 | nve0_graph_ctxctl_isr(priv); | |
173 | nv_wr32(priv, 0x400100, 0x00080000); | |
174 | stat &= ~0x00080000; | |
175 | } | |
176 | ||
177 | if (stat) { | |
178 | nv_error(priv, "unknown stat 0x%08x\n", stat); | |
179 | nv_wr32(priv, 0x400100, stat); | |
180 | } | |
181 | ||
182 | nv_wr32(priv, 0x400500, 0x00010001); | |
ab394543 BS |
183 | } |
184 | ||
185 | static int | |
ebb945a9 BS |
186 | nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
187 | struct nouveau_oclass *oclass, void *data, u32 size, | |
188 | struct nouveau_object **pobject) | |
ab394543 | 189 | { |
ebb945a9 BS |
190 | struct nvc0_graph_priv *priv; |
191 | int ret, i; | |
192 | ||
193 | ret = nouveau_graph_create(parent, engine, oclass, false, &priv); | |
194 | *pobject = nv_object(priv); | |
195 | if (ret) | |
196 | return ret; | |
197 | ||
198 | nv_subdev(priv)->unit = 0x18001000; | |
199 | nv_subdev(priv)->intr = nve0_graph_intr; | |
200 | nv_engine(priv)->cclass = &nve0_graph_cclass; | |
201 | nv_engine(priv)->sclass = nve0_graph_sclass; | |
202 | ||
203 | nv_info(priv, "using external firmware\n"); | |
204 | if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || | |
205 | nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || | |
206 | nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || | |
207 | nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) | |
208 | return -EINVAL; | |
209 | priv->firmware = true; | |
210 | ||
211 | ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); | |
212 | if (ret) | |
213 | return ret; | |
214 | ||
215 | ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); | |
216 | if (ret) | |
217 | return ret; | |
218 | ||
219 | for (i = 0; i < 0x1000; i += 4) { | |
220 | nv_wo32(priv->unk4188b4, i, 0x00000010); | |
221 | nv_wo32(priv->unk4188b8, i, 0x00000010); | |
222 | } | |
223 | ||
224 | priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; | |
225 | priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; | |
226 | for (i = 0; i < priv->gpc_nr; i++) { | |
227 | priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); | |
228 | priv->tpc_total += priv->tpc_nr[i]; | |
229 | } | |
230 | ||
231 | switch (nv_device(priv)->chipset) { | |
232 | case 0xe4: | |
233 | if (priv->tpc_total == 8) | |
234 | priv->magic_not_rop_nr = 3; | |
235 | else | |
236 | if (priv->tpc_total == 7) | |
237 | priv->magic_not_rop_nr = 1; | |
238 | break; | |
239 | case 0xe7: | |
240 | priv->magic_not_rop_nr = 1; | |
241 | break; | |
242 | default: | |
243 | break; | |
244 | } | |
245 | ||
ab394543 BS |
246 | return 0; |
247 | } | |
248 | ||
249 | static void | |
ebb945a9 | 250 | nve0_graph_init_obj418880(struct nvc0_graph_priv *priv) |
ab394543 | 251 | { |
ab394543 BS |
252 | int i; |
253 | ||
ebb945a9 BS |
254 | nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); |
255 | nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); | |
ab394543 | 256 | for (i = 0; i < 4; i++) |
ebb945a9 BS |
257 | nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000); |
258 | nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); | |
259 | nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); | |
ab394543 BS |
260 | } |
261 | ||
262 | static void | |
ebb945a9 | 263 | nve0_graph_init_regs(struct nvc0_graph_priv *priv) |
ab394543 | 264 | { |
ebb945a9 BS |
265 | nv_wr32(priv, 0x400080, 0x003083c2); |
266 | nv_wr32(priv, 0x400088, 0x0001ffe7); | |
267 | nv_wr32(priv, 0x40008c, 0x00000000); | |
268 | nv_wr32(priv, 0x400090, 0x00000030); | |
269 | nv_wr32(priv, 0x40013c, 0x003901f7); | |
270 | nv_wr32(priv, 0x400140, 0x00000100); | |
271 | nv_wr32(priv, 0x400144, 0x00000000); | |
272 | nv_wr32(priv, 0x400148, 0x00000110); | |
273 | nv_wr32(priv, 0x400138, 0x00000000); | |
274 | nv_wr32(priv, 0x400130, 0x00000000); | |
275 | nv_wr32(priv, 0x400134, 0x00000000); | |
276 | nv_wr32(priv, 0x400124, 0x00000002); | |
ab394543 BS |
277 | } |
278 | ||
279 | static void | |
ebb945a9 | 280 | nve0_graph_init_units(struct nvc0_graph_priv *priv) |
ab394543 | 281 | { |
ebb945a9 BS |
282 | nv_wr32(priv, 0x409ffc, 0x00000000); |
283 | nv_wr32(priv, 0x409c14, 0x00003e3e); | |
284 | nv_wr32(priv, 0x409c24, 0x000f0000); | |
285 | ||
286 | nv_wr32(priv, 0x404000, 0xc0000000); | |
287 | nv_wr32(priv, 0x404600, 0xc0000000); | |
288 | nv_wr32(priv, 0x408030, 0xc0000000); | |
289 | nv_wr32(priv, 0x404490, 0xc0000000); | |
290 | nv_wr32(priv, 0x406018, 0xc0000000); | |
291 | nv_wr32(priv, 0x407020, 0xc0000000); | |
292 | nv_wr32(priv, 0x405840, 0xc0000000); | |
293 | nv_wr32(priv, 0x405844, 0x00ffffff); | |
294 | ||
295 | nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); | |
296 | nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); | |
ab394543 BS |
297 | |
298 | } | |
299 | ||
300 | static void | |
ebb945a9 | 301 | nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv) |
ab394543 | 302 | { |
ab394543 BS |
303 | const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); |
304 | u32 data[TPC_MAX / 8]; | |
305 | u8 tpcnr[GPC_MAX]; | |
306 | int i, gpc, tpc; | |
307 | ||
ebb945a9 | 308 | nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); |
ab394543 BS |
309 | |
310 | memset(data, 0x00, sizeof(data)); | |
311 | memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); | |
312 | for (i = 0, gpc = -1; i < priv->tpc_total; i++) { | |
313 | do { | |
314 | gpc = (gpc + 1) % priv->gpc_nr; | |
315 | } while (!tpcnr[gpc]); | |
316 | tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; | |
317 | ||
318 | data[i / 8] |= tpc << ((i % 8) * 4); | |
319 | } | |
320 | ||
ebb945a9 BS |
321 | nv_wr32(priv, GPC_BCAST(0x0980), data[0]); |
322 | nv_wr32(priv, GPC_BCAST(0x0984), data[1]); | |
323 | nv_wr32(priv, GPC_BCAST(0x0988), data[2]); | |
324 | nv_wr32(priv, GPC_BCAST(0x098c), data[3]); | |
ab394543 BS |
325 | |
326 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | |
ebb945a9 | 327 | nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | |
ab394543 | 328 | priv->tpc_nr[gpc]); |
ebb945a9 BS |
329 | nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); |
330 | nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); | |
ab394543 BS |
331 | } |
332 | ||
ebb945a9 BS |
333 | nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); |
334 | nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); | |
ab394543 BS |
335 | } |
336 | ||
337 | static void | |
ebb945a9 | 338 | nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv) |
ab394543 | 339 | { |
ab394543 BS |
340 | int gpc, tpc; |
341 | ||
342 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | |
ebb945a9 BS |
343 | nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000); |
344 | nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); | |
345 | nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); | |
346 | nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); | |
347 | nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); | |
ab394543 | 348 | for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { |
ebb945a9 BS |
349 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); |
350 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); | |
351 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); | |
352 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); | |
353 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); | |
354 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); | |
355 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); | |
ab394543 | 356 | } |
ebb945a9 BS |
357 | nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); |
358 | nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); | |
ab394543 BS |
359 | } |
360 | } | |
361 | ||
362 | static void | |
ebb945a9 | 363 | nve0_graph_init_rop(struct nvc0_graph_priv *priv) |
ab394543 | 364 | { |
ab394543 BS |
365 | int rop; |
366 | ||
367 | for (rop = 0; rop < priv->rop_nr; rop++) { | |
ebb945a9 BS |
368 | nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); |
369 | nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); | |
370 | nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); | |
371 | nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); | |
ab394543 BS |
372 | } |
373 | } | |
374 | ||
375 | static int | |
ebb945a9 | 376 | nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv) |
ab394543 | 377 | { |
ab394543 BS |
378 | u32 r000260; |
379 | ||
380 | /* load fuc microcode */ | |
ebb945a9 BS |
381 | r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); |
382 | nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d); | |
383 | nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); | |
384 | nv_wr32(priv, 0x000260, r000260); | |
ab394543 BS |
385 | |
386 | /* start both of them running */ | |
ebb945a9 BS |
387 | nv_wr32(priv, 0x409840, 0xffffffff); |
388 | nv_wr32(priv, 0x41a10c, 0x00000000); | |
389 | nv_wr32(priv, 0x40910c, 0x00000000); | |
390 | nv_wr32(priv, 0x41a100, 0x00000002); | |
391 | nv_wr32(priv, 0x409100, 0x00000002); | |
392 | if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) | |
393 | nv_error(priv, "0x409800 wait failed\n"); | |
394 | ||
395 | nv_wr32(priv, 0x409840, 0xffffffff); | |
396 | nv_wr32(priv, 0x409500, 0x7fffffff); | |
397 | nv_wr32(priv, 0x409504, 0x00000021); | |
398 | ||
399 | nv_wr32(priv, 0x409840, 0xffffffff); | |
400 | nv_wr32(priv, 0x409500, 0x00000000); | |
401 | nv_wr32(priv, 0x409504, 0x00000010); | |
402 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
403 | nv_error(priv, "fuc09 req 0x10 timeout\n"); | |
ab394543 BS |
404 | return -EBUSY; |
405 | } | |
ebb945a9 | 406 | priv->size = nv_rd32(priv, 0x409800); |
ab394543 | 407 | |
ebb945a9 BS |
408 | nv_wr32(priv, 0x409840, 0xffffffff); |
409 | nv_wr32(priv, 0x409500, 0x00000000); | |
410 | nv_wr32(priv, 0x409504, 0x00000016); | |
411 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
412 | nv_error(priv, "fuc09 req 0x16 timeout\n"); | |
ab394543 BS |
413 | return -EBUSY; |
414 | } | |
415 | ||
ebb945a9 BS |
416 | nv_wr32(priv, 0x409840, 0xffffffff); |
417 | nv_wr32(priv, 0x409500, 0x00000000); | |
418 | nv_wr32(priv, 0x409504, 0x00000025); | |
419 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
420 | nv_error(priv, "fuc09 req 0x25 timeout\n"); | |
ab394543 BS |
421 | return -EBUSY; |
422 | } | |
423 | ||
ebb945a9 BS |
424 | nv_wr32(priv, 0x409800, 0x00000000); |
425 | nv_wr32(priv, 0x409500, 0x00000001); | |
426 | nv_wr32(priv, 0x409504, 0x00000030); | |
427 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
428 | nv_error(priv, "fuc09 req 0x30 timeout\n"); | |
ab394543 BS |
429 | return -EBUSY; |
430 | } | |
431 | ||
ebb945a9 BS |
432 | nv_wr32(priv, 0x409810, 0xb00095c8); |
433 | nv_wr32(priv, 0x409800, 0x00000000); | |
434 | nv_wr32(priv, 0x409500, 0x00000001); | |
435 | nv_wr32(priv, 0x409504, 0x00000031); | |
436 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
437 | nv_error(priv, "fuc09 req 0x31 timeout\n"); | |
ab394543 BS |
438 | return -EBUSY; |
439 | } | |
440 | ||
ebb945a9 BS |
441 | nv_wr32(priv, 0x409810, 0x00080420); |
442 | nv_wr32(priv, 0x409800, 0x00000000); | |
443 | nv_wr32(priv, 0x409500, 0x00000001); | |
444 | nv_wr32(priv, 0x409504, 0x00000032); | |
445 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
446 | nv_error(priv, "fuc09 req 0x32 timeout\n"); | |
ab394543 BS |
447 | return -EBUSY; |
448 | } | |
449 | ||
ebb945a9 BS |
450 | nv_wr32(priv, 0x409614, 0x00000070); |
451 | nv_wr32(priv, 0x409614, 0x00000770); | |
452 | nv_wr32(priv, 0x40802c, 0x00000001); | |
ac1499d9 BS |
453 | |
454 | if (priv->data == NULL) { | |
ebb945a9 | 455 | int ret = nve0_grctx_generate(priv); |
ac1499d9 | 456 | if (ret) { |
ebb945a9 | 457 | nv_error(priv, "failed to construct context\n"); |
ac1499d9 BS |
458 | return ret; |
459 | } | |
460 | ||
461 | return 1; | |
462 | } | |
463 | ||
ab394543 BS |
464 | return 0; |
465 | } | |
466 | ||
467 | static int | |
ebb945a9 | 468 | nve0_graph_init(struct nouveau_object *object) |
ab394543 | 469 | { |
ebb945a9 | 470 | struct nvc0_graph_priv *priv = (void *)object; |
ab394543 BS |
471 | int ret; |
472 | ||
ac1499d9 | 473 | reset: |
ebb945a9 | 474 | ret = nouveau_graph_init(&priv->base); |
ab394543 BS |
475 | if (ret) |
476 | return ret; | |
477 | ||
ebb945a9 BS |
478 | nve0_graph_init_obj418880(priv); |
479 | nve0_graph_init_regs(priv); | |
480 | nve0_graph_init_gpc_0(priv); | |
ab394543 | 481 | |
ebb945a9 BS |
482 | nv_wr32(priv, 0x400500, 0x00010001); |
483 | nv_wr32(priv, 0x400100, 0xffffffff); | |
484 | nv_wr32(priv, 0x40013c, 0xffffffff); | |
ab394543 | 485 | |
ebb945a9 BS |
486 | nve0_graph_init_units(priv); |
487 | nve0_graph_init_gpc_1(priv); | |
488 | nve0_graph_init_rop(priv); | |
ab394543 | 489 | |
ebb945a9 BS |
490 | nv_wr32(priv, 0x400108, 0xffffffff); |
491 | nv_wr32(priv, 0x400138, 0xffffffff); | |
492 | nv_wr32(priv, 0x400118, 0xffffffff); | |
493 | nv_wr32(priv, 0x400130, 0xffffffff); | |
494 | nv_wr32(priv, 0x40011c, 0xffffffff); | |
495 | nv_wr32(priv, 0x400134, 0xffffffff); | |
496 | nv_wr32(priv, 0x400054, 0x34ce3464); | |
ab394543 | 497 | |
ebb945a9 BS |
498 | ret = nve0_graph_init_ctxctl(priv); |
499 | if (ret) { | |
500 | if (ret == 1) | |
501 | goto reset; | |
502 | return ret; | |
ab394543 BS |
503 | } |
504 | ||
ab394543 | 505 | return 0; |
ab394543 | 506 | } |
ebb945a9 BS |
507 | |
508 | struct nouveau_oclass | |
509 | nve0_graph_oclass = { | |
510 | .handle = NV_ENGINE(GR, 0xe0), | |
511 | .ofuncs = &(struct nouveau_ofuncs) { | |
512 | .ctor = nve0_graph_ctor, | |
513 | .dtor = nvc0_graph_dtor, | |
514 | .init = nve0_graph_init, | |
515 | .fini = _nouveau_graph_fini, | |
516 | }, | |
517 | }; |