]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/esd/pf5200/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 typedef unsigned short FLASH_PORT_WIDTH
;
29 typedef volatile unsigned short FLASH_PORT_WIDTHV
;
31 #define FLASH_ID_MASK 0x00FF
33 #define FPW FLASH_PORT_WIDTH
34 #define FPWV FLASH_PORT_WIDTHV
36 #define FLASH_CYCLE1 0x0555
37 #define FLASH_CYCLE2 0x0aaa
38 #define FLASH_ID1 0x00
39 #define FLASH_ID2 0x01
40 #define FLASH_ID3 0x0E
41 #define FLASH_ID4 0x0F
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;
60 extern void flash_preinit(void);
61 extern void flash_afterinit(uint
, ulong
, ulong
);
63 ulong flashbase
= CFG_FLASH_BASE
;
67 /* There is only ONE FLASH device */
68 memset(&flash_info
[i
], 0, sizeof(flash_info_t
));
69 flash_info
[i
].size
= flash_get_size((FPW
*) flashbase
, &flash_info
[i
]);
70 size
+= flash_info
[i
].size
;
72 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
73 /* monitor protection ON by default */
74 flash_protect(FLAG_PROTECT_SET
, CFG_MONITOR_BASE
,
75 CFG_MONITOR_BASE
+ monitor_flash_len
- 1,
76 flash_get_info(CFG_MONITOR_BASE
));
79 #ifdef CFG_ENV_IS_IN_FLASH
80 /* ENV protection ON by default */
81 flash_protect(FLAG_PROTECT_SET
, CFG_ENV_ADDR
,
82 CFG_ENV_ADDR
+ CFG_ENV_SIZE
- 1,
83 flash_get_info(CFG_ENV_ADDR
));
86 flash_afterinit(i
, flash_info
[i
].start
[0], flash_info
[i
].size
);
87 return size
? size
: 1;
90 /*-----------------------------------------------------------------------
92 static void flash_reset(flash_info_t
* info
) {
93 FPWV
*base
= (FPWV
*) (info
->start
[0]);
95 /* Put FLASH back in read mode */
96 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
) {
97 *base
= (FPW
) 0x00FF00FF; /* Intel Read Mode */
98 } else if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
) {
99 *base
= (FPW
) 0x00F000F0; /* AMD Read Mode */
103 /*-----------------------------------------------------------------------
106 static flash_info_t
*flash_get_info(ulong base
) {
110 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++) {
111 info
= &flash_info
[i
];
112 if ((info
->size
) && (info
->start
[0] <= base
)
113 && (base
<= info
->start
[0] + info
->size
- 1)) {
117 return (i
== CFG_MAX_FLASH_BANKS
? 0 : info
);
120 /*-----------------------------------------------------------------------
123 void flash_print_info(flash_info_t
* info
) {
127 if (info
->flash_id
== FLASH_UNKNOWN
) {
128 printf("missing or unknown FLASH type\n");
132 switch (info
->flash_id
& FLASH_VENDMASK
) {
137 printf("Unknown Vendor ");
141 switch (info
->flash_id
& FLASH_TYPEMASK
) {
143 fmt
= "29LV256M (256 Mbit)\n";
146 fmt
= "Unknown Chip Type\n";
151 printf(" Size: %ld MB in %d Sectors\n", info
->size
>> 20,
153 printf(" Sector Start Addresses:");
155 for (i
= 0; i
< info
->sector_count
; ++i
) {
158 ulong
*flash
= (unsigned long *)info
->start
[i
];
165 * Check if whole sector is erased
169 (info
->sector_count
- 1)) ? (info
->start
[i
+ 1] -
170 info
->start
[i
]) >> 2 : (info
->
180 for (flash
= (unsigned long *)info
->start
[i
], erased
= 1;
181 (flash
!= (unsigned long *)info
->start
[i
] + size
)
182 && erased
; flash
++) {
183 erased
= *flash
== ~0x0UL
;
185 printf(" %08lX %s %s", info
->start
[i
], erased
? "E" : " ",
186 info
->protect
[i
] ? "(RO)" : " ");
192 /*-----------------------------------------------------------------------
196 * The following code cannot be run from FLASH!
199 ulong
flash_get_size(FPWV
* addr
, flash_info_t
* info
) {
202 /* Write auto select command: read Manufacturer ID */
203 /* Write auto select command sequence and test FLASH answer */
204 addr
[FLASH_CYCLE1
] = (FPW
) 0x00AA00AA; /* for AMD, Intel ignores this */
205 addr
[FLASH_CYCLE2
] = (FPW
) 0x00550055; /* for AMD, Intel ignores this */
206 addr
[FLASH_CYCLE1
] = (FPW
) 0x00900090; /* selects Intel or AMD */
208 /* The manufacturer codes are only 1 byte, so just use 1 byte. */
209 /* This works for any bus width and any FLASH device width. */
211 switch (addr
[FLASH_ID1
] & 0x00ff) {
212 case (uchar
) AMD_MANUFACT
:
213 info
->flash_id
= FLASH_MAN_AMD
;
216 printf("unknown vendor=%x ", addr
[FLASH_ID1
] & 0xff);
217 info
->flash_id
= FLASH_UNKNOWN
;
218 info
->sector_count
= 0;
223 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
224 if (info
->flash_id
!= FLASH_UNKNOWN
) {
225 switch ((FPW
) addr
[FLASH_ID2
]) {
226 case (FPW
) AMD_ID_MIRROR
:
227 /* MIRROR BIT FLASH, read more ID bytes */
228 if ((FPW
) addr
[FLASH_ID3
] == (FPW
) AMD_ID_LV256U_2
229 && (FPW
) addr
[FLASH_ID4
] == (FPW
) AMD_ID_LV256U_3
) {
230 /* attention: only the first 16 MB will be used in u-boot */
231 info
->flash_id
+= FLASH_AMLV256U
;
232 info
->sector_count
= 512;
233 info
->size
= 0x02000000;
234 for (i
= 0; i
< info
->sector_count
; i
++) {
236 (ulong
) addr
+ 0x10000 * i
;
240 /* fall thru to here ! */
242 printf("unknown AMD device=%x %x %x",
243 (FPW
) addr
[FLASH_ID2
], (FPW
) addr
[FLASH_ID3
],
244 (FPW
) addr
[FLASH_ID4
]);
245 info
->flash_id
= FLASH_UNKNOWN
;
246 info
->sector_count
= 0;
247 info
->size
= 0x800000;
251 /* Put FLASH back in read mode */
257 /*-----------------------------------------------------------------------
260 int flash_erase(flash_info_t
* info
, int s_first
, int s_last
) {
262 int flag
, prot
, sect
;
263 int intel
= (info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
;
264 ulong start
, now
, last
;
267 if ((s_first
< 0) || (s_first
> s_last
)) {
268 if (info
->flash_id
== FLASH_UNKNOWN
) {
269 printf("- missing\n");
271 printf("- no sectors to erase\n");
276 switch (info
->flash_id
& FLASH_TYPEMASK
) {
281 printf("Can't erase unknown flash type %08lx - aborted\n",
287 for (sect
= s_first
; sect
<= s_last
; ++sect
) {
288 if (info
->protect
[sect
]) {
294 printf("- Warning: %d protected sectors will not be erased!\n",
302 /* Start erase on unprotected sectors */
303 for (sect
= s_first
; sect
<= s_last
&& rcode
== 0; sect
++) {
304 if (info
->protect
[sect
] != 0) { /* protected, skip it */
307 /* Disable interrupts which might cause a timeout here */
308 flag
= disable_interrupts();
310 addr
= (FPWV
*) (info
->start
[sect
]);
312 *addr
= (FPW
) 0x00500050; /* clear status register */
313 *addr
= (FPW
) 0x00200020; /* erase setup */
314 *addr
= (FPW
) 0x00D000D0; /* erase confirm */
316 /* must be AMD style if not Intel */
317 FPWV
*base
; /* first address in bank */
319 base
= (FPWV
*) (info
->start
[0]);
320 base
[FLASH_CYCLE1
] = (FPW
) 0x00AA00AA; /* unlock */
321 base
[FLASH_CYCLE2
] = (FPW
) 0x00550055; /* unlock */
322 base
[FLASH_CYCLE1
] = (FPW
) 0x00800080; /* erase mode */
323 base
[FLASH_CYCLE1
] = (FPW
) 0x00AA00AA; /* unlock */
324 base
[FLASH_CYCLE2
] = (FPW
) 0x00550055; /* unlock */
325 *addr
= (FPW
) 0x00300030; /* erase sector */
328 /* re-enable interrupts if necessary */
332 start
= get_timer(0);
334 /* wait at least 50us for AMD, 80us for Intel. */
335 /* Let's wait 1 ms. */
338 while ((*addr
& (FPW
) 0x00800080) != (FPW
) 0x00800080) {
339 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
343 *addr
= (FPW
) 0x00B000B0;
345 flash_reset(info
); /* reset to read mode */
346 rcode
= 1; /* failed */
349 /* show that we're waiting */
350 if ((get_timer(last
)) > CFG_HZ
) {
356 /* show that we're waiting */
357 if ((get_timer(last
)) > CFG_HZ
) {
362 flash_reset(info
); /* reset to read mode */
368 /*-----------------------------------------------------------------------
369 * Copy memory to flash, returns:
372 * 2 - Flash not erased
374 int write_buff(flash_info_t
* info
, uchar
* src
, ulong addr
, ulong cnt
)
376 FPW data
= 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
377 int bytes
; /* number of bytes to program in current word */
378 int left
; /* number of bytes left to program */
381 for (left
= cnt
, res
= 0;
382 left
> 0 && res
== 0;
383 addr
+= sizeof(data
), left
-= sizeof(data
) - bytes
) {
385 bytes
= addr
& (sizeof(data
) - 1);
386 addr
&= ~(sizeof(data
) - 1);
388 /* combine source and destination data so can program
389 * an entire word of 16 or 32 bits
391 for (i
= 0; i
< sizeof(data
); i
++) {
393 if (i
< bytes
|| i
- bytes
>= left
)
394 data
+= *((uchar
*) addr
+ i
);
399 /* write one word to the flash */
400 switch (info
->flash_id
& FLASH_VENDMASK
) {
402 res
= write_word_amd(info
, (FPWV
*) addr
, data
);
405 /* unknown flash type, error! */
406 printf("missing or unknown FLASH type\n");
407 res
= 1; /* not really a timeout, but gives error */
414 /*-----------------------------------------------------------------------
415 * Write a word to Flash for AMD FLASH
416 * A word is 16 or 32 bits, whichever the bus width of the flash bank
417 * (not an individual chip) is.
422 * 2 - Flash not erased
424 static int write_word_amd(flash_info_t
* info
, FPWV
* dest
, FPW data
) {
427 int res
= 0; /* result, assume success */
428 FPWV
*base
; /* first address in flash bank */
430 /* Check if Flash is (sufficiently) erased */
431 if ((*dest
& data
) != data
) {
435 base
= (FPWV
*) (info
->start
[0]);
437 /* Disable interrupts which might cause a timeout here */
438 flag
= disable_interrupts();
440 base
[FLASH_CYCLE1
] = (FPW
) 0x00AA00AA; /* unlock */
441 base
[FLASH_CYCLE2
] = (FPW
) 0x00550055; /* unlock */
442 base
[FLASH_CYCLE1
] = (FPW
) 0x00A000A0; /* selects program mode */
444 *dest
= data
; /* start programming the data */
446 /* re-enable interrupts if necessary */
450 start
= get_timer(0);
452 /* data polling for D7 */
454 && (*dest
& (FPW
) 0x00800080) != (data
& (FPW
) 0x00800080)) {
455 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
456 *dest
= (FPW
) 0x00F000F0; /* reset bank */