]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/xsengine/flash.c
a188e244089e0e1a71e5e5c35ed40498fe324610
3 * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
5 * (C) Copyright 2000-2004
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8 * See file CREDITS for list of people who contributed to this
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #include <linux/byteorder/swab.h>
30 #define SWAP(x) __swab32(x)
32 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
35 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
);
36 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
37 static void flash_get_offsets (ulong base
, flash_info_t
*info
);
39 /*-----------------------------------------------------------------------
41 unsigned long flash_init (void)
46 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++) {
49 flash_get_size ((vu_long
*) PHYS_FLASH_1
, &flash_info
[i
]);
50 flash_get_offsets (PHYS_FLASH_1
, &flash_info
[i
]);
53 flash_get_size ((vu_long
*) PHYS_FLASH_2
, &flash_info
[i
]);
54 flash_get_offsets (PHYS_FLASH_2
, &flash_info
[i
]);
57 panic ("configured too many flash banks!\n");
60 size
+= flash_info
[i
].size
;
63 /* Protect monitor and environment sectors */
64 flash_protect ( FLAG_PROTECT_SET
,CFG_FLASH_BASE
,CFG_FLASH_BASE
+ monitor_flash_len
- 1,&flash_info
[0] );
65 flash_protect ( FLAG_PROTECT_SET
,CFG_ENV_ADDR
,CFG_ENV_ADDR
+ CFG_ENV_SIZE
- 1, &flash_info
[0] );
70 /*-----------------------------------------------------------------------
72 static void flash_get_offsets (ulong base
, flash_info_t
*info
)
76 if (info
->flash_id
== FLASH_UNKNOWN
) return;
78 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
) {
79 for (i
= 0; i
< info
->sector_count
; i
++) {
80 info
->start
[i
] = base
+ (i
* PHYS_FLASH_SECT_SIZE
);
86 /*-----------------------------------------------------------------------
88 void flash_print_info (flash_info_t
*info
)
92 if (info
->flash_id
== FLASH_UNKNOWN
) {
93 printf ("missing or unknown FLASH type\n");
97 switch (info
->flash_id
& FLASH_VENDMASK
) {
98 case FLASH_MAN_AMD
: printf ("AMD "); break;
99 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
100 default: printf ("Unknown Vendor "); break;
103 switch (info
->flash_id
& FLASH_TYPEMASK
) {
104 case FLASH_AMLV640U
: printf ("AM29LV640ML (64Mbit, uniform sector size)\n");
106 case FLASH_S29GL064M
: printf ("S29GL064M (64Mbit, top boot sector size)\n");
108 default: printf ("Unknown Chip Type\n");
112 printf (" Size: %ld MB in %d Sectors\n",
113 info
->size
>> 20, info
->sector_count
);
115 printf (" Sector Start Addresses:");
116 for (i
=0; i
<info
->sector_count
; ++i
) {
121 info
->protect
[i
] ? " (RO)" : " "
129 * The following code cannot be run from FLASH!
131 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
)
135 ulong base
= (ulong
)addr
;
137 /* Write auto select command: read Manufacturer ID */
138 addr
[0x0555] = 0x00AA00AA;
139 addr
[0x02AA] = 0x00550055;
140 addr
[0x0555] = 0x00900090;
144 debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong
)addr
, value
);
148 debug ("Manufacturer: AMD\n");
149 info
->flash_id
= FLASH_MAN_AMD
;
152 debug ("Manufacturer: FUJITSU\n");
153 info
->flash_id
= FLASH_MAN_FUJ
;
156 debug ("Manufacturer: *** unknown ***\n");
157 info
->flash_id
= FLASH_UNKNOWN
;
158 info
->sector_count
= 0;
160 return (0); /* no or unknown flash */
163 value
= addr
[1]; /* device ID */
165 debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong
)(&addr
[1]), value
);
170 debug ("Mirror Bit flash: addr[14] = %08lX addr[15] = %08lX\n",
173 case AMD_ID_LV640U_2
:
174 if (addr
[15] != AMD_ID_LV640U_3
) {
175 debug ("Chip: AMLV640U -> unknown\n");
176 info
->flash_id
= FLASH_UNKNOWN
;
178 debug ("Chip: AMLV640U\n");
179 info
->flash_id
+= FLASH_AMLV640U
;
180 info
->sector_count
= 128;
181 info
->size
= 0x01000000;
183 break; /* => 16 MB */
184 case AMD_ID_GL064MT_2
:
185 if (addr
[15] != AMD_ID_GL064MT_3
) {
186 debug ("Chip: S29GL064M-R3 -> unknown\n");
187 info
->flash_id
= FLASH_UNKNOWN
;
189 debug ("Chip: S29GL064M-R3\n");
190 info
->flash_id
+= FLASH_S29GL064M
;
191 info
->sector_count
= 128;
192 info
->size
= 0x01000000;
194 break; /* => 16 MB */
196 debug ("Chip: *** unknown ***\n");
197 info
->flash_id
= FLASH_UNKNOWN
;
203 info
->flash_id
= FLASH_UNKNOWN
;
204 return (0); /* => no or unknown flash */
207 /* set up sector start address table */
210 switch (info
->flash_id
& FLASH_TYPEMASK
) {
211 /* only known types here - no default */
215 for (i
= 0; i
< info
->sector_count
; i
++) {
216 info
->start
[i
] = base
;
221 for (i
= 0; i
< info
->sector_count
; i
++) {
222 info
->start
[i
] = base
;
224 * The first 8 sectors are 8 kB,
225 * all the other ones are 64 kB
241 /* check for protected sectors */
242 for (i
= 0; i
< info
->sector_count
; i
++) {
243 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
244 /* D0 = 1 if protected */
245 addr
= (volatile unsigned long *)(info
->start
[i
]);
246 info
->protect
[i
] = addr
[2] & 1;
251 * Prevent writes to uninitialized FLASH.
253 if (info
->flash_id
!= FLASH_UNKNOWN
) {
254 addr
= (volatile unsigned long *)info
->start
[0];
256 *addr
= 0x00F000F0; /* reset bank */
263 /*-----------------------------------------------------------------------
266 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
268 vu_long
*addr
= (vu_long
*)(info
->start
[0]);
269 int flag
, prot
, sect
, l_sect
;
270 ulong start
, now
, last
;
272 debug ("flash_erase: first: %d last: %d\n", s_first
, s_last
);
274 if ((s_first
< 0) || (s_first
> s_last
)) {
275 if (info
->flash_id
== FLASH_UNKNOWN
) {
276 printf ("- missing\n");
278 printf ("- no sectors to erase\n");
283 if ((info
->flash_id
== FLASH_UNKNOWN
) ||
284 (info
->flash_id
> FLASH_AMD_COMP
)) {
285 printf ("Can't erase unknown flash type %08lx - aborted\n",
291 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
292 if (info
->protect
[sect
]) {
298 printf ("- Warning: %d protected sectors will not be erased!\n",
306 /* Disable interrupts which might cause a timeout here */
307 flag
= disable_interrupts();
309 addr
[0x0555] = 0x00AA00AA;
310 addr
[0x02AA] = 0x00550055;
311 addr
[0x0555] = 0x00800080;
312 addr
[0x0555] = 0x00AA00AA;
313 addr
[0x02AA] = 0x00550055;
315 /* Start erase on unprotected sectors */
316 for (sect
= s_first
; sect
<=s_last
; sect
++) {
317 if (info
->protect
[sect
] == 0) { /* not protected */
318 addr
= (vu_long
*)(info
->start
[sect
]);
319 addr
[0] = 0x00300030;
324 /* re-enable interrupts if necessary */
328 /* wait at least 80us - let's wait 1 ms */
332 * We wait for the last triggered sector
337 start
= get_timer (0);
339 addr
= (vu_long
*)(info
->start
[l_sect
]);
340 while ((addr
[0] & 0x00800080) != 0x00800080) {
341 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
342 printf ("Timeout\n");
345 /* show that we're waiting */
346 if ((now
- last
) > 100000) { /* every second */
353 /* reset to read mode */
354 addr
= (volatile unsigned long *)info
->start
[0];
355 addr
[0] = 0x00F000F0; /* reset bank */
361 /*-----------------------------------------------------------------------
362 * Copy memory to flash, returns:
365 * 2 - Flash not erased
368 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
373 wp
= (addr
& ~3); /* get lower word aligned address */
376 * handle unaligned start bytes
378 if ((l
= addr
- wp
) != 0) {
380 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
381 data
= (data
<< 8) | (*(uchar
*)cp
);
383 for (; i
<4 && cnt
>0; ++i
) {
384 data
= (data
<< 8) | *src
++;
388 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
389 data
= (data
<< 8) | (*(uchar
*)cp
);
392 if ((rc
= write_word(info
, wp
, SWAP(data
))) != 0) {
399 * handle word aligned part
403 for (i
=0; i
<4; ++i
) {
404 data
= (data
<< 8) | *src
++;
406 if ((rc
= write_word(info
, wp
, SWAP(data
))) != 0) {
418 * handle unaligned tail bytes
421 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
422 data
= (data
<< 8) | *src
++;
425 for (; i
<4; ++i
, ++cp
) {
426 data
= (data
<< 8) | (*(uchar
*)cp
);
429 return (write_word(info
, wp
, SWAP(data
)));
432 /*-----------------------------------------------------------------------
433 * Write a word to Flash, returns:
436 * 2 - Flash not erased
438 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
)
440 vu_long
*addr
= (vu_long
*)(info
->start
[0]);
444 /* Check if Flash is (sufficiently) erased */
445 if ((*((vu_long
*)dest
) & data
) != data
) {
449 /* Disable interrupts which might cause a timeout here */
450 flag
= disable_interrupts();
452 addr
[0x0555] = 0x00AA00AA;
453 addr
[0x02AA] = 0x00550055;
454 addr
[0x0555] = 0x00A000A0;
456 *((vu_long
*)dest
) = data
;
458 /* re-enable interrupts if necessary */
462 /* data polling for D7 */
463 start
= get_timer (0);
464 while ((*((vu_long
*)dest
) & 0x00800080) != (data
& 0x00800080)) {
465 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {