]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/logodl/flash.c
* Header file cleanup for ARM
[people/ms/u-boot.git] / board / logodl / flash.c
CommitLineData
52f52c14
WD
1/*
2 * (C) 2000 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
3 * (C) 2003 August Hoeraendl, Logotronic GmbH
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#undef CONFIG_FLASH_16BIT
25
26#include <common.h>
27
28#define FLASH_BANK_SIZE 0x1000000
29#define MAIN_SECT_SIZE 0x20000 /* 2x64k = 128k per sector */
30
31flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
32
33/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
34 * has nothing to do with the flash chip being 8-bit or 16-bit.
35 */
36#ifdef CONFIG_FLASH_16BIT
37typedef unsigned short FLASH_PORT_WIDTH;
38typedef volatile unsigned short FLASH_PORT_WIDTHV;
39
40#define FLASH_ID_MASK 0xFFFF
41#else
42typedef unsigned long FLASH_PORT_WIDTH;
43typedef volatile unsigned long FLASH_PORT_WIDTHV;
44
45#define FLASH_ID_MASK 0xFFFFFFFF
46#endif
47
48#define FPW FLASH_PORT_WIDTH
49#define FPWV FLASH_PORT_WIDTHV
50
51#define ORMASK(size) ((-size) & OR_AM_MSK)
52
53/*-----------------------------------------------------------------------
54 * Functions
55 */
56static ulong flash_get_size (FPWV * addr, flash_info_t * info);
57static void flash_reset (flash_info_t * info);
58static int write_word_intel (flash_info_t * info, FPWV * dest, FPW data);
59static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data);
60
61#define write_word(in, de, da) write_word_amd(in, de, da)
62static void flash_get_offsets (ulong base, flash_info_t * info);
63
64#ifdef CFG_FLASH_PROTECTION
65static void flash_sync_real_protect (flash_info_t * info);
66#endif
67
68/*-----------------------------------------------------------------------
69 * flash_init()
70 *
71 * sets up flash_info and returns size of FLASH (bytes)
72 */
73ulong flash_init (void)
74{
75 int i, j;
76 ulong size = 0;
77
78 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
79 ulong flashbase = 0;
80
81 flash_info[i].flash_id =
82 (FLASH_MAN_AMD & FLASH_VENDMASK) |
83 (FLASH_AM640U & FLASH_TYPEMASK);
84 flash_info[i].size = FLASH_BANK_SIZE;
85 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
86 memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
87 switch (i) {
88 case 0:
89 flashbase = PHYS_FLASH_1;
90 break;
91 case 1:
92 flashbase = PHYS_FLASH_2;
93 break;
94 default:
95 panic ("configured to many flash banks!\n");
96 break;
97 }
98 for (j = 0; j < flash_info[i].sector_count; j++) {
99 flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
100 }
101 size += flash_info[i].size;
102 }
103
104 /* Protect monitor and environment sectors
105 */
106 flash_protect (FLAG_PROTECT_SET,
107 CFG_FLASH_BASE,
108 CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
109 &flash_info[0]);
110
111 flash_protect (FLAG_PROTECT_SET,
112 CFG_ENV_ADDR,
113 CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
114
115 return size;
116}
117
118/*-----------------------------------------------------------------------
119 */
120static void flash_reset (flash_info_t * info)
121{
122 FPWV *base = (FPWV *) (info->start[0]);
123
124 /* Put FLASH back in read mode */
125 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
126 *base = (FPW) 0x00FF00FF; /* Intel Read Mode */
127 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
128 *base = (FPW) 0x00F000F0; /* AMD Read Mode */
129}
130
131/*-----------------------------------------------------------------------
132 */
133static void flash_get_offsets (ulong base, flash_info_t * info)
134{
135 int i;
136
137 /* set up sector start address table */
138 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
139 && (info->flash_id & FLASH_BTYPE)) {
140 int bootsect_size; /* number of bytes/boot sector */
141 int sect_size; /* number of bytes/regular sector */
142
143 bootsect_size = 0x00002000 * (sizeof (FPW) / 2);
144 sect_size = 0x00010000 * (sizeof (FPW) / 2);
145
146 /* set sector offsets for bottom boot block type */
147 for (i = 0; i < 8; ++i) {
148 info->start[i] = base + (i * bootsect_size);
149 }
150 for (i = 8; i < info->sector_count; i++) {
151 info->start[i] = base + ((i - 7) * sect_size);
152 }
153 } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
154 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
155
156 int sect_size; /* number of bytes/sector */
157
158 sect_size = 0x00010000 * (sizeof (FPW) / 2);
159
160 /* set up sector start address table (uniform sector type) */
161 for (i = 0; i < info->sector_count; i++)
162 info->start[i] = base + (i * sect_size);
163 }
164}
165
166/*-----------------------------------------------------------------------
167 */
168
169void flash_print_info (flash_info_t * info)
170{
171 int i;
172 uchar *boottype;
173 uchar *bootletter;
174 uchar *fmt;
175 uchar botbootletter[] = "B";
176 uchar topbootletter[] = "T";
177 uchar botboottype[] = "bottom boot sector";
178 uchar topboottype[] = "top boot sector";
179
180 if (info->flash_id == FLASH_UNKNOWN) {
181 printf ("missing or unknown FLASH type\n");
182 return;
183 }
184
185 switch (info->flash_id & FLASH_VENDMASK) {
186 case FLASH_MAN_AMD:
187 printf ("AMD ");
188 break;
189 case FLASH_MAN_BM:
190 printf ("BRIGHT MICRO ");
191 break;
192 case FLASH_MAN_FUJ:
193 printf ("FUJITSU ");
194 break;
195 case FLASH_MAN_SST:
196 printf ("SST ");
197 break;
198 case FLASH_MAN_STM:
199 printf ("STM ");
200 break;
201 case FLASH_MAN_INTEL:
202 printf ("INTEL ");
203 break;
204 default:
205 printf ("Unknown Vendor ");
206 break;
207 }
208
209 /* check for top or bottom boot, if it applies */
210 if (info->flash_id & FLASH_BTYPE) {
211 boottype = botboottype;
212 bootletter = botbootletter;
213 } else {
214 boottype = topboottype;
215 bootletter = topbootletter;
216 }
217
218 switch (info->flash_id & FLASH_TYPEMASK) {
219 case FLASH_AM640U:
220 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
221 break;
222 case FLASH_28F800C3B:
223 case FLASH_28F800C3T:
224 fmt = "28F800C3%s (8 Mbit, %s)\n";
225 break;
226 case FLASH_INTEL800B:
227 case FLASH_INTEL800T:
228 fmt = "28F800B3%s (8 Mbit, %s)\n";
229 break;
230 case FLASH_28F160C3B:
231 case FLASH_28F160C3T:
232 fmt = "28F160C3%s (16 Mbit, %s)\n";
233 break;
234 case FLASH_INTEL160B:
235 case FLASH_INTEL160T:
236 fmt = "28F160B3%s (16 Mbit, %s)\n";
237 break;
238 case FLASH_28F320C3B:
239 case FLASH_28F320C3T:
240 fmt = "28F320C3%s (32 Mbit, %s)\n";
241 break;
242 case FLASH_INTEL320B:
243 case FLASH_INTEL320T:
244 fmt = "28F320B3%s (32 Mbit, %s)\n";
245 break;
246 case FLASH_28F640C3B:
247 case FLASH_28F640C3T:
248 fmt = "28F640C3%s (64 Mbit, %s)\n";
249 break;
250 case FLASH_INTEL640B:
251 case FLASH_INTEL640T:
252 fmt = "28F640B3%s (64 Mbit, %s)\n";
253 break;
254 default:
255 fmt = "Unknown Chip Type\n";
256 break;
257 }
258
259 printf (fmt, bootletter, boottype);
260
261 printf (" Size: %ld MB in %d Sectors\n",
262 info->size >> 20, info->sector_count);
263
264 printf (" Sector Start Addresses:");
265
266 for (i = 0; i < info->sector_count; ++i) {
267 if ((i % 5) == 0) {
268 printf ("\n ");
269 }
270
271 printf (" %08lX%s", info->start[i],
272 info->protect[i] ? " (RO)" : " ");
273 }
274
275 printf ("\n");
276}
277
278/*-----------------------------------------------------------------------
279 */
280
281/*
282 * The following code cannot be run from FLASH!
283 */
284
285ulong flash_get_size (FPWV * addr, flash_info_t * info)
286{
287 /* Write auto select command: read Manufacturer ID */
288
289 /* Write auto select command sequence and test FLASH answer */
290 addr[0x0555] = (FPW) 0x00AA00AA; /* for AMD, Intel ignores this */
291 addr[0x02AA] = (FPW) 0x00550055; /* for AMD, Intel ignores this */
292 addr[0x0555] = (FPW) 0x00900090; /* selects Intel or AMD */
293
294 /* The manufacturer codes are only 1 byte, so just use 1 byte.
295 * This works for any bus width and any FLASH device width.
296 */
297 switch (addr[0] & 0xff) {
298
299 case (uchar) AMD_MANUFACT:
300 info->flash_id = FLASH_MAN_AMD;
301 break;
302
303 case (uchar) INTEL_MANUFACT:
304 info->flash_id = FLASH_MAN_INTEL;
305 break;
306
307 default:
308 info->flash_id = FLASH_UNKNOWN;
309 info->sector_count = 0;
310 info->size = 0;
311 break;
312 }
313
314 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
315 if (info->flash_id != FLASH_UNKNOWN)
316 switch (addr[1]) {
317
318 case (FPW) AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */
319 info->flash_id += FLASH_AM640U;
320 info->sector_count = 128;
321 info->size = 0x00800000 * (sizeof (FPW) / 2);
322 break; /* => 8 or 16 MB */
323
324 case (FPW) INTEL_ID_28F800C3B:
325 info->flash_id += FLASH_28F800C3B;
326 info->sector_count = 23;
327 info->size = 0x00100000 * (sizeof (FPW) / 2);
328 break; /* => 1 or 2 MB */
329
330 case (FPW) INTEL_ID_28F800B3B:
331 info->flash_id += FLASH_INTEL800B;
332 info->sector_count = 23;
333 info->size = 0x00100000 * (sizeof (FPW) / 2);
334 break; /* => 1 or 2 MB */
335
336 case (FPW) INTEL_ID_28F160C3B:
337 info->flash_id += FLASH_28F160C3B;
338 info->sector_count = 39;
339 info->size = 0x00200000 * (sizeof (FPW) / 2);
340 break; /* => 2 or 4 MB */
341
342 case (FPW) INTEL_ID_28F160B3B:
343 info->flash_id += FLASH_INTEL160B;
344 info->sector_count = 39;
345 info->size = 0x00200000 * (sizeof (FPW) / 2);
346 break; /* => 2 or 4 MB */
347
348 case (FPW) INTEL_ID_28F320C3B:
349 info->flash_id += FLASH_28F320C3B;
350 info->sector_count = 71;
351 info->size = 0x00400000 * (sizeof (FPW) / 2);
352 break; /* => 4 or 8 MB */
353
354 case (FPW) INTEL_ID_28F320B3B:
355 info->flash_id += FLASH_INTEL320B;
356 info->sector_count = 71;
357 info->size = 0x00400000 * (sizeof (FPW) / 2);
358 break; /* => 4 or 8 MB */
359
360 case (FPW) INTEL_ID_28F640C3B:
361 info->flash_id += FLASH_28F640C3B;
362 info->sector_count = 135;
363 info->size = 0x00800000 * (sizeof (FPW) / 2);
364 break; /* => 8 or 16 MB */
365
366 case (FPW) INTEL_ID_28F640B3B:
367 info->flash_id += FLASH_INTEL640B;
368 info->sector_count = 135;
369 info->size = 0x00800000 * (sizeof (FPW) / 2);
370 break; /* => 8 or 16 MB */
371
372 default:
373 info->flash_id = FLASH_UNKNOWN;
374 info->sector_count = 0;
375 info->size = 0;
376 return (0); /* => no or unknown flash */
377 }
378
379 flash_get_offsets ((ulong) addr, info);
380
381 /* Put FLASH back in read mode */
382 flash_reset (info);
383
384 return (info->size);
385}
386
387#ifdef CFG_FLASH_PROTECTION
388/*-----------------------------------------------------------------------
389 */
390
391static void flash_sync_real_protect (flash_info_t * info)
392{
393 FPWV *addr = (FPWV *) (info->start[0]);
394 FPWV *sect;
395 int i;
396
397 switch (info->flash_id & FLASH_TYPEMASK) {
398 case FLASH_28F800C3B:
399 case FLASH_28F800C3T:
400 case FLASH_28F160C3B:
401 case FLASH_28F160C3T:
402 case FLASH_28F320C3B:
403 case FLASH_28F320C3T:
404 case FLASH_28F640C3B:
405 case FLASH_28F640C3T:
406 /* check for protected sectors */
407 *addr = (FPW) 0x00900090;
408 for (i = 0; i < info->sector_count; i++) {
409 /* read sector protection at sector address, (A7 .. A0) = 0x02.
410 * D0 = 1 for each device if protected.
411 * If at least one device is protected the sector is marked
412 * protected, but mixed protected and unprotected devices
413 * within a sector should never happen.
414 */
415 sect = (FPWV *) (info->start[i]);
416 info->protect[i] = (sect[2] & (FPW) (0x00010001)) ? 1 : 0;
417 }
418
419 /* Put FLASH back in read mode */
420 flash_reset (info);
421 break;
422
423 case FLASH_AM640U:
424 default:
425 /* no hardware protect that we support */
426 break;
427 }
428}
429#endif
430
431/*-----------------------------------------------------------------------
432 */
433
434int flash_erase (flash_info_t * info, int s_first, int s_last)
435{
436 FPWV *addr;
437 int flag, prot, sect;
438 int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
439 ulong start, now, last;
440 int rcode = 0;
441
442 if ((s_first < 0) || (s_first > s_last)) {
443 if (info->flash_id == FLASH_UNKNOWN) {
444 printf ("- missing\n");
445 } else {
446 printf ("- no sectors to erase\n");
447 }
448 return 1;
449 }
450
451 switch (info->flash_id & FLASH_TYPEMASK) {
452 case FLASH_INTEL800B:
453 case FLASH_INTEL160B:
454 case FLASH_INTEL320B:
455 case FLASH_INTEL640B:
456 case FLASH_28F800C3B:
457 case FLASH_28F160C3B:
458 case FLASH_28F320C3B:
459 case FLASH_28F640C3B:
460 case FLASH_AM640U:
461 break;
462 case FLASH_UNKNOWN:
463 default:
464 printf ("Can't erase unknown flash type %08lx - aborted\n",
465 info->flash_id);
466 return 1;
467 }
468
469 prot = 0;
470 for (sect = s_first; sect <= s_last; ++sect) {
471 if (info->protect[sect]) {
472 prot++;
473 }
474 }
475
476 if (prot) {
477 printf ("- Warning: %d protected sectors will not be erased!\n",
478 prot);
479 } else {
480 printf ("\n");
481 }
482
483 start = get_timer (0);
484 last = start;
485
486 /* Start erase on unprotected sectors */
487 for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
488
489 if (info->protect[sect] != 0) /* protected, skip it */
490 continue;
491
492 /* Disable interrupts which might cause a timeout here */
493 flag = disable_interrupts ();
494
495 addr = (FPWV *) (info->start[sect]);
496 if (intel) {
497 *addr = (FPW) 0x00500050; /* clear status register */
498 *addr = (FPW) 0x00200020; /* erase setup */
499 *addr = (FPW) 0x00D000D0; /* erase confirm */
500 } else {
501 /* must be AMD style if not Intel */
502 FPWV *base; /* first address in bank */
503
504 base = (FPWV *) (info->start[0]);
505 base[0x0555] = (FPW) 0x00AA00AA; /* unlock */
506 base[0x02AA] = (FPW) 0x00550055; /* unlock */
507 base[0x0555] = (FPW) 0x00800080; /* erase mode */
508 base[0x0555] = (FPW) 0x00AA00AA; /* unlock */
509 base[0x02AA] = (FPW) 0x00550055; /* unlock */
510 *addr = (FPW) 0x00300030; /* erase sector */
511 }
512
513 /* re-enable interrupts if necessary */
514 if (flag)
515 enable_interrupts ();
516
517 /* wait at least 50us for AMD, 80us for Intel.
518 * Let's wait 1 ms.
519 */
520 udelay (1000);
521
522 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
523 if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
524 printf ("Timeout\n");
525
526 if (intel) {
527 /* suspend erase */
528 *addr = (FPW) 0x00B000B0;
529 }
530
531 flash_reset (info); /* reset to read mode */
532 rcode = 1; /* failed */
533 break;
534 }
535
536 /* show that we're waiting */
537 if ((now - last) > 1000) { /* every second */
538 putc ('.');
539 last = now;
540 }
541 }
542
543 flash_reset (info); /* reset to read mode */
544 }
545
546 printf (" done\n");
547 return rcode;
548}
549
550/*-----------------------------------------------------------------------
551 * Copy memory to flash, returns:
552 * 0 - OK
553 * 1 - write timeout
554 * 2 - Flash not erased
555 */
556int bad_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
557{
558 FPW data = 0; /* 16 or 32 bit word, matches flash bus width */
559 int bytes; /* number of bytes to program in current word */
560 int left; /* number of bytes left to program */
561 int i, res;
562
563 /* printf("write_buff: src: %8p addr %08lx count: %ld\n", src, addr, cnt); */
564
565 for (left = cnt, res = 0;
566 left > 0 && res == 0;
567 addr += sizeof (data), left -= sizeof (data) - bytes) {
568
569 bytes = addr & (sizeof (data) - 1);
570 addr &= ~(sizeof (data) - 1);
571
572 /* combine source and destination data so can program
573 * an entire word of 16 or 32 bits
574 */
575 for (i = 0; i < sizeof (data); i++) {
576 data <<= 8;
577 if (i < bytes || i - bytes >= left)
578 data += *((uchar *) addr + i);
579 else
580 data += *src++;
581 }
582
583 /* write one word to the flash */
584 switch (info->flash_id & FLASH_VENDMASK) {
585 case FLASH_MAN_AMD:
586 res = write_word_amd (info, (FPWV *) addr, data);
587 break;
588 case FLASH_MAN_INTEL:
589 res = write_word_intel (info, (FPWV *) addr, data);
590 break;
591 default:
592 /* unknown flash type, error! */
593 printf ("missing or unknown FLASH type\n");
594 res = 1; /* not really a timeout, but gives error */
595 break;
596 }
597 }
598
599 return (res);
600}
601
602/**
603 * write_buf: - Copy memory to flash.
604 *
605 * @param info:
606 * @param src: source of copy transaction
607 * @param addr: where to copy to
608 * @param cnt: number of bytes to copy
609 *
610 * @return error code
611 */
612
613int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
614{
615 ulong cp, wp;
616 FPW data;
617 int l;
618 int i, rc;
619
620 wp = (addr & ~1); /* get lower word aligned address */
621
622 /*
623 * handle unaligned start bytes
624 */
625 if ((l = addr - wp) != 0) {
626 data = 0;
627 for (i = 0, cp = wp; i < l; ++i, ++cp) {
628 data = (data >> 8) | (*(uchar *) cp << 8);
629 }
630 for (; i < 2 && cnt > 0; ++i) {
631 data = (data >> 8) | (*src++ << 8);
632 --cnt;
633 ++cp;
634 }
635 for (; cnt == 0 && i < 2; ++i, ++cp) {
636 data = (data >> 8) | (*(uchar *) cp << 8);
637 }
638
639 if ((rc = write_word (info, wp, data)) != 0) {
640 return (rc);
641 }
642 wp += 2;
643 }
644
645 /*
646 * handle word aligned part
647 */
648 while (cnt >= 2) {
649 /* data = *((vushort*)src); */
650 data = *((FPW *) src);
651 if ((rc = write_word (info, wp, data)) != 0) {
652 return (rc);
653 }
654 src += sizeof (FPW);
655 wp += sizeof (FPW);
656 cnt -= sizeof (FPW);
657 }
658
659 if (cnt == 0)
660 return ERR_OK;
661
662 /*
663 * handle unaligned tail bytes
664 */
665 data = 0;
666 for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
667 data = (data >> 8) | (*src++ << 8);
668 --cnt;
669 }
670 for (; i < 2; ++i, ++cp) {
671 data = (data >> 8) | (*(uchar *) cp << 8);
672 }
673
674 return write_word (info, wp, data);
675}
676
677
678
679/*-----------------------------------------------------------------------
680 * Write a word to Flash for AMD FLASH
681 * A word is 16 or 32 bits, whichever the bus width of the flash bank
682 * (not an individual chip) is.
683 *
684 * returns:
685 * 0 - OK
686 * 1 - write timeout
687 * 2 - Flash not erased
688 */
689static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data)
690{
691 ulong start;
692 int flag;
693 int res = 0; /* result, assume success */
694 FPWV *base; /* first address in flash bank */
695
696 /* Check if Flash is (sufficiently) erased */
697 if ((*dest & data) != data) {
698 return (2);
699 }
700
701
702 base = (FPWV *) (info->start[0]);
703 /* Disable interrupts which might cause a timeout here */
704 flag = disable_interrupts ();
705
706 base[0x0555] = (FPW) 0x00AA00AA; /* unlock */
707 base[0x02AA] = (FPW) 0x00550055; /* unlock */
708 base[0x0555] = (FPW) 0x00A000A0; /* selects program mode */
709
710 *dest = data; /* start programming the data */
711
712 /* re-enable interrupts if necessary */
713 if (flag)
714 enable_interrupts ();
715
716 start = get_timer (0);
717
718 /* data polling for D7 */
719 while (res == 0
720 && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
721 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
722 *dest = (FPW) 0x00F000F0; /* reset bank */
723 res = 1;
724 }
725 }
726
727 return (res);
728}
729
730/*-----------------------------------------------------------------------
731 * Write a word to Flash for Intel FLASH
732 * A word is 16 or 32 bits, whichever the bus width of the flash bank
733 * (not an individual chip) is.
734 *
735 * returns:
736 * 0 - OK
737 * 1 - write timeout
738 * 2 - Flash not erased
739 */
740static int write_word_intel (flash_info_t * info, FPWV * dest, FPW data)
741{
742 ulong start;
743 int flag;
744 int res = 0; /* result, assume success */
745
746 /* Check if Flash is (sufficiently) erased */
747 if ((*dest & data) != data) {
748 return (2);
749 }
750
751 /* Disable interrupts which might cause a timeout here */
752 flag = disable_interrupts ();
753
754 *dest = (FPW) 0x00500050; /* clear status register */
755 *dest = (FPW) 0x00FF00FF; /* make sure in read mode */
756 *dest = (FPW) 0x00400040; /* program setup */
757
758 *dest = data; /* start programming the data */
759
760 /* re-enable interrupts if necessary */
761 if (flag)
762 enable_interrupts ();
763
764 start = get_timer (0);
765
766 while (res == 0 && (*dest & (FPW) 0x00800080) != (FPW) 0x00800080) {
767 if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
768 *dest = (FPW) 0x00B000B0; /* Suspend program */
769 res = 1;
770 }
771 }
772
773 if (res == 0 && (*dest & (FPW) 0x00100010))
774 res = 1; /* write failed, time out error is close enough */
775
776 *dest = (FPW) 0x00500050; /* clear status register */
777 *dest = (FPW) 0x00FF00FF; /* make sure in read mode */
778
779 return (res);
780}
781
782#ifdef CFG_FLASH_PROTECTION
783/*-----------------------------------------------------------------------
784 */
785int flash_real_protect (flash_info_t * info, long sector, int prot)
786{
787 int rcode = 0; /* assume success */
788 FPWV *addr; /* address of sector */
789 FPW value;
790
791 addr = (FPWV *) (info->start[sector]);
792
793 switch (info->flash_id & FLASH_TYPEMASK) {
794 case FLASH_28F800C3B:
795 case FLASH_28F800C3T:
796 case FLASH_28F160C3B:
797 case FLASH_28F160C3T:
798 case FLASH_28F320C3B:
799 case FLASH_28F320C3T:
800 case FLASH_28F640C3B:
801 case FLASH_28F640C3T:
802 flash_reset (info); /* make sure in read mode */
803 *addr = (FPW) 0x00600060L; /* lock command setup */
804 if (prot)
805 *addr = (FPW) 0x00010001L; /* lock sector */
806 else
807 *addr = (FPW) 0x00D000D0L; /* unlock sector */
808 flash_reset (info); /* reset to read mode */
809
810 /* now see if it really is locked/unlocked as requested */
811 *addr = (FPW) 0x00900090;
812 /* read sector protection at sector address, (A7 .. A0) = 0x02.
813 * D0 = 1 for each device if protected.
814 * If at least one device is protected the sector is marked
815 * protected, but return failure. Mixed protected and
816 * unprotected devices within a sector should never happen.
817 */
818 value = addr[2] & (FPW) 0x00010001;
819 if (value == 0)
820 info->protect[sector] = 0;
821 else if (value == (FPW) 0x00010001)
822 info->protect[sector] = 1;
823 else {
824 /* error, mixed protected and unprotected */
825 rcode = 1;
826 info->protect[sector] = 1;
827 }
828 if (info->protect[sector] != prot)
829 rcode = 1; /* failed to protect/unprotect as requested */
830
831 /* reload all protection bits from hardware for now */
832 flash_sync_real_protect (info);
833 break;
834
835 case FLASH_AM640U:
836 default:
837 /* no hardware protect that we support */
838 info->protect[sector] = prot;
839 break;
840 }
841
842 return rcode;
843}
844#endif