brintos

brintos / linux-shallow public Read only

0
0
Text · 13.1 KiB · 4984b00 Raw
493 lines · plain
1/* fuc microcode for gf100 PGRAPH/GPC2 *3 * Copyright 2011 Red Hat Inc.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * 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 OR21 * OTHER DEALINGS IN THE SOFTWARE.22 *23 * Authors: Ben Skeggs24 */25 26/* TODO27 * - bracket certain functions with scratch writes, useful for debugging28 * - watchdog timer around ctx operations29 */30 31#ifdef INCLUDE_DATA32gpc_mmio_list_head:	.b32 #mmio_list_base33gpc_mmio_list_tail:34tpc_mmio_list_head:	.b32 #mmio_list_base35tpc_mmio_list_tail:36unk_mmio_list_head:	.b32 #mmio_list_base37unk_mmio_list_tail:	.b32 #mmio_list_base38 39gpc_id:			.b32 040 41tpc_count:		.b32 042tpc_mask:		.b32 043 44#if NV_PGRAPH_GPCX_UNK__SIZE > 045unk_count:		.b32 046unk_mask:		.b32 047#endif48 49cmd_queue:		queue_init50 51mmio_list_base:52#endif53 54#ifdef INCLUDE_CODE55#define gpc_addr(reg,addr)                                                    /*56*/	imm32(reg,addr)                                                       /*57*/	or reg NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE58#define gpc_wr32(addr,reg)                                                    /*59*/	gpc_addr($r14,addr)                                                   /*60*/	mov b32 $r15 reg                                                      /*61*/	call(nv_wr32)62 63// reports an exception to the host64//65// In: $r15 error code (see os.h)66//67error:68	push $r1469	nv_wr32(NV_PGRAPH_FECS_CC_SCRATCH_VAL(5), $r15)70	mov $r15 171	nv_wr32(NV_PGRAPH_FECS_INTR_UP_SET, $r15)72	pop $r1473	ret74 75#if CHIPSET >= GM10776tpc_strand_wait:77	push $r978	trace_set(T_STRTPC)79	tpc_strand_busy:80		nv_iord($r9, NV_PGRAPH_GPCX_GPCCS_TPC_STATUS, 0)81		bra b32 $r9 0x0 ne #tpc_strand_busy82	trace_clr(T_STRTPC)83	pop $r984	ret85 86#define tpc_strand_wait() call(tpc_strand_wait)87#define tpc_strand_enable()                                                   /*88*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_ENABLE                        /*89*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*90*/	tpc_strand_wait()91#define tpc_strand_disable()                                                  /*92*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_DISABLE                       /*93*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*94*/	tpc_strand_wait()95#define tpc_strand_seek(p)                                                    /*96*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL                         /*97*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15)                      /*98*/	mov $r15 p                                                            /*99*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_SELECT, $r15)                     /*100*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SEEK                          /*101*/	tpc_strand_wait()102#define tpc_strand_info(m)                                                    /*103*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*104*/	mov $r15 m                                                            /*105*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_DATA, $r15)                       /*106*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_GET_INFO                      /*107*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*108*/	tpc_strand_wait()109#endif110 111 112// GPC fuc initialisation, executed by triggering ucode start, will113// fall through to main loop after completion.114//115// Input:116//   CC_SCRATCH[1]: context base117//118// Output:119//   CC_SCRATCH[0]:120//	     31:31: set to signal completion121//   CC_SCRATCH[1]:122//	      31:0: GPC context size123//124init:125	clear b32 $r0126 127	// setup stack128	nv_iord($r1, NV_PGRAPH_GPCX_GPCCS_CAPS, 0)129	extr $r1 $r1 9:17130	shl b32 $r1 8131	mov $sp $r1132 133	// enable fifo access134	mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO135	nv_iowr(NV_PGRAPH_GPCX_GPCCS_ACCESS, 0, $r2)136 137	// setup i0 handler, and route all interrupts to it138	mov $r1 #ih139	mov $iv0 $r1140	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE, 0, $r0)141 142	// enable fifo interrupt143	mov $r2 NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO144	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET, 0, $r2)145 146	// enable interrupts147	bset $flags ie0148 149	// how many TPCs do we have?150	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0)151	mov $r3 1152	and $r2 0x1f153	shl b32 $r3 $r2154	sub b32 $r3 1155	st b32 D[$r0 + #tpc_count] $r2156	st b32 D[$r0 + #tpc_mask] $r3157 158	// determine which GPC we are, setup (optional) mmio access offset159	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0)160	st b32 D[$r0 + #gpc_id] $r2161	shl b32 $r2 15162	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMIO_BASE, 0, $r2)163 164#if NV_PGRAPH_GPCX_UNK__SIZE > 0165	// figure out which, and how many, UNKs are actually present166	gpc_addr($r14, 0x500c30)167	clear b32 $r2168	clear b32 $r3169	clear b32 $r4170	init_unk_loop:171		call(nv_rd32)172		cmp b32 $r15 0173		bra z #init_unk_next174			mov $r15 1175			shl b32 $r15 $r2176			or $r4 $r15177			add b32 $r3 1178		init_unk_next:179		add b32 $r2 1180		add b32 $r14 4181		cmp b32 $r2 NV_PGRAPH_GPCX_UNK__SIZE182		bra ne #init_unk_loop183	init_unk_done:184	st b32 D[$r0 + #unk_count] $r3185	st b32 D[$r0 + #unk_mask] $r4186#endif187 188	// initialise context base, and size tracking189	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(1), 0)190	clear b32 $r3		// track GPC context size here191 192	// set mmctx base addresses now so we don't have to do it later,193	// they don't currently ever change194	shr b32 $r5 $r2 8195	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE, 0, $r5)196	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE, 0, $r5)197 198	// calculate GPC mmio context size199	ld b32 $r14 D[$r0 + #gpc_mmio_list_head]200	ld b32 $r15 D[$r0 + #gpc_mmio_list_tail]201	call(mmctx_size)202	add b32 $r2 $r15203	add b32 $r3 $r15204 205	// calculate per-TPC mmio context size206	ld b32 $r14 D[$r0 + #tpc_mmio_list_head]207	ld b32 $r15 D[$r0 + #tpc_mmio_list_tail]208	call(mmctx_size)209	ld b32 $r14 D[$r0 + #tpc_count]210	mulu $r14 $r15211	add b32 $r2 $r14212	add b32 $r3 $r14213 214#if NV_PGRAPH_GPCX_UNK__SIZE > 0215	// calculate per-UNK mmio context size216	ld b32 $r14 D[$r0 + #unk_mmio_list_head]217	ld b32 $r15 D[$r0 + #unk_mmio_list_tail]218	call(mmctx_size)219	ld b32 $r14 D[$r0 + #unk_count]220	mulu $r14 $r15221	add b32 $r2 $r14222	add b32 $r3 $r14223#endif224 225	// round up base/size to 256 byte boundary (for strand SWBASE)226	shr b32 $r3 2227	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT, 0, $r3) // wtf for?!228	shr b32 $r2 8229	shr b32 $r3 6230	add b32 $r2 1231	add b32 $r3 1232	shl b32 $r2 8233	shl b32 $r3 8234 235	// calculate size of strand context data236	mov b32 $r15 $r2237	call(strand_ctx_init)238	add b32 $r2 $r15239	add b32 $r3 $r15240 241#if CHIPSET >= GM107242	// calculate size of tpc strand context data243	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL244	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15)245	tpc_strand_enable();246	tpc_strand_seek(0);247	tpc_strand_info(-1);248 249	ld b32 $r4 D[$r0 + #tpc_count]250	gpc_addr($r5, NV_PGRAPH_GPC0_TPC0)251	tpc_strand_init_tpc_loop:252		add b32 $r14 $r5 NV_TPC_STRAND_CNT253		call(nv_rd32)254		mov b32 $r6 $r15255		clear b32 $r7256		tpc_strand_init_idx_loop:257			add b32 $r14 $r5 NV_TPC_STRAND_INDEX258			mov b32 $r15 $r7259			call(nv_wr32)260			add b32 $r14 $r5 NV_TPC_STRAND_SAVE_SWBASE261			shr b32 $r15 $r2 8262			call(nv_wr32)263			add b32 $r14 $r5 NV_TPC_STRAND_LOAD_SWBASE264			shr b32 $r15 $r2 8265			call(nv_wr32)266			add b32 $r14 $r5 NV_TPC_STRAND_WORDS267			call(nv_rd32)268			shr b32 $r15 6269			add b32 $r15 1270			shl b32 $r15 8271			add b32 $r2 $r15272			add b32 $r3 $r15273			add b32 $r7 1274			sub b32 $r6 1275			bra nz #tpc_strand_init_idx_loop276		add b32 $r5 NV_PGRAPH_GPC0_TPC0__SIZE277		sub b32 $r4 1278		bra nz #tpc_strand_init_tpc_loop279 280	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL281	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15)282	tpc_strand_disable();283#endif284 285	// save context size, and tell HUB we're done286	nv_iowr(NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(1), 0, $r3)287	clear b32 $r2288	bset $r2 31289	nv_iowr(NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(0), 0, $r2)290 291// Main program loop, very simple, sleeps until woken up by the interrupt292// handler, pulls a command from the queue and executes its handler293//294wait:295	sleep $p0296	bset $flags $p0297main:298	mov $r13 #cmd_queue299	call(queue_get)300	bra $p1 #wait301 302	// 0x0000-0x0003 are all context transfers303	cmpu b32 $r14 0x04304	bra nc #main_not_ctx_xfer305		// fetch $flags and mask off $p1/$p2306		mov $r1 $flags307		mov $r2 0x0006308		not b32 $r2309		and $r1 $r2310		// set $p1/$p2 according to transfer type311		shl b32 $r14 1312		or $r1 $r14313		mov $flags $r1314		// transfer context data315		call(ctx_xfer)316		bra #main317 318	main_not_ctx_xfer:319	shl b32 $r15 $r14 16320	or $r15 E_BAD_COMMAND321	call(error)322	bra #main323 324// interrupt handler325ih:326	push $r0327	push $r8328	mov $r8 $flags329	push $r8330	push $r9331	push $r10332	push $r11333	push $r13334	push $r14335	push $r15336	clear b32 $r0337 338	// incoming fifo command?339	nv_iord($r10, NV_PGRAPH_GPCX_GPCCS_INTR, 0)340	and $r11 $r10 NV_PGRAPH_GPCX_GPCCS_INTR_FIFO341	bra e #ih_no_fifo342		// queue incoming fifo command for later processing343		mov $r13 #cmd_queue344		nv_iord($r14, NV_PGRAPH_GPCX_GPCCS_FIFO_CMD, 0)345		nv_iord($r15, NV_PGRAPH_GPCX_GPCCS_FIFO_DATA, 0)346		call(queue_put)347		mov $r14 1348		nv_iowr(NV_PGRAPH_GPCX_GPCCS_FIFO_ACK, 0, $r14)349 350	// ack, and wake up main()351	ih_no_fifo:352	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ACK, 0, $r10)353 354	pop $r15355	pop $r14356	pop $r13357	pop $r11358	pop $r10359	pop $r9360	pop $r8361	mov $flags $r8362	pop $r8363	pop $r0364	bclr $flags $p0365	iret366 367// Set this GPC's bit in HUB_BAR, used to signal completion of various368// activities to the HUB fuc369//370hub_barrier_done:371	mov $r15 1372	ld b32 $r14 D[$r0 + #gpc_id]373	shl b32 $r15 $r14374	nv_wr32(0x409418, $r15)	// 0x409418 - HUB_BAR_SET375	ret376 377// Disables various things, waits a bit, and re-enables them..378//379// Not sure how exactly this helps, perhaps "ENABLE" is not such a380// good description for the bits we turn off?  Anyways, without this,381// funny things happen.382//383ctx_redswitch:384	mov $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER385	nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)386	mov $r14 8387	ctx_redswitch_delay:388		sub b32 $r14 1389		bra ne #ctx_redswitch_delay390	or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11391	or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE392	nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)393	ret394 395// Transfer GPC context data between GPU and storage area396//397// In: $r15 context base address398//     $p1 clear on save, set on load399//     $p2 set if opposite direction done/will be done, so:400//		on save it means: "a load will follow this save"401//		on load it means: "a save preceeded this load"402//403ctx_xfer:404	// set context base address405	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15)406#if CHIPSET >= GM107407	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_MEM_BASE, $r15)408#endif409	bra not $p1 #ctx_xfer_not_load410		call(ctx_redswitch)411	ctx_xfer_not_load:412 413	// strands414	call(strand_pre)415	clear b32 $r2416	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT, 0x3f, $r2)417	xbit $r2 $flags $p1	// SAVE/LOAD418	add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE419	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2)420 421#if CHIPSET >= GM107422	tpc_strand_enable();423	tpc_strand_seek(0);424	xbit $r15 $flags $p1	// SAVE/LOAD425	add b32 $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SAVE426	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)427#endif428 429	// mmio context430	xbit $r10 $flags $p1	// direction431	or $r10 2		// first432	imm32($r11,0x500000)433	ld b32 $r12 D[$r0 + #gpc_id]434	shl b32 $r12 15435	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn436	ld b32 $r12 D[$r0 + #gpc_mmio_list_head]437	ld b32 $r13 D[$r0 + #gpc_mmio_list_tail]438	mov $r14 0		// not multi439	call(mmctx_xfer)440 441	// per-TPC mmio context442	xbit $r10 $flags $p1	// direction443#if !NV_PGRAPH_GPCX_UNK__SIZE444	or $r10 4		// last445#endif446	imm32($r11, 0x504000)447	ld b32 $r12 D[$r0 + #gpc_id]448	shl b32 $r12 15449	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_TPC0450	ld b32 $r12 D[$r0 + #tpc_mmio_list_head]451	ld b32 $r13 D[$r0 + #tpc_mmio_list_tail]452	ld b32 $r15 D[$r0 + #tpc_mask]453	mov $r14 0x800		// stride = 0x800454	call(mmctx_xfer)455 456#if NV_PGRAPH_GPCX_UNK__SIZE > 0457	// per-UNK mmio context458	xbit $r10 $flags $p1	// direction459	or $r10 4		// last460	imm32($r11, 0x503000)461	ld b32 $r12 D[$r0 + #gpc_id]462	shl b32 $r12 15463	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_UNK0464	ld b32 $r12 D[$r0 + #unk_mmio_list_head]465	ld b32 $r13 D[$r0 + #unk_mmio_list_tail]466	ld b32 $r15 D[$r0 + #unk_mask]467	mov $r14 0x200		// stride = 0x200468	call(mmctx_xfer)469#endif470 471	// wait for strands to finish472	call(strand_wait)473#if CHIPSET >= GM107474	tpc_strand_wait()475#endif476 477	// if load, or a save without a load following, do some478	// unknown stuff that's done after finishing a block of479	// strand commands480	bra $p1 #ctx_xfer_post481	bra not $p2 #ctx_xfer_done482	ctx_xfer_post:483		call(strand_post)484#if CHIPSET >= GM107485		tpc_strand_disable()486#endif487 488	// mark completion in HUB's barrier489	ctx_xfer_done:490	call(hub_barrier_done)491	ret492#endif493