743 lines
25 KiB
ArmAsm
743 lines
25 KiB
ArmAsm
|
/*
|
||
|
* (C) Copyright 2001
|
||
|
* Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
|
||
|
* and
|
||
|
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
|
||
|
*
|
||
|
* See file CREDITS for list of people who contributed to this
|
||
|
* project.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of
|
||
|
* the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||
|
* MA 02111-1307 USA
|
||
|
*/
|
||
|
/*
|
||
|
* Description:
|
||
|
* Routine to exercise memory for the bringing up of our boards.
|
||
|
*/
|
||
|
#include <config.h>
|
||
|
#include <ppc4xx.h>
|
||
|
|
||
|
#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
|
||
|
|
||
|
#include <ppc_asm.tmpl>
|
||
|
#include <ppc_defs.h>
|
||
|
|
||
|
#include <asm/cache.h>
|
||
|
#include <asm/mmu.h>
|
||
|
|
||
|
#include <watchdog.h>
|
||
|
|
||
|
#include "errors.h"
|
||
|
|
||
|
#define _ASMLANGUAGE
|
||
|
|
||
|
.globl test_sdram
|
||
|
.globl test_led
|
||
|
.globl log_stat
|
||
|
.globl log_warn
|
||
|
.globl log_err
|
||
|
.globl temp_uart_init
|
||
|
.globl post_puts
|
||
|
.globl disp_hex
|
||
|
|
||
|
/*****************************************************
|
||
|
******* Text Strings for low level printing ******
|
||
|
******* In section got2 *******
|
||
|
*****************************************************/
|
||
|
|
||
|
/*
|
||
|
* Define the text strings for errors and warnings.
|
||
|
* Switch to .data section.
|
||
|
*/
|
||
|
.section ".data"
|
||
|
err_str: .asciz "*** POST ERROR = "
|
||
|
warn_str: .asciz "*** POST WARNING = "
|
||
|
end_str: .asciz "\r\n"
|
||
|
|
||
|
/*
|
||
|
* Enter the labels in Global Entry Table (GOT).
|
||
|
* Switch to .got2 section.
|
||
|
*/
|
||
|
START_GOT
|
||
|
GOT_ENTRY(err_str)
|
||
|
GOT_ENTRY(warn_str)
|
||
|
GOT_ENTRY(end_str)
|
||
|
END_GOT
|
||
|
|
||
|
/*
|
||
|
* Switch back to .text section.
|
||
|
*/
|
||
|
.text
|
||
|
|
||
|
/****************************************
|
||
|
****************************************
|
||
|
******** LED register test ********
|
||
|
****************************************
|
||
|
***************************************/
|
||
|
test_led:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -12(r1) /* Save back chain and move SP */
|
||
|
stw r0, +16(r1) /* Save link register */
|
||
|
stw r4, +8(r1) /* save R4 */
|
||
|
|
||
|
WATCHDOG_RESET /* Reset the watchdog */
|
||
|
|
||
|
addi r3, 0, ERR_FF /* first test value is ffff */
|
||
|
addi r4, r3, 0 /* save copy of pattern */
|
||
|
bl set_led /* store first test value */
|
||
|
bl get_led /* read it back */
|
||
|
xor. r4, r4, r3 /* compare to original */
|
||
|
#if defined(CONFIG_W7OLMC)
|
||
|
andi. r4, r4, 0x00ff /* lmc has 8 bits */
|
||
|
#else
|
||
|
andi. r4, r4, 0xffff /* lmg has 16 bits */
|
||
|
#endif
|
||
|
beq LED2 /* next test */
|
||
|
addi r3, 0, ERR_LED /* error code = 1 */
|
||
|
bl log_err /* display error and halt */
|
||
|
LED2: addi r3, 0, ERR_00 /* 2nd test value is 0000 */
|
||
|
addi r4, r3, 0 /* save copy of pattern */
|
||
|
bl set_led /* store first test value */
|
||
|
bl get_led /* read it back */
|
||
|
xor. r4, r4, r3 /* compare to original */
|
||
|
#if defined(CONFIG_W7OLMC)
|
||
|
andi. r4, r4, 0x00ff /* lmc has 8 bits */
|
||
|
#else
|
||
|
andi. r4, r4, 0xffff /* lmg has 16 bits */
|
||
|
#endif
|
||
|
beq LED3 /* next test */
|
||
|
addi r3, 0, ERR_LED /* error code = 1 */
|
||
|
bl log_err /* display error and halt */
|
||
|
|
||
|
LED3: /* restore stack and return */
|
||
|
lwz r0, +16(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
lwz r4, +8(r1) /* restore r4 */
|
||
|
addi r1, r1, +12 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
/****************************************
|
||
|
****************************************
|
||
|
******** SDRAM TESTS ********
|
||
|
****************************************
|
||
|
***************************************/
|
||
|
test_sdram:
|
||
|
/* called with mem size in r3 */
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -16(r1) /* Save back chain and move SP */
|
||
|
stw r0, +20(r1) /* Save link register */
|
||
|
stmw r30, +8(r1) /* save R30,R31 */
|
||
|
/* r30 is log2(mem size) */
|
||
|
/* r31 is mem size */
|
||
|
|
||
|
/* take log2 of total mem size */
|
||
|
addi r31, r3, 0 /* save total mem size */
|
||
|
addi r30, 0, 0 /* clear r30 */
|
||
|
l2_loop:
|
||
|
srwi. r31, r31, 1 /* shift right 1 */
|
||
|
addi r30, r30, 1 /* count shifts */
|
||
|
bne l2_loop /* loop till done */
|
||
|
addi r30, r30, -1 /* correct for over count */
|
||
|
addi r31, r3, 0 /* save original size */
|
||
|
|
||
|
/* now kick the dog and test the mem */
|
||
|
WATCHDOG_RESET /* Reset the watchdog */
|
||
|
bl Data_Buster /* test crossed/shorted data lines */
|
||
|
addi r3, r30, 0 /* get log2(memsize) */
|
||
|
addi r4, r31, 0 /* get memsize */
|
||
|
bl Ghost_Buster /* test crossed/shorted addr lines */
|
||
|
addi r3, r31, 0 /* get mem size */
|
||
|
bl Bit_Buster /* check for bad internal bits */
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lmw r30, +8(r1) /* Restore r30, r31 */
|
||
|
lwz r0, +20(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
addi r1, r1, +16 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
|
||
|
/****************************************
|
||
|
******** sdram data bus test ********
|
||
|
***************************************/
|
||
|
Data_Buster:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -24(r1) /* Save back chain and move SP */
|
||
|
stw r0, +28(r1) /* Save link register */
|
||
|
stmw r28, 8(r1) /* save r28 - r31 on stack */
|
||
|
/* r31 i/o register */
|
||
|
/* r30 sdram base address */
|
||
|
/* r29 5555 syndrom */
|
||
|
/* r28 aaaa syndrom */
|
||
|
|
||
|
/* set up led register for this test */
|
||
|
addi r3, 0, ERR_RAMG /* set led code to 1 */
|
||
|
bl log_stat /* store test value */
|
||
|
/* now test the dram data bus */
|
||
|
xor r30, r30, r30 /* load r30 with base addr of sdram */
|
||
|
addis r31, 0, 0x5555 /* load r31 with test value */
|
||
|
ori r31, r31, 0x5555
|
||
|
stw r31,0(r30) /* sto the value */
|
||
|
lwz r29,0(r30) /* read it back */
|
||
|
xor r29,r31,r29 /* compare it to original */
|
||
|
addis r31, 0, 0xaaaa /* load r31 with test value */
|
||
|
ori r31, r31, 0xaaaa
|
||
|
stw r31,0(r30) /* sto the value */
|
||
|
lwz r28,0(r30) /* read it back */
|
||
|
xor r28,r31,r28 /* compare it to original */
|
||
|
or r3,r28,r29 /* or together both error terms */
|
||
|
/*
|
||
|
* Now that we have the error bits,
|
||
|
* we have to decide which part they are in.
|
||
|
*/
|
||
|
bl get_idx /* r5 is now index to error */
|
||
|
addi r3, r3, ERR_RAMG
|
||
|
cmpwi r3, ERR_RAMG /* check for errors */
|
||
|
beq db_done /* skip if no errors */
|
||
|
bl log_err /* log the error */
|
||
|
|
||
|
db_done:
|
||
|
lmw r28, 8(r1) /* restore r28 - r31 from stack */
|
||
|
lwz r0, +28(r1) /* Get saved link register */
|
||
|
addi r1, r1, +24 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
|
||
|
/****************************************************
|
||
|
******** test for address ghosting in dram ********
|
||
|
***************************************************/
|
||
|
|
||
|
Ghost_Buster:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -36(r1) /* Save back chain and move SP */
|
||
|
stw r0, +40(r1) /* Save link register */
|
||
|
stmw r25, 8(r1) /* save r25 - r31 on stack */
|
||
|
/* r31 = scratch register */
|
||
|
/* r30 is main referance loop counter,
|
||
|
0 to 23 */
|
||
|
/* r29 is ghost loop count, 0 to 22 */
|
||
|
/* r28 is referance address */
|
||
|
/* r27 is ghost address */
|
||
|
/* r26 is log2 (mem size) =
|
||
|
number of byte addr bits */
|
||
|
/* r25 is mem size */
|
||
|
|
||
|
/* save the log2(mem size) and mem size */
|
||
|
addi r26, r3, 0 /* r26 is number of byte addr bits */
|
||
|
addi r25, r4, 0 /* r25 is mem size in bytes */
|
||
|
|
||
|
/* set the leds for address ghost test */
|
||
|
addi r3, 0, ERR_ADDG
|
||
|
bl set_led
|
||
|
|
||
|
/* first fill memory with zeros */
|
||
|
srwi r31, r25, 2 /* convert bytes to longs */
|
||
|
mtctr r31 /* setup byte counter */
|
||
|
addi r28, 0, 0 /* start at address at 0 */
|
||
|
addi r31, 0, 0 /* data value = 0 */
|
||
|
clr_loop:
|
||
|
stw r31, 0(r28) /* Store zero value */
|
||
|
addi r28, r28, 4 /* Increment to next word */
|
||
|
andi. r27, r28, 0xffff /* check for 2^16 loops */
|
||
|
bne clr_skip /* if not there, then skip */
|
||
|
WATCHDOG_RESET /* kick the dog every now and then */
|
||
|
clr_skip:
|
||
|
bdnz clr_loop /* Round and round... */
|
||
|
|
||
|
/* now do main test */
|
||
|
addi r30, 0, 0 /* start referance counter at 0 */
|
||
|
outside:
|
||
|
/*
|
||
|
* Calculate the referance address
|
||
|
* the referance address is calculated by setting the (r30-1)
|
||
|
* bit of the base address
|
||
|
* when r30=0, the referance address is the base address.
|
||
|
* thus the sequence 0,1,2,4,8,..,2^(n-1)
|
||
|
* setting the bit is done with the following shift functions.
|
||
|
*/
|
||
|
WATCHDOG_RESET /* Reset the watchdog */
|
||
|
|
||
|
addi r31, 0, 1 /* r31 = 1 */
|
||
|
slw r28, r31, r30 /* set bit coresponding to loop cnt */
|
||
|
srwi r28, r28, 1 /* then shift it right one so */
|
||
|
/* we start at location 0 */
|
||
|
/* fill referance address with Fs */
|
||
|
addi r31, 0, 0x00ff /* r31 = one byte of set bits */
|
||
|
stb r31,0(r28) /* save ff in referance address */
|
||
|
|
||
|
/* ghost (inner) loop, now check all posible ghosted addresses */
|
||
|
addi r29, 0, 0 /* start ghosted loop counter at 0 */
|
||
|
inside:
|
||
|
/*
|
||
|
* Calculate the ghost address by flipping one
|
||
|
* bit of referance address. This gives the
|
||
|
* sequence 1,2,4,8,...,2^(n-1)
|
||
|
*/
|
||
|
addi r31, 0, 1 /* r31 = 1 */
|
||
|
slw r27, r31, r29 /* set bit coresponding to loop cnt */
|
||
|
xor r27, r28, r27 /* ghost address = ref addr with
|
||
|
bit flipped*/
|
||
|
|
||
|
/* now check for ghosting */
|
||
|
lbz r31,0(r27) /* get content of ghost addr */
|
||
|
cmpwi r31, 0 /* compare read value to 0 */
|
||
|
bne Casper /* we found a ghost! */
|
||
|
|
||
|
/* now close ghost ( inner ) loop */
|
||
|
addi r29, r29, 1 /* increment inner loop counter */
|
||
|
cmpw r29, r26 /* check for last inner loop */
|
||
|
blt inside /* do more inner loops */
|
||
|
|
||
|
/* now close referance ( outer ) loop */
|
||
|
addi r31, 0, 0 /* r31 = zero */
|
||
|
stb r31, 0(28) /* zero out the altered address loc. */
|
||
|
/*
|
||
|
* Increment and check for end, count is zero based.
|
||
|
* With the ble, this gives us one more loops than
|
||
|
* address bits for sequence 0,1,2,4,8,...2^(n-1)
|
||
|
*/
|
||
|
addi r30, r30, 1 /* increment outer loop counter */
|
||
|
cmpw r30, r26 /* check for last inner loop */
|
||
|
ble outside /* do more outer loops */
|
||
|
|
||
|
/* were done, lets go home */
|
||
|
b gb_done
|
||
|
Casper: /* we found a ghost !! */
|
||
|
addi r3, 0, ERR_ADDF /* get indexed error message */
|
||
|
bl log_err /* log error led error code */
|
||
|
gb_done: /* pack your bags, and go home */
|
||
|
lmw r25, 8(r1) /* restore r25 - r31 from stack */
|
||
|
lwz r0, +40(r1) /* Get saved link register */
|
||
|
addi r1, r1, +36 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
/****************************************************
|
||
|
******** SDRAM data fill tests **********
|
||
|
***************************************************/
|
||
|
Bit_Buster:
|
||
|
/* called with mem size in r3 */
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -16(r1) /* Save back chain and move SP */
|
||
|
stw r0, +20(r1) /* Save link register */
|
||
|
stw r4, +8(r1) /* save R4 */
|
||
|
stw r5, +12(r1) /* save r5 */
|
||
|
|
||
|
addis r5, r3, 0 /* save mem size */
|
||
|
|
||
|
/* Test 55555555 */
|
||
|
addi r3, 0, ERR_R55G /* set up error code in case we fail */
|
||
|
bl log_stat /* store test value */
|
||
|
addis r4, 0, 0x5555
|
||
|
ori r4, r4, 0x5555
|
||
|
bl fill_test
|
||
|
|
||
|
/* Test aaaaaaaa */
|
||
|
addi r3, 0, ERR_RAAG /* set up error code in case we fail */
|
||
|
bl log_stat /* store test value */
|
||
|
addis r4, 0, 0xAAAA
|
||
|
ori r4, r4, 0xAAAA
|
||
|
bl fill_test
|
||
|
|
||
|
/* Test 00000000 */
|
||
|
addi r3, 0, ERR_R00G /* set up error code in case we fail */
|
||
|
bl log_stat /* store test value */
|
||
|
addis r4, 0, 0
|
||
|
ori r4, r4, 0
|
||
|
bl fill_test
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lwz r5, +12(r1) /* restore r4 */
|
||
|
lwz r4, +8(r1) /* restore r4 */
|
||
|
lwz r0, +20(r1) /* Get saved link register */
|
||
|
addi r1, r1, +16 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
|
||
|
/****************************************************
|
||
|
******** fill test ********
|
||
|
***************************************************/
|
||
|
/* tests memory by filling with value, and reading back */
|
||
|
/* r5 = Size of memory in bytes */
|
||
|
/* r4 = Value to write */
|
||
|
/* r3 = Error code */
|
||
|
fill_test:
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -32(r1) /* Save back chain and move SP */
|
||
|
stw r0, +36(r1) /* Save link register */
|
||
|
stmw r27, 8(r1) /* save r27 - r31 on stack */
|
||
|
/* r31 - scratch register */
|
||
|
/* r30 - memory address */
|
||
|
mr r27, r3
|
||
|
mr r28, r4
|
||
|
mr r29, r5
|
||
|
|
||
|
WATCHDOG_RESET /* Reset the watchdog */
|
||
|
|
||
|
/* first fill memory with Value */
|
||
|
srawi r31, r29, 2 /* convert bytes to longs */
|
||
|
mtctr r31 /* setup counter */
|
||
|
addi r30, 0, 0 /* Make r30 = addr 0 */
|
||
|
ft_0: stw r28, 0(r30) /* Store value */
|
||
|
addi r30, r30, 4 /* Increment to next word */
|
||
|
andi. r31, r30, 0xffff /* check for 2^16 loops */
|
||
|
bne ft_0a /* if not there, then skip */
|
||
|
WATCHDOG_RESET /* kick the dog every now and then */
|
||
|
ft_0a: bdnz ft_0 /* Round and round... */
|
||
|
|
||
|
WATCHDOG_RESET /* Reset the watchdog */
|
||
|
|
||
|
/* Now confirm Value is in memory */
|
||
|
srawi r31, r29, 2 /* convert bytes to longs */
|
||
|
mtctr r31 /* setup counter */
|
||
|
addi r30, 0, 0 /* Make r30 = addr 0 */
|
||
|
ft_1: lwz r31, 0(r30) /* get value from memory */
|
||
|
xor. r31, r31, r28 /* Writen = Read ? */
|
||
|
bne ft_err /* If bad, than halt */
|
||
|
addi r30, r30, 4 /* Increment to next word */
|
||
|
andi. r31, r30, 0xffff /* check for 2^16 loops*/
|
||
|
bne ft_1a /* if not there, then skip */
|
||
|
WATCHDOG_RESET /* kick the dog every now and then */
|
||
|
ft_1a: bdnz ft_1 /* Round and round... */
|
||
|
|
||
|
WATCHDOG_RESET /* Reset the watchdog */
|
||
|
|
||
|
b fill_done /* restore and return */
|
||
|
|
||
|
ft_err: addi r29, r27, 0 /* save current led code */
|
||
|
addi r27, r31, 0 /* get pattern in r27 */
|
||
|
bl get_idx /* get index from r27 */
|
||
|
add r27, r27, r29 /* add index to old led code */
|
||
|
bl log_err /* output led err code, halt CPU */
|
||
|
|
||
|
fill_done:
|
||
|
lmw r27, 8(r1) /* restore r27 - r31 from stack */
|
||
|
lwz r0, +36(r1) /* Get saved link register */
|
||
|
addi r1, r1, +32 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
|
||
|
/****************************************************
|
||
|
******* get error index from r3 pattern ********
|
||
|
***************************************************/
|
||
|
get_idx: /* r3 = (MSW(r3) !=0)*2 +
|
||
|
(LSW(r3) !=0) */
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -12(r1) /* Save back chain and move SP */
|
||
|
stw r0, +16(r1) /* Save link register */
|
||
|
stw r4, +8(r1) /* save R4 */
|
||
|
|
||
|
andi. r4, r3, 0xffff /* check for lower bits */
|
||
|
beq gi2 /* skip if no bits set */
|
||
|
andis. r4, r3, 0xffff /* check for upper bits */
|
||
|
beq gi3 /* skip if no bits set */
|
||
|
addi r3, 0, 3 /* both upper and lower bits set */
|
||
|
b gi_done
|
||
|
gi2: andis. r4, r3, 0xffff /* check for upper bits*/
|
||
|
beq gi4 /* skip if no bits set */
|
||
|
addi r3, 0, 2 /* only upper bits set */
|
||
|
b gi_done
|
||
|
gi3: addi r3, 0, 1 /* only lower bits set */
|
||
|
b gi_done
|
||
|
gi4: addi r3, 0, 0 /* no bits set */
|
||
|
gi_done:
|
||
|
/* restore stack and return */
|
||
|
lwz r0, +16(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
lwz r4, +8(r1) /* restore r4 */
|
||
|
addi r1, r1, +12 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
/****************************************************
|
||
|
******** set LED to R5 and hang ********
|
||
|
***************************************************/
|
||
|
log_stat: /* output a led code and continue */
|
||
|
set_led:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -12(r1) /* Save back chain and move SP */
|
||
|
stw r0, +16(r1) /* Save link register */
|
||
|
stw r4, +8(r1) /* save R4 */
|
||
|
|
||
|
addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
|
||
|
#if defined(CONFIG_W7OLMG) /* only on gateway, invert outputs */
|
||
|
xori r3,r3, 0xffff /* complement led code, active low */
|
||
|
sth r3, 0(r4) /* store first test value */
|
||
|
xori r3,r3, 0xffff /* complement led code, active low */
|
||
|
#else /* if not gateway, then don't invert */
|
||
|
sth r3, 0(r4) /* store first test value */
|
||
|
#endif
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lwz r0, +16(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
lwz r4, +8(r1) /* restore r4 */
|
||
|
addi r1, r1, +12 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
get_led:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -12(r1) /* Save back chain and move SP */
|
||
|
stw r0, +16(r1) /* Save link register */
|
||
|
stw r4, +8(r1) /* save R4 */
|
||
|
|
||
|
addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
|
||
|
lhz r3, 0(r4) /* store first test value */
|
||
|
#if defined(CONFIG_W7OLMG) /* only on gateway, invert inputs */
|
||
|
xori r3,r3, 0xffff /* complement led code, active low */
|
||
|
#endif
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lwz r0, +16(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
lwz r4, +8(r1) /* restore r4 */
|
||
|
addi r1, r1, +12 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
log_err: /* output the error and hang the board ( for now ) */
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -12(r1) /* Save back chain and move SP */
|
||
|
stw r0, +16(r1) /* Save link register */
|
||
|
stw r3, +8(r1) /* save a copy of error code */
|
||
|
bl set_led /* set the led pattern */
|
||
|
GET_GOT /* get GOT address in r14 */
|
||
|
lwz r3,GOT(err_str) /* get address of string */
|
||
|
bl post_puts /* output the warning string */
|
||
|
lwz r3, +8(r1) /* get error code */
|
||
|
addi r4, 0, 2 /* set disp length to 2 nibbles */
|
||
|
bl disp_hex /* output the error code */
|
||
|
lwz r3,GOT(end_str) /* get address of string */
|
||
|
bl post_puts /* output the warning string */
|
||
|
halt:
|
||
|
b halt /* hang */
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lwz r0, +16(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
addi r1, r1, +12 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
log_warn: /* output a warning, then continue with operations */
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -16(r1) /* Save back chain and move SP */
|
||
|
stw r0, +20(r1) /* Save link register */
|
||
|
stw r3, +8(r1) /* save a copy of error code */
|
||
|
stw r14, +12(r1) /* save a copy of r14 (used by GOT) */
|
||
|
|
||
|
bl set_led /* set the led pattern */
|
||
|
GET_GOT /* get GOT address in r14 */
|
||
|
lwz r3,GOT(warn_str) /* get address of string */
|
||
|
bl post_puts /* output the warning string */
|
||
|
lwz r3, +8(r1) /* get error code */
|
||
|
addi r4, 0, 2 /* set disp length to 2 nibbles */
|
||
|
bl disp_hex /* output the error code */
|
||
|
lwz r3,GOT(end_str) /* get address of string */
|
||
|
bl post_puts /* output the warning string */
|
||
|
|
||
|
addis r3, 0, 64 /* has a long delay */
|
||
|
mtctr r3
|
||
|
log_2:
|
||
|
WATCHDOG_RESET /* this keeps dog from barking, */
|
||
|
/* and takes time */
|
||
|
bdnz log_2 /* loop till time expires */
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lwz r0, +20(r1) /* Get saved link register */
|
||
|
lwz r14, +12(r1) /* restore r14 */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
addi r1, r1, +16 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
/*******************************************************************
|
||
|
* temp_uart_init
|
||
|
* Temporary UART initialization routine
|
||
|
* Sets up UART0 to run at 9600N81 off of the internal clock.
|
||
|
* R3-R4 are used.
|
||
|
******************************************************************/
|
||
|
temp_uart_init:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -8(r1) /* Save back chain and move SP */
|
||
|
stw r0, +12(r1) /* Save link register */
|
||
|
|
||
|
addis r3, 0, 0xef60
|
||
|
ori r3, r3, 0x0303 /* r3 = UART0_LCR */
|
||
|
addi r4, 0, 0x83 /* n81 format, divisor regs enabled */
|
||
|
stb r4, 0(r3)
|
||
|
|
||
|
/* set baud rate to use internal clock,
|
||
|
baud = (200e6/16)/31/42 = 9600 */
|
||
|
|
||
|
addis r3, 0, 0xef60 /* Address of baud divisor reg */
|
||
|
ori r3, r3, 0x0300 /* UART0_DLM */
|
||
|
addi r4, 0, +42 /* uart baud divisor LSB = 93 */
|
||
|
stb r4, 0(r3) /* baud = (200 /16)/14/93 */
|
||
|
|
||
|
addi r3, r3, 0x0001 /* uart baud divisor addr */
|
||
|
addi r4, 0, 0
|
||
|
stb r4, 0(r3) /* Divisor Latch MSB = 0 */
|
||
|
|
||
|
addis r3, 0, 0xef60
|
||
|
ori r3, r3, 0x0303 /* r3 = UART0_LCR */
|
||
|
addi r4, 0, 0x03 /* n81 format, tx/rx regs enabled */
|
||
|
stb r4, 0(r3)
|
||
|
|
||
|
/* output a few line feeds */
|
||
|
addi r3, 0, '\n' /* load line feed */
|
||
|
bl post_putc /* output the char */
|
||
|
addi r3, 0, '\n' /* load line feed */
|
||
|
bl post_putc /* output the char */
|
||
|
|
||
|
/* restore stack and return */
|
||
|
lwz r0, +12(r1) /* Get saved link register */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
addi r1, r1, +8 /* Remove frame from stack */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
/**********************************************************************
|
||
|
** post_putc
|
||
|
** outputs charactor in R3
|
||
|
** r3 returns the error code ( -1 if there is an error )
|
||
|
*********************************************************************/
|
||
|
|
||
|
post_putc:
|
||
|
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -20(r1) /* Save back chain and move SP */
|
||
|
stw r0, +24(r1) /* Save link register */
|
||
|
stmw r29, 8(r1) /* save r29 - r31 on stack
|
||
|
r31 - uart base address
|
||
|
r30 - delay counter
|
||
|
r29 - scratch reg */
|
||
|
|
||
|
addis r31, 0, 0xef60 /* Point to uart base */
|
||
|
ori r31, r31, 0x0300
|
||
|
addis r30, 0, 152 /* Load about 10,000,000 ticks. */
|
||
|
pputc_lp:
|
||
|
lbz r29, 5(r31) /* Read Line Status Register */
|
||
|
andi. r29, r29, 0x20 /* Check THRE status */
|
||
|
bne thre_set /* Branch if FIFO empty */
|
||
|
addic. r30, r30, -1 /* Decrement and check if empty. */
|
||
|
bne pputc_lp /* Try, try again */
|
||
|
addi r3, 0, -1 /* Load error code for timeout */
|
||
|
b pputc_done /* Bail out with error code set */
|
||
|
thre_set:
|
||
|
stb r3, 0(r31) /* Store character to UART */
|
||
|
addi r3, 0, 0 /* clear error code */
|
||
|
pputc_done:
|
||
|
lmw r29, 8(r1) /*restore r29 - r31 from stack */
|
||
|
lwz r0, +24(r1) /* Get saved link register */
|
||
|
addi r1, r1, +20 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
|
||
|
/****************************************************************
|
||
|
post_puts
|
||
|
Accepts a null-terminated string pointed to by R3
|
||
|
Outputs to the serial port until 0x00 is found.
|
||
|
r3 returns the error code ( -1 if there is an error )
|
||
|
*****************************************************************/
|
||
|
post_puts:
|
||
|
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -12(r1) /* Save back chain and move SP */
|
||
|
stw r0, +16(r1) /* Save link register */
|
||
|
stw r31, 8(r1) /* save r31 - char pointer */
|
||
|
|
||
|
addi r31, r3, 0 /* move pointer to R31 */
|
||
|
pputs_nxt:
|
||
|
lbz r3, 0(r31) /* Get next character */
|
||
|
addic. r3, r3, 0 /* Check for zero */
|
||
|
beq pputs_term /* bail out if zero */
|
||
|
bl post_putc /* output the char */
|
||
|
addic. r3, r3, 0 /* check for error */
|
||
|
bne pputs_err
|
||
|
addi r31, r31, 1 /* point to next char */
|
||
|
b pputs_nxt /* loop till term */
|
||
|
pputs_err:
|
||
|
addi r3, 0, -1 /* set error code */
|
||
|
b pputs_end /* were outa here */
|
||
|
pputs_term:
|
||
|
addi r3, 0, 1 /* set success code */
|
||
|
/* restore stack and return */
|
||
|
pputs_end:
|
||
|
lwz r31, 8(r1) /* restore r27 - r31 from stack */
|
||
|
lwz r0, +16(r1) /* Get saved link register */
|
||
|
addi r1, r1, +12 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
***** disp_hex
|
||
|
***** Routine to display a hex value from a register.
|
||
|
***** R3 is value to display
|
||
|
***** R4 is number of nibbles to display ie 2 for byte 8 for (long)word
|
||
|
***** Returns -1 in R3 if there is an error ( ie serial port hangs )
|
||
|
***** Returns 0 in R3 if no error
|
||
|
*******************************************************************/
|
||
|
disp_hex:
|
||
|
/* save the return info on stack */
|
||
|
mflr r0 /* Get link register */
|
||
|
stwu r1, -16(r1) /* Save back chain and move SP */
|
||
|
stw r0, +20(r1) /* Save link register */
|
||
|
stmw r30, 8(r1) /* save r30 - r31 on stack */
|
||
|
/* r31 output char */
|
||
|
/* r30 uart base address */
|
||
|
addi r30, 0, 8 /* Go through 8 nibbles. */
|
||
|
addi r31, r3, 0
|
||
|
pputh_nxt:
|
||
|
rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */
|
||
|
andi. r3, r31, 0x0f /* Get nibble. */
|
||
|
addi r3, r3, 0x30 /* Add zero's ASCII code. */
|
||
|
cmpwi r3, 0x03a
|
||
|
blt pputh_out
|
||
|
addi r3, r3, 0x07 /* 0x27 for lower case. */
|
||
|
pputh_out:
|
||
|
cmpw r30, r4
|
||
|
bgt pputh_skip
|
||
|
bl post_putc
|
||
|
addic. r3, r3, 0 /* check for error */
|
||
|
bne pputh_err
|
||
|
pputh_skip:
|
||
|
addic. r30, r30, -1
|
||
|
bne pputh_nxt
|
||
|
xor r3, r3, r3 /* Clear error code */
|
||
|
b pputh_done
|
||
|
pputh_err:
|
||
|
addi r3, 0, -1 /* set error code */
|
||
|
pputh_done:
|
||
|
/* restore stack and return */
|
||
|
lmw r30, 8(r1) /* restore r30 - r31 from stack */
|
||
|
lwz r0, +20(r1) /* Get saved link register */
|
||
|
addi r1, r1, +16 /* Remove frame from stack */
|
||
|
mtlr r0 /* Restore link register */
|
||
|
blr /* Return to calling function */
|