blob: da4ebe6e751a96f5133a54b81d2754dd4fffd2bb [file] [log] [blame]
wdenk281e00a2004-08-01 22:48:16 +00001/*
2 * (C) 2000-2004 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
wdenk281e00a2004-08-01 22:48:16 +000028#define FLASH_BANK_SIZE MX1FS2_FLASH_BANK_SIZE
29#define MAIN_SECT_SIZE MX1FS2_FLASH_SECT_SIZE
30
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020031flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
wdenk281e00a2004-08-01 22:48:16 +000032
33/*
34 * NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
35 * has nothing to do with the flash chip being 8-bit or 16-bit.
36 */
37#ifdef CONFIG_FLASH_16BIT
38typedef unsigned short FLASH_PORT_WIDTH;
39typedef volatile unsigned short FLASH_PORT_WIDTHV;
40
41#define FLASH_ID_MASK 0xFFFF
42#else
43typedef unsigned long FLASH_PORT_WIDTH;
44typedef volatile unsigned long FLASH_PORT_WIDTHV;
45
46#define FLASH_ID_MASK 0xFFFFFFFF
47#endif
48
49#define FPW FLASH_PORT_WIDTH
50#define FPWV FLASH_PORT_WIDTHV
51
52#define ORMASK(size) ((-size) & OR_AM_MSK)
53
54/*-----------------------------------------------------------------------
55 * Functions
56 */
57#if 0
58static ulong flash_get_size(FPWV * addr, flash_info_t * info);
59static void flash_get_offsets(ulong base, flash_info_t * info);
60#endif
61static void flash_reset(flash_info_t * info);
62static int write_word_intel(flash_info_t * info, FPWV * dest, FPW data);
63static int write_word_amd(flash_info_t * info, FPWV * dest, FPW data);
64#define write_word(in, de, da) write_word_amd(in, de, da)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020065#ifdef CONFIG_SYS_FLASH_PROTECTION
wdenk281e00a2004-08-01 22:48:16 +000066static void flash_sync_real_protect(flash_info_t * info);
67#endif
68
wdenk281e00a2004-08-01 22:48:16 +000069/*-----------------------------------------------------------------------
70 * flash_init()
71 *
72 * sets up flash_info and returns size of FLASH (bytes)
73 */
74ulong
75flash_init(void)
76{
77 int i, j;
78 ulong size = 0;
79
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020080 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
wdenk281e00a2004-08-01 22:48:16 +000081 ulong flashbase = 0;
82 flash_info[i].flash_id =
83 (FLASH_MAN_AMD & FLASH_VENDMASK) |
84 (FLASH_AM640U & FLASH_TYPEMASK);
85 flash_info[i].size = FLASH_BANK_SIZE;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020086 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
87 memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
wdenk281e00a2004-08-01 22:48:16 +000088 switch (i) {
89 case 0:
90 flashbase = MX1FS2_FLASH_BASE;
91 break;
92 default:
93 panic("configured too many flash banks!\n");
94 break;
95 }
96 for (j = 0; j < flash_info[i].sector_count; j++) {
97 flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
98 }
99 size += flash_info[i].size;
100 }
101
102 /* Protect monitor and environment sectors */
103 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200104 CONFIG_SYS_FLASH_BASE,
105 CONFIG_SYS_FLASH_BASE + _bss_start - _armboot_start,
wdenk281e00a2004-08-01 22:48:16 +0000106 &flash_info[0]);
107
108 flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +0200109 CONFIG_ENV_ADDR,
110 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
wdenk281e00a2004-08-01 22:48:16 +0000111
112 return size;
113}
114
115/*-----------------------------------------------------------------------
116 */
117static void
118flash_reset(flash_info_t * info)
119{
120 FPWV *base = (FPWV *) (info->start[0]);
121
122 /* Put FLASH back in read mode */
123 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
124 *base = (FPW) 0x00FF00FF; /* Intel Read Mode */
125 else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
126 *base = (FPW) 0x00F000F0; /* AMD Read Mode */
127}
128
129/*-----------------------------------------------------------------------
130 */
131#if 0
132static void
133flash_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#endif /* 0 */
166
167/*-----------------------------------------------------------------------
168 */
169
170void
171flash_print_info(flash_info_t * info)
172{
173 int i;
174 uchar *boottype;
175 uchar *bootletter;
Jean-Christophe PLAGNIOL-VILLARD217bf6b2008-02-25 00:03:12 +0100176 char *fmt;
wdenk281e00a2004-08-01 22:48:16 +0000177 uchar botbootletter[] = "B";
178 uchar topbootletter[] = "T";
179 uchar botboottype[] = "bottom boot sector";
180 uchar topboottype[] = "top boot sector";
181
182 if (info->flash_id == FLASH_UNKNOWN) {
183 printf("missing or unknown FLASH type\n");
184 return;
185 }
186
187 switch (info->flash_id & FLASH_VENDMASK) {
188 case FLASH_MAN_AMD:
189 printf("AMD ");
190 break;
191 case FLASH_MAN_BM:
192 printf("BRIGHT MICRO ");
193 break;
194 case FLASH_MAN_FUJ:
195 printf("FUJITSU ");
196 break;
197 case FLASH_MAN_SST:
198 printf("SST ");
199 break;
200 case FLASH_MAN_STM:
201 printf("STM ");
202 break;
203 case FLASH_MAN_INTEL:
204 printf("INTEL ");
205 break;
206 default:
207 printf("Unknown Vendor ");
208 break;
209 }
210
211 /* check for top or bottom boot, if it applies */
212 if (info->flash_id & FLASH_BTYPE) {
213 boottype = botboottype;
214 bootletter = botbootletter;
215 } else {
216 boottype = topboottype;
217 bootletter = topbootletter;
218 }
219
220 switch (info->flash_id & FLASH_TYPEMASK) {
221 case FLASH_AM640U:
222 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
223 break;
224 case FLASH_28F800C3B:
225 case FLASH_28F800C3T:
226 fmt = "28F800C3%s (8 Mbit, %s)\n";
227 break;
228 case FLASH_INTEL800B:
229 case FLASH_INTEL800T:
230 fmt = "28F800B3%s (8 Mbit, %s)\n";
231 break;
232 case FLASH_28F160C3B:
233 case FLASH_28F160C3T:
234 fmt = "28F160C3%s (16 Mbit, %s)\n";
235 break;
236 case FLASH_INTEL160B:
237 case FLASH_INTEL160T:
238 fmt = "28F160B3%s (16 Mbit, %s)\n";
239 break;
240 case FLASH_28F320C3B:
241 case FLASH_28F320C3T:
242 fmt = "28F320C3%s (32 Mbit, %s)\n";
243 break;
244 case FLASH_INTEL320B:
245 case FLASH_INTEL320T:
246 fmt = "28F320B3%s (32 Mbit, %s)\n";
247 break;
248 case FLASH_28F640C3B:
249 case FLASH_28F640C3T:
250 fmt = "28F640C3%s (64 Mbit, %s)\n";
251 break;
252 case FLASH_INTEL640B:
253 case FLASH_INTEL640T:
254 fmt = "28F640B3%s (64 Mbit, %s)\n";
255 break;
256 default:
257 fmt = "Unknown Chip Type\n";
258 break;
259 }
260
261 printf(fmt, bootletter, boottype);
262
263 printf(" Size: %ld MB in %d Sectors\n",
264 info->size >> 20, info->sector_count);
265
266 printf(" Sector Start Addresses:");
267
268 for (i = 0; i < info->sector_count; ++i) {
269 if ((i % 5) == 0) {
270 printf("\n ");
271 }
272
273 printf(" %08lX%s", info->start[i],
274 info->protect[i] ? " (RO)" : " ");
275 }
276
277 printf("\n");
278}
279
280/*-----------------------------------------------------------------------
281 */
282
283/*
284 * The following code cannot be run from FLASH!
285 */
286
287#if 0
288ulong
289flash_get_size(FPWV * addr, flash_info_t * info)
290{
291 /* Write auto select command: read Manufacturer ID */
292
293 /* Write auto select command sequence and test FLASH answer */
294 addr[0x0555] = (FPW) 0x00AA00AA; /* for AMD, Intel ignores this */
295 addr[0x02AA] = (FPW) 0x00550055; /* for AMD, Intel ignores this */
296 addr[0x0555] = (FPW) 0x00900090; /* selects Intel or AMD */
297
298 /* The manufacturer codes are only 1 byte, so just use 1 byte.
299 * This works for any bus width and any FLASH device width.
300 */
301 switch (addr[0] & 0xff) {
302
303 case (uchar) AMD_MANUFACT:
304 info->flash_id = FLASH_MAN_AMD;
305 break;
306
307 case (uchar) INTEL_MANUFACT:
308 info->flash_id = FLASH_MAN_INTEL;
309 break;
310
311 default:
312 info->flash_id = FLASH_UNKNOWN;
313 info->sector_count = 0;
314 info->size = 0;
315 break;
316 }
317
318 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
319 if (info->flash_id != FLASH_UNKNOWN)
320 switch (addr[1]) {
321
322 case (FPW) AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */
323 info->flash_id += FLASH_AM640U;
324 info->sector_count = 128;
325 info->size = 0x00800000 * (sizeof (FPW) / 2);
326 break; /* => 8 or 16 MB */
327
328 case (FPW) INTEL_ID_28F800C3B:
329 info->flash_id += FLASH_28F800C3B;
330 info->sector_count = 23;
331 info->size = 0x00100000 * (sizeof (FPW) / 2);
332 break; /* => 1 or 2 MB */
333
334 case (FPW) INTEL_ID_28F800B3B:
335 info->flash_id += FLASH_INTEL800B;
336 info->sector_count = 23;
337 info->size = 0x00100000 * (sizeof (FPW) / 2);
338 break; /* => 1 or 2 MB */
339
340 case (FPW) INTEL_ID_28F160C3B:
341 info->flash_id += FLASH_28F160C3B;
342 info->sector_count = 39;
343 info->size = 0x00200000 * (sizeof (FPW) / 2);
344 break; /* => 2 or 4 MB */
345
346 case (FPW) INTEL_ID_28F160B3B:
347 info->flash_id += FLASH_INTEL160B;
348 info->sector_count = 39;
349 info->size = 0x00200000 * (sizeof (FPW) / 2);
350 break; /* => 2 or 4 MB */
351
352 case (FPW) INTEL_ID_28F320C3B:
353 info->flash_id += FLASH_28F320C3B;
354 info->sector_count = 71;
355 info->size = 0x00400000 * (sizeof (FPW) / 2);
356 break; /* => 4 or 8 MB */
357
358 case (FPW) INTEL_ID_28F320B3B:
359 info->flash_id += FLASH_INTEL320B;
360 info->sector_count = 71;
361 info->size = 0x00400000 * (sizeof (FPW) / 2);
362 break; /* => 4 or 8 MB */
363
364 case (FPW) INTEL_ID_28F640C3B:
365 info->flash_id += FLASH_28F640C3B;
366 info->sector_count = 135;
367 info->size = 0x00800000 * (sizeof (FPW) / 2);
368 break; /* => 8 or 16 MB */
369
370 case (FPW) INTEL_ID_28F640B3B:
371 info->flash_id += FLASH_INTEL640B;
372 info->sector_count = 135;
373 info->size = 0x00800000 * (sizeof (FPW) / 2);
374 break; /* => 8 or 16 MB */
375
376 default:
377 info->flash_id = FLASH_UNKNOWN;
378 info->sector_count = 0;
379 info->size = 0;
380 return (0); /* => no or unknown flash */
381 }
382
383 flash_get_offsets((ulong) addr, info);
384
385 /* Put FLASH back in read mode */
386 flash_reset(info);
387
388 return (info->size);
389}
390#endif /* 0 */
391
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200392#ifdef CONFIG_SYS_FLASH_PROTECTION
wdenk281e00a2004-08-01 22:48:16 +0000393/*-----------------------------------------------------------------------
394 */
395
396static void
397flash_sync_real_protect(flash_info_t * info)
398{
399 FPWV *addr = (FPWV *) (info->start[0]);
400 FPWV *sect;
401 int i;
402
403 switch (info->flash_id & FLASH_TYPEMASK) {
404 case FLASH_28F800C3B:
405 case FLASH_28F800C3T:
406 case FLASH_28F160C3B:
407 case FLASH_28F160C3T:
408 case FLASH_28F320C3B:
409 case FLASH_28F320C3T:
410 case FLASH_28F640C3B:
411 case FLASH_28F640C3T:
412 /* check for protected sectors */
413 *addr = (FPW) 0x00900090;
414 for (i = 0; i < info->sector_count; i++) {
415 /* read sector protection at sector address, (A7 .. A0) = 0x02.
416 * D0 = 1 for each device if protected.
417 * If at least one device is protected the sector is marked
418 * protected, but mixed protected and unprotected devices
419 * within a sector should never happen.
420 */
421 sect = (FPWV *) (info->start[i]);
422 info->protect[i] =
423 (sect[2] & (FPW) (0x00010001)) ? 1 : 0;
424 }
425
426 /* Put FLASH back in read mode */
427 flash_reset(info);
428 break;
429
430 case FLASH_AM640U:
431 default:
432 /* no hardware protect that we support */
433 break;
434 }
435}
436#endif
437
438/*-----------------------------------------------------------------------
439 */
440
441int
442flash_erase(flash_info_t * info, int s_first, int s_last)
443{
444 FPWV *addr;
445 int flag, prot, sect;
446 int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
447 ulong start, now, last;
448 int rcode = 0;
449
450 if ((s_first < 0) || (s_first > s_last)) {
451 if (info->flash_id == FLASH_UNKNOWN) {
452 printf("- missing\n");
453 } else {
454 printf("- no sectors to erase\n");
455 }
456 return 1;
457 }
458
459 switch (info->flash_id & FLASH_TYPEMASK) {
460 case FLASH_INTEL800B:
461 case FLASH_INTEL160B:
462 case FLASH_INTEL320B:
463 case FLASH_INTEL640B:
464 case FLASH_28F800C3B:
465 case FLASH_28F160C3B:
466 case FLASH_28F320C3B:
467 case FLASH_28F640C3B:
468 case FLASH_AM640U:
469 break;
470 case FLASH_UNKNOWN:
471 default:
472 printf("Can't erase unknown flash type %08lx - aborted\n",
473 info->flash_id);
474 return 1;
475 }
476
477 prot = 0;
478 for (sect = s_first; sect <= s_last; ++sect) {
479 if (info->protect[sect]) {
480 prot++;
481 }
482 }
483
484 if (prot) {
485 printf("- Warning: %d protected sectors will not be erased!\n",
486 prot);
487 } else {
488 printf("\n");
489 }
490
491 start = get_timer(0);
492 last = start;
493
494 /* Start erase on unprotected sectors */
495 for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
496
497 if (info->protect[sect] != 0) /* protected, skip it */
498 continue;
499
500 /* Disable interrupts which might cause a timeout here */
501 flag = disable_interrupts();
502
503 addr = (FPWV *) (info->start[sect]);
504 if (intel) {
505 *addr = (FPW) 0x00500050; /* clear status register */
506 *addr = (FPW) 0x00200020; /* erase setup */
507 *addr = (FPW) 0x00D000D0; /* erase confirm */
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) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200531 if ((now = get_timer(0)) - start > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenk281e00a2004-08-01 22:48:16 +0000532 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
565bad_write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
566{
567 FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
568 int bytes; /* number of bytes to program in current word */
569 int left; /* number of bytes left to program */
570 int i, res;
571
572 for (left = cnt, res = 0;
573 left > 0 && res == 0;
574 addr += sizeof (data), left -= sizeof (data) - bytes) {
575
576 bytes = addr & (sizeof (data) - 1);
577 addr &= ~(sizeof (data) - 1);
578
579 /* combine source and destination data so can program
580 * an entire word of 16 or 32 bits
581 */
582 for (i = 0; i < sizeof (data); i++) {
583 data <<= 8;
584 if (i < bytes || i - bytes >= left)
585 data += *((uchar *) addr + i);
586 else
587 data += *src++;
588 }
589
590 /* write one word to the flash */
591 switch (info->flash_id & FLASH_VENDMASK) {
592 case FLASH_MAN_AMD:
593 res = write_word_amd(info, (FPWV *) addr, data);
594 break;
595 case FLASH_MAN_INTEL:
596 res = write_word_intel(info, (FPWV *) addr, data);
597 break;
598 default:
599 /* unknown flash type, error! */
600 printf("missing or unknown FLASH type\n");
601 res = 1; /* not really a timeout, but gives error */
602 break;
603 }
604 }
605
606 return (res);
607}
608
609/**
610 * write_buf: - Copy memory to flash.
611 *
612 * @param info:
613 * @param src: source of copy transaction
614 * @param addr: where to copy to
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200615 * @param cnt: number of bytes to copy
wdenk281e00a2004-08-01 22:48:16 +0000616 *
617 * @return error code
618 */
619
620int
621write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
622{
623 ulong cp, wp;
624 FPW data;
625 int l;
626 int i, rc;
627
628 wp = (addr & ~1); /* get lower word aligned address */
629
630 /* handle unaligned start bytes */
631 if ((l = addr - wp) != 0) {
632 data = 0;
633 for (i = 0, cp = wp; i < l; ++i, ++cp) {
634 data = (data >> 8) | (*(uchar *) cp << 8);
635 }
636 for (; i < 2 && cnt > 0; ++i) {
637 data = (data >> 8) | (*src++ << 8);
638 --cnt;
639 ++cp;
640 }
641 for (; cnt == 0 && i < 2; ++i, ++cp) {
642 data = (data >> 8) | (*(uchar *) cp << 8);
643 }
644
645 if ((rc = write_word(info, (FPWV *)wp, data)) != 0) {
646 return (rc);
647 }
648 wp += 2;
649 }
650
651 /* handle word aligned part */
652 while (cnt >= 2) {
653 /* data = *((vushort*)src); */
654 data = *((FPW *) src);
655 if ((rc = write_word(info, (FPWV *)wp, data)) != 0) {
656 return (rc);
657 }
658 src += sizeof (FPW);
659 wp += sizeof (FPW);
660 cnt -= sizeof (FPW);
661 }
662
663 if (cnt == 0)
664 return ERR_OK;
665
666 /*
667 * handle unaligned tail bytes
668 */
669 data = 0;
670 for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
671 data = (data >> 8) | (*src++ << 8);
672 --cnt;
673 }
674 for (; i < 2; ++i, ++cp) {
675 data = (data >> 8) | (*(uchar *) cp << 8);
676 }
677
678 return write_word(info, (FPWV *)wp, data);
679}
680
681/*-----------------------------------------------------------------------
682 * Write a word to Flash for AMD FLASH
683 * A word is 16 or 32 bits, whichever the bus width of the flash bank
684 * (not an individual chip) is.
685 *
686 * returns:
687 * 0 - OK
688 * 1 - write timeout
689 * 2 - Flash not erased
690 */
691static int
692write_word_amd(flash_info_t * info, FPWV * dest, FPW data)
693{
694 ulong start;
695 int flag;
696 int res = 0; /* result, assume success */
697 FPWV *base; /* first address in flash bank */
698
699 /* Check if Flash is (sufficiently) erased */
700 if ((*dest & data) != data) {
701 return (2);
702 }
703
704 base = (FPWV *) (info->start[0]);
705 /* Disable interrupts which might cause a timeout here */
706 flag = disable_interrupts();
707
708 base[0x0555] = (FPW) 0x00AA00AA; /* unlock */
709 base[0x02AA] = (FPW) 0x00550055; /* unlock */
710 base[0x0555] = (FPW) 0x00A000A0; /* selects program mode */
711
712 *dest = data; /* start programming the data */
713
714 /* re-enable interrupts if necessary */
715 if (flag)
716 enable_interrupts();
717
718 start = get_timer(0);
719
720 /* data polling for D7 */
721 while (res == 0
722 && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200723 if (get_timer(0) - start > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk281e00a2004-08-01 22:48:16 +0000724 *dest = (FPW) 0x00F000F0; /* reset bank */
725 printf("SHA timeout\n");
726 res = 1;
727 }
728 }
729
730 return (res);
731}
732
733/*-----------------------------------------------------------------------
734 * Write a word to Flash for Intel FLASH
735 * A word is 16 or 32 bits, whichever the bus width of the flash bank
736 * (not an individual chip) is.
737 *
738 * returns:
739 * 0 - OK
740 * 1 - write timeout
741 * 2 - Flash not erased
742 */
743static int
744write_word_intel(flash_info_t * info, FPWV * dest, FPW data)
745{
746 ulong start;
747 int flag;
748 int res = 0; /* result, assume success */
749
750 /* Check if Flash is (sufficiently) erased */
751 if ((*dest & data) != data) {
752 return (2);
753 }
754
755 /* Disable interrupts which might cause a timeout here */
756 flag = disable_interrupts();
757
758 *dest = (FPW) 0x00500050; /* clear status register */
759 *dest = (FPW) 0x00FF00FF; /* make sure in read mode */
760 *dest = (FPW) 0x00400040; /* program setup */
761
762 *dest = data; /* start programming the data */
763
764 /* re-enable interrupts if necessary */
765 if (flag)
766 enable_interrupts();
767
768 start = get_timer(0);
769
770 while (res == 0 && (*dest & (FPW) 0x00800080) != (FPW) 0x00800080) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200771 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenk281e00a2004-08-01 22:48:16 +0000772 *dest = (FPW) 0x00B000B0; /* Suspend program */
773 res = 1;
774 }
775 }
776
777 if (res == 0 && (*dest & (FPW) 0x00100010))
778 res = 1; /* write failed, time out error is close enough */
779
780 *dest = (FPW) 0x00500050; /* clear status register */
781 *dest = (FPW) 0x00FF00FF; /* make sure in read mode */
782
783 return (res);
784}
785
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200786#ifdef CONFIG_SYS_FLASH_PROTECTION
wdenk281e00a2004-08-01 22:48:16 +0000787/*-----------------------------------------------------------------------
788 */
789int
790flash_real_protect(flash_info_t * info, long sector, int prot)
791{
792 int rcode = 0; /* assume success */
793 FPWV *addr; /* address of sector */
794 FPW value;
795
796 addr = (FPWV *) (info->start[sector]);
797
798 switch (info->flash_id & FLASH_TYPEMASK) {
799 case FLASH_28F800C3B:
800 case FLASH_28F800C3T:
801 case FLASH_28F160C3B:
802 case FLASH_28F160C3T:
803 case FLASH_28F320C3B:
804 case FLASH_28F320C3T:
805 case FLASH_28F640C3B:
806 case FLASH_28F640C3T:
807 flash_reset(info); /* make sure in read mode */
808 *addr = (FPW) 0x00600060L; /* lock command setup */
809 if (prot)
810 *addr = (FPW) 0x00010001L; /* lock sector */
811 else
812 *addr = (FPW) 0x00D000D0L; /* unlock sector */
813 flash_reset(info); /* reset to read mode */
814
815 /* now see if it really is locked/unlocked as requested */
816 *addr = (FPW) 0x00900090;
817 /* read sector protection at sector address, (A7 .. A0) = 0x02.
818 * D0 = 1 for each device if protected.
819 * If at least one device is protected the sector is marked
820 * protected, but return failure. Mixed protected and
821 * unprotected devices within a sector should never happen.
822 */
823 value = addr[2] & (FPW) 0x00010001;
824 if (value == 0)
825 info->protect[sector] = 0;
826 else if (value == (FPW) 0x00010001)
827 info->protect[sector] = 1;
828 else {
829 /* error, mixed protected and unprotected */
830 rcode = 1;
831 info->protect[sector] = 1;
832 }
833 if (info->protect[sector] != prot)
834 rcode = 1; /* failed to protect/unprotect as requested */
835
836 /* reload all protection bits from hardware for now */
837 flash_sync_real_protect(info);
838 break;
839
840 case FLASH_AM640U:
841 default:
842 /* no hardware protect that we support */
843 info->protect[sector] = prot;
844 break;
845 }
846
847 return rcode;
848}
849#endif