]> git.ipfire.org Git - thirdparty/u-boot.git/blame - board/atc/flash.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[thirdparty/u-boot.git] / board / atc / flash.c
CommitLineData
7aa78614
WD
1/*
2 * (C) Copyright 2003
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
1a459660 5 * SPDX-License-Identifier: GPL-2.0+
7aa78614
WD
6 */
7
8#include <common.h>
9
6d0f6bcf 10flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
7aa78614
WD
11
12/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
13 * has nothing to do with the flash chip being 8-bit or 16-bit.
14 */
15#ifdef CONFIG_FLASH_16BIT
16typedef unsigned short FLASH_PORT_WIDTH;
17typedef volatile unsigned short FLASH_PORT_WIDTHV;
18#define FLASH_ID_MASK 0xFFFF
19#else
20typedef unsigned long FLASH_PORT_WIDTH;
21typedef volatile unsigned long FLASH_PORT_WIDTHV;
22#define FLASH_ID_MASK 0xFFFFFFFF
23#endif
24
25#define FPW FLASH_PORT_WIDTH
26#define FPWV FLASH_PORT_WIDTHV
27
28#define ORMASK(size) ((-size) & OR_AM_MSK)
29
30#define FLASH_CYCLE1 0x0555
31#define FLASH_CYCLE2 0x02aa
32
33/*-----------------------------------------------------------------------
34 * Functions
35 */
36static ulong flash_get_size(FPWV *addr, flash_info_t *info);
37static void flash_reset(flash_info_t *info);
38static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
39static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
40static void flash_get_offsets(ulong base, flash_info_t *info);
41static flash_info_t *flash_get_info(ulong base);
42
43/*-----------------------------------------------------------------------
44 * flash_init()
45 *
46 * sets up flash_info and returns size of FLASH (bytes)
47 */
48unsigned long flash_init (void)
49{
50 unsigned long size = 0;
51 int i;
52
53 /* Init: no FLASHes known */
6d0f6bcf 54 for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
7aa78614
WD
55#if 0
56 ulong flashbase = (i == 0) ? PHYS_FLASH_1 : PHYS_FLASH_2;
57#else
6d0f6bcf 58 ulong flashbase = CONFIG_SYS_FLASH_BASE;
7aa78614
WD
59#endif
60
61 memset(&flash_info[i], 0, sizeof(flash_info_t));
62
8bde7f77 63 flash_info[i].size =
7aa78614
WD
64 flash_get_size((FPW *)flashbase, &flash_info[i]);
65
66 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
67 printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx\n",
68 i, flash_info[i].size);
69 }
8bde7f77 70
7aa78614
WD
71 size += flash_info[i].size;
72 }
73
6d0f6bcf 74#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
7aa78614
WD
75 /* monitor protection ON by default */
76 flash_protect(FLAG_PROTECT_SET,
6d0f6bcf
JCPV
77 CONFIG_SYS_MONITOR_BASE,
78 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
79 flash_get_info(CONFIG_SYS_MONITOR_BASE));
7aa78614
WD
80#endif
81
5a1aceb0 82#ifdef CONFIG_ENV_IS_IN_FLASH
7aa78614
WD
83 /* ENV protection ON by default */
84 flash_protect(FLAG_PROTECT_SET,
0e8d1586
JCPV
85 CONFIG_ENV_ADDR,
86 CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
87 flash_get_info(CONFIG_ENV_ADDR));
7aa78614
WD
88#endif
89
90
91 return size ? size : 1;
92}
93
94/*-----------------------------------------------------------------------
95 */
96static void flash_reset(flash_info_t *info)
97{
98 FPWV *base = (FPWV *)(info->start[0]);
99
100 /* Put FLASH back in read mode */
101 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
102 *base = (FPW)0x00FF00FF; /* Intel Read Mode */
103 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
104 *base = (FPW)0x00F000F0; /* AMD Read Mode */
105}
106
107/*-----------------------------------------------------------------------
108 */
109static void flash_get_offsets (ulong base, flash_info_t *info)
110{
111 int i;
112
113 /* set up sector start address table */
114 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
115 && (info->flash_id & FLASH_BTYPE)) {
116 int bootsect_size; /* number of bytes/boot sector */
117 int sect_size; /* number of bytes/regular sector */
118
119 bootsect_size = 0x00002000 * (sizeof(FPW)/2);
120 sect_size = 0x00010000 * (sizeof(FPW)/2);
121
122 /* set sector offsets for bottom boot block type */
123 for (i = 0; i < 8; ++i) {
124 info->start[i] = base + (i * bootsect_size);
125 }
126 for (i = 8; i < info->sector_count; i++) {
127 info->start[i] = base + ((i - 7) * sect_size);
128 }
129 }
130 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
131 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
132
133 int sect_size; /* number of bytes/sector */
134
135 sect_size = 0x00010000 * (sizeof(FPW)/2);
136
137 /* set up sector start address table (uniform sector type) */
138 for( i = 0; i < info->sector_count; i++ )
139 info->start[i] = base + (i * sect_size);
140 }
141}
142
143/*-----------------------------------------------------------------------
144 */
145
146static flash_info_t *flash_get_info(ulong base)
147{
148 int i;
149 flash_info_t * info;
8bde7f77 150
6d0f6bcf 151 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
7aa78614
WD
152 info = & flash_info[i];
153 if (info->start[0] <= base && base < info->start[0] + info->size)
154 break;
155 }
8bde7f77 156
6d0f6bcf 157 return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
7aa78614
WD
158}
159
160/*-----------------------------------------------------------------------
161 */
162
163void flash_print_info (flash_info_t *info)
164{
165 int i;
166 uchar *boottype;
167 uchar *bootletter;
77ddac94 168 char *fmt;
7aa78614
WD
169 uchar botbootletter[] = "B";
170 uchar topbootletter[] = "T";
171 uchar botboottype[] = "bottom boot sector";
172 uchar topboottype[] = "top boot sector";
173
174 if (info->flash_id == FLASH_UNKNOWN) {
175 printf ("missing or unknown FLASH type\n");
176 return;
177 }
178
179 switch (info->flash_id & FLASH_VENDMASK) {
180 case FLASH_MAN_AMD: printf ("AMD "); break;
181 case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break;
182 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
183 case FLASH_MAN_SST: printf ("SST "); break;
184 case FLASH_MAN_STM: printf ("STM "); break;
185 case FLASH_MAN_INTEL: printf ("INTEL "); break;
186 default: printf ("Unknown Vendor "); break;
187 }
188
189 /* check for top or bottom boot, if it applies */
190 if (info->flash_id & FLASH_BTYPE) {
191 boottype = botboottype;
192 bootletter = botbootletter;
193 }
194 else {
195 boottype = topboottype;
196 bootletter = topbootletter;
197 }
198
199 switch (info->flash_id & FLASH_TYPEMASK) {
200 case FLASH_AM640U:
201 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
202 break;
8bde7f77
WD
203 case FLASH_28F800C3B:
204 case FLASH_28F800C3T:
7aa78614
WD
205 fmt = "28F800C3%s (8 Mbit, %s)\n";
206 break;
207 case FLASH_INTEL800B:
208 case FLASH_INTEL800T:
209 fmt = "28F800B3%s (8 Mbit, %s)\n";
210 break;
8bde7f77
WD
211 case FLASH_28F160C3B:
212 case FLASH_28F160C3T:
7aa78614
WD
213 fmt = "28F160C3%s (16 Mbit, %s)\n";
214 break;
215 case FLASH_INTEL160B:
216 case FLASH_INTEL160T:
217 fmt = "28F160B3%s (16 Mbit, %s)\n";
218 break;
8bde7f77
WD
219 case FLASH_28F320C3B:
220 case FLASH_28F320C3T:
7aa78614
WD
221 fmt = "28F320C3%s (32 Mbit, %s)\n";
222 break;
223 case FLASH_INTEL320B:
224 case FLASH_INTEL320T:
225 fmt = "28F320B3%s (32 Mbit, %s)\n";
226 break;
8bde7f77
WD
227 case FLASH_28F640C3B:
228 case FLASH_28F640C3T:
7aa78614
WD
229 fmt = "28F640C3%s (64 Mbit, %s)\n";
230 break;
231 case FLASH_INTEL640B:
232 case FLASH_INTEL640T:
233 fmt = "28F640B3%s (64 Mbit, %s)\n";
234 break;
235 default:
236 fmt = "Unknown Chip Type\n";
237 break;
238 }
239
240 printf (fmt, bootletter, boottype);
241
242 printf (" Size: %ld MB in %d Sectors\n",
243 info->size >> 20,
244 info->sector_count);
245
246 printf (" Sector Start Addresses:");
247
248 for (i=0; i<info->sector_count; ++i) {
249 if ((i % 5) == 0) {
250 printf ("\n ");
251 }
252
253 printf (" %08lX%s", info->start[i],
254 info->protect[i] ? " (RO)" : " ");
255 }
256
257 printf ("\n");
258}
259
260/*-----------------------------------------------------------------------
261 */
262
263/*
264 * The following code cannot be run from FLASH!
265 */
266
267ulong flash_get_size (FPWV *addr, flash_info_t *info)
268{
269 /* Write auto select command: read Manufacturer ID */
270
271 /* Write auto select command sequence and test FLASH answer */
272 addr[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* for AMD, Intel ignores this */
273 addr[FLASH_CYCLE2] = (FPW)0x00550055; /* for AMD, Intel ignores this */
274 addr[FLASH_CYCLE1] = (FPW)0x00900090; /* selects Intel or AMD */
275
276 /* The manufacturer codes are only 1 byte, so just use 1 byte.
277 * This works for any bus width and any FLASH device width.
278 */
e6009629
WD
279 udelay(100);
280 switch (addr[0] & 0xff) {
7aa78614
WD
281
282 case (uchar)AMD_MANUFACT:
283 info->flash_id = FLASH_MAN_AMD;
284 break;
285
286 case (uchar)INTEL_MANUFACT:
287 info->flash_id = FLASH_MAN_INTEL;
288 break;
289
290 default:
291 info->flash_id = FLASH_UNKNOWN;
292 info->sector_count = 0;
293 info->size = 0;
294 break;
295 }
296
297 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
7aa78614
WD
298 if (info->flash_id != FLASH_UNKNOWN) switch (addr[1]) {
299
300 case (FPW)AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */
301 info->flash_id += FLASH_AM640U;
302 info->sector_count = 128;
303 info->size = 0x00800000 * (sizeof(FPW)/2);
304 break; /* => 8 or 16 MB */
305
306 case (FPW)INTEL_ID_28F800C3B:
307 info->flash_id += FLASH_28F800C3B;
308 info->sector_count = 23;
309 info->size = 0x00100000 * (sizeof(FPW)/2);
310 break; /* => 1 or 2 MB */
311
312 case (FPW)INTEL_ID_28F800B3B:
313 info->flash_id += FLASH_INTEL800B;
314 info->sector_count = 23;
315 info->size = 0x00100000 * (sizeof(FPW)/2);
316 break; /* => 1 or 2 MB */
317
318 case (FPW)INTEL_ID_28F160C3B:
319 info->flash_id += FLASH_28F160C3B;
320 info->sector_count = 39;
321 info->size = 0x00200000 * (sizeof(FPW)/2);
322 break; /* => 2 or 4 MB */
323
324 case (FPW)INTEL_ID_28F160B3B:
325 info->flash_id += FLASH_INTEL160B;
326 info->sector_count = 39;
327 info->size = 0x00200000 * (sizeof(FPW)/2);
328 break; /* => 2 or 4 MB */
329
330 case (FPW)INTEL_ID_28F320C3B:
331 info->flash_id += FLASH_28F320C3B;
332 info->sector_count = 71;
333 info->size = 0x00400000 * (sizeof(FPW)/2);
334 break; /* => 4 or 8 MB */
335
336 case (FPW)INTEL_ID_28F320B3B:
337 info->flash_id += FLASH_INTEL320B;
338 info->sector_count = 71;
339 info->size = 0x00400000 * (sizeof(FPW)/2);
340 break; /* => 4 or 8 MB */
341
342 case (FPW)INTEL_ID_28F640C3B:
343 info->flash_id += FLASH_28F640C3B;
344 info->sector_count = 135;
345 info->size = 0x00800000 * (sizeof(FPW)/2);
346 break; /* => 8 or 16 MB */
347
348 case (FPW)INTEL_ID_28F640B3B:
349 info->flash_id += FLASH_INTEL640B;
350 info->sector_count = 135;
351 info->size = 0x00800000 * (sizeof(FPW)/2);
352 break; /* => 8 or 16 MB */
353
354 default:
355 info->flash_id = FLASH_UNKNOWN;
356 info->sector_count = 0;
357 info->size = 0;
358 return (0); /* => no or unknown flash */
359 }
360
361 flash_get_offsets((ulong)addr, info);
362
363 /* Put FLASH back in read mode */
364 flash_reset(info);
365
366 return (info->size);
367}
368
369/*-----------------------------------------------------------------------
370 */
371
372int flash_erase (flash_info_t *info, int s_first, int s_last)
373{
374 FPWV *addr;
375 int flag, prot, sect;
376 int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
377 ulong start, now, last;
378 int rcode = 0;
379
380 if ((s_first < 0) || (s_first > s_last)) {
381 if (info->flash_id == FLASH_UNKNOWN) {
382 printf ("- missing\n");
383 } else {
384 printf ("- no sectors to erase\n");
385 }
386 return 1;
387 }
388
389 switch (info->flash_id & FLASH_TYPEMASK) {
390 case FLASH_INTEL800B:
391 case FLASH_INTEL160B:
392 case FLASH_INTEL320B:
393 case FLASH_INTEL640B:
394 case FLASH_28F800C3B:
395 case FLASH_28F160C3B:
396 case FLASH_28F320C3B:
397 case FLASH_28F640C3B:
398 case FLASH_AM640U:
399 break;
400 case FLASH_UNKNOWN:
401 default:
402 printf ("Can't erase unknown flash type %08lx - aborted\n",
403 info->flash_id);
404 return 1;
405 }
406
407 prot = 0;
408 for (sect=s_first; sect<=s_last; ++sect) {
409 if (info->protect[sect]) {
410 prot++;
411 }
412 }
413
414 if (prot) {
415 printf ("- Warning: %d protected sectors will not be erased!\n",
416 prot);
417 } else {
418 printf ("\n");
419 }
420
421 last = get_timer(0);
422
423 /* Start erase on unprotected sectors */
424 for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
425
426 if (info->protect[sect] != 0) /* protected, skip it */
427 continue;
428
429 /* Disable interrupts which might cause a timeout here */
430 flag = disable_interrupts();
431
432 addr = (FPWV *)(info->start[sect]);
433 if (intel) {
434 *addr = (FPW)0x00500050; /* clear status register */
435 *addr = (FPW)0x00200020; /* erase setup */
436 *addr = (FPW)0x00D000D0; /* erase confirm */
437 }
438 else {
439 /* must be AMD style if not Intel */
440 FPWV *base; /* first address in bank */
441
442 base = (FPWV *)(info->start[0]);
443 base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
444 base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
445 base[FLASH_CYCLE1] = (FPW)0x00800080; /* erase mode */
446 base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
447 base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
448 *addr = (FPW)0x00300030; /* erase sector */
449 }
450
451 /* re-enable interrupts if necessary */
452 if (flag)
453 enable_interrupts();
454
455 start = get_timer(0);
456
457 /* wait at least 50us for AMD, 80us for Intel.
458 * Let's wait 1 ms.
459 */
460 udelay (1000);
461
462 while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
6d0f6bcf 463 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
7aa78614
WD
464 printf ("Timeout\n");
465
466 if (intel) {
467 /* suspend erase */
468 *addr = (FPW)0x00B000B0;
469 }
470
471 flash_reset(info); /* reset to read mode */
472 rcode = 1; /* failed */
473 break;
474 }
475
476 /* show that we're waiting */
6d0f6bcf 477 if ((get_timer(last)) > CONFIG_SYS_HZ) {/* every second */
7aa78614
WD
478 putc ('.');
479 last = get_timer(0);
480 }
481 }
482
483 /* show that we're waiting */
6d0f6bcf 484 if ((get_timer(last)) > CONFIG_SYS_HZ) { /* every second */
7aa78614
WD
485 putc ('.');
486 last = get_timer(0);
487 }
488
489 flash_reset(info); /* reset to read mode */
490 }
491
492 printf (" done\n");
493 return rcode;
494}
495
496/*-----------------------------------------------------------------------
497 * Copy memory to flash, returns:
498 * 0 - OK
499 * 1 - write timeout
500 * 2 - Flash not erased
501 */
502int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
503{
e6009629
WD
504 FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
505 int bytes; /* number of bytes to program in current word */
506 int left; /* number of bytes left to program */
507 int i, res;
7aa78614 508
e6009629
WD
509 for (left = cnt, res = 0;
510 left > 0 && res == 0;
511 addr += sizeof(data), left -= sizeof(data) - bytes) {
7aa78614 512
e6009629
WD
513 bytes = addr & (sizeof(data) - 1);
514 addr &= ~(sizeof(data) - 1);
7aa78614 515
e6009629
WD
516 /* combine source and destination data so can program
517 * an entire word of 16 or 32 bits
518 */
519 for (i = 0; i < sizeof(data); i++) {
520 data <<= 8;
521 if (i < bytes || i - bytes >= left )
522 data += *((uchar *)addr + i);
523 else
524 data += *src++;
525 }
7aa78614 526
e6009629
WD
527 /* write one word to the flash */
528 switch (info->flash_id & FLASH_VENDMASK) {
529 case FLASH_MAN_AMD:
530 res = write_word_amd(info, (FPWV *)addr, data);
531 break;
532 case FLASH_MAN_INTEL:
533 res = write_word_intel(info, (FPWV *)addr, data);
534 break;
535 default:
536 /* unknown flash type, error! */
537 printf ("missing or unknown FLASH type\n");
538 res = 1; /* not really a timeout, but gives error */
539 break;
540 }
7aa78614 541 }
7aa78614 542
e6009629 543 return (res);
7aa78614
WD
544}
545
546/*-----------------------------------------------------------------------
547 * Write a word to Flash for AMD FLASH
548 * A word is 16 or 32 bits, whichever the bus width of the flash bank
549 * (not an individual chip) is.
550 *
551 * returns:
552 * 0 - OK
553 * 1 - write timeout
554 * 2 - Flash not erased
555 */
556static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
557{
e6009629
WD
558 ulong start;
559 int flag;
560 int res = 0; /* result, assume success */
561 FPWV *base; /* first address in flash bank */
562
563 /* Check if Flash is (sufficiently) erased */
564 if ((*dest & data) != data) {
565 return (2);
566 }
7aa78614
WD
567
568
e6009629 569 base = (FPWV *)(info->start[0]);
7aa78614 570
e6009629
WD
571 /* Disable interrupts which might cause a timeout here */
572 flag = disable_interrupts();
7aa78614 573
e6009629
WD
574 base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */
575 base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */
576 base[FLASH_CYCLE1] = (FPW)0x00A000A0; /* selects program mode */
7aa78614 577
e6009629 578 *dest = data; /* start programming the data */
7aa78614 579
e6009629
WD
580 /* re-enable interrupts if necessary */
581 if (flag)
582 enable_interrupts();
7aa78614 583
e6009629 584 start = get_timer (0);
7aa78614 585
e6009629
WD
586 /* data polling for D7 */
587 while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
6d0f6bcf 588 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
e6009629
WD
589 *dest = (FPW)0x00F000F0; /* reset bank */
590 res = 1;
591 }
7aa78614 592 }
7aa78614 593
e6009629 594 return (res);
7aa78614
WD
595}
596
597/*-----------------------------------------------------------------------
598 * Write a word to Flash for Intel FLASH
599 * A word is 16 or 32 bits, whichever the bus width of the flash bank
600 * (not an individual chip) is.
601 *
602 * returns:
603 * 0 - OK
604 * 1 - write timeout
605 * 2 - Flash not erased
606 */
607static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data)
608{
e6009629
WD
609 ulong start;
610 int flag;
611 int res = 0; /* result, assume success */
7aa78614 612
e6009629
WD
613 /* Check if Flash is (sufficiently) erased */
614 if ((*dest & data) != data) {
615 return (2);
616 }
7aa78614 617
e6009629
WD
618 /* Disable interrupts which might cause a timeout here */
619 flag = disable_interrupts();
7aa78614 620
e6009629
WD
621 *dest = (FPW)0x00500050; /* clear status register */
622 *dest = (FPW)0x00FF00FF; /* make sure in read mode */
623 *dest = (FPW)0x00400040; /* program setup */
7aa78614 624
e6009629 625 *dest = data; /* start programming the data */
7aa78614 626
e6009629
WD
627 /* re-enable interrupts if necessary */
628 if (flag)
629 enable_interrupts();
7aa78614 630
e6009629 631 start = get_timer (0);
7aa78614 632
e6009629 633 while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
6d0f6bcf 634 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
e6009629
WD
635 *dest = (FPW)0x00B000B0; /* Suspend program */
636 res = 1;
637 }
7aa78614 638 }
7aa78614 639
e6009629
WD
640 if (res == 0 && (*dest & (FPW)0x00100010))
641 res = 1; /* write failed, time out error is close enough */
7aa78614 642
e6009629
WD
643 *dest = (FPW)0x00500050; /* clear status register */
644 *dest = (FPW)0x00FF00FF; /* make sure in read mode */
7aa78614 645
e6009629 646 return (res);
7aa78614 647}