Added support for the Hynix HY27US08121A 64MB Flash chip.
[u-boot-openmoko/mini2440.git] / board / pleb2 / flash.c
blob5a1eba6b3f7eb050095705c8c1de1094672b216d
1 /*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
6 * project.
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.
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.
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
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.
29 #include <environment.h>
31 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
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.
36 #ifdef CONFIG_FLASH_16BIT
37 typedef unsigned short FLASH_PORT_WIDTH;
38 typedef volatile unsigned short FLASH_PORT_WIDTHV;
40 #define FLASH_ID_MASK 0xFFFF
41 #else
42 typedef unsigned long FLASH_PORT_WIDTH;
43 typedef volatile unsigned long FLASH_PORT_WIDTHV;
45 #define FLASH_ID_MASK 0xFFFFFFFF
46 #endif
48 #define FPW FLASH_PORT_WIDTH
49 #define FPWV FLASH_PORT_WIDTHV
51 #define ORMASK(size) ((-size) & OR_AM_MSK)
53 /*-----------------------------------------------------------------------
54 * Functions
56 static ulong flash_get_size (FPWV * addr, flash_info_t * info);
57 static void flash_reset (flash_info_t * info);
58 static int write_word_intel (flash_info_t * info, FPWV * dest, FPW data);
59 static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data);
60 static void flash_get_offsets (ulong base, flash_info_t * info);
62 #ifdef CFG_FLASH_PROTECTION
63 static void flash_sync_real_protect (flash_info_t * info);
64 #endif
66 /*-----------------------------------------------------------------------
67 * flash_init()
69 * sets up flash_info and returns size of FLASH (bytes)
71 unsigned long flash_init (void)
73 unsigned long size_b;
74 int i;
76 /* Init: no FLASHes known */
77 for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
78 flash_info[i].flash_id = FLASH_UNKNOWN;
81 size_b = flash_get_size ((FPW *) CFG_FLASH_BASE, &flash_info[0]);
83 flash_info[0].size = size_b;
85 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
86 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx\n",
87 size_b);
90 /* Do this again (was done already in flast_get_size), just
91 * in case we move it when remap the FLASH.
93 flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
95 #ifdef CFG_FLASH_PROTECTION
96 /* read the hardware protection status (if any) into the
97 * protection array in flash_info.
99 flash_sync_real_protect (&flash_info[0]);
100 #endif
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
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
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
123 return (size_b);
126 /*-----------------------------------------------------------------------
128 static void flash_reset (flash_info_t * info)
130 FPWV *base = (FPWV *) (info->start[0]);
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 */
139 /*-----------------------------------------------------------------------
141 static void flash_get_offsets (ulong base, flash_info_t * info)
143 int i;
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 */
151 bootsect_size = 0x00002000 * (sizeof (FPW) / 2);
152 sect_size = 0x00010000 * (sizeof (FPW) / 2);
154 /* set sector offsets for bottom boot block type */
155 for (i = 0; i < 8; ++i) {
156 info->start[i] = base + (i * bootsect_size);
158 for (i = 8; i < info->sector_count; i++) {
159 info->start[i] = base + ((i - 7) * sect_size);
161 } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
162 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
164 int sect_size; /* number of bytes/sector */
166 sect_size = 0x00010000 * (sizeof (FPW) / 2);
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) {
174 int sect_size; /* number of bytes/sector */
176 sect_size = 0x00010000 * (sizeof (FPW) / 2);
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);
191 /*-----------------------------------------------------------------------
194 void flash_print_info (flash_info_t * info)
196 int i;
197 uchar *boottype;
198 uchar *bootletter;
199 char *fmt;
200 uchar botbootletter[] = "B";
201 uchar topbootletter[] = "T";
202 uchar botboottype[] = "bottom boot sector";
203 uchar topboottype[] = "top boot sector";
205 if (info->flash_id == FLASH_UNKNOWN) {
206 printf ("missing or unknown FLASH type\n");
207 return;
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;
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;
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;
287 printf (fmt, bootletter, boottype);
289 printf (" Size: %ld MB in %d Sectors\n",
290 info->size >> 20, info->sector_count);
292 printf (" Sector Start Addresses:");
294 for (i = 0; i < info->sector_count; ++i) {
295 if ((i % 5) == 0) {
296 printf ("\n ");
299 printf (" %08lX%s", info->start[i],
300 info->protect[i] ? " (RO)" : " ");
303 printf ("\n");
306 /*-----------------------------------------------------------------------
310 * The following code cannot be run from FLASH!
313 ulong flash_get_size (FPWV * addr, flash_info_t * info)
315 /* Write auto select command: read Manufacturer ID */
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 */
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.
325 switch (addr[0] & 0xff) {
327 case (uchar) AMD_MANUFACT:
328 info->flash_id = FLASH_MAN_AMD;
329 break;
331 case (uchar) INTEL_MANUFACT:
332 info->flash_id = FLASH_MAN_INTEL;
333 break;
335 default:
336 info->flash_id = FLASH_UNKNOWN;
337 info->sector_count = 0;
338 info->size = 0;
339 break;
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]) {
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
406 default:
407 info->flash_id = FLASH_UNKNOWN;
408 info->sector_count = 0;
409 info->size = 0;
410 return (0); /* => no or unknown flash */
413 flash_get_offsets ((ulong) addr, info);
415 /* Put FLASH back in read mode */
416 flash_reset (info);
418 return (info->size);
421 #ifdef CFG_FLASH_PROTECTION
422 /*-----------------------------------------------------------------------
425 static void flash_sync_real_protect (flash_info_t * info)
427 FPWV *addr = (FPWV *) (info->start[0]);
428 FPWV *sect;
429 int i;
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.
449 sect = (FPWV *) (info->start[i]);
450 info->protect[i] =
451 (sect[2] & (FPW) (0x00010001)) ? 1 : 0;
454 /* Put FLASH back in read mode */
455 flash_reset (info);
456 break;
458 case FLASH_AM640U:
459 case FLASH_AM800T:
460 default:
461 /* no hardware protect that we support */
462 break;
465 #endif
467 /*-----------------------------------------------------------------------
470 int flash_erase (flash_info_t * info, int s_first, int s_last)
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;
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");
484 return 1;
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;
506 prot = 0;
507 for (sect = s_first; sect <= s_last; ++sect) {
508 if (info->protect[sect]) {
509 prot++;
513 if (prot) {
514 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
515 } else {
516 printf ("\n");
519 reset_timer_masked ();
521 /* Start erase on unprotected sectors */
522 for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
524 if (info->protect[sect] != 0) /* protected, skip it */
525 continue;
527 /* Disable interrupts which might cause a timeout here */
528 flag = disable_interrupts ();
530 reset_timer_masked ();
531 last = 0;
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 */
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 */
551 /* re-enable interrupts if necessary */
552 if (flag)
553 enable_interrupts ();
555 /* wait at least 50us for AMD, 80us for Intel.
556 * Let's wait 1 ms.
558 udelay (1000);
560 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
561 if ((now =
562 get_timer_masked ()) > CFG_FLASH_ERASE_TOUT) {
563 printf ("Timeout\n");
565 if (intel) {
566 /* suspend erase */
567 *addr = (FPW) 0x00B000B0;
570 flash_reset (info); /* reset to read mode */
571 rcode = 1; /* failed */
572 break;
575 /* show that we're waiting */
576 if ((now - last) > 1 * CFG_HZ) { /* every second */
577 putc ('.');
578 last = now;
582 flash_reset (info); /* reset to read mode */
585 printf (" done\n");
586 return rcode;
589 /*-----------------------------------------------------------------------
590 * Copy memory to flash, returns:
591 * 0 - OK
592 * 1 - write timeout
593 * 2 - Flash not erased
595 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
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;
602 for (left = cnt, res = 0;
603 left > 0 && res == 0;
604 addr += sizeof (data), left -= sizeof (data) - bytes) {
606 bytes = addr & (sizeof (data) - 1);
607 addr &= ~(sizeof (data) - 1);
609 /* combine source and destination data so can program
610 * an entire word of 16 or 32 bits
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;
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++;
628 #endif
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;
646 return (res);
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.
654 * returns:
655 * 0 - OK
656 * 1 - write timeout
657 * 2 - Flash not erased
659 static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data)
661 int flag;
662 int res = 0; /* result, assume success */
663 FPWV *base; /* first address in flash bank */
665 /* Check if Flash is (sufficiently) erased */
666 if ((*dest & data) != data) {
667 return (2);
671 base = (FPWV *) (info->start[0]);
673 /* Disable interrupts which might cause a timeout here */
674 flag = disable_interrupts ();
676 base[0x0555] = (FPW) 0x00AA00AA; /* unlock */
677 base[0x02AA] = (FPW) 0x00550055; /* unlock */
678 base[0x0555] = (FPW) 0x00A000A0; /* selects program mode */
680 *dest = data; /* start programming the data */
682 /* re-enable interrupts if necessary */
683 if (flag)
684 enable_interrupts ();
686 reset_timer_masked ();
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;
697 return (res);
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.
705 * returns:
706 * 0 - OK
707 * 1 - write timeout
708 * 2 - Flash not erased
710 static int write_word_intel (flash_info_t * info, FPWV * dest, FPW data)
712 int flag;
713 int res = 0; /* result, assume success */
715 /* Check if Flash is (sufficiently) erased */
716 if ((*dest & data) != data) {
717 return (2);
720 /* Disable interrupts which might cause a timeout here */
721 flag = disable_interrupts ();
723 *dest = (FPW) 0x00500050; /* clear status register */
724 *dest = (FPW) 0x00FF00FF; /* make sure in read mode */
725 *dest = (FPW) 0x00400040; /* program setup */
727 *dest = data; /* start programming the data */
729 /* re-enable interrupts if necessary */
730 if (flag)
731 enable_interrupts ();
733 reset_timer_masked ();
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;
742 if (res == 0 && (*dest & (FPW) 0x00100010))
743 res = 1; /* write failed, time out error is close enough */
745 *dest = (FPW) 0x00500050; /* clear status register */
746 *dest = (FPW) 0x00FF00FF; /* make sure in read mode */
748 return (res);
751 #ifdef CFG_FLASH_PROTECTION
752 /*-----------------------------------------------------------------------
754 int flash_real_protect (flash_info_t * info, long sector, int prot)
756 int rcode = 0; /* assume success */
757 FPWV *addr; /* address of sector */
758 FPW value;
760 addr = (FPWV *) (info->start[sector]);
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 */
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.
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;
797 if (info->protect[sector] != prot)
798 rcode = 1; /* failed to protect/unprotect as requested */
800 /* reload all protection bits from hardware for now */
801 flash_sync_real_protect (info);
802 break;
804 case FLASH_AM640U:
805 case FLASH_AM800T:
806 default:
807 /* no hardware protect that we support */
808 info->protect[sector] = prot;
809 break;
812 return rcode;
814 #endif