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