]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/exbitgen/flash.c
4d83fd5efdb81ec79134ed4dfc779e27d1811590
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
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 * Wait for completion of each sector erase command issued
28 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
32 #include <asm/u-boot.h>
33 #include <asm/processor.h>
36 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
38 /*-----------------------------------------------------------------------
41 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
);
42 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
44 #ifdef MEIGSBOARD_ONBOARD_FLASH /* onboard = 2MB */
45 # ifdef CONFIG_EXBITGEN
46 # define FLASH_WORD_SIZE unsigned long
48 #else /* Meigsboard socket flash = 512KB */
49 # ifdef CONFIG_EXBITGEN
50 # define FLASH_WORD_SIZE unsigned char
54 #ifdef CONFIG_EXBITGEN
57 #define FLASH_WORD_SIZE unsigned char
60 /*-----------------------------------------------------------------------
63 unsigned long flash_init (void)
65 unsigned long bank_size
;
66 unsigned long tot_size
;
67 unsigned long bank_addr
;
70 /* Init: no FLASHes known */
71 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; ++i
) {
72 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
73 flash_info
[i
].size
= 0;
78 /* Detect Boot Flash */
79 bank_addr
= CFG_FLASH0_BASE
;
80 bank_size
= flash_get_size((vu_long
*)bank_addr
, &flash_info
[0]);
82 (void)flash_protect(FLAG_PROTECT_CLEAR
,
84 bank_addr
+ bank_size
- 1,
87 if (flash_info
[0].flash_id
== FLASH_UNKNOWN
) {
88 printf ("## Unknown FLASH on Boot Flash Bank\n");
90 flash_info
[0].size
= bank_size
;
91 tot_size
+= bank_size
;
93 /* Detect Application Flash */
94 bank_addr
= CFG_FLASH1_BASE
;
95 for (i
= 1; i
< CFG_MAX_FLASH_BANKS
; ++i
) {
96 bank_size
= flash_get_size((vu_long
*)bank_addr
, &flash_info
[i
]);
97 if (flash_info
[i
].flash_id
== FLASH_UNKNOWN
) {
101 (void)flash_protect(FLAG_PROTECT_CLEAR
,
103 bank_addr
+ bank_size
- 1,
106 flash_info
[i
].size
= bank_size
;
107 tot_size
+= bank_size
;
108 bank_addr
+= bank_size
;
110 if (flash_info
[1].flash_id
== FLASH_UNKNOWN
) {
111 printf ("## Unknown FLASH on Application Flash Bank\n");
114 /* Protect monitor and environment sectors */
115 #if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
116 flash_protect(FLAG_PROTECT_SET
,
118 CFG_MONITOR_BASE
+ monitor_flash_len
- 1,
120 #if 0xfffffffc >= CFG_FLASH0_BASE
121 #if 0xfffffffc <= CFG_FLASH0_BASE + CFG_FLASH0_SIZE - 1
122 flash_protect(FLAG_PROTECT_SET
,
123 0xfffffffc, 0xffffffff,
129 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CFG_ENV_ADDR)
130 flash_protect(FLAG_PROTECT_SET
,
132 CFG_ENV_ADDR
+ CFG_ENV_SIZE
- 1,
139 /*-----------------------------------------------------------------------
141 void flash_print_info (flash_info_t
*info
)
145 if (info
->flash_id
== FLASH_UNKNOWN
) {
146 printf ("missing or unknown FLASH type\n");
150 switch (info
->flash_id
& FLASH_VENDMASK
) {
151 case FLASH_MAN_AMD
: printf ("AMD "); break;
152 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
153 case FLASH_MAN_SST
: printf ("SST "); break;
154 default: printf ("Unknown Vendor "); break;
157 switch (info
->flash_id
& FLASH_TYPEMASK
) {
158 case FLASH_AM040
: printf ("AM29F040 (512 Kbit, uniform sector size)\n");
160 case FLASH_AM400B
: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
162 case FLASH_AM400T
: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
164 case FLASH_AM800B
: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
166 case FLASH_AM800T
: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
168 case FLASH_AM160B
: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
170 case FLASH_AM160T
: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
172 case FLASH_AM320B
: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
174 case FLASH_AM320T
: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
176 case FLASH_AMDLV033C
: printf ("AM29LV033C (32 Mbit, uniform sector size)\n");
178 case FLASH_AMDLV065D
: printf ("AM29LV065D (64 Mbit, uniform sector size)\n");
180 case FLASH_SST800A
: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
182 case FLASH_SST160A
: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
184 case FLASH_SST040
: printf ("SST39LF/VF040 (4 Mbit, uniform sector size)\n");
186 default: printf ("Unknown Chip Type\n");
190 printf (" Size: %ld KB in %d Sectors\n",
191 info
->size
>> 10, info
->sector_count
);
193 printf (" Sector Start Addresses:");
194 for (i
=0; i
<info
->sector_count
; ++i
) {
199 info
->protect
[i
] ? " (RO)" : " "
205 /*-----------------------------------------------------------------------
209 /*-----------------------------------------------------------------------
213 * The following code cannot be run from FLASH!
215 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
)
218 FLASH_WORD_SIZE value
;
219 ulong base
= (ulong
)addr
;
220 volatile FLASH_WORD_SIZE
*addr2
= (FLASH_WORD_SIZE
*)addr
;
222 /* Write auto select command: read Manufacturer ID */
223 addr2
[ADDR0
] = (FLASH_WORD_SIZE
)0x00AA00AA;
224 addr2
[ADDR1
] = (FLASH_WORD_SIZE
)0x00550055;
225 addr2
[ADDR0
] = (FLASH_WORD_SIZE
)0x00900090;
230 case (FLASH_WORD_SIZE
)AMD_MANUFACT
:
231 info
->flash_id
= FLASH_MAN_AMD
;
233 case (FLASH_WORD_SIZE
)FUJ_MANUFACT
:
234 info
->flash_id
= FLASH_MAN_FUJ
;
236 case (FLASH_WORD_SIZE
)SST_MANUFACT
:
237 info
->flash_id
= FLASH_MAN_SST
;
240 info
->flash_id
= FLASH_UNKNOWN
;
241 info
->sector_count
= 0;
243 return (0); /* no or unknown flash */
246 value
= addr2
[1]; /* device ID */
249 case (FLASH_WORD_SIZE
)AMD_ID_F040B
:
250 info
->flash_id
+= FLASH_AM040
;
251 info
->sector_count
= 8;
252 info
->size
= 0x0080000; /* => 512 ko */
254 case (FLASH_WORD_SIZE
)AMD_ID_LV400T
:
255 info
->flash_id
+= FLASH_AM400T
;
256 info
->sector_count
= 11;
257 info
->size
= 0x00080000;
258 break; /* => 0.5 MB */
260 case (FLASH_WORD_SIZE
)AMD_ID_LV400B
:
261 info
->flash_id
+= FLASH_AM400B
;
262 info
->sector_count
= 11;
263 info
->size
= 0x00080000;
264 break; /* => 0.5 MB */
266 case (FLASH_WORD_SIZE
)AMD_ID_LV800T
:
267 info
->flash_id
+= FLASH_AM800T
;
268 info
->sector_count
= 19;
269 info
->size
= 0x00100000;
272 case (FLASH_WORD_SIZE
)AMD_ID_LV800B
:
273 info
->flash_id
+= FLASH_AM800B
;
274 info
->sector_count
= 19;
275 info
->size
= 0x00100000;
278 case (FLASH_WORD_SIZE
)AMD_ID_LV160T
:
279 info
->flash_id
+= FLASH_AM160T
;
280 info
->sector_count
= 35;
281 info
->size
= 0x00200000;
284 case (FLASH_WORD_SIZE
)AMD_ID_LV160B
:
285 info
->flash_id
+= FLASH_AM160B
;
286 info
->sector_count
= 35;
287 info
->size
= 0x00200000;
290 case (FLASH_WORD_SIZE
)AMD_ID_LV033C
:
291 info
->flash_id
+= FLASH_AMDLV033C
;
292 info
->sector_count
= 64;
293 info
->size
= 0x00400000;
296 case (FLASH_WORD_SIZE
)AMD_ID_LV065D
:
297 info
->flash_id
+= FLASH_AMDLV065D
;
298 info
->sector_count
= 128;
299 info
->size
= 0x00800000;
302 case (FLASH_WORD_SIZE
)AMD_ID_LV320T
:
303 info
->flash_id
+= FLASH_AM320T
;
304 info
->sector_count
= 67;
305 info
->size
= 0x00400000;
308 case (FLASH_WORD_SIZE
)AMD_ID_LV320B
:
309 info
->flash_id
+= FLASH_AM320B
;
310 info
->sector_count
= 67;
311 info
->size
= 0x00400000;
314 case (FLASH_WORD_SIZE
)SST_ID_xF800A
:
315 info
->flash_id
+= FLASH_SST800A
;
316 info
->sector_count
= 16;
317 info
->size
= 0x00100000;
320 case (FLASH_WORD_SIZE
)SST_ID_xF160A
:
321 info
->flash_id
+= FLASH_SST160A
;
322 info
->sector_count
= 32;
323 info
->size
= 0x00200000;
325 case (FLASH_WORD_SIZE
)SST_ID_xF040
:
326 info
->flash_id
+= FLASH_SST040
;
327 info
->sector_count
= 128;
328 info
->size
= 0x00080000;
329 break; /* => 512KB */
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_AM040
) ||
340 (info
->flash_id
== FLASH_AMDLV033C
) ||
341 (info
->flash_id
== FLASH_AMDLV065D
)) {
342 ulong sectsize
= info
->size
/ info
->sector_count
;
343 for (i
= 0; i
< info
->sector_count
; i
++)
344 info
->start
[i
] = base
+ (i
* sectsize
);
346 if (info
->flash_id
& FLASH_BTYPE
) {
347 /* set sector offsets for bottom boot block type */
348 info
->start
[0] = base
+ 0x00000000;
349 info
->start
[1] = base
+ 0x00004000;
350 info
->start
[2] = base
+ 0x00006000;
351 info
->start
[3] = base
+ 0x00008000;
352 for (i
= 4; i
< info
->sector_count
; i
++) {
353 info
->start
[i
] = base
+ (i
* 0x00010000) - 0x00030000;
356 /* set sector offsets for top boot block type */
357 i
= info
->sector_count
- 1;
358 info
->start
[i
--] = base
+ info
->size
- 0x00004000;
359 info
->start
[i
--] = base
+ info
->size
- 0x00006000;
360 info
->start
[i
--] = base
+ info
->size
- 0x00008000;
361 for (; i
>= 0; i
--) {
362 info
->start
[i
] = base
+ i
* 0x00010000;
367 /* check for protected sectors */
368 for (i
= 0; i
< info
->sector_count
; i
++) {
369 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
370 /* D0 = 1 if protected */
372 addr2
= (volatile FLASH_WORD_SIZE
*)(info
->start
[i
]);
373 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_SST
)
374 info
->protect
[i
] = 0;
376 info
->protect
[i
] = addr2
[2] & 1;
379 /* switch to the read mode */
380 if (info
->flash_id
!= FLASH_UNKNOWN
) {
381 addr2
= (FLASH_WORD_SIZE
*)info
->start
[0];
382 *addr2
= (FLASH_WORD_SIZE
)0x00F000F0; /* reset bank */
388 /*-----------------------------------------------------------------------
391 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
393 volatile FLASH_WORD_SIZE
*addr
= (FLASH_WORD_SIZE
*)(info
->start
[0]);
394 volatile FLASH_WORD_SIZE
*addr2
;
395 int flag
, prot
, sect
;
396 ulong start
, now
, last
;
398 if ((s_first
< 0) || (s_first
> s_last
)) {
399 if (info
->flash_id
== FLASH_UNKNOWN
) {
400 printf ("- missing\n");
402 printf ("- no sectors to erase\n");
407 if (info
->flash_id
== FLASH_UNKNOWN
) {
408 printf ("Can't erase unknown flash type - aborted\n");
413 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
414 if (info
->protect
[sect
]) {
420 printf ("- Warning: %d protected sectors will not be erased!\n",
426 start
= get_timer (0);
428 /* Start erase on unprotected sectors */
429 for (sect
= s_first
; sect
<= s_last
; sect
++) {
430 if (info
->protect
[sect
] == 0) { /* not protected */
431 addr2
= (FLASH_WORD_SIZE
*)(info
->start
[sect
]);
433 /* Disable interrupts which might cause a timeout here */
434 flag
= disable_interrupts();
436 addr
[ADDR0
] = (FLASH_WORD_SIZE
)0x00AA00AA;
437 addr
[ADDR1
] = (FLASH_WORD_SIZE
)0x00550055;
438 addr
[ADDR0
] = (FLASH_WORD_SIZE
)0x00800080;
439 addr
[ADDR0
] = (FLASH_WORD_SIZE
)0x00AA00AA;
440 addr
[ADDR1
] = (FLASH_WORD_SIZE
)0x00550055;
441 addr2
[0] = (FLASH_WORD_SIZE
)0x00300030;
443 /* re-enable interrupts if necessary */
447 /* wait at least 80us - let's wait 1 ms */
450 while ((addr2
[0] & 0x00800080) !=
451 (FLASH_WORD_SIZE
) 0x00800080) {
452 if ((now
=get_timer(start
)) >
453 CFG_FLASH_ERASE_TOUT
) {
454 printf ("Timeout\n");
455 addr
[0] = (FLASH_WORD_SIZE
)0x00F000F0;
459 /* show that we're waiting */
460 if ((now
- last
) > 1000) { /* every second */
466 addr
[0] = (FLASH_WORD_SIZE
)0x00F000F0;
475 /*-----------------------------------------------------------------------
476 * Copy memory to flash, returns:
479 * 2 - Flash not erased
482 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
487 wp
= (addr
& ~3); /* get lower word aligned address */
490 * handle unaligned start bytes
492 if ((l
= addr
- wp
) != 0) {
494 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
495 data
= (data
<< 8) | (*(uchar
*)cp
);
497 for (; i
<4 && cnt
>0; ++i
) {
498 data
= (data
<< 8) | *src
++;
502 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
503 data
= (data
<< 8) | (*(uchar
*)cp
);
506 if ((rc
= write_word(info
, wp
, data
)) != 0) {
513 * handle word aligned part
517 for (i
=0; i
<4; ++i
) {
518 data
= (data
<< 8) | *src
++;
520 if ((rc
= write_word(info
, wp
, data
)) != 0) {
532 * handle unaligned tail bytes
535 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
536 data
= (data
<< 8) | *src
++;
539 for (; i
<4; ++i
, ++cp
) {
540 data
= (data
<< 8) | (*(uchar
*)cp
);
543 return (write_word(info
, wp
, data
));
546 /*-----------------------------------------------------------------------
547 * Write a word to Flash, returns:
550 * 2 - Flash not erased
552 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
)
554 volatile FLASH_WORD_SIZE
*addr2
= (FLASH_WORD_SIZE
*)(info
->start
[0]);
555 volatile FLASH_WORD_SIZE
*dest2
= (FLASH_WORD_SIZE
*)dest
;
556 volatile FLASH_WORD_SIZE
*data2
= (FLASH_WORD_SIZE
*)&data
;
561 /* Check if Flash is (sufficiently) erased */
562 if ((*((volatile ulong
*)dest
) & data
) != data
) {
563 printf("dest = %08lx, *dest = %08lx, data = %08lx\n",
564 dest
, *(volatile ulong
*)dest
, data
);
568 for (i
=0; i
< 4/sizeof(FLASH_WORD_SIZE
); i
++) {
569 /* Disable interrupts which might cause a timeout here */
570 flag
= disable_interrupts();
572 addr2
[ADDR0
] = (FLASH_WORD_SIZE
)0x00AA00AA;
573 addr2
[ADDR1
] = (FLASH_WORD_SIZE
)0x00550055;
574 addr2
[ADDR0
] = (FLASH_WORD_SIZE
)0x00A000A0;
577 /* re-enable interrupts if necessary */
581 /* data polling for D7 */
582 start
= get_timer (0);
583 while ((dest2
[i
] & 0x00800080) != (data2
[i
] & 0x00800080)) {
584 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
585 addr2
[0] = (FLASH_WORD_SIZE
)0x00F000F0;
591 addr2
[0] = (FLASH_WORD_SIZE
)0x00F000F0;
596 /*-----------------------------------------------------------------------