diff options
Diffstat (limited to 'nvkm/subdev/pwr/fuc/kernel.fuc')
-rw-r--r-- | nvkm/subdev/pwr/fuc/kernel.fuc | 556 |
1 files changed, 0 insertions, 556 deletions
diff --git a/nvkm/subdev/pwr/fuc/kernel.fuc b/nvkm/subdev/pwr/fuc/kernel.fuc deleted file mode 100644 index 5cf5be63c..000000000 --- a/nvkm/subdev/pwr/fuc/kernel.fuc +++ /dev/null @@ -1,556 +0,0 @@ -/* - * 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 - */ - -/****************************************************************************** - * kernel data segment - *****************************************************************************/ -#ifdef INCLUDE_PROC -proc_kern: -process(PROC_KERN, 0, 0) -proc_list_head: -#endif - -#ifdef INCLUDE_DATA -proc_list_tail: -time_prev: .b32 0 -time_next: .b32 0 -#endif - -/****************************************************************************** - * kernel code segment - *****************************************************************************/ -#ifdef INCLUDE_CODE - bra #init - -// read nv register -// -// $r15 - current -// $r14 - addr -// $r13 - data (return) -// $r0 - zero -rd32: - nv_iowr(NV_PPWR_MMIO_ADDR, $r14) - mov $r13 NV_PPWR_MMIO_CTRL_OP_RD - sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER - nv_iowr(NV_PPWR_MMIO_CTRL, $r13) - rd32_wait: - nv_iord($r13, NV_PPWR_MMIO_CTRL) - and $r13 NV_PPWR_MMIO_CTRL_STATUS - bra nz #rd32_wait - nv_iord($r13, NV_PPWR_MMIO_DATA) - ret - -// write nv register -// -// $r15 - current -// $r14 - addr -// $r13 - data -// $r0 - zero -wr32: - nv_iowr(NV_PPWR_MMIO_ADDR, $r14) - nv_iowr(NV_PPWR_MMIO_DATA, $r13) - mov $r13 NV_PPWR_MMIO_CTRL_OP_WR - or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0 - sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER - -#ifdef NVKM_FALCON_MMIO_TRAP - push $r13 - mov $r13 NV_PPWR_INTR_TRIGGER_USER1 - nv_iowr(NV_PPWR_INTR_TRIGGER, $r13) - wr32_host: - nv_iord($r13, NV_PPWR_INTR) - and $r13 NV_PPWR_INTR_USER1 - bra nz #wr32_host - pop $r13 -#endif - - nv_iowr(NV_PPWR_MMIO_CTRL, $r13) - wr32_wait: - nv_iord($r13, NV_PPWR_MMIO_CTRL) - and $r13 NV_PPWR_MMIO_CTRL_STATUS - bra nz #wr32_wait - ret - -// busy-wait for a period of time -// -// $r15 - current -// $r14 - ns -// $r0 - zero -nsec: - push $r9 - push $r8 - nv_iord($r8, NV_PPWR_TIMER_LOW) - nsec_loop: - nv_iord($r9, NV_PPWR_TIMER_LOW) - sub b32 $r9 $r8 - cmp b32 $r9 $r14 - bra l #nsec_loop - pop $r8 - pop $r9 - ret - -// busy-wait for a period of time -// -// $r15 - current -// $r14 - addr -// $r13 - mask -// $r12 - data -// $r11 - timeout (ns) -// $r0 - zero -wait: - push $r9 - push $r8 - nv_iord($r8, NV_PPWR_TIMER_LOW) - wait_loop: - nv_rd32($r10, $r14) - and $r10 $r13 - cmp b32 $r10 $r12 - bra e #wait_done - nv_iord($r9, NV_PPWR_TIMER_LOW) - sub b32 $r9 $r8 - cmp b32 $r9 $r11 - bra l #wait_loop - wait_done: - pop $r8 - pop $r9 - ret - -// $r15 - current (kern) -// $r14 - process -// $r8 - NV_PPWR_INTR -intr_watchdog: - // read process' timer status, skip if not enabled - ld b32 $r9 D[$r14 + #proc_time] - cmp b32 $r9 0 - bra z #intr_watchdog_next_proc - - // subtract last timer's value from process' timer, - // if it's <= 0 then the timer has expired - ld b32 $r10 D[$r0 + #time_prev] - sub b32 $r9 $r10 - bra g #intr_watchdog_next_time - mov $r13 KMSG_ALARM - call(send_proc) - clear b32 $r9 - bra #intr_watchdog_next_proc - - // otherwise, update the next timer's value if this - // process' timer is the soonest - intr_watchdog_next_time: - // ... or if there's no next timer yet - ld b32 $r10 D[$r0 + #time_next] - cmp b32 $r10 0 - bra z #intr_watchdog_next_time_set - - cmp b32 $r9 $r10 - bra g #intr_watchdog_next_proc - intr_watchdog_next_time_set: - st b32 D[$r0 + #time_next] $r9 - - // update process' timer status, and advance - intr_watchdog_next_proc: - st b32 D[$r14 + #proc_time] $r9 - add b32 $r14 #proc_size - cmp b32 $r14 #proc_list_tail - bra ne #intr_watchdog - ret - -intr: - push $r0 - clear b32 $r0 - push $r8 - push $r9 - push $r10 - push $r11 - push $r12 - push $r13 - push $r14 - push $r15 - mov $r15 #proc_kern - mov $r8 $flags - push $r8 - - nv_iord($r8, NV_PPWR_DSCRATCH(0)) - add b32 $r8 1 - nv_iowr(NV_PPWR_DSCRATCH(0), $r8) - - nv_iord($r8, NV_PPWR_INTR) - and $r9 $r8 NV_PPWR_INTR_WATCHDOG - bra z #intr_skip_watchdog - st b32 D[$r0 + #time_next] $r0 - mov $r14 #proc_list_head - call(intr_watchdog) - ld b32 $r9 D[$r0 + #time_next] - cmp b32 $r9 0 - bra z #intr_skip_watchdog - nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9) - st b32 D[$r0 + #time_prev] $r9 - - intr_skip_watchdog: - and $r9 $r8 NV_PPWR_INTR_SUBINTR - bra z #intr_skip_subintr - nv_iord($r9, NV_PPWR_SUBINTR) - and $r10 $r9 NV_PPWR_SUBINTR_FIFO - bra z #intr_subintr_skip_fifo - nv_iord($r12, NV_PPWR_FIFO_INTR) - push $r12 - mov $r14 (PROC_HOST & 0x0000ffff) - sethi $r14 (PROC_HOST & 0xffff0000) - mov $r13 KMSG_FIFO - call(send) - pop $r12 - nv_iowr(NV_PPWR_FIFO_INTR, $r12) - intr_subintr_skip_fifo: - nv_iowr(NV_PPWR_SUBINTR, $r9) - - intr_skip_subintr: - and $r9 $r8 NV_PPWR_INTR_PAUSE - bra z #intr_skip_pause - and $r10 0xffbf - - intr_skip_pause: - and $r9 $r8 NV_PPWR_INTR_USER0 - bra z #intr_skip_user0 - and $r10 0xffbf - - intr_skip_user0: - nv_iowr(NV_PPWR_INTR_ACK, $r8) - pop $r8 - mov $flags $r8 - pop $r15 - pop $r14 - pop $r13 - pop $r12 - pop $r11 - pop $r10 - pop $r9 - pop $r8 - pop $r0 - bclr $flags $p0 - iret - -// calculate the number of ticks in the specified nanoseconds delay -// -// $r15 - current -// $r14 - ns -// $r14 - ticks (return) -// $r0 - zero -ticks_from_ns: - push $r12 - push $r11 - - /* try not losing precision (multiply then divide) */ - imm32($r13, HW_TICKS_PER_US) - call #mulu32_32_64 - - /* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */ - div $r12 $r12 1000 - - /* check if there wasn't any overflow */ - cmpu b32 $r11 0 - bra e #ticks_from_ns_quit - - /* let's divide then multiply, too bad for the precision! */ - div $r14 $r14 1000 - imm32($r13, HW_TICKS_PER_US) - call #mulu32_32_64 - - /* this cannot overflow as long as HW_TICKS_PER_US < 1000 */ - -ticks_from_ns_quit: - mov b32 $r14 $r12 - pop $r11 - pop $r12 - ret - -// calculate the number of ticks in the specified microsecond delay -// -// $r15 - current -// $r14 - us -// $r14 - ticks (return) -// $r0 - zero -ticks_from_us: - push $r12 - push $r11 - - /* simply multiply $us by HW_TICKS_PER_US */ - imm32($r13, HW_TICKS_PER_US) - call #mulu32_32_64 - mov b32 $r14 $r12 - - /* check if there wasn't any overflow */ - cmpu b32 $r11 0 - bra e #ticks_from_us_quit - - /* Overflow! */ - clear b32 $r14 - -ticks_from_us_quit: - pop $r11 - pop $r12 - ret - -// calculate the number of ticks in the specified microsecond delay -// -// $r15 - current -// $r14 - ticks -// $r14 - us (return) -// $r0 - zero -ticks_to_us: - /* simply divide $ticks by HW_TICKS_PER_US */ - imm32($r13, HW_TICKS_PER_US) - div $r14 $r14 $r13 - - ret - -// request the current process be sent a message after a timeout expires -// -// $r15 - current -// $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow) -// $r0 - zero -timer: - push $r9 - push $r8 - - // interrupts off to prevent racing with timer isr - bclr $flags ie0 - - // if current process already has a timer set, bail - ld b32 $r8 D[$r15 + #proc_time] - cmp b32 $r8 0 - bra g #timer_done - - // halt watchdog timer temporarily - clear b32 $r8 - nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8) - - // find out how much time elapsed since the last update - // of the watchdog and add this time to the wanted ticks - nv_iord($r8, NV_PPWR_WATCHDOG_TIME) - ld b32 $r9 D[$r0 + #time_prev] - sub b32 $r9 $r8 - add b32 $r14 $r9 - st b32 D[$r15 + #proc_time] $r14 - - // check for a pending interrupt. if there's one already - // pending, we can just bail since the timer isr will - // queue the next soonest right after it's done - nv_iord($r8, NV_PPWR_INTR) - and $r8 NV_PPWR_INTR_WATCHDOG - bra nz #timer_enable - - // update the watchdog if this timer should expire first, - // or if there's no timeout already set - nv_iord($r8, NV_PPWR_WATCHDOG_TIME) - cmp b32 $r14 $r0 - bra e #timer_reset - cmp b32 $r14 $r8 - bra g #timer_enable - timer_reset: - nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14) - st b32 D[$r0 + #time_prev] $r14 - - // re-enable the watchdog timer - timer_enable: - mov $r8 1 - nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8) - - // interrupts back on - timer_done: - bset $flags ie0 - - pop $r8 - pop $r9 - ret - -// send message to another process -// -// $r15 - current -// $r14 - process -// $r13 - message -// $r12 - message data 0 -// $r11 - message data 1 -// $r0 - zero -send_proc: - push $r8 - push $r9 - // check for space in queue - ld b32 $r8 D[$r14 + #proc_qget] - ld b32 $r9 D[$r14 + #proc_qput] - xor $r8 #proc_qmaskb - cmp b32 $r8 $r9 - bra e #send_done - - // enqueue message - and $r8 $r9 #proc_qmaskp - shl b32 $r8 $r8 #proc_qlen - add b32 $r8 #proc_queue - add b32 $r8 $r14 - - ld b32 $r10 D[$r15 + #proc_id] - st b32 D[$r8 + #msg_process] $r10 - st b32 D[$r8 + #msg_message] $r13 - st b32 D[$r8 + #msg_data0] $r12 - st b32 D[$r8 + #msg_data1] $r11 - - // increment PUT - add b32 $r9 1 - and $r9 #proc_qmaskf - st b32 D[$r14 + #proc_qput] $r9 - bset $flags $p2 - send_done: - pop $r9 - pop $r8 - ret - -// lookup process structure by its name -// -// $r15 - current -// $r14 - process name -// $r0 - zero -// -// $r14 - process -// $p1 - success -find: - push $r8 - mov $r8 #proc_list_head - bset $flags $p1 - find_loop: - ld b32 $r10 D[$r8 + #proc_id] - cmp b32 $r10 $r14 - bra e #find_done - add b32 $r8 #proc_size - cmp b32 $r8 #proc_list_tail - bra ne #find_loop - bclr $flags $p1 - find_done: - mov b32 $r14 $r8 - pop $r8 - ret - -// send message to another process -// -// $r15 - current -// $r14 - process id -// $r13 - message -// $r12 - message data 0 -// $r11 - message data 1 -// $r0 - zero -send: - call(find) - bra $p1 #send_proc - ret - -// process single message for a given process -// -// $r15 - current -// $r14 - process -// $r0 - zero -recv: - push $r9 - push $r8 - - ld b32 $r8 D[$r14 + #proc_qget] - ld b32 $r9 D[$r14 + #proc_qput] - bclr $flags $p1 - cmp b32 $r8 $r9 - bra e #recv_done - // dequeue message - and $r9 $r8 #proc_qmaskp - add b32 $r8 1 - and $r8 #proc_qmaskf - st b32 D[$r14 + #proc_qget] $r8 - ld b32 $r10 D[$r14 + #proc_recv] - - push $r15 - mov $r15 $flags - push $r15 - mov b32 $r15 $r14 - - shl b32 $r9 $r9 #proc_qlen - add b32 $r14 $r9 - add b32 $r14 #proc_queue - ld b32 $r11 D[$r14 + #msg_data1] - ld b32 $r12 D[$r14 + #msg_data0] - ld b32 $r13 D[$r14 + #msg_message] - ld b32 $r14 D[$r14 + #msg_process] - - // process it - call $r10 - pop $r15 - mov $flags $r15 - bset $flags $p1 - pop $r15 - recv_done: - pop $r8 - pop $r9 - ret - -init: - // setup stack - nv_iord($r1, NV_PPWR_CAPS) - extr $r1 $r1 9:17 - shl b32 $r1 8 - mov $sp $r1 - -#ifdef NVKM_FALCON_MMIO_UAS - // somehow allows the magic "access mmio via D[]" stuff that's - // used by the nv_rd32/nv_wr32 macros to work - mov $r1 0x0010 - sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE - nv_iowrs(NV_PPWR_UAS_CONFIG, $r1) -#endif - - // route all interrupts except user0/1 and pause to fuc - mov $r1 0x00e0 - sethi $r1 0x00000000 - nv_iowr(NV_PPWR_INTR_ROUTE, $r1) - - // enable watchdog and subintr intrs - mov $r1 NV_PPWR_INTR_EN_CLR_MASK - nv_iowr(NV_PPWR_INTR_EN_CLR, $r1) - mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG - or $r1 NV_PPWR_INTR_EN_SET_SUBINTR - nv_iowr(NV_PPWR_INTR_EN_SET, $r1) - - // enable interrupts globally - mov $r1 #intr - sethi $r1 0x00000000 - mov $iv0 $r1 - bset $flags ie0 - - // enable watchdog timer - mov $r1 1 - nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1) - - // bootstrap processes, idle process will be last, and not return - mov $r15 #proc_list_head - init_proc: - ld b32 $r1 D[$r15 + #proc_init] - cmp b32 $r1 0 - bra z #init_proc - call $r1 - add b32 $r15 #proc_size - bra #init_proc -#endif |