blob: b99a9a089b957a49c69a12ec0975f1e2f4b41fb2 [file] [log] [blame]
wdenkcc1c8a12002-11-02 22:58:18 +00001/*
2 * (C) Copyright 2001, 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * Flash Routines for Intel devices
6 *
7 *--------------------------------------------------------------------
Wolfgang Denk3765b3e2013-10-07 13:07:26 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenkcc1c8a12002-11-02 22:58:18 +00009 */
10
11#include <common.h>
12#include <mpc8xx.h>
13#include "cpu86.h"
14
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020015flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
wdenkcc1c8a12002-11-02 22:58:18 +000016
17/*-----------------------------------------------------------------------
18 */
19ulong flash_int_get_size (volatile unsigned long *baseaddr,
20 flash_info_t * info)
21{
22 short i;
23 unsigned long flashtest_h, flashtest_l;
24
25 info->sector_count = info->size = 0;
26 info->flash_id = FLASH_UNKNOWN;
27
wdenkefa329c2004-03-23 20:18:25 +000028 /* Write identify command sequence and test FLASH answer
wdenkcc1c8a12002-11-02 22:58:18 +000029 */
wdenkefa329c2004-03-23 20:18:25 +000030 baseaddr[0] = 0x00900090;
31 baseaddr[1] = 0x00900090;
wdenkcc1c8a12002-11-02 22:58:18 +000032
33 flashtest_h = baseaddr[0]; /* manufacturer ID */
34 flashtest_l = baseaddr[1];
35
36 if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
37 return (0); /* no or unknown flash */
38
39 flashtest_h = baseaddr[2]; /* device ID */
40 flashtest_l = baseaddr[3];
41
42 if (flashtest_h != flashtest_l)
43 return (0);
44
45 switch (flashtest_h) {
46 case INTEL_ID_28F160C3B:
47 info->flash_id = FLASH_28F160C3B;
48 info->sector_count = 39;
49 info->size = 0x00800000; /* 4 * 2 MB = 8 MB */
50 break;
51 case INTEL_ID_28F160F3B:
52 info->flash_id = FLASH_28F160F3B;
53 info->sector_count = 39;
54 info->size = 0x00800000; /* 4 * 2 MB = 8 MB */
55 break;
56 default:
57 return (0); /* no or unknown flash */
58 }
59
60 info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
61
62 if (info->flash_id & FLASH_BTYPE) {
63 volatile unsigned long *tmp = baseaddr;
64
65 /* set up sector start adress table (bottom sector type)
66 * AND unlock the sectors (if our chip is 160C3)
67 */
68 for (i = 0; i < info->sector_count; i++) {
69 if ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) {
70 tmp[0] = 0x00600060;
71 tmp[1] = 0x00600060;
72 tmp[0] = 0x00D000D0;
73 tmp[1] = 0x00D000D0;
74 }
75 info->start[i] = (uint) tmp;
76 tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith */
77 }
78 }
79
80 memset (info->protect, 0, info->sector_count);
81
82 baseaddr[0] = 0x00FF00FF;
83 baseaddr[1] = 0x00FF00FF;
84
85 return (info->size);
86}
87
88static ulong flash_amd_get_size (vu_char *addr, flash_info_t *info)
89{
90 short i;
91 uchar vendor, devid;
92 ulong base = (ulong)addr;
93
94 /* Write auto select command: read Manufacturer ID */
95 addr[0x0555] = 0xAA;
96 addr[0x02AA] = 0x55;
97 addr[0x0555] = 0x90;
98
99 udelay(1000);
100
101 vendor = addr[0];
102 devid = addr[1] & 0xff;
103
104 /* only support AMD */
105 if (vendor != 0x01) {
106 return 0;
107 }
108
109 vendor &= 0xf;
110 devid &= 0xff;
111
112 if (devid == AMD_ID_F040B) {
113 info->flash_id = vendor << 16 | devid;
114 info->sector_count = 8;
115 info->size = info->sector_count * 0x10000;
116 }
117 else if (devid == AMD_ID_F080B) {
118 info->flash_id = vendor << 16 | devid;
119 info->sector_count = 16;
120 info->size = 4 * info->sector_count * 0x10000;
121 }
122 else if (devid == AMD_ID_F016D) {
123 info->flash_id = vendor << 16 | devid;
124 info->sector_count = 32;
125 info->size = 4 * info->sector_count * 0x10000;
126 }
127 else {
128 printf ("## Unknown Flash Type: %02x\n", devid);
129 return 0;
130 }
131
132 /* check for protected sectors */
133 for (i = 0; i < info->sector_count; i++) {
134 /* sector base address */
135 info->start[i] = base + i * (info->size / info->sector_count);
136 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
137 /* D0 = 1 if protected */
138 addr = (volatile unsigned char *)(info->start[i]);
139 info->protect[i] = addr[2] & 1;
140 }
141
142 /*
143 * Prevent writes to uninitialized FLASH.
144 */
145 if (info->flash_id != FLASH_UNKNOWN) {
146 addr = (vu_char *)info->start[0];
147 addr[0] = 0xF0; /* reset bank */
148 }
149
150 return (info->size);
151}
152
153
154/*-----------------------------------------------------------------------
155 */
156unsigned long flash_init (void)
157{
158 unsigned long size_b0 = 0;
159 unsigned long size_b1 = 0;
160 int i;
161
162 /* Init: no FLASHes known
163 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200164 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
wdenkcc1c8a12002-11-02 22:58:18 +0000165 flash_info[i].flash_id = FLASH_UNKNOWN;
166 }
167
168 /* Disable flash protection */
169 CPU86_BCR |= (CPU86_BCR_FWPT | CPU86_BCR_FWRE);
170
171 /* Static FLASH Bank configuration here (only one bank) */
172
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200173 size_b0 = flash_int_get_size ((ulong *) CONFIG_SYS_FLASH_BASE, &flash_info[0]);
174 size_b1 = flash_amd_get_size ((uchar *) CONFIG_SYS_BOOTROM_BASE, &flash_info[1]);
wdenkcc1c8a12002-11-02 22:58:18 +0000175
176 if (size_b0 > 0 || size_b1 > 0) {
177
178 printf("(");
179
180 if (size_b0 > 0) {
181 puts ("Bank#1 - ");
182 print_size (size_b0, (size_b1 > 0) ? ", " : ") ");
183 }
184
185 if (size_b1 > 0) {
186 puts ("Bank#2 - ");
187 print_size (size_b1, ") ");
188 }
189 }
190 else {
191 printf ("## No FLASH found.\n");
192 return 0;
193 }
194 /* protect monitor and environment sectors
195 */
196
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200197#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_BOOTROM_BASE
wdenkcc1c8a12002-11-02 22:58:18 +0000198 if (size_b1) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200199 /* If U-Boot is booted from ROM the CONFIG_SYS_MONITOR_BASE > CONFIG_SYS_FLASH_BASE
wdenkcc1c8a12002-11-02 22:58:18 +0000200 * but we shouldn't protect it.
201 */
202
203 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200204 CONFIG_SYS_MONITOR_BASE,
205 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[1]
wdenkcc1c8a12002-11-02 22:58:18 +0000206 );
207 }
208#else
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200209#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
wdenkcc1c8a12002-11-02 22:58:18 +0000210 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200211 CONFIG_SYS_MONITOR_BASE,
212 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]
wdenkcc1c8a12002-11-02 22:58:18 +0000213 );
214#endif
215#endif
216
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200217#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
218# ifndef CONFIG_ENV_SIZE
219# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
wdenkcc1c8a12002-11-02 22:58:18 +0000220# endif
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200221# if CONFIG_ENV_ADDR >= CONFIG_SYS_BOOTROM_BASE
wdenkcc1c8a12002-11-02 22:58:18 +0000222 if (size_b1) {
223 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200224 CONFIG_ENV_ADDR,
225 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[1]);
wdenkcc1c8a12002-11-02 22:58:18 +0000226 }
227# else
228 flash_protect (FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200229 CONFIG_ENV_ADDR,
230 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
wdenkcc1c8a12002-11-02 22:58:18 +0000231# endif
232#endif
233
234 return (size_b0 + size_b1);
235}
236
237/*-----------------------------------------------------------------------
238 */
239void flash_print_info (flash_info_t * info)
240{
241 int i;
242
243 if (info->flash_id == FLASH_UNKNOWN) {
244 printf ("missing or unknown FLASH type\n");
245 return;
246 }
247
248 switch ((info->flash_id >> 16) & 0xff) {
249 case 0x89:
250 printf ("INTEL ");
251 break;
252 case 0x1:
253 printf ("AMD ");
254 break;
255 default:
256 printf ("Unknown Vendor ");
257 break;
258 }
259
260 switch (info->flash_id & FLASH_TYPEMASK) {
261 case FLASH_28F160C3B:
262 printf ("28F160C3B (16 Mbit, bottom sector)\n");
263 break;
264 case FLASH_28F160F3B:
265 printf ("28F160F3B (16 Mbit, bottom sector)\n");
266 break;
267 case AMD_ID_F040B:
268 printf ("AM29F040B (4 Mbit)\n");
269 break;
270 default:
271 printf ("Unknown Chip Type\n");
272 break;
273 }
274
275 if (info->size < 0x100000)
276 printf (" Size: %ld KB in %d Sectors\n",
277 info->size >> 10, info->sector_count);
278 else
279 printf (" Size: %ld MB in %d Sectors\n",
280 info->size >> 20, info->sector_count);
281
282 printf (" Sector Start Addresses:");
283 for (i = 0; i < info->sector_count; ++i) {
284 if ((i % 5) == 0)
285 printf ("\n ");
286 printf (" %08lX%s",
287 info->start[i],
288 info->protect[i] ? " (RO)" : " "
289 );
290 }
291 printf ("\n");
292}
293
294/*-----------------------------------------------------------------------
295 */
296int flash_erase (flash_info_t * info, int s_first, int s_last)
297{
298 vu_char *addr = (vu_char *)(info->start[0]);
299 int flag, prot, sect, l_sect;
300 ulong start, now, last;
301
302 if ((s_first < 0) || (s_first > s_last)) {
303 if (info->flash_id == FLASH_UNKNOWN) {
304 printf ("- missing\n");
305 } else {
306 printf ("- no sectors to erase\n");
307 }
308 return 1;
309 }
310
311 prot = 0;
312 for (sect = s_first; sect <= s_last; sect++) {
313 if (info->protect[sect])
314 prot++;
315 }
316
317 if (prot) {
318 printf ("- Warning: %d protected sectors will not be erased!\n",
319 prot);
320 } else {
321 printf ("\n");
322 }
323
324 /* Check the type of erased flash
325 */
326 if (info->flash_id >> 16 == 0x1) {
327 /* Erase AMD flash
328 */
329 l_sect = -1;
330
331 /* Disable interrupts which might cause a timeout here */
332 flag = disable_interrupts();
333
334 addr[0x0555] = 0xAA;
335 addr[0x02AA] = 0x55;
336 addr[0x0555] = 0x80;
337 addr[0x0555] = 0xAA;
338 addr[0x02AA] = 0x55;
339
340 /* wait at least 80us - let's wait 1 ms */
341 udelay (1000);
342
343 /* Start erase on unprotected sectors */
344 for (sect = s_first; sect<=s_last; sect++) {
345 if (info->protect[sect] == 0) { /* not protected */
346 addr = (vu_char *)(info->start[sect]);
347 addr[0] = 0x30;
348 l_sect = sect;
349 }
350 }
351
352 /* re-enable interrupts if necessary */
353 if (flag)
354 enable_interrupts();
355
356 /* wait at least 80us - let's wait 1 ms */
357 udelay (1000);
358
359 /*
360 * We wait for the last triggered sector
361 */
362 if (l_sect < 0)
363 goto AMD_DONE;
364
365 start = get_timer (0);
366 last = start;
367 addr = (vu_char *)(info->start[l_sect]);
368 while ((addr[0] & 0x80) != 0x80) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200369 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkcc1c8a12002-11-02 22:58:18 +0000370 printf ("Timeout\n");
371 return 1;
372 }
373 /* show that we're waiting */
374 if ((now - last) > 1000) { /* every second */
375 serial_putc ('.');
376 last = now;
377 }
378 }
379
380AMD_DONE:
381 /* reset to read mode */
382 addr = (volatile unsigned char *)info->start[0];
383 addr[0] = 0xF0; /* reset bank */
384
385 } else {
386 /* Erase Intel flash
387 */
388
389 /* Start erase on unprotected sectors
390 */
391 for (sect = s_first; sect <= s_last; sect++) {
392 volatile ulong *addr =
393 (volatile unsigned long *) info->start[sect];
394
395 start = get_timer (0);
396 last = start;
397 if (info->protect[sect] == 0) {
398 /* Disable interrupts which might cause a timeout here
399 */
400 flag = disable_interrupts ();
401
402 /* Erase the block
403 */
404 addr[0] = 0x00200020;
405 addr[1] = 0x00200020;
406 addr[0] = 0x00D000D0;
407 addr[1] = 0x00D000D0;
408
409 /* re-enable interrupts if necessary
410 */
411 if (flag)
412 enable_interrupts ();
413
414 /* wait at least 80us - let's wait 1 ms
415 */
416 udelay (1000);
417
418 last = start;
419 while ((addr[0] & 0x00800080) != 0x00800080 ||
420 (addr[1] & 0x00800080) != 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200421 if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkcc1c8a12002-11-02 22:58:18 +0000422 printf ("Timeout (erase suspended!)\n");
423 /* Suspend erase
424 */
425 addr[0] = 0x00B000B0;
426 addr[1] = 0x00B000B0;
427 goto DONE;
428 }
429 /* show that we're waiting
430 */
431 if ((now - last) > 1000) { /* every second */
432 serial_putc ('.');
433 last = now;
434 }
435 }
436 if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
437 printf ("*** ERROR: erase failed!\n");
438 goto DONE;
439 }
440 }
441 /* Clear status register and reset to read mode
442 */
443 addr[0] = 0x00500050;
444 addr[1] = 0x00500050;
445 addr[0] = 0x00FF00FF;
446 addr[1] = 0x00FF00FF;
447 }
448 }
449
450 printf (" done\n");
451
452DONE:
453 return 0;
454}
455
456static int write_word (flash_info_t *, volatile unsigned long *, ulong);
457static int write_byte (flash_info_t *info, ulong dest, uchar data);
458
459/*-----------------------------------------------------------------------
460 * Copy memory to flash, returns:
461 * 0 - OK
462 * 1 - write timeout
463 * 2 - Flash not erased
464 */
465int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
466{
467 ulong v;
468 int i, l, rc, cc = cnt, res = 0;
469
470 if (info->flash_id >> 16 == 0x1) {
471
472 /* Write to AMD 8-bit flash
473 */
474 while (cnt > 0) {
475 if ((rc = write_byte(info, addr, *src)) != 0) {
476 return (rc);
477 }
478 addr++;
479 src++;
480 cnt--;
481 }
482
483 return (0);
484 } else {
485
486 /* Write to Intel 64-bit flash
487 */
488 for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
489 l = (addr & 3);
490 addr &= ~3;
491
492 for (i = 0; i < 4; i++) {
493 v = (v << 8) + (i < l || i - l >= cc ?
494 *((unsigned char *) addr + i) : *src++);
495 }
496
497 if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
498 break;
499 }
500 }
501
502 return (res);
503}
504
505/*-----------------------------------------------------------------------
506 * Write a word to Flash, returns:
507 * 0 - OK
508 * 1 - write timeout
509 * 2 - Flash not erased
510 */
511static int write_word (flash_info_t * info, volatile unsigned long *addr,
512 ulong data)
513{
514 int flag, res = 0;
515 ulong start;
516
517 /* Check if Flash is (sufficiently) erased
518 */
519 if ((*addr & data) != data)
520 return (2);
521
522 /* Disable interrupts which might cause a timeout here
523 */
524 flag = disable_interrupts ();
525
526 *addr = 0x00400040;
527 *addr = data;
528
529 /* re-enable interrupts if necessary
530 */
531 if (flag)
532 enable_interrupts ();
533
534 start = get_timer (0);
535 while ((*addr & 0x00800080) != 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200536 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkcc1c8a12002-11-02 22:58:18 +0000537 /* Suspend program
538 */
539 *addr = 0x00B000B0;
540 res = 1;
541 goto OUT;
542 }
543 }
544
545 if (*addr & 0x00220022) {
546 printf ("*** ERROR: program failed!\n");
547 res = 1;
548 }
549
550OUT:
551 /* Clear status register and reset to read mode
552 */
553 *addr = 0x00500050;
554 *addr = 0x00FF00FF;
555
556 return (res);
557}
558
559/*-----------------------------------------------------------------------
560 * Write a byte to Flash, returns:
561 * 0 - OK
562 * 1 - write timeout
563 * 2 - Flash not erased
564 */
565static int write_byte (flash_info_t *info, ulong dest, uchar data)
566{
567 vu_char *addr = (vu_char *)(info->start[0]);
568 ulong start;
569 int flag;
570
571 /* Check if Flash is (sufficiently) erased */
572 if ((*((vu_char *)dest) & data) != data) {
573 return (2);
574 }
575 /* Disable interrupts which might cause a timeout here */
576 flag = disable_interrupts();
577
578 addr[0x0555] = 0xAA;
579 addr[0x02AA] = 0x55;
580 addr[0x0555] = 0xA0;
581
582 *((vu_char *)dest) = data;
583
584 /* re-enable interrupts if necessary */
585 if (flag)
586 enable_interrupts();
587
588 /* data polling for D7 */
589 start = get_timer (0);
590 while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200591 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkcc1c8a12002-11-02 22:58:18 +0000592 return (1);
593 }
594 }
595 return (0);
596}
597
598/*-----------------------------------------------------------------------
599 */