blob: d43741eccb11b66fd4106e233199c77516f0706b [file] [log] [blame]
/*
* 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 , 0x0001, 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)
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_data_head:
.skip 0x0800
memx_data_tail:
#endif
/******************************************************************************
* MEMX code segment
*****************************************************************************/
#ifdef INCLUDE_CODE
// description
//
// $r15 - current (memx)
// $r4 - packet length
// +00: bitmask of heads to wait for vblank on
// $r3 - opcode desciption
// $r0 - zero
memx_func_enter:
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
//XXX: TODO
ld b32 $r6 D[$r1 + 0x00]
add b32 $r1 0x04
ret
// description
//
// $r15 - current (memx)
// $r4 - packet length
// $r3 - opcode desciption
// $r0 - zero
memx_func_leave:
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
ret
// 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)
// $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, and locate opcode info
ld b32 $r3 D[$r1]
add b32 $r1 4
shr b32 $r4 $r3 16
mulu $r3 #memx_func_size
// execute the opcode handler
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
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:
mov $r12 #memx_data_head
mov $r11 #memx_data_tail - #memx_data_head
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