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