blob: aae538721245d60187e9833c109ec28ab2b09f9e [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 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +02007 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00008 */
9/*
10 * Description:
11 * Routine to exercise memory for the bringing up of our boards.
12 */
13#include <config.h>
Stefan Roeseb36df562010-09-09 19:18:00 +020014#include <asm/ppc4xx.h>
wdenkc6097192002-11-03 00:24:07 +000015
wdenkc6097192002-11-03 00:24:07 +000016#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"
Wolfgang Denk53677ef2008-05-20 16:00:29 +020047err_str: .asciz "*** POST ERROR = "
wdenkc6097192002-11-03 00:24:07 +000048warn_str: .asciz "*** POST WARNING = "
49end_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 ***************************************/
71test_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
Wolfgang Denk53677ef2008-05-20 16:00:29 +020078 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +000079
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 */
93LED2: 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
107LED3: /* 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 ***************************************/
119test_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 */
132l2_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200140 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000141 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 ***************************************/
159Data_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
196db_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
208Ghost_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 */
237clr_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200242 WATCHDOG_RESET /* kick the dog every now and then */
wdenkc6097192002-11-03 00:24:07 +0000243clr_skip:
244 bdnz clr_loop /* Round and round... */
245
246 /* now do main test */
247 addi r30, 0, 0 /* start referance counter at 0 */
248outside:
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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200257 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000258
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
wdenk8bde7f72003-06-27 21:31:46 +0000267 /* ghost (inner) loop, now check all posible ghosted addresses */
wdenkc6097192002-11-03 00:24:07 +0000268 addi r29, 0, 0 /* start ghosted loop counter at 0 */
269inside:
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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200286 addi r29, r29, 1 /* increment inner loop counter */
287 cmpw r29, r26 /* check for last inner loop */
wdenkc6097192002-11-03 00:24:07 +0000288 blt inside /* do more inner loops */
289
290 /* now close referance ( outer ) loop */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200291 addi r31, 0, 0 /* r31 = zero */
wdenkc6097192002-11-03 00:24:07 +0000292 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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200298 addi r30, r30, 1 /* increment outer loop counter */
299 cmpw r30, r26 /* check for last inner loop */
wdenkc6097192002-11-03 00:24:07 +0000300 ble outside /* do more outer loops */
301
302 /* were done, lets go home */
303 b gb_done
304Casper: /* we found a ghost !! */
305 addi r3, 0, ERR_ADDF /* get indexed error message */
306 bl log_err /* log error led error code */
307gb_done: /* pack your bags, and go home */
wdenk8bde7f72003-06-27 21:31:46 +0000308 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 */
wdenkc6097192002-11-03 00:24:07 +0000313
314/****************************************************
315 ******** SDRAM data fill tests **********
316 ***************************************************/
317Bit_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
wdenkc6097192002-11-03 00:24:07 +0000358/****************************************************
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 */
365fill_test:
wdenk8bde7f72003-06-27 21:31:46 +0000366 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 */
wdenkc6097192002-11-03 00:24:07 +0000372 mr r27, r3
373 mr r28, r4
374 mr r29, r5
375
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200376 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000377
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 */
382ft_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200386 WATCHDOG_RESET /* kick the dog every now and then */
wdenkc6097192002-11-03 00:24:07 +0000387ft_0a: bdnz ft_0 /* Round and round... */
388
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200389 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000390
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 */
395ft_1: lwz r31, 0(r30) /* get value from memory */
wdenk8bde7f72003-06-27 21:31:46 +0000396 xor. r31, r31, r28 /* Writen = Read ? */
397 bne ft_err /* If bad, than halt */
wdenkc6097192002-11-03 00:24:07 +0000398 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 */
402ft_1a: bdnz ft_1 /* Round and round... */
403
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200404 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000405
406 b fill_done /* restore and return */
407
408ft_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
414fill_done:
wdenk8bde7f72003-06-27 21:31:46 +0000415 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 */
wdenkc6097192002-11-03 00:24:07 +0000420
421
422/****************************************************
423 ******* get error index from r3 pattern ********
424 ***************************************************/
425get_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
439gi2: 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
443gi3: addi r3, 0, 1 /* only lower bits set */
444 b gi_done
445gi4: addi r3, 0, 0 /* no bits set */
446gi_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 ***************************************************/
457log_stat: /* output a led code and continue */
458set_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
481get_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
501log_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 */
516halt:
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
525log_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
545log_2:
546 WATCHDOG_RESET /* this keeps dog from barking, */
wdenk8bde7f72003-06-27 21:31:46 +0000547 /* and takes time */
wdenkc6097192002-11-03 00:24:07 +0000548 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 ******************************************************************/
563temp_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
wdenk8bde7f72003-06-27 21:31:46 +0000569 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)
wdenkc6097192002-11-03 00:24:07 +0000573
574 /* set baud rate to use internal clock,
575 baud = (200e6/16)/31/42 = 9600 */
576
wdenk8bde7f72003-06-27 21:31:46 +0000577 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 */
wdenkc6097192002-11-03 00:24:07 +0000581
wdenk8bde7f72003-06-27 21:31:46 +0000582 addi r3, r3, 0x0001 /* uart baud divisor addr */
583 addi r4, 0, 0
584 stb r4, 0(r3) /* Divisor Latch MSB = 0 */
wdenkc6097192002-11-03 00:24:07 +0000585
wdenk8bde7f72003-06-27 21:31:46 +0000586 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)
wdenkc6097192002-11-03 00:24:07 +0000590
591 /* output a few line feeds */
592 addi r3, 0, '\n' /* load line feed */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200593 bl post_putc /* output the char */
wdenkc6097192002-11-03 00:24:07 +0000594 addi r3, 0, '\n' /* load line feed */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200595 bl post_putc /* output the char */
wdenkc6097192002-11-03 00:24:07 +0000596
wdenk8bde7f72003-06-27 21:31:46 +0000597 /* restore stack and return */
wdenkc6097192002-11-03 00:24:07 +0000598 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
609post_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
wdenk8bde7f72003-06-27 21:31:46 +0000617 r30 - delay counter
wdenkc6097192002-11-03 00:24:07 +0000618 r29 - scratch reg */
619
620 addis r31, 0, 0xef60 /* Point to uart base */
621 ori r31, r31, 0x0300
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200622 addis r30, 0, 152 /* Load about 10,000,000 ticks. */
wdenkc6097192002-11-03 00:24:07 +0000623pputc_lp:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200624 lbz r29, 5(r31) /* Read Line Status Register */
wdenkc6097192002-11-03 00:24:07 +0000625 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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200630 b pputc_done /* Bail out with error code set */
wdenkc6097192002-11-03 00:24:07 +0000631thre_set:
632 stb r3, 0(r31) /* Store character to UART */
633 addi r3, 0, 0 /* clear error code */
634pputc_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*****************************************************************/
648post_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
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200656 addi r31, r3, 0 /* move pointer to R31 */
wdenkc6097192002-11-03 00:24:07 +0000657pputs_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
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200664 addi r31, r31, 1 /* point to next char */
665 b pputs_nxt /* loop till term */
wdenkc6097192002-11-03 00:24:07 +0000666pputs_err:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200667 addi r3, 0, -1 /* set error code */
wdenkc6097192002-11-03 00:24:07 +0000668 b pputs_end /* were outa here */
669pputs_term:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200670 addi r3, 0, 1 /* set success code */
wdenk8bde7f72003-06-27 21:31:46 +0000671 /* restore stack and return */
wdenkc6097192002-11-03 00:24:07 +0000672pputs_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
wdenkc6097192002-11-03 00:24:07 +0000680/********************************************************************
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 *******************************************************************/
688disp_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200696 addi r30, 0, 8 /* Go through 8 nibbles. */
697 addi r31, r3, 0
wdenkc6097192002-11-03 00:24:07 +0000698pputh_nxt:
699 rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200700 andi. r3, r31, 0x0f /* Get nibble. */
701 addi r3, r3, 0x30 /* Add zero's ASCII code. */
wdenkc6097192002-11-03 00:24:07 +0000702 cmpwi r3, 0x03a
703 blt pputh_out
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200704 addi r3, r3, 0x07 /* 0x27 for lower case. */
wdenkc6097192002-11-03 00:24:07 +0000705pputh_out:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200706 cmpw r30, r4
wdenkc6097192002-11-03 00:24:07 +0000707 bgt pputh_skip
708 bl post_putc
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200709 addic. r3, r3, 0 /* check for error */
wdenkc6097192002-11-03 00:24:07 +0000710 bne pputh_err
711pputh_skip:
712 addic. r30, r30, -1
713 bne pputh_nxt
714 xor r3, r3, r3 /* Clear error code */
715 b pputh_done
716pputh_err:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200717 addi r3, 0, -1 /* set error code */
wdenkc6097192002-11-03 00:24:07 +0000718pputh_done:
wdenk8bde7f72003-06-27 21:31:46 +0000719 /* restore stack and return */
wdenkc6097192002-11-03 00:24:07 +0000720 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 */