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