708 lines
16 KiB
ArmAsm
708 lines
16 KiB
ArmAsm
/******************************************************************************
|
|
* Copyright (c) 2004, 2008 IBM Corporation
|
|
* All rights reserved.
|
|
* This program and the accompanying materials
|
|
* are made available under the terms of the BSD License
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.opensource.org/licenses/bsd-license.php
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial implementation
|
|
*****************************************************************************/
|
|
|
|
# SLOF for JS20/JS21 -- ROM boot code.
|
|
# Initial entry point, copy code from flash to cache, memory setup.
|
|
# Also sets up serial console and optimizes some settings.
|
|
|
|
#include "termctrl.h"
|
|
#include <product.h>
|
|
#include <xvect.h>
|
|
#include <cpu.h>
|
|
#include <macros.h>
|
|
#include <southbridge.h>
|
|
|
|
.text
|
|
.globl __start
|
|
__start:
|
|
/* put rombase in sprg1 ***********************/
|
|
|
|
bl postHeader
|
|
.long 0xDEADBEE0
|
|
.long 0x0 /* size */
|
|
.long 0x0 /* crc */
|
|
.long relTag - __start
|
|
postHeader:
|
|
mflr r3
|
|
li r4, 0x7fff
|
|
not r4, r4
|
|
and r3, r3, r4
|
|
mtsprg 1, r3 /* romfs base */
|
|
bl _start
|
|
|
|
.org 0x150 - 0x100
|
|
__startSlave:
|
|
bl setup_cpu
|
|
bl set_ci_bit
|
|
# b slaveWithNumber
|
|
b slave
|
|
|
|
.org 0x180 - 0x100
|
|
__startMaster:
|
|
li 3,0
|
|
mtsprg 1, r3 /* romfs base */
|
|
bl setup_cpu
|
|
bl set_ci_bit
|
|
b master
|
|
|
|
|
|
/* FIXME: Also need 0280, 0380, 0f20, etc. */
|
|
|
|
.irp i, 0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,0x0400,0x0500,0x0600,0x0700, \
|
|
0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \
|
|
0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \
|
|
0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \
|
|
0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \
|
|
0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00
|
|
. = \i
|
|
|
|
/* enable this if you get exceptions before the console works */
|
|
/* this will allow using the hardware debugger to see where */
|
|
/* it traps, and with what register values etc. */
|
|
// b $
|
|
|
|
mtsprg 0, r0
|
|
mfctr r0
|
|
mtsprg 2,r0
|
|
mflr r0
|
|
// 10
|
|
mtsprg 3,r0
|
|
ld r0, (\i + 0x160)(0)
|
|
mtctr r0
|
|
li r0, \i + 0x100
|
|
// 20
|
|
bctr
|
|
|
|
. = \i + 0x60
|
|
|
|
.quad intHandler2C
|
|
|
|
.endr
|
|
|
|
|
|
. = XVECT_M_HANDLER - 0x100
|
|
.quad 0x00
|
|
. = XVECT_S_HANDLER - 0x100
|
|
|
|
.quad 0
|
|
|
|
|
|
|
|
.org 0x4000 - 0x100
|
|
_start:
|
|
# optimize HID register settings
|
|
bl setup_cpu
|
|
bl set_ci_bit
|
|
|
|
# read semaphore, run as slave if not the first to do so
|
|
li 3,0 ; oris 3,3,0xf800 ; lwz 3,0x60(3) ; andi. 3,3,1 ; beq slave
|
|
master:
|
|
# setup flash, serial
|
|
bl setup_sio
|
|
|
|
# early greet
|
|
li r3, 10
|
|
bl putc
|
|
li 3,13 ; bl putc ; li 3,10 ; bl putc ; li 3,'S' ; bl putc
|
|
|
|
|
|
#do we run from ram ?
|
|
mfsprg r3, 1 /* rombase */
|
|
cmpdi r3,0 /* rombase is 0 when running from RAM */
|
|
|
|
bne copy_to_cache
|
|
|
|
# wait a bit, start scripts are slow... need to get all cores running!
|
|
lis 3,0x4000 ; mtctr 3 ; bdnz $
|
|
|
|
# copy 4MB from 0 to temp memory
|
|
lis 4,0x8 ; mtctr 4 ; lis 4,0x200 ; li 3,0 ; addi 4,4,-8 ; addi 3,3,-8
|
|
0: ldu 5,8(3) ; stdu 5,8(4) ; bdnz 0b
|
|
|
|
lis 4,0x200
|
|
mtsprg 1, r4
|
|
|
|
lis 4,0x1
|
|
lis 3,0x20 ; addi 3,3,0x200-8 ;
|
|
FLUSH_CACHE(r3, r4)
|
|
|
|
lis 4,0x200
|
|
addi 4,4,copy_to_cache@l
|
|
mtctr 4
|
|
bctr
|
|
|
|
# make all data accesses cache-inhibited
|
|
set_ci_bit:
|
|
SETCI(r0)
|
|
blr
|
|
|
|
# make all data accesses cacheable
|
|
clr_ci_bit:
|
|
CLRCI(r0)
|
|
blr
|
|
|
|
# write a character to the serial port
|
|
putc:
|
|
# always write to serial1
|
|
0: lbz 0,5(13) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(13) ; eieio
|
|
|
|
# read ID register: only if it is a PC87427 (JS21) also use serial2
|
|
li 4,0 ; oris 4,4,0xf400
|
|
li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4); cmpdi 5,0xf2 ; bne 1f
|
|
|
|
addi 4,4,0x2f8
|
|
0: lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio
|
|
|
|
1: blr
|
|
|
|
# transfer from running from flash to running from cache
|
|
return_cacheable:
|
|
# find and set address to start running from cache, set msr value
|
|
mflr 3 ; rldicl 3,3,0,44
|
|
jump_cacheable:
|
|
mtsrr0 3 ;
|
|
mfmsr 3 ; ori 3,3,0x1000 ; mtsrr1 3 # enable MCE, as well
|
|
|
|
# set cacheable insn fetches, jump to cache
|
|
mfspr 3,HID1 ; rldicl 3,3,32,0 ; oris 3,3,0x0020 ; rldicl 3,3,32,0
|
|
sync ; mtspr HID1,3 ; mtspr HID1,3 ; rfid ; b .
|
|
|
|
|
|
|
|
|
|
copy_to_cache:
|
|
# zero the whole cache
|
|
# also, invalidate the insn cache, to clear parity errors
|
|
# 128kB @ 0MB (boot code and vectors from 0x0 up to 0x20000)
|
|
li 4,0x400 ; mtctr 4 ; li 5,0x0 ; bl clr_ci_bit
|
|
0: dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b
|
|
|
|
# 0x2000 to 0x100000/0x80000 (smaller on 970/970FX)
|
|
li 4,0x1C00 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0xC00
|
|
0:
|
|
mtctr 4 ; li 5,0x2000
|
|
0: dcbz 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b ; bl set_ci_bit
|
|
|
|
# find base address
|
|
bcl 20,31,$+4 ; mflr 31 ; rldicr 31,31,0,43
|
|
|
|
# copy 1kB from 0x4000
|
|
li 4,0x80 ; mtctr 4 ;
|
|
li 5,0x3ff8
|
|
addi 3,31,0x3ff8
|
|
0: ldu 4,8(3) ; bl clr_ci_bit ; stdu 4,8(5) ; bl set_ci_bit ; bdnz 0b
|
|
# now start executing from cache -- insn cache is huge speed boost
|
|
|
|
bl return_cacheable
|
|
|
|
li 3,'L' ; bl putc
|
|
|
|
# copy 128kB of flash to cache
|
|
li 4,0x800 ; mtctr 4 ; li 5,0x200-64 ; addi 3,31,0x200-64 ;
|
|
0: ldu 16,64(3) ; ld 17,8(3) ; ld 18,16(3) ; ld 19,24(3)
|
|
ld 20,32(3) ; ld 21,40(3) ; ld 22,48(3) ; ld 23,56(3)
|
|
bl clr_ci_bit
|
|
stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5)
|
|
std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5)
|
|
icbi 0,5 ; bl set_ci_bit ; bdnz 0b ; isync
|
|
|
|
|
|
li 3,'O' ; bl putc
|
|
|
|
lis 4,0x20
|
|
mfsprg r3,1
|
|
cmpd r3,r4
|
|
beq 1f
|
|
|
|
// at 0xf8000000 we decide if it is u3 or u4
|
|
li 4,0 ; oris 4,4,0xf800 ; lwz 3,0(4) ; srdi 3,3,4 ; cmpdi 3,3 ; bne 0f
|
|
bl setup_mem_u3
|
|
bl setup_mem_size
|
|
b 1f
|
|
0:
|
|
|
|
1:
|
|
li 3,'F' ; bl putc
|
|
|
|
# setup nvram logging only when not running from RAM
|
|
mfsprg r3, 1 /* rombase */
|
|
cmpdi r3, 0 /* rombase is 0 when running from RAM */
|
|
beq 0f
|
|
|
|
// at 0xf8000000 we decide if it is u3 or u4
|
|
li r4, 0
|
|
oris r4, r4, 0xf800
|
|
lwz r3, 0(r4)
|
|
srdi r3, r3, 4
|
|
cmpdi r3, 3 /* 3 means js20; no nvram logging on js20 */
|
|
beq 0f
|
|
|
|
bl io_log_init
|
|
0:
|
|
|
|
#bl print_mem
|
|
|
|
# data is cacheable by default from now on
|
|
bl clr_ci_bit
|
|
|
|
|
|
/* give live sign *****************************/
|
|
bl 0f
|
|
.ascii TERM_CTRL_RESET
|
|
.ascii TERM_CTRL_CRSOFF
|
|
.ascii " **********************************************************************"
|
|
.ascii "\r\n"
|
|
.ascii TERM_CTRL_BRIGHT
|
|
.ascii PRODUCT_NAME
|
|
.ascii " Starting\r\n"
|
|
.ascii TERM_CTRL_RESET
|
|
.ascii " Build Date = ", __DATE__, " ", __TIME__
|
|
.ascii "\r\n"
|
|
.ascii " FW Version = " , RELEASE
|
|
.ascii "\r\n\0"
|
|
.align 2
|
|
0: mflr r3
|
|
bl io_print
|
|
|
|
# go!
|
|
li r3,__startC@l
|
|
mtctr r3
|
|
mfsprg r10, 1
|
|
bctrl
|
|
|
|
relTag:
|
|
.ascii RELEASE
|
|
.ascii "\0"
|
|
.align 2
|
|
|
|
slave:
|
|
|
|
# get cpu number
|
|
li 3,0 ; oris 3,3,0xf800 ; lwz 28,0x50(3)
|
|
|
|
slaveWithNumber:
|
|
# create our slave loop address
|
|
sldi 3,28,24 ; oris 3,3,0x3000
|
|
|
|
# invalidate the insn cache, to clear parity errors
|
|
# clear the L2 cache as well, to get ECC right
|
|
li 4,0x2000 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0x1000
|
|
0: mtctr 4 ; mr 5,3 ; bl clr_ci_bit
|
|
|
|
0: dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b
|
|
|
|
|
|
# write a "b $" insn in there
|
|
lis 4,0x4800 ; stw 4,0(3)
|
|
/*
|
|
mr 5,3
|
|
|
|
# jump there
|
|
bl set_ci_bit
|
|
li 13,0 ; oris 13,13,0xf400
|
|
# device address
|
|
addi 13,13,0x2f8
|
|
li 3,'O' ; add 3,3,28 ; bl putc
|
|
bl clr_ci_bit
|
|
mr 3,5
|
|
*/
|
|
b jump_cacheable
|
|
|
|
|
|
|
|
|
|
# allow the flash chip to be accessed faster
|
|
# initialize the 16550-compatible uart on serial port 1 of the sio
|
|
setup_sio:
|
|
|
|
# i/o base address
|
|
li 3,0 ; oris 3,3,0xf400
|
|
|
|
# i/o base address
|
|
li 3,0 ; oris 3,3,0xf400
|
|
|
|
# put x-bus in turbo mode
|
|
li 4,0xf1 ; stb 4,0x400(3) ; eieio
|
|
|
|
|
|
# select sio serial1
|
|
li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio
|
|
|
|
# set base address to 3f8
|
|
li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio
|
|
|
|
# enable device
|
|
li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio
|
|
|
|
# read ID register: only if it is a PC87427, enable serial2
|
|
li 4,0x20 ; stb 4,0x2e(3) ; eieio ; lbz 4,0x2f(3) ; cmpdi 4,0xf2 ; bne 0f
|
|
|
|
# select sio serial2
|
|
li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio
|
|
|
|
# set base address to 2f8
|
|
li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio
|
|
|
|
# enable device
|
|
li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio
|
|
|
|
# uart @0x2f8
|
|
addi 3,3,0x2f8
|
|
|
|
# disable interrupts, fifo off
|
|
li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio
|
|
|
|
# set serial speed
|
|
li 4,0x80 ; stb 4,3(3) ; eieio
|
|
li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio
|
|
|
|
# set 8-N-1, set RTS and DTR
|
|
li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio
|
|
|
|
eieio
|
|
|
|
addi 3,3,-0x2f8
|
|
|
|
# uart @0x3f8
|
|
0: addi 3,3,0x3f8
|
|
|
|
# disable interrupts, fifo off
|
|
li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio
|
|
|
|
# set serial speed
|
|
li 4,0x80 ; stb 4,3(3) ; eieio
|
|
li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio
|
|
|
|
# set 8-N-1, set RTS and DTR
|
|
li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio
|
|
|
|
eieio
|
|
|
|
# save UART base for putc routine
|
|
0: mr 13,3
|
|
|
|
blr
|
|
|
|
|
|
|
|
|
|
# set the HID registers of the 970 for optimally executing from flash
|
|
setup_cpu:
|
|
|
|
/* clear all the HV cruft */
|
|
li r0, 0
|
|
sync
|
|
mtspr HID4, r0
|
|
isync
|
|
|
|
/* enable dpm, disable attn insn, enable external mce
|
|
* first, try external time base; if clock doesn't run, switch to
|
|
* internal */
|
|
li r0, 1 /* do the setup for external timebase */
|
|
rldicl r0, r0, 44, 0 /* bit 19 has to be set */
|
|
oris r0, r0, 0x8000 /* Enable external machine check */
|
|
/* interrupts (preferred state */
|
|
/* equals `1'). */
|
|
sync
|
|
mtspr HID0, r0
|
|
isync
|
|
|
|
mftb r3 /* read the timebase */
|
|
li r1, 0x4000 /* wait long enough for the external */
|
|
mtctr r1 /* timebase (14MHz) to tick a bit */
|
|
bdnz $ /* 0x4000 seems to be enough (for now) */
|
|
mftb r4 /* read the timebase a second time */
|
|
cmpld r3, r4 /* see if it changed */
|
|
bne 0f
|
|
/* timebase did not change, do the setup for internal */
|
|
rldicl r0, r0, 19, 1
|
|
rldicl r0, r0, 45, 0
|
|
sync
|
|
mtspr HID0, r0
|
|
isync
|
|
|
|
0:
|
|
/* enable insn prefetch, speculative table walks */
|
|
mfspr r0, HID1
|
|
rldicl r0, r0, 20, 0
|
|
ori r0, r0, 0x1002
|
|
mfsprg r3, 1 /* read rombase */
|
|
cmpdi r3, 0 /* check if running from ram */
|
|
bne 0f
|
|
/* running from ram */
|
|
/* Enable instruction fetch cacheability control */
|
|
ori r0, r0, 0x200
|
|
0:
|
|
rldicl r0, r0, 44, 0
|
|
sync
|
|
mtspr HID1, r0
|
|
isync
|
|
|
|
/* enable cache parity */
|
|
mfspr r0, HID4
|
|
oris r0, r0, 0xfff0
|
|
xoris r0, r0, 0xfff0
|
|
sync
|
|
mtspr HID4, r0
|
|
isync
|
|
|
|
/* exception offset at 0 */
|
|
li r3, 0
|
|
mtspr HIOR, r3
|
|
|
|
blr
|
|
|
|
C_ENTRY(proceedInterrupt)
|
|
|
|
ld r3,exception_stack_frame@got(r2)
|
|
ld r1,0(r3)
|
|
|
|
.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
|
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
|
|
27, 28, 29, 30, 31
|
|
ld r\i, 0x30+\i*8 (r1)
|
|
.endr
|
|
|
|
ld r14,0x138(r1);
|
|
mtsrr0 r14
|
|
|
|
ld r14,0x140(r1);
|
|
mtsrr1 r14
|
|
|
|
ld r14,0x148(r1);
|
|
mtcr r14
|
|
|
|
|
|
ld 0,XVECT_M_HANDLER(0)
|
|
mtctr 0
|
|
|
|
ld r0,0x30(r1); # restore vector number
|
|
ld r1,0x38(r1);
|
|
|
|
bctr
|
|
|
|
intHandler2C:
|
|
mtctr r1 # save old stack pointer
|
|
lis r1,0x4
|
|
stdu r1, -0x160(r1)
|
|
.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
|
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
|
|
27, 28, 29, 30, 31
|
|
std r\i, 0x30+\i*8 (r1)
|
|
.endr
|
|
|
|
std r0,0x30(r1); # save vector number
|
|
|
|
mfctr r14
|
|
std r14,0x38(r1); # save old r1
|
|
|
|
mfsrr0 r14
|
|
std r14,0x138(r1);
|
|
|
|
mfsrr1 r14
|
|
std r14,0x140(r1);
|
|
|
|
mfcr r14
|
|
std r14,0x148(r1);
|
|
|
|
mfxer r14
|
|
std r14,0x150(r1);
|
|
|
|
bl toc_init
|
|
|
|
ld r3,exception_stack_frame@got(r2)
|
|
std r1,0(r3)
|
|
|
|
|
|
mr r3,r0
|
|
bl .c_interrupt
|
|
|
|
ld r14,0x138(r1);
|
|
mtsrr0 r14
|
|
|
|
ld r14,0x140(r1);
|
|
mtsrr1 r14
|
|
|
|
ld r14,0x148(r1);
|
|
mtcr r14
|
|
|
|
ld r14,0x150(r1);
|
|
mtxer r14
|
|
|
|
|
|
.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
|
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
|
|
27, 28, 29, 30, 31
|
|
ld r\i, 0x30+\i*8 (r1)
|
|
.endr
|
|
|
|
ld r1,0x38(r1);
|
|
|
|
mfsprg r0,2
|
|
mtctr r0
|
|
mfsprg r0,3
|
|
mtlr r0
|
|
mfsprg r0,0
|
|
rfid
|
|
|
|
/* Set exception handler for given exception vector.
|
|
r3: exception vector offset
|
|
r4: exception handler
|
|
*/
|
|
.globl .set_exception
|
|
.set_exception:
|
|
.globl set_exception
|
|
set_exception:
|
|
ld r4,0x0(r4)
|
|
.globl .set_exception_asm
|
|
.set_exception_asm:
|
|
.globl set_exception_asm
|
|
set_exception_asm:
|
|
std r4, 0x60(r3) # fixme diff 1f - 0b
|
|
blr
|
|
|
|
|
|
setup_mem_u3:
|
|
li 4,0x2000 ; oris 4,4,0xf800
|
|
|
|
# MemTimingParam -- CAS lat 2.5 / 4 (read-to-read / read-to-write)
|
|
lis 3,0x49e1 ; ori 3,3,0xa000 ; stw 3,0x50(4)
|
|
|
|
# MRSRegCntl -- CAS lat 2.5
|
|
li 3,0x6a ; stw 3,0xf0(4)
|
|
|
|
# MemBusConfig -- 128 bit bus
|
|
lis 3,0x8500 ; stw 3,0x190(4)
|
|
|
|
# CKDelAdj -- clock delay 75
|
|
lis 3,0x12c3 ; ori 3,3,0x30cc ; stw 3,0x520(4)
|
|
|
|
# IOModeCntl -- no termination on differential and 3-state drivers
|
|
lis 3,0x0350 ; stw 3,0x530(4)
|
|
|
|
li 3,18 ; mtctr 3 ; addi 5,4,0x5f0
|
|
0: # DQSDelAdj -- read delay offset -10
|
|
lis 3,0x3d8f ; ori 3,3,0x6000 ; stwu 3,0x10(5)
|
|
|
|
# DQSDataDelAdj -- write delay offset -32, write data delay offset +15
|
|
lis 3,0x380e ; ori 3,3,0x003c ; stwu 3,0x10(5)
|
|
bdnz 0b
|
|
|
|
# MemProgCntl -- set all
|
|
lis 3,0xc000 ; stw 3,0xe0(4)
|
|
|
|
eieio
|
|
|
|
blr
|
|
|
|
|
|
# read dimm SPDs, program memory size and type
|
|
setup_mem_size:
|
|
mflr 14
|
|
|
|
li 15,0 ; oris 15,15,0xf800 ; li 17,0
|
|
li 3,0xa0 ; li 4,3 ; li 5,3 ; bl i2c_read
|
|
mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0
|
|
0: li 3,0xa2 ; li 4,3 ; li 5,3 ; bl i2c_read
|
|
cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f
|
|
0: li 16,0x1e00
|
|
1: #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte
|
|
#mr 3,16 ; bl print_hex
|
|
|
|
#li 3,0x20 ; bl print_byte
|
|
sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00
|
|
stw 3,0x21c0(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x21e0(15)
|
|
0: #bl print_hex
|
|
sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3
|
|
# slw, not sld, so that empty/bad banks translate into size 0
|
|
stw 17,0x21d0(15) ; bl add17173 ; stw 17,0x21f0(15)
|
|
andi. 0,16,2 ; beq 0f ; bl add17173
|
|
0: #bl print_hex
|
|
|
|
li 3,0xa4 ; li 4,3 ; li 5,3 ; bl i2c_read
|
|
mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0
|
|
0: li 3,0xa6 ; li 4,3 ; li 5,3 ; bl i2c_read
|
|
cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f
|
|
0: li 16,0x1e00
|
|
1: #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte
|
|
#mr 3,16 ; bl print_hex
|
|
|
|
#li 3,0x20 ; bl print_byte
|
|
sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00
|
|
stw 3,0x2200(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x2220(15)
|
|
0: #bl print_hex
|
|
sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3
|
|
stw 17,0x2210(15) ; bl add17173 ; stw 17,0x2230(15)
|
|
andi. 0,16,2 ; beq 0f ; bl add17173
|
|
0: #bl print_hex
|
|
#mr 3,17 ; bl print_hex
|
|
stw 17,0x2250(15) ; stw 17,0x2270(15)
|
|
stw 17,0x2290(15) ; stw 17,0x22b0(15)
|
|
|
|
mtlr 14
|
|
blr
|
|
|
|
|
|
|
|
|
|
# print GPR3 as 8-digit hex. uses GPR18,19
|
|
print_hex:
|
|
mflr 18 ; mr 19,3 ; li 3,8 ; mtctr 3
|
|
1: rlwinm 3,19,4,28,31 ; sldi 19,19,4
|
|
cmpdi 3,0xa ; blt 0f ; addi 3,3,0x27
|
|
0: addi 3,3,0x30 ; bl putc
|
|
bdnz 1b ; mtlr 18 ; blr
|
|
|
|
|
|
# i2c stuff uses GPR20..GPR24
|
|
|
|
# terminate any i2c transaction, at any point during that transaction
|
|
i2c_stop:
|
|
0: lwz 3,0x30(20) ; stw 3,0x30(20) ; andi. 3,3,4 ; beq 0b
|
|
mr 3,21 ; mr 4,22 ; mtlr 24 ; eieio ; blr
|
|
|
|
# do a combined-mode read
|
|
# in: GPR3 = addr, GPR4 = subaddr, GPR5 = len
|
|
# out: GPR3 = error, GPR4 = result (right-aligned, msb)
|
|
i2c_read:
|
|
mflr 24
|
|
li 20,0x1000 ; oris 20,20,0xf800 # uni-n i2c base
|
|
mr 21,3 ; mr 22,4 ; mr 23,5 # save params
|
|
li 4,0xc ; stw 4,0(20) # set mode (combined)
|
|
ori 4,21,1 ; stw 4,0x50(20) # set addr, read
|
|
stw 22,0x60(20) # set subaddr
|
|
li 4,2 ; stw 4,0x10(20) ; eieio # start address phase
|
|
li 21,1 # error
|
|
li 22,0 # result accumulator
|
|
0: lwz 3,0x30(20) ; andi. 3,3,2 ; beq 0b # wait until sent
|
|
lwz 3,0x20(20) ; andi. 3,3,2 ; beq i2c_stop # check result
|
|
li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0
|
|
0: stw 4,0x10(20) # AAK for next byte (or not)
|
|
li 4,2 ; stw 4,0x30(20) ; eieio # ack address phase
|
|
i2c_read_loop:
|
|
lwz 3,0x30(20) ; andi. 3,3,1 ; beq 1f # if byte recv'd:
|
|
subi 23,23,1 ; sldi 22,22,8 # shift byte accum
|
|
lwz 3,0x70(20) ; rlwimi 22,3,0,24,31 # get byte
|
|
cmpdi 23,0 ; bne 0f ; li 21,0 ; b i2c_stop # all done
|
|
0: li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0
|
|
0: stw 4,0x10(20) # AAK for next byte (or not)
|
|
li 4,1 ; stw 4,0x30(20) ; eieio # ack data phase
|
|
1: lwz 3,0x30(20) ; andi. 3,3,4 ; beq i2c_read_loop
|
|
li 4,0 ; stw 4,0x10(20) ; eieio ; b i2c_stop # stop bit received
|
|
|
|
add17173: # add GPR3 into GPR17; if passing 2GB (0x10000000), add another 2GB.
|
|
lis 0,0x1000 ; cmpld 17,0 ; add 17,17,3 ; bgtlr
|
|
cmpld 17,0 ; blelr ; add 17,17,0 ; blr
|
|
|
|
io_log_init:
|
|
LOAD64(r3, SB_NVRAM_adr)
|
|
b checkinitLog
|