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