| /* |
| * 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 |
| imm32($r1, PROC_KERN) |
| 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 |