]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/tqm5200/flash.c
2 * (C) Copyright 2003-2004
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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,
29 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
32 * CPU to flash interface is 32-bit, so make declaration accordingly
34 typedef unsigned long FLASH_PORT_WIDTH
;
35 typedef volatile unsigned long FLASH_PORT_WIDTHV
;
37 #define FPW FLASH_PORT_WIDTH
38 #define FPWV FLASH_PORT_WIDTHV
40 #define FLASH_CYCLE1 0x0555
41 #define FLASH_CYCLE2 0x02aa
43 /*-----------------------------------------------------------------------
46 static ulong
flash_get_size(FPWV
*addr
, flash_info_t
*info
);
47 static void flash_reset(flash_info_t
*info
);
48 static int write_word_amd(flash_info_t
*info
, FPWV
*dest
, FPW data
);
49 static flash_info_t
*flash_get_info(ulong base
);
51 /*-----------------------------------------------------------------------
54 * sets up flash_info and returns size of FLASH (bytes)
56 unsigned long flash_init (void)
58 unsigned long size
= 0;
59 extern void flash_preinit(void);
60 ulong flashbase
= CFG_FLASH_BASE
;
64 /* Init: no FLASHes known */
65 memset(&flash_info
[0], 0, sizeof(flash_info_t
));
68 flash_get_size((FPW
*)flashbase
, &flash_info
[0]);
70 size
= flash_info
[0].size
;
72 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
73 /* monitor protection ON by default */
74 flash_protect(FLAG_PROTECT_SET
,
76 CFG_MONITOR_BASE
+monitor_flash_len
-1,
77 flash_get_info(CFG_MONITOR_BASE
));
80 #ifdef CFG_ENV_IS_IN_FLASH
81 /* ENV protection ON by default */
82 flash_protect(FLAG_PROTECT_SET
,
84 CFG_ENV_ADDR
+CFG_ENV_SIZE
-1,
85 flash_get_info(CFG_ENV_ADDR
));
88 return size
? size
: 1;
91 /*-----------------------------------------------------------------------
93 static void flash_reset(flash_info_t
*info
)
95 FPWV
*base
= (FPWV
*)(info
->start
[0]);
97 /* Put FLASH back in read mode */
98 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
)
99 *base
= (FPW
)0x00FF00FF; /* Intel Read Mode */
100 else if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
)
101 *base
= (FPW
)0x00F000F0; /* AMD Read Mode */
104 /*-----------------------------------------------------------------------
107 static flash_info_t
*flash_get_info(ulong base
)
112 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++) {
113 info
= & flash_info
[i
];
114 if (info
->size
&& info
->start
[0] <= base
&&
115 base
<= info
->start
[0] + info
->size
- 1)
119 return i
== CFG_MAX_FLASH_BANKS
? 0 : info
;
122 /*-----------------------------------------------------------------------
125 void flash_print_info (flash_info_t
*info
)
129 if (info
->flash_id
== FLASH_UNKNOWN
) {
130 printf ("missing or unknown FLASH type\n");
134 switch (info
->flash_id
& FLASH_VENDMASK
) {
135 case FLASH_MAN_AMD
: printf ("AMD "); break;
136 case FLASH_MAN_BM
: printf ("BRIGHT MICRO "); break;
137 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
138 case FLASH_MAN_SST
: printf ("SST "); break;
139 case FLASH_MAN_STM
: printf ("STM "); break;
140 case FLASH_MAN_INTEL
: printf ("INTEL "); break;
141 default: printf ("Unknown Vendor "); break;
144 switch (info
->flash_id
& FLASH_TYPEMASK
) {
146 printf ("AM29LV128ML (128Mbit, uniform sector size)\n");
149 printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
152 printf ("Unknown Chip Type\n");
156 printf (" Size: %ld MB in %d Sectors\n",
160 printf (" Sector Start Addresses:");
162 for (i
=0; i
<info
->sector_count
; ++i
) {
168 info
->protect
[i
] ? " (RO)" : " ");
174 /*-----------------------------------------------------------------------
178 * The following code cannot be run from FLASH!
181 ulong
flash_get_size (FPWV
*addr
, flash_info_t
*info
)
184 ulong base
= (ulong
)addr
;
186 /* Write auto select command: read Manufacturer ID */
187 /* Write auto select command sequence and test FLASH answer */
188 addr
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* for AMD, Intel ignores this */
189 addr
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* for AMD, Intel ignores this */
190 addr
[FLASH_CYCLE1
] = (FPW
)0x00900090; /* selects Intel or AMD */
192 /* The manufacturer codes are only 1 byte, so just use 1 byte.
193 * This works for any bus width and any FLASH device width.
196 switch (addr
[0] & 0xff) {
198 case (uchar
)AMD_MANUFACT
:
199 debug ("Manufacturer: AMD (Spansion)\n");
200 info
->flash_id
= FLASH_MAN_AMD
;
203 case (uchar
)INTEL_MANUFACT
:
204 debug ("Manufacturer: Intel (not supported yet)\n");
205 info
->flash_id
= FLASH_MAN_INTEL
;
209 info
->flash_id
= FLASH_UNKNOWN
;
210 info
->sector_count
= 0;
215 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
216 if (info
->flash_id
!= FLASH_UNKNOWN
) switch ((FPW
)addr
[1]) {
218 case (FPW
)AMD_ID_LV160B
:
219 debug ("Chip: AM29LV160MB\n");
220 info
->flash_id
+= FLASH_AM160B
;
221 info
->sector_count
= 35;
222 info
->size
= 0x00400000;
224 * The first 4 sectors are 16 kB, 8 kB, 8 kB and 32 kB, all
225 * the other ones are 64 kB
227 info
->start
[0] = base
+ 0x00000000;
228 info
->start
[1] = base
+ 0x00008000;
229 info
->start
[2] = base
+ 0x0000C000;
230 info
->start
[3] = base
+ 0x00010000;
231 for( i
= 4; i
< info
->sector_count
; i
++ )
233 base
+ (i
* 2 * (64 << 10)) - 0x00060000;
237 debug ("Mirror Bit flash: addr[14] = %08lX addr[15] = %08lX\n",
241 case AMD_ID_LV128U_2
:
242 if (addr
[15] != AMD_ID_LV128U_3
) {
243 debug ("Chip: AM29LVxxxM -> unknown\n");
244 info
->flash_id
= FLASH_UNKNOWN
;
245 info
->sector_count
= 0;
248 debug ("Chip: AM29LV128M\n");
249 info
->flash_id
+= FLASH_AMLV128U
;
250 info
->sector_count
= 256;
251 info
->size
= 0x02000000;
252 for (i
= 0; i
< info
->sector_count
; i
++) {
253 info
->start
[i
] = base
;
257 break; /* => 32 MB */
259 debug ("Chip: *** unknown ***\n");
260 info
->flash_id
= FLASH_UNKNOWN
;
261 info
->sector_count
= 0;
268 info
->flash_id
= FLASH_UNKNOWN
;
269 info
->sector_count
= 0;
273 /* Put FLASH back in read mode */
279 /*-----------------------------------------------------------------------
282 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
284 vu_long
*addr
= (vu_long
*)(info
->start
[0]);
285 int flag
, prot
, sect
, l_sect
;
286 ulong start
, now
, last
;
288 debug ("flash_erase: first: %d last: %d\n", s_first
, s_last
);
290 if ((s_first
< 0) || (s_first
> s_last
)) {
291 if (info
->flash_id
== FLASH_UNKNOWN
) {
292 printf ("- missing\n");
294 printf ("- no sectors to erase\n");
299 if ((info
->flash_id
== FLASH_UNKNOWN
) ||
300 (info
->flash_id
> FLASH_AMD_COMP
)) {
301 printf ("Can't erase unknown flash type %08lx - aborted\n",
307 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
308 if (info
->protect
[sect
]) {
314 printf ("- Warning: %d protected sectors will not be erased!\n",
322 /* Disable interrupts which might cause a timeout here */
323 flag
= disable_interrupts();
325 addr
[0x0555] = 0x00AA00AA;
326 addr
[0x02AA] = 0x00550055;
327 addr
[0x0555] = 0x00800080;
328 addr
[0x0555] = 0x00AA00AA;
329 addr
[0x02AA] = 0x00550055;
331 /* Start erase on unprotected sectors */
332 for (sect
= s_first
; sect
<=s_last
; sect
++) {
333 if (info
->protect
[sect
] == 0) { /* not protected */
334 addr
= (vu_long
*)(info
->start
[sect
]);
335 addr
[0] = 0x00300030;
340 /* re-enable interrupts if necessary */
344 /* wait at least 80us - let's wait 1 ms */
348 * We wait for the last triggered sector
353 start
= get_timer (0);
355 addr
= (vu_long
*)(info
->start
[l_sect
]);
356 while ((addr
[0] & 0x00800080) != 0x00800080) {
357 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
358 printf ("Timeout\n");
361 /* show that we're waiting */
362 if ((now
- last
) > 1000) { /* every second */
369 /* reset to read mode */
370 addr
= (volatile unsigned long *)info
->start
[0];
371 addr
[0] = 0x00F000F0; /* reset bank */
377 /*-----------------------------------------------------------------------
378 * Copy memory to flash, returns:
381 * 2 - Flash not erased
384 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
390 * Get lower word aligned address. Assumes 32 bit flash bus width.
395 * handle unaligned start bytes
397 if ((l
= addr
- wp
) != 0) {
399 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
400 data
= (data
<< 8) | (*(uchar
*)cp
);
402 for (; i
<4 && cnt
>0; ++i
) {
403 data
= (data
<< 8) | *src
++;
407 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
408 data
= (data
<< 8) | (*(uchar
*)cp
);
411 if ((rc
= write_word_amd(info
, (FPW
*)wp
, data
)) != 0) {
418 * handle word aligned part
422 for (i
=0; i
<4; ++i
) {
423 data
= (data
<< 8) | *src
++;
425 if ((rc
= write_word_amd(info
, (FPW
*)wp
, data
)) != 0) {
437 * handle unaligned tail bytes
440 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
441 data
= (data
<< 8) | *src
++;
444 for (; i
<4; ++i
, ++cp
) {
445 data
= (data
<< 8) | (*(uchar
*)cp
);
448 return (write_word_amd(info
, (FPW
*)wp
, data
));
451 /*-----------------------------------------------------------------------
452 * Write a word to Flash for AMD FLASH
453 * A word is 16 or 32 bits, whichever the bus width of the flash bank
454 * (not an individual chip) is.
459 * 2 - Flash not erased
461 static int write_word_amd (flash_info_t
*info
, FPWV
*dest
, FPW data
)
465 FPWV
*base
; /* first address in flash bank */
467 /* Check if Flash is (sufficiently) erased */
468 if ((*dest
& data
) != data
) {
472 base
= (FPWV
*)(info
->start
[0]);
474 /* Disable interrupts which might cause a timeout here */
475 flag
= disable_interrupts();
477 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
478 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
479 base
[FLASH_CYCLE1
] = (FPW
)0x00A000A0; /* selects program mode */
481 *dest
= data
; /* start programming the data */
483 /* re-enable interrupts if necessary */
487 start
= get_timer (0);
489 /* data polling for D7 */
490 while ((*dest
& (FPW
)0x00800080) != (data
& (FPW
)0x00800080)) {
491 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
492 *dest
= (FPW
)0x00F000F0; /* reset bank */