]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/icecube/flash.c
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 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
28 /* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
29 * has nothing to do with the flash chip being 8-bit or 16-bit.
31 #ifdef CONFIG_FLASH_16BIT
32 typedef unsigned short FLASH_PORT_WIDTH
;
33 typedef volatile unsigned short FLASH_PORT_WIDTHV
;
34 #define FLASH_ID_MASK 0xFFFF
36 typedef unsigned char FLASH_PORT_WIDTH
;
37 typedef volatile unsigned char FLASH_PORT_WIDTHV
;
38 #define FLASH_ID_MASK 0xFF
41 #define FPW FLASH_PORT_WIDTH
42 #define FPWV FLASH_PORT_WIDTHV
44 #define ORMASK(size) ((-size) & OR_AM_MSK)
46 #define FLASH_CYCLE1 0x0555
47 #define FLASH_CYCLE2 0x02aa
49 /*-----------------------------------------------------------------------
52 static ulong
flash_get_size(FPWV
*addr
, flash_info_t
*info
);
53 static void flash_reset(flash_info_t
*info
);
54 static int write_word_amd(flash_info_t
*info
, FPWV
*dest
, FPW data
);
55 static flash_info_t
*flash_get_info(ulong base
);
57 /*-----------------------------------------------------------------------
60 * sets up flash_info and returns size of FLASH (bytes)
62 unsigned long flash_init (void)
64 unsigned long size
= 0;
66 extern void flash_preinit(void);
67 extern void flash_afterinit(ulong
);
68 ulong flashbase
= CFG_FLASH_BASE
;
72 /* Init: no FLASHes known */
73 for (i
=0; i
< CFG_MAX_FLASH_BANKS
; ++i
) {
74 memset(&flash_info
[i
], 0, sizeof(flash_info_t
));
77 flash_get_size((FPW
*)flashbase
, &flash_info
[i
]);
79 size
+= flash_info
[i
].size
;
80 flashbase
+= 0x800000;
82 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
83 /* monitor protection ON by default */
84 flash_protect(FLAG_PROTECT_SET
,
86 CFG_MONITOR_BASE
+monitor_flash_len
-1,
87 flash_get_info(CFG_MONITOR_BASE
));
90 #ifdef CFG_ENV_IS_IN_FLASH
91 /* ENV protection ON by default */
92 flash_protect(FLAG_PROTECT_SET
,
94 CFG_ENV_ADDR
+CFG_ENV_SIZE
-1,
95 flash_get_info(CFG_ENV_ADDR
));
99 flash_afterinit(size
);
100 return size
? size
: 1;
103 /*-----------------------------------------------------------------------
105 static void flash_reset(flash_info_t
*info
)
107 FPWV
*base
= (FPWV
*)(info
->start
[0]);
109 /* Put FLASH back in read mode */
110 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
)
111 *base
= (FPW
)0x00FF00FF; /* Intel Read Mode */
112 else if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
)
113 *base
= (FPW
)0x00F000F0; /* AMD Read Mode */
116 /*-----------------------------------------------------------------------
119 static flash_info_t
*flash_get_info(ulong base
)
124 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++) {
125 info
= & flash_info
[i
];
127 info
->start
[0] <= base
&& base
<= info
->start
[0] + info
->size
- 1)
131 return i
== CFG_MAX_FLASH_BANKS
? 0 : info
;
134 /*-----------------------------------------------------------------------
137 void flash_print_info (flash_info_t
*info
)
143 uchar botbootletter
[] = "B";
144 uchar topbootletter
[] = "T";
145 uchar botboottype
[] = "bottom boot sector";
146 uchar topboottype
[] = "top boot sector";
148 if (info
->flash_id
== FLASH_UNKNOWN
) {
149 printf ("missing or unknown FLASH type\n");
153 switch (info
->flash_id
& FLASH_VENDMASK
) {
154 case FLASH_MAN_AMD
: printf ("AMD "); break;
155 case FLASH_MAN_BM
: printf ("BRIGHT MICRO "); break;
156 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
157 case FLASH_MAN_SST
: printf ("SST "); break;
158 case FLASH_MAN_STM
: printf ("STM "); break;
159 case FLASH_MAN_INTEL
: printf ("INTEL "); break;
160 default: printf ("Unknown Vendor "); break;
163 /* check for top or bottom boot, if it applies */
164 if (info
->flash_id
& FLASH_BTYPE
) {
165 boottype
= botboottype
;
166 bootletter
= botbootletter
;
169 boottype
= topboottype
;
170 bootletter
= topbootletter
;
173 switch (info
->flash_id
& FLASH_TYPEMASK
) {
174 case FLASH_AMDLV065D
:
175 fmt
= "29LV065 (64 Mbit, uniform sectors)\n";
178 fmt
= "Unknown Chip Type\n";
182 printf (fmt
, bootletter
, boottype
);
184 printf (" Size: %ld MB in %d Sectors\n",
188 printf (" Sector Start Addresses:");
190 for (i
=0; i
<info
->sector_count
; ++i
) {
195 printf (" %08lX%s", info
->start
[i
],
196 info
->protect
[i
] ? " (RO)" : " ");
202 /*-----------------------------------------------------------------------
206 * The following code cannot be run from FLASH!
209 ulong
flash_get_size (FPWV
*addr
, flash_info_t
*info
)
214 /* Write auto select command: read Manufacturer ID */
215 /* Write auto select command sequence and test FLASH answer */
216 addr
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* for AMD, Intel ignores this */
217 addr
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* for AMD, Intel ignores this */
218 addr
[FLASH_CYCLE1
] = (FPW
)0x00900090; /* selects Intel or AMD */
220 /* The manufacturer codes are only 1 byte, so just use 1 byte.
221 * This works for any bus width and any FLASH device width.
224 switch (addr
[0] & 0xff) {
226 case (uchar
)AMD_MANUFACT
:
227 info
->flash_id
= FLASH_MAN_AMD
;
230 case (uchar
)INTEL_MANUFACT
:
231 info
->flash_id
= FLASH_MAN_INTEL
;
235 info
->flash_id
= FLASH_UNKNOWN
;
236 info
->sector_count
= 0;
241 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
242 if (info
->flash_id
!= FLASH_UNKNOWN
) switch ((FPW
)addr
[1]) {
244 case (FPW
)AMD_ID_LV065D
:
245 info
->flash_id
+= FLASH_AMDLV065D
;
246 info
->sector_count
= 128;
247 info
->size
= 0x00800000;
248 for( i
= 0; i
< info
->sector_count
; i
++ )
249 info
->start
[i
] = (ulong
)addr
+ (i
* 0x10000);
250 break; /* => 8 or 16 MB */
253 info
->flash_id
= FLASH_UNKNOWN
;
254 info
->sector_count
= 0;
256 return (0); /* => no or unknown flash */
259 /* test for real flash at bank 1 */
260 addr2
= (FPW
*)((ulong
)addr
| 0x800000);
262 ((addr2
[0] & 0xff) == (addr
[0] & 0xff)) && ((FPW
)addr2
[1] == (FPW
)addr
[1])) {
263 /* Seems 2 banks are the same space (8Mb chip is installed,
264 * J24 in default position (CS0)). Disable this (first) bank.
266 info
->flash_id
= FLASH_UNKNOWN
;
267 info
->sector_count
= 0;
270 /* Put FLASH back in read mode */
276 /*-----------------------------------------------------------------------
279 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
282 int flag
, prot
, sect
;
283 int intel
= (info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
;
284 ulong start
, now
, last
;
287 if ((s_first
< 0) || (s_first
> s_last
)) {
288 if (info
->flash_id
== FLASH_UNKNOWN
) {
289 printf ("- missing\n");
291 printf ("- no sectors to erase\n");
296 switch (info
->flash_id
& FLASH_TYPEMASK
) {
297 case FLASH_AMDLV065D
:
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 /* Start erase on unprotected sectors */
323 for (sect
= s_first
; sect
<=s_last
&& rcode
== 0; sect
++) {
325 if (info
->protect
[sect
] != 0) /* protected, skip it */
328 /* Disable interrupts which might cause a timeout here */
329 flag
= disable_interrupts();
331 addr
= (FPWV
*)(info
->start
[sect
]);
333 *addr
= (FPW
)0x00500050; /* clear status register */
334 *addr
= (FPW
)0x00200020; /* erase setup */
335 *addr
= (FPW
)0x00D000D0; /* erase confirm */
338 /* must be AMD style if not Intel */
339 FPWV
*base
; /* first address in bank */
341 base
= (FPWV
*)(info
->start
[0]);
342 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
343 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
344 base
[FLASH_CYCLE1
] = (FPW
)0x00800080; /* erase mode */
345 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
346 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
347 *addr
= (FPW
)0x00300030; /* erase sector */
350 /* re-enable interrupts if necessary */
354 start
= get_timer(0);
356 /* wait at least 50us for AMD, 80us for Intel.
361 while ((*addr
& (FPW
)0x00800080) != (FPW
)0x00800080) {
362 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
363 printf ("Timeout\n");
367 *addr
= (FPW
)0x00B000B0;
370 flash_reset(info
); /* reset to read mode */
371 rcode
= 1; /* failed */
375 /* show that we're waiting */
376 if ((get_timer(last
)) > CFG_HZ
) {/* every second */
382 /* show that we're waiting */
383 if ((get_timer(last
)) > CFG_HZ
) { /* every second */
388 flash_reset(info
); /* reset to read mode */
395 /*-----------------------------------------------------------------------
396 * Copy memory to flash, returns:
399 * 2 - Flash not erased
401 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
403 FPW data
= 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
404 int bytes
; /* number of bytes to program in current word */
405 int left
; /* number of bytes left to program */
408 for (left
= cnt
, res
= 0;
409 left
> 0 && res
== 0;
410 addr
+= sizeof(data
), left
-= sizeof(data
) - bytes
) {
412 bytes
= addr
& (sizeof(data
) - 1);
413 addr
&= ~(sizeof(data
) - 1);
415 /* combine source and destination data so can program
416 * an entire word of 16 or 32 bits
418 for (i
= 0; i
< sizeof(data
); i
++) {
420 if (i
< bytes
|| i
- bytes
>= left
)
421 data
+= *((uchar
*)addr
+ i
);
426 /* write one word to the flash */
427 switch (info
->flash_id
& FLASH_VENDMASK
) {
429 res
= write_word_amd(info
, (FPWV
*)addr
, data
);
432 /* unknown flash type, error! */
433 printf ("missing or unknown FLASH type\n");
434 res
= 1; /* not really a timeout, but gives error */
442 /*-----------------------------------------------------------------------
443 * Write a word to Flash for AMD FLASH
444 * A word is 16 or 32 bits, whichever the bus width of the flash bank
445 * (not an individual chip) is.
450 * 2 - Flash not erased
452 static int write_word_amd (flash_info_t
*info
, FPWV
*dest
, FPW data
)
456 int res
= 0; /* result, assume success */
457 FPWV
*base
; /* first address in flash bank */
459 /* Check if Flash is (sufficiently) erased */
460 if ((*dest
& data
) != data
) {
465 base
= (FPWV
*)(info
->start
[0]);
467 /* Disable interrupts which might cause a timeout here */
468 flag
= disable_interrupts();
470 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
471 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
472 base
[FLASH_CYCLE1
] = (FPW
)0x00A000A0; /* selects program mode */
474 *dest
= data
; /* start programming the data */
476 /* re-enable interrupts if necessary */
480 start
= get_timer (0);
482 /* data polling for D7 */
483 while (res
== 0 && (*dest
& (FPW
)0x00800080) != (data
& (FPW
)0x00800080)) {
484 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
485 *dest
= (FPW
)0x00F000F0; /* reset bank */