Commit afd7f3d0de7be71ee90478d4dde00dc1a8f9d204
1 parent
f18f47f4d4
Exists in
master
and in
55 other branches
Initial revision
Showing 4 changed files with 3073 additions and 0 deletions Side-by-side Diff
board/bmw/early_init.S
Changes suppressed. Click to show
1 | +#include <ppc_asm.tmpl> | |
2 | +#include <mpc824x.h> | |
3 | +#include <ppc_defs.h> | |
4 | +#include <asm/cache.h> | |
5 | +#include <asm/mmu.h> | |
6 | + | |
7 | +#define USE_V2_INIT 1 /* Jimmy Blair's initialization. */ | |
8 | + | |
9 | + | |
10 | +/* | |
11 | + * Initialize the MMU using BAT entries and hardwired TLB | |
12 | + * This obviates the need for any code in cpu_init_f which | |
13 | + * configures the BAT registers. | |
14 | +*/ | |
15 | +#define MEMORY_MGMT_MSR_BITS (MSR_DR | MSR_IR) /* Data and Inst Relocate */ | |
16 | + .global iommu_setup | |
17 | + /* Initialize IO/MMU mappings via BAT method Ch. 7, | |
18 | + * PPC Programming Reference | |
19 | + */ | |
20 | +iommu_setup: | |
21 | + | |
22 | +/* initialize the BAT registers (SPRs 528 - 543 */ | |
23 | +#define mtibat0u(x) mtspr 528,(x) /* SPR 528 (IBAT0U) */ | |
24 | +#define mtibat0l(x) mtspr 529,(x) /* SPR 529 (IBAT0L) */ | |
25 | +#define mtibat1u(x) mtspr 530,(x) /* SPR 530 (IBAT1U) */ | |
26 | +#define mtibat1l(x) mtspr 531,(x) /* SPR 531 (IBAT1L) */ | |
27 | +#define mtibat2u(x) mtspr 532,(x) /* SPR 532 (IBAT2U) */ | |
28 | +#define mtibat2l(x) mtspr 533,(x) /* SPR 533 (IBAT2L) */ | |
29 | +#define mtibat3u(x) mtspr 534,(x) /* SPR 534 (IBAT3U) */ | |
30 | +#define mtibat3l(x) mtspr 535,(x) /* SPR 535 (IBAT3L) */ | |
31 | +#define mtdbat0u(x) mtspr 536,(x) /* SPR 536 (DBAT0U) */ | |
32 | +#define mtdbat0l(x) mtspr 537,(x) /* SPR 537 (DBAT0L) */ | |
33 | +#define mtdbat1u(x) mtspr 538,(x) /* SPR 538 (DBAT1U) */ | |
34 | +#define mtdbat1l(x) mtspr 539,(x) /* SPR 539 (DBAT1L) */ | |
35 | +#define mtdbat2u(x) mtspr 540,(x) /* SPR 540 (DBAT2U) */ | |
36 | +#define mtdbat2l(x) mtspr 541,(x) /* SPR 541 (DBAT2L) */ | |
37 | +#define mtdbat3u(x) mtspr 542,(x) /* SPR 542 (DBAT3U) */ | |
38 | +#define mtdbat3l(x) mtspr 543,(x) /* SPR 543 (DBAT3L) */ | |
39 | + | |
40 | + | |
41 | +/* PowerPC processors do not necessarily initialize the BAT | |
42 | + registers on power-up or reset. So they are in an unknown | |
43 | + state. Before programming the BATs for the first time, all | |
44 | + BAT registers MUST have their Vs and Vp bits cleared in the | |
45 | + upper BAT half in order to avoid possibly having 2 BATs | |
46 | + valid and mapping the same memory region. | |
47 | + | |
48 | + The reason for this is that, even with address translation | |
49 | + disabled, multiple BAT hits for an address are treated as | |
50 | + programming errors and can cause unpredictable results. | |
51 | + | |
52 | + It is up to the software to make sure it never has 2 IBAT | |
53 | + mappings or 2 DBAT mappings that are valid for the same | |
54 | + addresses. It is not necessary to perform this code | |
55 | + sequence every time the BATs are programmed, only when | |
56 | + there is a possibility that there may be overlapping BAT | |
57 | + entries. | |
58 | + | |
59 | + When programming the BATs in non-reset scenarios, even if | |
60 | + you are sure that your new mapping will not temporarily | |
61 | + create overlapping regions, it is still a wise idea to | |
62 | + invalidate a BAT entry by setting its upper BAT register to | |
63 | + all 0's before programming it. This will avoid having a | |
64 | + BAT marked valid that is in an unknown or transient state | |
65 | +*/ | |
66 | + | |
67 | + addis r5,0,0x0000 | |
68 | + mtibat0u(r5) | |
69 | + mtibat0l(r5) | |
70 | + mtibat1u(r5) | |
71 | + mtibat1l(r5) | |
72 | + mtibat2u(r5) | |
73 | + mtibat2l(r5) | |
74 | + mtibat3u(r5) | |
75 | + mtibat3l(r5) | |
76 | + mtdbat0u(r5) | |
77 | + mtdbat0l(r5) | |
78 | + mtdbat1u(r5) | |
79 | + mtdbat1l(r5) | |
80 | + mtdbat2u(r5) | |
81 | + mtdbat2l(r5) | |
82 | + mtdbat3u(r5) | |
83 | + mtdbat3l(r5) | |
84 | + isync | |
85 | + | |
86 | +/* | |
87 | + * Set up I/D BAT0 | |
88 | + */ | |
89 | + lis r4, CFG_DBAT0L@h | |
90 | + ori r4, r4, CFG_DBAT0L@l | |
91 | + lis r3, CFG_DBAT0U@h | |
92 | + ori r3, r3, CFG_DBAT0U@l | |
93 | + | |
94 | + mtdbat0l(r4) | |
95 | + isync | |
96 | + mtdbat0u(r3) | |
97 | + isync | |
98 | + sync | |
99 | + | |
100 | + lis r4, CFG_IBAT0L@h | |
101 | + ori r4, r4, CFG_IBAT0L@l | |
102 | + lis r3, CFG_IBAT0U@h | |
103 | + ori r3, r3, CFG_IBAT0U@l | |
104 | + | |
105 | + isync | |
106 | + mtibat0l(r4) | |
107 | + isync | |
108 | + mtibat0u(r3) | |
109 | + isync | |
110 | + | |
111 | +/* | |
112 | + * Set up I/D BAT1 | |
113 | + */ | |
114 | + lis r4, CFG_IBAT1L@h | |
115 | + ori r4, r4, CFG_IBAT1L@l | |
116 | + lis r3, CFG_IBAT1U@h | |
117 | + ori r3, r3, CFG_IBAT1U@l | |
118 | + | |
119 | + isync | |
120 | + mtibat1l(r4) | |
121 | + isync | |
122 | + mtibat1u(r3) | |
123 | + isync | |
124 | + mtdbat1l(r4) | |
125 | + isync | |
126 | + mtdbat1u(r3) | |
127 | + isync | |
128 | + sync | |
129 | + | |
130 | +/* | |
131 | + * Set up I/D BAT2 | |
132 | + */ | |
133 | + lis r4, CFG_IBAT2L@h | |
134 | + ori r4, r4, CFG_IBAT2L@l | |
135 | + lis r3, CFG_IBAT2U@h | |
136 | + ori r3, r3, CFG_IBAT2U@l | |
137 | + | |
138 | + isync | |
139 | + mtibat2l(r4) | |
140 | + isync | |
141 | + mtibat2u(r3) | |
142 | + isync | |
143 | + mtdbat2l(r4) | |
144 | + isync | |
145 | + mtdbat2u(r3) | |
146 | + isync | |
147 | + sync | |
148 | + | |
149 | +/* | |
150 | + * Setup I/D BAT3 | |
151 | + */ | |
152 | + lis r4, CFG_IBAT3L@h | |
153 | + ori r4, r4, CFG_IBAT3L@l | |
154 | + lis r3, CFG_IBAT3U@h | |
155 | + ori r3, r3, CFG_IBAT3U@l | |
156 | + | |
157 | + isync | |
158 | + mtibat3l(r4) | |
159 | + isync | |
160 | + mtibat3u(r3) | |
161 | + isync | |
162 | + mtdbat3l(r4) | |
163 | + isync | |
164 | + mtdbat3u(r3) | |
165 | + isync | |
166 | + sync | |
167 | + | |
168 | + | |
169 | +/* | |
170 | + * Invalidate all 64 TLB's | |
171 | + */ | |
172 | + lis r3, 0 | |
173 | + mtctr r3 | |
174 | + lis r5, 4 | |
175 | + | |
176 | +tlblp: | |
177 | + tlbie r3 | |
178 | + sync | |
179 | + addi r3, r3, 0x1000 | |
180 | + cmplw r3, r5 | |
181 | + blt tlblp | |
182 | + | |
183 | + sync | |
184 | + | |
185 | +/* | |
186 | + * Enable Data Translation | |
187 | + */ | |
188 | + lis r4, MEMORY_MGMT_MSR_BITS@h | |
189 | + ori r4, r4, MEMORY_MGMT_MSR_BITS@l | |
190 | + mfmsr r3 | |
191 | + or r3, r4, r3 | |
192 | + mtmsr r3 | |
193 | + isync | |
194 | + sync | |
195 | + | |
196 | + blr | |
197 | + | |
198 | + | |
199 | +#ifdef USE_V2_INIT | |
200 | +/* #define USER_I_CACHE_ENABLE 1*/ /* Fast rom boots */ | |
201 | +/* Macro for hiadjust and lo */ | |
202 | +#define HIADJ(arg) arg@ha | |
203 | +#define HI(arg) arg@h | |
204 | +#define LO(arg) arg@l | |
205 | + | |
206 | +#undef LOADPTR | |
207 | +#define LOADPTR(reg,const32) \ | |
208 | + addis reg,r0,HIADJ(const32); addi reg,reg,LO(const32) | |
209 | + | |
210 | +.globl early_init_f | |
211 | + | |
212 | +early_init_f: | |
213 | +/* MPC8245/BMW CPCI System Init | |
214 | + * Jimmy Blair, Broadcom Corp, 2002. | |
215 | + */ | |
216 | + mflr r11 | |
217 | + /* Zero-out registers */ | |
218 | + | |
219 | + addis r0,r0,0 | |
220 | + mtspr SPRG0,r0 | |
221 | + mtspr SPRG1,r0 | |
222 | + mtspr SPRG2,r0 | |
223 | + mtspr SPRG3,r0 | |
224 | + | |
225 | + /* Set MPU/MSR to a known state. Turn on FP */ | |
226 | + | |
227 | + LOADPTR (r3, MSR_FP) | |
228 | + sync | |
229 | + mtmsr r3 | |
230 | + isync | |
231 | + | |
232 | + /* Init the floating point control/status register */ | |
233 | + | |
234 | + mtfsfi 7,0x0 | |
235 | + mtfsfi 6,0x0 | |
236 | + mtfsfi 5,0x0 | |
237 | + mtfsfi 4,0x0 | |
238 | + mtfsfi 3,0x0 | |
239 | + mtfsfi 2,0x0 | |
240 | + mtfsfi 1,0x0 | |
241 | + mtfsfi 0,0x0 | |
242 | + isync | |
243 | + | |
244 | + /* Set MPU/MSR to a known state. Turn off FP */ | |
245 | + | |
246 | +#if 1 /* Turn off floating point (remove to keep FP on) */ | |
247 | + andi. r3, r3, 0 | |
248 | + sync | |
249 | + mtmsr r3 | |
250 | + isync | |
251 | +#endif | |
252 | + | |
253 | + /* Init the Segment registers */ | |
254 | + | |
255 | + andi. r3, r3, 0 | |
256 | + isync | |
257 | + mtsr 0,r3 | |
258 | + isync | |
259 | + mtsr 1,r3 | |
260 | + isync | |
261 | + mtsr 2,r3 | |
262 | + isync | |
263 | + mtsr 3,r3 | |
264 | + isync | |
265 | + mtsr 4,r3 | |
266 | + isync | |
267 | + mtsr 5,r3 | |
268 | + isync | |
269 | + mtsr 6,r3 | |
270 | + isync | |
271 | + mtsr 7,r3 | |
272 | + isync | |
273 | + mtsr 8,r3 | |
274 | + isync | |
275 | + mtsr 9,r3 | |
276 | + isync | |
277 | + mtsr 10,r3 | |
278 | + isync | |
279 | + mtsr 11,r3 | |
280 | + isync | |
281 | + mtsr 12,r3 | |
282 | + isync | |
283 | + mtsr 13,r3 | |
284 | + isync | |
285 | + mtsr 14,r3 | |
286 | + isync | |
287 | + mtsr 15,r3 | |
288 | + isync | |
289 | + | |
290 | + /* Turn off data and instruction cache control bits */ | |
291 | + | |
292 | + mfspr r3, HID0 | |
293 | + isync | |
294 | + rlwinm r4, r3, 0, 18, 15 /* r4 has ICE and DCE bits cleared */ | |
295 | + sync | |
296 | + isync | |
297 | + mtspr HID0, r4 /* HID0 = r4 */ | |
298 | + isync | |
299 | + | |
300 | + /* Get cpu type */ | |
301 | + | |
302 | + mfspr r28, PVR | |
303 | + rlwinm r28, r28, 16, 16, 31 | |
304 | + | |
305 | + /* invalidate the MPU's data/instruction caches */ | |
306 | + | |
307 | + lis r3, 0x0 | |
308 | + cmpli 0, 0, r28, CPU_TYPE_603 | |
309 | + beq cpuIs603 | |
310 | + cmpli 0, 0, r28, CPU_TYPE_603E | |
311 | + beq cpuIs603 | |
312 | + cmpli 0, 0, r28, CPU_TYPE_603P | |
313 | + beq cpuIs603 | |
314 | + cmpli 0, 0, r28, CPU_TYPE_604R | |
315 | + bne cpuNot604R | |
316 | + | |
317 | +cpuIs604R: | |
318 | + lis r3, 0x0 | |
319 | + mtspr HID0, r3 /* disable the caches */ | |
320 | + isync | |
321 | + ori r4, r4, 0x0002 /* disable BTAC by setting bit 30 */ | |
322 | + | |
323 | +cpuNot604R: | |
324 | + ori r3, r3, (HID0_ICFI |HID0_DCI) | |
325 | + | |
326 | +cpuIs603: | |
327 | + ori r3, r3, (HID0_ICE | HID0_DCE) | |
328 | + or r4, r4, r3 /* set bits */ | |
329 | + sync | |
330 | + isync | |
331 | + mtspr HID0, r4 /* HID0 = r4 */ | |
332 | + andc r4, r4, r3 /* clear bits */ | |
333 | + isync | |
334 | + cmpli 0, 0, r28, CPU_TYPE_604 | |
335 | + beq cpuIs604 | |
336 | + cmpli 0, 0, r28, CPU_TYPE_604E | |
337 | + beq cpuIs604 | |
338 | + cmpli 0, 0, r28, CPU_TYPE_604R | |
339 | + beq cpuIs604 | |
340 | + mtspr HID0, r4 | |
341 | + isync | |
342 | + | |
343 | +#ifdef USER_I_CACHE_ENABLE | |
344 | + b instCacheOn603 | |
345 | +#else | |
346 | + b cacheEnableDone | |
347 | +#endif | |
348 | + | |
349 | +cpuIs604: | |
350 | + LOADPTR (r5, 0x1000) /* loop count, 0x1000 */ | |
351 | + mtspr CTR, r5 | |
352 | +loopDelay: | |
353 | + nop | |
354 | + bdnz loopDelay | |
355 | + isync | |
356 | + mtspr HID0, r4 | |
357 | + isync | |
358 | + | |
359 | + /* turn the Instruction cache ON for faster FLASH ROM boots */ | |
360 | + | |
361 | +#ifdef USER_I_CACHE_ENABLE | |
362 | + | |
363 | + ori r4, r4, (HID0_ICE | HID0_ICFI) | |
364 | + isync /* Synchronize for ICE enable */ | |
365 | + b writeReg4 | |
366 | +instCacheOn603: | |
367 | + ori r4, r4, (HID0_ICE | HID0_ICFI) | |
368 | + rlwinm r3, r4, 0, 21, 19 /* clear the ICFI bit */ | |
369 | + | |
370 | + /* | |
371 | + * The setting of the instruction cache enable (ICE) bit must be | |
372 | + * preceded by an isync instruction to prevent the cache from being | |
373 | + * enabled or disabled while an instruction access is in progress. | |
374 | + */ | |
375 | + isync | |
376 | +writeReg4: | |
377 | + mtspr HID0, r4 /* Enable Instr Cache & Inval cache */ | |
378 | + cmpli 0, 0, r28, CPU_TYPE_604 | |
379 | + beq cacheEnableDone | |
380 | + cmpli 0, 0, r28, CPU_TYPE_604E | |
381 | + beq cacheEnableDone | |
382 | + | |
383 | + mtspr HID0, r3 /* using 2 consec instructions */ | |
384 | + /* PPC603 recommendation */ | |
385 | +#endif | |
386 | +cacheEnableDone: | |
387 | + | |
388 | + /* Detect map A or B */ | |
389 | + | |
390 | + addis r5,r0, HI(CHRP_REG_ADDR) | |
391 | + addis r6,r0, HI(CHRP_REG_DATA) | |
392 | + LOADPTR (r7, KAHLUA_ID) /* Kahlua PCI controller ID */ | |
393 | + LOADPTR (r8, BMC_BASE) | |
394 | + | |
395 | + stwbrx r8,0,(r5) | |
396 | + lwbrx r3,0,(r6) /* Store read value to r3 */ | |
397 | + cmp 0,0,r3,r7 | |
398 | + beq cr0, X4_KAHLUA_START | |
399 | + | |
400 | + /* It's not an 8240, is it an 8245? */ | |
401 | + | |
402 | + LOADPTR (r7, KAHLUA2_ID) /* Kahlua PCI controller ID */ | |
403 | + cmp 0,0,r3,r7 | |
404 | + beq cr0, X4_KAHLUA_START | |
405 | + | |
406 | + /* Save the PCI controller type in r7 */ | |
407 | + mr r7, r3 | |
408 | + | |
409 | + LOADPTR (r5, PREP_REG_ADDR) | |
410 | + LOADPTR (r6, PREP_REG_DATA) | |
411 | + | |
412 | +X4_KAHLUA_START: | |
413 | + /* MPC8245 changes begin here */ | |
414 | + LOADPTR (r3, MPC107_PCI_CMD) /* PCI command reg */ | |
415 | + stwbrx r3,0,r5 | |
416 | + li r4, 6 /* Command register value */ | |
417 | + sthbrx r4, 0, r6 | |
418 | + | |
419 | + LOADPTR (r3, MPC107_PCI_STAT) /* PCI status reg */ | |
420 | + stwbrx r3,0,r5 | |
421 | + li r4, -1 /* Write-to-clear all bits */ | |
422 | + li r3, 2 /* PCI_STATUS is at +2 offset */ | |
423 | + sthbrx r4, r3, r6 | |
424 | + | |
425 | + /*-------PROC_INT1_ADR */ | |
426 | + | |
427 | + LOADPTR (r3, PROC_INT1_ADR) /* Processor I/F Config 1 reg. */ | |
428 | + stwbrx r3,0,r5 | |
429 | + LOADPTR (r4, 0xff141b98) | |
430 | + stwbrx r4,0,r6 | |
431 | + | |
432 | + /*-------PROC_INT2_ADR */ | |
433 | + | |
434 | + LOADPTR (r3, PROC_INT2_ADR) /* Processor I/F Config 2 reg. */ | |
435 | + stwbrx r3,0,r5 | |
436 | + lis r4, 0x2000 /* Flush PCI config writes */ | |
437 | + stwbrx r4,0,r6 | |
438 | + | |
439 | + LOADPTR (r9, KAHLUA2_ID) | |
440 | + cmpl 0, 0, r7, r9 | |
441 | + bne L1not8245 | |
442 | + | |
443 | + /* MIOCR1 -- turn on bit for DLL delay */ | |
444 | + | |
445 | + LOADPTR (r3, MIOCR1_ADR_X) | |
446 | + stwbrx r3,0,r5 | |
447 | + li r4, 0x04 | |
448 | + stb r4, MIOCR1_SHIFT(r6) | |
449 | + | |
450 | + /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */ | |
451 | + /* SDRAM_CLK_DEL (0x77)*/ | |
452 | + | |
453 | + LOADPTR (r3, MIOCR2_ADR_X) | |
454 | + stwbrx r3,0,r5 | |
455 | + li r4, 0x10 | |
456 | + stb r4, MIOCR2_SHIFT(r6) | |
457 | + | |
458 | + /* PMCR2 -- set PCI hold delay to <10>b for 33 MHz */ | |
459 | + | |
460 | + LOADPTR (r3, PMCR2_ADR_X) | |
461 | + stwbrx r3,0,r5 | |
462 | + li r4, 0x20 | |
463 | + stb r4, PMCR2_SHIFT(r6) | |
464 | + | |
465 | + /* Initialize EUMBBAR early since 8245 has internal UART in EUMB */ | |
466 | + | |
467 | + LOADPTR (r3, EUMBBAR) | |
468 | + stwbrx r3,0,r5 | |
469 | + LOADPTR (r4, CFG_EUMB_ADDR) | |
470 | + stwbrx r4,0,r6 | |
471 | + | |
472 | +L1not8245: | |
473 | + | |
474 | + /* Toggle the DLL reset bit in AMBOR */ | |
475 | + | |
476 | + LOADPTR (r3, AMBOR) | |
477 | + stwbrx r3,0,r5 | |
478 | + lbz r4, 0(r6) | |
479 | + | |
480 | + andi. r4, r4, 0xdf | |
481 | + stb r4, 0(r6) /* Clear DLL_RESET */ | |
482 | + sync | |
483 | + | |
484 | + ori r4, r4, 0x20 /* Set DLL_RESET */ | |
485 | + stb r4, 0(r6) | |
486 | + sync | |
487 | + | |
488 | + andi. r4, r4, 0xdf | |
489 | + stb r4, 0(r6) /* Clear DLL_RESET */ | |
490 | + | |
491 | + | |
492 | + /* Enable RCS2, use supplied timings */ | |
493 | + LOADPTR (r3, ERCR1) | |
494 | + stwbrx r3,0,r5 | |
495 | + LOADPTR (r4, 0x80408000) | |
496 | + stwbrx r4,0,r6 | |
497 | + | |
498 | + /* Disable RCS3 parameters */ | |
499 | + LOADPTR (r3, ERCR2) | |
500 | + stwbrx r3,0,r5 | |
501 | + LOADPTR (r4, 0x00000000) | |
502 | + stwbrx r4,0,r6 | |
503 | + | |
504 | + /* RCS3 at 0x70000000, 64KBytes */ | |
505 | + LOADPTR (r3, ERCR2) | |
506 | + stwbrx r3,0,r5 | |
507 | + LOADPTR (r4, 0x00000004) | |
508 | + stwbrx r4,0,r6 | |
509 | + | |
510 | + /*-------MCCR1 */ | |
511 | + | |
512 | +#ifdef INCLUDE_ECC | |
513 | +#define MC_ECC 1 | |
514 | +#else /* INCLUDE_ECC */ | |
515 | +#define MC_ECC 0 | |
516 | +#endif /* INCLUDE_ECC */ | |
517 | + | |
518 | +#define MC1_ROMNAL 8 /* 0-15 */ | |
519 | +#define MC1_ROMFAL 11 /* 0-31 */ | |
520 | +#define MC1_DBUS_SIZE 0 /* 0-3, read only */ | |
521 | +#define MC1_BURST 0 /* 0-1 */ | |
522 | +#define MC1_MEMGO 0 /* 0-1 */ | |
523 | +#define MC1_SREN 1 /* 0-1 */ | |
524 | +#define MC1_RAM_TYPE 0 /* 0-1 */ | |
525 | +#define MC1_PCKEN MC_ECC /* 0-1 */ | |
526 | +#define MC1_BANKBITS 0x5555 /* 2 bits/bank 7-0 */ | |
527 | + | |
528 | + LOADPTR (r3, MEM_CONT1_ADR) /* Set MCCR1 (F0) */ | |
529 | + stwbrx r3,0,r5 | |
530 | + LOADPTR(r4, \ | |
531 | + MC1_ROMNAL << 28 | MC1_ROMFAL << 23 | \ | |
532 | + MC1_DBUS_SIZE << 21 | MC1_BURST << 20 | \ | |
533 | + MC1_MEMGO << 19 | MC1_SREN << 18 | \ | |
534 | + MC1_RAM_TYPE << 17 | MC1_PCKEN << 16 ) | |
535 | + li r3, MC1_BANKBITS | |
536 | + cmpl 0, 0, r7, r9 /* Check for Kahlua2 */ | |
537 | + bne BankBitsAdd | |
538 | + cmpli 0, 0, r3, 0x5555 | |
539 | + beq K2BankBitsHack /* On 8245, 5555 ==> 0 */ | |
540 | +BankBitsAdd: | |
541 | + ori r4, r3, 0 | |
542 | +K2BankBitsHack: | |
543 | + stwbrx r4, 0, r6 | |
544 | + | |
545 | + /*------- MCCR2 */ | |
546 | + | |
547 | +#define MC2_TS_WAIT_TIMER 0 /* 0-7 */ | |
548 | +#define MC2_ASRISE 8 /* 0-15 */ | |
549 | +#define MC2_ASFALL 4 /* 0-15 */ | |
550 | +#define MC2_INLINE_PAR_NOT_ECC 0 /* 0-1 */ | |
551 | +#define MC2_WRITE_PARITY_CHK_EN MC_ECC /* 0-1 */ | |
552 | +#define MC2_INLRD_PARECC_CHK_EN MC_ECC /* 0-1 */ | |
553 | +#define MC2_ECC_EN 0 /* 0-1 */ | |
554 | +#define MC2_EDO 0 /* 0-1 */ | |
555 | +/* | |
556 | +* N.B. This refresh interval looks good up to 85 MHz with Hynix SDRAM. | |
557 | +* May need to be decreased for 100 MHz | |
558 | +*/ | |
559 | +#define MC2_REFINT 0x3a5 /* 0-0x3fff */ | |
560 | +#define MC2_RSV_PG 0 /* 0-1 */ | |
561 | +#define MC2_RMW_PAR MC_ECC /* 0-1 */ | |
562 | + | |
563 | + LOADPTR (r3, MEM_CONT2_ADR) /* Set MCCR2 (F4) */ | |
564 | + stwbrx r3,0,r5 | |
565 | + LOADPTR(r4, \ | |
566 | + MC2_TS_WAIT_TIMER << 29 | MC2_ASRISE << 25 | \ | |
567 | + MC2_ASFALL << 21 | MC2_INLINE_PAR_NOT_ECC << 20 | \ | |
568 | + MC2_WRITE_PARITY_CHK_EN << 19 | \ | |
569 | + MC2_INLRD_PARECC_CHK_EN << 18 | \ | |
570 | + MC2_ECC_EN << 17 | MC2_EDO << 16 | \ | |
571 | + MC2_REFINT << 2 | MC2_RSV_PG << 1 | MC2_RMW_PAR) | |
572 | + cmpl 0, 0, r7, r9 /* Check for Kahlua2 */ | |
573 | + bne notK2 | |
574 | + /* clear Kahlua2 reserved bits */ | |
575 | + LOADPTR (r3, 0xfffcffff) | |
576 | + and r4, r4, r3 | |
577 | +notK2: | |
578 | + stwbrx r4,0,r6 | |
579 | + | |
580 | + /*------- MCCR3 */ | |
581 | + | |
582 | +#define MC_BSTOPRE 0x079 /* 0-0x7ff */ | |
583 | + | |
584 | +#define MC3_BSTOPRE_U (MC_BSTOPRE >> 4 & 0xf) | |
585 | +#define MC3_REFREC 8 /* 0-15 */ | |
586 | +#define MC3_RDLAT (4+MC_ECC) /* 0-15 */ | |
587 | +#define MC3_CPX 0 /* 0-1 */ | |
588 | +#define MC3_RAS6P 0 /* 0-15 */ | |
589 | +#define MC3_CAS5 0 /* 0-7 */ | |
590 | +#define MC3_CP4 0 /* 0-7 */ | |
591 | +#define MC3_CAS3 0 /* 0-7 */ | |
592 | +#define MC3_RCD2 0 /* 0-7 */ | |
593 | +#define MC3_RP1 0 /* 0-7 */ | |
594 | + | |
595 | + LOADPTR (r3, MEM_CONT3_ADR) /* Set MCCR3 (F8) */ | |
596 | + stwbrx r3,0,r5 | |
597 | + LOADPTR(r4, \ | |
598 | + MC3_BSTOPRE_U << 28 | MC3_REFREC << 24 | \ | |
599 | + MC3_RDLAT << 20 | MC3_CPX << 19 | \ | |
600 | + MC3_RAS6P << 15 | MC3_CAS5 << 12 | MC3_CP4 << 9 | \ | |
601 | + MC3_CAS3 << 6 | MC3_RCD2 << 3 | MC3_RP1) | |
602 | + cmpl 0, 0, r7, r9 /* Check for Kahlua2 */ | |
603 | + bne notK2b | |
604 | + /* clear Kahlua2 reserved bits */ | |
605 | + LOADPTR (r3, 0xff000000) | |
606 | + and r4, r4, r3 | |
607 | +notK2b: | |
608 | + stwbrx r4,0,r6 | |
609 | + | |
610 | + /*------- MCCR4 */ | |
611 | + | |
612 | +#define MC4_PRETOACT 3 /* 0-15 */ | |
613 | +#define MC4_ACTOPRE 5 /* 0-15 */ | |
614 | +#define MC4_WMODE 0 /* 0-1 */ | |
615 | +#define MC4_INLINE MC_ECC /* 0-1 */ | |
616 | +#define MC4_REGISTERED (1-MC_ECC) /* 0-1 */ | |
617 | +#define MC4_BSTOPRE_UU (MC_BSTOPRE >> 8 & 3) | |
618 | +#define MC4_REGDIMM 0 /* 0-1 */ | |
619 | +#define MC4_SDMODE_CAS 2 /* 0-7 */ | |
620 | +#define MC4_DBUS_RCS1 1 /* 0-1, 8-bit */ | |
621 | +#define MC4_SDMODE_WRAP 0 /* 0-1 */ | |
622 | +#define MC4_SDMODE_BURST 2 /* 0-7 */ | |
623 | +#define MC4_ACTORW 3 /* 0-15 */ | |
624 | +#define MC4_BSTOPRE_L (MC_BSTOPRE & 0xf) | |
625 | + | |
626 | + LOADPTR (r3, MEM_CONT4_ADR) /* Set MCCR4 (FC) */ | |
627 | + stwbrx r3,0,r5 | |
628 | + LOADPTR(r4, \ | |
629 | + MC4_PRETOACT << 28 | MC4_ACTOPRE << 24 | \ | |
630 | + MC4_WMODE << 23 | MC4_INLINE << 22 | \ | |
631 | + MC4_REGISTERED << 20 | MC4_BSTOPRE_UU << 18 | \ | |
632 | + MC4_DBUS_RCS1 << 17 | \ | |
633 | + MC4_REGDIMM << 15 | MC4_SDMODE_CAS << 12 | \ | |
634 | + MC4_SDMODE_WRAP << 11 | MC4_SDMODE_BURST << 8 | \ | |
635 | + MC4_ACTORW << 4 | MC4_BSTOPRE_L) | |
636 | + cmpl 0, 0, r7, r9 /* Check for Kahlua 2 */ | |
637 | + bne notK2c | |
638 | + /* Turn on Kahlua2 extended ROM space */ | |
639 | + LOADPTR (r3, 0x00200000) | |
640 | + or r4, r4, r3 | |
641 | +notK2c: | |
642 | + stwbrx r4,0,r6 | |
643 | + | |
644 | +#ifdef INCLUDE_ECC | |
645 | + /*------- MEM_ERREN1 */ | |
646 | + | |
647 | + LOADPTR (r3, MEM_ERREN1_ADR) /* Set MEM_ERREN1 (c0) */ | |
648 | + stwbrx r3,0,r5 | |
649 | + lwbrx r4,0,r6 | |
650 | + ori r4,r4,4 /* Set MEM_PERR_EN */ | |
651 | + stwbrx r4,0,r6 | |
652 | +#endif /* INCLUDE_ECC */ | |
653 | + | |
654 | + /*------- MSAR/MEAR */ | |
655 | + | |
656 | + LOADPTR (r3, MEM_START1_ADR) /* Set MSAR1 (80) */ | |
657 | + stwbrx r3,0,r5 | |
658 | + LOADPTR (r4, 0xc0804000) | |
659 | + stwbrx r4,0,r6 | |
660 | + | |
661 | + LOADPTR (r3, MEM_START2_ADR) /* Set MSAR2 (84) */ | |
662 | + stwbrx r3,0,r5 | |
663 | + LOADPTR (r4, 0xc0804000) | |
664 | + stwbrx r4,0,r6 | |
665 | + | |
666 | + LOADPTR (r3, XMEM_START1_ADR) /* Set MESAR1 (88) */ | |
667 | + stwbrx r3,0,r5 | |
668 | + LOADPTR (r4, 0x00000000) | |
669 | + stwbrx r4,0,r6 | |
670 | + | |
671 | + LOADPTR (r3, XMEM_START2_ADR) /* Set MESAR2 (8c) */ | |
672 | + stwbrx r3,0,r5 | |
673 | + LOADPTR (r4, 0x01010101) | |
674 | + stwbrx r4,0,r6 | |
675 | + | |
676 | + LOADPTR (r3, MEM_END1_ADR) /* Set MEAR1 (90) */ | |
677 | + stwbrx r3,0,r5 | |
678 | + LOADPTR (r4, 0xffbf7f3f) | |
679 | + stwbrx r4,0,r6 | |
680 | + | |
681 | + LOADPTR (r3, MEM_END2_ADR) /* Set MEAR2 (94) */ | |
682 | + stwbrx r3,0,r5 | |
683 | + LOADPTR (r4, 0xffbf7f3f) | |
684 | + stwbrx r4,0,r6 | |
685 | + | |
686 | + LOADPTR (r3, XMEM_END1_ADR) /* MEEAR1 (98) */ | |
687 | + stwbrx r3,0,r5 | |
688 | + LOADPTR (r4, 0x00000000) | |
689 | + stwbrx r4,0,r6 | |
690 | + | |
691 | + LOADPTR (r3, XMEM_END2_ADR) /* MEEAR2 (9c) */ | |
692 | + stwbrx r3,0,r5 | |
693 | + LOADPTR (r4, 0x01010101) | |
694 | + stwbrx r4,0,r6 | |
695 | + | |
696 | + /*-------ODCR */ | |
697 | + | |
698 | + LOADPTR (r3, ODCR_ADR_X) /* Set ODCR */ | |
699 | + stwbrx r3,0,r5 | |
700 | + | |
701 | + li r4, 0x7f | |
702 | + stb r4, ODCR_SHIFT(r6) /* ODCR is at +3 offset */ | |
703 | + | |
704 | + /*-------MBEN */ | |
705 | + | |
706 | + LOADPTR (r3, MEM_EN_ADR) /* Set MBEN (a0) */ | |
707 | + stwbrx r3,0,r5 | |
708 | + li r4, 0x01 /* Enable bank 0 */ | |
709 | + stb r4, 0(r6) /* MBEN is at +0 offset */ | |
710 | + | |
711 | +#if 0 /* Jimmy: I think page made is broken */ | |
712 | + /*-------PGMAX */ | |
713 | + | |
714 | + LOADPTR (r3, MPM_ADR_X) | |
715 | + stwbrx r3,0,r5 | |
716 | + li r4, 0x32 | |
717 | + stb r4, MPM_SHIFT(r6) /* PAGE_MODE is at +3 offset */ | |
718 | +#endif | |
719 | + | |
720 | + /* Wait before initializing other registers */ | |
721 | + | |
722 | + lis r4,0x0001 | |
723 | + mtctr r4 | |
724 | + | |
725 | +KahluaX4wait200us: | |
726 | + bdnz KahluaX4wait200us | |
727 | + | |
728 | + /* Set MEMGO bit */ | |
729 | + | |
730 | + LOADPTR (r3, MEM_CONT1_ADR) /* MCCR1 (F0) |= PGMAX */ | |
731 | + stwbrx r3,0,r5 | |
732 | + lwbrx r4,0,r6 /* old MCCR1 */ | |
733 | + oris r4,r4,0x0008 /* MEMGO=1 */ | |
734 | + stwbrx r4, 0, r6 | |
735 | + | |
736 | + /* Wait again */ | |
737 | + | |
738 | + addis r4,r0,0x0002 | |
739 | + ori r4,r4,0xffff | |
740 | + | |
741 | + mtctr r4 | |
742 | + | |
743 | +KahluaX4wait8ref: | |
744 | + bdnz KahluaX4wait8ref | |
745 | + | |
746 | + sync | |
747 | + eieio | |
748 | + mtlr r11 | |
749 | + blr | |
750 | + | |
751 | +#else /* USE_V2_INIT */ | |
752 | + | |
753 | + | |
754 | + | |
755 | +/* U-Boot works, but memory will not run reliably for all address ranges. | |
756 | + * Early U-Boot Working init, but 2.4.19 kernel will crash since memory is not | |
757 | + * initialized correctly. Could work if debugged. | |
758 | + */ | |
759 | +/* PCI Support routines */ | |
760 | + | |
761 | + .globl __pci_config_read_32 | |
762 | +__pci_config_read_32: | |
763 | + lis r4, 0xfec0 | |
764 | + stwbrx r3, r0, r4 | |
765 | + sync | |
766 | + lis r4, 0xfee0 | |
767 | + lwbrx r3, 0, r4 | |
768 | + blr | |
769 | + .globl __pci_config_read_16 | |
770 | +__pci_config_read_16: | |
771 | + lis r4, 0xfec0 | |
772 | + andi. r5, r3, 2 | |
773 | + stwbrx r3, r0, r4 | |
774 | + sync | |
775 | + oris r4, r5, 0xfee0 | |
776 | + lhbrx r3, r0, r4 | |
777 | + blr | |
778 | + .globl __pci_config_read_8 | |
779 | +__pci_config_read_8: | |
780 | + lis r4, 0xfec0 | |
781 | + andi. r5, r3, 3 | |
782 | + stwbrx r3, r0, r4 | |
783 | + sync | |
784 | + oris r4, r5, 0xfee0 | |
785 | + lbz r3, 0(4) | |
786 | + blr | |
787 | + .globl __pci_config_write_32 | |
788 | +__pci_config_write_32: | |
789 | + lis r5, 0xfec0 | |
790 | + stwbrx r3, r0, r5 | |
791 | + sync | |
792 | + lis r5, 0xfee0 | |
793 | + stwbrx r4, r0, r5 | |
794 | + sync | |
795 | + blr | |
796 | + .globl __pci_config_write_16 | |
797 | +__pci_config_write_16: | |
798 | + lis r5, 0xfec0 | |
799 | + andi. r6, r3, 2 | |
800 | + stwbrx r3, r0, 5 | |
801 | + sync | |
802 | + oris r5, r6, 0xfee0 | |
803 | + sthbrx r4, r0, r5 | |
804 | + sync | |
805 | + blr | |
806 | + .globl __pci_config_write_8 | |
807 | +__pci_config_write_8: | |
808 | + lis r5, 0xfec0 | |
809 | + andi. r6, r3, 3 | |
810 | + stwbrx r3, r0, r5 | |
811 | + sync | |
812 | + oris r5, r6, 0xfee0 | |
813 | + stb r4, 0(r5) | |
814 | + sync | |
815 | + blr | |
816 | + .globl in_8 | |
817 | +in_8: | |
818 | + oris r3, r3, 0xfe00 | |
819 | + lbz r3,0(r3) | |
820 | + blr | |
821 | + .globl in_16 | |
822 | +in_16: | |
823 | + oris r3, r3, 0xfe00 | |
824 | + lhbrx r3, 0, r3 | |
825 | + blr | |
826 | + .globl in_16_ne | |
827 | +in_16_ne: | |
828 | + oris r3, r3, 0xfe00 | |
829 | + lhzx r3, 0, r3 | |
830 | + blr | |
831 | + .globl in_32 | |
832 | +in_32: | |
833 | + oris r3, r3, 0xfe00 | |
834 | + lwbrx r3, 0, r3 | |
835 | + blr | |
836 | + .globl out_8 | |
837 | +out_8: | |
838 | + oris r3, r3, 0xfe00 | |
839 | + stb r4, 0(r3) | |
840 | + eieio | |
841 | + blr | |
842 | + .globl out_16 | |
843 | +out_16: | |
844 | + oris r3, r3, 0xfe00 | |
845 | + sthbrx r4, 0, r3 | |
846 | + eieio | |
847 | + blr | |
848 | + .globl out_16_ne | |
849 | +out_16_ne: | |
850 | + oris r3, r3, 0xfe00 | |
851 | + sth r4, 0(r3) | |
852 | + eieio | |
853 | + blr | |
854 | + .globl out_32 | |
855 | +out_32: | |
856 | + oris r3, r3, 0xfe00 | |
857 | + stwbrx r4, 0, r3 | |
858 | + eieio | |
859 | + blr | |
860 | + .globl read_8 | |
861 | +read_8: | |
862 | + lbz r3,0(r3) | |
863 | + blr | |
864 | + .globl read_16 | |
865 | +read_16: | |
866 | + lhbrx r3, 0, r3 | |
867 | + blr | |
868 | + .globl read_32 | |
869 | +read_32: | |
870 | + lwbrx r3, 0, r3 | |
871 | + blr | |
872 | + .globl read_32_ne | |
873 | +read_32_ne: | |
874 | + lwz r3, 0(r3) | |
875 | + blr | |
876 | + .globl write_8 | |
877 | +write_8: | |
878 | + stb r4, 0(r3) | |
879 | + eieio | |
880 | + blr | |
881 | + .globl write_16 | |
882 | +write_16: | |
883 | + sthbrx r4, 0, r3 | |
884 | + eieio | |
885 | + blr | |
886 | + .globl write_32 | |
887 | +write_32: | |
888 | + stwbrx r4, 0, r3 | |
889 | + eieio | |
890 | + blr | |
891 | + .globl write_32_ne | |
892 | +write_32_ne: | |
893 | + stw r4, 0(r3) | |
894 | + eieio | |
895 | + blr | |
896 | + | |
897 | + | |
898 | +.globl early_init_f | |
899 | + | |
900 | +early_init_f: | |
901 | + mflr r11 | |
902 | + lis r10, 0x8000 | |
903 | + | |
904 | + /* PCI Latency Timer */ | |
905 | + li r4, 0x0d | |
906 | + ori r3, r10, PLTR@l | |
907 | + bl __pci_config_write_8 | |
908 | + | |
909 | + /* Cache Line Size */ | |
910 | + li r4, 0x08 | |
911 | + ori r3, r10, PCLSR@l | |
912 | + bl __pci_config_write_8 | |
913 | + | |
914 | + /* PCI Cmd */ | |
915 | + li r4, 6 | |
916 | + ori r3, r10, PCICR@l | |
917 | + bl __pci_config_write_16 | |
918 | + | |
919 | +#if 1 | |
920 | + /* PCI Stat */ | |
921 | + ori r3, r10, PCISR@l | |
922 | + bl __pci_config_read_16 | |
923 | + ori r4, r4, 0xffff | |
924 | + ori r3, r10, PCISR@l | |
925 | + bl __pci_config_write_16 | |
926 | +#endif | |
927 | + | |
928 | + /* PICR1 */ | |
929 | + lis r4, 0xff14 | |
930 | + ori r4, r4, 0x1b98 | |
931 | + ori r3, r10, PICR1@l | |
932 | + bl __pci_config_write_32 | |
933 | + | |
934 | + | |
935 | + /* PICR2 */ | |
936 | + lis r4, 0x0404 | |
937 | + ori r4, r4, 0x0004 | |
938 | + ori r3, r10, PICR2@l | |
939 | + bl __pci_config_write_32 | |
940 | + | |
941 | + /* MIOCR1 */ | |
942 | + li r4, 0x04 | |
943 | + ori r3, r10, MIOCR1@l | |
944 | + bl __pci_config_write_8 | |
945 | + | |
946 | + /* For the MPC8245, set register 77 to %00100000 (see Errata #15) */ | |
947 | + /* SDRAM_CLK_DEL (0x77)*/ | |
948 | + li r4, 0x10 | |
949 | + ori r3, r10, MIOCR2@l | |
950 | + bl __pci_config_write_8 | |
951 | + | |
952 | + /* EUMBBAR */ | |
953 | + lis r4, 0xfc00 | |
954 | + ori r3, r10, EUMBBAR@l | |
955 | + bl __pci_config_write_32 | |
956 | + | |
957 | + /* AMBOR */ | |
958 | + | |
959 | + /* Even if Address Map B is not being used (though it should), | |
960 | + * the memory DLL needs to be cleared/set/cleared before using memory. | |
961 | + */ | |
962 | + | |
963 | + ori r3, r10, AMBOR@l | |
964 | + bl __pci_config_read_8 /* get Current bits */ | |
965 | + | |
966 | + andi. r4, r4, 0xffdf | |
967 | + ori r3, r10, AMBOR@l | |
968 | + bl __pci_config_write_16 /* Clear DLL_RESET */ | |
969 | + | |
970 | + ori r4, r4, 0x0020 | |
971 | + ori r3, r10, AMBOR@l | |
972 | + bl __pci_config_write_16 /* Set DLL_RESET */ | |
973 | + | |
974 | + andi. r4, r4, 0xffdf | |
975 | + ori r3, r10, AMBOR@l | |
976 | + bl __pci_config_write_16 /* Clear DLL_RESET */ | |
977 | + | |
978 | + /* ERCR1 */ | |
979 | + lis r4, 0x8040 /* Enable RCS2, use supplied timings */ | |
980 | + ori r4, r4, 0x8000 | |
981 | + ori r3, r10, ERCR1@l | |
982 | + bl __pci_config_write_32 | |
983 | + | |
984 | + /* ERCR2 */ | |
985 | + lis r4, 0x0000 /* Disable RCS3 parms */ | |
986 | + ori r4, r4, 0x0000 | |
987 | + ori r3, r10, ERCR2@l | |
988 | + bl __pci_config_write_32 | |
989 | + | |
990 | + /* ERCR3 */ | |
991 | + lis r4, 0x0000 /* RCS3 at 0x70000000, 64K bytes */ | |
992 | + ori r4, r4, 0x0004 | |
993 | + ori r3, r10, ERCR2@l | |
994 | + bl __pci_config_write_32 | |
995 | + | |
996 | + /* Preserve memgo bit */ | |
997 | + /* MCCR1 */ | |
998 | + | |
999 | +/* lis r4, 0x75a8 / Safe Local ROM = 11+3 clocks */ | |
1000 | + lis r4, 0x75a0 /* Safe Local ROM = 11+3 clocks */ | |
1001 | +/* lis r4, 0x73a0 / Fast Local ROM = 7+3 clocks */ | |
1002 | +/* oris r4, r4, 0x0010 / Burst ROM/Flash enable */ | |
1003 | +/* oris r4, r4, 0x0004 / Self-refresh enable */ | |
1004 | + | |
1005 | +/* ori r4,r4,0xFFFF / 16Mbit 2bank SDRAM */ | |
1006 | +/* ori r4,r4,0xAAAA / 256Mbit 4bank SDRAM (8245 only) */ | |
1007 | +/* ori r4,r4,0x5555 / 64Mbit 2bank SDRAM */ | |
1008 | + ori r4,r4,0x0000 /* 64Mbit 4bank SDRAM */ | |
1009 | + | |
1010 | + ori r3, r10, MCCR1@l | |
1011 | + bl __pci_config_write_32 | |
1012 | + | |
1013 | + /* MCCR2 */ | |
1014 | + | |
1015 | + lis r4,0x0000 | |
1016 | +/* oris r4,r4,0x4000 / TS_WAIT_TIMER = 3 clocks */ | |
1017 | + oris r4,r4,0x1000 /* ASRISE = 8 clocks */ | |
1018 | + oris r4,r4,0x0080 /* ASFALL = 8 clocks */ | |
1019 | +/* oris r4,r4,0x0010 / SDRAM Parity (else ECC) */ | |
1020 | +/* oris r4,r4,0x0008 / Write parity check */ | |
1021 | +/* oris r4,r4,0x0004 / SDRAM inline reads */ | |
1022 | + | |
1023 | + | |
1024 | +/* Select a refresh rate; it needs to match the bus speed; if too */ | |
1025 | +/* slow, data may be lost; if too fast, performance is lost. We */ | |
1026 | +/* use the fastest value so we run at all speeds. */ | |
1027 | +/* Refresh = (15600ns/busclk) - (213 (see UM)). */ | |
1028 | + | |
1029 | +/* ori r4,r4,0x1d2c / 133 MHz mem bus = 1867 */ | |
1030 | +/* ori r4,r4,0x150c / 100 MHz mem bus = 1347 */ | |
1031 | +/* ori r4,r4,0x10fc / 83 MHz mem bus = 1087 */ | |
1032 | +/* ori r4,r4,0x0cc4 / 66 MHz mem bus = 817 */ | |
1033 | + ori r4,r4,0x04cc /* 33 MHz mem bus (SAFE) = 307 */ | |
1034 | +/* ori r4,r4,0x0002 / Reserve a page */ | |
1035 | +/* ori r4,r4,0x0001 / RWM parity */ | |
1036 | + | |
1037 | + ori r3, r10, MCCR2@l | |
1038 | + bl __pci_config_write_32 | |
1039 | + | |
1040 | + | |
1041 | + /* MCCR3 */ | |
1042 | + lis r4,0x0000 /* BSTOPRE_M = 7 (see A/N) */ | |
1043 | + oris r4,r4,0x0500 /* REFREC = 8 clocks */ | |
1044 | + ori r3, r10, MCCR3@l | |
1045 | + bl __pci_config_write_32 | |
1046 | + | |
1047 | + /* MCCR4 */ /* Turn on registered buffer mode */ | |
1048 | + lis r4, 0x2000 /* PRETOACT = 3 clocks */ | |
1049 | + oris r4,r4,0x0400 /* ACTOPRE = 5 clocks */ | |
1050 | +/* oris r4,r4,0x0080 / Enable 8-beat burst (32-bit bus) */ | |
1051 | +/* oris r4,r4,0x0040 / Enable Inline ECC/Parity */ | |
1052 | + oris r4,r4,0x0020 /* EXTROM enabled */ | |
1053 | + oris r4,r4,0x0010 /* Registered buffers */ | |
1054 | +/* oris r4,r4,0x0000 / BSTOPRE_U = 0 (see A/N) */ | |
1055 | + oris r4,r4,0x0002 /* DBUS_SIZ[2] (8 bit on RCS1) */ | |
1056 | + | |
1057 | +/* ori r4,r4,0x8000 / Registered DIMMs */ | |
1058 | + ori r4,r4,0x2000 /*CAS Latency (CL=3) (see RDLAT) */ | |
1059 | +/* ori r4,r4,0x2000 / CAS Latency (CL=2) (see RDLAT) */ | |
1060 | +/* ori r4,r4,0x0300 / Sequential wrap/8-beat burst */ | |
1061 | + ori r4,r4,0x0200 /* Sequential wrap/4-beat burst */ | |
1062 | + ori r4,r4,0x0030 /* ACTORW = 3 clocks */ | |
1063 | + ori r4,r4,0x0009 /* BSTOPRE_L = 9 (see A/N) */ | |
1064 | + | |
1065 | + ori r3, r10, MCCR4@l | |
1066 | + bl __pci_config_write_32 | |
1067 | + | |
1068 | + /* MSAR1 */ | |
1069 | + lis r4, 0xc0804000@h | |
1070 | + ori r4, r4, 0xc0804000@l | |
1071 | + ori r3, r10, MSAR1@l | |
1072 | + bl __pci_config_write_32 | |
1073 | + | |
1074 | + /* MSAR2 */ | |
1075 | + lis r4, 0xc0804000@h | |
1076 | + ori r4, r4, 0xc0804000@l | |
1077 | + ori r3, r10, MSAR2@l | |
1078 | + bl __pci_config_write_32 | |
1079 | + | |
1080 | + /* MESAR1 */ | |
1081 | + lis r4, 0x00000000@h | |
1082 | + ori r4, r4, 0x00000000@l | |
1083 | + ori r3, r10, EMSAR1@l | |
1084 | + bl __pci_config_write_32 | |
1085 | + | |
1086 | + /* MESAR2 */ | |
1087 | + lis r4, 0x01010101@h | |
1088 | + ori r4, r4, 0x01010101@l | |
1089 | + ori r3, r10, EMSAR2@l | |
1090 | + bl __pci_config_write_32 | |
1091 | + | |
1092 | + /* MEAR1 */ | |
1093 | + lis r4, 0xffbf7f3f@h | |
1094 | + ori r4, r4, 0xffbf7f3f@l | |
1095 | + ori r3, r10, MEAR1@l | |
1096 | + bl __pci_config_write_32 | |
1097 | + | |
1098 | + /* MEAR2 */ | |
1099 | + lis r4, 0xffbf7f3f@h | |
1100 | + ori r4, r4, 0xffbf7f3f@l | |
1101 | + ori r3, r10, MEAR2@l | |
1102 | + bl __pci_config_write_32 | |
1103 | + | |
1104 | + /* MEEAR1 */ | |
1105 | + lis r4, 0x00000000@h | |
1106 | + ori r4, r4, 0x00000000@l | |
1107 | + ori r3, r10, EMEAR1@l | |
1108 | + bl __pci_config_write_32 | |
1109 | + | |
1110 | + /* MEEAR2 */ | |
1111 | + lis r4, 0x01010101@h | |
1112 | + ori r4, r4, 0x01010101@l | |
1113 | + ori r3, r10, EMEAR2@l | |
1114 | + bl __pci_config_write_32 | |
1115 | + | |
1116 | + /* ODCR */ | |
1117 | + li r4, 0x7f | |
1118 | + ori r3, r10, ODCR@l | |
1119 | + bl __pci_config_write_8 | |
1120 | + | |
1121 | + /* MBER */ | |
1122 | + li r4, 0x01 | |
1123 | + ori r3, r10, MBER@l | |
1124 | + bl __pci_config_write_8 | |
1125 | + | |
1126 | + /* Page CTR aka PGMAX */ | |
1127 | + li r4, 0x32 | |
1128 | + ori r3, r10, 0x70 | |
1129 | + bl __pci_config_write_8 | |
1130 | + | |
1131 | +#if 0 | |
1132 | + /* CLK Drive */ | |
1133 | + ori r4, r10, 0xfc01 /* Top bit will be ignored */ | |
1134 | + ori r3, r10, 0x74 | |
1135 | + bl __pci_config_write_16 | |
1136 | +#endif | |
1137 | + | |
1138 | + /* delay */ | |
1139 | + lis r7, 1 | |
1140 | + mtctr r7 | |
1141 | +label1: bdnz label1 | |
1142 | + | |
1143 | + /* Set memgo bit */ | |
1144 | + /* MCCR1 */ | |
1145 | + ori r3, r10, MCCR1@l | |
1146 | + bl __pci_config_read_32 | |
1147 | + lis r7, 0x0008 | |
1148 | + or r4, r3, r7 | |
1149 | + ori r3, r10, MCCR1@l | |
1150 | + bl __pci_config_write_32 | |
1151 | + | |
1152 | + /* delay again */ | |
1153 | + lis r7, 1 | |
1154 | + mtctr r7 | |
1155 | +label2: bdnz label2 | |
1156 | +#if 0 | |
1157 | +/* DEBUG: Infinite loop, write then read */ | |
1158 | +loop: | |
1159 | + lis r7, 0xffff | |
1160 | + mtctr r7 | |
1161 | + li r3, 0x5004 | |
1162 | + lis r4, 0xa0a0 | |
1163 | + ori r4, r4, 0x5050 | |
1164 | + bl write_32_ne | |
1165 | + li r3, 0x5004 | |
1166 | + bl read_32_ne | |
1167 | + bdnz loop | |
1168 | +#endif | |
1169 | + mtlr r11 | |
1170 | + blr | |
1171 | +#endif |
board/gw8260/flash.c
1 | +/* | |
2 | + * (C) Copyright 2000 | |
3 | + * Marius Groeger <mgroeger@sysgo.de> | |
4 | + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
5 | + * | |
6 | + * (C) Copyright 2000, 2001 | |
7 | + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
8 | + * | |
9 | + * (C) Copyright 2001 | |
10 | + * Advent Networks, Inc. <http://www.adventnetworks.com> | |
11 | + * Oliver Brown <oliverb@alumni.utexas.net> | |
12 | + * | |
13 | + *-------------------------------------------------------------------- | |
14 | + * See file CREDITS for list of people who contributed to this | |
15 | + * project. | |
16 | + * | |
17 | + * This program is free software; you can redistribute it and/or | |
18 | + * modify it under the terms of the GNU General Public License as | |
19 | + * published by the Free Software Foundation; either version 2 of | |
20 | + * the License, or (at your option) any later version. | |
21 | + * | |
22 | + * This program is distributed in the hope that it will be useful, | |
23 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | + * GNU General Public License for more details. | |
26 | + * | |
27 | + * You should have received a copy of the GNU General Public License | |
28 | + * along with this program; if not, write to the Free Software | |
29 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
30 | + * MA 02111-1307 USA | |
31 | + */ | |
32 | + | |
33 | +/*********************************************************************/ | |
34 | +/* DESCRIPTION: | |
35 | + * This file contains the flash routines for the GW8260 board. | |
36 | + * | |
37 | + * | |
38 | + * | |
39 | + * MODULE DEPENDENCY: | |
40 | + * None | |
41 | + * | |
42 | + * | |
43 | + * RESTRICTIONS/LIMITATIONS: | |
44 | + * | |
45 | + * Only supports the following flash devices: | |
46 | + * AMD 29F080B | |
47 | + * AMD 29F016D | |
48 | + * | |
49 | + * Copyright (c) 2001, Advent Networks, Inc. | |
50 | + * | |
51 | + */ | |
52 | +/*********************************************************************/ | |
53 | + | |
54 | +#include <common.h> | |
55 | +#include <mpc8260.h> | |
56 | + | |
57 | +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; | |
58 | + | |
59 | +static ulong flash_get_size (vu_long *addr, flash_info_t *info); | |
60 | +static int write_word (flash_info_t *info, ulong dest, ulong data); | |
61 | + | |
62 | +/*********************************************************************/ | |
63 | +/* functions */ | |
64 | +/*********************************************************************/ | |
65 | + | |
66 | +/*********************************************************************/ | |
67 | +/* NAME: flash_init() - initializes flash banks */ | |
68 | +/* */ | |
69 | +/* DESCRIPTION: */ | |
70 | +/* This function initializes the flash bank(s). */ | |
71 | +/* */ | |
72 | +/* RETURNS: */ | |
73 | +/* The size in bytes of the flash */ | |
74 | +/* */ | |
75 | +/* RESTRICTIONS/LIMITATIONS: */ | |
76 | +/* */ | |
77 | +/* */ | |
78 | +/*********************************************************************/ | |
79 | +unsigned long flash_init (void) | |
80 | +{ | |
81 | + unsigned long size; | |
82 | + int i; | |
83 | + | |
84 | + /* Init: no FLASHes known */ | |
85 | + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { | |
86 | + flash_info[i].flash_id = FLASH_UNKNOWN; | |
87 | + } | |
88 | + | |
89 | + /* for now, only support the 4 MB Flash SIMM */ | |
90 | + size = flash_get_size((vu_long *)CFG_FLASH0_BASE, &flash_info[0]); | |
91 | + | |
92 | + /* | |
93 | + * protect monitor and environment sectors | |
94 | + */ | |
95 | + | |
96 | +#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE | |
97 | + flash_protect(FLAG_PROTECT_SET, | |
98 | + CFG_MONITOR_BASE, | |
99 | + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, | |
100 | + &flash_info[0]); | |
101 | +#endif | |
102 | + | |
103 | +#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR) | |
104 | +# ifndef CFG_ENV_SIZE | |
105 | +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE | |
106 | +# endif | |
107 | + flash_protect(FLAG_PROTECT_SET, | |
108 | + CFG_ENV_ADDR, | |
109 | + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, | |
110 | + &flash_info[0]); | |
111 | +#endif | |
112 | + | |
113 | + return (CFG_FLASH0_SIZE * 1024 * 1024); /*size*/ | |
114 | +} | |
115 | + | |
116 | +/*********************************************************************/ | |
117 | +/* NAME: flash_print_info() - prints flash imformation */ | |
118 | +/* */ | |
119 | +/* DESCRIPTION: */ | |
120 | +/* This function prints the flash information. */ | |
121 | +/* */ | |
122 | +/* INPUTS: */ | |
123 | +/* flash_info_t *info - flash information structure */ | |
124 | +/* */ | |
125 | +/* OUTPUTS: */ | |
126 | +/* Displays flash information to console */ | |
127 | +/* */ | |
128 | +/* RETURNS: */ | |
129 | +/* None */ | |
130 | +/* */ | |
131 | +/* RESTRICTIONS/LIMITATIONS: */ | |
132 | +/* */ | |
133 | +/* */ | |
134 | +/*********************************************************************/ | |
135 | +void flash_print_info (flash_info_t *info) | |
136 | +{ | |
137 | + int i; | |
138 | + | |
139 | + if (info->flash_id == FLASH_UNKNOWN) { | |
140 | + printf ("missing or unknown FLASH type\n"); | |
141 | + return; | |
142 | + } | |
143 | + | |
144 | + switch ((info->flash_id >> 16) & 0xff) { | |
145 | + case 0x1: | |
146 | + printf ("AMD "); | |
147 | + break; | |
148 | + default: | |
149 | + printf ("Unknown Vendor "); | |
150 | + break; | |
151 | + } | |
152 | + | |
153 | + switch (info->flash_id & FLASH_TYPEMASK) { | |
154 | + case AMD_ID_F040B: | |
155 | + printf ("AM29F040B (4 Mbit)\n"); | |
156 | + break; | |
157 | + case AMD_ID_F080B: | |
158 | + printf ("AM29F080B (8 Mbit)\n"); | |
159 | + break; | |
160 | + case AMD_ID_F016D: | |
161 | + printf ("AM29F016D (16 Mbit)\n"); | |
162 | + break; | |
163 | + default: | |
164 | + printf ("Unknown Chip Type\n"); | |
165 | + break; | |
166 | + } | |
167 | + | |
168 | + printf (" Size: %ld MB in %d Sectors\n", | |
169 | + info->size >> 20, info->sector_count); | |
170 | + | |
171 | + printf (" Sector Start Addresses:"); | |
172 | + for (i=0; i<info->sector_count; ++i) { | |
173 | + if ((i % 5) == 0) | |
174 | + printf ("\n "); | |
175 | + printf (" %08lX%s", | |
176 | + info->start[i], | |
177 | + info->protect[i] ? " (RO)" : " " | |
178 | + ); | |
179 | + } | |
180 | + printf ("\n"); | |
181 | + return; | |
182 | +} | |
183 | + | |
184 | +/*********************************************************************/ | |
185 | +/* The following code cannot be run from FLASH! */ | |
186 | +/*********************************************************************/ | |
187 | + | |
188 | +/*********************************************************************/ | |
189 | +/* NAME: flash_get_size() - detects the flash size */ | |
190 | +/* */ | |
191 | +/* DESCRIPTION: */ | |
192 | +/* 1) Reads vendor ID and devices ID from the flash devices. */ | |
193 | +/* 2) Initializes flash info struct. */ | |
194 | +/* 3) Return the flash size */ | |
195 | +/* */ | |
196 | +/* INPUTS: */ | |
197 | +/* vu_long *addr - pointer to start of flash */ | |
198 | +/* flash_info_t *info - flash information structure */ | |
199 | +/* */ | |
200 | +/* OUTPUTS: */ | |
201 | +/* None */ | |
202 | +/* */ | |
203 | +/* RETURNS: */ | |
204 | +/* Size of the flash in bytes, or 0 if device id is unknown. */ | |
205 | +/* */ | |
206 | +/* RESTRICTIONS/LIMITATIONS: */ | |
207 | +/* Only supports the following devices: */ | |
208 | +/* AM29F080D */ | |
209 | +/* AM29F016D */ | |
210 | +/* */ | |
211 | +/*********************************************************************/ | |
212 | +static ulong flash_get_size (vu_long *addr, flash_info_t *info) | |
213 | +{ | |
214 | + short i; | |
215 | + vu_long vendor, devid; | |
216 | + ulong base = (ulong)addr; | |
217 | + | |
218 | + /*printf("addr = %08lx\n", (unsigned long)addr); */ | |
219 | + | |
220 | + /* Reset and Write auto select command: read Manufacturer ID */ | |
221 | + addr[0x0000] = 0xf0f0f0f0; | |
222 | + addr[0x0555] = 0xAAAAAAAA; | |
223 | + addr[0x02AA] = 0x55555555; | |
224 | + addr[0x0555] = 0x90909090; | |
225 | + udelay (1000); | |
226 | + | |
227 | + vendor = addr[0]; | |
228 | + /*printf("vendor = %08lx\n", vendor); */ | |
229 | + if (vendor != 0x01010101) { | |
230 | + info->size = 0; | |
231 | + goto out; | |
232 | + } | |
233 | + | |
234 | + devid = addr[1]; | |
235 | + /*printf("devid = %08lx\n", devid); */ | |
236 | + | |
237 | + if ((devid & 0xff) == AMD_ID_F080B) { | |
238 | + info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F080B; | |
239 | + /* we have 16 sectors with 64KB each x 4 */ | |
240 | + info->sector_count = 16; | |
241 | + info->size = 4 * info->sector_count * 64*1024; | |
242 | + } else if ((devid & 0xff) == AMD_ID_F016D){ | |
243 | + info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F016D; | |
244 | + /* we have 32 sectors with 64KB each x 4 */ | |
245 | + info->sector_count = 32; | |
246 | + info->size = 4 * info->sector_count * 64*1024; | |
247 | + } else { | |
248 | + info->size = 0; | |
249 | + goto out; | |
250 | + } | |
251 | + /*printf("sector count = %08x\n", info->sector_count); */ | |
252 | + /* check for protected sectors */ | |
253 | + for (i = 0; i < info->sector_count; i++) { | |
254 | + /* sector base address */ | |
255 | + info->start[i] = base + i * (info->size / info->sector_count); | |
256 | + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ | |
257 | + /* D0 = 1 if protected */ | |
258 | + addr = (volatile unsigned long *)(info->start[i]); | |
259 | + info->protect[i] = addr[2] & 1; | |
260 | + } | |
261 | + | |
262 | + /* reset command */ | |
263 | + addr = (vu_long *)info->start[0]; | |
264 | + | |
265 | + out: | |
266 | + addr[0] = 0xf0f0f0f0; | |
267 | + | |
268 | + /*printf("size = %08x\n", info->size); */ | |
269 | + return info->size; | |
270 | +} | |
271 | + | |
272 | +/*********************************************************************/ | |
273 | +/* NAME: flash_erase() - erases flash by sector */ | |
274 | +/* */ | |
275 | +/* DESCRIPTION: */ | |
276 | +/* This function erases flash sectors starting for s_first to */ | |
277 | +/* s_last. */ | |
278 | +/* */ | |
279 | +/* INPUTS: */ | |
280 | +/* flash_info_t *info - flash information structure */ | |
281 | +/* int s_first - first sector to erase */ | |
282 | +/* int s_last - last sector to erase */ | |
283 | +/* */ | |
284 | +/* OUTPUTS: */ | |
285 | +/* None */ | |
286 | +/* */ | |
287 | +/* RETURNS: */ | |
288 | +/* Returns 0 for success, 1 for failure. */ | |
289 | +/* */ | |
290 | +/* RESTRICTIONS/LIMITATIONS: */ | |
291 | +/* */ | |
292 | +/*********************************************************************/ | |
293 | +int flash_erase (flash_info_t *info, int s_first, int s_last) | |
294 | +{ | |
295 | + vu_long *addr = (vu_long*)(info->start[0]); | |
296 | + int flag, prot, sect, l_sect; | |
297 | + ulong start, now, last; | |
298 | + | |
299 | + if ((s_first < 0) || (s_first > s_last)) { | |
300 | + if (info->flash_id == FLASH_UNKNOWN) { | |
301 | + printf ("- missing\n"); | |
302 | + } else { | |
303 | + printf ("- no sectors to erase\n"); | |
304 | + } | |
305 | + return 1; | |
306 | + } | |
307 | + | |
308 | + prot = 0; | |
309 | + for (sect = s_first; sect <= s_last; sect++) { | |
310 | + if (info->protect[sect]) { | |
311 | + prot++; | |
312 | + } | |
313 | + } | |
314 | + | |
315 | + if (prot) { | |
316 | + printf ("- Warning: %d protected sectors will not be erased!\n", | |
317 | + prot); | |
318 | + } else { | |
319 | + printf ("\n"); | |
320 | + } | |
321 | + | |
322 | + l_sect = -1; | |
323 | + | |
324 | + /* Disable interrupts which might cause a timeout here */ | |
325 | + flag = disable_interrupts(); | |
326 | + | |
327 | + addr[0x0555] = 0xAAAAAAAA; | |
328 | + addr[0x02AA] = 0x55555555; | |
329 | + addr[0x0555] = 0x80808080; | |
330 | + addr[0x0555] = 0xAAAAAAAA; | |
331 | + addr[0x02AA] = 0x55555555; | |
332 | + udelay (100); | |
333 | + | |
334 | + /* Start erase on unprotected sectors */ | |
335 | + for (sect = s_first; sect <= s_last; sect++) { | |
336 | + if (info->protect[sect] == 0) { /* not protected */ | |
337 | + addr = (vu_long*)(info->start[sect]); | |
338 | + addr[0] = 0x30303030; | |
339 | + l_sect = sect; | |
340 | + } | |
341 | + } | |
342 | + | |
343 | + /* re-enable interrupts if necessary */ | |
344 | + if (flag) | |
345 | + enable_interrupts(); | |
346 | + | |
347 | + /* wait at least 80us - let's wait 1 ms */ | |
348 | + udelay (1000); | |
349 | + | |
350 | + /* | |
351 | + * We wait for the last triggered sector | |
352 | + */ | |
353 | + if (l_sect < 0) | |
354 | + goto DONE; | |
355 | + | |
356 | + start = get_timer (0); | |
357 | + last = start; | |
358 | + addr = (vu_long*)(info->start[l_sect]); | |
359 | + while ((addr[0] & 0x80808080) != 0x80808080) { | |
360 | + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { | |
361 | + printf ("Timeout\n"); | |
362 | + return 1; | |
363 | + } | |
364 | + /* show that we're waiting */ | |
365 | + if ((now - last) > 1000) { /* every second */ | |
366 | + serial_putc ('.'); | |
367 | + last = now; | |
368 | + } | |
369 | + } | |
370 | + | |
371 | + DONE: | |
372 | + /* reset to read mode */ | |
373 | + addr = (volatile unsigned long *)info->start[0]; | |
374 | + addr[0] = 0xF0F0F0F0; /* reset bank */ | |
375 | + | |
376 | + printf (" done\n"); | |
377 | + return 0; | |
378 | +} | |
379 | + | |
380 | +/*********************************************************************/ | |
381 | +/* NAME: write_buff() - writes a buffer to flash */ | |
382 | +/* */ | |
383 | +/* DESCRIPTION: */ | |
384 | +/* This function copies a buffer, *src, to flash. */ | |
385 | +/* */ | |
386 | +/* INPUTS: */ | |
387 | +/* flash_info_t *info - flash information structure */ | |
388 | +/* uchar *src - pointer to buffer to write to flash */ | |
389 | +/* ulong addr - address to start write at */ | |
390 | +/* ulong cnt - number of bytes to write to flash */ | |
391 | +/* */ | |
392 | +/* OUTPUTS: */ | |
393 | +/* None */ | |
394 | +/* */ | |
395 | +/* RETURNS: */ | |
396 | +/* 0 - OK */ | |
397 | +/* 1 - write timeout */ | |
398 | +/* 2 - Flash not erased */ | |
399 | +/* */ | |
400 | +/* RESTRICTIONS/LIMITATIONS: */ | |
401 | +/* */ | |
402 | +/*********************************************************************/ | |
403 | +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) | |
404 | +{ | |
405 | + ulong cp, wp, data; | |
406 | + int i, l, rc; | |
407 | + | |
408 | + wp = (addr & ~3); /* get lower word aligned address */ | |
409 | + | |
410 | + /* | |
411 | + * handle unaligned start bytes | |
412 | + */ | |
413 | + if ((l = addr - wp) != 0) { | |
414 | + data = 0; | |
415 | + for (i = 0, cp = wp; i < l; ++i, ++cp) { | |
416 | + data = (data << 8) | (*(uchar *)cp); | |
417 | + } | |
418 | + for (; (i < 4) && (cnt > 0); ++i) { | |
419 | + data = (data << 8) | *src++; | |
420 | + --cnt; | |
421 | + ++cp; | |
422 | + } | |
423 | + for (; (cnt == 0) && (i < 4); ++i, ++cp) { | |
424 | + data = (data << 8) | (*(uchar *)cp); | |
425 | + } | |
426 | + | |
427 | + if ((rc = write_word(info, wp, data)) != 0) { | |
428 | + return (rc); | |
429 | + } | |
430 | + wp += 4; | |
431 | + } | |
432 | + | |
433 | + /* | |
434 | + * handle word aligned part | |
435 | + */ | |
436 | + while (cnt >= 4) { | |
437 | + data = 0; | |
438 | + for (i = 0; i < 4; ++i) { | |
439 | + data = (data << 8) | *src++; | |
440 | + } | |
441 | + if ((rc = write_word(info, wp, data)) != 0) { | |
442 | + return (rc); | |
443 | + } | |
444 | + wp += 4; | |
445 | + cnt -= 4; | |
446 | + } | |
447 | + | |
448 | + if (cnt == 0) { | |
449 | + return (0); | |
450 | + } | |
451 | + | |
452 | + /* | |
453 | + * handle unaligned tail bytes | |
454 | + */ | |
455 | + data = 0; | |
456 | + for (i = 0, cp = wp; (i < 4) && (cnt > 0); ++i, ++cp) { | |
457 | + data = (data << 8) | *src++; | |
458 | + --cnt; | |
459 | + } | |
460 | + for (; (i < 4); ++i, ++cp) { | |
461 | + data = (data << 8) | (*(uchar *)cp); | |
462 | + } | |
463 | + | |
464 | + return (write_word(info, wp, data)); | |
465 | +} | |
466 | + | |
467 | +/*********************************************************************/ | |
468 | +/* NAME: write_word() - writes a word to flash */ | |
469 | +/* */ | |
470 | +/* DESCRIPTION: */ | |
471 | +/* This writes a single word to flash. */ | |
472 | +/* */ | |
473 | +/* INPUTS: */ | |
474 | +/* flash_info_t *info - flash information structure */ | |
475 | +/* ulong dest - address to write */ | |
476 | +/* ulong data - data to write */ | |
477 | +/* */ | |
478 | +/* OUTPUTS: */ | |
479 | +/* None */ | |
480 | +/* */ | |
481 | +/* RETURNS: */ | |
482 | +/* 0 - OK */ | |
483 | +/* 1 - write timeout */ | |
484 | +/* 2 - Flash not erased */ | |
485 | +/* */ | |
486 | +/* RESTRICTIONS/LIMITATIONS: */ | |
487 | +/* */ | |
488 | +/*********************************************************************/ | |
489 | +static int write_word (flash_info_t *info, ulong dest, ulong data) | |
490 | +{ | |
491 | + vu_long *addr = (vu_long*)(info->start[0]); | |
492 | + ulong start; | |
493 | + int flag; | |
494 | + | |
495 | + /* Check if Flash is (sufficiently) erased */ | |
496 | + if ((*((vu_long *)dest) & data) != data) { | |
497 | + return (2); | |
498 | + } | |
499 | + /* Disable interrupts which might cause a timeout here */ | |
500 | + flag = disable_interrupts(); | |
501 | + | |
502 | + addr[0x0555] = 0xAAAAAAAA; | |
503 | + addr[0x02AA] = 0x55555555; | |
504 | + addr[0x0555] = 0xA0A0A0A0; | |
505 | + | |
506 | + *((vu_long *)dest) = data; | |
507 | + | |
508 | + /* re-enable interrupts if necessary */ | |
509 | + if (flag) | |
510 | + enable_interrupts(); | |
511 | + | |
512 | + /* data polling for D7 */ | |
513 | + start = get_timer (0); | |
514 | + while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) { | |
515 | + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { | |
516 | + return (1); | |
517 | + } | |
518 | + } | |
519 | + return (0); | |
520 | +} | |
521 | +/*********************************************************************/ | |
522 | +/* End of flash.c */ | |
523 | +/*********************************************************************/ |
board/gw8260/gw8260.c
1 | +/* | |
2 | + * (C) Copyright 2000 | |
3 | + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
4 | + * Marius Groeger <mgroeger@sysgo.de> | |
5 | + * | |
6 | + * (C) Copyright 2001 | |
7 | + * Advent Networks, Inc. <http://www.adventnetworks.com> | |
8 | + * Jay Monkman <jtm@smoothsmoothie.com> | |
9 | + * | |
10 | + * (C) Copyright 2001 | |
11 | + * Advent Networks, Inc. <http://www.adventnetworks.com> | |
12 | + * Oliver Brown <oliverb@alumni.utexas.net> | |
13 | + * | |
14 | + * See file CREDITS for list of people who contributed to this | |
15 | + * project. | |
16 | + * | |
17 | + * This program is free software; you can redistribute it and/or | |
18 | + * modify it under the terms of the GNU General Public License as | |
19 | + * published by the Free Software Foundation; either version 2 of | |
20 | + * the License, or (at your option) any later version. | |
21 | + * | |
22 | + * This program is distributed in the hope that it will be useful, | |
23 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | + * GNU General Public License for more details. | |
26 | + * | |
27 | + * You should have received a copy of the GNU General Public License | |
28 | + * along with this program; if not, write to the Free Software | |
29 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
30 | + * MA 02111-1307 USA | |
31 | + */ | |
32 | + | |
33 | +/*********************************************************************/ | |
34 | +/* DESCRIPTION: | |
35 | + * This file contains the board routines for the GW8260 board. | |
36 | + * | |
37 | + * MODULE DEPENDENCY: | |
38 | + * None | |
39 | + * | |
40 | + * RESTRICTIONS/LIMITATIONS: | |
41 | + * None | |
42 | + * | |
43 | + * Copyright (c) 2001, Advent Networks, Inc. | |
44 | + */ | |
45 | +/*********************************************************************/ | |
46 | + | |
47 | +#include <common.h> | |
48 | +#include <ioports.h> | |
49 | +#include <mpc8260.h> | |
50 | + | |
51 | +/* | |
52 | + * I/O Port configuration table | |
53 | + * | |
54 | + */ | |
55 | +const iop_conf_t iop_conf_tab[4][32] = { | |
56 | + | |
57 | + /* Port A configuration */ | |
58 | + { /* conf ppar psor pdir podr pdat */ | |
59 | + /* PA31 */ { 1, 0, 0, 1, 0, 0 }, /* TP14 */ | |
60 | + /* PA30 */ { 1, 1, 1, 1, 0, 0 }, /* US_RTS */ | |
61 | + /* PA29 */ { 1, 0, 0, 1, 0, 1 }, /* LSSI_DATA */ | |
62 | + /* PA28 */ { 1, 0, 0, 1, 0, 1 }, /* LSSI_CLK */ | |
63 | + /* PA27 */ { 1, 0, 0, 1, 0, 0 }, /* TP12 */ | |
64 | + /* PA26 */ { 1, 0, 0, 0, 0, 0 }, /* IO_STATUS */ | |
65 | + /* PA25 */ { 1, 0, 0, 0, 0, 0 }, /* IO_CLOCK */ | |
66 | + /* PA24 */ { 1, 0, 0, 0, 0, 0 }, /* IO_CONFIG */ | |
67 | + /* PA23 */ { 1, 0, 0, 0, 0, 0 }, /* IO_DONE */ | |
68 | + /* PA22 */ { 1, 0, 0, 0, 0, 0 }, /* IO_DATA */ | |
69 | + /* PA21 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD3 */ | |
70 | + /* PA20 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD2 */ | |
71 | + /* PA19 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD1 */ | |
72 | + /* PA18 */ { 1, 1, 0, 1, 0, 0 }, /* US_TXD0 */ | |
73 | + /* PA17 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD0 */ | |
74 | + /* PA16 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD1 */ | |
75 | + /* PA15 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD2 */ | |
76 | + /* PA14 */ { 1, 1, 0, 0, 0, 0 }, /* DS_RXD3 */ | |
77 | + /* PA13 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE7 */ | |
78 | + /* PA12 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE6 */ | |
79 | + /* PA11 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE5 */ | |
80 | + /* PA10 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE4 */ | |
81 | + /* PA9 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE3 */ | |
82 | + /* PA8 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE2 */ | |
83 | + /* PA7 */ { 1, 0, 0, 0, 0, 0 }, /* LSSI_IN */ | |
84 | + /* PA6 */ { 1, 0, 0, 1, 0, 0 }, /* SPARE0 */ | |
85 | + /* PA5 */ { 1, 0, 0, 1, 0, 0 }, /* DEMOD_RESET_ */ | |
86 | + /* PA4 */ { 1, 0, 0, 1, 0, 0 }, /* MOD_RESET_ */ | |
87 | + /* PA3 */ { 1, 0, 0, 1, 0, 0 }, /* IO_RESET */ | |
88 | + /* PA2 */ { 1, 0, 0, 1, 0, 0 }, /* TX_ENABLE */ | |
89 | + /* PA1 */ { 1, 0, 0, 0, 0, 0 }, /* RX_LOCK */ | |
90 | + /* PA0 */ { 1, 0, 0, 1, 0, 1 } /* MPC_RESET_ */ | |
91 | + }, | |
92 | + | |
93 | + /* Port B configuration */ | |
94 | + { /* conf ppar psor pdir podr pdat */ | |
95 | + /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TX_ER */ | |
96 | + /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RX_DV */ | |
97 | + /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FETH0_TX_EN */ | |
98 | + /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RX_ER */ | |
99 | + /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_COL */ | |
100 | + /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_CRS */ | |
101 | + /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD3 */ | |
102 | + /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD2 */ | |
103 | + /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD1 */ | |
104 | + /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FETH0_TXD0 */ | |
105 | + /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD0 */ | |
106 | + /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD1 */ | |
107 | + /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD2 */ | |
108 | + /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RXD3 */ | |
109 | + /* PB17 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RX_DV */ | |
110 | + /* PB16 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RX_ER */ | |
111 | + /* PB15 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TX_ER */ | |
112 | + /* PB14 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TX_EN */ | |
113 | + /* PB13 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_COL */ | |
114 | + /* PB12 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_CRS */ | |
115 | + /* PB11 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD3 */ | |
116 | + /* PB10 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD2 */ | |
117 | + /* PB9 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD1 */ | |
118 | + /* PB8 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RXD0 */ | |
119 | + /* PB7 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD0 */ | |
120 | + /* PB6 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD1 */ | |
121 | + /* PB5 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD2 */ | |
122 | + /* PB4 */ { 1, 1, 0, 1, 0, 0 }, /* FETH1_TXD3 */ | |
123 | + /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ | |
124 | + /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ | |
125 | + /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ | |
126 | + /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ | |
127 | + }, | |
128 | + | |
129 | + /* Port C */ | |
130 | + { /* conf ppar psor pdir podr pdat */ | |
131 | + /* PC31 */ { 1, 0, 0, 1, 0, 1 }, /* FAST_RESET_ */ | |
132 | + /* PC30 */ { 1, 0, 0, 1, 0, 1 }, /* FAST_PAUSE_ */ | |
133 | + /* PC29 */ { 1, 0, 0, 1, 0, 0 }, /* FAST_SLEW1 */ | |
134 | + /* PC28 */ { 1, 0, 0, 1, 0, 0 }, /* FAST_SLEW0 */ | |
135 | + /* PC27 */ { 1, 0, 0, 1, 0, 0 }, /* TP13 */ | |
136 | + /* PC26 */ { 1, 0, 0, 0, 0, 0 }, /* RXDECDFLG */ | |
137 | + /* PC25 */ { 1, 0, 0, 0, 0, 0 }, /* RXACQFAIL */ | |
138 | + /* PC24 */ { 1, 0, 0, 0, 0, 0 }, /* RXACQFLG */ | |
139 | + /* PC23 */ { 1, 0, 0, 1, 0, 0 }, /* WD_TCL */ | |
140 | + /* PC22 */ { 1, 0, 0, 1, 0, 0 }, /* WD_EN */ | |
141 | + /* PC21 */ { 1, 0, 0, 1, 0, 0 }, /* US_TXCLK */ | |
142 | + /* PC20 */ { 1, 0, 0, 0, 0, 0 }, /* DS_RXCLK */ | |
143 | + /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_RX_CLK */ | |
144 | + /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FETH0_TX_CLK */ | |
145 | + /* PC17 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_RX_CLK */ | |
146 | + /* PC16 */ { 1, 1, 0, 0, 0, 0 }, /* FETH1_TX_CLK */ | |
147 | + /* PC15 */ { 1, 0, 0, 1, 0, 0 }, /* TX_SHUTDOWN_ */ | |
148 | + /* PC14 */ { 1, 0, 0, 0, 0, 0 }, /* RS_232_DTR_ */ | |
149 | + /* PC13 */ { 1, 0, 0, 0, 0, 0 }, /* TXERR */ | |
150 | + /* PC12 */ { 1, 0, 0, 1, 0, 1 }, /* FETH1_MDDIS */ | |
151 | + /* PC11 */ { 1, 0, 0, 1, 0, 1 }, /* FETH0_MDDIS */ | |
152 | + /* PC10 */ { 1, 0, 0, 1, 0, 0 }, /* MDC */ | |
153 | + /* PC9 */ { 1, 0, 0, 1, 1, 1 }, /* MDIO */ | |
154 | + /* PC8 */ { 1, 0, 0, 1, 1, 1 }, /* SER_NUM */ | |
155 | + /* PC7 */ { 1, 1, 0, 0, 0, 0 }, /* US_CTS */ | |
156 | + /* PC6 */ { 1, 1, 0, 0, 0, 0 }, /* DS_CD_ */ | |
157 | + /* PC5 */ { 1, 0, 0, 1, 0, 0 }, /* FETH1_PWRDWN */ | |
158 | + /* PC4 */ { 1, 0, 0, 1, 0, 0 }, /* FETH0_PWRDWN */ | |
159 | + /* PC3 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED3 */ | |
160 | + /* PC2 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED2 */ | |
161 | + /* PC1 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED1 */ | |
162 | + /* PC0 */ { 1, 0, 0, 1, 0, 1 }, /* MPULED0 */ | |
163 | + }, | |
164 | + | |
165 | + /* Port D */ | |
166 | + { /* conf ppar psor pdir podr pdat */ | |
167 | + /* PD31 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
168 | + /* PD30 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
169 | + /* PD29 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
170 | + /* PD28 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
171 | + /* PD27 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
172 | + /* PD26 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
173 | + /* PD25 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
174 | + /* PD24 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
175 | + /* PD23 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
176 | + /* PD22 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
177 | + /* PD21 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
178 | + /* PD20 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
179 | + /* PD19 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ | |
180 | + /* PD18 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ | |
181 | + /* PD17 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ | |
182 | + /* PD16 */ { 1, 1, 1, 0, 0, 0 }, /* not used */ | |
183 | + /* PD15 */ { 1, 1, 1, 0, 1, 1 }, /* SDRAM_SDA */ | |
184 | + /* PD14 */ { 1, 1, 1, 0, 1, 1 }, /* SDRAM_SCL */ | |
185 | + /* PD13 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED7 */ | |
186 | + /* PD12 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED6 */ | |
187 | + /* PD11 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED5 */ | |
188 | + /* PD10 */ { 1, 0, 0, 1, 0, 0 }, /* MPULED4 */ | |
189 | + /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* RS232_TXD */ | |
190 | + /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* RD232_RXD */ | |
191 | + /* PD7 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
192 | + /* PD6 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
193 | + /* PD5 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
194 | + /* PD4 */ { 1, 0, 0, 0, 0, 0 }, /* not used */ | |
195 | + /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ | |
196 | + /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ | |
197 | + /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */ | |
198 | + /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */ | |
199 | + } | |
200 | +}; | |
201 | + | |
202 | +/*********************************************************************/ | |
203 | +/* NAME: checkboard() - Displays the board type and serial number */ | |
204 | +/* */ | |
205 | +/* OUTPUTS: */ | |
206 | +/* Displays the board type and serial number */ | |
207 | +/* */ | |
208 | +/* RETURNS: */ | |
209 | +/* Always returns 1 */ | |
210 | +/* */ | |
211 | +/* RESTRICTIONS/LIMITATIONS: */ | |
212 | +/* */ | |
213 | +/* */ | |
214 | +/*********************************************************************/ | |
215 | +int checkboard(void) | |
216 | +{ | |
217 | + char *str; | |
218 | + puts ("Board: Advent Networks gw8260\n"); | |
219 | + | |
220 | + str = getenv("serial#"); | |
221 | + if (str != NULL) { | |
222 | + printf("SN: %s\n", str); | |
223 | + } | |
224 | + return 0; | |
225 | +} | |
226 | + | |
227 | + | |
228 | +#if defined (CFG_DRAM_TEST) | |
229 | +/*********************************************************************/ | |
230 | +/* NAME: move64() - moves a double word (64-bit) */ | |
231 | +/* */ | |
232 | +/* DESCRIPTION: */ | |
233 | +/* this function performs a double word move from the data at */ | |
234 | +/* the source pointer to the location at the destination pointer. */ | |
235 | +/* */ | |
236 | +/* INPUTS: */ | |
237 | +/* unsigned long long *src - pointer to data to move */ | |
238 | +/* */ | |
239 | +/* OUTPUTS: */ | |
240 | +/* unsigned long long *dest - pointer to locate to move data */ | |
241 | +/* */ | |
242 | +/* RETURNS: */ | |
243 | +/* None */ | |
244 | +/* */ | |
245 | +/* RESTRICTIONS/LIMITATIONS: */ | |
246 | +/* May cloober fr0. */ | |
247 | +/* */ | |
248 | +/*********************************************************************/ | |
249 | +static void move64(unsigned long long *src, unsigned long long *dest) | |
250 | +{ | |
251 | + asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ | |
252 | + "stfd 0, 0(4)" /* *dest = fpr0 */ | |
253 | + : : : "fr0" ); /* Clobbers fr0 */ | |
254 | + return; | |
255 | +} | |
256 | + | |
257 | + | |
258 | +#if defined (CFG_DRAM_TEST_DATA) | |
259 | + | |
260 | +unsigned long long pattern[]= { | |
261 | + 0xaaaaaaaaaaaaaaaa, | |
262 | + 0xcccccccccccccccc, | |
263 | + 0xf0f0f0f0f0f0f0f0, | |
264 | + 0xff00ff00ff00ff00, | |
265 | + 0xffff0000ffff0000, | |
266 | + 0xffffffff00000000, | |
267 | + 0x00000000ffffffff, | |
268 | + 0x0000ffff0000ffff, | |
269 | + 0x00ff00ff00ff00ff, | |
270 | + 0x0f0f0f0f0f0f0f0f, | |
271 | + 0x3333333333333333, | |
272 | + 0x5555555555555555}; | |
273 | + | |
274 | +/*********************************************************************/ | |
275 | +/* NAME: mem_test_data() - test data lines for shorts and opens */ | |
276 | +/* */ | |
277 | +/* DESCRIPTION: */ | |
278 | +/* Tests data lines for shorts and opens by forcing adjacent data */ | |
279 | +/* to opposite states. Because the data lines could be routed in */ | |
280 | +/* an arbitrary manner the must ensure test patterns ensure that */ | |
281 | +/* every case is tested. By using the following series of binary */ | |
282 | +/* patterns every combination of adjacent bits is test regardless */ | |
283 | +/* of routing. */ | |
284 | +/* */ | |
285 | +/* ...101010101010101010101010 */ | |
286 | +/* ...110011001100110011001100 */ | |
287 | +/* ...111100001111000011110000 */ | |
288 | +/* ...111111110000000011111111 */ | |
289 | +/* */ | |
290 | +/* Carrying this out, gives us six hex patterns as follows: */ | |
291 | +/* */ | |
292 | +/* 0xaaaaaaaaaaaaaaaa */ | |
293 | +/* 0xcccccccccccccccc */ | |
294 | +/* 0xf0f0f0f0f0f0f0f0 */ | |
295 | +/* 0xff00ff00ff00ff00 */ | |
296 | +/* 0xffff0000ffff0000 */ | |
297 | +/* 0xffffffff00000000 */ | |
298 | +/* */ | |
299 | +/* The number test patterns will always be given by: */ | |
300 | +/* */ | |
301 | +/* log(base 2)(number data bits) = log2 (64) = 6 */ | |
302 | +/* */ | |
303 | +/* To test for short and opens to other signals on our boards. we */ | |
304 | +/* simply */ | |
305 | +/* test with the 1's complemnt of the paterns as well. */ | |
306 | +/* */ | |
307 | +/* OUTPUTS: */ | |
308 | +/* Displays failing test pattern */ | |
309 | +/* */ | |
310 | +/* RETURNS: */ | |
311 | +/* 0 - Passed test */ | |
312 | +/* 1 - Failed test */ | |
313 | +/* */ | |
314 | +/* RESTRICTIONS/LIMITATIONS: */ | |
315 | +/* Assumes only one one SDRAM bank */ | |
316 | +/* */ | |
317 | +/*********************************************************************/ | |
318 | +int mem_test_data(void) | |
319 | +{ | |
320 | + unsigned long long * pmem = | |
321 | + (unsigned long long *)CFG_SDRAM_BASE ; | |
322 | + unsigned long long temp64; | |
323 | + int num_patterns = sizeof(pattern)/ sizeof(pattern[0]); | |
324 | + int i; | |
325 | + unsigned int hi, lo; | |
326 | + | |
327 | + for ( i = 0; i < num_patterns; i++) { | |
328 | + move64(&(pattern[i]), pmem); | |
329 | + move64(pmem, &temp64); | |
330 | + | |
331 | + /* hi = (temp64>>32) & 0xffffffff; */ | |
332 | + /* lo = temp64 & 0xffffffff; */ | |
333 | + /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ | |
334 | + | |
335 | + hi = (pattern[i]>>32) & 0xffffffff; | |
336 | + lo = pattern[i] & 0xffffffff; | |
337 | + /* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */ | |
338 | + | |
339 | + if (temp64 != pattern[i]){ | |
340 | + printf ("\n Data Test Failed, pattern 0x%08x%08x", hi, lo); | |
341 | + return 1; | |
342 | + } | |
343 | + } | |
344 | + | |
345 | + return 0; | |
346 | +} | |
347 | +#endif /* CFG_DRAM_TEST_DATA */ | |
348 | + | |
349 | +#if defined (CFG_DRAM_TEST_ADDRESS) | |
350 | +/*********************************************************************/ | |
351 | +/* NAME: mem_test_address() - test address lines */ | |
352 | +/* */ | |
353 | +/* DESCRIPTION: */ | |
354 | +/* This function performs a test to verify that each word im */ | |
355 | +/* memory is uniquly addressable. The test sequence is as follows: */ | |
356 | +/* */ | |
357 | +/* 1) write the address of each word to each word. */ | |
358 | +/* 2) verify that each location equals its address */ | |
359 | +/* */ | |
360 | +/* OUTPUTS: */ | |
361 | +/* Displays failing test pattern and address */ | |
362 | +/* */ | |
363 | +/* RETURNS: */ | |
364 | +/* 0 - Passed test */ | |
365 | +/* 1 - Failed test */ | |
366 | +/* */ | |
367 | +/* RESTRICTIONS/LIMITATIONS: */ | |
368 | +/* */ | |
369 | +/* */ | |
370 | +/*********************************************************************/ | |
371 | +int mem_test_address(void) | |
372 | +{ | |
373 | + volatile unsigned int * pmem = (volatile unsigned int *)CFG_SDRAM_BASE ; | |
374 | + const unsigned int size = (CFG_SDRAM_SIZE * 1024 * 1024)/4; | |
375 | + unsigned int i; | |
376 | + | |
377 | + /* write address to each location */ | |
378 | + for ( i = 0; i < size; i++) { | |
379 | + pmem[i] = i; | |
380 | + } | |
381 | + | |
382 | + /* verify each loaction */ | |
383 | + for ( i = 0; i < size; i++) { | |
384 | + if (pmem[i] != i) { | |
385 | + printf("\n Address Test Failed at 0x%x", i); | |
386 | + return 1; | |
387 | + } | |
388 | + } | |
389 | + return 0; | |
390 | +} | |
391 | +#endif /* CFG_DRAM_TEST_ADDRESS */ | |
392 | + | |
393 | +#if defined (CFG_DRAM_TEST_WALK) | |
394 | +/*********************************************************************/ | |
395 | +/* NAME: mem_march() - memory march */ | |
396 | +/* */ | |
397 | +/* DESCRIPTION: */ | |
398 | +/* Marches up through memory. At each location verifies rmask if */ | |
399 | +/* read = 1. At each location write wmask if write = 1. Displays */ | |
400 | +/* failing address and pattern. */ | |
401 | +/* */ | |
402 | +/* INPUTS: */ | |
403 | +/* volatile unsigned long long * base - start address of test */ | |
404 | +/* unsigned int size - number of dwords(64-bit) to test */ | |
405 | +/* unsigned long long rmask - read verify mask */ | |
406 | +/* unsigned long long wmask - wrtie verify mask */ | |
407 | +/* short read - verifies rmask if read = 1 */ | |
408 | +/* short write - writes wmask if write = 1 */ | |
409 | +/* */ | |
410 | +/* OUTPUTS: */ | |
411 | +/* Displays failing test pattern and address */ | |
412 | +/* */ | |
413 | +/* RETURNS: */ | |
414 | +/* 0 - Passed test */ | |
415 | +/* 1 - Failed test */ | |
416 | +/* */ | |
417 | +/* RESTRICTIONS/LIMITATIONS: */ | |
418 | +/* */ | |
419 | +/* */ | |
420 | +/*********************************************************************/ | |
421 | +int mem_march(volatile unsigned long long * base, | |
422 | + unsigned int size, | |
423 | + unsigned long long rmask, | |
424 | + unsigned long long wmask, | |
425 | + short read, | |
426 | + short write) | |
427 | +{ | |
428 | + unsigned int i; | |
429 | + unsigned long long temp; | |
430 | + unsigned int hitemp, lotemp, himask, lomask; | |
431 | + | |
432 | + for (i = 0 ; i < size ; i++) { | |
433 | + if (read != 0) { | |
434 | + /* temp = base[i]; */ | |
435 | + move64 ((unsigned long long *)&(base[i]), &temp); | |
436 | + if (rmask != temp) { | |
437 | + hitemp = (temp>>32) & 0xffffffff; | |
438 | + lotemp = temp & 0xffffffff; | |
439 | + himask = (rmask>>32) & 0xffffffff; | |
440 | + lomask = rmask & 0xffffffff; | |
441 | + | |
442 | + printf("\n Walking one's test failed: address = 0x%08x," | |
443 | + "\n\texpected 0x%08x%08x, found 0x%08x%08x", | |
444 | + i<<3, himask, lomask, hitemp, lotemp); | |
445 | + return 1; | |
446 | + } | |
447 | + } | |
448 | + if ( write != 0 ) { | |
449 | + /* base[i] = wmask; */ | |
450 | + move64 (&wmask, (unsigned long long *)&(base[i])); | |
451 | + } | |
452 | + } | |
453 | + return 0; | |
454 | +} | |
455 | +#endif /* CFG_DRAM_TEST_WALK */ | |
456 | + | |
457 | +/*********************************************************************/ | |
458 | +/* NAME: mem_test_walk() - a simple walking ones test */ | |
459 | +/* */ | |
460 | +/* DESCRIPTION: */ | |
461 | +/* Performs a walking ones through entire physical memory. The */ | |
462 | +/* test uses as series of memory marches, mem_march(), to verify */ | |
463 | +/* and write the test patterns to memory. The test sequence is as */ | |
464 | +/* follows: */ | |
465 | +/* 1) march writing 0000...0001 */ | |
466 | +/* 2) march verifying 0000...0001 , writing 0000...0010 */ | |
467 | +/* 3) repeat step 2 shifting masks left 1 bit each time unitl */ | |
468 | +/* the write mask equals 1000...0000 */ | |
469 | +/* 4) march verifying 1000...0000 */ | |
470 | +/* The test fails if any of the memory marches return a failure. */ | |
471 | +/* */ | |
472 | +/* OUTPUTS: */ | |
473 | +/* Displays which pass on the memory test is executing */ | |
474 | +/* */ | |
475 | +/* RETURNS: */ | |
476 | +/* 0 - Passed test */ | |
477 | +/* 1 - Failed test */ | |
478 | +/* */ | |
479 | +/* RESTRICTIONS/LIMITATIONS: */ | |
480 | +/* */ | |
481 | +/* */ | |
482 | +/*********************************************************************/ | |
483 | +int mem_test_walk(void) | |
484 | +{ | |
485 | + unsigned long long mask; | |
486 | + volatile unsigned long long * pmem = | |
487 | + (volatile unsigned long long *)CFG_SDRAM_BASE ; | |
488 | + const unsigned long size = (CFG_SDRAM_SIZE * 1024 * 1024)/8; | |
489 | + | |
490 | + unsigned int i; | |
491 | + mask = 0x01; | |
492 | + | |
493 | + printf("Initial Pass"); | |
494 | + mem_march(pmem,size,0x0,0x1,0,1); | |
495 | + | |
496 | + printf("\b\b\b\b\b\b\b\b\b\b\b\b"); | |
497 | + printf(" "); | |
498 | + printf("\b\b\b\b\b\b\b\b\b\b\b\b"); | |
499 | + | |
500 | + for (i = 0 ; i < 63 ; i++) { | |
501 | + printf("Pass %2d", i+2); | |
502 | + if ( mem_march(pmem,size, mask,mask << 1, 1, 1) != 0 ){ | |
503 | + /*printf("mask: 0x%x, pass: %d, ", mask, i);*/ | |
504 | + return 1; | |
505 | + } | |
506 | + mask = mask<<1; | |
507 | + printf("\b\b\b\b\b\b\b"); | |
508 | + } | |
509 | + | |
510 | + printf("Last Pass"); | |
511 | + if (mem_march(pmem, size, 0, mask, 0, 1) != 0) { | |
512 | + /* printf("mask: 0x%x", mask); */ | |
513 | + return 1; | |
514 | + } | |
515 | + printf("\b\b\b\b\b\b\b\b\b"); | |
516 | + printf(" "); | |
517 | + printf("\b\b\b\b\b\b\b\b\b"); | |
518 | + | |
519 | + return 0; | |
520 | +} | |
521 | + | |
522 | +/*********************************************************************/ | |
523 | +/* NAME: testdram() - calls any enabled memory tests */ | |
524 | +/* */ | |
525 | +/* DESCRIPTION: */ | |
526 | +/* Runs memory tests if the environment test variables are set to */ | |
527 | +/* 'y'. */ | |
528 | +/* */ | |
529 | +/* INPUTS: */ | |
530 | +/* testdramdata - If set to 'y', data test is run. */ | |
531 | +/* testdramaddress - If set to 'y', address test is run. */ | |
532 | +/* testdramwalk - If set to 'y', walking ones test is run */ | |
533 | +/* */ | |
534 | +/* OUTPUTS: */ | |
535 | +/* None */ | |
536 | +/* */ | |
537 | +/* RETURNS: */ | |
538 | +/* 0 - Passed test */ | |
539 | +/* 1 - Failed test */ | |
540 | +/* */ | |
541 | +/* RESTRICTIONS/LIMITATIONS: */ | |
542 | +/* */ | |
543 | +/* */ | |
544 | +/*********************************************************************/ | |
545 | +int testdram(void) | |
546 | +{ | |
547 | + char *s; | |
548 | + int rundata, runaddress, runwalk; | |
549 | + | |
550 | + s = getenv ("testdramdata"); | |
551 | + rundata = (s && (*s == 'y')) ? 1 : 0; | |
552 | + s = getenv ("testdramaddress"); | |
553 | + runaddress = (s && (*s == 'y')) ? 1 : 0; | |
554 | + s = getenv ("testdramwalk"); | |
555 | + runwalk = (s && (*s == 'y')) ? 1 : 0; | |
556 | + | |
557 | + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { | |
558 | + printf("Testing RAM ... "); | |
559 | + } | |
560 | +#ifdef CFG_DRAM_TEST_DATA | |
561 | + if (rundata == 1) { | |
562 | + if (mem_test_data() == 1){ | |
563 | + return 1; | |
564 | + } | |
565 | + } | |
566 | +#endif | |
567 | +#ifdef CFG_DRAM_TEST_ADDRESS | |
568 | + if (runaddress == 1) { | |
569 | + if (mem_test_address() == 1){ | |
570 | + return 1; | |
571 | + } | |
572 | + } | |
573 | +#endif | |
574 | +#ifdef CFG_DRAM_TEST_WALK | |
575 | + if (runwalk == 1) { | |
576 | + if (mem_test_walk() == 1){ | |
577 | + return 1; | |
578 | + } | |
579 | + } | |
580 | +#endif | |
581 | + if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { | |
582 | + printf("passed"); | |
583 | + } | |
584 | + return 0; | |
585 | + | |
586 | +} | |
587 | +#endif /* CFG_DRAM_TEST */ | |
588 | + | |
589 | +/*********************************************************************/ | |
590 | +/* NAME: initdram() - initializes SDRAM controller */ | |
591 | +/* */ | |
592 | +/* DESCRIPTION: */ | |
593 | +/* Initializes the MPC8260's SDRAM controller. */ | |
594 | +/* */ | |
595 | +/* INPUTS: */ | |
596 | +/* CFG_IMMR - MPC8260 Internal memory map */ | |
597 | +/* CFG_SDRAM_BASE - Physical start address of SDRAM */ | |
598 | +/* CFG_PSDMR - SDRAM mode register */ | |
599 | +/* CFG_MPTPR - Memory refresh timer prescaler register */ | |
600 | +/* CFG_SDRAM0_SIZE - SDRAM size */ | |
601 | +/* */ | |
602 | +/* RETURNS: */ | |
603 | +/* SDRAM size in bytes */ | |
604 | +/* */ | |
605 | +/* RESTRICTIONS/LIMITATIONS: */ | |
606 | +/* */ | |
607 | +/* */ | |
608 | +/*********************************************************************/ | |
609 | +long int initdram(int board_type) | |
610 | +{ | |
611 | + volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
612 | + volatile memctl8260_t *memctl = &immap->im_memctl; | |
613 | + volatile uchar c = 0, *ramaddr = (uchar *)(CFG_SDRAM_BASE + 0x8); | |
614 | + ulong psdmr = CFG_PSDMR; | |
615 | + int i; | |
616 | + | |
617 | + /* | |
618 | + * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35): | |
619 | + * | |
620 | + * "At system reset, initialization software must set up the | |
621 | + * programmable parameters in the memory controller banks registers | |
622 | + * (ORx, BRx, P/LSDMR). After all memory parameters are configured, | |
623 | + * system software should execute the following initialization sequence | |
624 | + * for each SDRAM device. | |
625 | + * | |
626 | + * 1. Issue a PRECHARGE-ALL-BANKS command | |
627 | + * 2. Issue eight CBR REFRESH commands | |
628 | + * 3. Issue a MODE-SET command to initialize the mode register | |
629 | + * | |
630 | + * The initial commands are executed by setting P/LSDMR[OP] and | |
631 | + * accessing the SDRAM with a single-byte transaction." | |
632 | + * | |
633 | + * The appropriate BRx/ORx registers have already been set when we | |
634 | + * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE. | |
635 | + */ | |
636 | + | |
637 | + memctl->memc_psrt = CFG_PSRT; | |
638 | + memctl->memc_mptpr = CFG_MPTPR; | |
639 | + | |
640 | + memctl->memc_psdmr = psdmr | PSDMR_OP_PREA; | |
641 | + *ramaddr = c; | |
642 | + | |
643 | + memctl->memc_psdmr = psdmr | PSDMR_OP_CBRR; | |
644 | + for (i = 0; i < 8; i++){ | |
645 | + *ramaddr = c; | |
646 | + } | |
647 | + memctl->memc_psdmr = psdmr | PSDMR_OP_MRW; | |
648 | + *ramaddr = c; | |
649 | + | |
650 | + memctl->memc_psdmr = psdmr | PSDMR_OP_NORM | PSDMR_RFEN; | |
651 | + *ramaddr = c; | |
652 | + | |
653 | + /* return total ram size */ | |
654 | + return (CFG_SDRAM0_SIZE * 1024 * 1024); | |
655 | +} | |
656 | + | |
657 | +/*********************************************************************/ | |
658 | +/* End of gw8260.c */ | |
659 | +/*********************************************************************/ |
board/mvs1/flash.c
1 | +/* | |
2 | + * (C) Copyright 2000 | |
3 | + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | + * | |
5 | + * Changes for MATRIX Vision MVsensor (C) Copyright 2001 | |
6 | + * MATRIX Vision GmbH / hg, info@matrix-vision.de | |
7 | + * | |
8 | + * See file CREDITS for list of people who contributed to this | |
9 | + * project. | |
10 | + * | |
11 | + * This program is free software; you can redistribute it and/or | |
12 | + * modify it under the terms of the GNU General Public License as | |
13 | + * published by the Free Software Foundation; either version 2 of | |
14 | + * the License, or (at your option) any later version. | |
15 | + * | |
16 | + * This program is distributed in the hope that it will be useful, | |
17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | + * GNU General Public License for more details. | |
20 | + * | |
21 | + * You should have received a copy of the GNU General Public License | |
22 | + * along with this program; if not, write to the Free Software | |
23 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
24 | + * MA 02111-1307 USA | |
25 | + */ | |
26 | + | |
27 | +#include <common.h> | |
28 | +#include <mpc8xx.h> | |
29 | + | |
30 | +#undef MVDEBUG | |
31 | +#ifdef MVDEBUG | |
32 | +#define mvdebug debug | |
33 | +#else | |
34 | +#define mvdebug(p) do {} while (0) | |
35 | +#endif | |
36 | + | |
37 | + | |
38 | +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ | |
39 | + | |
40 | + | |
41 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
42 | + #define FLASH_DATA_MASK 0xffff | |
43 | + #define FLASH_SHIFT 0 | |
44 | +#else | |
45 | + #define FLASH_DATA_MASK 0xffffffff | |
46 | + #define FLASH_SHIFT 1 | |
47 | +#endif | |
48 | + | |
49 | + | |
50 | +/*----------------------------------------------------------------------- | |
51 | + * Functions | |
52 | + */ | |
53 | +static ulong flash_get_size (vu_long *address, flash_info_t *info); | |
54 | +static int write_word (flash_info_t *info, ulong dest, ulong data); | |
55 | +static void flash_get_offsets (ulong base, flash_info_t *info); | |
56 | + | |
57 | +/*----------------------------------------------------------------------- | |
58 | + */ | |
59 | + | |
60 | +unsigned long flash_init (void) | |
61 | +{ | |
62 | + volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
63 | + volatile memctl8xx_t *memctl = &immap->im_memctl; | |
64 | + unsigned long size_b0, size_b1; | |
65 | + int i; | |
66 | + | |
67 | + /* Init: no FLASHes known */ | |
68 | + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { | |
69 | + flash_info[i].flash_id = FLASH_UNKNOWN; | |
70 | + } | |
71 | + | |
72 | + /* Static FLASH Bank configuration here - FIXME XXX */ | |
73 | + | |
74 | + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); | |
75 | + | |
76 | + if (flash_info[0].flash_id == FLASH_UNKNOWN) { | |
77 | + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", | |
78 | + size_b0, size_b0<<20); | |
79 | + } | |
80 | + | |
81 | +#if defined (FLASH_BASE1_PRELIM) | |
82 | + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); | |
83 | + | |
84 | + if (size_b1 > size_b0) { | |
85 | + printf ("## ERROR: " | |
86 | + "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n", | |
87 | + size_b1, size_b1<<20, | |
88 | + size_b0, size_b0<<20 | |
89 | + ); | |
90 | + flash_info[0].flash_id = FLASH_UNKNOWN; | |
91 | + flash_info[1].flash_id = FLASH_UNKNOWN; | |
92 | + flash_info[0].sector_count = -1; | |
93 | + flash_info[1].sector_count = -1; | |
94 | + flash_info[0].size = 0; | |
95 | + flash_info[1].size = 0; | |
96 | + return (0); | |
97 | + } | |
98 | +#else | |
99 | + size_b1 = 0; | |
100 | +#endif | |
101 | + | |
102 | + /* Remap FLASH according to real size */ | |
103 | + memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000); | |
104 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
105 | + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_MS_GPCM | BR_V; | |
106 | +#else | |
107 | + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_PS_32 | BR_MS_GPCM | BR_V; | |
108 | +#endif | |
109 | + | |
110 | + /* Re-do sizing to get full correct info */ | |
111 | + size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); | |
112 | + | |
113 | + flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]); | |
114 | + | |
115 | + /* monitor protection ON by default */ | |
116 | + flash_protect(FLAG_PROTECT_SET, | |
117 | + CFG_FLASH_BASE, | |
118 | + CFG_FLASH_BASE+CFG_MONITOR_LEN-1, | |
119 | + &flash_info[0]); | |
120 | + | |
121 | + if (size_b1) { | |
122 | + memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000); | |
123 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
124 | + memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | | |
125 | + BR_PS_16 | BR_MS_GPCM | BR_V; | |
126 | +#else | |
127 | + memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | | |
128 | + BR_PS_32 | BR_MS_GPCM | BR_V; | |
129 | +#endif | |
130 | + /* Re-do sizing to get full correct info */ | |
131 | + size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0), | |
132 | + &flash_info[1]); | |
133 | + | |
134 | + flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]); | |
135 | + | |
136 | + /* monitor protection ON by default */ | |
137 | + flash_protect(FLAG_PROTECT_SET, | |
138 | + CFG_FLASH_BASE, | |
139 | + CFG_FLASH_BASE+CFG_MONITOR_LEN-1, | |
140 | + &flash_info[1]); | |
141 | + } else { | |
142 | + memctl->memc_br1 = 0; /* invalidate bank */ | |
143 | + | |
144 | + flash_info[1].flash_id = FLASH_UNKNOWN; | |
145 | + flash_info[1].sector_count = -1; | |
146 | + } | |
147 | + | |
148 | + flash_info[0].size = size_b0; | |
149 | + flash_info[1].size = size_b1; | |
150 | + | |
151 | + return (size_b0 + size_b1); | |
152 | +} | |
153 | + | |
154 | +/*----------------------------------------------------------------------- | |
155 | + */ | |
156 | +static void flash_get_offsets (ulong base, flash_info_t *info) | |
157 | +{ | |
158 | + int i; | |
159 | + | |
160 | + /* set up sector start address table */ | |
161 | + if (info->flash_id & FLASH_BTYPE) | |
162 | + { /* bottom boot sector types - these are the useful ones! */ | |
163 | + /* set sector offsets for bottom boot block type */ | |
164 | + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) | |
165 | + { /* AMDLV320B has 8 x 8k bottom boot sectors */ | |
166 | + for (i = 0; i < 8; i++) /* +8k */ | |
167 | + info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT)); | |
168 | + for (; i < info->sector_count; i++) /* +64k */ | |
169 | + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00070000 << FLASH_SHIFT); | |
170 | + } | |
171 | + else | |
172 | + { /* other types have 4 bottom boot sectors (16,8,8,32) */ | |
173 | + i = 0; | |
174 | + info->start[i++] = base + 0x00000000; /* - */ | |
175 | + info->start[i++] = base + (0x00004000 << FLASH_SHIFT); /* +16k */ | |
176 | + info->start[i++] = base + (0x00006000 << FLASH_SHIFT); /* +8k */ | |
177 | + info->start[i++] = base + (0x00008000 << FLASH_SHIFT); /* +8k */ | |
178 | + info->start[i++] = base + (0x00010000 << FLASH_SHIFT); /* +32k */ | |
179 | + for (; i < info->sector_count; i++) /* +64k */ | |
180 | + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00030000 << FLASH_SHIFT); | |
181 | + } | |
182 | + } | |
183 | + else | |
184 | + { /* top boot sector types - not so useful */ | |
185 | + /* set sector offsets for top boot block type */ | |
186 | + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) | |
187 | + { /* AMDLV320T has 8 x 8k top boot sectors */ | |
188 | + for (i = 0; i < info->sector_count - 8; i++) /* +64k */ | |
189 | + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)); | |
190 | + for (; i < info->sector_count; i++) /* +8k */ | |
191 | + info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT)); | |
192 | + } | |
193 | + else | |
194 | + { /* other types have 4 top boot sectors (32,8,8,16) */ | |
195 | + for (i = 0; i < info->sector_count - 4; i++) /* +64k */ | |
196 | + info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)); | |
197 | + | |
198 | + info->start[i++] = base + info->size - (0x00010000 << FLASH_SHIFT); /* -32k */ | |
199 | + info->start[i++] = base + info->size - (0x00008000 << FLASH_SHIFT); /* -8k */ | |
200 | + info->start[i++] = base + info->size - (0x00006000 << FLASH_SHIFT); /* -8k */ | |
201 | + info->start[i] = base + info->size - (0x00004000 << FLASH_SHIFT); /* -16k */ | |
202 | + } | |
203 | + } | |
204 | +} | |
205 | + | |
206 | +/*----------------------------------------------------------------------- | |
207 | + */ | |
208 | +void flash_print_info (flash_info_t *info) | |
209 | +{ | |
210 | + int i; | |
211 | + | |
212 | + if (info->flash_id == FLASH_UNKNOWN) { | |
213 | + printf ("missing or unknown FLASH type\n"); | |
214 | + return; | |
215 | + } | |
216 | + | |
217 | + switch (info->flash_id & FLASH_VENDMASK) { | |
218 | + case FLASH_MAN_AMD: printf ("AMD "); break; | |
219 | + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; | |
220 | + case FLASH_MAN_STM: printf ("ST "); break; | |
221 | + default: printf ("Unknown Vendor "); break; | |
222 | + } | |
223 | + | |
224 | + switch (info->flash_id & FLASH_TYPEMASK) { | |
225 | + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); | |
226 | + break; | |
227 | + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); | |
228 | + break; | |
229 | + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); | |
230 | + break; | |
231 | + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); | |
232 | + break; | |
233 | + case FLASH_STMW320DB: printf ("M29W320B (32 Mbit, bottom boot sect)\n"); | |
234 | + break; | |
235 | + case FLASH_STMW320DT: printf ("M29W320T (32 Mbit, top boot sector)\n"); | |
236 | + break; | |
237 | + default: printf ("Unknown Chip Type\n"); | |
238 | + break; | |
239 | + } | |
240 | + | |
241 | + printf (" Size: %ld MB in %d Sectors\n", | |
242 | + info->size >> 20, info->sector_count); | |
243 | + | |
244 | + printf (" Sector Start Addresses:"); | |
245 | + for (i=0; i<info->sector_count; ++i) { | |
246 | + if ((i % 5) == 0) | |
247 | + printf ("\n "); | |
248 | + printf (" %08lX%s", | |
249 | + info->start[i], | |
250 | + info->protect[i] ? " (RO)" : " " | |
251 | + ); | |
252 | + } | |
253 | + printf ("\n"); | |
254 | +} | |
255 | + | |
256 | +/*----------------------------------------------------------------------- | |
257 | + */ | |
258 | + | |
259 | + | |
260 | +/*----------------------------------------------------------------------- | |
261 | + */ | |
262 | + | |
263 | +/* | |
264 | + * The following code cannot be run from FLASH! | |
265 | + */ | |
266 | + | |
267 | +#define AMD_ID_LV160T_MVS (AMD_ID_LV160T & FLASH_DATA_MASK) | |
268 | +#define AMD_ID_LV160B_MVS (AMD_ID_LV160B & FLASH_DATA_MASK) | |
269 | +#define AMD_ID_LV320T_MVS (AMD_ID_LV320T & FLASH_DATA_MASK) | |
270 | +#define AMD_ID_LV320B_MVS (AMD_ID_LV320B & FLASH_DATA_MASK) | |
271 | +#define STM_ID_W320DT_MVS (STM_ID_29W320DT & FLASH_DATA_MASK) | |
272 | +#define STM_ID_W320DB_MVS (STM_ID_29W320DB & FLASH_DATA_MASK) | |
273 | +#define AMD_MANUFACT_MVS (AMD_MANUFACT & FLASH_DATA_MASK) | |
274 | +#define FUJ_MANUFACT_MVS (FUJ_MANUFACT & FLASH_DATA_MASK) | |
275 | +#define STM_MANUFACT_MVS (STM_MANUFACT & FLASH_DATA_MASK) | |
276 | + | |
277 | +#define AUTOSELECT_ADDR1 0x0555 | |
278 | +#define AUTOSELECT_ADDR2 0x02AA | |
279 | +#define AUTOSELECT_ADDR3 AUTOSELECT_ADDR1 | |
280 | + | |
281 | +#define AUTOSELECT_DATA1 (0x00AA00AA & FLASH_DATA_MASK) | |
282 | +#define AUTOSELECT_DATA2 (0x00550055 & FLASH_DATA_MASK) | |
283 | +#define AUTOSELECT_DATA3 (0x00900090 & FLASH_DATA_MASK) | |
284 | + | |
285 | +#define RESET_BANK_DATA (0x00F000F0 & FLASH_DATA_MASK) | |
286 | + | |
287 | +static ulong flash_get_size (vu_long *address, flash_info_t *info) | |
288 | +{ | |
289 | + short i; | |
290 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
291 | + ushort value; | |
292 | + vu_short *addr = (vu_short *)address; | |
293 | +#else | |
294 | + ulong value; | |
295 | + vu_long *addr = (vu_long *)address; | |
296 | +#endif | |
297 | + ulong base = (ulong)address; | |
298 | + | |
299 | + /* Write auto select command: read Manufacturer ID */ | |
300 | + addr[AUTOSELECT_ADDR1] = AUTOSELECT_DATA1; | |
301 | + addr[AUTOSELECT_ADDR2] = AUTOSELECT_DATA2; | |
302 | + addr[AUTOSELECT_ADDR3] = AUTOSELECT_DATA3; | |
303 | + | |
304 | + value = addr[0]; /* manufacturer ID */ | |
305 | + switch (value) { | |
306 | + case AMD_MANUFACT_MVS: | |
307 | + info->flash_id = FLASH_MAN_AMD; | |
308 | + break; | |
309 | + case FUJ_MANUFACT_MVS: | |
310 | + info->flash_id = FLASH_MAN_FUJ; | |
311 | + break; | |
312 | + case STM_MANUFACT_MVS: | |
313 | + info->flash_id = FLASH_MAN_STM; | |
314 | + break; | |
315 | + default: | |
316 | + info->flash_id = FLASH_UNKNOWN; | |
317 | + info->sector_count = 0; | |
318 | + info->size = 0; | |
319 | + return (0); /* no or unknown flash */ | |
320 | + } | |
321 | + | |
322 | + value = addr[1]; /* device ID */ | |
323 | + switch (value) { | |
324 | + case AMD_ID_LV160T_MVS: | |
325 | + info->flash_id += FLASH_AM160T; | |
326 | + info->sector_count = 37; | |
327 | + info->size = (0x00200000 << FLASH_SHIFT); | |
328 | + break; /* => 2 or 4 MB */ | |
329 | + | |
330 | + case AMD_ID_LV160B_MVS: | |
331 | + info->flash_id += FLASH_AM160B; | |
332 | + info->sector_count = 37; | |
333 | + info->size = (0x00200000 << FLASH_SHIFT); | |
334 | + break; /* => 2 or 4 MB */ | |
335 | + | |
336 | + case AMD_ID_LV320T_MVS: | |
337 | + info->flash_id += FLASH_AM320T; | |
338 | + info->sector_count = 71; | |
339 | + info->size = (0x00400000 << FLASH_SHIFT); | |
340 | + break; /* => 4 or 8 MB */ | |
341 | + | |
342 | + case AMD_ID_LV320B_MVS: | |
343 | + info->flash_id += FLASH_AM320B; | |
344 | + info->sector_count = 71; | |
345 | + info->size = (0x00400000 << FLASH_SHIFT); | |
346 | + break; /* => 4 or 8MB */ | |
347 | + | |
348 | + case STM_ID_W320DT_MVS: | |
349 | + info->flash_id += FLASH_STMW320DT; | |
350 | + info->sector_count = 67; | |
351 | + info->size = (0x00400000 << FLASH_SHIFT); | |
352 | + break; /* => 4 or 8 MB */ | |
353 | + | |
354 | + case STM_ID_W320DB_MVS: | |
355 | + info->flash_id += FLASH_STMW320DB; | |
356 | + info->sector_count = 67; | |
357 | + info->size = (0x00400000 << FLASH_SHIFT); | |
358 | + break; /* => 4 or 8MB */ | |
359 | + | |
360 | + default: | |
361 | + info->flash_id = FLASH_UNKNOWN; | |
362 | + return (0); /* => no or unknown flash */ | |
363 | + | |
364 | + } | |
365 | + | |
366 | + /* set up sector start address table */ | |
367 | + flash_get_offsets (base, info); | |
368 | + | |
369 | + /* check for protected sectors */ | |
370 | + for (i = 0; i < info->sector_count; i++) { | |
371 | + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ | |
372 | + /* D0 = 1 if protected */ | |
373 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
374 | + addr = (vu_short *)(info->start[i]); | |
375 | +#else | |
376 | + addr = (vu_long *)(info->start[i]); | |
377 | +#endif | |
378 | + info->protect[i] = addr[2] & 1; | |
379 | + } | |
380 | + | |
381 | + /* | |
382 | + * Prevent writes to uninitialized FLASH. | |
383 | + */ | |
384 | + if (info->flash_id != FLASH_UNKNOWN) { | |
385 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
386 | + addr = (vu_short *)info->start[0]; | |
387 | +#else | |
388 | + addr = (vu_long *)info->start[0]; | |
389 | +#endif | |
390 | + *addr = RESET_BANK_DATA; /* reset bank */ | |
391 | + } | |
392 | + | |
393 | + return (info->size); | |
394 | +} | |
395 | + | |
396 | + | |
397 | +/*----------------------------------------------------------------------- | |
398 | + */ | |
399 | + | |
400 | +#define ERASE_ADDR1 0x0555 | |
401 | +#define ERASE_ADDR2 0x02AA | |
402 | +#define ERASE_ADDR3 ERASE_ADDR1 | |
403 | +#define ERASE_ADDR4 ERASE_ADDR1 | |
404 | +#define ERASE_ADDR5 ERASE_ADDR2 | |
405 | + | |
406 | +#define ERASE_DATA1 (0x00AA00AA & FLASH_DATA_MASK) | |
407 | +#define ERASE_DATA2 (0x00550055 & FLASH_DATA_MASK) | |
408 | +#define ERASE_DATA3 (0x00800080 & FLASH_DATA_MASK) | |
409 | +#define ERASE_DATA4 ERASE_DATA1 | |
410 | +#define ERASE_DATA5 ERASE_DATA2 | |
411 | + | |
412 | +#define ERASE_SECTOR_DATA (0x00300030 & FLASH_DATA_MASK) | |
413 | +#define ERASE_CHIP_DATA (0x00100010 & FLASH_DATA_MASK) | |
414 | +#define ERASE_CONFIRM_DATA (0x00800080 & FLASH_DATA_MASK) | |
415 | + | |
416 | +int flash_erase (flash_info_t *info, int s_first, int s_last) | |
417 | +{ | |
418 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
419 | + vu_short *addr = (vu_short *)(info->start[0]); | |
420 | +#else | |
421 | + vu_long *addr = (vu_long *)(info->start[0]); | |
422 | +#endif | |
423 | + int flag, prot, sect, l_sect; | |
424 | + ulong start, now, last; | |
425 | + | |
426 | + if ((s_first < 0) || (s_first > s_last)) { | |
427 | + if (info->flash_id == FLASH_UNKNOWN) { | |
428 | + printf ("- missing\n"); | |
429 | + } else { | |
430 | + printf ("- no sectors to erase\n"); | |
431 | + } | |
432 | + return 1; | |
433 | + } | |
434 | + | |
435 | + if ((info->flash_id == FLASH_UNKNOWN) || | |
436 | + (info->flash_id > FLASH_AMD_COMP)) { | |
437 | + printf ("Can't erase unknown flash type %08lx - aborted\n", | |
438 | + info->flash_id); | |
439 | + return 1; | |
440 | + } | |
441 | + | |
442 | + prot = 0; | |
443 | + for (sect=s_first; sect<=s_last; ++sect) { | |
444 | + if (info->protect[sect]) { | |
445 | + prot++; | |
446 | + } | |
447 | + } | |
448 | + | |
449 | + if (prot) { | |
450 | + printf ("- Warning: %d protected sectors will not be erased!\n", | |
451 | + prot); | |
452 | + } else { | |
453 | + printf ("\n"); | |
454 | + } | |
455 | + | |
456 | + l_sect = -1; | |
457 | + | |
458 | + /* Disable interrupts which might cause a timeout here */ | |
459 | + flag = disable_interrupts(); | |
460 | + | |
461 | + addr[ERASE_ADDR1] = ERASE_DATA1; | |
462 | + addr[ERASE_ADDR2] = ERASE_DATA2; | |
463 | + addr[ERASE_ADDR3] = ERASE_DATA3; | |
464 | + addr[ERASE_ADDR4] = ERASE_DATA4; | |
465 | + addr[ERASE_ADDR5] = ERASE_DATA5; | |
466 | + | |
467 | + /* Start erase on unprotected sectors */ | |
468 | + for (sect = s_first; sect<=s_last; sect++) { | |
469 | + if (info->protect[sect] == 0) { /* not protected */ | |
470 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
471 | + addr = (vu_short *)(info->start[sect]); | |
472 | +#else | |
473 | + addr = (vu_long *)(info->start[sect]); | |
474 | +#endif | |
475 | + addr[0] = ERASE_SECTOR_DATA; | |
476 | + l_sect = sect; | |
477 | + } | |
478 | + } | |
479 | + | |
480 | + /* re-enable interrupts if necessary */ | |
481 | + if (flag) | |
482 | + enable_interrupts(); | |
483 | + | |
484 | + /* wait at least 80us - let's wait 1 ms */ | |
485 | + udelay (1000); | |
486 | + | |
487 | + /* | |
488 | + * We wait for the last triggered sector | |
489 | + */ | |
490 | + if (l_sect < 0) | |
491 | + goto DONE; | |
492 | + | |
493 | + start = get_timer (0); | |
494 | + last = start; | |
495 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
496 | + addr = (vu_short *)(info->start[l_sect]); | |
497 | +#else | |
498 | + addr = (vu_long *)(info->start[l_sect]); | |
499 | +#endif | |
500 | + while ((addr[0] & ERASE_CONFIRM_DATA) != ERASE_CONFIRM_DATA) { | |
501 | + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { | |
502 | + printf ("Timeout\n"); | |
503 | + return 1; | |
504 | + } | |
505 | + /* show that we're waiting */ | |
506 | + if ((now - last) > 1000) { /* every second */ | |
507 | + putc ('.'); | |
508 | + last = now; | |
509 | + } | |
510 | + } | |
511 | + | |
512 | +DONE: | |
513 | + /* reset to read mode */ | |
514 | +#ifdef CONFIG_MVS_16BIT_FLASH | |
515 | + addr = (vu_short *)info->start[0]; | |
516 | +#else | |
517 | + addr = (vu_long *)info->start[0]; | |
518 | +#endif | |
519 | + addr[0] = RESET_BANK_DATA; /* reset bank */ | |
520 | + | |
521 | + printf (" done\n"); | |
522 | + return 0; | |
523 | +} | |
524 | + | |
525 | + | |
526 | +/*----------------------------------------------------------------------- | |
527 | + * Copy memory to flash, returns: | |
528 | + * 0 - OK | |
529 | + * 1 - write timeout | |
530 | + * 2 - Flash not erased | |
531 | + */ | |
532 | + | |
533 | +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) | |
534 | +{ | |
535 | +#define BUFF_INC 4 | |
536 | + ulong cp, wp, data; | |
537 | + int i, l, rc; | |
538 | + | |
539 | + mvdebug (("+write_buff %p ==> 0x%08lx, count = 0x%08lx\n", src, addr, cnt)); | |
540 | + | |
541 | + wp = (addr & ~3); /* get lower word aligned address */ | |
542 | + /* | |
543 | + * handle unaligned start bytes | |
544 | + */ | |
545 | + if ((l = addr - wp) != 0) { | |
546 | + mvdebug ((" handle unaligned start bytes (cnt = 0x%08%lx)\n", cnt)); | |
547 | + data = 0; | |
548 | + for (i=0, cp=wp; i<l; ++i, ++cp) { | |
549 | + data = (data << 8) | (*(uchar *)cp); | |
550 | + } | |
551 | + for (; i<BUFF_INC && cnt>0; ++i) { | |
552 | + data = (data << 8) | *src++; | |
553 | + --cnt; | |
554 | + ++cp; | |
555 | + } | |
556 | + for (; cnt==0 && i<BUFF_INC; ++i, ++cp) { | |
557 | + data = (data << 8) | (*(uchar *)cp); | |
558 | + } | |
559 | + | |
560 | + if ((rc = write_word(info, wp, data)) != 0) { | |
561 | + return (rc); | |
562 | + } | |
563 | + wp += BUFF_INC; | |
564 | + } | |
565 | + | |
566 | + /* | |
567 | + * handle (half)word aligned part | |
568 | + */ | |
569 | + mvdebug ((" handle word aligned part (cnt = 0x%08%lx)\n", cnt)); | |
570 | + while (cnt >= BUFF_INC) { | |
571 | + data = 0; | |
572 | + for (i=0; i<BUFF_INC; ++i) { | |
573 | + data = (data << 8) | *src++; | |
574 | + } | |
575 | + if ((rc = write_word(info, wp, data)) != 0) { | |
576 | + return (rc); | |
577 | + } | |
578 | + wp += BUFF_INC; | |
579 | + cnt -= BUFF_INC; | |
580 | + } | |
581 | + | |
582 | + if (cnt == 0) { | |
583 | + return (0); | |
584 | + } | |
585 | + | |
586 | + /* | |
587 | + * handle unaligned tail bytes | |
588 | + */ | |
589 | + mvdebug ((" handle unaligned tail bytes (cnt = 0x%08%lx)\n", cnt)); | |
590 | + data = 0; | |
591 | + for (i=0, cp=wp; i<BUFF_INC && cnt>0; ++i, ++cp) { | |
592 | + data = (data << 8) | *src++; | |
593 | + --cnt; | |
594 | + } | |
595 | + for (; i<BUFF_INC; ++i, ++cp) { | |
596 | + data = (data << 8) | (*(uchar *)cp); | |
597 | + } | |
598 | + | |
599 | + return (write_word(info, wp, data)); | |
600 | +} | |
601 | + | |
602 | +#define WRITE_ADDR1 0x0555 | |
603 | +#define WRITE_ADDR2 0x02AA | |
604 | +#define WRITE_ADDR3 WRITE_ADDR1 | |
605 | + | |
606 | +#define WRITE_DATA1 (0x00AA00AA & FLASH_DATA_MASK) | |
607 | +#define WRITE_DATA2 (0x00550055 & FLASH_DATA_MASK) | |
608 | +#define WRITE_DATA3 (0x00A000A0 & FLASH_DATA_MASK) | |
609 | + | |
610 | +#define WRITE_CONFIRM_DATA ERASE_CONFIRM_DATA | |
611 | + | |
612 | +#ifndef CONFIG_MVS_16BIT_FLASH | |
613 | +/*----------------------------------------------------------------------- | |
614 | + * Write a word to Flash, returns: | |
615 | + * 0 - OK | |
616 | + * 1 - write timeout | |
617 | + * 2 - Flash not erased | |
618 | + */ | |
619 | +static int write_word (flash_info_t *info, ulong dest, ulong data) | |
620 | +{ | |
621 | + vu_long *addr = (vu_long *)(info->start[0]); | |
622 | + ulong start; | |
623 | + int flag; | |
624 | + | |
625 | + mvdebug (("+write_word (to 0x%08lx)\n", dest)); | |
626 | + /* Check if Flash is (sufficiently) erased */ | |
627 | + if ((*((vu_long *)dest) & data) != data) { | |
628 | + return (2); | |
629 | + } | |
630 | + /* Disable interrupts which might cause a timeout here */ | |
631 | + flag = disable_interrupts(); | |
632 | + | |
633 | + addr[WRITE_ADDR1] = WRITE_DATA1; | |
634 | + addr[WRITE_ADDR2] = WRITE_DATA2; | |
635 | + addr[WRITE_ADDR3] = WRITE_DATA3; | |
636 | + | |
637 | + *((vu_long *)dest) = data; | |
638 | + | |
639 | + /* re-enable interrupts if necessary */ | |
640 | + if (flag) | |
641 | + enable_interrupts(); | |
642 | + | |
643 | + /* data polling for D7 */ | |
644 | + start = get_timer (0); | |
645 | + addr = (vu_long *)dest; | |
646 | + while ((*addr & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) { | |
647 | + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { | |
648 | + return (1); | |
649 | + } | |
650 | + } | |
651 | + | |
652 | + mvdebug (("-write_word\n")); | |
653 | + return (0); | |
654 | +} | |
655 | +#else /* CONFIG_MVS_16BIT_FLASH */ | |
656 | +/*----------------------------------------------------------------------- | |
657 | + * Write a halfword to Flash, returns: | |
658 | + * 0 - OK | |
659 | + * 1 - write timeout | |
660 | + * 2 - Flash not erased | |
661 | + */ | |
662 | +static int write_halfword (flash_info_t *info, ulong dest, ushort data) | |
663 | +{ | |
664 | + vu_short *addr = (vu_short *)(info->start[0]); | |
665 | + ulong start; | |
666 | + int flag; | |
667 | + | |
668 | + mvdebug (("+write_halfword (to 0x%08lx)\n", dest)); | |
669 | + /* Check if Flash is (sufficiently) erased */ | |
670 | + if ((*((vu_short *)dest) & data) != data) { | |
671 | + return (2); | |
672 | + } | |
673 | + /* Disable interrupts which might cause a timeout here */ | |
674 | + flag = disable_interrupts(); | |
675 | + | |
676 | + addr[WRITE_ADDR1] = WRITE_DATA1; | |
677 | + addr[WRITE_ADDR2] = WRITE_DATA2; | |
678 | + addr[WRITE_ADDR3] = WRITE_DATA3; | |
679 | + | |
680 | + *((vu_short *)dest) = data; | |
681 | + | |
682 | + /* re-enable interrupts if necessary */ | |
683 | + if (flag) | |
684 | + enable_interrupts(); | |
685 | + | |
686 | + /* data polling for D7 */ | |
687 | + start = get_timer (0); | |
688 | + addr = (vu_short *)dest; | |
689 | + while ((*addr & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) { | |
690 | + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { | |
691 | + return (1); | |
692 | + } | |
693 | + } | |
694 | + mvdebug (("-write_halfword\n")); | |
695 | + return (0); | |
696 | +} | |
697 | + | |
698 | + | |
699 | +/*----------------------------------------------------------------------- | |
700 | + * Write a word to Flash, returns: | |
701 | + * 0 - OK | |
702 | + * 1 - write timeout | |
703 | + * 2 - Flash not erased | |
704 | + */ | |
705 | +static int write_word (flash_info_t *info, ulong dest, ulong data) | |
706 | +{ | |
707 | + int result = 0; | |
708 | + | |
709 | + if (write_halfword (info, dest, (data & ~FLASH_DATA_MASK) >> 16) == 0) | |
710 | + { | |
711 | + dest += 2; | |
712 | + data = data & FLASH_DATA_MASK; | |
713 | + result = write_halfword (info, dest, data); | |
714 | + } | |
715 | + return result; | |
716 | +} | |
717 | +#endif | |
718 | +/*----------------------------------------------------------------------- | |
719 | + */ |