]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc
drm/nvc0/gr: update initial register/context values
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / core / engine / graph / fuc / hubnvc0.fuc
1 /* fuc microcode for nvc0 PGRAPH/HUB
2  *
3  * Copyright 2011 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: Ben Skeggs
24  */
25
26 /* To build:
27  *    m4 hubnvc0.fuc | envyas -a -w -m fuc -V fuc3 -o hubnvc0.fuc.h
28  */
29
30 .section #nvc0_grhub_data
31 include(`nvc0.fuc')
32 gpc_count:              .b32 0
33 rop_count:              .b32 0
34 cmd_queue:              queue_init
35 hub_mmio_list_head:     .b32 0
36 hub_mmio_list_tail:     .b32 0
37
38 ctx_current:            .b32 0
39
40 .align 256
41 chan_data:
42 chan_mmio_count:        .b32 0
43 chan_mmio_address:      .b32 0
44
45 .align 256
46 xfer_data:              .b32 0
47
48 .align 256
49 chipsets:
50 .b8  0xc0 0 0 0
51 .b16 #nnvc0_hub_mmio_head
52 .b16 #nnvc0_hub_mmio_tail
53 .b8  0xc1 0 0 0
54 .b16 #nvc0_hub_mmio_head
55 .b16 #nvc1_hub_mmio_tail
56 .b8  0xc3 0 0 0
57 .b16 #nvc0_hub_mmio_head
58 .b16 #nvc0_hub_mmio_tail
59 .b8  0xc4 0 0 0
60 .b16 #nvc0_hub_mmio_head
61 .b16 #nvc0_hub_mmio_tail
62 .b8  0xc8 0 0 0
63 .b16 #nvc0_hub_mmio_head
64 .b16 #nvc0_hub_mmio_tail
65 .b8  0xce 0 0 0
66 .b16 #nvc0_hub_mmio_head
67 .b16 #nvc0_hub_mmio_tail
68 .b8  0xcf 0 0 0
69 .b16 #nvc0_hub_mmio_head
70 .b16 #nvc0_hub_mmio_tail
71 .b8  0xd9 0 0 0
72 .b16 #nvd9_hub_mmio_head
73 .b16 #nvd9_hub_mmio_tail
74 .b8  0xd7 0 0 0
75 .b16 #nvd9_hub_mmio_head
76 .b16 #nvd9_hub_mmio_tail
77 .b8  0 0 0 0
78
79 nvc0_hub_mmio_head:
80 mmctx_data(0x17e91c, 2)
81 mmctx_data(0x400204, 2)
82 mmctx_data(0x404004, 11)
83 mmctx_data(0x404044, 1)
84 mmctx_data(0x404094, 14)
85 mmctx_data(0x4040d0, 7)
86 mmctx_data(0x4040f8, 1)
87 mmctx_data(0x404130, 3)
88 mmctx_data(0x404150, 3)
89 mmctx_data(0x404164, 2)
90 mmctx_data(0x404174, 3)
91 mmctx_data(0x404200, 8)
92 mmctx_data(0x404404, 14)
93 mmctx_data(0x404460, 4)
94 mmctx_data(0x404480, 1)
95 mmctx_data(0x404498, 1)
96 mmctx_data(0x404604, 4)
97 mmctx_data(0x404618, 32)
98 mmctx_data(0x404698, 21)
99 mmctx_data(0x4046f0, 2)
100 mmctx_data(0x404700, 22)
101 mmctx_data(0x405800, 1)
102 mmctx_data(0x405830, 3)
103 mmctx_data(0x405854, 1)
104 mmctx_data(0x405870, 4)
105 mmctx_data(0x405a00, 2)
106 mmctx_data(0x405a18, 1)
107 mmctx_data(0x406020, 1)
108 mmctx_data(0x406028, 4)
109 mmctx_data(0x4064a8, 2)
110 mmctx_data(0x4064b4, 2)
111 mmctx_data(0x407804, 1)
112 mmctx_data(0x40780c, 6)
113 mmctx_data(0x4078bc, 1)
114 mmctx_data(0x408000, 7)
115 mmctx_data(0x408064, 1)
116 mmctx_data(0x408800, 3)
117 mmctx_data(0x408900, 4)
118 mmctx_data(0x408980, 1)
119 nvc0_hub_mmio_tail:
120 mmctx_data(0x4064c0, 2)
121 nvc1_hub_mmio_tail:
122
123 nnvc0_hub_mmio_head:
124 mmctx_data(0x17e91c, 2)
125 mmctx_data(0x400204, 2)
126 mmctx_data(0x404004, 11)
127 mmctx_data(0x404044, 1)
128 mmctx_data(0x404094, 14)
129 mmctx_data(0x4040d0, 7)
130 mmctx_data(0x4040f8, 1)
131 mmctx_data(0x404130, 3)
132 mmctx_data(0x404150, 3)
133 mmctx_data(0x404164, 2)
134 mmctx_data(0x404174, 3)
135 mmctx_data(0x404200, 8)
136 mmctx_data(0x404404, 14)
137 mmctx_data(0x404460, 4)
138 mmctx_data(0x404480, 1)
139 mmctx_data(0x404498, 1)
140 mmctx_data(0x404604, 4)
141 mmctx_data(0x404618, 32)
142 mmctx_data(0x404698, 21)
143 mmctx_data(0x4046f0, 2)
144 mmctx_data(0x404700, 22)
145 mmctx_data(0x405800, 1)
146 mmctx_data(0x405830, 3)
147 mmctx_data(0x405854, 1)
148 mmctx_data(0x405870, 4)
149 mmctx_data(0x405a00, 2)
150 mmctx_data(0x405a18, 1)
151 mmctx_data(0x406020, 1)
152 mmctx_data(0x406028, 4)
153 mmctx_data(0x4064a8, 2)
154 mmctx_data(0x4064b4, 2)
155 mmctx_data(0x407804, 1)
156 mmctx_data(0x40780c, 6)
157 mmctx_data(0x4078bc, 1)
158 mmctx_data(0x408000, 7)
159 mmctx_data(0x408064, 1)
160 mmctx_data(0x408800, 3)
161 mmctx_data(0x408900, 3)
162 mmctx_data(0x408980, 1)
163 nnvc0_hub_mmio_tail:
164
165 nvd9_hub_mmio_head:
166 mmctx_data(0x17e91c, 2)
167 mmctx_data(0x400204, 2)
168 mmctx_data(0x404004, 10)
169 mmctx_data(0x404044, 1)
170 mmctx_data(0x404094, 14)
171 mmctx_data(0x4040d0, 7)
172 mmctx_data(0x4040f8, 1)
173 mmctx_data(0x404130, 3)
174 mmctx_data(0x404150, 3)
175 mmctx_data(0x404164, 2)
176 mmctx_data(0x404178, 2)
177 mmctx_data(0x404200, 8)
178 mmctx_data(0x404404, 14)
179 mmctx_data(0x404460, 4)
180 mmctx_data(0x404480, 1)
181 mmctx_data(0x404498, 1)
182 mmctx_data(0x404604, 4)
183 mmctx_data(0x404618, 32)
184 mmctx_data(0x404698, 21)
185 mmctx_data(0x4046f0, 2)
186 mmctx_data(0x404700, 22)
187 mmctx_data(0x405800, 1)
188 mmctx_data(0x405830, 3)
189 mmctx_data(0x405854, 1)
190 mmctx_data(0x405870, 4)
191 mmctx_data(0x405a00, 2)
192 mmctx_data(0x405a18, 1)
193 mmctx_data(0x406020, 1)
194 mmctx_data(0x406028, 4)
195 mmctx_data(0x4064a8, 2)
196 mmctx_data(0x4064b4, 5)
197 mmctx_data(0x407804, 1)
198 mmctx_data(0x40780c, 6)
199 mmctx_data(0x4078bc, 1)
200 mmctx_data(0x408000, 7)
201 mmctx_data(0x408064, 1)
202 mmctx_data(0x408800, 3)
203 mmctx_data(0x408900, 3)
204 mmctx_data(0x408980, 1)
205 nvd9_hub_mmio_tail:
206
207 .section #nvc0_grhub_code
208 bra #init
209 define(`include_code')
210 include(`nvc0.fuc')
211
212 // reports an exception to the host
213 //
214 // In: $r15 error code (see nvc0.fuc)
215 //
216 error:
217         push $r14
218         mov $r14 0x814
219         shl b32 $r14 6
220         iowr I[$r14 + 0x000] $r15       // CC_SCRATCH[5] = error code
221         mov $r14 0xc1c
222         shl b32 $r14 6
223         mov $r15 1
224         iowr I[$r14 + 0x000] $r15       // INTR_UP_SET
225         pop $r14
226         ret
227
228 // HUB fuc initialisation, executed by triggering ucode start, will
229 // fall through to main loop after completion.
230 //
231 // Input:
232 //   CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
233 //
234 // Output:
235 //   CC_SCRATCH[0]:
236 //           31:31: set to signal completion
237 //   CC_SCRATCH[1]:
238 //            31:0: total PGRAPH context size
239 //
240 init:
241         clear b32 $r0
242         mov $sp $r0
243         mov $xdbase $r0
244
245         // enable fifo access
246         mov $r1 0x1200
247         mov $r2 2
248         iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
249
250         // setup i0 handler, and route all interrupts to it
251         mov $r1 #ih
252         mov $iv0 $r1
253         mov $r1 0x400
254         iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
255
256         // route HUB_CHANNEL_SWITCH to fuc interrupt 8
257         mov $r3 0x404
258         shl b32 $r3 6
259         mov $r2 0x2003          // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
260         iowr I[$r3 + 0x000] $r2
261
262         // not sure what these are, route them because NVIDIA does, and
263         // the IRQ handler will signal the host if we ever get one.. we
264         // may find out if/why we need to handle these if so..
265         //
266         mov $r2 0x2004
267         iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
268         mov $r2 0x200b
269         iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
270         mov $r2 0x200c
271         iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
272
273         // enable all INTR_UP interrupts
274         mov $r2 0xc24
275         shl b32 $r2 6
276         not b32 $r3 $r0
277         iowr I[$r2] $r3
278
279         // enable fifo, ctxsw, 9, 10, 15 interrupts
280         mov $r2 -0x78fc         // 0x8704
281         sethi $r2 0
282         iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
283
284         // fifo level triggered, rest edge
285         sub b32 $r1 0x100
286         mov $r2 4
287         iowr I[$r1] $r2
288
289         // enable interrupts
290         bset $flags ie0
291
292         // fetch enabled GPC/ROP counts
293         mov $r14 -0x69fc        // 0x409604
294         sethi $r14 0x400000
295         call #nv_rd32
296         extr $r1 $r15 16:20
297         st b32 D[$r0 + #rop_count] $r1
298         and $r15 0x1f
299         st b32 D[$r0 + #gpc_count] $r15
300
301         // set BAR_REQMASK to GPC mask
302         mov $r1 1
303         shl b32 $r1 $r15
304         sub b32 $r1 1
305         mov $r2 0x40c
306         shl b32 $r2 6
307         iowr I[$r2 + 0x000] $r1
308         iowr I[$r2 + 0x100] $r1
309
310         // find context data for this chipset
311         mov $r2 0x800
312         shl b32 $r2 6
313         iord $r2 I[$r2 + 0x000]         // CC_SCRATCH[0]
314         mov $r15 #chipsets - 8
315         init_find_chipset:
316                 add b32 $r15 8
317                 ld b32 $r3 D[$r15 + 0x00]
318                 cmpu b32 $r3 $r2
319                 bra e #init_context
320                 cmpu b32 $r3 0
321                 bra ne #init_find_chipset
322                 // unknown chipset
323                 ret
324
325         // context size calculation, reserve first 256 bytes for use by fuc
326         init_context:
327         mov $r1 256
328
329         // calculate size of mmio context data
330         ld b16 $r14 D[$r15 + 4]
331         ld b16 $r15 D[$r15 + 6]
332         sethi $r14 0
333         st b32 D[$r0 + #hub_mmio_list_head] $r14
334         st b32 D[$r0 + #hub_mmio_list_tail] $r15
335         call #mmctx_size
336
337         // set mmctx base addresses now so we don't have to do it later,
338         // they don't (currently) ever change
339         mov $r3 0x700
340         shl b32 $r3 6
341         shr b32 $r4 $r1 8
342         iowr I[$r3 + 0x000] $r4         // MMCTX_SAVE_SWBASE
343         iowr I[$r3 + 0x100] $r4         // MMCTX_LOAD_SWBASE
344         add b32 $r3 0x1300
345         add b32 $r1 $r15
346         shr b32 $r15 2
347         iowr I[$r3 + 0x000] $r15        // MMCTX_LOAD_COUNT, wtf for?!?
348
349         // strands, base offset needs to be aligned to 256 bytes
350         shr b32 $r1 8
351         add b32 $r1 1
352         shl b32 $r1 8
353         mov b32 $r15 $r1
354         call #strand_ctx_init
355         add b32 $r1 $r15
356
357         // initialise each GPC in sequence by passing in the offset of its
358         // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which
359         // has previously been uploaded by the host) running.
360         //
361         // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31
362         // when it has completed, and return the size of its context data
363         // in GPCn_CC_SCRATCH[1]
364         //
365         ld b32 $r3 D[$r0 + #gpc_count]
366         mov $r4 0x2000
367         sethi $r4 0x500000
368         init_gpc:
369                 // setup, and start GPC ucode running
370                 add b32 $r14 $r4 0x804
371                 mov b32 $r15 $r1
372                 call #nv_wr32                   // CC_SCRATCH[1] = ctx offset
373                 add b32 $r14 $r4 0x800
374                 mov b32 $r15 $r2
375                 call #nv_wr32                   // CC_SCRATCH[0] = chipset
376                 add b32 $r14 $r4 0x10c
377                 clear b32 $r15
378                 call #nv_wr32
379                 add b32 $r14 $r4 0x104
380                 call #nv_wr32                   // ENTRY
381                 add b32 $r14 $r4 0x100
382                 mov $r15 2                      // CTRL_START_TRIGGER
383                 call #nv_wr32                   // CTRL
384
385                 // wait for it to complete, and adjust context size
386                 add b32 $r14 $r4 0x800
387                 init_gpc_wait:
388                         call #nv_rd32
389                         xbit $r15 $r15 31
390                         bra e #init_gpc_wait
391                 add b32 $r14 $r4 0x804
392                 call #nv_rd32
393                 add b32 $r1 $r15
394
395                 // next!
396                 add b32 $r4 0x8000
397                 sub b32 $r3 1
398                 bra ne #init_gpc
399
400         // save context size, and tell host we're ready
401         mov $r2 0x800
402         shl b32 $r2 6
403         iowr I[$r2 + 0x100] $r1         // CC_SCRATCH[1]  = context size
404         add b32 $r2 0x800
405         clear b32 $r1
406         bset $r1 31
407         iowr I[$r2 + 0x000] $r1         // CC_SCRATCH[0] |= 0x80000000
408
409 // Main program loop, very simple, sleeps until woken up by the interrupt
410 // handler, pulls a command from the queue and executes its handler
411 //
412 main:
413         // sleep until we have something to do
414         bset $flags $p0
415         sleep $p0
416         mov $r13 #cmd_queue
417         call #queue_get
418         bra $p1 #main
419
420         // context switch, requested by GPU?
421         cmpu b32 $r14 0x4001
422         bra ne #main_not_ctx_switch
423                 trace_set(T_AUTO)
424                 mov $r1 0xb00
425                 shl b32 $r1 6
426                 iord $r2 I[$r1 + 0x100]         // CHAN_NEXT
427                 iord $r1 I[$r1 + 0x000]         // CHAN_CUR
428
429                 xbit $r3 $r1 31
430                 bra e #chsw_no_prev
431                         xbit $r3 $r2 31
432                         bra e #chsw_prev_no_next
433                                 push $r2
434                                 mov b32 $r2 $r1
435                                 trace_set(T_SAVE)
436                                 bclr $flags $p1
437                                 bset $flags $p2
438                                 call #ctx_xfer
439                                 trace_clr(T_SAVE);
440                                 pop $r2
441                                 trace_set(T_LOAD);
442                                 bset $flags $p1
443                                 call #ctx_xfer
444                                 trace_clr(T_LOAD);
445                                 bra #chsw_done
446                         chsw_prev_no_next:
447                                 push $r2
448                                 mov b32 $r2 $r1
449                                 bclr $flags $p1
450                                 bclr $flags $p2
451                                 call #ctx_xfer
452                                 pop $r2
453                                 mov $r1 0xb00
454                                 shl b32 $r1 6
455                                 iowr I[$r1] $r2
456                                 bra #chsw_done
457                 chsw_no_prev:
458                         xbit $r3 $r2 31
459                         bra e #chsw_done
460                                 bset $flags $p1
461                                 bclr $flags $p2
462                                 call #ctx_xfer
463
464                 // ack the context switch request
465                 chsw_done:
466                 mov $r1 0xb0c
467                 shl b32 $r1 6
468                 mov $r2 1
469                 iowr I[$r1 + 0x000] $r2         // 0x409b0c
470                 trace_clr(T_AUTO)
471                 bra #main
472
473         // request to set current channel? (*not* a context switch)
474         main_not_ctx_switch:
475         cmpu b32 $r14 0x0001
476         bra ne #main_not_ctx_chan
477                 mov b32 $r2 $r15
478                 call #ctx_chan
479                 bra #main_done
480
481         // request to store current channel context?
482         main_not_ctx_chan:
483         cmpu b32 $r14 0x0002
484         bra ne #main_not_ctx_save
485                 trace_set(T_SAVE)
486                 bclr $flags $p1
487                 bclr $flags $p2
488                 call #ctx_xfer
489                 trace_clr(T_SAVE)
490                 bra #main_done
491
492         main_not_ctx_save:
493                 shl b32 $r15 $r14 16
494                 or $r15 E_BAD_COMMAND
495                 call #error
496                 bra #main
497
498         main_done:
499         mov $r1 0x820
500         shl b32 $r1 6
501         clear b32 $r2
502         bset $r2 31
503         iowr I[$r1 + 0x000] $r2         // CC_SCRATCH[0] |= 0x80000000
504         bra #main
505
506 // interrupt handler
507 ih:
508         push $r8
509         mov $r8 $flags
510         push $r8
511         push $r9
512         push $r10
513         push $r11
514         push $r13
515         push $r14
516         push $r15
517
518         // incoming fifo command?
519         iord $r10 I[$r0 + 0x200]        // INTR
520         and $r11 $r10 0x00000004
521         bra e #ih_no_fifo
522                 // queue incoming fifo command for later processing
523                 mov $r11 0x1900
524                 mov $r13 #cmd_queue
525                 iord $r14 I[$r11 + 0x100]       // FIFO_CMD
526                 iord $r15 I[$r11 + 0x000]       // FIFO_DATA
527                 call #queue_put
528                 add b32 $r11 0x400
529                 mov $r14 1
530                 iowr I[$r11 + 0x000] $r14       // FIFO_ACK
531
532         // context switch request?
533         ih_no_fifo:
534         and $r11 $r10 0x00000100
535         bra e #ih_no_ctxsw
536                 // enqueue a context switch for later processing
537                 mov $r13 #cmd_queue
538                 mov $r14 0x4001
539                 call #queue_put
540
541         // anything we didn't handle, bring it to the host's attention
542         ih_no_ctxsw:
543         mov $r11 0x104
544         not b32 $r11
545         and $r11 $r10 $r11
546         bra e #ih_no_other
547                 mov $r10 0xc1c
548                 shl b32 $r10 6
549                 iowr I[$r10] $r11       // INTR_UP_SET
550
551         // ack, and wake up main()
552         ih_no_other:
553         iowr I[$r0 + 0x100] $r10        // INTR_ACK
554
555         pop $r15
556         pop $r14
557         pop $r13
558         pop $r11
559         pop $r10
560         pop $r9
561         pop $r8
562         mov $flags $r8
563         pop $r8
564         bclr $flags $p0
565         iret
566
567 // Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
568 ctx_4160s:
569         mov $r14 0x4160
570         sethi $r14 0x400000
571         mov $r15 1
572         call #nv_wr32
573         ctx_4160s_wait:
574                 call #nv_rd32
575                 xbit $r15 $r15 4
576                 bra e #ctx_4160s_wait
577         ret
578
579 // Without clearing again at end of xfer, some things cause PGRAPH
580 // to hang with STATUS=0x00000007 until it's cleared.. fbcon can
581 // still function with it set however...
582 ctx_4160c:
583         mov $r14 0x4160
584         sethi $r14 0x400000
585         clear b32 $r15
586         call #nv_wr32
587         ret
588
589 // Again, not real sure
590 //
591 // In: $r15 value to set 0x404170 to
592 //
593 ctx_4170s:
594         mov $r14 0x4170
595         sethi $r14 0x400000
596         or $r15 0x10
597         call #nv_wr32
598         ret
599
600 // Waits for a ctx_4170s() call to complete
601 //
602 ctx_4170w:
603         mov $r14 0x4170
604         sethi $r14 0x400000
605         call #nv_rd32
606         and $r15 0x10
607         bra ne #ctx_4170w
608         ret
609
610 // Disables various things, waits a bit, and re-enables them..
611 //
612 // Not sure how exactly this helps, perhaps "ENABLE" is not such a
613 // good description for the bits we turn off?  Anyways, without this,
614 // funny things happen.
615 //
616 ctx_redswitch:
617         mov $r14 0x614
618         shl b32 $r14 6
619         mov $r15 0x270
620         iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
621         mov $r15 8
622         ctx_redswitch_delay:
623                 sub b32 $r15 1
624                 bra ne #ctx_redswitch_delay
625         mov $r15 0x770
626         iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
627         ret
628
629 // Not a clue what this is for, except that unless the value is 0x10, the
630 // strand context is saved (and presumably restored) incorrectly..
631 //
632 // In: $r15 value to set to (0x00/0x10 are used)
633 //
634 ctx_86c:
635         mov $r14 0x86c
636         shl b32 $r14 6
637         iowr I[$r14] $r15       // HUB(0x86c) = val
638         mov $r14 -0x75ec
639         sethi $r14 0x400000
640         call #nv_wr32           // ROP(0xa14) = val
641         mov $r14 -0x5794
642         sethi $r14 0x410000
643         call #nv_wr32           // GPC(0x86c) = val
644         ret
645
646 // ctx_load - load's a channel's ctxctl data, and selects its vm
647 //
648 // In: $r2 channel address
649 //
650 ctx_load:
651         trace_set(T_CHAN)
652
653         // switch to channel, somewhat magic in parts..
654         mov $r10 12             // DONE_UNK12
655         call #wait_donez
656         mov $r1 0xa24
657         shl b32 $r1 6
658         iowr I[$r1 + 0x000] $r0 // 0x409a24
659         mov $r3 0xb00
660         shl b32 $r3 6
661         iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
662         mov $r1 0xa0c
663         shl b32 $r1 6
664         mov $r4 7
665         iowr I[$r1 + 0x000] $r2 // MEM_CHAN
666         iowr I[$r1 + 0x100] $r4 // MEM_CMD
667         ctx_chan_wait_0:
668                 iord $r4 I[$r1 + 0x100]
669                 and $r4 0x1f
670                 bra ne #ctx_chan_wait_0
671         iowr I[$r3 + 0x000] $r2 // CHAN_CUR
672
673         // load channel header, fetch PGRAPH context pointer
674         mov $xtargets $r0
675         bclr $r2 31
676         shl b32 $r2 4
677         add b32 $r2 2
678
679         trace_set(T_LCHAN)
680         mov $r1 0xa04
681         shl b32 $r1 6
682         iowr I[$r1 + 0x000] $r2         // MEM_BASE
683         mov $r1 0xa20
684         shl b32 $r1 6
685         mov $r2 0x0002
686         sethi $r2 0x80000000
687         iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vram
688         mov $r1 0x10                    // chan + 0x0210
689         mov $r2 #xfer_data
690         sethi $r2 0x00020000            // 16 bytes
691         xdld $r1 $r2
692         xdwait
693         trace_clr(T_LCHAN)
694
695         // update current context
696         ld b32 $r1 D[$r0 + #xfer_data + 4]
697         shl b32 $r1 24
698         ld b32 $r2 D[$r0 + #xfer_data + 0]
699         shr b32 $r2 8
700         or $r1 $r2
701         st b32 D[$r0 + #ctx_current] $r1
702
703         // set transfer base to start of context, and fetch context header
704         trace_set(T_LCTXH)
705         mov $r2 0xa04
706         shl b32 $r2 6
707         iowr I[$r2 + 0x000] $r1         // MEM_BASE
708         mov $r2 1
709         mov $r1 0xa20
710         shl b32 $r1 6
711         iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vm
712         mov $r1 #chan_data
713         sethi $r1 0x00060000            // 256 bytes
714         xdld $r0 $r1
715         xdwait
716         trace_clr(T_LCTXH)
717
718         trace_clr(T_CHAN)
719         ret
720
721 // ctx_chan - handler for HUB_SET_CHAN command, will set a channel as
722 //            the active channel for ctxctl, but not actually transfer
723 //            any context data.  intended for use only during initial
724 //            context construction.
725 //
726 // In: $r2 channel address
727 //
728 ctx_chan:
729         call #ctx_4160s
730         call #ctx_load
731         mov $r10 12                     // DONE_UNK12
732         call #wait_donez
733         mov $r1 0xa10
734         shl b32 $r1 6
735         mov $r2 5
736         iowr I[$r1 + 0x000] $r2         // MEM_CMD = 5 (???)
737         ctx_chan_wait:
738                 iord $r2 I[$r1 + 0x000]
739                 or $r2 $r2
740                 bra ne #ctx_chan_wait
741         call #ctx_4160c
742         ret
743
744 // Execute per-context state overrides list
745 //
746 // Only executed on the first load of a channel.  Might want to look into
747 // removing this and having the host directly modify the channel's context
748 // to change this state...  The nouveau DRM already builds this list as
749 // it's definitely needed for NVIDIA's, so we may as well use it for now
750 //
751 // Input: $r1 mmio list length
752 //
753 ctx_mmio_exec:
754         // set transfer base to be the mmio list
755         ld b32 $r3 D[$r0 + #chan_mmio_address]
756         mov $r2 0xa04
757         shl b32 $r2 6
758         iowr I[$r2 + 0x000] $r3         // MEM_BASE
759
760         clear b32 $r3
761         ctx_mmio_loop:
762                 // fetch next 256 bytes of mmio list if necessary
763                 and $r4 $r3 0xff
764                 bra ne #ctx_mmio_pull
765                         mov $r5 #xfer_data
766                         sethi $r5 0x00060000    // 256 bytes
767                         xdld $r3 $r5
768                         xdwait
769
770                 // execute a single list entry
771                 ctx_mmio_pull:
772                 ld b32 $r14 D[$r4 + #xfer_data + 0x00]
773                 ld b32 $r15 D[$r4 + #xfer_data + 0x04]
774                 call #nv_wr32
775
776                 // next!
777                 add b32 $r3 8
778                 sub b32 $r1 1
779                 bra ne #ctx_mmio_loop
780
781         // set transfer base back to the current context
782         ctx_mmio_done:
783         ld b32 $r3 D[$r0 + #ctx_current]
784         iowr I[$r2 + 0x000] $r3         // MEM_BASE
785
786         // disable the mmio list now, we don't need/want to execute it again
787         st b32 D[$r0 + #chan_mmio_count] $r0
788         mov $r1 #chan_data
789         sethi $r1 0x00060000            // 256 bytes
790         xdst $r0 $r1
791         xdwait
792         ret
793
794 // Transfer HUB context data between GPU and storage area
795 //
796 // In: $r2 channel address
797 //     $p1 clear on save, set on load
798 //     $p2 set if opposite direction done/will be done, so:
799 //              on save it means: "a load will follow this save"
800 //              on load it means: "a save preceeded this load"
801 //
802 ctx_xfer:
803         // according to mwk, some kind of wait for idle
804         mov $r15 0xc00
805         shl b32 $r15 6
806         mov $r14 4
807         iowr I[$r15 + 0x200] $r14
808         ctx_xfer_idle:
809                 iord $r14 I[$r15 + 0x000]
810                 and $r14 0x2000
811                 bra ne #ctx_xfer_idle
812
813         bra not $p1 #ctx_xfer_pre
814         bra $p2 #ctx_xfer_pre_load
815         ctx_xfer_pre:
816                 mov $r15 0x10
817                 call #ctx_86c
818                 call #ctx_4160s
819                 bra not $p1 #ctx_xfer_exec
820
821         ctx_xfer_pre_load:
822                 mov $r15 2
823                 call #ctx_4170s
824                 call #ctx_4170w
825                 call #ctx_redswitch
826                 clear b32 $r15
827                 call #ctx_4170s
828                 call #ctx_load
829
830         // fetch context pointer, and initiate xfer on all GPCs
831         ctx_xfer_exec:
832         ld b32 $r1 D[$r0 + #ctx_current]
833         mov $r2 0x414
834         shl b32 $r2 6
835         iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
836         mov $r14 -0x5b00
837         sethi $r14 0x410000
838         mov b32 $r15 $r1
839         call #nv_wr32           // GPC_BCAST_WRCMD_DATA = ctx pointer
840         add b32 $r14 4
841         xbit $r15 $flags $p1
842         xbit $r2 $flags $p2
843         shl b32 $r2 1
844         or $r15 $r2
845         call #nv_wr32           // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
846
847         // strands
848         mov $r1 0x4afc
849         sethi $r1 0x20000
850         mov $r2 0xc
851         iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
852         call #strand_wait
853         mov $r2 0x47fc
854         sethi $r2 0x20000
855         iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
856         xbit $r2 $flags $p1
857         add b32 $r2 3
858         iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
859
860         // mmio context
861         xbit $r10 $flags $p1    // direction
862         or $r10 6               // first, last
863         mov $r11 0              // base = 0
864         ld b32 $r12 D[$r0 + #hub_mmio_list_head]
865         ld b32 $r13 D[$r0 + #hub_mmio_list_tail]
866         mov $r14 0              // not multi
867         call #mmctx_xfer
868
869         // wait for GPCs to all complete
870         mov $r10 8              // DONE_BAR
871         call #wait_doneo
872
873         // wait for strand xfer to complete
874         call #strand_wait
875
876         // post-op
877         bra $p1 #ctx_xfer_post
878                 mov $r10 12             // DONE_UNK12
879                 call #wait_donez
880                 mov $r1 0xa10
881                 shl b32 $r1 6
882                 mov $r2 5
883                 iowr I[$r1] $r2         // MEM_CMD
884                 ctx_xfer_post_save_wait:
885                         iord $r2 I[$r1]
886                         or $r2 $r2
887                         bra ne #ctx_xfer_post_save_wait
888
889         bra $p2 #ctx_xfer_done
890         ctx_xfer_post:
891                 mov $r15 2
892                 call #ctx_4170s
893                 clear b32 $r15
894                 call #ctx_86c
895                 call #strand_post
896                 call #ctx_4170w
897                 clear b32 $r15
898                 call #ctx_4170s
899
900                 bra not $p1 #ctx_xfer_no_post_mmio
901                 ld b32 $r1 D[$r0 + #chan_mmio_count]
902                 or $r1 $r1
903                 bra e #ctx_xfer_no_post_mmio
904                         call #ctx_mmio_exec
905
906                 ctx_xfer_no_post_mmio:
907                 call #ctx_4160c
908
909         ctx_xfer_done:
910         ret
911
912 .align 256