/* * 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_HOST, #host_init, #host_recv) #endif /****************************************************************************** * HOST data segment *****************************************************************************/ #ifdef INCLUDE_DATA // HOST (R)FIFO packet format .equ #fifo_process 0x00 .equ #fifo_message 0x04 .equ #fifo_data0 0x08 .equ #fifo_data1 0x0c // HOST HOST->PWR queue description .equ #fifo_qlen 4 // log2(size of queue entry in bytes) .equ #fifo_qnum 3 // log2(max number of entries in queue) .equ #fifo_qmaskb (1 << #fifo_qnum) // max number of entries in queue .equ #fifo_qmaskp (#fifo_qmaskb - 1) .equ #fifo_qmaskf ((#fifo_qmaskb << 1) - 1) .equ #fifo_qsize (1 << (#fifo_qlen + #fifo_qnum)) fifo_queue: .skip 128 // #fifo_qsize // HOST PWR->HOST queue description .equ #rfifo_qlen 4 // log2(size of queue entry in bytes) .equ #rfifo_qnum 3 // log2(max number of entries in queue) .equ #rfifo_qmaskb (1 << #rfifo_qnum) // max number of entries in queue .equ #rfifo_qmaskp (#rfifo_qmaskb - 1) .equ #rfifo_qmaskf ((#rfifo_qmaskb << 1) - 1) .equ #rfifo_qsize (1 << (#rfifo_qlen + #rfifo_qnum)) rfifo_queue: .skip 128 // #rfifo_qsize #endif /****************************************************************************** * HOST code segment *****************************************************************************/ #ifdef INCLUDE_CODE // HOST->PWR comms - dequeue message(s) for process(es) from FIFO // // $r15 - current (host) // $r0 - zero host_send: nv_iord($r1, NV_PPWR_FIFO_GET(0)) nv_iord($r2, NV_PPWR_FIFO_PUT(0)) cmp b32 $r1 $r2 bra e #host_send_done // calculate address of message and $r14 $r1 #fifo_qmaskp shl b32 $r14 $r14 #fifo_qlen add b32 $r14 #fifo_queue // read message data, and pass to appropriate process ld b32 $r11 D[$r14 + #fifo_data1] ld b32 $r12 D[$r14 + #fifo_data0] ld b32 $r13 D[$r14 + #fifo_message] ld b32 $r14 D[$r14 + #fifo_process] call(send) // increment GET add b32 $r1 0x1 and $r14 $r1 #fifo_qmaskf nv_iowr(NV_PPWR_FIFO_GET(0), $r14) bra #host_send host_send_done: ret // PWR->HOST comms - enqueue message for HOST to RFIFO // // $r15 - current (host) // $r14 - process // $r13 - message // $r12 - message data 0 // $r11 - message data 1 // $r0 - zero host_recv: // message from intr handler == HOST->PWR comms pending mov $r1 (PROC_KERN & 0x0000ffff) sethi $r1 (PROC_KERN & 0xffff0000) cmp b32 $r14 $r1 bra e #host_send // wait for space in RFIFO host_recv_wait: nv_iord($r1, NV_PPWR_RFIFO_GET) nv_iord($r2, NV_PPWR_RFIFO_PUT) xor $r1 #rfifo_qmaskb cmp b32 $r1 $r2 bra e #host_recv_wait and $r3 $r2 #rfifo_qmaskp shl b32 $r3 #rfifo_qlen add b32 $r3 #rfifo_queue // enqueue message st b32 D[$r3 + #fifo_data1] $r11 st b32 D[$r3 + #fifo_data0] $r12 st b32 D[$r3 + #fifo_message] $r13 st b32 D[$r3 + #fifo_process] $r14 add b32 $r2 0x1 and $r2 #rfifo_qmaskf nv_iowr(NV_PPWR_RFIFO_PUT, $r2) // notify host of pending message mov $r2 NV_PPWR_INTR_TRIGGER_USER0 nv_iowr(NV_PPWR_INTR_TRIGGER, $r2) ret // $r15 - current (host) // $r0 - zero host_init: // store each fifo's base/size in H2D/D2H scratch regs mov $r1 #fifo_qsize shl b32 $r1 16 or $r1 #fifo_queue nv_iowr(NV_PPWR_H2D, $r1); mov $r1 #rfifo_qsize shl b32 $r1 16 or $r1 #rfifo_queue nv_iowr(NV_PPWR_D2H, $r1); // enable fifo subintr for first fifo mov $r1 1 nv_iowr(NV_PPWR_FIFO_INTR_EN, $r1) ret #endif