1/* 2 * Copyright 2013 Red Hat Inc. 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 21 * 22 * Authors: Ben Skeggs 23 */ 24 25#ifdef INCLUDE_PROC 26process(PROC_MEMX, #memx_init, #memx_recv) 27#endif 28 29/****************************************************************************** 30 * MEMX data segment 31 *****************************************************************************/ 32#ifdef INCLUDE_DATA 33.equ #memx_opcode 0 34.equ #memx_header 2 35.equ #memx_length 4 36.equ #memx_func 8 37 38#define handler(cmd,hdr,len,func) /* 39*/ .b16 MEMX_##cmd /* 40*/ .b16 hdr /* 41*/ .b16 len /* 42*/ .b16 0 /* 43*/ .b32 func 44 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_head 57.equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size 58 59memx_ts_start: 60.b32 0 61memx_ts_end: 62.b32 0 63 64memx_data_head: 65.skip 0x0800 66memx_data_tail: 67 68memx_train_head: 69.skip 0x0100 70memx_train_tail: 71#endif 72 73/****************************************************************************** 74 * MEMX code segment 75 *****************************************************************************/ 76#ifdef INCLUDE_CODE 77// description 78// 79// $r15 - current (memx) 80// $r4 - packet length 81// $r3 - opcode desciption 82// $r0 - zero 83memx_func_enter: 84#if NVKM_PPWR_CHIPSET == GT215 85 mov $r8 0x1610 86 nv_rd32($r7, $r8) 87 imm32($r6, 0xfffffffc) 88 and $r7 $r6 89 mov $r6 0x2 90 or $r7 $r6 91 nv_wr32($r8, $r7) 92#else 93 mov $r6 0x001620 94 imm32($r7, ~0x00000aa2); 95 nv_rd32($r8, $r6) 96 and $r8 $r7 97 nv_wr32($r6, $r8) 98 99 imm32($r7, ~0x00000001) 100 nv_rd32($r8, $r6) 101 and $r8 $r7 102 nv_wr32($r6, $r8) 103 104 mov $r6 0x0026f0 105 nv_rd32($r8, $r6) 106 and $r8 $r7 107 nv_wr32($r6, $r8) 108#endif 109 110 mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE 111 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_PAUSE 115 bra z #memx_func_enter_wait 116 117 nv_iord($r6, NV_PPWR_TIMER_LOW) 118 st b32 D[$r0 + #memx_ts_start] $r6 119 ret 120 121// description 122// 123// $r15 - current (memx) 124// $r4 - packet length 125// $r3 - opcode desciption 126// $r0 - zero 127memx_func_leave: 128 nv_iord($r6, NV_PPWR_TIMER_LOW) 129 st b32 D[$r0 + #memx_ts_end] $r6 130 131 mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE 132 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_PAUSE 136 bra nz #memx_func_leave_wait 137 138#if NVKM_PPWR_CHIPSET == GT215 139 mov $r8 0x1610 140 nv_rd32($r7, $r8) 141 imm32($r6, 0xffffffcc) 142 and $r7 $r6 143 nv_wr32($r8, $r7) 144#else 145 mov $r6 0x0026f0 146 imm32($r7, 0x00000001) 147 nv_rd32($r8, $r6) 148 or $r8 $r7 149 nv_wr32($r6, $r8) 150 151 mov $r6 0x001620 152 nv_rd32($r8, $r6) 153 or $r8 $r7 154 nv_wr32($r6, $r8) 155 156 imm32($r7, 0x00000aa2); 157 nv_rd32($r8, $r6) 158 or $r8 $r7 159 nv_wr32($r6, $r8) 160#endif 161 ret 162 163#if NVKM_PPWR_CHIPSET < GF119 164// description 165// 166// $r15 - current (memx) 167// $r4 - packet length 168// +00: head to wait for vblank on 169// $r3 - opcode desciption 170// $r0 - zero 171memx_func_wait_vblank: 172 ld b32 $r6 D[$r1 + 0x00] 173 cmp b32 $r6 0x0 174 bra z #memx_func_wait_vblank_head0 175 cmp b32 $r6 0x1 176 bra z #memx_func_wait_vblank_head1 177 bra #memx_func_wait_vblank_fini 178 179 memx_func_wait_vblank_head1: 180 mov $r7 0x20 181 bra #memx_func_wait_vblank_0 182 183 memx_func_wait_vblank_head0: 184 mov $r7 0x8 185 186 memx_func_wait_vblank_0: 187 nv_iord($r6, NV_PPWR_INPUT) 188 and $r6 $r7 189 bra nz #memx_func_wait_vblank_0 190 191 memx_func_wait_vblank_1: 192 nv_iord($r6, NV_PPWR_INPUT) 193 and $r6 $r7 194 bra z #memx_func_wait_vblank_1 195 196 memx_func_wait_vblank_fini: 197 add b32 $r1 0x4 198 ret 199 200#else 201 202// XXX: currently no-op 203// 204// $r15 - current (memx) 205// $r4 - packet length 206// +00: head to wait for vblank on 207// $r3 - opcode desciption 208// $r0 - zero 209memx_func_wait_vblank: 210 add b32 $r1 0x4 211 ret 212 213#endif 214 215// description 216// 217// $r15 - current (memx) 218// $r4 - packet length 219// +00*n: addr 220// +04*n: data 221// $r3 - opcode desciption 222// $r0 - zero 223memx_func_wr32: 224 ld b32 $r6 D[$r1 + 0x00] 225 ld b32 $r5 D[$r1 + 0x04] 226 add b32 $r1 0x08 227 nv_wr32($r6, $r5) 228 sub b32 $r4 0x02 229 bra nz #memx_func_wr32 230 ret 231 232// description 233// 234// $r15 - current (memx) 235// $r4 - packet length 236// +00: addr 237// +04: mask 238// +08: data 239// +0c: timeout (ns) 240// $r3 - opcode desciption 241// $r0 - zero 242memx_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 0x10 249 call(wait) 250 ret 251 252// description 253// 254// $r15 - current (memx) 255// $r4 - packet length 256// +00: time (ns) 257// $r3 - opcode desciption 258// $r0 - zero 259memx_func_delay: 260 ld b32 $r14 D[$r1 + 0x00] 261 add b32 $r1 0x04 262 call(nsec) 263 ret 264 265// description 266// 267// $r15 - current (memx) 268// $r4 - packet length 269// $r3 - opcode desciption 270// $r0 - zero 271memx_func_train: 272#if NVKM_PPWR_CHIPSET == GT215 273// $r5 - outer loop counter 274// $r6 - inner loop counter 275// $r7 - entry counter (#memx_train_head + $r7) 276 mov $r5 0x3 277 mov $r7 0x0 278 279// Read random memory to wake up... things 280 imm32($r9, 0x700000) 281 nv_rd32($r8,$r9) 282 mov $r14 0x2710 283 call(nsec) 284 285 memx_func_train_loop_outer: 286 mulu $r8 $r5 0x101 287 sethi $r8 0x02000000 288 imm32($r9, 0x1111e0) 289 nv_wr32($r9, $r8) 290 push $r5 291 292 mov $r6 0x0 293 memx_func_train_loop_inner: 294 mov $r8 0x1111 295 mulu $r9 $r6 $r8 296 shl b32 $r8 $r9 0x10 297 or $r8 $r9 298 imm32($r9, 0x100720) 299 nv_wr32($r9, $r8) 300 301 imm32($r9, 0x100080) 302 nv_rd32($r8, $r9) 303 or $r8 $r8 0x20 304 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 0 313 imm32($r11, 0x001e8480) 314 call(wait) 315 316 // $r5 - inner inner loop counter 317 // $r9 - result 318 mov $r5 0 319 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 $r11 325 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 $r13 334 imm32($r11, 0x00002710) 335 call(wait) 336 337 nv_rd32($r13, $r14) 338 and $r9 $r9 $r13 339 340 add b32 $r5 1 341 cmp b16 $r5 0x4 342 bra l #memx_func_train_loop_4x 343 344 add b32 $r10 $r7 #memx_train_head 345 st b32 D[$r10 + 0] $r9 346 add b32 $r6 1 347 add b32 $r7 4 348 349 cmp b16 $r6 0x10 350 bra l #memx_func_train_loop_inner 351 352 pop $r5 353 add b32 $r5 1 354 cmp b16 $r5 7 355 bra l #memx_func_train_loop_outer 356 357#endif 358 ret 359 360// description 361// 362// $r15 - current (memx) 363// $r14 - sender process name 364// $r13 - message (exec) 365// $r12 - head of script 366// $r11 - tail of script 367// $r0 - zero 368memx_exec: 369 push $r14 370 push $r13 371 mov b32 $r1 $r12 372 mov b32 $r2 $r11 373 374 memx_exec_next: 375 // fetch the packet header 376 ld b32 $r3 D[$r1] 377 add b32 $r1 4 378 extr $r4 $r3 16:31 379 extr $r3 $r3 0:15 380 381 // execute the opcode handler 382 sub b32 $r3 1 383 mulu $r3 #memx_func_size 384 ld b32 $r5 D[$r3 + #memx_func_head + #memx_func] 385 call $r5 386 387 // keep going, if we haven't reached the end 388 cmp b32 $r1 $r2 389 bra l #memx_exec_next 390 391 // send completion reply 392 ld b32 $r11 D[$r0 + #memx_ts_start] 393 ld b32 $r12 D[$r0 + #memx_ts_end] 394 sub b32 $r12 $r11 395 nv_iord($r11, NV_PPWR_INPUT) 396 pop $r13 397 pop $r14 398 call(send) 399 ret 400 401// description 402// 403// $r15 - current (memx) 404// $r14 - sender process name 405// $r13 - message 406// $r12 - data0 407// $r11 - data1 408// $r0 - zero 409memx_info: 410 cmp b16 $r12 0x1 411 bra e #memx_info_train 412 413 memx_info_data: 414 mov $r12 #memx_data_head 415 mov $r11 #memx_data_tail - #memx_data_head 416 bra #memx_info_send 417 418 memx_info_train: 419 mov $r12 #memx_train_head 420 mov $r11 #memx_train_tail - #memx_train_head 421 422 memx_info_send: 423 call(send) 424 ret 425 426// description 427// 428// $r15 - current (memx) 429// $r14 - sender process name 430// $r13 - message 431// $r12 - data0 432// $r11 - data1 433// $r0 - zero 434memx_recv: 435 cmp b32 $r13 MEMX_MSG_EXEC 436 bra e #memx_exec 437 cmp b32 $r13 MEMX_MSG_INFO 438 bra e #memx_info 439 ret 440 441// description 442// 443// $r15 - current (memx) 444// $r0 - zero 445memx_init: 446 ret 447#endif 448