448 lines · plain
1/*2 * Copyright 2013 Red Hat Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: Ben Skeggs23 */24 25#ifdef INCLUDE_PROC26process(PROC_MEMX, #memx_init, #memx_recv)27#endif28 29/******************************************************************************30 * MEMX data segment31 *****************************************************************************/32#ifdef INCLUDE_DATA33.equ #memx_opcode 034.equ #memx_header 235.equ #memx_length 436.equ #memx_func 837 38#define handler(cmd,hdr,len,func) /*39*/ .b16 MEMX_##cmd /*40*/ .b16 hdr /*41*/ .b16 len /*42*/ .b16 0 /*43*/ .b32 func44 45memx_func_head:46handler(ENTER , 0x0000, 0x0000, #memx_func_enter)47memx_func_next:48handler(LEAVE , 0x0000, 0x0000, #memx_func_leave)49handler(WR32 , 0x0000, 0x0002, #memx_func_wr32)50handler(WAIT , 0x0004, 0x0000, #memx_func_wait)51handler(DELAY , 0x0001, 0x0000, #memx_func_delay)52handler(VBLANK, 0x0001, 0x0000, #memx_func_wait_vblank)53handler(TRAIN , 0x0000, 0x0000, #memx_func_train)54memx_func_tail:55 56.equ #memx_func_size #memx_func_next - #memx_func_head57.equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size58 59memx_ts_start:60.b32 061memx_ts_end:62.b32 063 64memx_data_head:65.skip 0x080066memx_data_tail:67 68memx_train_head:69.skip 0x010070memx_train_tail:71#endif72 73/******************************************************************************74 * MEMX code segment75 *****************************************************************************/76#ifdef INCLUDE_CODE77// description78//79// $r15 - current (memx)80// $r4 - packet length81// $r3 - opcode desciption82// $r0 - zero83memx_func_enter:84#if NVKM_PPWR_CHIPSET == GT21585 mov $r8 0x161086 nv_rd32($r7, $r8)87 imm32($r6, 0xfffffffc)88 and $r7 $r689 mov $r6 0x290 or $r7 $r691 nv_wr32($r8, $r7)92#else93 mov $r6 0x00162094 imm32($r7, ~0x00000aa2);95 nv_rd32($r8, $r6)96 and $r8 $r797 nv_wr32($r6, $r8)98 99 imm32($r7, ~0x00000001)100 nv_rd32($r8, $r6)101 and $r8 $r7102 nv_wr32($r6, $r8)103 104 mov $r6 0x0026f0105 nv_rd32($r8, $r6)106 and $r8 $r7107 nv_wr32($r6, $r8)108#endif109 110 mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE111 nv_iowr(NV_PPWR_OUTPUT_SET, $r6)112 memx_func_enter_wait:113 nv_iord($r6, NV_PPWR_OUTPUT)114 and $r6 NV_PPWR_OUTPUT_FB_PAUSE115 bra z #memx_func_enter_wait116 117 nv_iord($r6, NV_PPWR_TIMER_LOW)118 st b32 D[$r0 + #memx_ts_start] $r6119 ret120 121// description122//123// $r15 - current (memx)124// $r4 - packet length125// $r3 - opcode desciption126// $r0 - zero127memx_func_leave:128 nv_iord($r6, NV_PPWR_TIMER_LOW)129 st b32 D[$r0 + #memx_ts_end] $r6130 131 mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE132 nv_iowr(NV_PPWR_OUTPUT_CLR, $r6)133 memx_func_leave_wait:134 nv_iord($r6, NV_PPWR_OUTPUT)135 and $r6 NV_PPWR_OUTPUT_FB_PAUSE136 bra nz #memx_func_leave_wait137 138#if NVKM_PPWR_CHIPSET == GT215139 mov $r8 0x1610140 nv_rd32($r7, $r8)141 imm32($r6, 0xffffffcc)142 and $r7 $r6143 nv_wr32($r8, $r7)144#else145 mov $r6 0x0026f0146 imm32($r7, 0x00000001)147 nv_rd32($r8, $r6)148 or $r8 $r7149 nv_wr32($r6, $r8)150 151 mov $r6 0x001620152 nv_rd32($r8, $r6)153 or $r8 $r7154 nv_wr32($r6, $r8)155 156 imm32($r7, 0x00000aa2);157 nv_rd32($r8, $r6)158 or $r8 $r7159 nv_wr32($r6, $r8)160#endif161 ret162 163#if NVKM_PPWR_CHIPSET < GF119164// description165//166// $r15 - current (memx)167// $r4 - packet length168// +00: head to wait for vblank on169// $r3 - opcode desciption170// $r0 - zero171memx_func_wait_vblank:172 ld b32 $r6 D[$r1 + 0x00]173 cmp b32 $r6 0x0174 bra z #memx_func_wait_vblank_head0175 cmp b32 $r6 0x1176 bra z #memx_func_wait_vblank_head1177 bra #memx_func_wait_vblank_fini178 179 memx_func_wait_vblank_head1:180 mov $r7 0x20181 bra #memx_func_wait_vblank_0182 183 memx_func_wait_vblank_head0:184 mov $r7 0x8185 186 memx_func_wait_vblank_0:187 nv_iord($r6, NV_PPWR_INPUT)188 and $r6 $r7189 bra nz #memx_func_wait_vblank_0190 191 memx_func_wait_vblank_1:192 nv_iord($r6, NV_PPWR_INPUT)193 and $r6 $r7194 bra z #memx_func_wait_vblank_1195 196 memx_func_wait_vblank_fini:197 add b32 $r1 0x4198 ret199 200#else201 202// XXX: currently no-op203//204// $r15 - current (memx)205// $r4 - packet length206// +00: head to wait for vblank on207// $r3 - opcode desciption208// $r0 - zero209memx_func_wait_vblank:210 add b32 $r1 0x4211 ret212 213#endif214 215// description216//217// $r15 - current (memx)218// $r4 - packet length219// +00*n: addr220// +04*n: data221// $r3 - opcode desciption222// $r0 - zero223memx_func_wr32:224 ld b32 $r6 D[$r1 + 0x00]225 ld b32 $r5 D[$r1 + 0x04]226 add b32 $r1 0x08227 nv_wr32($r6, $r5)228 sub b32 $r4 0x02229 bra nz #memx_func_wr32230 ret231 232// description233//234// $r15 - current (memx)235// $r4 - packet length236// +00: addr237// +04: mask238// +08: data239// +0c: timeout (ns)240// $r3 - opcode desciption241// $r0 - zero242memx_func_wait:243 nv_iord($r8, NV_PPWR_TIMER_LOW)244 ld b32 $r14 D[$r1 + 0x00]245 ld b32 $r13 D[$r1 + 0x04]246 ld b32 $r12 D[$r1 + 0x08]247 ld b32 $r11 D[$r1 + 0x0c]248 add b32 $r1 0x10249 call(wait)250 ret251 252// description253//254// $r15 - current (memx)255// $r4 - packet length256// +00: time (ns)257// $r3 - opcode desciption258// $r0 - zero259memx_func_delay:260 ld b32 $r14 D[$r1 + 0x00]261 add b32 $r1 0x04262 call(nsec)263 ret264 265// description266//267// $r15 - current (memx)268// $r4 - packet length269// $r3 - opcode desciption270// $r0 - zero271memx_func_train:272#if NVKM_PPWR_CHIPSET == GT215273// $r5 - outer loop counter274// $r6 - inner loop counter275// $r7 - entry counter (#memx_train_head + $r7)276 mov $r5 0x3277 mov $r7 0x0278 279// Read random memory to wake up... things280 imm32($r9, 0x700000)281 nv_rd32($r8,$r9)282 mov $r14 0x2710283 call(nsec)284 285 memx_func_train_loop_outer:286 mulu $r8 $r5 0x101287 sethi $r8 0x02000000288 imm32($r9, 0x1111e0)289 nv_wr32($r9, $r8)290 push $r5291 292 mov $r6 0x0293 memx_func_train_loop_inner:294 mov $r8 0x1111295 mulu $r9 $r6 $r8296 shl b32 $r8 $r9 0x10297 or $r8 $r9298 imm32($r9, 0x100720)299 nv_wr32($r9, $r8)300 301 imm32($r9, 0x100080)302 nv_rd32($r8, $r9)303 or $r8 $r8 0x20304 nv_wr32($r9, $r8)305 306 imm32($r9, 0x10053c)307 imm32($r8, 0x80003002)308 nv_wr32($r9, $r8)309 310 imm32($r14, 0x100560)311 imm32($r13, 0x80000000)312 add b32 $r12 $r13 0313 imm32($r11, 0x001e8480)314 call(wait)315 316 // $r5 - inner inner loop counter317 // $r9 - result318 mov $r5 0319 imm32($r9, 0x8300ffff)320 memx_func_train_loop_4x:321 imm32($r10, 0x100080)322 nv_rd32($r8, $r10)323 imm32($r11, 0xffffffdf)324 and $r8 $r11325 nv_wr32($r10, $r8)326 327 imm32($r10, 0x10053c)328 imm32($r8, 0x80003002)329 nv_wr32($r10, $r8)330 331 imm32($r14, 0x100560)332 imm32($r13, 0x80000000)333 mov b32 $r12 $r13334 imm32($r11, 0x00002710)335 call(wait)336 337 nv_rd32($r13, $r14)338 and $r9 $r9 $r13339 340 add b32 $r5 1341 cmp b16 $r5 0x4342 bra l #memx_func_train_loop_4x343 344 add b32 $r10 $r7 #memx_train_head345 st b32 D[$r10 + 0] $r9346 add b32 $r6 1347 add b32 $r7 4348 349 cmp b16 $r6 0x10350 bra l #memx_func_train_loop_inner351 352 pop $r5353 add b32 $r5 1354 cmp b16 $r5 7355 bra l #memx_func_train_loop_outer356 357#endif358 ret359 360// description361//362// $r15 - current (memx)363// $r14 - sender process name364// $r13 - message (exec)365// $r12 - head of script366// $r11 - tail of script367// $r0 - zero368memx_exec:369 push $r14370 push $r13371 mov b32 $r1 $r12372 mov b32 $r2 $r11373 374 memx_exec_next:375 // fetch the packet header376 ld b32 $r3 D[$r1]377 add b32 $r1 4378 extr $r4 $r3 16:31379 extr $r3 $r3 0:15380 381 // execute the opcode handler382 sub b32 $r3 1383 mulu $r3 #memx_func_size384 ld b32 $r5 D[$r3 + #memx_func_head + #memx_func]385 call $r5386 387 // keep going, if we haven't reached the end388 cmp b32 $r1 $r2389 bra l #memx_exec_next390 391 // send completion reply392 ld b32 $r11 D[$r0 + #memx_ts_start]393 ld b32 $r12 D[$r0 + #memx_ts_end]394 sub b32 $r12 $r11395 nv_iord($r11, NV_PPWR_INPUT)396 pop $r13397 pop $r14398 call(send)399 ret400 401// description402//403// $r15 - current (memx)404// $r14 - sender process name405// $r13 - message406// $r12 - data0407// $r11 - data1408// $r0 - zero409memx_info:410 cmp b16 $r12 0x1411 bra e #memx_info_train412 413 memx_info_data:414 mov $r12 #memx_data_head415 mov $r11 #memx_data_tail - #memx_data_head416 bra #memx_info_send417 418 memx_info_train:419 mov $r12 #memx_train_head420 mov $r11 #memx_train_tail - #memx_train_head421 422 memx_info_send:423 call(send)424 ret425 426// description427//428// $r15 - current (memx)429// $r14 - sender process name430// $r13 - message431// $r12 - data0432// $r11 - data1433// $r0 - zero434memx_recv:435 cmp b32 $r13 MEMX_MSG_EXEC436 bra e #memx_exec437 cmp b32 $r13 MEMX_MSG_INFO438 bra e #memx_info439 ret440 441// description442//443// $r15 - current (memx)444// $r0 - zero445memx_init:446 ret447#endif448