]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/w7o/post1.S
Merge branch 'master' of ssh://10.10.0.7/home/wd/git/u-boot/master
[karo-tx-uboot.git] / board / w7o / post1.S
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"
65 err_str:        .asciz "*** POST ERROR   = "
66 warn_str:       .asciz "*** POST WARNING = "
67 end_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  ***************************************/
89 test_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 */
111 LED2:   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
125 LED3:   /* 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  ***************************************/
137 test_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 */
150 l2_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  ***************************************/
177 Data_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
214 db_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
226 Ghost_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 */
255 clr_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 */
261 clr_skip:
262         bdnz    clr_loop                /* Round and round... */
263
264         /* now do main test */
265         addi    r30, 0, 0               /* start referance counter at 0 */
266 outside:
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 */
287 inside:
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
322 Casper:                                 /* we found a ghost !! */
323         addi    r3, 0, ERR_ADDF         /* get indexed error message */
324         bl      log_err                 /* log error led error code */
325 gb_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  ***************************************************/
335 Bit_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 */
383 fill_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 */
400 ft_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 */
405 ft_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 */
413 ft_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 */
420 ft_1a:  bdnz    ft_1                    /* Round and round... */
421
422         WATCHDOG_RESET                  /* Reset the watchdog */
423
424         b       fill_done               /* restore and return */
425
426 ft_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
432 fill_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  ***************************************************/
443 get_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
457 gi2:    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
461 gi3:    addi    r3, 0, 1                /* only lower bits set */
462         b       gi_done
463 gi4:    addi    r3, 0, 0                /* no bits set */
464 gi_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  ***************************************************/
475 log_stat:                               /* output a led code and continue */
476 set_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
499 get_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
519 log_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 */
534 halt:
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
543 log_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
563 log_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  ******************************************************************/
581 temp_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
627 post_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. */
641 pputc_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 */
649 thre_set:
650         stb     r3, 0(r31)              /* Store character to UART */
651         addi    r3, 0, 0                /* clear error code */
652 pputc_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 *****************************************************************/
666 post_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 */
675 pputs_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 */
684 pputs_err:
685         addi    r3, 0, -1               /* set error code */
686         b       pputs_end               /* were outa here */
687 pputs_term:
688         addi    r3, 0, 1                /* set success code */
689         /* restore stack and return */
690 pputs_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  *******************************************************************/
706 disp_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
716 pputh_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. */
723 pputh_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
729 pputh_skip:
730         addic.  r30, r30, -1
731         bne     pputh_nxt
732         xor     r3, r3, r3              /* Clear error code */
733         b       pputh_done
734 pputh_err:
735         addi    r3, 0, -1               /* set error code */
736 pputh_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 */