3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
5 * See file CREDITS for list of people who contributed to this
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,
26 #include <asm/processor.h>
28 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
30 /*-----------------------------------------------------------------------
33 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
35 /*-----------------------------------------------------------------------
37 static void flash_get_offsets (ulong base
, flash_info_t
*info
)
42 /* set up sector start address table */
43 if (((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_SST
) ||
44 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM640U
)) {
45 for (i
= 0; i
< info
->sector_count
; i
++)
46 info
->start
[i
] = base
+ (i
* 0x00010000);
47 } else if (((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL322B
) ||
48 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL323B
) ||
49 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM320B
) ||
50 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL324B
)) {
51 /* set sector offsets for bottom boot block type */
52 for (i
=0; i
<8; ++i
) { /* 8 x 8k boot sectors */
53 info
->start
[i
] = base
;
56 while (i
< info
->sector_count
) { /* 64k regular sectors */
57 info
->start
[i
] = base
;
61 } else if (((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL322T
) ||
62 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL323T
) ||
63 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM320T
) ||
64 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL324T
)) {
65 /* set sector offsets for top boot block type */
67 i
= info
->sector_count
;
68 for (n
=0; n
<8; ++n
) { /* 8 x 8k boot sectors */
71 info
->start
[i
] = base
;
73 while (i
> 0) { /* 64k regular sectors */
76 info
->start
[i
] = base
;
79 if (info
->flash_id
& FLASH_BTYPE
) {
80 /* set sector offsets for bottom boot block type */
81 info
->start
[0] = base
+ 0x00000000;
82 info
->start
[1] = base
+ 0x00004000;
83 info
->start
[2] = base
+ 0x00006000;
84 info
->start
[3] = base
+ 0x00008000;
85 for (i
= 4; i
< info
->sector_count
; i
++) {
86 info
->start
[i
] = base
+ (i
* 0x00010000) - 0x00030000;
89 /* set sector offsets for top boot block type */
90 i
= info
->sector_count
- 1;
91 info
->start
[i
--] = base
+ info
->size
- 0x00004000;
92 info
->start
[i
--] = base
+ info
->size
- 0x00006000;
93 info
->start
[i
--] = base
+ info
->size
- 0x00008000;
95 info
->start
[i
] = base
+ i
* 0x00010000;
101 /*-----------------------------------------------------------------------
103 void flash_print_info (flash_info_t
*info
)
109 volatile unsigned long *flash
;
111 if (info
->flash_id
== FLASH_UNKNOWN
) {
112 printf ("missing or unknown FLASH type\n");
116 switch (info
->flash_id
& FLASH_VENDMASK
) {
117 case FLASH_MAN_AMD
: printf ("AMD "); break;
118 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
119 case FLASH_MAN_SST
: printf ("SST "); break;
120 default: printf ("Unknown Vendor "); break;
123 switch (info
->flash_id
& FLASH_TYPEMASK
) {
124 case FLASH_AM400B
: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
126 case FLASH_AM400T
: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
128 case FLASH_AM800B
: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
130 case FLASH_AM800T
: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
132 case FLASH_AM160B
: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
134 case FLASH_AM160T
: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
136 case FLASH_AM320T
: printf ("AM29LV320T (32 M, top sector)\n");
138 case FLASH_AM320B
: printf ("AM29LV320B (32 M, bottom sector)\n");
140 case FLASH_AMDL322T
: printf ("AM29DL322T (32 M, top sector)\n");
142 case FLASH_AMDL322B
: printf ("AM29DL322B (32 M, bottom sector)\n");
144 case FLASH_AMDL323T
: printf ("AM29DL323T (32 M, top sector)\n");
146 case FLASH_AMDL323B
: printf ("AM29DL323B (32 M, bottom sector)\n");
148 case FLASH_AM640U
: printf ("AM29LV640D (64 M, uniform sector)\n");
150 case FLASH_SST800A
: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
152 case FLASH_SST160A
: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
154 default: printf ("Unknown Chip Type\n");
158 printf (" Size: %ld MB in %d Sectors\n",
159 info
->size
>> 20, info
->sector_count
);
161 printf (" Sector Start Addresses:");
162 for (i
=0; i
<info
->sector_count
; ++i
) {
163 #ifdef CFG_FLASH_EMPTY_INFO
165 * Check if whole sector is erased
167 if (i
!= (info
->sector_count
-1))
168 size
= info
->start
[i
+1] - info
->start
[i
];
170 size
= info
->start
[0] + info
->size
- info
->start
[i
];
172 flash
= (volatile unsigned long *)info
->start
[i
];
173 size
= size
>> 2; /* divide by 4 for longword access */
174 for (k
=0; k
<size
; k
++)
176 if (*flash
++ != 0xffffffff)
185 /* print empty and read-only info */
186 printf (" %08lX%s%s",
189 info
->protect
[i
] ? "RO " : " ");
195 info
->protect
[i
] ? " (RO)" : " ");
203 /*-----------------------------------------------------------------------
207 /*-----------------------------------------------------------------------
211 * The following code cannot be run from FLASH!
213 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
)
217 CFG_FLASH_WORD_SIZE value
;
218 ulong base
= (ulong
)addr
;
219 volatile CFG_FLASH_WORD_SIZE
*addr2
= (CFG_FLASH_WORD_SIZE
*)addr
;
221 /* Write auto select command: read Manufacturer ID */
222 addr2
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00AA00AA;
223 addr2
[CFG_FLASH_ADDR1
] = (CFG_FLASH_WORD_SIZE
)0x00550055;
224 addr2
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00900090;
226 value
= addr2
[CFG_FLASH_READ0
];
229 case (CFG_FLASH_WORD_SIZE
)AMD_MANUFACT
:
230 info
->flash_id
= FLASH_MAN_AMD
;
232 case (CFG_FLASH_WORD_SIZE
)FUJ_MANUFACT
:
233 info
->flash_id
= FLASH_MAN_FUJ
;
235 case (CFG_FLASH_WORD_SIZE
)SST_MANUFACT
:
236 info
->flash_id
= FLASH_MAN_SST
;
239 info
->flash_id
= FLASH_UNKNOWN
;
240 info
->sector_count
= 0;
242 return (0); /* no or unknown flash */
245 value
= addr2
[CFG_FLASH_READ1
]; /* device ID */
248 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV400T
:
249 info
->flash_id
+= FLASH_AM400T
;
250 info
->sector_count
= 11;
251 info
->size
= 0x00080000;
252 break; /* => 0.5 MB */
254 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV400B
:
255 info
->flash_id
+= FLASH_AM400B
;
256 info
->sector_count
= 11;
257 info
->size
= 0x00080000;
258 break; /* => 0.5 MB */
260 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV800T
:
261 info
->flash_id
+= FLASH_AM800T
;
262 info
->sector_count
= 19;
263 info
->size
= 0x00100000;
266 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV800B
:
267 info
->flash_id
+= FLASH_AM800B
;
268 info
->sector_count
= 19;
269 info
->size
= 0x00100000;
272 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV160T
:
273 info
->flash_id
+= FLASH_AM160T
;
274 info
->sector_count
= 35;
275 info
->size
= 0x00200000;
278 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV160B
:
279 info
->flash_id
+= FLASH_AM160B
;
280 info
->sector_count
= 35;
281 info
->size
= 0x00200000;
284 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV320T
:
285 info
->flash_id
+= FLASH_AM320T
;
286 info
->sector_count
= 71;
287 info
->size
= 0x00400000; break; /* => 4 MB */
289 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV320B
:
290 info
->flash_id
+= FLASH_AM320B
;
291 info
->sector_count
= 71;
292 info
->size
= 0x00400000; break; /* => 4 MB */
294 case (CFG_FLASH_WORD_SIZE
)AMD_ID_DL322T
:
295 info
->flash_id
+= FLASH_AMDL322T
;
296 info
->sector_count
= 71;
297 info
->size
= 0x00400000; break; /* => 4 MB */
299 case (CFG_FLASH_WORD_SIZE
)AMD_ID_DL322B
:
300 info
->flash_id
+= FLASH_AMDL322B
;
301 info
->sector_count
= 71;
302 info
->size
= 0x00400000; break; /* => 4 MB */
304 case (CFG_FLASH_WORD_SIZE
)AMD_ID_DL323T
:
305 info
->flash_id
+= FLASH_AMDL323T
;
306 info
->sector_count
= 71;
307 info
->size
= 0x00400000; break; /* => 4 MB */
309 case (CFG_FLASH_WORD_SIZE
)AMD_ID_DL323B
:
310 info
->flash_id
+= FLASH_AMDL323B
;
311 info
->sector_count
= 71;
312 info
->size
= 0x00400000; break; /* => 4 MB */
314 case (CFG_FLASH_WORD_SIZE
)AMD_ID_LV640U
:
315 info
->flash_id
+= FLASH_AM640U
;
316 info
->sector_count
= 128;
317 info
->size
= 0x00800000; break; /* => 8 MB */
319 case (CFG_FLASH_WORD_SIZE
)SST_ID_xF800A
:
320 info
->flash_id
+= FLASH_SST800A
;
321 info
->sector_count
= 16;
322 info
->size
= 0x00100000;
325 case (CFG_FLASH_WORD_SIZE
)SST_ID_xF160A
:
326 info
->flash_id
+= FLASH_SST160A
;
327 info
->sector_count
= 32;
328 info
->size
= 0x00200000;
332 info
->flash_id
= FLASH_UNKNOWN
;
333 return (0); /* => no or unknown flash */
337 /* set up sector start address table */
338 if (((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_SST
) ||
339 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM640U
)) {
340 for (i
= 0; i
< info
->sector_count
; i
++)
341 info
->start
[i
] = base
+ (i
* 0x00010000);
342 } else if (((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL322B
) ||
343 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL323B
) ||
344 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM320B
) ||
345 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL324B
)) {
346 /* set sector offsets for bottom boot block type */
347 for (i
=0; i
<8; ++i
) { /* 8 x 8k boot sectors */
348 info
->start
[i
] = base
;
351 while (i
< info
->sector_count
) { /* 64k regular sectors */
352 info
->start
[i
] = base
;
356 } else if (((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL322T
) ||
357 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL323T
) ||
358 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM320T
) ||
359 ((info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AMDL324T
)) {
360 /* set sector offsets for top boot block type */
362 i
= info
->sector_count
;
363 for (n
=0; n
<8; ++n
) { /* 8 x 8k boot sectors */
366 info
->start
[i
] = base
;
368 while (i
> 0) { /* 64k regular sectors */
371 info
->start
[i
] = base
;
374 if (info
->flash_id
& FLASH_BTYPE
) {
375 /* set sector offsets for bottom boot block type */
376 info
->start
[0] = base
+ 0x00000000;
377 info
->start
[1] = base
+ 0x00004000;
378 info
->start
[2] = base
+ 0x00006000;
379 info
->start
[3] = base
+ 0x00008000;
380 for (i
= 4; i
< info
->sector_count
; i
++) {
381 info
->start
[i
] = base
+ (i
* 0x00010000) - 0x00030000;
384 /* set sector offsets for top boot block type */
385 i
= info
->sector_count
- 1;
386 info
->start
[i
--] = base
+ info
->size
- 0x00004000;
387 info
->start
[i
--] = base
+ info
->size
- 0x00006000;
388 info
->start
[i
--] = base
+ info
->size
- 0x00008000;
389 for (; i
>= 0; i
--) {
390 info
->start
[i
] = base
+ i
* 0x00010000;
395 /* check for protected sectors */
396 for (i
= 0; i
< info
->sector_count
; i
++) {
397 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
398 /* D0 = 1 if protected */
399 addr2
= (volatile CFG_FLASH_WORD_SIZE
*)(info
->start
[i
]);
400 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_SST
)
401 info
->protect
[i
] = 0;
403 info
->protect
[i
] = addr2
[CFG_FLASH_READ2
] & 1;
407 * Prevent writes to uninitialized FLASH.
409 if (info
->flash_id
!= FLASH_UNKNOWN
) {
410 addr2
= (CFG_FLASH_WORD_SIZE
*)info
->start
[0];
411 *addr2
= (CFG_FLASH_WORD_SIZE
)0x00F000F0; /* reset bank */
418 /*-----------------------------------------------------------------------
421 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
423 volatile CFG_FLASH_WORD_SIZE
*addr
= (CFG_FLASH_WORD_SIZE
*)(info
->start
[0]);
424 volatile CFG_FLASH_WORD_SIZE
*addr2
;
425 int flag
, prot
, sect
, l_sect
;
426 ulong start
, now
, last
;
429 if ((s_first
< 0) || (s_first
> s_last
)) {
430 if (info
->flash_id
== FLASH_UNKNOWN
) {
431 printf ("- missing\n");
433 printf ("- no sectors to erase\n");
438 if (info
->flash_id
== FLASH_UNKNOWN
) {
439 printf ("Can't erase unknown flash type - aborted\n");
444 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
445 if (info
->protect
[sect
]) {
451 printf ("- Warning: %d protected sectors will not be erased!\n",
459 /* Disable interrupts which might cause a timeout here */
460 flag
= disable_interrupts();
462 /* Start erase on unprotected sectors */
463 for (sect
= s_first
; sect
<=s_last
; sect
++) {
464 if (info
->protect
[sect
] == 0) { /* not protected */
465 addr2
= (CFG_FLASH_WORD_SIZE
*)(info
->start
[sect
]);
466 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_SST
) {
467 addr
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00AA00AA;
468 addr
[CFG_FLASH_ADDR1
] = (CFG_FLASH_WORD_SIZE
)0x00550055;
469 addr
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00800080;
470 addr
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00AA00AA;
471 addr
[CFG_FLASH_ADDR1
] = (CFG_FLASH_WORD_SIZE
)0x00550055;
472 addr2
[0] = (CFG_FLASH_WORD_SIZE
)0x00500050; /* block erase */
474 udelay(1000); /* wait 1 ms */
476 if (sect
== s_first
) {
477 addr
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00AA00AA;
478 addr
[CFG_FLASH_ADDR1
] = (CFG_FLASH_WORD_SIZE
)0x00550055;
479 addr
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00800080;
480 addr
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00AA00AA;
481 addr
[CFG_FLASH_ADDR1
] = (CFG_FLASH_WORD_SIZE
)0x00550055;
483 addr2
[0] = (CFG_FLASH_WORD_SIZE
)0x00300030; /* sector erase */
489 /* re-enable interrupts if necessary */
493 /* wait at least 80us - let's wait 1 ms */
497 * We wait for the last triggered sector
502 start
= get_timer (0);
504 addr
= (CFG_FLASH_WORD_SIZE
*)(info
->start
[l_sect
]);
505 while ((addr
[0] & (CFG_FLASH_WORD_SIZE
)0x00800080) != (CFG_FLASH_WORD_SIZE
)0x00800080) {
506 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
507 printf ("Timeout\n");
510 /* show that we're waiting */
511 if ((now
- last
) > 1000) { /* every second */
518 /* reset to read mode */
519 addr
= (CFG_FLASH_WORD_SIZE
*)info
->start
[0];
520 addr
[0] = (CFG_FLASH_WORD_SIZE
)0x00F000F0; /* reset bank */
526 /*-----------------------------------------------------------------------
527 * Copy memory to flash, returns:
530 * 2 - Flash not erased
533 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
538 wp
= (addr
& ~3); /* get lower word aligned address */
541 * handle unaligned start bytes
543 if ((l
= addr
- wp
) != 0) {
545 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
546 data
= (data
<< 8) | (*(uchar
*)cp
);
548 for (; i
<4 && cnt
>0; ++i
) {
549 data
= (data
<< 8) | *src
++;
553 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
554 data
= (data
<< 8) | (*(uchar
*)cp
);
557 if ((rc
= write_word(info
, wp
, data
)) != 0) {
564 * handle word aligned part
568 for (i
=0; i
<4; ++i
) {
569 data
= (data
<< 8) | *src
++;
571 if ((rc
= write_word(info
, wp
, data
)) != 0) {
583 * handle unaligned tail bytes
586 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
587 data
= (data
<< 8) | *src
++;
590 for (; i
<4; ++i
, ++cp
) {
591 data
= (data
<< 8) | (*(uchar
*)cp
);
594 return (write_word(info
, wp
, data
));
597 /*-----------------------------------------------------------------------
598 * Write a word to Flash, returns:
601 * 2 - Flash not erased
603 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
)
605 volatile CFG_FLASH_WORD_SIZE
*addr2
= (CFG_FLASH_WORD_SIZE
*)(info
->start
[0]);
606 volatile CFG_FLASH_WORD_SIZE
*dest2
= (CFG_FLASH_WORD_SIZE
*)dest
;
607 volatile CFG_FLASH_WORD_SIZE
*data2
= (CFG_FLASH_WORD_SIZE
*)&data
;
612 /* Check if Flash is (sufficiently) erased */
613 if ((*((volatile CFG_FLASH_WORD_SIZE
*)dest
) &
614 (CFG_FLASH_WORD_SIZE
)data
) != (CFG_FLASH_WORD_SIZE
)data
) {
617 /* Disable interrupts which might cause a timeout here */
618 flag
= disable_interrupts();
620 for (i
=0; i
<4/sizeof(CFG_FLASH_WORD_SIZE
); i
++)
622 addr2
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00AA00AA;
623 addr2
[CFG_FLASH_ADDR1
] = (CFG_FLASH_WORD_SIZE
)0x00550055;
624 addr2
[CFG_FLASH_ADDR0
] = (CFG_FLASH_WORD_SIZE
)0x00A000A0;
628 /* re-enable interrupts if necessary */
632 /* data polling for D7 */
633 start
= get_timer (0);
634 while ((dest2
[i
] & (CFG_FLASH_WORD_SIZE
)0x00800080) !=
635 (data2
[i
] & (CFG_FLASH_WORD_SIZE
)0x00800080)) {
636 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
645 /*-----------------------------------------------------------------------