blob: 8a1b9e69099edb5f3a560a45ce55f53d7e0d4e97 [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 Denk1a459662013-07-08 09:37:19 +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
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"
Wolfgang Denk53677ef2008-05-20 16:00:29 +020049err_str: .asciz "*** POST ERROR = "
wdenkc6097192002-11-03 00:24:07 +000050warn_str: .asciz "*** POST WARNING = "
51end_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 ***************************************/
73test_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
Wolfgang Denk53677ef2008-05-20 16:00:29 +020080 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +000081
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 */
95LED2: 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
109LED3: /* 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 ***************************************/
121test_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 */
134l2_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200142 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000143 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 ***************************************/
161Data_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
198db_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
210Ghost_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 */
239clr_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200244 WATCHDOG_RESET /* kick the dog every now and then */
wdenkc6097192002-11-03 00:24:07 +0000245clr_skip:
246 bdnz clr_loop /* Round and round... */
247
248 /* now do main test */
249 addi r30, 0, 0 /* start referance counter at 0 */
250outside:
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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200259 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000260
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
wdenk8bde7f72003-06-27 21:31:46 +0000269 /* ghost (inner) loop, now check all posible ghosted addresses */
wdenkc6097192002-11-03 00:24:07 +0000270 addi r29, 0, 0 /* start ghosted loop counter at 0 */
271inside:
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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200288 addi r29, r29, 1 /* increment inner loop counter */
289 cmpw r29, r26 /* check for last inner loop */
wdenkc6097192002-11-03 00:24:07 +0000290 blt inside /* do more inner loops */
291
292 /* now close referance ( outer ) loop */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200293 addi r31, 0, 0 /* r31 = zero */
wdenkc6097192002-11-03 00:24:07 +0000294 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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200300 addi r30, r30, 1 /* increment outer loop counter */
301 cmpw r30, r26 /* check for last inner loop */
wdenkc6097192002-11-03 00:24:07 +0000302 ble outside /* do more outer loops */
303
304 /* were done, lets go home */
305 b gb_done
306Casper: /* we found a ghost !! */
307 addi r3, 0, ERR_ADDF /* get indexed error message */
308 bl log_err /* log error led error code */
309gb_done: /* pack your bags, and go home */
wdenk8bde7f72003-06-27 21:31:46 +0000310 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 */
wdenkc6097192002-11-03 00:24:07 +0000315
316/****************************************************
317 ******** SDRAM data fill tests **********
318 ***************************************************/
319Bit_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
wdenkc6097192002-11-03 00:24:07 +0000360/****************************************************
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 */
367fill_test:
wdenk8bde7f72003-06-27 21:31:46 +0000368 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 */
wdenkc6097192002-11-03 00:24:07 +0000374 mr r27, r3
375 mr r28, r4
376 mr r29, r5
377
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200378 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000379
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 */
384ft_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200388 WATCHDOG_RESET /* kick the dog every now and then */
wdenkc6097192002-11-03 00:24:07 +0000389ft_0a: bdnz ft_0 /* Round and round... */
390
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200391 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000392
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 */
397ft_1: lwz r31, 0(r30) /* get value from memory */
wdenk8bde7f72003-06-27 21:31:46 +0000398 xor. r31, r31, r28 /* Writen = Read ? */
399 bne ft_err /* If bad, than halt */
wdenkc6097192002-11-03 00:24:07 +0000400 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 */
404ft_1a: bdnz ft_1 /* Round and round... */
405
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200406 WATCHDOG_RESET /* Reset the watchdog */
wdenkc6097192002-11-03 00:24:07 +0000407
408 b fill_done /* restore and return */
409
410ft_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
416fill_done:
wdenk8bde7f72003-06-27 21:31:46 +0000417 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 */
wdenkc6097192002-11-03 00:24:07 +0000422
423
424/****************************************************
425 ******* get error index from r3 pattern ********
426 ***************************************************/
427get_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
441gi2: 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
445gi3: addi r3, 0, 1 /* only lower bits set */
446 b gi_done
447gi4: addi r3, 0, 0 /* no bits set */
448gi_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 ***************************************************/
459log_stat: /* output a led code and continue */
460set_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
483get_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
503log_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 */
518halt:
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
527log_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
547log_2:
548 WATCHDOG_RESET /* this keeps dog from barking, */
wdenk8bde7f72003-06-27 21:31:46 +0000549 /* and takes time */
wdenkc6097192002-11-03 00:24:07 +0000550 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 ******************************************************************/
565temp_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
wdenk8bde7f72003-06-27 21:31:46 +0000571 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)
wdenkc6097192002-11-03 00:24:07 +0000575
576 /* set baud rate to use internal clock,
577 baud = (200e6/16)/31/42 = 9600 */
578
wdenk8bde7f72003-06-27 21:31:46 +0000579 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 */
wdenkc6097192002-11-03 00:24:07 +0000583
wdenk8bde7f72003-06-27 21:31:46 +0000584 addi r3, r3, 0x0001 /* uart baud divisor addr */
585 addi r4, 0, 0
586 stb r4, 0(r3) /* Divisor Latch MSB = 0 */
wdenkc6097192002-11-03 00:24:07 +0000587
wdenk8bde7f72003-06-27 21:31:46 +0000588 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)
wdenkc6097192002-11-03 00:24:07 +0000592
593 /* output a few line feeds */
594 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 addi r3, 0, '\n' /* load line feed */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200597 bl post_putc /* output the char */
wdenkc6097192002-11-03 00:24:07 +0000598
wdenk8bde7f72003-06-27 21:31:46 +0000599 /* restore stack and return */
wdenkc6097192002-11-03 00:24:07 +0000600 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
611post_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
wdenk8bde7f72003-06-27 21:31:46 +0000619 r30 - delay counter
wdenkc6097192002-11-03 00:24:07 +0000620 r29 - scratch reg */
621
622 addis r31, 0, 0xef60 /* Point to uart base */
623 ori r31, r31, 0x0300
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200624 addis r30, 0, 152 /* Load about 10,000,000 ticks. */
wdenkc6097192002-11-03 00:24:07 +0000625pputc_lp:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200626 lbz r29, 5(r31) /* Read Line Status Register */
wdenkc6097192002-11-03 00:24:07 +0000627 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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200632 b pputc_done /* Bail out with error code set */
wdenkc6097192002-11-03 00:24:07 +0000633thre_set:
634 stb r3, 0(r31) /* Store character to UART */
635 addi r3, 0, 0 /* clear error code */
636pputc_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*****************************************************************/
650post_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
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200658 addi r31, r3, 0 /* move pointer to R31 */
wdenkc6097192002-11-03 00:24:07 +0000659pputs_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
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200666 addi r31, r31, 1 /* point to next char */
667 b pputs_nxt /* loop till term */
wdenkc6097192002-11-03 00:24:07 +0000668pputs_err:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200669 addi r3, 0, -1 /* set error code */
wdenkc6097192002-11-03 00:24:07 +0000670 b pputs_end /* were outa here */
671pputs_term:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200672 addi r3, 0, 1 /* set success code */
wdenk8bde7f72003-06-27 21:31:46 +0000673 /* restore stack and return */
wdenkc6097192002-11-03 00:24:07 +0000674pputs_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
wdenkc6097192002-11-03 00:24:07 +0000682/********************************************************************
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 *******************************************************************/
690disp_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 */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200698 addi r30, 0, 8 /* Go through 8 nibbles. */
699 addi r31, r3, 0
wdenkc6097192002-11-03 00:24:07 +0000700pputh_nxt:
701 rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200702 andi. r3, r31, 0x0f /* Get nibble. */
703 addi r3, r3, 0x30 /* Add zero's ASCII code. */
wdenkc6097192002-11-03 00:24:07 +0000704 cmpwi r3, 0x03a
705 blt pputh_out
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200706 addi r3, r3, 0x07 /* 0x27 for lower case. */
wdenkc6097192002-11-03 00:24:07 +0000707pputh_out:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200708 cmpw r30, r4
wdenkc6097192002-11-03 00:24:07 +0000709 bgt pputh_skip
710 bl post_putc
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200711 addic. r3, r3, 0 /* check for error */
wdenkc6097192002-11-03 00:24:07 +0000712 bne pputh_err
713pputh_skip:
714 addic. r30, r30, -1
715 bne pputh_nxt
716 xor r3, r3, r3 /* Clear error code */
717 b pputh_done
718pputh_err:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200719 addi r3, 0, -1 /* set error code */
wdenkc6097192002-11-03 00:24:07 +0000720pputh_done:
wdenk8bde7f72003-06-27 21:31:46 +0000721 /* restore stack and return */
wdenkc6097192002-11-03 00:24:07 +0000722 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 */