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