1/* fuc microcode util functions for nvc0 PGRAPH 2 * 3 * Copyright 2011 Red Hat Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: Ben Skeggs 24 */ 25 26define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)') 27define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))') 28 29ifdef(`include_code', ` 30// Error codes 31define(`E_BAD_COMMAND', 0x01) 32define(`E_CMD_OVERFLOW', 0x02) 33 34// Util macros to help with debugging ucode hangs etc 35define(`T_WAIT', 0) 36define(`T_MMCTX', 1) 37define(`T_STRWAIT', 2) 38define(`T_STRINIT', 3) 39define(`T_AUTO', 4) 40define(`T_CHAN', 5) 41define(`T_LOAD', 6) 42define(`T_SAVE', 7) 43define(`T_LCHAN', 8) 44define(`T_LCTXH', 9) 45 46define(`trace_set', ` 47 mov $r8 0x83c 48 shl b32 $r8 6 49 clear b32 $r9 50 bset $r9 $1 51 iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] 52') 53 54define(`trace_clr', ` 55 mov $r8 0x85c 56 shl b32 $r8 6 57 clear b32 $r9 58 bset $r9 $1 59 iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] 60') 61 62// queue_put - add request to queue 63// 64// In : $r13 queue pointer 65// $r14 command 66// $r15 data 67// 68queue_put: 69 // make sure we have space.. 70 ld b32 $r8 D[$r13 + 0x0] // GET 71 ld b32 $r9 D[$r13 + 0x4] // PUT 72 xor $r8 8 73 cmpu b32 $r8 $r9 74 bra ne #queue_put_next 75 mov $r15 E_CMD_OVERFLOW 76 call #error 77 ret 78 79 // store cmd/data on queue 80 queue_put_next: 81 and $r8 $r9 7 82 shl b32 $r8 3 83 add b32 $r8 $r13 84 add b32 $r8 8 85 st b32 D[$r8 + 0x0] $r14 86 st b32 D[$r8 + 0x4] $r15 87 88 // update PUT 89 add b32 $r9 1 90 and $r9 0xf 91 st b32 D[$r13 + 0x4] $r9 92 ret 93 94// queue_get - fetch request from queue 95// 96// In : $r13 queue pointer 97// 98// Out: $p1 clear on success (data available) 99// $r14 command 100// $r15 data 101// 102queue_get: 103 bset $flags $p1 104 ld b32 $r8 D[$r13 + 0x0] // GET 105 ld b32 $r9 D[$r13 + 0x4] // PUT 106 cmpu b32 $r8 $r9 107 bra e #queue_get_done 108 // fetch first cmd/data pair 109 and $r9 $r8 7 110 shl b32 $r9 3 111 add b32 $r9 $r13 112 add b32 $r9 8 113 ld b32 $r14 D[$r9 + 0x0] 114 ld b32 $r15 D[$r9 + 0x4] 115 116 // update GET 117 add b32 $r8 1 118 and $r8 0xf 119 st b32 D[$r13 + 0x0] $r8 120 bclr $flags $p1 121queue_get_done: 122 ret 123 124// nv_rd32 - read 32-bit value from nv register 125// 126// In : $r14 register 127// Out: $r15 value 128// 129nv_rd32: 130 mov $r11 0x728 131 shl b32 $r11 6 132 mov b32 $r12 $r14 133 bset $r12 31 // MMIO_CTRL_PENDING 134 iowr I[$r11 + 0x000] $r12 // MMIO_CTRL 135 nv_rd32_wait: 136 iord $r12 I[$r11 + 0x000] 137 xbit $r12 $r12 31 138 bra ne #nv_rd32_wait 139 mov $r10 6 // DONE_MMIO_RD 140 call #wait_doneo 141 iord $r15 I[$r11 + 0x100] // MMIO_RDVAL 142 ret 143 144// nv_wr32 - write 32-bit value to nv register 145// 146// In : $r14 register 147// $r15 value 148// 149nv_wr32: 150 mov $r11 0x728 151 shl b32 $r11 6 152 iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL 153 mov b32 $r12 $r14 154 bset $r12 31 // MMIO_CTRL_PENDING 155 bset $r12 30 // MMIO_CTRL_WRITE 156 iowr I[$r11 + 0x000] $r12 // MMIO_CTRL 157 nv_wr32_wait: 158 iord $r12 I[$r11 + 0x000] 159 xbit $r12 $r12 31 160 bra ne #nv_wr32_wait 161 ret 162 163// (re)set watchdog timer 164// 165// In : $r15 timeout 166// 167watchdog_reset: 168 mov $r8 0x430 169 shl b32 $r8 6 170 bset $r15 31 171 iowr I[$r8 + 0x000] $r15 172 ret 173 174// clear watchdog timer 175watchdog_clear: 176 mov $r8 0x430 177 shl b32 $r8 6 178 iowr I[$r8 + 0x000] $r0 179 ret 180 181// wait_done{z,o} - wait on FUC_DONE bit to become clear/set 182// 183// In : $r10 bit to wait on 184// 185define(`wait_done', ` 186$1: 187 trace_set(T_WAIT); 188 mov $r8 0x818 189 shl b32 $r8 6 190 iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit 191 wait_done_$1: 192 mov $r8 0x400 193 shl b32 $r8 6 194 iord $r8 I[$r8 + 0x000] // DONE 195 xbit $r8 $r8 $r10 196 bra $2 #wait_done_$1 197 trace_clr(T_WAIT) 198 ret 199') 200wait_done(wait_donez, ne) 201wait_done(wait_doneo, e) 202 203// mmctx_size - determine size of a mmio list transfer 204// 205// In : $r14 mmio list head 206// $r15 mmio list tail 207// Out: $r15 transfer size (in bytes) 208// 209mmctx_size: 210 clear b32 $r9 211 nv_mmctx_size_loop: 212 ld b32 $r8 D[$r14] 213 shr b32 $r8 26 214 add b32 $r8 1 215 shl b32 $r8 2 216 add b32 $r9 $r8 217 add b32 $r14 4 218 cmpu b32 $r14 $r15 219 bra ne #nv_mmctx_size_loop 220 mov b32 $r15 $r9 221 ret 222 223// mmctx_xfer - execute a list of mmio transfers 224// 225// In : $r10 flags 226// bit 0: direction (0 = save, 1 = load) 227// bit 1: set if first transfer 228// bit 2: set if last transfer 229// $r11 base 230// $r12 mmio list head 231// $r13 mmio list tail 232// $r14 multi_stride 233// $r15 multi_mask 234// 235mmctx_xfer: 236 trace_set(T_MMCTX) 237 mov $r8 0x710 238 shl b32 $r8 6 239 clear b32 $r9 240 or $r11 $r11 241 bra e #mmctx_base_disabled 242 iowr I[$r8 + 0x000] $r11 // MMCTX_BASE 243 bset $r9 0 // BASE_EN 244 mmctx_base_disabled: 245 or $r14 $r14 246 bra e #mmctx_multi_disabled 247 iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE 248 iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK 249 bset $r9 1 // MULTI_EN 250 mmctx_multi_disabled: 251 add b32 $r8 0x100 252 253 xbit $r11 $r10 0 254 shl b32 $r11 16 // DIR 255 bset $r11 12 // QLIMIT = 0x10 256 xbit $r14 $r10 1 257 shl b32 $r14 17 258 or $r11 $r14 // START_TRIGGER 259 iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL 260 261 // loop over the mmio list, and send requests to the hw 262 mmctx_exec_loop: 263 // wait for space in mmctx queue 264 mmctx_wait_free: 265 iord $r14 I[$r8 + 0x000] // MMCTX_CTRL 266 and $r14 0x1f 267 bra e #mmctx_wait_free 268 269 // queue up an entry 270 ld b32 $r14 D[$r12] 271 or $r14 $r9 272 iowr I[$r8 + 0x300] $r14 273 add b32 $r12 4 274 cmpu b32 $r12 $r13 275 bra ne #mmctx_exec_loop 276 277 xbit $r11 $r10 2 278 bra ne #mmctx_stop 279 // wait for queue to empty 280 mmctx_fini_wait: 281 iord $r11 I[$r8 + 0x000] // MMCTX_CTRL 282 and $r11 0x1f 283 cmpu b32 $r11 0x10 284 bra ne #mmctx_fini_wait 285 mov $r10 2 // DONE_MMCTX 286 call #wait_donez 287 bra #mmctx_done 288 mmctx_stop: 289 xbit $r11 $r10 0 290 shl b32 $r11 16 // DIR 291 bset $r11 12 // QLIMIT = 0x10 292 bset $r11 18 // STOP_TRIGGER 293 iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL 294 mmctx_stop_wait: 295 // wait for STOP_TRIGGER to clear 296 iord $r11 I[$r8 + 0x000] // MMCTX_CTRL 297 xbit $r11 $r11 18 298 bra ne #mmctx_stop_wait 299 mmctx_done: 300 trace_clr(T_MMCTX) 301 ret 302 303// Wait for DONE_STRAND 304// 305strand_wait: 306 push $r10 307 mov $r10 2 308 call #wait_donez 309 pop $r10 310 ret 311 312// unknown - call before issuing strand commands 313// 314strand_pre: 315 mov $r8 0x4afc 316 sethi $r8 0x20000 317 mov $r9 0xc 318 iowr I[$r8] $r9 319 call #strand_wait 320 ret 321 322// unknown - call after issuing strand commands 323// 324strand_post: 325 mov $r8 0x4afc 326 sethi $r8 0x20000 327 mov $r9 0xd 328 iowr I[$r8] $r9 329 call #strand_wait 330 ret 331 332// Selects strand set?! 333// 334// In: $r14 id 335// 336strand_set: 337 mov $r10 0x4ffc 338 sethi $r10 0x20000 339 sub b32 $r11 $r10 0x500 340 mov $r12 0xf 341 iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf 342 mov $r12 0xb 343 iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb 344 call #strand_wait 345 iowr I[$r10 + 0x000] $r14 // 0x93c = <id> 346 mov $r12 0xa 347 iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa 348 call #strand_wait 349 ret 350 351// Initialise strand context data 352// 353// In : $r15 context base 354// Out: $r15 context size (in bytes) 355// 356// Strandset(?) 3 hardcoded currently 357// 358strand_ctx_init: 359 trace_set(T_STRINIT) 360 call #strand_pre 361 mov $r14 3 362 call #strand_set 363 mov $r10 0x46fc 364 sethi $r10 0x20000 365 add b32 $r11 $r10 0x400 366 iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 367 mov $r12 1 368 iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE 369 call #strand_wait 370 sub b32 $r12 $r0 1 371 iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff 372 mov $r12 2 373 iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT 374 call #strand_wait 375 call #strand_post 376 377 // read the size of each strand, poke the context offset of 378 // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry 379 // about it later then. 380 mov $r8 0x880 381 shl b32 $r8 6 382 iord $r9 I[$r8 + 0x000] // STRANDS 383 add b32 $r8 0x2200 384 shr b32 $r14 $r15 8 385 ctx_init_strand_loop: 386 iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE 387 iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE 388 iord $r10 I[$r8 + 0x200] // STRAND_SIZE 389 shr b32 $r10 6 390 add b32 $r10 1 391 add b32 $r14 $r10 392 add b32 $r8 4 393 sub b32 $r9 1 394 bra ne #ctx_init_strand_loop 395 396 shl b32 $r14 8 397 sub b32 $r15 $r14 $r15 398 trace_clr(T_STRINIT) 399 ret 400') 401