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