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" |
1978a2f2 BS |
26 | #include "fuc/hubnve0.fuc.h" |
27 | #include "fuc/gpcnve0.fuc.h" | |
ab394543 | 28 | |
ebb945a9 BS |
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 }, | |
ebb945a9 BS |
39 | {} |
40 | }; | |
41 | ||
42 | /******************************************************************************* | |
43 | * PGRAPH context | |
44 | ******************************************************************************/ | |
45 | ||
46 | static struct nouveau_oclass | |
47 | nve0_graph_cclass = { | |
48 | .handle = NV_ENGCTX(GR, 0xe0), | |
49 | .ofuncs = &(struct nouveau_ofuncs) { | |
50 | .ctor = nvc0_graph_context_ctor, | |
51 | .dtor = nvc0_graph_context_dtor, | |
52 | .init = _nouveau_graph_context_init, | |
53 | .fini = _nouveau_graph_context_fini, | |
54 | .rd32 = _nouveau_graph_context_rd32, | |
55 | .wr32 = _nouveau_graph_context_wr32, | |
56 | }, | |
57 | }; | |
58 | ||
59 | /******************************************************************************* | |
60 | * PGRAPH engine/subdev functions | |
61 | ******************************************************************************/ | |
62 | ||
ab394543 | 63 | static void |
ebb945a9 | 64 | nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) |
ab394543 | 65 | { |
ebb945a9 BS |
66 | u32 ustat = nv_rd32(priv, 0x409c18); |
67 | ||
68 | if (ustat & 0x00000001) | |
69 | nv_error(priv, "CTXCTRL ucode error\n"); | |
70 | if (ustat & 0x00080000) | |
71 | nv_error(priv, "CTXCTRL watchdog timeout\n"); | |
72 | if (ustat & ~0x00080001) | |
73 | nv_error(priv, "CTXCTRL 0x%08x\n", ustat); | |
74 | ||
75 | nvc0_graph_ctxctl_debug(priv); | |
76 | nv_wr32(priv, 0x409c20, ustat); | |
ab394543 BS |
77 | } |
78 | ||
bf3d8165 CB |
79 | static const struct nouveau_enum nve0_mp_warp_error[] = { |
80 | { 0x00, "NO_ERROR" }, | |
81 | { 0x01, "STACK_MISMATCH" }, | |
82 | { 0x05, "MISALIGNED_PC" }, | |
83 | { 0x08, "MISALIGNED_GPR" }, | |
84 | { 0x09, "INVALID_OPCODE" }, | |
85 | { 0x0d, "GPR_OUT_OF_BOUNDS" }, | |
86 | { 0x0e, "MEM_OUT_OF_BOUNDS" }, | |
87 | { 0x0f, "UNALIGNED_MEM_ACCESS" }, | |
88 | { 0x11, "INVALID_PARAM" }, | |
89 | {} | |
90 | }; | |
91 | ||
16b133df BS |
92 | static const struct nouveau_bitfield nve0_mp_global_error[] = { |
93 | { 0x00000004, "MULTIPLE_WARP_ERRORS" }, | |
94 | { 0x00000008, "OUT_OF_STACK_SPACE" }, | |
bf3d8165 CB |
95 | {} |
96 | }; | |
97 | ||
98 | static const struct nouveau_enum nve0_gpc_rop_error[] = { | |
99 | { 1, "RT_PITCH_OVERRUN" }, | |
100 | { 4, "RT_WIDTH_OVERRUN" }, | |
101 | { 5, "RT_HEIGHT_OVERRUN" }, | |
102 | { 7, "ZETA_STORAGE_TYPE_MISMATCH" }, | |
103 | { 8, "RT_STORAGE_TYPE_MISMATCH" }, | |
104 | { 10, "RT_LINEAR_MISMATCH" }, | |
105 | {} | |
106 | }; | |
107 | ||
108 | static const struct nouveau_enum nve0_sked_error[] = { | |
109 | { 7, "CONSTANT_BUFFER_SIZE" }, | |
110 | { 9, "LOCAL_MEMORY_SIZE_POS" }, | |
111 | { 10, "LOCAL_MEMORY_SIZE_NEG" }, | |
112 | { 11, "WARP_CSTACK_SIZE" }, | |
113 | { 12, "TOTAL_TEMP_SIZE" }, | |
114 | { 13, "REGISTER_COUNT" }, | |
115 | { 18, "TOTAL_THREADS" }, | |
116 | { 20, "PROGRAM_OFFSET" }, | |
117 | { 21, "SHARED_MEMORY_SIZE" }, | |
118 | { 25, "SHARED_CONFIG_TOO_SMALL" }, | |
119 | { 26, "TOTAL_REGISTER_COUNT" }, | |
120 | {} | |
121 | }; | |
122 | ||
123 | static void | |
3d8a6ed2 | 124 | nve0_graph_mp_trap(struct nvc0_graph_priv *priv, int gpc, int tpc) |
bf3d8165 | 125 | { |
3d8a6ed2 BS |
126 | u32 werr = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x648)); |
127 | u32 gerr = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x650)); | |
bf3d8165 | 128 | |
3d8a6ed2 | 129 | nv_error(priv, "GPC%i/TPC%i/MP trap:", gpc, tpc); |
16b133df | 130 | nouveau_bitfield_print(nve0_mp_global_error, gerr); |
bf3d8165 CB |
131 | if (werr) { |
132 | pr_cont(" "); | |
133 | nouveau_enum_print(nve0_mp_warp_error, werr & 0xffff); | |
134 | } | |
135 | pr_cont("\n"); | |
136 | ||
16b133df BS |
137 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x648), 0x00000000); |
138 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x650), gerr); | |
bf3d8165 CB |
139 | } |
140 | ||
141 | static void | |
3d8a6ed2 | 142 | nve0_graph_tpc_trap(struct nvc0_graph_priv *priv, int gpc, int tpc) |
bf3d8165 | 143 | { |
3d8a6ed2 | 144 | u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x508)); |
bf3d8165 CB |
145 | |
146 | if (stat & 0x1) { | |
3d8a6ed2 BS |
147 | u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x224)); |
148 | nv_error(priv, "GPC%i/TPC%i/TEX trap: %08x\n", | |
149 | gpc, tpc, trap); | |
bf3d8165 | 150 | |
3d8a6ed2 | 151 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); |
bf3d8165 CB |
152 | stat &= ~0x1; |
153 | } | |
154 | ||
155 | if (stat & 0x2) { | |
3d8a6ed2 | 156 | nve0_graph_mp_trap(priv, gpc, tpc); |
bf3d8165 CB |
157 | stat &= ~0x2; |
158 | } | |
159 | ||
160 | if (stat & 0x4) { | |
3d8a6ed2 BS |
161 | u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x084)); |
162 | nv_error(priv, "GPC%i/TPC%i/POLY trap: %08x\n", | |
163 | gpc, tpc, trap); | |
bf3d8165 | 164 | |
3d8a6ed2 | 165 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); |
bf3d8165 CB |
166 | stat &= ~0x4; |
167 | } | |
168 | ||
169 | if (stat & 0x8) { | |
3d8a6ed2 BS |
170 | u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x48c)); |
171 | nv_error(priv, "GPC%i/TPC%i/L1C trap: %08x\n", | |
172 | gpc, tpc, trap); | |
bf3d8165 | 173 | |
3d8a6ed2 | 174 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); |
bf3d8165 CB |
175 | stat &= ~0x8; |
176 | } | |
177 | ||
178 | if (stat) { | |
3d8a6ed2 BS |
179 | nv_error(priv, "GPC%i/TPC%i: unknown stat %08x\n", |
180 | gpc, tpc, stat); | |
bf3d8165 CB |
181 | } |
182 | } | |
183 | ||
184 | static void | |
185 | nve0_graph_gpc_trap(struct nvc0_graph_priv *priv) | |
186 | { | |
187 | const u32 mask = nv_rd32(priv, 0x400118); | |
188 | int gpc; | |
189 | ||
190 | for (gpc = 0; gpc < 4; ++gpc) { | |
191 | u32 stat; | |
3d8a6ed2 | 192 | int tpc; |
bf3d8165 CB |
193 | |
194 | if (!(mask & (1 << gpc))) | |
195 | continue; | |
196 | stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90)); | |
197 | ||
198 | if (stat & 0x0001) { | |
199 | u32 trap[4]; | |
200 | int i; | |
201 | ||
202 | trap[0] = nv_rd32(priv, GPC_UNIT(gpc, 0x0420)); | |
203 | trap[1] = nv_rd32(priv, GPC_UNIT(gpc, 0x0434)); | |
204 | trap[2] = nv_rd32(priv, GPC_UNIT(gpc, 0x0438)); | |
205 | trap[3] = nv_rd32(priv, GPC_UNIT(gpc, 0x043c)); | |
206 | ||
207 | nv_error(priv, "GPC%i/PROP trap:", gpc); | |
208 | for (i = 0; i <= 29; ++i) { | |
209 | if (!(trap[0] & (1 << i))) | |
210 | continue; | |
211 | pr_cont(" "); | |
212 | nouveau_enum_print(nve0_gpc_rop_error, i); | |
213 | } | |
214 | pr_cont("\n"); | |
215 | ||
216 | nv_error(priv, "x = %u, y = %u, " | |
217 | "format = %x, storage type = %x\n", | |
218 | trap[1] & 0xffff, | |
219 | trap[1] >> 16, | |
220 | (trap[2] >> 8) & 0x3f, | |
221 | trap[3] & 0xff); | |
222 | ||
223 | nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); | |
224 | stat &= ~0x0001; | |
225 | } | |
226 | ||
227 | if (stat & 0x0002) { | |
228 | u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900)); | |
229 | nv_error(priv, "GPC%i/ZCULL trap: %08x\n", gpc, | |
230 | trap); | |
231 | nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); | |
232 | stat &= ~0x0002; | |
233 | } | |
234 | ||
235 | if (stat & 0x0004) { | |
236 | u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028)); | |
237 | nv_error(priv, "GPC%i/CCACHE trap: %08x\n", gpc, | |
238 | trap); | |
239 | nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); | |
240 | stat &= ~0x0004; | |
241 | } | |
242 | ||
243 | if (stat & 0x0008) { | |
244 | u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824)); | |
245 | nv_error(priv, "GPC%i/ESETUP trap %08x\n", gpc, | |
246 | trap); | |
247 | nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); | |
248 | stat &= ~0x0008; | |
249 | } | |
250 | ||
3d8a6ed2 BS |
251 | for (tpc = 0; tpc < 8; ++tpc) { |
252 | if (stat & (1 << (16 + tpc))) | |
253 | nve0_graph_tpc_trap(priv, gpc, tpc); | |
bf3d8165 CB |
254 | } |
255 | stat &= ~0xff0000; | |
256 | ||
257 | if (stat) { | |
258 | nv_error(priv, "GPC%i: unknown stat %08x\n", | |
259 | gpc, stat); | |
260 | } | |
261 | } | |
262 | } | |
263 | ||
264 | ||
ab394543 | 265 | static void |
93260d3c MS |
266 | nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, |
267 | struct nouveau_object *engctx) | |
ab394543 | 268 | { |
ebb945a9 | 269 | u32 trap = nv_rd32(priv, 0x400108); |
bf3d8165 | 270 | int i; |
ebb945a9 BS |
271 | int rop; |
272 | ||
273 | if (trap & 0x00000001) { | |
274 | u32 stat = nv_rd32(priv, 0x404000); | |
93260d3c MS |
275 | nv_error(priv, "DISPATCH ch %d [0x%010llx %s] 0x%08x\n", |
276 | chid, inst, nouveau_client_name(engctx), stat); | |
ebb945a9 BS |
277 | nv_wr32(priv, 0x404000, 0xc0000000); |
278 | nv_wr32(priv, 0x400108, 0x00000001); | |
279 | trap &= ~0x00000001; | |
280 | } | |
ab394543 | 281 | |
ebb945a9 BS |
282 | if (trap & 0x00000010) { |
283 | u32 stat = nv_rd32(priv, 0x405840); | |
93260d3c MS |
284 | nv_error(priv, "SHADER ch %d [0x%010llx %s] 0x%08x\n", |
285 | chid, inst, nouveau_client_name(engctx), stat); | |
ebb945a9 BS |
286 | nv_wr32(priv, 0x405840, 0xc0000000); |
287 | nv_wr32(priv, 0x400108, 0x00000010); | |
288 | trap &= ~0x00000010; | |
289 | } | |
290 | ||
bf3d8165 CB |
291 | if (trap & 0x00000100) { |
292 | u32 stat = nv_rd32(priv, 0x407020); | |
293 | nv_error(priv, "SKED ch %d [0x%010llx %s]:", | |
294 | chid, inst, nouveau_client_name(engctx)); | |
295 | ||
296 | for (i = 0; i <= 29; ++i) { | |
297 | if (!(stat & (1 << i))) | |
298 | continue; | |
299 | pr_cont(" "); | |
300 | nouveau_enum_print(nve0_sked_error, i); | |
301 | } | |
302 | pr_cont("\n"); | |
303 | ||
304 | if (stat & 0x3fffffff) | |
305 | nv_wr32(priv, 0x407020, 0x40000000); | |
306 | nv_wr32(priv, 0x400108, 0x00000100); | |
307 | trap &= ~0x00000100; | |
308 | } | |
309 | ||
310 | if (trap & 0x01000000) { | |
311 | nv_error(priv, "GPC ch %d [0x%010llx %s]:\n", | |
312 | chid, inst, nouveau_client_name(engctx)); | |
313 | nve0_graph_gpc_trap(priv); | |
314 | trap &= ~0x01000000; | |
315 | } | |
316 | ||
ebb945a9 BS |
317 | if (trap & 0x02000000) { |
318 | for (rop = 0; rop < priv->rop_nr; rop++) { | |
319 | u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); | |
320 | u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); | |
93260d3c MS |
321 | nv_error(priv, |
322 | "ROP%d ch %d [0x%010llx %s] 0x%08x 0x%08x\n", | |
323 | rop, chid, inst, nouveau_client_name(engctx), | |
324 | statz, statc); | |
ebb945a9 BS |
325 | nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); |
326 | nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); | |
327 | } | |
328 | nv_wr32(priv, 0x400108, 0x02000000); | |
329 | trap &= ~0x02000000; | |
330 | } | |
331 | ||
332 | if (trap) { | |
93260d3c MS |
333 | nv_error(priv, "TRAP ch %d [0x%010llx %s] 0x%08x\n", |
334 | chid, inst, nouveau_client_name(engctx), trap); | |
ebb945a9 BS |
335 | nv_wr32(priv, 0x400108, trap); |
336 | } | |
ab394543 BS |
337 | } |
338 | ||
ebb945a9 BS |
339 | static void |
340 | nve0_graph_intr(struct nouveau_subdev *subdev) | |
ab394543 | 341 | { |
72a14827 | 342 | struct nouveau_fifo *pfifo = nouveau_fifo(subdev); |
ebb945a9 | 343 | struct nouveau_engine *engine = nv_engine(subdev); |
72a14827 BS |
344 | struct nouveau_object *engctx; |
345 | struct nouveau_handle *handle; | |
346 | struct nvc0_graph_priv *priv = (void *)subdev; | |
347 | u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff; | |
ebb945a9 BS |
348 | u32 stat = nv_rd32(priv, 0x400100); |
349 | u32 addr = nv_rd32(priv, 0x400704); | |
350 | u32 mthd = (addr & 0x00003ffc); | |
351 | u32 subc = (addr & 0x00070000) >> 16; | |
352 | u32 data = nv_rd32(priv, 0x400708); | |
353 | u32 code = nv_rd32(priv, 0x400110); | |
354 | u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); | |
72a14827 BS |
355 | int chid; |
356 | ||
357 | engctx = nouveau_engctx_get(engine, inst); | |
358 | chid = pfifo->chid(pfifo, engctx); | |
ebb945a9 BS |
359 | |
360 | if (stat & 0x00000010) { | |
72a14827 | 361 | handle = nouveau_handle_get_class(engctx, class); |
ebb945a9 | 362 | if (!handle || nv_call(handle->object, mthd, data)) { |
93260d3c MS |
363 | nv_error(priv, |
364 | "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", | |
365 | chid, inst, nouveau_client_name(engctx), subc, | |
366 | class, mthd, data); | |
ebb945a9 | 367 | } |
72a14827 | 368 | nouveau_handle_put(handle); |
ebb945a9 BS |
369 | nv_wr32(priv, 0x400100, 0x00000010); |
370 | stat &= ~0x00000010; | |
371 | } | |
372 | ||
373 | if (stat & 0x00000020) { | |
93260d3c MS |
374 | nv_error(priv, |
375 | "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", | |
376 | chid, inst, nouveau_client_name(engctx), subc, class, | |
377 | mthd, data); | |
ebb945a9 BS |
378 | nv_wr32(priv, 0x400100, 0x00000020); |
379 | stat &= ~0x00000020; | |
380 | } | |
381 | ||
382 | if (stat & 0x00100000) { | |
383 | nv_error(priv, "DATA_ERROR ["); | |
384 | nouveau_enum_print(nv50_data_error_names, code); | |
93260d3c MS |
385 | pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", |
386 | chid, inst, nouveau_client_name(engctx), subc, class, | |
387 | mthd, data); | |
ebb945a9 BS |
388 | nv_wr32(priv, 0x400100, 0x00100000); |
389 | stat &= ~0x00100000; | |
390 | } | |
391 | ||
392 | if (stat & 0x00200000) { | |
93260d3c | 393 | nve0_graph_trap_isr(priv, chid, inst, engctx); |
ebb945a9 BS |
394 | nv_wr32(priv, 0x400100, 0x00200000); |
395 | stat &= ~0x00200000; | |
396 | } | |
397 | ||
398 | if (stat & 0x00080000) { | |
399 | nve0_graph_ctxctl_isr(priv); | |
400 | nv_wr32(priv, 0x400100, 0x00080000); | |
401 | stat &= ~0x00080000; | |
402 | } | |
403 | ||
404 | if (stat) { | |
405 | nv_error(priv, "unknown stat 0x%08x\n", stat); | |
406 | nv_wr32(priv, 0x400100, stat); | |
407 | } | |
408 | ||
409 | nv_wr32(priv, 0x400500, 0x00010001); | |
72a14827 | 410 | nouveau_engctx_put(engctx); |
ab394543 BS |
411 | } |
412 | ||
413 | static int | |
ebb945a9 BS |
414 | nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
415 | struct nouveau_oclass *oclass, void *data, u32 size, | |
416 | struct nouveau_object **pobject) | |
ab394543 | 417 | { |
1978a2f2 | 418 | struct nouveau_device *device = nv_device(parent); |
ebb945a9 BS |
419 | struct nvc0_graph_priv *priv; |
420 | int ret, i; | |
421 | ||
eca15296 | 422 | ret = nouveau_graph_create(parent, engine, oclass, true, &priv); |
ebb945a9 BS |
423 | *pobject = nv_object(priv); |
424 | if (ret) | |
425 | return ret; | |
426 | ||
427 | nv_subdev(priv)->unit = 0x18001000; | |
428 | nv_subdev(priv)->intr = nve0_graph_intr; | |
429 | nv_engine(priv)->cclass = &nve0_graph_cclass; | |
430 | nv_engine(priv)->sclass = nve0_graph_sclass; | |
431 | ||
7e22e71e CB |
432 | priv->base.units = nvc0_graph_units; |
433 | ||
e5bf578c | 434 | if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { |
1978a2f2 BS |
435 | nv_info(priv, "using external firmware\n"); |
436 | if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || | |
437 | nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || | |
438 | nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) || | |
439 | nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad)) | |
440 | return -EINVAL; | |
441 | priv->firmware = true; | |
442 | } | |
ebb945a9 | 443 | |
617a6cbd BS |
444 | ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, |
445 | &priv->unk4188b4); | |
ebb945a9 BS |
446 | if (ret) |
447 | return ret; | |
448 | ||
617a6cbd BS |
449 | ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, |
450 | &priv->unk4188b8); | |
ebb945a9 BS |
451 | if (ret) |
452 | return ret; | |
453 | ||
454 | for (i = 0; i < 0x1000; i += 4) { | |
455 | nv_wo32(priv->unk4188b4, i, 0x00000010); | |
456 | nv_wo32(priv->unk4188b8, i, 0x00000010); | |
457 | } | |
458 | ||
459 | priv->gpc_nr = nv_rd32(priv, 0x409604) & 0x0000001f; | |
460 | priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16; | |
461 | for (i = 0; i < priv->gpc_nr; i++) { | |
462 | priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608)); | |
463 | priv->tpc_total += priv->tpc_nr[i]; | |
464 | } | |
465 | ||
466 | switch (nv_device(priv)->chipset) { | |
467 | case 0xe4: | |
468 | if (priv->tpc_total == 8) | |
469 | priv->magic_not_rop_nr = 3; | |
470 | else | |
471 | if (priv->tpc_total == 7) | |
472 | priv->magic_not_rop_nr = 1; | |
473 | break; | |
474 | case 0xe7: | |
caba5570 | 475 | case 0xe6: |
ebb945a9 BS |
476 | priv->magic_not_rop_nr = 1; |
477 | break; | |
478 | default: | |
479 | break; | |
480 | } | |
481 | ||
ab394543 BS |
482 | return 0; |
483 | } | |
484 | ||
485 | static void | |
ebb945a9 | 486 | nve0_graph_init_obj418880(struct nvc0_graph_priv *priv) |
ab394543 | 487 | { |
ab394543 BS |
488 | int i; |
489 | ||
ebb945a9 BS |
490 | nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); |
491 | nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000); | |
ab394543 | 492 | for (i = 0; i < 4; i++) |
ebb945a9 BS |
493 | nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000); |
494 | nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); | |
495 | nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); | |
ab394543 BS |
496 | } |
497 | ||
498 | static void | |
ebb945a9 | 499 | nve0_graph_init_regs(struct nvc0_graph_priv *priv) |
ab394543 | 500 | { |
ebb945a9 BS |
501 | nv_wr32(priv, 0x400080, 0x003083c2); |
502 | nv_wr32(priv, 0x400088, 0x0001ffe7); | |
503 | nv_wr32(priv, 0x40008c, 0x00000000); | |
504 | nv_wr32(priv, 0x400090, 0x00000030); | |
505 | nv_wr32(priv, 0x40013c, 0x003901f7); | |
506 | nv_wr32(priv, 0x400140, 0x00000100); | |
507 | nv_wr32(priv, 0x400144, 0x00000000); | |
508 | nv_wr32(priv, 0x400148, 0x00000110); | |
509 | nv_wr32(priv, 0x400138, 0x00000000); | |
510 | nv_wr32(priv, 0x400130, 0x00000000); | |
511 | nv_wr32(priv, 0x400134, 0x00000000); | |
512 | nv_wr32(priv, 0x400124, 0x00000002); | |
ab394543 BS |
513 | } |
514 | ||
99bd5537 BS |
515 | static void |
516 | nve0_graph_init_unk40xx(struct nvc0_graph_priv *priv) | |
517 | { | |
518 | nv_wr32(priv, 0x40415c, 0x00000000); | |
519 | nv_wr32(priv, 0x404170, 0x00000000); | |
cb1e06e0 BS |
520 | switch (nv_device(priv)->chipset) { |
521 | case 0xf0: | |
522 | nv_wr32(priv, 0x4041b4, 0x00000000); | |
523 | break; | |
524 | default: | |
525 | break; | |
526 | } | |
99bd5537 BS |
527 | } |
528 | ||
529 | static void | |
530 | nve0_graph_init_unk44xx(struct nvc0_graph_priv *priv) | |
531 | { | |
532 | nv_wr32(priv, 0x404488, 0x00000000); | |
533 | nv_wr32(priv, 0x40448c, 0x00000000); | |
534 | } | |
535 | ||
536 | static void | |
537 | nve0_graph_init_unk78xx(struct nvc0_graph_priv *priv) | |
538 | { | |
539 | nv_wr32(priv, 0x407808, 0x00000000); | |
540 | } | |
541 | ||
542 | static void | |
543 | nve0_graph_init_unk60xx(struct nvc0_graph_priv *priv) | |
544 | { | |
545 | nv_wr32(priv, 0x406024, 0x00000000); | |
546 | } | |
547 | ||
548 | static void | |
549 | nve0_graph_init_unk64xx(struct nvc0_graph_priv *priv) | |
550 | { | |
551 | nv_wr32(priv, 0x4064f0, 0x00000000); | |
552 | nv_wr32(priv, 0x4064f4, 0x00000000); | |
553 | nv_wr32(priv, 0x4064f8, 0x00000000); | |
554 | } | |
555 | ||
556 | static void | |
557 | nve0_graph_init_unk58xx(struct nvc0_graph_priv *priv) | |
558 | { | |
559 | nv_wr32(priv, 0x405844, 0x00ffffff); | |
560 | nv_wr32(priv, 0x405850, 0x00000000); | |
cb1e06e0 BS |
561 | switch (nv_device(priv)->chipset) { |
562 | case 0xf0: | |
563 | nv_wr32(priv, 0x405900, 0x0000ff00); | |
564 | break; | |
565 | default: | |
566 | nv_wr32(priv, 0x405900, 0x0000ff34); | |
567 | break; | |
568 | } | |
99bd5537 BS |
569 | nv_wr32(priv, 0x405908, 0x00000000); |
570 | nv_wr32(priv, 0x405928, 0x00000000); | |
571 | nv_wr32(priv, 0x40592c, 0x00000000); | |
572 | } | |
573 | ||
574 | static void | |
575 | nve0_graph_init_unk80xx(struct nvc0_graph_priv *priv) | |
576 | { | |
577 | nv_wr32(priv, 0x40803c, 0x00000000); | |
578 | } | |
579 | ||
580 | static void | |
581 | nve0_graph_init_unk70xx(struct nvc0_graph_priv *priv) | |
582 | { | |
583 | nv_wr32(priv, 0x407010, 0x00000000); | |
cb1e06e0 BS |
584 | switch (nv_device(priv)->chipset) { |
585 | case 0xf0: | |
586 | nv_wr32(priv, 0x407040, 0x80440424); | |
587 | nv_wr32(priv, 0x407048, 0x0000000a); | |
588 | break; | |
589 | default: | |
590 | break; | |
591 | } | |
99bd5537 BS |
592 | } |
593 | ||
594 | static void | |
595 | nve0_graph_init_unk5bxx(struct nvc0_graph_priv *priv) | |
596 | { | |
cb1e06e0 BS |
597 | switch (nv_device(priv)->chipset) { |
598 | case 0xf0: | |
599 | nv_wr32(priv, 0x505b44, 0x00000000); | |
600 | break; | |
601 | default: | |
602 | break; | |
603 | } | |
99bd5537 BS |
604 | nv_wr32(priv, 0x405b50, 0x00000000); |
605 | } | |
606 | ||
607 | static void | |
608 | nve0_graph_init_gpc(struct nvc0_graph_priv *priv) | |
609 | { | |
610 | nv_wr32(priv, 0x418408, 0x00000000); | |
611 | nv_wr32(priv, 0x4184a0, 0x00000000); | |
612 | nv_wr32(priv, 0x4184a4, 0x00000000); | |
613 | nv_wr32(priv, 0x4184a8, 0x00000000); | |
614 | nv_wr32(priv, 0x418604, 0x00000000); | |
615 | nv_wr32(priv, 0x418680, 0x00000000); | |
616 | nv_wr32(priv, 0x418714, 0x00000000); | |
617 | nv_wr32(priv, 0x418384, 0x00000000); | |
618 | nv_wr32(priv, 0x418814, 0x00000000); | |
619 | nv_wr32(priv, 0x418818, 0x00000000); | |
620 | nv_wr32(priv, 0x41881c, 0x00000000); | |
621 | nv_wr32(priv, 0x418b04, 0x00000000); | |
622 | nv_wr32(priv, 0x4188c8, 0x00000000); | |
623 | nv_wr32(priv, 0x4188cc, 0x00000000); | |
624 | nv_wr32(priv, 0x4188d0, 0x00010000); | |
625 | nv_wr32(priv, 0x4188d4, 0x00000001); | |
626 | nv_wr32(priv, 0x418910, 0x00010001); | |
627 | nv_wr32(priv, 0x418914, 0x00000301); | |
628 | nv_wr32(priv, 0x418918, 0x00800000); | |
629 | nv_wr32(priv, 0x418980, 0x77777770); | |
630 | nv_wr32(priv, 0x418984, 0x77777777); | |
631 | nv_wr32(priv, 0x418988, 0x77777777); | |
632 | nv_wr32(priv, 0x41898c, 0x77777777); | |
633 | nv_wr32(priv, 0x418c04, 0x00000000); | |
634 | nv_wr32(priv, 0x418c64, 0x00000000); | |
635 | nv_wr32(priv, 0x418c68, 0x00000000); | |
636 | nv_wr32(priv, 0x418c88, 0x00000000); | |
637 | nv_wr32(priv, 0x418cb4, 0x00000000); | |
638 | nv_wr32(priv, 0x418cb8, 0x00000000); | |
639 | nv_wr32(priv, 0x418d00, 0x00000000); | |
640 | nv_wr32(priv, 0x418d28, 0x00000000); | |
641 | nv_wr32(priv, 0x418d2c, 0x00000000); | |
cb1e06e0 BS |
642 | switch (nv_device(priv)->chipset) { |
643 | case 0xf0: | |
644 | nv_wr32(priv, 0x418f00, 0x00000400); | |
645 | break; | |
646 | default: | |
647 | nv_wr32(priv, 0x418f00, 0x00000000); | |
648 | break; | |
649 | } | |
99bd5537 BS |
650 | nv_wr32(priv, 0x418f08, 0x00000000); |
651 | nv_wr32(priv, 0x418f20, 0x00000000); | |
652 | nv_wr32(priv, 0x418f24, 0x00000000); | |
cb1e06e0 BS |
653 | switch (nv_device(priv)->chipset) { |
654 | case 0xf0: | |
655 | nv_wr32(priv, 0x418e00, 0x00000000); | |
656 | break; | |
657 | default: | |
658 | nv_wr32(priv, 0x418e00, 0x00000060); | |
659 | break; | |
660 | } | |
99bd5537 BS |
661 | nv_wr32(priv, 0x418e08, 0x00000000); |
662 | nv_wr32(priv, 0x418e1c, 0x00000000); | |
663 | nv_wr32(priv, 0x418e20, 0x00000000); | |
664 | nv_wr32(priv, 0x41900c, 0x00000000); | |
665 | nv_wr32(priv, 0x419018, 0x00000000); | |
666 | } | |
667 | ||
668 | static void | |
669 | nve0_graph_init_tpc(struct nvc0_graph_priv *priv) | |
670 | { | |
671 | nv_wr32(priv, 0x419d0c, 0x00000000); | |
672 | nv_wr32(priv, 0x419d10, 0x00000014); | |
673 | nv_wr32(priv, 0x419ab0, 0x00000000); | |
674 | nv_wr32(priv, 0x419ac8, 0x00000000); | |
675 | nv_wr32(priv, 0x419ab8, 0x000000e7); | |
cb1e06e0 BS |
676 | switch (nv_device(priv)->chipset) { |
677 | case 0xf0: | |
678 | nv_wr32(priv, 0x419aec, 0x00000000); | |
679 | break; | |
680 | default: | |
681 | break; | |
682 | } | |
99bd5537 BS |
683 | nv_wr32(priv, 0x419abc, 0x00000000); |
684 | nv_wr32(priv, 0x419ac0, 0x00000000); | |
685 | nv_wr32(priv, 0x419ab4, 0x00000000); | |
cb1e06e0 BS |
686 | switch (nv_device(priv)->chipset) { |
687 | case 0xf0: | |
688 | nv_wr32(priv, 0x419aa8, 0x00000000); | |
689 | nv_wr32(priv, 0x419aac, 0x00000000); | |
690 | break; | |
691 | default: | |
692 | break; | |
693 | } | |
99bd5537 BS |
694 | nv_wr32(priv, 0x41980c, 0x00000010); |
695 | nv_wr32(priv, 0x419844, 0x00000000); | |
696 | nv_wr32(priv, 0x419850, 0x00000004); | |
697 | nv_wr32(priv, 0x419854, 0x00000000); | |
698 | nv_wr32(priv, 0x419858, 0x00000000); | |
699 | nv_wr32(priv, 0x419c98, 0x00000000); | |
700 | nv_wr32(priv, 0x419ca8, 0x00000000); | |
701 | nv_wr32(priv, 0x419cb0, 0x01000000); | |
702 | nv_wr32(priv, 0x419cb4, 0x00000000); | |
703 | nv_wr32(priv, 0x419cb8, 0x00b08bea); | |
704 | nv_wr32(priv, 0x419c84, 0x00010384); | |
cb1e06e0 BS |
705 | switch (nv_device(priv)->chipset) { |
706 | case 0xf0: | |
707 | nv_wr32(priv, 0x419cbc, 0x281b3646); | |
708 | break; | |
709 | default: | |
710 | nv_wr32(priv, 0x419cbc, 0x28137646); | |
711 | break; | |
712 | } | |
99bd5537 BS |
713 | nv_wr32(priv, 0x419cc0, 0x00000000); |
714 | nv_wr32(priv, 0x419cc4, 0x00000000); | |
cb1e06e0 BS |
715 | switch (nv_device(priv)->chipset) { |
716 | case 0xf0: | |
717 | nv_wr32(priv, 0x419c80, 0x00020230); | |
718 | nv_wr32(priv, 0x419ccc, 0x00000000); | |
719 | nv_wr32(priv, 0x419cd0, 0x00000000); | |
720 | nv_wr32(priv, 0x419c0c, 0x00000000); | |
721 | nv_wr32(priv, 0x419e00, 0x00000080); | |
722 | break; | |
723 | default: | |
724 | nv_wr32(priv, 0x419c80, 0x00020232); | |
725 | nv_wr32(priv, 0x419c0c, 0x00000000); | |
726 | nv_wr32(priv, 0x419e00, 0x00000000); | |
727 | break; | |
728 | } | |
99bd5537 BS |
729 | nv_wr32(priv, 0x419ea0, 0x00000000); |
730 | nv_wr32(priv, 0x419ee4, 0x00000000); | |
731 | nv_wr32(priv, 0x419ea4, 0x00000100); | |
732 | nv_wr32(priv, 0x419ea8, 0x00000000); | |
733 | nv_wr32(priv, 0x419eb4, 0x00000000); | |
cb1e06e0 BS |
734 | switch (nv_device(priv)->chipset) { |
735 | case 0xf0: | |
736 | break; | |
737 | default: | |
738 | nv_wr32(priv, 0x419eb8, 0x00000000); | |
739 | break; | |
740 | } | |
99bd5537 BS |
741 | nv_wr32(priv, 0x419ebc, 0x00000000); |
742 | nv_wr32(priv, 0x419ec0, 0x00000000); | |
743 | nv_wr32(priv, 0x419edc, 0x00000000); | |
744 | nv_wr32(priv, 0x419f00, 0x00000000); | |
cb1e06e0 BS |
745 | switch (nv_device(priv)->chipset) { |
746 | case 0xf0: | |
747 | nv_wr32(priv, 0x419ed0, 0x00003234); | |
748 | nv_wr32(priv, 0x419f74, 0x00015555); | |
749 | nv_wr32(priv, 0x419f80, 0x00000000); | |
750 | nv_wr32(priv, 0x419f84, 0x00000000); | |
751 | nv_wr32(priv, 0x419f88, 0x00000000); | |
752 | nv_wr32(priv, 0x419f8c, 0x00000000); | |
753 | break; | |
754 | default: | |
755 | nv_wr32(priv, 0x419f74, 0x00000555); | |
756 | break; | |
757 | } | |
99bd5537 BS |
758 | } |
759 | ||
760 | static void | |
761 | nve0_graph_init_tpcunk(struct nvc0_graph_priv *priv) | |
762 | { | |
763 | nv_wr32(priv, 0x41be04, 0x00000000); | |
764 | nv_wr32(priv, 0x41be08, 0x00000004); | |
765 | nv_wr32(priv, 0x41be0c, 0x00000000); | |
766 | nv_wr32(priv, 0x41be10, 0x003b8bc7); | |
767 | nv_wr32(priv, 0x41be14, 0x00000000); | |
768 | nv_wr32(priv, 0x41be18, 0x00000000); | |
769 | nv_wr32(priv, 0x41bfd4, 0x00800000); | |
770 | nv_wr32(priv, 0x41bfdc, 0x00000000); | |
771 | nv_wr32(priv, 0x41bff8, 0x00000000); | |
772 | nv_wr32(priv, 0x41bffc, 0x00000000); | |
773 | nv_wr32(priv, 0x41becc, 0x00000000); | |
774 | nv_wr32(priv, 0x41bee8, 0x00000000); | |
775 | nv_wr32(priv, 0x41beec, 0x00000000); | |
776 | } | |
777 | ||
778 | static void | |
779 | nve0_graph_init_unk88xx(struct nvc0_graph_priv *priv) | |
780 | { | |
781 | nv_wr32(priv, 0x40880c, 0x00000000); | |
782 | nv_wr32(priv, 0x408850, 0x00000004); | |
783 | nv_wr32(priv, 0x408910, 0x00000000); | |
784 | nv_wr32(priv, 0x408914, 0x00000000); | |
785 | nv_wr32(priv, 0x408918, 0x00000000); | |
786 | nv_wr32(priv, 0x40891c, 0x00000000); | |
787 | nv_wr32(priv, 0x408920, 0x00000000); | |
788 | nv_wr32(priv, 0x408924, 0x00000000); | |
789 | nv_wr32(priv, 0x408928, 0x00000000); | |
790 | nv_wr32(priv, 0x40892c, 0x00000000); | |
791 | nv_wr32(priv, 0x408930, 0x00000000); | |
792 | nv_wr32(priv, 0x408950, 0x00000000); | |
793 | nv_wr32(priv, 0x408954, 0x0000ffff); | |
794 | nv_wr32(priv, 0x408958, 0x00000034); | |
795 | nv_wr32(priv, 0x408984, 0x00000000); | |
796 | nv_wr32(priv, 0x408988, 0x08040201); | |
797 | nv_wr32(priv, 0x40898c, 0x80402010); | |
798 | } | |
799 | ||
ab394543 | 800 | static void |
ebb945a9 | 801 | nve0_graph_init_units(struct nvc0_graph_priv *priv) |
ab394543 | 802 | { |
ebb945a9 BS |
803 | nv_wr32(priv, 0x409ffc, 0x00000000); |
804 | nv_wr32(priv, 0x409c14, 0x00003e3e); | |
99bd5537 | 805 | switch (nv_device(priv)->chipset) { |
507cd5b5 | 806 | case 0xe7: |
99bd5537 BS |
807 | case 0xe6: |
808 | nv_wr32(priv, 0x409c24, 0x000f0001); | |
809 | break; | |
810 | default: | |
811 | nv_wr32(priv, 0x409c24, 0x000f0000); | |
812 | break; | |
813 | } | |
ebb945a9 BS |
814 | |
815 | nv_wr32(priv, 0x404000, 0xc0000000); | |
816 | nv_wr32(priv, 0x404600, 0xc0000000); | |
817 | nv_wr32(priv, 0x408030, 0xc0000000); | |
818 | nv_wr32(priv, 0x404490, 0xc0000000); | |
819 | nv_wr32(priv, 0x406018, 0xc0000000); | |
99bd5537 | 820 | switch (nv_device(priv)->chipset) { |
507cd5b5 | 821 | case 0xe7: |
99bd5537 | 822 | case 0xe6: |
cb1e06e0 | 823 | case 0xf0: |
99bd5537 BS |
824 | nv_wr32(priv, 0x407020, 0x40000000); |
825 | break; | |
826 | default: | |
827 | nv_wr32(priv, 0x407020, 0xc0000000); | |
828 | break; | |
829 | } | |
ebb945a9 BS |
830 | nv_wr32(priv, 0x405840, 0xc0000000); |
831 | nv_wr32(priv, 0x405844, 0x00ffffff); | |
832 | ||
833 | nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); | |
834 | nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000); | |
ab394543 BS |
835 | |
836 | } | |
837 | ||
838 | static void | |
ebb945a9 | 839 | nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv) |
ab394543 | 840 | { |
ab394543 BS |
841 | const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); |
842 | u32 data[TPC_MAX / 8]; | |
843 | u8 tpcnr[GPC_MAX]; | |
844 | int i, gpc, tpc; | |
845 | ||
ebb945a9 | 846 | nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); |
ab394543 BS |
847 | |
848 | memset(data, 0x00, sizeof(data)); | |
849 | memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); | |
850 | for (i = 0, gpc = -1; i < priv->tpc_total; i++) { | |
851 | do { | |
852 | gpc = (gpc + 1) % priv->gpc_nr; | |
853 | } while (!tpcnr[gpc]); | |
854 | tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; | |
855 | ||
856 | data[i / 8] |= tpc << ((i % 8) * 4); | |
857 | } | |
858 | ||
ebb945a9 BS |
859 | nv_wr32(priv, GPC_BCAST(0x0980), data[0]); |
860 | nv_wr32(priv, GPC_BCAST(0x0984), data[1]); | |
861 | nv_wr32(priv, GPC_BCAST(0x0988), data[2]); | |
862 | nv_wr32(priv, GPC_BCAST(0x098c), data[3]); | |
ab394543 BS |
863 | |
864 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | |
ebb945a9 | 865 | nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | |
ab394543 | 866 | priv->tpc_nr[gpc]); |
ebb945a9 BS |
867 | nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total); |
868 | nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); | |
ab394543 BS |
869 | } |
870 | ||
65b5f42e | 871 | nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); |
ebb945a9 | 872 | nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); |
ab394543 BS |
873 | } |
874 | ||
875 | static void | |
ebb945a9 | 876 | nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv) |
ab394543 | 877 | { |
ab394543 BS |
878 | int gpc, tpc; |
879 | ||
880 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | |
ebb945a9 BS |
881 | nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000); |
882 | nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); | |
883 | nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); | |
884 | nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); | |
885 | nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); | |
ab394543 | 886 | for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { |
ebb945a9 BS |
887 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); |
888 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); | |
889 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); | |
890 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); | |
891 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); | |
892 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe); | |
893 | nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f); | |
ab394543 | 894 | } |
ebb945a9 BS |
895 | nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); |
896 | nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); | |
ab394543 BS |
897 | } |
898 | } | |
899 | ||
900 | static void | |
ebb945a9 | 901 | nve0_graph_init_rop(struct nvc0_graph_priv *priv) |
ab394543 | 902 | { |
ab394543 BS |
903 | int rop; |
904 | ||
905 | for (rop = 0; rop < priv->rop_nr; rop++) { | |
ebb945a9 BS |
906 | nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); |
907 | nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); | |
908 | nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); | |
909 | nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); | |
ab394543 BS |
910 | } |
911 | } | |
912 | ||
913 | static int | |
ebb945a9 | 914 | nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv) |
ab394543 | 915 | { |
ab394543 | 916 | u32 r000260; |
1978a2f2 | 917 | int i; |
ab394543 | 918 | |
1978a2f2 BS |
919 | if (priv->firmware) { |
920 | /* load fuc microcode */ | |
921 | r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); | |
922 | nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d); | |
923 | nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); | |
924 | nv_wr32(priv, 0x000260, r000260); | |
925 | ||
926 | /* start both of them running */ | |
927 | nv_wr32(priv, 0x409840, 0xffffffff); | |
928 | nv_wr32(priv, 0x41a10c, 0x00000000); | |
929 | nv_wr32(priv, 0x40910c, 0x00000000); | |
930 | nv_wr32(priv, 0x41a100, 0x00000002); | |
931 | nv_wr32(priv, 0x409100, 0x00000002); | |
932 | if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001)) | |
933 | nv_error(priv, "0x409800 wait failed\n"); | |
934 | ||
935 | nv_wr32(priv, 0x409840, 0xffffffff); | |
936 | nv_wr32(priv, 0x409500, 0x7fffffff); | |
937 | nv_wr32(priv, 0x409504, 0x00000021); | |
938 | ||
939 | nv_wr32(priv, 0x409840, 0xffffffff); | |
940 | nv_wr32(priv, 0x409500, 0x00000000); | |
941 | nv_wr32(priv, 0x409504, 0x00000010); | |
942 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
943 | nv_error(priv, "fuc09 req 0x10 timeout\n"); | |
944 | return -EBUSY; | |
945 | } | |
946 | priv->size = nv_rd32(priv, 0x409800); | |
947 | ||
948 | nv_wr32(priv, 0x409840, 0xffffffff); | |
949 | nv_wr32(priv, 0x409500, 0x00000000); | |
950 | nv_wr32(priv, 0x409504, 0x00000016); | |
951 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
952 | nv_error(priv, "fuc09 req 0x16 timeout\n"); | |
953 | return -EBUSY; | |
954 | } | |
ab394543 | 955 | |
1978a2f2 BS |
956 | nv_wr32(priv, 0x409840, 0xffffffff); |
957 | nv_wr32(priv, 0x409500, 0x00000000); | |
958 | nv_wr32(priv, 0x409504, 0x00000025); | |
959 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
960 | nv_error(priv, "fuc09 req 0x25 timeout\n"); | |
961 | return -EBUSY; | |
962 | } | |
ab394543 | 963 | |
1978a2f2 BS |
964 | nv_wr32(priv, 0x409800, 0x00000000); |
965 | nv_wr32(priv, 0x409500, 0x00000001); | |
966 | nv_wr32(priv, 0x409504, 0x00000030); | |
967 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
968 | nv_error(priv, "fuc09 req 0x30 timeout\n"); | |
969 | return -EBUSY; | |
970 | } | |
ab394543 | 971 | |
1978a2f2 BS |
972 | nv_wr32(priv, 0x409810, 0xb00095c8); |
973 | nv_wr32(priv, 0x409800, 0x00000000); | |
974 | nv_wr32(priv, 0x409500, 0x00000001); | |
975 | nv_wr32(priv, 0x409504, 0x00000031); | |
976 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
977 | nv_error(priv, "fuc09 req 0x31 timeout\n"); | |
978 | return -EBUSY; | |
979 | } | |
980 | ||
981 | nv_wr32(priv, 0x409810, 0x00080420); | |
982 | nv_wr32(priv, 0x409800, 0x00000000); | |
983 | nv_wr32(priv, 0x409500, 0x00000001); | |
984 | nv_wr32(priv, 0x409504, 0x00000032); | |
985 | if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) { | |
986 | nv_error(priv, "fuc09 req 0x32 timeout\n"); | |
987 | return -EBUSY; | |
988 | } | |
989 | ||
990 | nv_wr32(priv, 0x409614, 0x00000070); | |
991 | nv_wr32(priv, 0x409614, 0x00000770); | |
992 | nv_wr32(priv, 0x40802c, 0x00000001); | |
993 | ||
994 | if (priv->data == NULL) { | |
995 | int ret = nve0_grctx_generate(priv); | |
996 | if (ret) { | |
997 | nv_error(priv, "failed to construct context\n"); | |
998 | return ret; | |
999 | } | |
1000 | } | |
1001 | ||
1002 | return 0; | |
ab394543 BS |
1003 | } |
1004 | ||
1978a2f2 BS |
1005 | /* load HUB microcode */ |
1006 | r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000); | |
1007 | nv_wr32(priv, 0x4091c0, 0x01000000); | |
1008 | for (i = 0; i < sizeof(nve0_grhub_data) / 4; i++) | |
1009 | nv_wr32(priv, 0x4091c4, nve0_grhub_data[i]); | |
1010 | ||
1011 | nv_wr32(priv, 0x409180, 0x01000000); | |
1012 | for (i = 0; i < sizeof(nve0_grhub_code) / 4; i++) { | |
1013 | if ((i & 0x3f) == 0) | |
1014 | nv_wr32(priv, 0x409188, i >> 6); | |
1015 | nv_wr32(priv, 0x409184, nve0_grhub_code[i]); | |
ab394543 BS |
1016 | } |
1017 | ||
1978a2f2 BS |
1018 | /* load GPC microcode */ |
1019 | nv_wr32(priv, 0x41a1c0, 0x01000000); | |
1020 | for (i = 0; i < sizeof(nve0_grgpc_data) / 4; i++) | |
1021 | nv_wr32(priv, 0x41a1c4, nve0_grgpc_data[i]); | |
1022 | ||
1023 | nv_wr32(priv, 0x41a180, 0x01000000); | |
1024 | for (i = 0; i < sizeof(nve0_grgpc_code) / 4; i++) { | |
1025 | if ((i & 0x3f) == 0) | |
1026 | nv_wr32(priv, 0x41a188, i >> 6); | |
1027 | nv_wr32(priv, 0x41a184, nve0_grgpc_code[i]); | |
ab394543 | 1028 | } |
1978a2f2 | 1029 | nv_wr32(priv, 0x000260, r000260); |
ab394543 | 1030 | |
1978a2f2 BS |
1031 | /* start HUB ucode running, it'll init the GPCs */ |
1032 | nv_wr32(priv, 0x409800, nv_device(priv)->chipset); | |
1033 | nv_wr32(priv, 0x40910c, 0x00000000); | |
1034 | nv_wr32(priv, 0x409100, 0x00000002); | |
1035 | if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { | |
1036 | nv_error(priv, "HUB_INIT timed out\n"); | |
1037 | nvc0_graph_ctxctl_debug(priv); | |
ab394543 BS |
1038 | return -EBUSY; |
1039 | } | |
1040 | ||
1978a2f2 | 1041 | priv->size = nv_rd32(priv, 0x409804); |
ac1499d9 | 1042 | if (priv->data == NULL) { |
ebb945a9 | 1043 | int ret = nve0_grctx_generate(priv); |
ac1499d9 | 1044 | if (ret) { |
ebb945a9 | 1045 | nv_error(priv, "failed to construct context\n"); |
ac1499d9 BS |
1046 | return ret; |
1047 | } | |
ac1499d9 BS |
1048 | } |
1049 | ||
ab394543 BS |
1050 | return 0; |
1051 | } | |
1052 | ||
1053 | static int | |
ebb945a9 | 1054 | nve0_graph_init(struct nouveau_object *object) |
ab394543 | 1055 | { |
ebb945a9 | 1056 | struct nvc0_graph_priv *priv = (void *)object; |
ab394543 BS |
1057 | int ret; |
1058 | ||
ebb945a9 | 1059 | ret = nouveau_graph_init(&priv->base); |
ab394543 BS |
1060 | if (ret) |
1061 | return ret; | |
1062 | ||
ebb945a9 BS |
1063 | nve0_graph_init_obj418880(priv); |
1064 | nve0_graph_init_regs(priv); | |
99bd5537 BS |
1065 | |
1066 | switch (nv_device(priv)->chipset) { | |
507cd5b5 | 1067 | case 0xe7: |
99bd5537 | 1068 | case 0xe6: |
cb1e06e0 | 1069 | case 0xf0: |
99bd5537 BS |
1070 | nve0_graph_init_unk40xx(priv); |
1071 | nve0_graph_init_unk44xx(priv); | |
1072 | nve0_graph_init_unk78xx(priv); | |
1073 | nve0_graph_init_unk60xx(priv); | |
1074 | nve0_graph_init_unk64xx(priv); | |
1075 | nve0_graph_init_unk58xx(priv); | |
1076 | nve0_graph_init_unk80xx(priv); | |
1077 | nve0_graph_init_unk70xx(priv); | |
1078 | nve0_graph_init_unk5bxx(priv); | |
1079 | nve0_graph_init_gpc(priv); | |
1080 | nve0_graph_init_tpc(priv); | |
1081 | nve0_graph_init_tpcunk(priv); | |
1082 | nve0_graph_init_unk88xx(priv); | |
1083 | break; | |
1084 | default: | |
1085 | break; | |
1086 | } | |
1087 | ||
ebb945a9 | 1088 | nve0_graph_init_gpc_0(priv); |
ab394543 | 1089 | |
ebb945a9 BS |
1090 | nv_wr32(priv, 0x400500, 0x00010001); |
1091 | nv_wr32(priv, 0x400100, 0xffffffff); | |
1092 | nv_wr32(priv, 0x40013c, 0xffffffff); | |
ab394543 | 1093 | |
ebb945a9 BS |
1094 | nve0_graph_init_units(priv); |
1095 | nve0_graph_init_gpc_1(priv); | |
1096 | nve0_graph_init_rop(priv); | |
ab394543 | 1097 | |
ebb945a9 BS |
1098 | nv_wr32(priv, 0x400108, 0xffffffff); |
1099 | nv_wr32(priv, 0x400138, 0xffffffff); | |
1100 | nv_wr32(priv, 0x400118, 0xffffffff); | |
1101 | nv_wr32(priv, 0x400130, 0xffffffff); | |
1102 | nv_wr32(priv, 0x40011c, 0xffffffff); | |
1103 | nv_wr32(priv, 0x400134, 0xffffffff); | |
1104 | nv_wr32(priv, 0x400054, 0x34ce3464); | |
ab394543 | 1105 | |
ebb945a9 | 1106 | ret = nve0_graph_init_ctxctl(priv); |
b10f20d5 | 1107 | if (ret) |
ebb945a9 | 1108 | return ret; |
ab394543 | 1109 | |
ab394543 | 1110 | return 0; |
ab394543 | 1111 | } |
ebb945a9 BS |
1112 | |
1113 | struct nouveau_oclass | |
1114 | nve0_graph_oclass = { | |
1115 | .handle = NV_ENGINE(GR, 0xe0), | |
1116 | .ofuncs = &(struct nouveau_ofuncs) { | |
1117 | .ctor = nve0_graph_ctor, | |
1118 | .dtor = nvc0_graph_dtor, | |
1119 | .init = nve0_graph_init, | |
1120 | .fini = _nouveau_graph_fini, | |
1121 | }, | |
1122 | }; |