Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / subdev / pmu / fuc / memx.fuc
1 /*
2  * Copyright 2013 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24
25 #ifdef INCLUDE_PROC
26 process(PROC_MEMX, #memx_init, #memx_recv)
27 #endif
28
29 /******************************************************************************
30  * MEMX data segment
31  *****************************************************************************/
32 #ifdef INCLUDE_DATA
33 .equ #memx_opcode 0
34 .equ #memx_header 2
35 .equ #memx_length 4
36 .equ #memx_func   8
37
38 #define handler(cmd,hdr,len,func) /*
39 */      .b16 MEMX_##cmd /*
40 */      .b16 hdr /*
41 */      .b16 len /*
42 */      .b16 0 /*
43 */      .b32 func
44
45 memx_func_head:
46 handler(ENTER , 0x0000, 0x0000, #memx_func_enter)
47 memx_func_next:
48 handler(LEAVE , 0x0000, 0x0000, #memx_func_leave)
49 handler(WR32  , 0x0000, 0x0002, #memx_func_wr32)
50 handler(WAIT  , 0x0004, 0x0000, #memx_func_wait)
51 handler(DELAY , 0x0001, 0x0000, #memx_func_delay)
52 handler(VBLANK, 0x0001, 0x0000, #memx_func_wait_vblank)
53 handler(TRAIN , 0x0000, 0x0000, #memx_func_train)
54 memx_func_tail:
55
56 .equ #memx_func_size #memx_func_next - #memx_func_head
57 .equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size
58
59 memx_ts_start:
60 .b32 0
61 memx_ts_end:
62 .b32 0
63
64 memx_data_head:
65 .skip 0x0800
66 memx_data_tail:
67
68 memx_train_head:
69 .skip 0x0100
70 memx_train_tail:
71 #endif
72
73 /******************************************************************************
74  * MEMX code segment
75  *****************************************************************************/
76 #ifdef INCLUDE_CODE
77 // description
78 //
79 // $r15 - current (memx)
80 // $r4  - packet length
81 // $r3  - opcode desciption
82 // $r0  - zero
83 memx_func_enter:
84 #if NVKM_PPWR_CHIPSET == GT215
85         movw $r8 0x1610
86         nv_rd32($r7, $r8)
87         imm32($r6, 0xfffffffc)
88         and $r7 $r6
89         movw $r6 0x2
90         or $r7 $r6
91         nv_wr32($r8, $r7)
92 #else
93         movw $r6 0x001620
94         imm32($r7, ~0x00000aa2);
95         nv_rd32($r8, $r6)
96         and $r8 $r7
97         nv_wr32($r6, $r8)
98
99         imm32($r7, ~0x00000001)
100         nv_rd32($r8, $r6)
101         and $r8 $r7
102         nv_wr32($r6, $r8)
103
104         movw $r6 0x0026f0
105         nv_rd32($r8, $r6)
106         and $r8 $r7
107         nv_wr32($r6, $r8)
108 #endif
109
110         mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE
111         nv_iowr(NV_PPWR_OUTPUT_SET, $r6)
112         memx_func_enter_wait:
113                 nv_iord($r6, NV_PPWR_OUTPUT)
114                 and $r6 NV_PPWR_OUTPUT_FB_PAUSE
115                 bra z #memx_func_enter_wait
116
117         nv_iord($r6, NV_PPWR_TIMER_LOW)
118         st b32 D[$r0 + #memx_ts_start] $r6
119         ret
120
121 // description
122 //
123 // $r15 - current (memx)
124 // $r4  - packet length
125 // $r3  - opcode desciption
126 // $r0  - zero
127 memx_func_leave:
128         nv_iord($r6, NV_PPWR_TIMER_LOW)
129         st b32 D[$r0 + #memx_ts_end] $r6
130
131         mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE
132         nv_iowr(NV_PPWR_OUTPUT_CLR, $r6)
133         memx_func_leave_wait:
134                 nv_iord($r6, NV_PPWR_OUTPUT)
135                 and $r6 NV_PPWR_OUTPUT_FB_PAUSE
136                 bra nz #memx_func_leave_wait
137
138 #if NVKM_PPWR_CHIPSET == GT215
139         movw $r8 0x1610
140         nv_rd32($r7, $r8)
141         imm32($r6, 0xffffffcc)
142         and $r7 $r6
143         nv_wr32($r8, $r7)
144 #else
145         movw $r6 0x0026f0
146         imm32($r7, 0x00000001)
147         nv_rd32($r8, $r6)
148         or $r8 $r7
149         nv_wr32($r6, $r8)
150
151         movw $r6 0x001620
152         nv_rd32($r8, $r6)
153         or $r8 $r7
154         nv_wr32($r6, $r8)
155
156         imm32($r7, 0x00000aa2);
157         nv_rd32($r8, $r6)
158         or $r8 $r7
159         nv_wr32($r6, $r8)
160 #endif
161         ret
162
163 #if NVKM_PPWR_CHIPSET < GF119
164 // description
165 //
166 // $r15 - current (memx)
167 // $r4  - packet length
168 //      +00: head to wait for vblank on
169 // $r3  - opcode desciption
170 // $r0  - zero
171 memx_func_wait_vblank:
172         ld b32 $r6 D[$r1 + 0x00]
173         cmp b32 $r6 0x0
174         bra z #memx_func_wait_vblank_head0
175         cmp b32 $r6 0x1
176         bra z #memx_func_wait_vblank_head1
177         bra #memx_func_wait_vblank_fini
178
179         memx_func_wait_vblank_head1:
180         movw $r7 0x20
181         bra #memx_func_wait_vblank_0
182
183         memx_func_wait_vblank_head0:
184         movw $r7 0x8
185
186         memx_func_wait_vblank_0:
187                 nv_iord($r6, NV_PPWR_INPUT)
188                 and $r6 $r7
189                 bra nz #memx_func_wait_vblank_0
190
191         memx_func_wait_vblank_1:
192                 nv_iord($r6, NV_PPWR_INPUT)
193                 and $r6 $r7
194                 bra z #memx_func_wait_vblank_1
195
196         memx_func_wait_vblank_fini:
197         add b32 $r1 0x4
198         ret
199
200 #else
201
202 // XXX: currently no-op
203 //
204 // $r15 - current (memx)
205 // $r4  - packet length
206 //      +00: head to wait for vblank on
207 // $r3  - opcode desciption
208 // $r0  - zero
209 memx_func_wait_vblank:
210         add b32 $r1 0x4
211         ret
212
213 #endif
214
215 // description
216 //
217 // $r15 - current (memx)
218 // $r4  - packet length
219 //      +00*n: addr
220 //      +04*n: data
221 // $r3  - opcode desciption
222 // $r0  - zero
223 memx_func_wr32:
224         ld b32 $r6 D[$r1 + 0x00]
225         ld b32 $r5 D[$r1 + 0x04]
226         add b32 $r1 0x08
227         nv_wr32($r6, $r5)
228         sub b32 $r4 0x02
229         bra nz #memx_func_wr32
230         ret
231
232 // description
233 //
234 // $r15 - current (memx)
235 // $r4  - packet length
236 //      +00: addr
237 //      +04: mask
238 //      +08: data
239 //      +0c: timeout (ns)
240 // $r3  - opcode desciption
241 // $r0  - zero
242 memx_func_wait:
243         nv_iord($r8, NV_PPWR_TIMER_LOW)
244         ld b32 $r14 D[$r1 + 0x00]
245         ld b32 $r13 D[$r1 + 0x04]
246         ld b32 $r12 D[$r1 + 0x08]
247         ld b32 $r11 D[$r1 + 0x0c]
248         add b32 $r1 0x10
249         call(wait)
250         ret
251
252 // description
253 //
254 // $r15 - current (memx)
255 // $r4  - packet length
256 //      +00: time (ns)
257 // $r3  - opcode desciption
258 // $r0  - zero
259 memx_func_delay:
260         ld b32 $r14 D[$r1 + 0x00]
261         add b32 $r1 0x04
262         call(nsec)
263         ret
264
265 // description
266 //
267 // $r15 - current (memx)
268 // $r4  - packet length
269 // $r3  - opcode desciption
270 // $r0  - zero
271 memx_func_train:
272 #if NVKM_PPWR_CHIPSET == GT215
273 // $r5 - outer loop counter
274 // $r6 - inner loop counter
275 // $r7 - entry counter (#memx_train_head + $r7)
276         movw $r5 0x3
277         movw $r7 0x0
278
279 // Read random memory to wake up... things
280         imm32($r9, 0x700000)
281         nv_rd32($r8,$r9)
282         movw $r14 0x2710
283         call(nsec)
284
285         memx_func_train_loop_outer:
286                 mulu $r8 $r5 0x101
287                 sethi $r8 0x02000000
288                 imm32($r9, 0x1111e0)
289                 nv_wr32($r9, $r8)
290                 push $r5
291
292                 movw $r6 0x0
293                 memx_func_train_loop_inner:
294                         movw $r8 0x1111
295                         mulu $r9 $r6 $r8
296                         shl b32 $r8 $r9 0x10
297                         or $r8 $r9
298                         imm32($r9, 0x100720)
299                         nv_wr32($r9, $r8)
300
301                         imm32($r9, 0x100080)
302                         nv_rd32($r8, $r9)
303                         or $r8 $r8 0x20
304                         nv_wr32($r9, $r8)
305
306                         imm32($r9, 0x10053c)
307                         imm32($r8, 0x80003002)
308                         nv_wr32($r9, $r8)
309
310                         imm32($r14, 0x100560)
311                         imm32($r13, 0x80000000)
312                         add b32 $r12 $r13 0
313                         imm32($r11, 0x001e8480)
314                         call(wait)
315
316                         // $r5 - inner inner loop counter
317                         // $r9 - result
318                         movw $r5 0
319                         imm32($r9, 0x8300ffff)
320                         memx_func_train_loop_4x:
321                                 imm32($r10, 0x100080)
322                                 nv_rd32($r8, $r10)
323                                 imm32($r11, 0xffffffdf)
324                                 and $r8 $r11
325                                 nv_wr32($r10, $r8)
326
327                                 imm32($r10, 0x10053c)
328                                 imm32($r8, 0x80003002)
329                                 nv_wr32($r10, $r8)
330
331                                 imm32($r14, 0x100560)
332                                 imm32($r13, 0x80000000)
333                                 mov b32 $r12 $r13
334                                 imm32($r11, 0x00002710)
335                                 call(wait)
336
337                                 nv_rd32($r13, $r14)
338                                 and $r9 $r9 $r13
339
340                                 add b32 $r5 1
341                                 cmp b16 $r5 0x4
342                                 bra l #memx_func_train_loop_4x
343
344                         add b32 $r10 $r7 #memx_train_head
345                         st b32 D[$r10 + 0] $r9
346                         add b32 $r6 1
347                         add b32 $r7 4
348
349                         cmp b16 $r6 0x10
350                         bra l #memx_func_train_loop_inner
351
352                 pop $r5
353                 add b32 $r5 1
354                 cmp b16 $r5 7
355                 bra l #memx_func_train_loop_outer
356
357 #endif
358         ret
359
360 // description
361 //
362 // $r15 - current (memx)
363 // $r14 - sender process name
364 // $r13 - message (exec)
365 // $r12 - head of script
366 // $r11 - tail of script
367 // $r0  - zero
368 memx_exec:
369         push $r14
370         push $r13
371         mov b32 $r1 $r12
372         mov b32 $r2 $r11
373
374         memx_exec_next:
375                 // fetch the packet header
376                 ld b32 $r3 D[$r1]
377                 add b32 $r1 4
378                 extr $r4 $r3 16:31
379                 extr $r3 $r3 0:15
380
381                 // execute the opcode handler
382                 sub b32 $r3 1
383                 mulu $r3 #memx_func_size
384                 ld b32 $r5 D[$r3 + #memx_func_head + #memx_func]
385                 call $r5
386
387                 // keep going, if we haven't reached the end
388                 cmp b32 $r1 $r2
389                 bra l #memx_exec_next
390
391         // send completion reply
392         ld b32 $r11 D[$r0 + #memx_ts_start]
393         ld b32 $r12 D[$r0 + #memx_ts_end]
394         sub b32 $r12 $r11
395         nv_iord($r11, NV_PPWR_INPUT)
396         pop $r13
397         pop $r14
398         call(send)
399         ret
400
401 // description
402 //
403 // $r15 - current (memx)
404 // $r14 - sender process name
405 // $r13 - message
406 // $r12 - data0
407 // $r11 - data1
408 // $r0  - zero
409 memx_info:
410         cmp b16 $r12 0x1
411         bra e #memx_info_train
412
413         memx_info_data:
414         mov $r12 #memx_data_head
415         mov $r11 #memx_data_tail - #memx_data_head
416         bra #memx_info_send
417
418         memx_info_train:
419         mov $r12 #memx_train_head
420         mov $r11 #memx_train_tail - #memx_train_head
421
422         memx_info_send:
423         call(send)
424         ret
425
426 // description
427 //
428 // $r15 - current (memx)
429 // $r14 - sender process name
430 // $r13 - message
431 // $r12 - data0
432 // $r11 - data1
433 // $r0  - zero
434 memx_recv:
435         cmp b32 $r13 MEMX_MSG_EXEC
436         bra e #memx_exec
437         cmp b32 $r13 MEMX_MSG_INFO
438         bra e #memx_info
439         ret
440
441 // description
442 //
443 // $r15 - current (memx)
444 // $r0  - zero
445 memx_init:
446         ret
447 #endif