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