blob: 14d3aee8215fa286cf653d2dcd22e5d9c1ea420b [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00006 */
7
8#include <common.h>
9#include <mpc8xx.h>
10
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020011flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenkaffae2b2002-08-17 09:36:01 +000012
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +020013#if defined(CONFIG_ENV_IS_IN_FLASH)
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020014# ifndef CONFIG_ENV_ADDR
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020015# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
wdenkaffae2b2002-08-17 09:36:01 +000016# endif
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020017# ifndef CONFIG_ENV_SIZE
18# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
wdenkaffae2b2002-08-17 09:36:01 +000019# endif
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020020# ifndef CONFIG_ENV_SECT_SIZE
21# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
wdenkaffae2b2002-08-17 09:36:01 +000022# endif
23#endif
24
25/*-----------------------------------------------------------------------
26 * Functions
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{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020037 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
wdenkaffae2b2002-08-17 09:36:01 +000038 volatile memctl8xx_t *memctl = &immap->im_memctl;
39 unsigned long size_b0;
40 int i;
41
42 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020043 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenkaffae2b2002-08-17 09:36:01 +000044 flash_info[i].flash_id = FLASH_UNKNOWN;
45 }
46
47 /* Static FLASH Bank configuration here - FIXME XXX */
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 /* Remap FLASH according to real size */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020059 memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
60 memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | \
wdenkaffae2b2002-08-17 09:36:01 +000061 BR_MS_GPCM | BR_PS_16 | BR_V;
62
63 /* Re-do sizing to get full correct info */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020064 size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
wdenkaffae2b2002-08-17 09:36:01 +000065
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020066 flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
wdenkaffae2b2002-08-17 09:36:01 +000067
68 flash_info[0].size = size_b0;
69
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020070#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
wdenkaffae2b2002-08-17 09:36:01 +000071 /* monitor protection ON by default */
72 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020073 CONFIG_SYS_MONITOR_BASE,
74 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
wdenkaffae2b2002-08-17 09:36:01 +000075 &flash_info[0]);
76#endif
77
Jean-Christophe PLAGNIOL-VILLARD5a1aceb2008-09-10 22:48:04 +020078#ifdef CONFIG_ENV_IS_IN_FLASH
wdenkaffae2b2002-08-17 09:36:01 +000079 /* ENV protection ON by default */
80 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020081 CONFIG_ENV_ADDR,
82 CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
wdenkaffae2b2002-08-17 09:36:01 +000083 &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 /* set sector offsets for bottom boot block type */
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 /* set sector offsets for top boot block type */
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 /* set up sector start address table */
132 if (info->flash_id & FLASH_BTYPE) {
133 /* set sector offsets for bottom boot block type */
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 /* set sector offsets for top boot block type */
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 * The following code cannot be run from FLASH!
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 /* Read Manufacturer ID */
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; /* restore read mode */
279 return (0); /* no or unknown flash */
280 }
281
282 value = saddr[1]; /* device ID */
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; /* => 1 MB */
290
291 case (AMD_ID_LV400B & 0xFFFF):
292 info->flash_id += FLASH_AM400B;
293 info->sector_count = 11;
294 info->size = 0x00100000;
295 break; /* => 1 MB */
296
297 case (AMD_ID_LV800T & 0xFFFF):
298 info->flash_id += FLASH_AM800T;
299 info->sector_count = 19;
300 info->size = 0x00200000;
301 break; /* => 2 MB */
302
303 case (AMD_ID_LV800B & 0xFFFF):
304 info->flash_id += FLASH_AM800B;
305 info->sector_count = 19;
306 info->size = 0x00200000;
307 break; /* => 2 MB */
308
309 case (AMD_ID_LV160T & 0xFFFF):
310 info->flash_id += FLASH_AM160T;
311 info->sector_count = 35;
312 info->size = 0x00400000;
313 break; /* => 4 MB */
314
315 case (AMD_ID_LV160B & 0xFFFF):
316 info->flash_id += FLASH_AM160B;
317 info->sector_count = 35;
318 info->size = 0x00400000;
319 break; /* => 4 MB */
320#if 0 /* enable when device IDs are available */
321 case (AMD_ID_LV320T & 0xFFFF):
322 info->flash_id += FLASH_AM320T;
323 info->sector_count = 67;
324 info->size = 0x00800000;
325 break; /* => 8 MB */
326
327 case (AMD_ID_LV320B & 0xFFFF):
328 info->flash_id += FLASH_AM320B;
329 info->sector_count = 67;
330 info->size = 0x00800000;
331 break; /* => 8 MB */
332#endif
333 case (SST_ID_xF200A & 0xFFFF):
334 info->flash_id += FLASH_SST200A;
335 info->sector_count = 64; /* 39xF200A ID ( 2M = 128K x 16 ) */
336 info->size = 0x00080000;
337 break;
338 case (SST_ID_xF400A & 0xFFFF):
339 info->flash_id += FLASH_SST400A;
340 info->sector_count = 128; /* 39xF400A ID ( 4M = 256K x 16 ) */
341 info->size = 0x00100000;
342 break;
343 case (SST_ID_xF800A & 0xFFFF):
344 info->flash_id += FLASH_SST800A;
345 info->sector_count = 256; /* 39xF800A ID ( 8M = 512K x 16 ) */
346 info->size = 0x00200000;
347 break; /* => 2 MB */
348 case (STM_ID_x800AB & 0xFFFF):
349 info->flash_id += FLASH_STM800AB;
350 info->sector_count = 19;
351 info->size = 0x00200000;
352 break; /* => 2 MB */
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; /* => 512 kB */
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; /* => 512 kB */
363 default:
364 info->flash_id = FLASH_UNKNOWN;
365 saddr[0] = 0x00FF; /* restore read mode */
366 return (0); /* => no or unknown flash */
367
368 }
369
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200370 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
wdenkaffae2b2002-08-17 09:36:01 +0000371 printf ("** ERROR: sector count %d > max (%d) **\n",
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200372 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
373 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
wdenkaffae2b2002-08-17 09:36:01 +0000374 }
375
376 saddr[0] = 0x00FF; /* restore read mode */
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 /* Start erase on unprotected sectors */
421 for (sect = s_first; sect<=s_last; sect++) {
422 if (info->protect[sect] == 0) { /* not protected */
423 vu_short *addr = (vu_short *)(info->start[sect]);
424 unsigned short status;
425
426 /* Disable interrupts which might cause a timeout here */
427 flag = disable_interrupts();
428
429 *addr = 0x0050; /* clear status register */
430 *addr = 0x0020; /* erase setup */
431 *addr = 0x00D0; /* erase confirm */
432
433 /* re-enable interrupts if necessary */
434 if (flag)
435 enable_interrupts();
436
437 /* wait at least 80us - let's wait 1 ms */
438 udelay (1000);
439
440 while (((status = *addr) & 0x0080) != 0x0080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200441 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkaffae2b2002-08-17 09:36:01 +0000442 printf ("Timeout\n");
443 *addr = 0x00FF; /* reset to read mode */
444 return 1;
445 }
446
447 /* show that we're waiting */
448 if ((now - last) > 1000) { /* every second */
449 putc ('.');
450 last = now;
451 }
452 }
453
454 *addr = 0x00FF; /* reset to read mode */
455 }
456 }
457 printf (" done\n");
458 return 0;
459}
460
461/*-----------------------------------------------------------------------
462 * Copy memory to flash, returns:
463 * 0 - OK
464 * 1 - write timeout
465 * 2 - Flash not erased
466 * 4 - Flash not identified
467 */
468
469#define FLASH_WIDTH 2 /* flash bus width in bytes */
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)); /* get lower FLASH_WIDTH aligned address */
481
482 /*
483 * handle unaligned start bytes
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 * handle FLASH_WIDTH aligned part
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 * handle unaligned tail bytes
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 * Write a word to Flash, returns:
541 * 0 - OK
542 * 1 - write timeout
543 * 2 - Flash not erased
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 /* Check if Flash is (sufficiently) erased */
554 if ((*addr & sdata) != sdata) {
555 return (2);
556 }
557 /* Disable interrupts which might cause a timeout here */
558 flag = disable_interrupts();
559
560 *addr = 0x0040; /* write setup */
561 *addr = sdata;
562
563 /* re-enable interrupts if necessary */
564 if (flag)
565 enable_interrupts();
566
567 start = get_timer (0);
568
569 while (((status = *addr) & 0x0080) != 0x0080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200570 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkaffae2b2002-08-17 09:36:01 +0000571 *addr = 0x00FF; /* restore read mode */
572 return (1);
573 }
574 }
575
576 *addr = 0x00FF; /* restore read mode */
577
578 return (0);
579}
580
581/*-----------------------------------------------------------------------
582 */