Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2013 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs
0023  */
0024 
0025 #ifdef INCLUDE_PROC
0026 process(PROC_MEMX, #memx_init, #memx_recv)
0027 #endif
0028 
0029 /******************************************************************************
0030  * MEMX data segment
0031  *****************************************************************************/
0032 #ifdef INCLUDE_DATA
0033 .equ #memx_opcode 0
0034 .equ #memx_header 2
0035 .equ #memx_length 4
0036 .equ #memx_func   8
0037 
0038 #define handler(cmd,hdr,len,func) /*
0039 */      .b16 MEMX_##cmd /*
0040 */      .b16 hdr /*
0041 */      .b16 len /*
0042 */      .b16 0 /*
0043 */      .b32 func
0044 
0045 memx_func_head:
0046 handler(ENTER , 0x0000, 0x0000, #memx_func_enter)
0047 memx_func_next:
0048 handler(LEAVE , 0x0000, 0x0000, #memx_func_leave)
0049 handler(WR32  , 0x0000, 0x0002, #memx_func_wr32)
0050 handler(WAIT  , 0x0004, 0x0000, #memx_func_wait)
0051 handler(DELAY , 0x0001, 0x0000, #memx_func_delay)
0052 handler(VBLANK, 0x0001, 0x0000, #memx_func_wait_vblank)
0053 handler(TRAIN , 0x0000, 0x0000, #memx_func_train)
0054 memx_func_tail:
0055 
0056 .equ #memx_func_size #memx_func_next - #memx_func_head
0057 .equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size
0058 
0059 memx_ts_start:
0060 .b32 0
0061 memx_ts_end:
0062 .b32 0
0063 
0064 memx_data_head:
0065 .skip 0x0800
0066 memx_data_tail:
0067 
0068 memx_train_head:
0069 .skip 0x0100
0070 memx_train_tail:
0071 #endif
0072 
0073 /******************************************************************************
0074  * MEMX code segment
0075  *****************************************************************************/
0076 #ifdef INCLUDE_CODE
0077 // description
0078 //
0079 // $r15 - current (memx)
0080 // $r4  - packet length
0081 // $r3  - opcode desciption
0082 // $r0  - zero
0083 memx_func_enter:
0084 #if NVKM_PPWR_CHIPSET == GT215
0085         mov $r8 0x1610
0086         nv_rd32($r7, $r8)
0087         imm32($r6, 0xfffffffc)
0088         and $r7 $r6
0089         mov $r6 0x2
0090         or $r7 $r6
0091         nv_wr32($r8, $r7)
0092 #else
0093         mov $r6 0x001620
0094         imm32($r7, ~0x00000aa2);
0095         nv_rd32($r8, $r6)
0096         and $r8 $r7
0097         nv_wr32($r6, $r8)
0098 
0099         imm32($r7, ~0x00000001)
0100         nv_rd32($r8, $r6)
0101         and $r8 $r7
0102         nv_wr32($r6, $r8)
0103 
0104         mov $r6 0x0026f0
0105         nv_rd32($r8, $r6)
0106         and $r8 $r7
0107         nv_wr32($r6, $r8)
0108 #endif
0109 
0110         mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE
0111         nv_iowr(NV_PPWR_OUTPUT_SET, $r6)
0112         memx_func_enter_wait:
0113                 nv_iord($r6, NV_PPWR_OUTPUT)
0114                 and $r6 NV_PPWR_OUTPUT_FB_PAUSE
0115                 bra z #memx_func_enter_wait
0116 
0117         nv_iord($r6, NV_PPWR_TIMER_LOW)
0118         st b32 D[$r0 + #memx_ts_start] $r6
0119         ret
0120 
0121 // description
0122 //
0123 // $r15 - current (memx)
0124 // $r4  - packet length
0125 // $r3  - opcode desciption
0126 // $r0  - zero
0127 memx_func_leave:
0128         nv_iord($r6, NV_PPWR_TIMER_LOW)
0129         st b32 D[$r0 + #memx_ts_end] $r6
0130 
0131         mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE
0132         nv_iowr(NV_PPWR_OUTPUT_CLR, $r6)
0133         memx_func_leave_wait:
0134                 nv_iord($r6, NV_PPWR_OUTPUT)
0135                 and $r6 NV_PPWR_OUTPUT_FB_PAUSE
0136                 bra nz #memx_func_leave_wait
0137 
0138 #if NVKM_PPWR_CHIPSET == GT215
0139         mov $r8 0x1610
0140         nv_rd32($r7, $r8)
0141         imm32($r6, 0xffffffcc)
0142         and $r7 $r6
0143         nv_wr32($r8, $r7)
0144 #else
0145         mov $r6 0x0026f0
0146         imm32($r7, 0x00000001)
0147         nv_rd32($r8, $r6)
0148         or $r8 $r7
0149         nv_wr32($r6, $r8)
0150 
0151         mov $r6 0x001620
0152         nv_rd32($r8, $r6)
0153         or $r8 $r7
0154         nv_wr32($r6, $r8)
0155 
0156         imm32($r7, 0x00000aa2);
0157         nv_rd32($r8, $r6)
0158         or $r8 $r7
0159         nv_wr32($r6, $r8)
0160 #endif
0161         ret
0162 
0163 #if NVKM_PPWR_CHIPSET < GF119
0164 // description
0165 //
0166 // $r15 - current (memx)
0167 // $r4  - packet length
0168 //      +00: head to wait for vblank on
0169 // $r3  - opcode desciption
0170 // $r0  - zero
0171 memx_func_wait_vblank:
0172         ld b32 $r6 D[$r1 + 0x00]
0173         cmp b32 $r6 0x0
0174         bra z #memx_func_wait_vblank_head0
0175         cmp b32 $r6 0x1
0176         bra z #memx_func_wait_vblank_head1
0177         bra #memx_func_wait_vblank_fini
0178 
0179         memx_func_wait_vblank_head1:
0180         mov $r7 0x20
0181         bra #memx_func_wait_vblank_0
0182 
0183         memx_func_wait_vblank_head0:
0184         mov $r7 0x8
0185 
0186         memx_func_wait_vblank_0:
0187                 nv_iord($r6, NV_PPWR_INPUT)
0188                 and $r6 $r7
0189                 bra nz #memx_func_wait_vblank_0
0190 
0191         memx_func_wait_vblank_1:
0192                 nv_iord($r6, NV_PPWR_INPUT)
0193                 and $r6 $r7
0194                 bra z #memx_func_wait_vblank_1
0195 
0196         memx_func_wait_vblank_fini:
0197         add b32 $r1 0x4
0198         ret
0199 
0200 #else
0201 
0202 // XXX: currently no-op
0203 //
0204 // $r15 - current (memx)
0205 // $r4  - packet length
0206 //      +00: head to wait for vblank on
0207 // $r3  - opcode desciption
0208 // $r0  - zero
0209 memx_func_wait_vblank:
0210         add b32 $r1 0x4
0211         ret
0212 
0213 #endif
0214 
0215 // description
0216 //
0217 // $r15 - current (memx)
0218 // $r4  - packet length
0219 //      +00*n: addr
0220 //      +04*n: data
0221 // $r3  - opcode desciption
0222 // $r0  - zero
0223 memx_func_wr32:
0224         ld b32 $r6 D[$r1 + 0x00]
0225         ld b32 $r5 D[$r1 + 0x04]
0226         add b32 $r1 0x08
0227         nv_wr32($r6, $r5)
0228         sub b32 $r4 0x02
0229         bra nz #memx_func_wr32
0230         ret
0231 
0232 // description
0233 //
0234 // $r15 - current (memx)
0235 // $r4  - packet length
0236 //      +00: addr
0237 //      +04: mask
0238 //      +08: data
0239 //      +0c: timeout (ns)
0240 // $r3  - opcode desciption
0241 // $r0  - zero
0242 memx_func_wait:
0243         nv_iord($r8, NV_PPWR_TIMER_LOW)
0244         ld b32 $r14 D[$r1 + 0x00]
0245         ld b32 $r13 D[$r1 + 0x04]
0246         ld b32 $r12 D[$r1 + 0x08]
0247         ld b32 $r11 D[$r1 + 0x0c]
0248         add b32 $r1 0x10
0249         call(wait)
0250         ret
0251 
0252 // description
0253 //
0254 // $r15 - current (memx)
0255 // $r4  - packet length
0256 //      +00: time (ns)
0257 // $r3  - opcode desciption
0258 // $r0  - zero
0259 memx_func_delay:
0260         ld b32 $r14 D[$r1 + 0x00]
0261         add b32 $r1 0x04
0262         call(nsec)
0263         ret
0264 
0265 // description
0266 //
0267 // $r15 - current (memx)
0268 // $r4  - packet length
0269 // $r3  - opcode desciption
0270 // $r0  - zero
0271 memx_func_train:
0272 #if NVKM_PPWR_CHIPSET == GT215
0273 // $r5 - outer loop counter
0274 // $r6 - inner loop counter
0275 // $r7 - entry counter (#memx_train_head + $r7)
0276         mov $r5 0x3
0277         mov $r7 0x0
0278 
0279 // Read random memory to wake up... things
0280         imm32($r9, 0x700000)
0281         nv_rd32($r8,$r9)
0282         mov $r14 0x2710
0283         call(nsec)
0284 
0285         memx_func_train_loop_outer:
0286                 mulu $r8 $r5 0x101
0287                 sethi $r8 0x02000000
0288                 imm32($r9, 0x1111e0)
0289                 nv_wr32($r9, $r8)
0290                 push $r5
0291 
0292                 mov $r6 0x0
0293                 memx_func_train_loop_inner:
0294                         mov $r8 0x1111
0295                         mulu $r9 $r6 $r8
0296                         shl b32 $r8 $r9 0x10
0297                         or $r8 $r9
0298                         imm32($r9, 0x100720)
0299                         nv_wr32($r9, $r8)
0300 
0301                         imm32($r9, 0x100080)
0302                         nv_rd32($r8, $r9)
0303                         or $r8 $r8 0x20
0304                         nv_wr32($r9, $r8)
0305 
0306                         imm32($r9, 0x10053c)
0307                         imm32($r8, 0x80003002)
0308                         nv_wr32($r9, $r8)
0309 
0310                         imm32($r14, 0x100560)
0311                         imm32($r13, 0x80000000)
0312                         add b32 $r12 $r13 0
0313                         imm32($r11, 0x001e8480)
0314                         call(wait)
0315 
0316                         // $r5 - inner inner loop counter
0317                         // $r9 - result
0318                         mov $r5 0
0319                         imm32($r9, 0x8300ffff)
0320                         memx_func_train_loop_4x:
0321                                 imm32($r10, 0x100080)
0322                                 nv_rd32($r8, $r10)
0323                                 imm32($r11, 0xffffffdf)
0324                                 and $r8 $r11
0325                                 nv_wr32($r10, $r8)
0326 
0327                                 imm32($r10, 0x10053c)
0328                                 imm32($r8, 0x80003002)
0329                                 nv_wr32($r10, $r8)
0330 
0331                                 imm32($r14, 0x100560)
0332                                 imm32($r13, 0x80000000)
0333                                 mov b32 $r12 $r13
0334                                 imm32($r11, 0x00002710)
0335                                 call(wait)
0336 
0337                                 nv_rd32($r13, $r14)
0338                                 and $r9 $r9 $r13
0339 
0340                                 add b32 $r5 1
0341                                 cmp b16 $r5 0x4
0342                                 bra l #memx_func_train_loop_4x
0343 
0344                         add b32 $r10 $r7 #memx_train_head
0345                         st b32 D[$r10 + 0] $r9
0346                         add b32 $r6 1
0347                         add b32 $r7 4
0348 
0349                         cmp b16 $r6 0x10
0350                         bra l #memx_func_train_loop_inner
0351 
0352                 pop $r5
0353                 add b32 $r5 1
0354                 cmp b16 $r5 7
0355                 bra l #memx_func_train_loop_outer
0356 
0357 #endif
0358         ret
0359 
0360 // description
0361 //
0362 // $r15 - current (memx)
0363 // $r14 - sender process name
0364 // $r13 - message (exec)
0365 // $r12 - head of script
0366 // $r11 - tail of script
0367 // $r0  - zero
0368 memx_exec:
0369         push $r14
0370         push $r13
0371         mov b32 $r1 $r12
0372         mov b32 $r2 $r11
0373 
0374         memx_exec_next:
0375                 // fetch the packet header
0376                 ld b32 $r3 D[$r1]
0377                 add b32 $r1 4
0378                 extr $r4 $r3 16:31
0379                 extr $r3 $r3 0:15
0380 
0381                 // execute the opcode handler
0382                 sub b32 $r3 1
0383                 mulu $r3 #memx_func_size
0384                 ld b32 $r5 D[$r3 + #memx_func_head + #memx_func]
0385                 call $r5
0386 
0387                 // keep going, if we haven't reached the end
0388                 cmp b32 $r1 $r2
0389                 bra l #memx_exec_next
0390 
0391         // send completion reply
0392         ld b32 $r11 D[$r0 + #memx_ts_start]
0393         ld b32 $r12 D[$r0 + #memx_ts_end]
0394         sub b32 $r12 $r11
0395         nv_iord($r11, NV_PPWR_INPUT)
0396         pop $r13
0397         pop $r14
0398         call(send)
0399         ret
0400 
0401 // description
0402 //
0403 // $r15 - current (memx)
0404 // $r14 - sender process name
0405 // $r13 - message
0406 // $r12 - data0
0407 // $r11 - data1
0408 // $r0  - zero
0409 memx_info:
0410         cmp b16 $r12 0x1
0411         bra e #memx_info_train
0412 
0413         memx_info_data:
0414         mov $r12 #memx_data_head
0415         mov $r11 #memx_data_tail - #memx_data_head
0416         bra #memx_info_send
0417 
0418         memx_info_train:
0419         mov $r12 #memx_train_head
0420         mov $r11 #memx_train_tail - #memx_train_head
0421 
0422         memx_info_send:
0423         call(send)
0424         ret
0425 
0426 // description
0427 //
0428 // $r15 - current (memx)
0429 // $r14 - sender process name
0430 // $r13 - message
0431 // $r12 - data0
0432 // $r11 - data1
0433 // $r0  - zero
0434 memx_recv:
0435         cmp b32 $r13 MEMX_MSG_EXEC
0436         bra e #memx_exec
0437         cmp b32 $r13 MEMX_MSG_INFO
0438         bra e #memx_info
0439         ret
0440 
0441 // description
0442 //
0443 // $r15 - current (memx)
0444 // $r0  - zero
0445 memx_init:
0446         ret
0447 #endif