Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / w7o / post1.S
diff --git a/qemu/roms/u-boot/board/w7o/post1.S b/qemu/roms/u-boot/board/w7o/post1.S
new file mode 100644 (file)
index 0000000..aae5387
--- /dev/null
@@ -0,0 +1,724 @@
+/*
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
+ *  and
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+/*
+ * Description:
+ *     Routine to exercise memory for the bringing up of our boards.
+ */
+#include <config.h>
+#include <asm/ppc4xx.h>
+
+#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 */