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