2 * Copyright 2013 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 /******************************************************************************
27 *****************************************************************************/
30 process(PROC_KERN, 0, 0)
40 /******************************************************************************
42 *****************************************************************************/
50 // $r13 - data (return)
53 nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
54 mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
55 sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
56 nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
58 nv_iord($r13, NV_PPWR_MMIO_CTRL)
59 and $r13 NV_PPWR_MMIO_CTRL_STATUS
61 nv_iord($r13, NV_PPWR_MMIO_DATA)
71 nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
72 nv_iowr(NV_PPWR_MMIO_DATA, $r13)
73 mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
74 or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
75 sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
77 #ifdef NVKM_FALCON_MMIO_TRAP
79 mov $r13 NV_PPWR_INTR_TRIGGER_USER1
80 nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
82 nv_iord($r13, NV_PPWR_INTR)
83 and $r13 NV_PPWR_INTR_USER1
88 nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
90 nv_iord($r13, NV_PPWR_MMIO_CTRL)
91 and $r13 NV_PPWR_MMIO_CTRL_STATUS
95 // busy-wait for a period of time
103 nv_iord($r8, NV_PPWR_TIMER_LOW)
105 nv_iord($r9, NV_PPWR_TIMER_LOW)
113 // busy-wait for a period of time
119 // $r11 - timeout (ns)
124 nv_iord($r8, NV_PPWR_TIMER_LOW)
130 nv_iord($r9, NV_PPWR_TIMER_LOW)
139 // $r15 - current (kern)
141 // $r8 - NV_PPWR_INTR
143 // read process' timer status, skip if not enabled
144 ld b32 $r9 D[$r14 + #proc_time]
146 bra z #intr_watchdog_next_proc
148 // subtract last timer's value from process' timer,
149 // if it's <= 0 then the timer has expired
150 ld b32 $r10 D[$r0 + #time_prev]
152 bra g #intr_watchdog_next_time
156 bra #intr_watchdog_next_proc
158 // otherwise, update the next timer's value if this
159 // process' timer is the soonest
160 intr_watchdog_next_time:
161 // ... or if there's no next timer yet
162 ld b32 $r10 D[$r0 + #time_next]
164 bra z #intr_watchdog_next_time_set
167 bra g #intr_watchdog_next_proc
168 intr_watchdog_next_time_set:
169 st b32 D[$r0 + #time_next] $r9
171 // update process' timer status, and advance
172 intr_watchdog_next_proc:
173 st b32 D[$r14 + #proc_time] $r9
174 add b32 $r14 #proc_size
175 cmp b32 $r14 #proc_list_tail
176 bra ne #intr_watchdog
194 nv_iord($r8, NV_PPWR_DSCRATCH(0))
196 nv_iowr(NV_PPWR_DSCRATCH(0), $r8)
198 nv_iord($r8, NV_PPWR_INTR)
199 and $r9 $r8 NV_PPWR_INTR_WATCHDOG
200 bra z #intr_skip_watchdog
201 st b32 D[$r0 + #time_next] $r0
202 mov $r14 #proc_list_head
204 ld b32 $r9 D[$r0 + #time_next]
206 bra z #intr_skip_watchdog
207 nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9)
208 st b32 D[$r0 + #time_prev] $r9
211 and $r9 $r8 NV_PPWR_INTR_SUBINTR
212 bra z #intr_skip_subintr
213 nv_iord($r9, NV_PPWR_SUBINTR)
214 and $r10 $r9 NV_PPWR_SUBINTR_FIFO
215 bra z #intr_subintr_skip_fifo
216 nv_iord($r12, NV_PPWR_FIFO_INTR)
218 mov $r14 (PROC_HOST & 0x0000ffff)
219 sethi $r14 (PROC_HOST & 0xffff0000)
223 nv_iowr(NV_PPWR_FIFO_INTR, $r12)
224 intr_subintr_skip_fifo:
225 nv_iowr(NV_PPWR_SUBINTR, $r9)
228 and $r9 $r8 NV_PPWR_INTR_PAUSE
229 bra z #intr_skip_pause
233 and $r9 $r8 NV_PPWR_INTR_USER0
234 bra z #intr_skip_user0
238 nv_iowr(NV_PPWR_INTR_ACK, $r8)
253 // calculate the number of ticks in the specified nanoseconds delay
257 // $r14 - ticks (return)
263 /* try not losing precision (multiply then divide) */
264 imm32($r13, HW_TICKS_PER_US)
267 /* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */
270 /* check if there wasn't any overflow */
272 bra e #ticks_from_ns_quit
274 /* let's divide then multiply, too bad for the precision! */
276 imm32($r13, HW_TICKS_PER_US)
279 /* this cannot overflow as long as HW_TICKS_PER_US < 1000 */
287 // calculate the number of ticks in the specified microsecond delay
291 // $r14 - ticks (return)
297 /* simply multiply $us by HW_TICKS_PER_US */
298 imm32($r13, HW_TICKS_PER_US)
302 /* check if there wasn't any overflow */
304 bra e #ticks_from_us_quit
314 // calculate the number of ticks in the specified microsecond delay
318 // $r14 - us (return)
321 /* simply divide $ticks by HW_TICKS_PER_US */
322 imm32($r13, HW_TICKS_PER_US)
327 // request the current process be sent a message after a timeout expires
330 // $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow)
336 // interrupts off to prevent racing with timer isr
339 // if current process already has a timer set, bail
340 ld b32 $r8 D[$r15 + #proc_time]
344 // halt watchdog timer temporarily
346 nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)
348 // find out how much time elapsed since the last update
349 // of the watchdog and add this time to the wanted ticks
350 nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
351 ld b32 $r9 D[$r0 + #time_prev]
354 st b32 D[$r15 + #proc_time] $r14
356 // check for a pending interrupt. if there's one already
357 // pending, we can just bail since the timer isr will
358 // queue the next soonest right after it's done
359 nv_iord($r8, NV_PPWR_INTR)
360 and $r8 NV_PPWR_INTR_WATCHDOG
363 // update the watchdog if this timer should expire first,
364 // or if there's no timeout already set
365 nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
371 nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14)
372 st b32 D[$r0 + #time_prev] $r14
374 // re-enable the watchdog timer
377 nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)
379 // interrupts back on
387 // send message to another process
392 // $r12 - message data 0
393 // $r11 - message data 1
398 // check for space in queue
399 ld b32 $r8 D[$r14 + #proc_qget]
400 ld b32 $r9 D[$r14 + #proc_qput]
406 and $r8 $r9 #proc_qmaskp
407 shl b32 $r8 $r8 #proc_qlen
408 add b32 $r8 #proc_queue
411 ld b32 $r10 D[$r15 + #proc_id]
412 st b32 D[$r8 + #msg_process] $r10
413 st b32 D[$r8 + #msg_message] $r13
414 st b32 D[$r8 + #msg_data0] $r12
415 st b32 D[$r8 + #msg_data1] $r11
420 st b32 D[$r14 + #proc_qput] $r9
427 // lookup process structure by its name
430 // $r14 - process name
437 mov $r8 #proc_list_head
440 ld b32 $r10 D[$r8 + #proc_id]
443 add b32 $r8 #proc_size
444 cmp b32 $r8 #proc_list_tail
452 // send message to another process
457 // $r12 - message data 0
458 // $r11 - message data 1
465 // process single message for a given process
474 ld b32 $r8 D[$r14 + #proc_qget]
475 ld b32 $r9 D[$r14 + #proc_qput]
480 and $r9 $r8 #proc_qmaskp
483 st b32 D[$r14 + #proc_qget] $r8
484 ld b32 $r10 D[$r14 + #proc_recv]
491 shl b32 $r9 $r9 #proc_qlen
493 add b32 $r14 #proc_queue
494 ld b32 $r11 D[$r14 + #msg_data1]
495 ld b32 $r12 D[$r14 + #msg_data0]
496 ld b32 $r13 D[$r14 + #msg_message]
497 ld b32 $r14 D[$r14 + #msg_process]
512 nv_iord($r1, NV_PPWR_CAPS)
517 #ifdef NVKM_FALCON_MMIO_UAS
518 // somehow allows the magic "access mmio via D[]" stuff that's
519 // used by the nv_rd32/nv_wr32 macros to work
521 sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE
522 nv_iowrs(NV_PPWR_UAS_CONFIG, $r1)
525 // route all interrupts except user0/1 and pause to fuc
528 nv_iowr(NV_PPWR_INTR_ROUTE, $r1)
530 // enable watchdog and subintr intrs
531 mov $r1 NV_PPWR_INTR_EN_CLR_MASK
532 nv_iowr(NV_PPWR_INTR_EN_CLR, $r1)
533 mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG
534 or $r1 NV_PPWR_INTR_EN_SET_SUBINTR
535 nv_iowr(NV_PPWR_INTR_EN_SET, $r1)
537 // enable interrupts globally
543 // enable watchdog timer
545 nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1)
547 // bootstrap processes, idle process will be last, and not return
548 mov $r15 #proc_list_head
550 ld b32 $r1 D[$r15 + #proc_init]
554 add b32 $r15 #proc_size