1/* fuc microcode util functions for gf100 PGRAPH
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#ifdef INCLUDE_CODE
27// queue_put - add request to queue
28//
29// In : $r13 queue pointer
30//	$r14 command
31//	$r15 data
32//
33queue_put:
34	// make sure we have space..
35	ld b32 $r8 D[$r13 + 0x0]	// GET
36	ld b32 $r9 D[$r13 + 0x4]	// PUT
37	xor $r8 8
38	cmpu b32 $r8 $r9
39	bra ne #queue_put_next
40		mov $r15 E_CMD_OVERFLOW
41		call(error)
42		ret
43
44	// store cmd/data on queue
45	queue_put_next:
46	and $r8 $r9 7
47	shl b32 $r8 3
48	add b32 $r8 $r13
49	add b32 $r8 8
50	st b32 D[$r8 + 0x0] $r14
51	st b32 D[$r8 + 0x4] $r15
52
53	// update PUT
54	add b32 $r9 1
55	and $r9 0xf
56	st b32 D[$r13 + 0x4] $r9
57	ret
58
59// queue_get - fetch request from queue
60//
61// In : $r13 queue pointer
62//
63// Out:	$p1  clear on success (data available)
64//	$r14 command
65// 	$r15 data
66//
67queue_get:
68	bset $flags $p1
69	ld b32 $r8 D[$r13 + 0x0]	// GET
70	ld b32 $r9 D[$r13 + 0x4]	// PUT
71	cmpu b32 $r8 $r9
72	bra e #queue_get_done
73		// fetch first cmd/data pair
74		and $r9 $r8 7
75		shl b32 $r9 3
76		add b32 $r9 $r13
77		add b32 $r9 8
78		ld b32 $r14 D[$r9 + 0x0]
79		ld b32 $r15 D[$r9 + 0x4]
80
81		// update GET
82		add b32 $r8 1
83		and $r8 0xf
84		st b32 D[$r13 + 0x0] $r8
85		bclr $flags $p1
86queue_get_done:
87	ret
88
89// nv_rd32 - read 32-bit value from nv register
90//
91// In : $r14 register
92// Out: $r15 value
93//
94nv_rd32:
95	mov b32 $r12 $r14
96	bset $r12 31			// MMIO_CTRL_PENDING
97	nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
98	nv_rd32_wait:
99		nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
100		xbit $r12 $r12 31
101		bra ne #nv_rd32_wait
102	mov $r10 6			// DONE_MMIO_RD
103	call(wait_doneo)
104	nv_iord($r15, NV_PGRAPH_FECS_MMIO_RDVAL, 0)
105	ret
106
107// nv_wr32 - write 32-bit value to nv register
108//
109// In : $r14 register
110//      $r15 value
111//
112nv_wr32:
113	nv_iowr(NV_PGRAPH_FECS_MMIO_WRVAL, 0, $r15)
114	mov b32 $r12 $r14
115	bset $r12 31			// MMIO_CTRL_PENDING
116	bset $r12 30			// MMIO_CTRL_WRITE
117	nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
118	nv_wr32_wait:
119		nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
120		xbit $r12 $r12 31
121		bra ne #nv_wr32_wait
122	ret
123
124// wait_donez - wait on FUC_DONE bit to become clear
125//
126// In : $r10 bit to wait on
127//
128wait_donez:
129	trace_set(T_WAIT);
130	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(6), 0, $r10)
131	wait_donez_ne:
132		nv_iord($r8, NV_PGRAPH_FECS_SIGNAL, 0)
133		xbit $r8 $r8 $r10
134		bra ne #wait_donez_ne
135	trace_clr(T_WAIT)
136	ret
137
138// wait_doneo - wait on FUC_DONE bit to become set
139//
140// In : $r10 bit to wait on
141//
142wait_doneo:
143	trace_set(T_WAIT);
144	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(6), 0, $r10)
145	wait_doneo_e:
146		nv_iord($r8, NV_PGRAPH_FECS_SIGNAL, 0)
147		xbit $r8 $r8 $r10
148		bra e #wait_doneo_e
149	trace_clr(T_WAIT)
150	ret
151
152// mmctx_size - determine size of a mmio list transfer
153//
154// In : $r14 mmio list head
155//      $r15 mmio list tail
156// Out: $r15 transfer size (in bytes)
157//
158mmctx_size:
159	clear b32 $r9
160	nv_mmctx_size_loop:
161		ld b32 $r8 D[$r14]
162		shr b32 $r8 26
163		add b32 $r8 1
164		shl b32 $r8 2
165		add b32 $r9 $r8
166		add b32 $r14 4
167		cmpu b32 $r14 $r15
168		bra ne #nv_mmctx_size_loop
169	mov b32 $r15 $r9
170	ret
171
172// mmctx_xfer - execute a list of mmio transfers
173//
174// In : $r10 flags
175//		bit 0: direction (0 = save, 1 = load)
176//		bit 1: set if first transfer
177//		bit 2: set if last transfer
178//	$r11 base
179//	$r12 mmio list head
180//	$r13 mmio list tail
181//	$r14 multi_stride
182//	$r15 multi_mask
183//
184mmctx_xfer:
185	trace_set(T_MMCTX)
186	clear b32 $r9
187	or $r11 $r11
188	bra e #mmctx_base_disabled
189		nv_iowr(NV_PGRAPH_FECS_MMCTX_BASE, 0, $r11)
190		bset $r9 0			// BASE_EN
191	mmctx_base_disabled:
192	or $r14 $r14
193	bra e #mmctx_multi_disabled
194		nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE, 0, $r14)
195		nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_MASK, 0, $r15)
196		bset $r9 1			// MULTI_EN
197	mmctx_multi_disabled:
198
199	xbit $r11 $r10 0
200	shl b32 $r11 16			// DIR
201	bset $r11 12			// QLIMIT = 0x10
202	xbit $r14 $r10 1
203	shl b32 $r14 17
204	or $r11 $r14			// START_TRIGGER
205	nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
206
207	// loop over the mmio list, and send requests to the hw
208	mmctx_exec_loop:
209		// wait for space in mmctx queue
210		mmctx_wait_free:
211			nv_iord($r14, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
212			and $r14 0x1f
213			bra e #mmctx_wait_free
214
215		// queue up an entry
216		ld b32 $r14 D[$r12]
217		or $r14 $r9
218		nv_iowr(NV_PGRAPH_FECS_MMCTX_QUEUE, 0, $r14)
219		add b32 $r12 4
220		cmpu b32 $r12 $r13
221		bra ne #mmctx_exec_loop
222
223	xbit $r11 $r10 2
224	bra ne #mmctx_stop
225		// wait for queue to empty
226		mmctx_fini_wait:
227			nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
228			and $r11 0x1f
229			cmpu b32 $r11 0x10
230			bra ne #mmctx_fini_wait
231		mov $r10 5			// DONE_MMCTX
232		call(wait_donez)
233		bra #mmctx_done
234	mmctx_stop:
235		xbit $r11 $r10 0
236		shl b32 $r11 16			// DIR
237		bset $r11 12			// QLIMIT = 0x10
238		bset $r11 18			// STOP_TRIGGER
239		nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
240		mmctx_stop_wait:
241			// wait for STOP_TRIGGER to clear
242			nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
243			xbit $r11 $r11 18
244			bra ne #mmctx_stop_wait
245	mmctx_done:
246	trace_clr(T_MMCTX)
247	ret
248
249// Wait for DONE_STRAND
250//
251strand_wait:
252	push $r10
253	mov $r10 2
254	call(wait_donez)
255	pop $r10
256	ret
257
258// unknown - call before issuing strand commands
259//
260strand_pre:
261	mov $r9 NV_PGRAPH_FECS_STRAND_CMD_ENABLE
262	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
263	call(strand_wait)
264	ret
265
266// unknown - call after issuing strand commands
267//
268strand_post:
269	mov $r9 NV_PGRAPH_FECS_STRAND_CMD_DISABLE
270	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
271	call(strand_wait)
272	ret
273
274// Selects strand set?!
275//
276// In: $r14 id
277//
278strand_set:
279	mov $r12 0xf
280	nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r12)
281	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER
282	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
283	nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r14)
284	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER
285	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
286	call(strand_wait)
287	ret
288
289// Initialise strand context data
290//
291// In : $r15 context base
292// Out: $r15 context size (in bytes)
293//
294// Strandset(?) 3 hardcoded currently
295//
296strand_ctx_init:
297	trace_set(T_STRINIT)
298	call(strand_pre)
299	mov $r14 3
300	call(strand_set)
301
302	clear b32 $r12
303	nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r12)
304	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_SEEK
305	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
306	call(strand_wait)
307	sub b32 $r12 $r0 1
308	nv_iowr(NV_PGRAPH_FECS_STRAND_DATA, 0x3f, $r12)
309	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_GET_INFO
310	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
311	call(strand_wait)
312	call(strand_post)
313
314	// read the size of each strand, poke the context offset of
315	// each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
316	// about it later then.
317	nv_mkio($r8, NV_PGRAPH_FECS_STRAND_SAVE_SWBASE, 0x00)
318	nv_iord($r9, NV_PGRAPH_FECS_STRANDS_CNT, 0x00)
319	shr b32 $r14 $r15 8
320	ctx_init_strand_loop:
321		iowr I[$r8 + 0x000] $r14	// STRAND_SAVE_SWBASE
322		iowr I[$r8 + 0x100] $r14	// STRAND_LOAD_SWBASE
323		iord $r10 I[$r8 + 0x200]	// STRAND_SIZE
324		shr b32 $r10 6
325		add b32 $r10 1
326		add b32 $r14 $r10
327		add b32 $r8 4
328		sub b32 $r9 1
329		bra ne #ctx_init_strand_loop
330
331	shl b32 $r14 8
332	sub b32 $r15 $r14 $r15
333	trace_clr(T_STRINIT)
334	ret
335#endif
336