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