uboot/board/w7o/post1.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
   4 *  and
   5 * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
   6 *
   7 * See file CREDITS for list of people who contributed to this
   8 * project.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 of
  13 * the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 * MA 02111-1307 USA
  24 */
  25/*
  26 * Description:
  27 *      Routine to exercise memory for the bringing up of our boards.
  28 */
  29#include <config.h>
  30#include <ppc4xx.h>
  31
  32#define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
  33
  34#include <ppc_asm.tmpl>
  35#include <ppc_defs.h>
  36
  37#include <asm/cache.h>
  38#include <asm/mmu.h>
  39
  40#include <watchdog.h>
  41
  42#include "errors.h"
  43
  44#define _ASMLANGUAGE
  45
  46        .globl  test_sdram
  47        .globl  test_led
  48        .globl  log_stat
  49        .globl  log_warn
  50        .globl  log_err
  51        .globl  temp_uart_init
  52        .globl  post_puts
  53        .globl  disp_hex
  54
  55/*****************************************************
  56*******   Text Strings for low level printing   ******
  57*******          In section got2               *******
  58*****************************************************/
  59
  60/*
  61 * Define the text strings for errors and warnings.
  62 * Switch to .data section.
  63 */
  64        .section ".data"
  65err_str:        .asciz "*** POST ERROR   = "
  66warn_str:       .asciz "*** POST WARNING = "
  67end_str:  .asciz "\r\n"
  68
  69/*
  70 * Enter the labels in Global Entry Table (GOT).
  71 * Switch to .got2 section.
  72 */
  73        START_GOT
  74        GOT_ENTRY(err_str)
  75        GOT_ENTRY(warn_str)
  76        GOT_ENTRY(end_str)
  77        END_GOT
  78
  79/*
  80 * Switch  back to .text section.
  81 */
  82        .text
  83
  84/****************************************
  85 ****************************************
  86 ********    LED register test   ********
  87 ****************************************
  88 ***************************************/
  89test_led:
  90        /* save the return info on stack */
  91        mflr    r0                      /* Get link register */
  92        stwu    r1, -12(r1)             /* Save back chain and move SP */
  93        stw     r0, +16(r1)             /* Save link register */
  94        stw     r4, +8(r1)              /* save R4 */
  95
  96        WATCHDOG_RESET                  /* Reset the watchdog */
  97
  98        addi    r3, 0, ERR_FF           /* first test value is ffff */
  99        addi    r4, r3, 0               /* save copy of pattern */
 100        bl      set_led                 /* store first test value */
 101        bl      get_led                 /* read it back */
 102        xor.    r4, r4, r3              /* compare to original */
 103#if defined(CONFIG_W7OLMC)
 104        andi.   r4, r4, 0x00ff          /* lmc has 8 bits */
 105#else
 106        andi.   r4, r4, 0xffff          /* lmg has 16 bits */
 107#endif
 108        beq     LED2                    /* next test */
 109        addi    r3, 0, ERR_LED          /* error code = 1 */
 110        bl      log_err                 /* display error and halt */
 111LED2:   addi    r3, 0, ERR_00           /* 2nd test value is 0000 */
 112        addi    r4, r3, 0               /* save copy of pattern */
 113        bl      set_led                 /* store first test value */
 114        bl      get_led                 /* read it back */
 115        xor.    r4, r4, r3              /* compare to original */
 116#if defined(CONFIG_W7OLMC)
 117        andi.   r4, r4, 0x00ff          /* lmc has 8 bits */
 118#else
 119        andi.   r4, r4, 0xffff          /* lmg has 16 bits */
 120#endif
 121        beq     LED3                    /* next test */
 122        addi    r3, 0, ERR_LED          /* error code = 1 */
 123        bl      log_err                 /* display error and halt */
 124
 125LED3:   /* restore stack and return */
 126        lwz     r0, +16(r1)             /* Get saved link register */
 127        mtlr    r0                      /* Restore link register */
 128        lwz     r4, +8(r1)              /* restore r4 */
 129        addi    r1, r1, +12             /* Remove frame from stack */
 130        blr                             /* Return to calling function */
 131
 132/****************************************
 133 ****************************************
 134 ********     SDRAM TESTS        ********
 135 ****************************************
 136 ***************************************/
 137test_sdram:
 138        /* called with mem size in r3 */
 139        /* save the return info on stack */
 140        mflr    r0                      /* Get link register */
 141        stwu    r1, -16(r1)             /* Save back chain and move SP */
 142        stw     r0, +20(r1)             /* Save link register */
 143        stmw    r30, +8(r1)             /* save R30,R31 */
 144                                        /* r30 is log2(mem size) */
 145                                        /* r31 is mem size */
 146
 147        /* take log2 of total mem size */
 148        addi    r31, r3, 0              /* save total mem size */
 149        addi    r30, 0, 0               /* clear r30 */
 150l2_loop:
 151        srwi.   r31, r31, 1             /* shift right 1 */
 152        addi    r30, r30, 1             /* count shifts */
 153        bne     l2_loop                 /* loop till done */
 154        addi    r30, r30, -1            /* correct for over count */
 155        addi    r31, r3, 0              /* save original size */
 156
 157        /* now kick the dog and test the mem */
 158        WATCHDOG_RESET                  /* Reset the watchdog */
 159        bl      Data_Buster             /* test crossed/shorted data lines */
 160        addi    r3, r30, 0              /* get log2(memsize) */
 161        addi    r4, r31, 0              /* get memsize */
 162        bl      Ghost_Buster            /* test crossed/shorted addr lines */
 163        addi    r3, r31, 0              /* get mem size */
 164        bl      Bit_Buster              /* check for bad internal bits */
 165
 166        /* restore stack and return */
 167        lmw     r30, +8(r1)             /* Restore r30, r31 */
 168        lwz     r0, +20(r1)             /* Get saved link register */
 169        mtlr    r0                      /* Restore link register */
 170        addi    r1, r1, +16             /* Remove frame from stack */
 171        blr                             /* Return to calling function */
 172
 173
 174/****************************************
 175 ********  sdram data bus test   ********
 176 ***************************************/
 177Data_Buster:
 178        /* save the return info on stack */
 179        mflr    r0                      /* Get link register */
 180        stwu    r1, -24(r1)             /* Save back chain and move SP */
 181        stw     r0, +28(r1)             /* Save link register */
 182        stmw    r28, 8(r1)              /* save r28 - r31 on stack */
 183                                        /* r31 i/o register */
 184                                        /* r30 sdram base address */
 185                                        /* r29 5555 syndrom */
 186                                        /* r28 aaaa syndrom */
 187
 188        /* set up led register for this test */
 189        addi    r3, 0, ERR_RAMG         /* set led code to 1 */
 190        bl      log_stat                /* store test value */
 191        /* now test the dram data bus */
 192        xor     r30, r30, r30           /* load r30 with base addr of sdram */
 193        addis   r31, 0, 0x5555          /* load r31 with test value */
 194        ori     r31, r31, 0x5555
 195        stw     r31,0(r30)              /* sto the value */
 196        lwz     r29,0(r30)              /* read it back */
 197        xor     r29,r31,r29             /* compare it to original */
 198        addis   r31, 0, 0xaaaa          /* load r31 with test value */
 199        ori     r31, r31, 0xaaaa
 200        stw     r31,0(r30)              /* sto the value */
 201        lwz     r28,0(r30)              /* read it back */
 202        xor     r28,r31,r28             /* compare it to original */
 203        or      r3,r28,r29              /* or together both error terms */
 204        /*
 205         * Now that we have the error bits,
 206         * we have to decide which part they are in.
 207         */
 208        bl      get_idx                 /* r5 is now index to error */
 209        addi    r3, r3, ERR_RAMG
 210        cmpwi   r3, ERR_RAMG            /* check for errors */
 211        beq     db_done                 /* skip if no errors */
 212        bl      log_err                 /* log the error */
 213
 214db_done:
 215        lmw     r28, 8(r1)              /* restore r28 - r31 from stack */
 216        lwz     r0, +28(r1)             /* Get saved link register */
 217        addi    r1, r1, +24             /* Remove frame from stack */
 218        mtlr    r0                      /* Restore link register */
 219        blr                             /* Return to calling function */
 220
 221
 222/****************************************************
 223 ********  test for address ghosting in dram ********
 224 ***************************************************/
 225
 226Ghost_Buster:
 227        /* save the return info on stack */
 228        mflr    r0                      /* Get link register */
 229        stwu    r1, -36(r1)             /* Save back chain and move SP */
 230        stw     r0, +40(r1)             /* Save link register */
 231        stmw    r25, 8(r1)              /* save r25 - r31 on stack */
 232                                        /* r31 = scratch register */
 233                                        /* r30 is main referance loop counter,
 234                                           0 to 23 */
 235                                        /* r29 is ghost loop count, 0 to 22 */
 236                                        /* r28 is referance address */
 237                                        /* r27 is ghost address */
 238                                        /* r26 is log2 (mem size) =
 239                                             number of byte addr bits */
 240                                        /* r25 is mem size */
 241
 242        /* save the log2(mem size) and mem size */
 243        addi    r26, r3, 0              /* r26 is number of byte addr bits */
 244        addi    r25, r4, 0              /* r25 is mem size in bytes */
 245
 246        /* set the leds for address ghost test */
 247        addi    r3, 0, ERR_ADDG
 248        bl      set_led
 249
 250        /* first fill memory with zeros */
 251        srwi    r31, r25, 2             /* convert bytes to longs */
 252        mtctr   r31                     /* setup byte counter */
 253        addi    r28, 0, 0               /* start at address at 0 */
 254        addi    r31, 0, 0               /* data value = 0 */
 255clr_loop:
 256        stw     r31, 0(r28)             /* Store zero value */
 257        addi    r28, r28, 4             /* Increment to next word */
 258        andi.   r27, r28, 0xffff        /* check for 2^16 loops */
 259        bne     clr_skip                /* if not there, then skip */
 260        WATCHDOG_RESET                  /* kick the dog every now and then */
 261clr_skip:
 262        bdnz    clr_loop                /* Round and round... */
 263
 264        /* now do main test */
 265        addi    r30, 0, 0               /* start referance counter at 0 */
 266outside:
 267        /*
 268         * Calculate the referance address
 269         *   the referance address is calculated by setting the (r30-1)
 270         *   bit of the base address
 271         * when r30=0, the referance address is the base address.
 272         * thus the sequence 0,1,2,4,8,..,2^(n-1)
 273         * setting the bit is done with the following shift functions.
 274         */
 275        WATCHDOG_RESET                  /* Reset the watchdog */
 276
 277        addi    r31, 0, 1               /* r31 = 1 */
 278        slw     r28, r31, r30           /* set bit coresponding to loop cnt */
 279        srwi    r28, r28, 1             /* then shift it right one so  */
 280                                        /*   we start at location 0 */
 281        /* fill referance address with Fs */
 282        addi    r31, 0, 0x00ff          /* r31 = one byte of set bits */
 283        stb     r31,0(r28)              /* save ff in referance address */
 284
 285        /* ghost (inner) loop, now check all posible ghosted addresses */
 286        addi    r29, 0, 0               /* start ghosted loop counter at 0 */
 287inside:
 288        /*
 289         * Calculate the ghost address by flipping one
 290         *  bit of referance address.  This gives the
 291         *  sequence 1,2,4,8,...,2^(n-1)
 292         */
 293        addi    r31, 0, 1               /* r31 = 1 */
 294        slw     r27, r31, r29           /* set  bit coresponding to loop cnt */
 295        xor     r27, r28, r27           /* ghost address = ref addr with
 296                                             bit flipped*/
 297
 298        /* now check for ghosting */
 299        lbz     r31,0(r27)              /* get content of ghost addr */
 300        cmpwi   r31, 0                  /* compare read value to 0 */
 301        bne     Casper                  /*   we found a ghost! */
 302
 303        /* now close ghost ( inner ) loop */
 304        addi    r29, r29, 1             /* increment inner loop counter */
 305        cmpw    r29, r26                /* check for last inner loop */
 306        blt             inside          /* do more inner loops */
 307
 308        /* now close referance ( outer ) loop */
 309        addi    r31, 0, 0               /* r31 = zero */
 310        stb     r31, 0(28)              /* zero out the altered address loc. */
 311        /*
 312         * Increment and check for end, count is zero based.
 313         * With the ble, this gives us one more loops than
 314         * address bits for sequence 0,1,2,4,8,...2^(n-1)
 315        */
 316        addi    r30, r30, 1             /* increment outer loop counter */
 317        cmpw    r30, r26                /* check for last inner loop */
 318        ble     outside                 /* do more outer loops */
 319
 320        /* were done, lets go home */
 321        b       gb_done
 322Casper:                                 /* we found a ghost !! */
 323        addi    r3, 0, ERR_ADDF         /* get indexed error message */
 324        bl      log_err                 /* log error led error code */
 325gb_done: /*  pack your bags, and go home */
 326        lmw     r25, 8(r1)              /* restore r25 - r31 from stack */
 327        lwz     r0, +40(r1)             /* Get saved link register */
 328        addi    r1, r1, +36             /* Remove frame from stack */
 329        mtlr    r0                      /* Restore link register */
 330        blr                             /* Return to calling function */
 331
 332/****************************************************
 333 ********      SDRAM data fill tests       **********
 334 ***************************************************/
 335Bit_Buster:
 336        /* called with mem size in r3 */
 337        /* save the return info on stack */
 338        mflr    r0                      /* Get link register */
 339        stwu    r1, -16(r1)             /* Save back chain and move SP */
 340        stw     r0, +20(r1)             /* Save link register */
 341        stw     r4, +8(r1)              /* save R4 */
 342        stw     r5, +12(r1)             /* save r5 */
 343
 344        addis   r5, r3, 0               /* save mem size */
 345
 346        /* Test 55555555 */
 347        addi    r3, 0, ERR_R55G         /* set up error code in case we fail */
 348        bl      log_stat                /* store test value */
 349        addis   r4, 0, 0x5555
 350        ori     r4, r4, 0x5555
 351        bl      fill_test
 352
 353        /* Test aaaaaaaa  */
 354        addi    r3, 0, ERR_RAAG         /* set up error code in case we fail */
 355        bl      log_stat                /* store test value */
 356        addis   r4, 0, 0xAAAA
 357        ori     r4, r4, 0xAAAA
 358        bl      fill_test
 359
 360        /* Test 00000000  */
 361        addi    r3, 0, ERR_R00G         /* set up error code in case we fail */
 362        bl      log_stat                /* store test value */
 363        addis   r4, 0, 0
 364        ori     r4, r4, 0
 365        bl      fill_test
 366
 367        /* restore stack and return */
 368        lwz     r5, +12(r1)             /* restore r4 */
 369        lwz     r4, +8(r1)              /* restore r4 */
 370        lwz     r0, +20(r1)             /* Get saved link register */
 371        addi    r1, r1, +16             /* Remove frame from stack */
 372        mtlr    r0                      /* Restore link register */
 373        blr                             /* Return to calling function */
 374
 375
 376/****************************************************
 377 ********             fill test              ********
 378 ***************************************************/
 379/*      tests memory by filling with value, and reading back */
 380/*      r5 = Size of memory in bytes */
 381/*      r4 = Value to write */
 382/*      r3 = Error code */
 383fill_test:
 384        mflr    r0                      /* Get link register */
 385        stwu    r1, -32(r1)             /* Save back chain and move SP */
 386        stw     r0, +36(r1)             /* Save link register */
 387        stmw    r27, 8(r1)              /* save r27 - r31 on stack */
 388                                        /* r31 - scratch register */
 389                                        /* r30 - memory address */
 390        mr      r27, r3
 391        mr      r28, r4
 392        mr      r29, r5
 393
 394        WATCHDOG_RESET                  /* Reset the watchdog */
 395
 396        /* first fill memory with Value */
 397        srawi   r31, r29, 2             /* convert bytes to longs */
 398        mtctr   r31                     /* setup counter */
 399        addi    r30, 0, 0               /* Make r30 = addr 0 */
 400ft_0:   stw     r28, 0(r30)             /* Store value */
 401        addi    r30, r30, 4             /* Increment to next word */
 402        andi.   r31, r30, 0xffff        /* check for 2^16 loops */
 403        bne     ft_0a                   /* if not there, then skip */
 404        WATCHDOG_RESET                  /* kick the dog every now and then */
 405ft_0a:  bdnz    ft_0                    /* Round and round... */
 406
 407        WATCHDOG_RESET                  /* Reset the watchdog */
 408
 409        /* Now confirm Value is in memory */
 410        srawi   r31, r29, 2             /* convert bytes to longs */
 411        mtctr   r31                     /* setup counter */
 412        addi    r30, 0, 0               /* Make r30 = addr 0 */
 413ft_1:   lwz     r31, 0(r30)             /* get value from memory */
 414        xor.    r31, r31, r28           /* Writen = Read ? */
 415        bne     ft_err                  /* If bad, than halt */
 416        addi    r30, r30, 4             /* Increment to next word */
 417        andi.   r31, r30, 0xffff        /* check for 2^16 loops*/
 418        bne     ft_1a                   /* if not there, then skip */
 419        WATCHDOG_RESET                  /* kick the dog every now and then */
 420ft_1a:  bdnz    ft_1                    /* Round and round... */
 421
 422        WATCHDOG_RESET                  /* Reset the watchdog */
 423
 424        b       fill_done               /* restore and return */
 425
 426ft_err: addi    r29, r27, 0             /* save current led code */
 427        addi    r27, r31, 0             /* get pattern in r27 */
 428        bl      get_idx                 /* get index from r27 */
 429        add     r27, r27, r29           /* add index to old led code */
 430        bl      log_err                 /* output led err code, halt CPU */
 431
 432fill_done:
 433        lmw     r27, 8(r1)              /* restore r27 - r31 from stack */
 434        lwz     r0, +36(r1)             /* Get saved link register */
 435        addi    r1, r1, +32             /* Remove frame from stack */
 436        mtlr    r0                      /* Restore link register */
 437        blr                             /* Return to calling function */
 438
 439
 440/****************************************************
 441 *******  get error index from r3 pattern    ********
 442 ***************************************************/
 443get_idx:                                /* r3 = (MSW(r3) !=0)*2 +
 444                                            (LSW(r3) !=0) */
 445        /* save the return info on stack */
 446        mflr    r0                      /* Get link register */
 447        stwu    r1, -12(r1)             /* Save back chain and move SP */
 448        stw     r0, +16(r1)             /* Save link register */
 449        stw     r4, +8(r1)              /* save R4 */
 450
 451        andi.   r4, r3, 0xffff          /* check for lower bits */
 452        beq     gi2                     /* skip if no bits set */
 453        andis.  r4, r3, 0xffff          /* check for upper bits */
 454        beq     gi3                     /* skip if no bits set */
 455        addi    r3, 0, 3                /* both upper and lower bits set */
 456        b       gi_done
 457gi2:    andis.  r4, r3, 0xffff          /* check for upper bits*/
 458        beq     gi4                     /* skip if no bits set */
 459        addi    r3, 0, 2                /* only upper bits set */
 460        b       gi_done
 461gi3:    addi    r3, 0, 1                /* only lower bits set */
 462        b       gi_done
 463gi4:    addi    r3, 0, 0                /* no bits set */
 464gi_done:
 465        /* restore stack and return */
 466        lwz     r0, +16(r1)             /* Get saved link register */
 467        mtlr    r0                      /* Restore link register */
 468        lwz     r4, +8(r1)              /* restore r4 */
 469        addi    r1, r1, +12             /* Remove frame from stack */
 470        blr                             /* Return to calling function */
 471
 472/****************************************************
 473 ********       set LED to R5 and hang       ********
 474 ***************************************************/
 475log_stat:                               /* output a led code and continue */
 476set_led:
 477        /* save the return info on stack */
 478        mflr    r0                      /* Get link register */
 479        stwu    r1, -12(r1)             /* Save back chain and move SP */
 480        stw     r0, +16(r1)             /* Save link register */
 481        stw     r4, +8(r1)              /* save R4 */
 482
 483        addis   r4, 0, 0xfe00           /* LED buffer is at 0xfe000000 */
 484#if defined(CONFIG_W7OLMG)              /* only on gateway, invert outputs */
 485        xori    r3,r3, 0xffff           /* complement led code, active low */
 486        sth     r3, 0(r4)               /* store first test value */
 487        xori    r3,r3, 0xffff           /* complement led code, active low */
 488#else                                   /* if not gateway, then don't invert */
 489        sth     r3, 0(r4)               /* store first test value */
 490#endif
 491
 492        /* restore stack and return */
 493        lwz     r0, +16(r1)             /* Get saved link register */
 494        mtlr    r0                      /* Restore link register */
 495        lwz     r4, +8(r1)              /* restore r4 */
 496        addi    r1, r1, +12             /* Remove frame from stack */
 497        blr                             /* Return to calling function */
 498
 499get_led:
 500        /* save the return info on stack */
 501        mflr    r0                      /* Get link register */
 502        stwu    r1, -12(r1)             /* Save back chain and move SP */
 503        stw     r0, +16(r1)             /* Save link register */
 504        stw     r4, +8(r1)              /* save R4 */
 505
 506        addis   r4, 0, 0xfe00           /* LED buffer is at 0xfe000000 */
 507        lhz     r3, 0(r4)               /* store first test value */
 508#if defined(CONFIG_W7OLMG)              /* only on gateway, invert inputs */
 509        xori    r3,r3, 0xffff           /* complement led code, active low */
 510#endif
 511
 512        /* restore stack and return */
 513        lwz     r0, +16(r1)             /* Get saved link register */
 514        mtlr    r0                      /* Restore link register */
 515        lwz     r4, +8(r1)              /* restore r4 */
 516        addi    r1, r1, +12             /* Remove frame from stack */
 517        blr                             /* Return to calling function */
 518
 519log_err:        /* output the error and hang the board ( for now ) */
 520        /* save the return info on stack */
 521        mflr    r0                      /* Get link register */
 522        stwu    r1, -12(r1)             /* Save back chain and move SP */
 523        stw     r0, +16(r1)             /* Save link register */
 524        stw     r3, +8(r1)              /* save a copy of error code */
 525        bl      set_led                 /* set the led pattern */
 526        GET_GOT                         /* get GOT address in r14 */
 527        lwz     r3,GOT(err_str)         /* get address of string */
 528        bl      post_puts               /* output the warning string */
 529        lwz     r3, +8(r1)              /* get error code */
 530        addi    r4, 0, 2                /* set disp length to 2 nibbles */
 531        bl      disp_hex                /* output the error code */
 532        lwz     r3,GOT(end_str)         /* get address of string */
 533        bl      post_puts               /* output the warning string */
 534halt:
 535        b       halt                    /* hang */
 536
 537        /* restore stack and return */
 538        lwz     r0, +16(r1)             /* Get saved link register */
 539        mtlr    r0                      /* Restore link register */
 540        addi    r1, r1, +12             /* Remove frame from stack */
 541        blr                             /* Return to calling function */
 542
 543log_warn:       /* output a warning, then continue with operations */
 544        /* save the return info on stack */
 545        mflr    r0                      /* Get link register */
 546        stwu    r1, -16(r1)             /* Save back chain and move SP */
 547        stw     r0, +20(r1)             /* Save link register */
 548        stw     r3, +8(r1)              /* save a copy of error code */
 549        stw     r14, +12(r1)            /* save a copy of r14 (used by GOT) */
 550
 551        bl      set_led                 /* set the led pattern */
 552        GET_GOT                         /* get GOT address in r14 */
 553        lwz     r3,GOT(warn_str)        /* get address of string */
 554        bl      post_puts               /* output the warning string */
 555        lwz     r3, +8(r1)              /* get error code */
 556        addi    r4, 0, 2                /* set disp length to 2 nibbles */
 557        bl      disp_hex                /* output the error code */
 558        lwz     r3,GOT(end_str)         /* get address of string */
 559        bl      post_puts               /* output the warning string */
 560
 561        addis   r3, 0, 64               /* has a long delay */
 562        mtctr   r3
 563log_2:
 564        WATCHDOG_RESET                  /* this keeps dog from barking, */
 565                                        /*   and takes time */
 566        bdnz    log_2                   /* loop till time expires */
 567
 568        /* restore stack and return */
 569        lwz     r0, +20(r1)             /* Get saved link register */
 570        lwz     r14, +12(r1)            /* restore r14 */
 571        mtlr    r0                      /* Restore link register */
 572        addi    r1, r1, +16             /* Remove frame from stack */
 573        blr                             /* Return to calling function */
 574
 575/*******************************************************************
 576 *      temp_uart_init
 577 *      Temporary UART initialization routine
 578 *      Sets up UART0 to run at 9600N81 off of the internal clock.
 579 *      R3-R4 are used.
 580 ******************************************************************/
 581temp_uart_init:
 582        /* save the return info on stack */
 583        mflr    r0                      /* Get link register */
 584        stwu    r1, -8(r1)              /* Save back chain and move SP */
 585        stw     r0, +12(r1)             /* Save link register */
 586
 587        addis   r3, 0, 0xef60
 588        ori     r3, r3, 0x0303          /* r3 = UART0_LCR */
 589        addi    r4, 0, 0x83             /* n81 format, divisor regs enabled */
 590        stb     r4, 0(r3)
 591
 592        /* set baud rate to use internal clock,
 593           baud = (200e6/16)/31/42 = 9600 */
 594
 595        addis   r3, 0, 0xef60           /* Address of baud divisor reg */
 596        ori     r3, r3, 0x0300          /*   UART0_DLM */
 597        addi    r4, 0, +42              /* uart baud divisor LSB = 93 */
 598        stb     r4, 0(r3)               /* baud = (200 /16)/14/93 */
 599
 600        addi    r3, r3, 0x0001          /* uart baud divisor addr */
 601        addi    r4, 0, 0
 602        stb     r4, 0(r3)               /* Divisor Latch MSB = 0 */
 603
 604        addis   r3, 0, 0xef60
 605        ori     r3, r3, 0x0303          /* r3 = UART0_LCR */
 606        addi    r4, 0, 0x03             /* n81 format, tx/rx regs enabled */
 607        stb     r4, 0(r3)
 608
 609        /* output a few line feeds */
 610        addi    r3, 0, '\n'             /* load line feed */
 611        bl      post_putc               /* output the char */
 612        addi    r3, 0, '\n'             /* load line feed */
 613        bl      post_putc               /* output the char */
 614
 615        /* restore stack and return */
 616        lwz     r0, +12(r1)             /* Get saved link register */
 617        mtlr    r0                      /* Restore link register */
 618        addi    r1, r1, +8              /* Remove frame from stack */
 619        blr                             /* Return to calling function */
 620
 621/**********************************************************************
 622 **     post_putc
 623 **     outputs charactor in R3
 624 **     r3 returns the error code ( -1 if there is an error )
 625 *********************************************************************/
 626
 627post_putc:
 628
 629        /* save the return info on stack */
 630        mflr    r0                      /* Get link register */
 631        stwu    r1, -20(r1)             /* Save back chain and move SP */
 632        stw     r0, +24(r1)             /* Save link register */
 633        stmw    r29, 8(r1)              /* save r29 - r31 on stack
 634                                           r31 - uart base address
 635                                           r30 - delay counter
 636                                           r29 - scratch reg */
 637
 638     addis   r31, 0, 0xef60             /* Point to uart base */
 639     ori     r31, r31, 0x0300
 640     addis   r30, 0, 152                /* Load about 10,000,000 ticks. */
 641pputc_lp:
 642        lbz     r29, 5(r31)             /* Read Line Status Register */
 643        andi.   r29, r29, 0x20          /* Check THRE status */
 644        bne     thre_set                /* Branch if FIFO empty */
 645        addic.  r30, r30, -1            /* Decrement and check if empty. */
 646        bne     pputc_lp                /* Try, try again */
 647        addi    r3, 0, -1               /* Load error code for timeout */
 648        b       pputc_done              /* Bail out with error code set */
 649thre_set:
 650        stb     r3, 0(r31)              /* Store character to UART */
 651        addi    r3, 0, 0                /* clear error code */
 652pputc_done:
 653        lmw     r29, 8(r1)              /*restore r29 - r31 from stack */
 654        lwz     r0, +24(r1)             /* Get saved link register */
 655        addi    r1, r1, +20             /* Remove frame from stack */
 656        mtlr    r0                      /* Restore link register */
 657        blr                             /* Return to calling function */
 658
 659
 660/****************************************************************
 661    post_puts
 662    Accepts a null-terminated string pointed to by R3
 663    Outputs to the serial port until 0x00 is found.
 664    r3 returns the error code ( -1 if there is an error )
 665*****************************************************************/
 666post_puts:
 667
 668        /* save the return info on stack */
 669        mflr    r0                      /* Get link register */
 670        stwu    r1, -12(r1)             /* Save back chain and move SP */
 671        stw     r0, +16(r1)             /* Save link register */
 672        stw     r31, 8(r1)              /* save r31 - char pointer */
 673
 674        addi    r31, r3, 0              /* move pointer to R31 */
 675pputs_nxt:
 676        lbz     r3, 0(r31)              /* Get next character */
 677        addic.  r3, r3, 0               /* Check for zero */
 678        beq     pputs_term              /* bail out if zero */
 679        bl      post_putc               /* output the char */
 680        addic.  r3, r3, 0               /* check for error */
 681        bne     pputs_err
 682        addi    r31, r31, 1             /* point to next char */
 683        b       pputs_nxt               /* loop till term */
 684pputs_err:
 685        addi    r3, 0, -1               /* set error code */
 686        b       pputs_end               /* were outa here */
 687pputs_term:
 688        addi    r3, 0, 1                /* set success code */
 689        /* restore stack and return */
 690pputs_end:
 691        lwz     r31, 8(r1)              /* restore r27 - r31 from stack */
 692        lwz     r0, +16(r1)             /* Get saved link register */
 693        addi    r1, r1, +12             /* Remove frame from stack */
 694        mtlr    r0                      /* Restore link register */
 695        blr                             /* Return to calling function */
 696
 697
 698/********************************************************************
 699 *****  disp_hex
 700 *****  Routine to display a hex value from a register.
 701 *****  R3 is value to display
 702 *****  R4 is number of nibbles to display ie 2 for byte 8 for (long)word
 703 *****  Returns -1 in R3 if there is an error ( ie serial port hangs )
 704 *****  Returns 0 in R3 if no error
 705 *******************************************************************/
 706disp_hex:
 707        /* save the return info on stack */
 708        mflr    r0                      /* Get link register */
 709        stwu    r1, -16(r1)             /* Save back chain and move SP */
 710        stw     r0, +20(r1)             /* Save link register */
 711        stmw    r30, 8(r1)              /* save r30 - r31 on stack */
 712                                        /* r31 output char */
 713                                        /* r30 uart base address */
 714        addi    r30, 0, 8               /* Go through 8 nibbles. */
 715        addi    r31, r3, 0
 716pputh_nxt:
 717        rlwinm  r31, r31, 4, 0, 31      /* Rotate next nibble into position */
 718        andi.   r3, r31, 0x0f           /* Get nibble. */
 719        addi    r3, r3, 0x30            /* Add zero's ASCII code. */
 720        cmpwi   r3, 0x03a
 721        blt     pputh_out
 722        addi    r3, r3, 0x07            /* 0x27 for lower case. */
 723pputh_out:
 724        cmpw    r30, r4
 725        bgt     pputh_skip
 726        bl      post_putc
 727        addic.  r3, r3, 0               /* check for error */
 728        bne     pputh_err
 729pputh_skip:
 730        addic.  r30, r30, -1
 731        bne     pputh_nxt
 732        xor     r3, r3, r3              /* Clear error code */
 733        b       pputh_done
 734pputh_err:
 735        addi    r3, 0, -1               /* set error code */
 736pputh_done:
 737        /* restore stack and return */
 738        lmw     r30, 8(r1)              /*  restore r30 - r31 from stack */
 739        lwz     r0, +20(r1)             /* Get saved link register */
 740        addi    r1, r1, +16             /* Remove frame from stack */
 741        mtlr    r0                      /* Restore link register */
 742        blr                             /* Return to calling function */
 743