1/****************************************************************************** 2 * Copyright (c) 2004, 2008 IBM Corporation 3 * All rights reserved. 4 * This program and the accompanying materials 5 * are made available under the terms of the BSD License 6 * which accompanies this distribution, and is available at 7 * http://www.opensource.org/licenses/bsd-license.php 8 * 9 * Contributors: 10 * IBM Corporation - initial implementation 11 *****************************************************************************/ 12 13# SLOF for JS20/JS21 -- ROM boot code. 14# Initial entry point, copy code from flash to cache, memory setup. 15# Also sets up serial console and optimizes some settings. 16 17#include "termctrl.h" 18#include <product.h> 19#include <xvect.h> 20#include <cpu.h> 21#include <macros.h> 22#include <southbridge.h> 23 24 .text 25 .globl __start 26__start: 27 /* put rombase in sprg1 ***********************/ 28 29 bl postHeader 30 .long 0xDEADBEE0 31 .long 0x0 /* size */ 32 .long 0x0 /* crc */ 33 .long relTag - __start 34postHeader: 35 mflr r3 36 li r4, 0x7fff 37 not r4, r4 38 and r3, r3, r4 39 mtsprg 1, r3 /* romfs base */ 40 bl _start 41 42 .org 0x150 - 0x100 43__startSlave: 44 bl setup_cpu 45 bl set_ci_bit 46# b slaveWithNumber 47 b slave 48 49 .org 0x180 - 0x100 50__startMaster: 51 li 3,0 52 mtsprg 1, r3 /* romfs base */ 53 bl setup_cpu 54 bl set_ci_bit 55 b master 56 57 58 /* FIXME: Also need 0280, 0380, 0f20, etc. */ 59 60 .irp i, 0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,0x0400,0x0500,0x0600,0x0700, \ 61 0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \ 62 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \ 63 0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \ 64 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \ 65 0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00 66 . = \i 67 68 /* enable this if you get exceptions before the console works */ 69 /* this will allow using the hardware debugger to see where */ 70 /* it traps, and with what register values etc. */ 71 // b $ 72 73 mtsprg 0, r0 74 mfctr r0 75 mtsprg 2,r0 76 mflr r0 77// 10 78 mtsprg 3,r0 79 ld r0, (\i + 0x160)(0) 80 mtctr r0 81 li r0, \i + 0x100 82// 20 83 bctr 84 85 . = \i + 0x60 86 87 .quad intHandler2C 88 89 .endr 90 91 92 . = XVECT_M_HANDLER - 0x100 93 .quad 0x00 94 . = XVECT_S_HANDLER - 0x100 95 96 .quad 0 97 98 99 100 .org 0x4000 - 0x100 101_start: 102 # optimize HID register settings 103 bl setup_cpu 104 bl set_ci_bit 105 106 # read semaphore, run as slave if not the first to do so 107 li 3,0 ; oris 3,3,0xf800 ; lwz 3,0x60(3) ; andi. 3,3,1 ; beq slave 108master: 109 # setup flash, serial 110 bl setup_sio 111 112 # early greet 113 li r3, 10 114 bl putc 115 li 3,13 ; bl putc ; li 3,10 ; bl putc ; li 3,'S' ; bl putc 116 117 118 #do we run from ram ? 119 mfsprg r3, 1 /* rombase */ 120 cmpdi r3,0 /* rombase is 0 when running from RAM */ 121 122 bne copy_to_cache 123 124 # wait a bit, start scripts are slow... need to get all cores running! 125 lis 3,0x4000 ; mtctr 3 ; bdnz $ 126 127 # copy 4MB from 0 to temp memory 128 lis 4,0x8 ; mtctr 4 ; lis 4,0x200 ; li 3,0 ; addi 4,4,-8 ; addi 3,3,-8 1290: ldu 5,8(3) ; stdu 5,8(4) ; bdnz 0b 130 131 lis 4,0x200 132 mtsprg 1, r4 133 134 lis 4,0x1 135 lis 3,0x20 ; addi 3,3,0x200-8 ; 136 FLUSH_CACHE(r3, r4) 137 138 lis 4,0x200 139 addi 4,4,copy_to_cache@l 140 mtctr 4 141 bctr 142 143# make all data accesses cache-inhibited 144set_ci_bit: 145 SETCI(r0) 146 blr 147 148# make all data accesses cacheable 149clr_ci_bit: 150 CLRCI(r0) 151 blr 152 153# write a character to the serial port 154putc: 155# always write to serial1 1560: lbz 0,5(13) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(13) ; eieio 157 158# read ID register: only if it is a PC87427 (JS21) also use serial2 159 li 4,0 ; oris 4,4,0xf400 160 li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4); cmpdi 5,0xf2 ; bne 1f 161 162 addi 4,4,0x2f8 1630: lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio 164 1651: blr 166 167# transfer from running from flash to running from cache 168return_cacheable: 169 # find and set address to start running from cache, set msr value 170 mflr 3 ; rldicl 3,3,0,44 171jump_cacheable: 172 mtsrr0 3 ; 173 mfmsr 3 ; ori 3,3,0x1000 ; mtsrr1 3 # enable MCE, as well 174 175 # set cacheable insn fetches, jump to cache 176 mfspr 3,HID1 ; rldicl 3,3,32,0 ; oris 3,3,0x0020 ; rldicl 3,3,32,0 177 sync ; mtspr HID1,3 ; mtspr HID1,3 ; rfid ; b . 178 179 180 181 182copy_to_cache: 183 # zero the whole cache 184 # also, invalidate the insn cache, to clear parity errors 185 # 128kB @ 0MB (boot code and vectors from 0x0 up to 0x20000) 186 li 4,0x400 ; mtctr 4 ; li 5,0x0 ; bl clr_ci_bit 1870: dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b 188 189 # 0x2000 to 0x100000/0x80000 (smaller on 970/970FX) 190 li 4,0x1C00 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0xC00 1910: 192 mtctr 4 ; li 5,0x2000 1930: dcbz 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b ; bl set_ci_bit 194 195 # find base address 196 bcl 20,31,$+4 ; mflr 31 ; rldicr 31,31,0,43 197 198 # copy 1kB from 0x4000 199 li 4,0x80 ; mtctr 4 ; 200 li 5,0x3ff8 201 addi 3,31,0x3ff8 2020: ldu 4,8(3) ; bl clr_ci_bit ; stdu 4,8(5) ; bl set_ci_bit ; bdnz 0b 203 # now start executing from cache -- insn cache is huge speed boost 204 205 bl return_cacheable 206 207 li 3,'L' ; bl putc 208 209 # copy 128kB of flash to cache 210 li 4,0x800 ; mtctr 4 ; li 5,0x200-64 ; addi 3,31,0x200-64 ; 2110: ldu 16,64(3) ; ld 17,8(3) ; ld 18,16(3) ; ld 19,24(3) 212 ld 20,32(3) ; ld 21,40(3) ; ld 22,48(3) ; ld 23,56(3) 213 bl clr_ci_bit 214 stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5) 215 std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5) 216 icbi 0,5 ; bl set_ci_bit ; bdnz 0b ; isync 217 218 219 li 3,'O' ; bl putc 220 221 lis 4,0x20 222 mfsprg r3,1 223 cmpd r3,r4 224 beq 1f 225 226 // at 0xf8000000 we decide if it is u3 or u4 227 li 4,0 ; oris 4,4,0xf800 ; lwz 3,0(4) ; srdi 3,3,4 ; cmpdi 3,3 ; bne 0f 228 bl setup_mem_u3 229 bl setup_mem_size 230 b 1f 2310: 232 2331: 234 li 3,'F' ; bl putc 235 236 # setup nvram logging only when not running from RAM 237 mfsprg r3, 1 /* rombase */ 238 cmpdi r3, 0 /* rombase is 0 when running from RAM */ 239 beq 0f 240 241 // at 0xf8000000 we decide if it is u3 or u4 242 li r4, 0 243 oris r4, r4, 0xf800 244 lwz r3, 0(r4) 245 srdi r3, r3, 4 246 cmpdi r3, 3 /* 3 means js20; no nvram logging on js20 */ 247 beq 0f 248 249 bl io_log_init 2500: 251 252 #bl print_mem 253 254 # data is cacheable by default from now on 255 bl clr_ci_bit 256 257 258 /* give live sign *****************************/ 259 bl 0f 260 .ascii TERM_CTRL_RESET 261 .ascii TERM_CTRL_CRSOFF 262 .ascii " **********************************************************************" 263 .ascii "\r\n" 264 .ascii TERM_CTRL_BRIGHT 265 .ascii PRODUCT_NAME 266 .ascii " Starting\r\n" 267 .ascii TERM_CTRL_RESET 268 .ascii " Build Date = ", __DATE__, " ", __TIME__ 269 .ascii "\r\n" 270 .ascii " FW Version = " , RELEASE 271 .ascii "\r\n\0" 272 .align 2 2730: mflr r3 274 bl io_print 275 276 # go! 277 li r3,__startC@l 278 mtctr r3 279 mfsprg r10, 1 280 bctrl 281 282relTag: 283 .ascii RELEASE 284 .ascii "\0" 285 .align 2 286 287slave: 288 289 # get cpu number 290 li 3,0 ; oris 3,3,0xf800 ; lwz 28,0x50(3) 291 292slaveWithNumber: 293 # create our slave loop address 294 sldi 3,28,24 ; oris 3,3,0x3000 295 296 # invalidate the insn cache, to clear parity errors 297 # clear the L2 cache as well, to get ECC right 298 li 4,0x2000 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0x1000 2990: mtctr 4 ; mr 5,3 ; bl clr_ci_bit 300 3010: dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b 302 303 304 # write a "b $" insn in there 305 lis 4,0x4800 ; stw 4,0(3) 306/* 307 mr 5,3 308 309 # jump there 310 bl set_ci_bit 311 li 13,0 ; oris 13,13,0xf400 312 # device address 313 addi 13,13,0x2f8 314 li 3,'O' ; add 3,3,28 ; bl putc 315 bl clr_ci_bit 316 mr 3,5 317*/ 318 b jump_cacheable 319 320 321 322 323# allow the flash chip to be accessed faster 324# initialize the 16550-compatible uart on serial port 1 of the sio 325setup_sio: 326 327 # i/o base address 328 li 3,0 ; oris 3,3,0xf400 329 330 # i/o base address 331 li 3,0 ; oris 3,3,0xf400 332 333 # put x-bus in turbo mode 334 li 4,0xf1 ; stb 4,0x400(3) ; eieio 335 336 337 # select sio serial1 338 li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio 339 340 # set base address to 3f8 341 li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio 342 343 # enable device 344 li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio 345 346 # read ID register: only if it is a PC87427, enable serial2 347 li 4,0x20 ; stb 4,0x2e(3) ; eieio ; lbz 4,0x2f(3) ; cmpdi 4,0xf2 ; bne 0f 348 349 # select sio serial2 350 li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio 351 352 # set base address to 2f8 353 li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio 354 355 # enable device 356 li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio 357 358 # uart @0x2f8 359 addi 3,3,0x2f8 360 361 # disable interrupts, fifo off 362 li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio 363 364 # set serial speed 365 li 4,0x80 ; stb 4,3(3) ; eieio 366 li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio 367 368 # set 8-N-1, set RTS and DTR 369 li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio 370 371 eieio 372 373 addi 3,3,-0x2f8 374 375 # uart @0x3f8 3760: addi 3,3,0x3f8 377 378 # disable interrupts, fifo off 379 li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio 380 381 # set serial speed 382 li 4,0x80 ; stb 4,3(3) ; eieio 383 li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio 384 385 # set 8-N-1, set RTS and DTR 386 li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio 387 388 eieio 389 390 # save UART base for putc routine 3910: mr 13,3 392 393 blr 394 395 396 397 398# set the HID registers of the 970 for optimally executing from flash 399setup_cpu: 400 401 /* clear all the HV cruft */ 402 li r0, 0 403 sync 404 mtspr HID4, r0 405 isync 406 407 /* enable dpm, disable attn insn, enable external mce 408 * first, try external time base; if clock doesn't run, switch to 409 * internal */ 410 li r0, 1 /* do the setup for external timebase */ 411 rldicl r0, r0, 44, 0 /* bit 19 has to be set */ 412 oris r0, r0, 0x8000 /* Enable external machine check */ 413 /* interrupts (preferred state */ 414 /* equals `1'). */ 415 sync 416 mtspr HID0, r0 417 isync 418 419 mftb r3 /* read the timebase */ 420 li r1, 0x4000 /* wait long enough for the external */ 421 mtctr r1 /* timebase (14MHz) to tick a bit */ 422 bdnz $ /* 0x4000 seems to be enough (for now) */ 423 mftb r4 /* read the timebase a second time */ 424 cmpld r3, r4 /* see if it changed */ 425 bne 0f 426 /* timebase did not change, do the setup for internal */ 427 rldicl r0, r0, 19, 1 428 rldicl r0, r0, 45, 0 429 sync 430 mtspr HID0, r0 431 isync 432 4330: 434 /* enable insn prefetch, speculative table walks */ 435 mfspr r0, HID1 436 rldicl r0, r0, 20, 0 437 ori r0, r0, 0x1002 438 mfsprg r3, 1 /* read rombase */ 439 cmpdi r3, 0 /* check if running from ram */ 440 bne 0f 441 /* running from ram */ 442 /* Enable instruction fetch cacheability control */ 443 ori r0, r0, 0x200 4440: 445 rldicl r0, r0, 44, 0 446 sync 447 mtspr HID1, r0 448 isync 449 450 /* enable cache parity */ 451 mfspr r0, HID4 452 oris r0, r0, 0xfff0 453 xoris r0, r0, 0xfff0 454 sync 455 mtspr HID4, r0 456 isync 457 458 /* exception offset at 0 */ 459 li r3, 0 460 mtspr HIOR, r3 461 462 blr 463 464C_ENTRY(proceedInterrupt) 465 466 ld r3,exception_stack_frame@got(r2) 467 ld r1,0(r3) 468 469 .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ 470 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ 471 27, 28, 29, 30, 31 472 ld r\i, 0x30+\i*8 (r1) 473 .endr 474 475 ld r14,0x138(r1); 476 mtsrr0 r14 477 478 ld r14,0x140(r1); 479 mtsrr1 r14 480 481 ld r14,0x148(r1); 482 mtcr r14 483 484 485 ld 0,XVECT_M_HANDLER(0) 486 mtctr 0 487 488 ld r0,0x30(r1); # restore vector number 489 ld r1,0x38(r1); 490 491 bctr 492 493intHandler2C: 494 mtctr r1 # save old stack pointer 495 lis r1,0x4 496 stdu r1, -0x160(r1) 497 .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ 498 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ 499 27, 28, 29, 30, 31 500 std r\i, 0x30+\i*8 (r1) 501 .endr 502 503 std r0,0x30(r1); # save vector number 504 505 mfctr r14 506 std r14,0x38(r1); # save old r1 507 508 mfsrr0 r14 509 std r14,0x138(r1); 510 511 mfsrr1 r14 512 std r14,0x140(r1); 513 514 mfcr r14 515 std r14,0x148(r1); 516 517 mfxer r14 518 std r14,0x150(r1); 519 520 bl toc_init 521 522 ld r3,exception_stack_frame@got(r2) 523 std r1,0(r3) 524 525 526 mr r3,r0 527 bl .c_interrupt 528 529 ld r14,0x138(r1); 530 mtsrr0 r14 531 532 ld r14,0x140(r1); 533 mtsrr1 r14 534 535 ld r14,0x148(r1); 536 mtcr r14 537 538 ld r14,0x150(r1); 539 mtxer r14 540 541 542 .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ 543 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ 544 27, 28, 29, 30, 31 545 ld r\i, 0x30+\i*8 (r1) 546 .endr 547 548 ld r1,0x38(r1); 549 550 mfsprg r0,2 551 mtctr r0 552 mfsprg r0,3 553 mtlr r0 554 mfsprg r0,0 555 rfid 556 557/* Set exception handler for given exception vector. 558 r3: exception vector offset 559 r4: exception handler 560*/ 561 .globl .set_exception 562.set_exception: 563 .globl set_exception 564set_exception: 565 ld r4,0x0(r4) 566 .globl .set_exception_asm 567.set_exception_asm: 568 .globl set_exception_asm 569set_exception_asm: 570 std r4, 0x60(r3) # fixme diff 1f - 0b 571 blr 572 573 574setup_mem_u3: 575 li 4,0x2000 ; oris 4,4,0xf800 576 577 # MemTimingParam -- CAS lat 2.5 / 4 (read-to-read / read-to-write) 578 lis 3,0x49e1 ; ori 3,3,0xa000 ; stw 3,0x50(4) 579 580 # MRSRegCntl -- CAS lat 2.5 581 li 3,0x6a ; stw 3,0xf0(4) 582 583 # MemBusConfig -- 128 bit bus 584 lis 3,0x8500 ; stw 3,0x190(4) 585 586 # CKDelAdj -- clock delay 75 587 lis 3,0x12c3 ; ori 3,3,0x30cc ; stw 3,0x520(4) 588 589 # IOModeCntl -- no termination on differential and 3-state drivers 590 lis 3,0x0350 ; stw 3,0x530(4) 591 592 li 3,18 ; mtctr 3 ; addi 5,4,0x5f0 5930: # DQSDelAdj -- read delay offset -10 594 lis 3,0x3d8f ; ori 3,3,0x6000 ; stwu 3,0x10(5) 595 596 # DQSDataDelAdj -- write delay offset -32, write data delay offset +15 597 lis 3,0x380e ; ori 3,3,0x003c ; stwu 3,0x10(5) 598 bdnz 0b 599 600 # MemProgCntl -- set all 601 lis 3,0xc000 ; stw 3,0xe0(4) 602 603 eieio 604 605 blr 606 607 608# read dimm SPDs, program memory size and type 609setup_mem_size: 610 mflr 14 611 612 li 15,0 ; oris 15,15,0xf800 ; li 17,0 613 li 3,0xa0 ; li 4,3 ; li 5,3 ; bl i2c_read 614 mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0 6150: li 3,0xa2 ; li 4,3 ; li 5,3 ; bl i2c_read 616 cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f 6170: li 16,0x1e00 6181: #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte 619 #mr 3,16 ; bl print_hex 620 621 #li 3,0x20 ; bl print_byte 622 sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00 623 stw 3,0x21c0(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x21e0(15) 6240: #bl print_hex 625 sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3 626 # slw, not sld, so that empty/bad banks translate into size 0 627 stw 17,0x21d0(15) ; bl add17173 ; stw 17,0x21f0(15) 628 andi. 0,16,2 ; beq 0f ; bl add17173 6290: #bl print_hex 630 631 li 3,0xa4 ; li 4,3 ; li 5,3 ; bl i2c_read 632 mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0 6330: li 3,0xa6 ; li 4,3 ; li 5,3 ; bl i2c_read 634 cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f 6350: li 16,0x1e00 6361: #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte 637 #mr 3,16 ; bl print_hex 638 639 #li 3,0x20 ; bl print_byte 640 sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00 641 stw 3,0x2200(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x2220(15) 6420: #bl print_hex 643 sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3 644 stw 17,0x2210(15) ; bl add17173 ; stw 17,0x2230(15) 645 andi. 0,16,2 ; beq 0f ; bl add17173 6460: #bl print_hex 647 #mr 3,17 ; bl print_hex 648 stw 17,0x2250(15) ; stw 17,0x2270(15) 649 stw 17,0x2290(15) ; stw 17,0x22b0(15) 650 651 mtlr 14 652 blr 653 654 655 656 657# print GPR3 as 8-digit hex. uses GPR18,19 658print_hex: 659 mflr 18 ; mr 19,3 ; li 3,8 ; mtctr 3 6601: rlwinm 3,19,4,28,31 ; sldi 19,19,4 661 cmpdi 3,0xa ; blt 0f ; addi 3,3,0x27 6620: addi 3,3,0x30 ; bl putc 663 bdnz 1b ; mtlr 18 ; blr 664 665 666# i2c stuff uses GPR20..GPR24 667 668# terminate any i2c transaction, at any point during that transaction 669i2c_stop: 6700: lwz 3,0x30(20) ; stw 3,0x30(20) ; andi. 3,3,4 ; beq 0b 671 mr 3,21 ; mr 4,22 ; mtlr 24 ; eieio ; blr 672 673# do a combined-mode read 674# in: GPR3 = addr, GPR4 = subaddr, GPR5 = len 675# out: GPR3 = error, GPR4 = result (right-aligned, msb) 676i2c_read: 677 mflr 24 678 li 20,0x1000 ; oris 20,20,0xf800 # uni-n i2c base 679 mr 21,3 ; mr 22,4 ; mr 23,5 # save params 680 li 4,0xc ; stw 4,0(20) # set mode (combined) 681 ori 4,21,1 ; stw 4,0x50(20) # set addr, read 682 stw 22,0x60(20) # set subaddr 683 li 4,2 ; stw 4,0x10(20) ; eieio # start address phase 684 li 21,1 # error 685 li 22,0 # result accumulator 6860: lwz 3,0x30(20) ; andi. 3,3,2 ; beq 0b # wait until sent 687 lwz 3,0x20(20) ; andi. 3,3,2 ; beq i2c_stop # check result 688 li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0 6890: stw 4,0x10(20) # AAK for next byte (or not) 690 li 4,2 ; stw 4,0x30(20) ; eieio # ack address phase 691i2c_read_loop: 692 lwz 3,0x30(20) ; andi. 3,3,1 ; beq 1f # if byte recv'd: 693 subi 23,23,1 ; sldi 22,22,8 # shift byte accum 694 lwz 3,0x70(20) ; rlwimi 22,3,0,24,31 # get byte 695 cmpdi 23,0 ; bne 0f ; li 21,0 ; b i2c_stop # all done 6960: li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0 6970: stw 4,0x10(20) # AAK for next byte (or not) 698 li 4,1 ; stw 4,0x30(20) ; eieio # ack data phase 6991: lwz 3,0x30(20) ; andi. 3,3,4 ; beq i2c_read_loop 700 li 4,0 ; stw 4,0x10(20) ; eieio ; b i2c_stop # stop bit received 701 702add17173: # add GPR3 into GPR17; if passing 2GB (0x10000000), add another 2GB. 703 lis 0,0x1000 ; cmpld 17,0 ; add 17,17,3 ; bgtlr 704 cmpld 17,0 ; blelr ; add 17,17,0 ; blr 705 706io_log_init: 707 LOAD64(r3, SB_NVRAM_adr) 708 b checkinitLog 709