]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net | |
4 | * and | |
5 | * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com | |
6 | * | |
3765b3e7 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
c609719b WD |
8 | */ |
9 | /* | |
10 | * Description: | |
11 | * Routine to exercise memory for the bringing up of our boards. | |
12 | */ | |
13 | #include <config.h> | |
b36df561 | 14 | #include <asm/ppc4xx.h> |
c609719b | 15 | |
c609719b WD |
16 | #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" | |
53677ef1 | 47 | err_str: .asciz "*** POST ERROR = " |
c609719b WD |
48 | warn_str: .asciz "*** POST WARNING = " |
49 | end_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 | ***************************************/ | |
71 | test_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 | ||
53677ef1 | 78 | WATCHDOG_RESET /* Reset the watchdog */ |
c609719b WD |
79 | |
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 */ | |
93 | LED2: 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 | ||
107 | LED3: /* 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 | ***************************************/ | |
119 | test_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 */ | |
132 | l2_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 */ | |
53677ef1 | 140 | WATCHDOG_RESET /* Reset the watchdog */ |
c609719b WD |
141 | 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 | ***************************************/ | |
159 | Data_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 | ||
196 | db_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 | ||
208 | Ghost_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 */ | |
237 | clr_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 */ | |
53677ef1 | 242 | WATCHDOG_RESET /* kick the dog every now and then */ |
c609719b WD |
243 | clr_skip: |
244 | bdnz clr_loop /* Round and round... */ | |
245 | ||
246 | /* now do main test */ | |
247 | addi r30, 0, 0 /* start referance counter at 0 */ | |
248 | outside: | |
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 | */ | |
53677ef1 | 257 | WATCHDOG_RESET /* Reset the watchdog */ |
c609719b WD |
258 | |
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 | ||
8bde7f77 | 267 | /* ghost (inner) loop, now check all posible ghosted addresses */ |
c609719b WD |
268 | addi r29, 0, 0 /* start ghosted loop counter at 0 */ |
269 | inside: | |
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 */ | |
53677ef1 WD |
286 | addi r29, r29, 1 /* increment inner loop counter */ |
287 | cmpw r29, r26 /* check for last inner loop */ | |
c609719b WD |
288 | blt inside /* do more inner loops */ |
289 | ||
290 | /* now close referance ( outer ) loop */ | |
53677ef1 | 291 | addi r31, 0, 0 /* r31 = zero */ |
c609719b WD |
292 | 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 | */ | |
53677ef1 WD |
298 | addi r30, r30, 1 /* increment outer loop counter */ |
299 | cmpw r30, r26 /* check for last inner loop */ | |
c609719b WD |
300 | ble outside /* do more outer loops */ |
301 | ||
302 | /* were done, lets go home */ | |
303 | b gb_done | |
304 | Casper: /* we found a ghost !! */ | |
305 | addi r3, 0, ERR_ADDF /* get indexed error message */ | |
306 | bl log_err /* log error led error code */ | |
307 | gb_done: /* pack your bags, and go home */ | |
8bde7f77 WD |
308 | 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 */ | |
c609719b WD |
313 | |
314 | /**************************************************** | |
315 | ******** SDRAM data fill tests ********** | |
316 | ***************************************************/ | |
317 | Bit_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 | ||
c609719b WD |
358 | /**************************************************** |
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 */ | |
365 | fill_test: | |
8bde7f77 WD |
366 | 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 */ | |
c609719b WD |
372 | mr r27, r3 |
373 | mr r28, r4 | |
374 | mr r29, r5 | |
375 | ||
53677ef1 | 376 | WATCHDOG_RESET /* Reset the watchdog */ |
c609719b WD |
377 | |
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 */ | |
382 | ft_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 */ | |
53677ef1 | 386 | WATCHDOG_RESET /* kick the dog every now and then */ |
c609719b WD |
387 | ft_0a: bdnz ft_0 /* Round and round... */ |
388 | ||
53677ef1 | 389 | WATCHDOG_RESET /* Reset the watchdog */ |
c609719b WD |
390 | |
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 */ | |
395 | ft_1: lwz r31, 0(r30) /* get value from memory */ | |
8bde7f77 WD |
396 | xor. r31, r31, r28 /* Writen = Read ? */ |
397 | bne ft_err /* If bad, than halt */ | |
c609719b WD |
398 | 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 */ | |
402 | ft_1a: bdnz ft_1 /* Round and round... */ | |
403 | ||
53677ef1 | 404 | WATCHDOG_RESET /* Reset the watchdog */ |
c609719b WD |
405 | |
406 | b fill_done /* restore and return */ | |
407 | ||
408 | ft_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 | ||
414 | fill_done: | |
8bde7f77 WD |
415 | 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 */ | |
c609719b WD |
420 | |
421 | ||
422 | /**************************************************** | |
423 | ******* get error index from r3 pattern ******** | |
424 | ***************************************************/ | |
425 | get_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 | |
439 | gi2: 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 | |
443 | gi3: addi r3, 0, 1 /* only lower bits set */ | |
444 | b gi_done | |
445 | gi4: addi r3, 0, 0 /* no bits set */ | |
446 | gi_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 | ***************************************************/ | |
457 | log_stat: /* output a led code and continue */ | |
458 | set_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 | ||
481 | get_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 | ||
501 | log_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 */ | |
516 | halt: | |
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 | ||
525 | log_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 | |
545 | log_2: | |
546 | WATCHDOG_RESET /* this keeps dog from barking, */ | |
8bde7f77 | 547 | /* and takes time */ |
c609719b WD |
548 | 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 | ******************************************************************/ | |
563 | temp_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 | ||
8bde7f77 WD |
569 | 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) | |
c609719b WD |
573 | |
574 | /* set baud rate to use internal clock, | |
575 | baud = (200e6/16)/31/42 = 9600 */ | |
576 | ||
8bde7f77 WD |
577 | 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 */ | |
c609719b | 581 | |
8bde7f77 WD |
582 | addi r3, r3, 0x0001 /* uart baud divisor addr */ |
583 | addi r4, 0, 0 | |
584 | stb r4, 0(r3) /* Divisor Latch MSB = 0 */ | |
c609719b | 585 | |
8bde7f77 WD |
586 | 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) | |
c609719b WD |
590 | |
591 | /* output a few line feeds */ | |
592 | addi r3, 0, '\n' /* load line feed */ | |
53677ef1 | 593 | bl post_putc /* output the char */ |
c609719b | 594 | addi r3, 0, '\n' /* load line feed */ |
53677ef1 | 595 | bl post_putc /* output the char */ |
c609719b | 596 | |
8bde7f77 | 597 | /* restore stack and return */ |
c609719b WD |
598 | 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 | ||
609 | post_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 | |
8bde7f77 | 617 | r30 - delay counter |
c609719b WD |
618 | r29 - scratch reg */ |
619 | ||
620 | addis r31, 0, 0xef60 /* Point to uart base */ | |
621 | ori r31, r31, 0x0300 | |
53677ef1 | 622 | addis r30, 0, 152 /* Load about 10,000,000 ticks. */ |
c609719b | 623 | pputc_lp: |
53677ef1 | 624 | lbz r29, 5(r31) /* Read Line Status Register */ |
c609719b WD |
625 | 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 */ | |
53677ef1 | 630 | b pputc_done /* Bail out with error code set */ |
c609719b WD |
631 | thre_set: |
632 | stb r3, 0(r31) /* Store character to UART */ | |
633 | addi r3, 0, 0 /* clear error code */ | |
634 | pputc_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 | *****************************************************************/ | |
648 | post_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 | ||
53677ef1 | 656 | addi r31, r3, 0 /* move pointer to R31 */ |
c609719b WD |
657 | pputs_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 | |
53677ef1 WD |
664 | addi r31, r31, 1 /* point to next char */ |
665 | b pputs_nxt /* loop till term */ | |
c609719b | 666 | pputs_err: |
53677ef1 | 667 | addi r3, 0, -1 /* set error code */ |
c609719b WD |
668 | b pputs_end /* were outa here */ |
669 | pputs_term: | |
53677ef1 | 670 | addi r3, 0, 1 /* set success code */ |
8bde7f77 | 671 | /* restore stack and return */ |
c609719b WD |
672 | pputs_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 | ||
c609719b WD |
680 | /******************************************************************** |
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 | *******************************************************************/ | |
688 | disp_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 */ | |
53677ef1 WD |
696 | addi r30, 0, 8 /* Go through 8 nibbles. */ |
697 | addi r31, r3, 0 | |
c609719b WD |
698 | pputh_nxt: |
699 | rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */ | |
53677ef1 WD |
700 | andi. r3, r31, 0x0f /* Get nibble. */ |
701 | addi r3, r3, 0x30 /* Add zero's ASCII code. */ | |
c609719b WD |
702 | cmpwi r3, 0x03a |
703 | blt pputh_out | |
53677ef1 | 704 | addi r3, r3, 0x07 /* 0x27 for lower case. */ |
c609719b | 705 | pputh_out: |
53677ef1 | 706 | cmpw r30, r4 |
c609719b WD |
707 | bgt pputh_skip |
708 | bl post_putc | |
53677ef1 | 709 | addic. r3, r3, 0 /* check for error */ |
c609719b WD |
710 | bne pputh_err |
711 | pputh_skip: | |
712 | addic. r30, r30, -1 | |
713 | bne pputh_nxt | |
714 | xor r3, r3, r3 /* Clear error code */ | |
715 | b pputh_done | |
716 | pputh_err: | |
53677ef1 | 717 | addi r3, 0, -1 /* set error code */ |
c609719b | 718 | pputh_done: |
8bde7f77 | 719 | /* restore stack and return */ |
c609719b WD |
720 | 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 */ |