448 lines
9.0 KiB
Plaintext
448 lines
9.0 KiB
Plaintext
|
/*
|
||
|
* Copyright 2013 Red Hat Inc.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*
|
||
|
* Authors: Ben Skeggs
|
||
|
*/
|
||
|
|
||
|
#ifdef INCLUDE_PROC
|
||
|
process(PROC_MEMX, #memx_init, #memx_recv)
|
||
|
#endif
|
||
|
|
||
|
/******************************************************************************
|
||
|
* MEMX data segment
|
||
|
*****************************************************************************/
|
||
|
#ifdef INCLUDE_DATA
|
||
|
.equ #memx_opcode 0
|
||
|
.equ #memx_header 2
|
||
|
.equ #memx_length 4
|
||
|
.equ #memx_func 8
|
||
|
|
||
|
#define handler(cmd,hdr,len,func) /*
|
||
|
*/ .b16 MEMX_##cmd /*
|
||
|
*/ .b16 hdr /*
|
||
|
*/ .b16 len /*
|
||
|
*/ .b16 0 /*
|
||
|
*/ .b32 func
|
||
|
|
||
|
memx_func_head:
|
||
|
handler(ENTER , 0x0000, 0x0000, #memx_func_enter)
|
||
|
memx_func_next:
|
||
|
handler(LEAVE , 0x0000, 0x0000, #memx_func_leave)
|
||
|
handler(WR32 , 0x0000, 0x0002, #memx_func_wr32)
|
||
|
handler(WAIT , 0x0004, 0x0000, #memx_func_wait)
|
||
|
handler(DELAY , 0x0001, 0x0000, #memx_func_delay)
|
||
|
handler(VBLANK, 0x0001, 0x0000, #memx_func_wait_vblank)
|
||
|
handler(TRAIN , 0x0000, 0x0000, #memx_func_train)
|
||
|
memx_func_tail:
|
||
|
|
||
|
.equ #memx_func_size #memx_func_next - #memx_func_head
|
||
|
.equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size
|
||
|
|
||
|
memx_ts_start:
|
||
|
.b32 0
|
||
|
memx_ts_end:
|
||
|
.b32 0
|
||
|
|
||
|
memx_data_head:
|
||
|
.skip 0x0800
|
||
|
memx_data_tail:
|
||
|
|
||
|
memx_train_head:
|
||
|
.skip 0x0100
|
||
|
memx_train_tail:
|
||
|
#endif
|
||
|
|
||
|
/******************************************************************************
|
||
|
* MEMX code segment
|
||
|
*****************************************************************************/
|
||
|
#ifdef INCLUDE_CODE
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_enter:
|
||
|
#if NVKM_PPWR_CHIPSET == GT215
|
||
|
mov $r8 0x1610
|
||
|
nv_rd32($r7, $r8)
|
||
|
imm32($r6, 0xfffffffc)
|
||
|
and $r7 $r6
|
||
|
mov $r6 0x2
|
||
|
or $r7 $r6
|
||
|
nv_wr32($r8, $r7)
|
||
|
#else
|
||
|
mov $r6 0x001620
|
||
|
imm32($r7, ~0x00000aa2);
|
||
|
nv_rd32($r8, $r6)
|
||
|
and $r8 $r7
|
||
|
nv_wr32($r6, $r8)
|
||
|
|
||
|
imm32($r7, ~0x00000001)
|
||
|
nv_rd32($r8, $r6)
|
||
|
and $r8 $r7
|
||
|
nv_wr32($r6, $r8)
|
||
|
|
||
|
mov $r6 0x0026f0
|
||
|
nv_rd32($r8, $r6)
|
||
|
and $r8 $r7
|
||
|
nv_wr32($r6, $r8)
|
||
|
#endif
|
||
|
|
||
|
mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE
|
||
|
nv_iowr(NV_PPWR_OUTPUT_SET, $r6)
|
||
|
memx_func_enter_wait:
|
||
|
nv_iord($r6, NV_PPWR_OUTPUT)
|
||
|
and $r6 NV_PPWR_OUTPUT_FB_PAUSE
|
||
|
bra z #memx_func_enter_wait
|
||
|
|
||
|
nv_iord($r6, NV_PPWR_TIMER_LOW)
|
||
|
st b32 D[$r0 + #memx_ts_start] $r6
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_leave:
|
||
|
nv_iord($r6, NV_PPWR_TIMER_LOW)
|
||
|
st b32 D[$r0 + #memx_ts_end] $r6
|
||
|
|
||
|
mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE
|
||
|
nv_iowr(NV_PPWR_OUTPUT_CLR, $r6)
|
||
|
memx_func_leave_wait:
|
||
|
nv_iord($r6, NV_PPWR_OUTPUT)
|
||
|
and $r6 NV_PPWR_OUTPUT_FB_PAUSE
|
||
|
bra nz #memx_func_leave_wait
|
||
|
|
||
|
#if NVKM_PPWR_CHIPSET == GT215
|
||
|
mov $r8 0x1610
|
||
|
nv_rd32($r7, $r8)
|
||
|
imm32($r6, 0xffffffcc)
|
||
|
and $r7 $r6
|
||
|
nv_wr32($r8, $r7)
|
||
|
#else
|
||
|
mov $r6 0x0026f0
|
||
|
imm32($r7, 0x00000001)
|
||
|
nv_rd32($r8, $r6)
|
||
|
or $r8 $r7
|
||
|
nv_wr32($r6, $r8)
|
||
|
|
||
|
mov $r6 0x001620
|
||
|
nv_rd32($r8, $r6)
|
||
|
or $r8 $r7
|
||
|
nv_wr32($r6, $r8)
|
||
|
|
||
|
imm32($r7, 0x00000aa2);
|
||
|
nv_rd32($r8, $r6)
|
||
|
or $r8 $r7
|
||
|
nv_wr32($r6, $r8)
|
||
|
#endif
|
||
|
ret
|
||
|
|
||
|
#if NVKM_PPWR_CHIPSET < GF119
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// +00: head to wait for vblank on
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_wait_vblank:
|
||
|
ld b32 $r6 D[$r1 + 0x00]
|
||
|
cmp b32 $r6 0x0
|
||
|
bra z #memx_func_wait_vblank_head0
|
||
|
cmp b32 $r6 0x1
|
||
|
bra z #memx_func_wait_vblank_head1
|
||
|
bra #memx_func_wait_vblank_fini
|
||
|
|
||
|
memx_func_wait_vblank_head1:
|
||
|
mov $r7 0x20
|
||
|
bra #memx_func_wait_vblank_0
|
||
|
|
||
|
memx_func_wait_vblank_head0:
|
||
|
mov $r7 0x8
|
||
|
|
||
|
memx_func_wait_vblank_0:
|
||
|
nv_iord($r6, NV_PPWR_INPUT)
|
||
|
and $r6 $r7
|
||
|
bra nz #memx_func_wait_vblank_0
|
||
|
|
||
|
memx_func_wait_vblank_1:
|
||
|
nv_iord($r6, NV_PPWR_INPUT)
|
||
|
and $r6 $r7
|
||
|
bra z #memx_func_wait_vblank_1
|
||
|
|
||
|
memx_func_wait_vblank_fini:
|
||
|
add b32 $r1 0x4
|
||
|
ret
|
||
|
|
||
|
#else
|
||
|
|
||
|
// XXX: currently no-op
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// +00: head to wait for vblank on
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_wait_vblank:
|
||
|
add b32 $r1 0x4
|
||
|
ret
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// +00*n: addr
|
||
|
// +04*n: data
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_wr32:
|
||
|
ld b32 $r6 D[$r1 + 0x00]
|
||
|
ld b32 $r5 D[$r1 + 0x04]
|
||
|
add b32 $r1 0x08
|
||
|
nv_wr32($r6, $r5)
|
||
|
sub b32 $r4 0x02
|
||
|
bra nz #memx_func_wr32
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// +00: addr
|
||
|
// +04: mask
|
||
|
// +08: data
|
||
|
// +0c: timeout (ns)
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_wait:
|
||
|
nv_iord($r8, NV_PPWR_TIMER_LOW)
|
||
|
ld b32 $r14 D[$r1 + 0x00]
|
||
|
ld b32 $r13 D[$r1 + 0x04]
|
||
|
ld b32 $r12 D[$r1 + 0x08]
|
||
|
ld b32 $r11 D[$r1 + 0x0c]
|
||
|
add b32 $r1 0x10
|
||
|
call(wait)
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// +00: time (ns)
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_delay:
|
||
|
ld b32 $r14 D[$r1 + 0x00]
|
||
|
add b32 $r1 0x04
|
||
|
call(nsec)
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r4 - packet length
|
||
|
// $r3 - opcode desciption
|
||
|
// $r0 - zero
|
||
|
memx_func_train:
|
||
|
#if NVKM_PPWR_CHIPSET == GT215
|
||
|
// $r5 - outer loop counter
|
||
|
// $r6 - inner loop counter
|
||
|
// $r7 - entry counter (#memx_train_head + $r7)
|
||
|
mov $r5 0x3
|
||
|
mov $r7 0x0
|
||
|
|
||
|
// Read random memory to wake up... things
|
||
|
imm32($r9, 0x700000)
|
||
|
nv_rd32($r8,$r9)
|
||
|
mov $r14 0x2710
|
||
|
call(nsec)
|
||
|
|
||
|
memx_func_train_loop_outer:
|
||
|
mulu $r8 $r5 0x101
|
||
|
sethi $r8 0x02000000
|
||
|
imm32($r9, 0x1111e0)
|
||
|
nv_wr32($r9, $r8)
|
||
|
push $r5
|
||
|
|
||
|
mov $r6 0x0
|
||
|
memx_func_train_loop_inner:
|
||
|
mov $r8 0x1111
|
||
|
mulu $r9 $r6 $r8
|
||
|
shl b32 $r8 $r9 0x10
|
||
|
or $r8 $r9
|
||
|
imm32($r9, 0x100720)
|
||
|
nv_wr32($r9, $r8)
|
||
|
|
||
|
imm32($r9, 0x100080)
|
||
|
nv_rd32($r8, $r9)
|
||
|
or $r8 $r8 0x20
|
||
|
nv_wr32($r9, $r8)
|
||
|
|
||
|
imm32($r9, 0x10053c)
|
||
|
imm32($r8, 0x80003002)
|
||
|
nv_wr32($r9, $r8)
|
||
|
|
||
|
imm32($r14, 0x100560)
|
||
|
imm32($r13, 0x80000000)
|
||
|
add b32 $r12 $r13 0
|
||
|
imm32($r11, 0x001e8480)
|
||
|
call(wait)
|
||
|
|
||
|
// $r5 - inner inner loop counter
|
||
|
// $r9 - result
|
||
|
mov $r5 0
|
||
|
imm32($r9, 0x8300ffff)
|
||
|
memx_func_train_loop_4x:
|
||
|
imm32($r10, 0x100080)
|
||
|
nv_rd32($r8, $r10)
|
||
|
imm32($r11, 0xffffffdf)
|
||
|
and $r8 $r11
|
||
|
nv_wr32($r10, $r8)
|
||
|
|
||
|
imm32($r10, 0x10053c)
|
||
|
imm32($r8, 0x80003002)
|
||
|
nv_wr32($r10, $r8)
|
||
|
|
||
|
imm32($r14, 0x100560)
|
||
|
imm32($r13, 0x80000000)
|
||
|
mov b32 $r12 $r13
|
||
|
imm32($r11, 0x00002710)
|
||
|
call(wait)
|
||
|
|
||
|
nv_rd32($r13, $r14)
|
||
|
and $r9 $r9 $r13
|
||
|
|
||
|
add b32 $r5 1
|
||
|
cmp b16 $r5 0x4
|
||
|
bra l #memx_func_train_loop_4x
|
||
|
|
||
|
add b32 $r10 $r7 #memx_train_head
|
||
|
st b32 D[$r10 + 0] $r9
|
||
|
add b32 $r6 1
|
||
|
add b32 $r7 4
|
||
|
|
||
|
cmp b16 $r6 0x10
|
||
|
bra l #memx_func_train_loop_inner
|
||
|
|
||
|
pop $r5
|
||
|
add b32 $r5 1
|
||
|
cmp b16 $r5 7
|
||
|
bra l #memx_func_train_loop_outer
|
||
|
|
||
|
#endif
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r14 - sender process name
|
||
|
// $r13 - message (exec)
|
||
|
// $r12 - head of script
|
||
|
// $r11 - tail of script
|
||
|
// $r0 - zero
|
||
|
memx_exec:
|
||
|
push $r14
|
||
|
push $r13
|
||
|
mov b32 $r1 $r12
|
||
|
mov b32 $r2 $r11
|
||
|
|
||
|
memx_exec_next:
|
||
|
// fetch the packet header
|
||
|
ld b32 $r3 D[$r1]
|
||
|
add b32 $r1 4
|
||
|
extr $r4 $r3 16:31
|
||
|
extr $r3 $r3 0:15
|
||
|
|
||
|
// execute the opcode handler
|
||
|
sub b32 $r3 1
|
||
|
mulu $r3 #memx_func_size
|
||
|
ld b32 $r5 D[$r3 + #memx_func_head + #memx_func]
|
||
|
call $r5
|
||
|
|
||
|
// keep going, if we haven't reached the end
|
||
|
cmp b32 $r1 $r2
|
||
|
bra l #memx_exec_next
|
||
|
|
||
|
// send completion reply
|
||
|
ld b32 $r11 D[$r0 + #memx_ts_start]
|
||
|
ld b32 $r12 D[$r0 + #memx_ts_end]
|
||
|
sub b32 $r12 $r11
|
||
|
nv_iord($r11, NV_PPWR_INPUT)
|
||
|
pop $r13
|
||
|
pop $r14
|
||
|
call(send)
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r14 - sender process name
|
||
|
// $r13 - message
|
||
|
// $r12 - data0
|
||
|
// $r11 - data1
|
||
|
// $r0 - zero
|
||
|
memx_info:
|
||
|
cmp b16 $r12 0x1
|
||
|
bra e #memx_info_train
|
||
|
|
||
|
memx_info_data:
|
||
|
mov $r12 #memx_data_head
|
||
|
mov $r11 #memx_data_tail - #memx_data_head
|
||
|
bra #memx_info_send
|
||
|
|
||
|
memx_info_train:
|
||
|
mov $r12 #memx_train_head
|
||
|
mov $r11 #memx_train_tail - #memx_train_head
|
||
|
|
||
|
memx_info_send:
|
||
|
call(send)
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r14 - sender process name
|
||
|
// $r13 - message
|
||
|
// $r12 - data0
|
||
|
// $r11 - data1
|
||
|
// $r0 - zero
|
||
|
memx_recv:
|
||
|
cmp b32 $r13 MEMX_MSG_EXEC
|
||
|
bra e #memx_exec
|
||
|
cmp b32 $r13 MEMX_MSG_INFO
|
||
|
bra e #memx_info
|
||
|
ret
|
||
|
|
||
|
// description
|
||
|
//
|
||
|
// $r15 - current (memx)
|
||
|
// $r0 - zero
|
||
|
memx_init:
|
||
|
ret
|
||
|
#endif
|