1
2
3
4
5
6
7
8#include <common.h>
9#include <mpc8xx.h>
10
11flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
12
13#if defined(CONFIG_ENV_IS_IN_FLASH)
14# ifndef CONFIG_ENV_ADDR
15# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
16# endif
17# ifndef CONFIG_ENV_SIZE
18# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
19# endif
20# ifndef CONFIG_ENV_SECT_SIZE
21# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
22# endif
23#endif
24
25
26
27
28static ulong flash_get_size (vu_long *addr, flash_info_t *info);
29static int write_data (flash_info_t *info, ulong dest, ulong data);
30static void flash_get_offsets (ulong base, flash_info_t *info);
31
32
33
34
35unsigned long flash_init (void)
36{
37 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
38 volatile memctl8xx_t *memctl = &immap->im_memctl;
39 unsigned long size_b0;
40 int i;
41
42
43 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
44 flash_info[i].flash_id = FLASH_UNKNOWN;
45 }
46
47
48
49 size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
50
51 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
52 printf ("## Unknown FLASH on Bank 0: "
53 "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
54 flash_info[0].flash_id,
55 size_b0, size_b0<<20);
56 }
57
58
59 memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
60 memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | \
61 BR_MS_GPCM | BR_PS_16 | BR_V;
62
63
64 size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
65
66 flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
67
68 flash_info[0].size = size_b0;
69
70#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
71
72 flash_protect(FLAG_PROTECT_SET,
73 CONFIG_SYS_MONITOR_BASE,
74 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
75 &flash_info[0]);
76#endif
77
78#ifdef CONFIG_ENV_IS_IN_FLASH
79
80 flash_protect(FLAG_PROTECT_SET,
81 CONFIG_ENV_ADDR,
82 CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
83 &flash_info[0]);
84#endif
85
86 return (size_b0);
87}
88
89
90
91static void flash_get_offsets (ulong base, flash_info_t *info)
92{
93 int i;
94
95 if (info->flash_id == FLASH_UNKNOWN) {
96 return;
97 }
98
99 switch (info->flash_id & FLASH_VENDMASK) {
100 case FLASH_MAN_MT:
101 if (info->flash_id & FLASH_BTYPE) {
102
103 info->start[0] = base + 0x00000000;
104 info->start[1] = base + 0x00004000;
105 info->start[2] = base + 0x00006000;
106 info->start[3] = base + 0x00008000;
107 for (i = 4; i < info->sector_count; i++) {
108 info->start[i] = base + ((i-3) * 0x00020000);
109 }
110 } else {
111
112 i = info->sector_count - 1;
113 info->start[i--] = base + info->size - 0x00004000;
114 info->start[i--] = base + info->size - 0x00006000;
115 info->start[i--] = base + info->size - 0x00008000;
116 for (; i >= 0; i--) {
117 info->start[i] = base + i * 0x00020000;
118 }
119 }
120 return;
121
122 case FLASH_MAN_SST:
123 for (i = 0; i < info->sector_count; i++) {
124 info->start[i] = base + (i * 0x00002000);
125 }
126 return;
127
128 case FLASH_MAN_AMD:
129 case FLASH_MAN_FUJ:
130
131
132 if (info->flash_id & FLASH_BTYPE) {
133
134 info->start[0] = base + 0x00000000;
135 info->start[1] = base + 0x00008000;
136 info->start[2] = base + 0x0000C000;
137 info->start[3] = base + 0x00010000;
138 for (i = 4; i < info->sector_count; i++) {
139 info->start[i] = base + (i * 0x00020000) - 0x00060000;
140 }
141 } else {
142
143 i = info->sector_count - 1;
144 info->start[i--] = base + info->size - 0x00008000;
145 info->start[i--] = base + info->size - 0x0000C000;
146 info->start[i--] = base + info->size - 0x00010000;
147 for (; i >= 0; i--) {
148 info->start[i] = base + i * 0x00020000;
149 }
150 }
151 return;
152 default:
153 printf ("Don't know sector ofsets for flash type 0x%lx\n",
154 info->flash_id);
155 return;
156 }
157}
158
159
160
161void flash_print_info (flash_info_t *info)
162{
163 int i;
164
165 if (info->flash_id == FLASH_UNKNOWN) {
166 printf ("missing or unknown FLASH type\n");
167 return;
168 }
169
170 switch (info->flash_id & FLASH_VENDMASK) {
171 case FLASH_MAN_AMD: printf ("AMD "); break;
172 case FLASH_MAN_FUJ: printf ("Fujitsu "); break;
173 case FLASH_MAN_SST: printf ("SST "); break;
174 case FLASH_MAN_STM: printf ("STM "); break;
175 case FLASH_MAN_MT: printf ("MT "); break;
176 case FLASH_MAN_INTEL: printf ("Intel "); break;
177 default: printf ("Unknown Vendor "); break;
178 }
179
180 switch (info->flash_id & FLASH_TYPEMASK) {
181 case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
182 break;
183 case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
184 break;
185 case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
186 break;
187 case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
188 break;
189 case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
190 break;
191 case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
192 break;
193 case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
194 break;
195 case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
196 break;
197 case FLASH_SST200A: printf ("39xF200A (2M = 128K x 16)\n");
198 break;
199 case FLASH_SST400A: printf ("39xF400A (4M = 256K x 16)\n");
200 break;
201 case FLASH_SST800A: printf ("39xF800A (8M = 512K x 16)\n");
202 break;
203 case FLASH_STM800AB: printf ("M29W800AB (8M = 512K x 16)\n");
204 break;
205 case FLASH_28F008S5: printf ("28F008S5 (1M = 64K x 16)\n");
206 break;
207 case FLASH_28F400_T: printf ("28F400B3 (4Mbit, top boot sector)\n");
208 break;
209 case FLASH_28F400_B: printf ("28F400B3 (4Mbit, bottom boot sector)\n");
210 break;
211 default: printf ("Unknown Chip Type\n");
212 break;
213 }
214
215 if (info->size >= (1 << 20)) {
216 i = 20;
217 } else {
218 i = 10;
219 }
220 printf (" Size: %ld %cB in %d Sectors\n",
221 info->size >> i,
222 (i == 20) ? 'M' : 'k',
223 info->sector_count);
224
225 printf (" Sector Start Addresses:");
226 for (i=0; i<info->sector_count; ++i) {
227 if ((i % 5) == 0)
228 printf ("\n ");
229 printf (" %08lX%s",
230 info->start[i],
231 info->protect[i] ? " (RO)" : " "
232 );
233 }
234 printf ("\n");
235 return;
236}
237
238
239
240
241
242
243
244
245
246
247
248
249static ulong flash_get_size (vu_long *addr, flash_info_t *info)
250{
251 ushort value;
252 vu_short *saddr = (vu_short *)addr;
253
254
255 saddr[0] = 0x0090;
256 value = saddr[0];
257
258 switch (value) {
259 case (AMD_MANUFACT & 0xFFFF):
260 info->flash_id = FLASH_MAN_AMD;
261 break;
262 case (FUJ_MANUFACT & 0xFFFF):
263 info->flash_id = FLASH_MAN_FUJ;
264 break;
265 case (SST_MANUFACT & 0xFFFF):
266 info->flash_id = FLASH_MAN_SST;
267 break;
268 case (STM_MANUFACT & 0xFFFF):
269 info->flash_id = FLASH_MAN_STM;
270 break;
271 case (MT_MANUFACT & 0xFFFF):
272 info->flash_id = FLASH_MAN_MT;
273 break;
274 default:
275 info->flash_id = FLASH_UNKNOWN;
276 info->sector_count = 0;
277 info->size = 0;
278 saddr[0] = 0x00FF;
279 return (0);
280 }
281
282 value = saddr[1];
283
284 switch (value) {
285 case (AMD_ID_LV400T & 0xFFFF):
286 info->flash_id += FLASH_AM400T;
287 info->sector_count = 11;
288 info->size = 0x00100000;
289 break;
290
291 case (AMD_ID_LV400B & 0xFFFF):
292 info->flash_id += FLASH_AM400B;
293 info->sector_count = 11;
294 info->size = 0x00100000;
295 break;
296
297 case (AMD_ID_LV800T & 0xFFFF):
298 info->flash_id += FLASH_AM800T;
299 info->sector_count = 19;
300 info->size = 0x00200000;
301 break;
302
303 case (AMD_ID_LV800B & 0xFFFF):
304 info->flash_id += FLASH_AM800B;
305 info->sector_count = 19;
306 info->size = 0x00200000;
307 break;
308
309 case (AMD_ID_LV160T & 0xFFFF):
310 info->flash_id += FLASH_AM160T;
311 info->sector_count = 35;
312 info->size = 0x00400000;
313 break;
314
315 case (AMD_ID_LV160B & 0xFFFF):
316 info->flash_id += FLASH_AM160B;
317 info->sector_count = 35;
318 info->size = 0x00400000;
319 break;
320#if 0
321 case (AMD_ID_LV320T & 0xFFFF):
322 info->flash_id += FLASH_AM320T;
323 info->sector_count = 67;
324 info->size = 0x00800000;
325 break;
326
327 case (AMD_ID_LV320B & 0xFFFF):
328 info->flash_id += FLASH_AM320B;
329 info->sector_count = 67;
330 info->size = 0x00800000;
331 break;
332#endif
333 case (SST_ID_xF200A & 0xFFFF):
334 info->flash_id += FLASH_SST200A;
335 info->sector_count = 64;
336 info->size = 0x00080000;
337 break;
338 case (SST_ID_xF400A & 0xFFFF):
339 info->flash_id += FLASH_SST400A;
340 info->sector_count = 128;
341 info->size = 0x00100000;
342 break;
343 case (SST_ID_xF800A & 0xFFFF):
344 info->flash_id += FLASH_SST800A;
345 info->sector_count = 256;
346 info->size = 0x00200000;
347 break;
348 case (STM_ID_x800AB & 0xFFFF):
349 info->flash_id += FLASH_STM800AB;
350 info->sector_count = 19;
351 info->size = 0x00200000;
352 break;
353 case (MT_ID_28F400_T & 0xFFFF):
354 info->flash_id += FLASH_28F400_T;
355 info->sector_count = 7;
356 info->size = 0x00080000;
357 break;
358 case (MT_ID_28F400_B & 0xFFFF):
359 info->flash_id += FLASH_28F400_B;
360 info->sector_count = 7;
361 info->size = 0x00080000;
362 break;
363 default:
364 info->flash_id = FLASH_UNKNOWN;
365 saddr[0] = 0x00FF;
366 return (0);
367
368 }
369
370 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
371 printf ("** ERROR: sector count %d > max (%d) **\n",
372 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
373 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
374 }
375
376 saddr[0] = 0x00FF;
377
378 return (info->size);
379}
380
381
382
383
384
385int flash_erase (flash_info_t *info, int s_first, int s_last)
386{
387 int flag, prot, sect;
388 ulong start, now, last;
389
390 if ((s_first < 0) || (s_first > s_last)) {
391 if (info->flash_id == FLASH_UNKNOWN) {
392 printf ("- missing\n");
393 } else {
394 printf ("- no sectors to erase\n");
395 }
396 return 1;
397 }
398
399 if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MT) {
400 printf ("Can erase only MT flash types - aborted\n");
401 return 1;
402 }
403
404 prot = 0;
405 for (sect=s_first; sect<=s_last; ++sect) {
406 if (info->protect[sect]) {
407 prot++;
408 }
409 }
410
411 if (prot) {
412 printf ("- Warning: %d protected sectors will not be erased!\n",
413 prot);
414 } else {
415 printf ("\n");
416 }
417
418 start = get_timer (0);
419 last = start;
420
421 for (sect = s_first; sect<=s_last; sect++) {
422 if (info->protect[sect] == 0) {
423 vu_short *addr = (vu_short *)(info->start[sect]);
424 unsigned short status;
425
426
427 flag = disable_interrupts();
428
429 *addr = 0x0050;
430 *addr = 0x0020;
431 *addr = 0x00D0;
432
433
434 if (flag)
435 enable_interrupts();
436
437
438 udelay (1000);
439
440 while (((status = *addr) & 0x0080) != 0x0080) {
441 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
442 printf ("Timeout\n");
443 *addr = 0x00FF;
444 return 1;
445 }
446
447
448 if ((now - last) > 1000) {
449 putc ('.');
450 last = now;
451 }
452 }
453
454 *addr = 0x00FF;
455 }
456 }
457 printf (" done\n");
458 return 0;
459}
460
461
462
463
464
465
466
467
468
469#define FLASH_WIDTH 2
470
471int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
472{
473 ulong cp, wp, data;
474 int i, l, rc;
475
476 if (info->flash_id == FLASH_UNKNOWN) {
477 return 4;
478 }
479
480 wp = (addr & ~(FLASH_WIDTH-1));
481
482
483
484
485 if ((l = addr - wp) != 0) {
486 data = 0;
487 for (i=0, cp=wp; i<l; ++i, ++cp) {
488 data = (data << 8) | (*(uchar *)cp);
489 }
490 for (; i<FLASH_WIDTH && cnt>0; ++i) {
491 data = (data << 8) | *src++;
492 --cnt;
493 ++cp;
494 }
495 for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
496 data = (data << 8) | (*(uchar *)cp);
497 }
498
499 if ((rc = write_data(info, wp, data)) != 0) {
500 return (rc);
501 }
502 wp += FLASH_WIDTH;
503 }
504
505
506
507
508 while (cnt >= FLASH_WIDTH) {
509 data = 0;
510 for (i=0; i<FLASH_WIDTH; ++i) {
511 data = (data << 8) | *src++;
512 }
513 if ((rc = write_data(info, wp, data)) != 0) {
514 return (rc);
515 }
516 wp += FLASH_WIDTH;
517 cnt -= FLASH_WIDTH;
518 }
519
520 if (cnt == 0) {
521 return (0);
522 }
523
524
525
526
527 data = 0;
528 for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
529 data = (data << 8) | *src++;
530 --cnt;
531 }
532 for (; i<FLASH_WIDTH; ++i, ++cp) {
533 data = (data << 8) | (*(uchar *)cp);
534 }
535
536 return (write_data(info, wp, data));
537}
538
539
540
541
542
543
544
545static int write_data (flash_info_t *info, ulong dest, ulong data)
546{
547 vu_short *addr = (vu_short *)dest;
548 ushort sdata = (ushort)data;
549 ushort status;
550 ulong start;
551 int flag;
552
553
554 if ((*addr & sdata) != sdata) {
555 return (2);
556 }
557
558 flag = disable_interrupts();
559
560 *addr = 0x0040;
561 *addr = sdata;
562
563
564 if (flag)
565 enable_interrupts();
566
567 start = get_timer (0);
568
569 while (((status = *addr) & 0x0080) != 0x0080) {
570 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
571 *addr = 0x00FF;
572 return (1);
573 }
574 }
575
576 *addr = 0x00FF;
577
578 return (0);
579}
580
581
582
583