]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/sc520_cdp/flash.c
2 * (C) Copyright 2002, 2003
3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
6 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 * Alex Zuepke <azu@sysgo.de>
9 * See file CREDITS for list of people who contributed to this
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
31 #include <asm/ic/sc520.h>
33 #define PROBE_BUFFER_SIZE 1024
34 static unsigned char buffer
[PROBE_BUFFER_SIZE
];
36 #define SC520_MAX_FLASH_BANKS 3
37 #define SC520_FLASH_BANK0_BASE 0x38000000 /* BOOTCS */
38 #define SC520_FLASH_BANK1_BASE 0x30000000 /* ROMCS0 */
39 #define SC520_FLASH_BANK2_BASE 0x28000000 /* ROMCS1 */
40 #define SC520_FLASH_BANKSIZE 0x8000000
42 #define AMD29LV016B_SIZE 0x200000
43 #define AMD29LV016B_SECTORS 32
45 flash_info_t flash_info
[SC520_MAX_FLASH_BANKS
];
51 /*-----------------------------------------------------------------------
55 static u32
_probe_flash(u32 addr
, u32 bw
, int il
)
59 /* First do an unlock cycle for the benefit of
60 * devices that need it */
65 *(volatile u8
*)(addr
+0x5555) = 0xaa;
66 *(volatile u8
*)(addr
+0x2aaa) = 0x55;
67 *(volatile u8
*)(addr
+0x5555) = 0x90;
70 result
= *(volatile u8
*)addr
;
74 result
|= *(volatile u8
*)(addr
+2);
76 /* Return device to data mode */
77 *(volatile u8
*)addr
= 0xff;
78 *(volatile u8
*)(addr
+0x5555), 0xf0;
82 *(volatile u16
*)(addr
+0xaaaa) = 0xaaaa;
83 *(volatile u16
*)(addr
+0x5554) = 0x5555;
85 /* Issue identification command */
87 *(volatile u16
*)(addr
+0xaaaa) = 0x9090;
90 result
= *(volatile u8
*)addr
;
94 result
|= *(volatile u8
*)(addr
+2);
96 /* Return device to data mode */
97 *(volatile u16
*)addr
= 0xffff;
98 *(volatile u16
*)(addr
+0xaaaa), 0xf0f0;
101 *(volatile u8
*)(addr
+0xaaaa) = 0x90;
103 result
= *(volatile u16
*)addr
;
107 result
|= *(volatile u16
*)(addr
+2);
109 /* Return device to data mode */
110 *(volatile u8
*)addr
= 0xff;
111 *(volatile u8
*)(addr
+0xaaaa), 0xf0;
117 *(volatile u32
*)(addr
+0x5554) = 0xaaaaaaaa;
118 *(volatile u32
*)(addr
+0xaaa8) = 0x55555555;
122 /* Issue identification command */
123 *(volatile u8
*)(addr
+0x5554) = 0x90;
126 result
= *(volatile u16
*)addr
;
130 result
|= *(volatile u16
*)(addr
+4);
132 /* Return device to data mode */
133 *(volatile u8
*)addr
= 0xff;
134 *(volatile u8
*)(addr
+0x5554), 0xf0;
138 /* Issue identification command */
139 *(volatile u32
*)(addr
+ 0x5554) = 0x00900090;
142 result
= *(volatile u16
*)addr
;
146 result
|= *(volatile u16
*)(addr
+4);
148 /* Return device to data mode */
149 *(volatile u32
*)addr
= 0x00ff00ff;
150 *(volatile u32
*)(addr
+0x5554), 0x00f000f0;
154 /* Issue identification command */
155 *(volatile u32
*)(addr
+0x5554) = 0x90909090;
158 result
= *(volatile u8
*)addr
;
162 result
|= *(volatile u8
*)(addr
+4);
164 /* Return device to data mode */
165 *(volatile u32
*)addr
= 0xffffffff;
166 *(volatile u32
*)(addr
+0x5554), 0xf0f0f0f0;
177 extern int _probe_flash_end
;
178 asm ("_probe_flash_end:\n"
181 static int identify_flash(unsigned address
, int width
)
189 u32 (*_probe_flash_ptr
)(u32 a
, u32 bw
, int il
);
191 size
= (unsigned)&_probe_flash_end
- (unsigned)_probe_flash
;
193 if (size
> PROBE_BUFFER_SIZE
) {
194 printf("_probe_flash() routine too large (%d) %p - %p\n",
195 size
, &_probe_flash_end
, _probe_flash
);
199 memcpy(buffer
, _probe_flash
, size
);
200 _probe_flash_ptr
= (void*)buffer
;
202 is
= disable_interrupts();
203 res
= _probe_flash_ptr(address
, width
, 1);
210 device
= res
& 0xffff;
216 ulong
flash_init(void)
221 for (i
= 0; i
< SC520_MAX_FLASH_BANKS
; i
++) {
226 memset(flash_info
[i
].protect
, 0, CFG_MAX_FLASH_SECT
);
229 flashbase
= SC520_FLASH_BANK0_BASE
;
232 flashbase
= SC520_FLASH_BANK1_BASE
;
235 flashbase
= SC520_FLASH_BANK2_BASE
;
238 panic("configured to many flash banks!\n");
241 id
= identify_flash(flashbase
, 4);
242 switch (id
& 0x00ff00ff) {
244 /* 29LV016B/29LV017B */
245 flash_info
[i
].flash_id
=
246 (AMD_MANUFACT
& FLASH_VENDMASK
) |
247 (AMD_ID_LV016B
& FLASH_TYPEMASK
);
249 flash_info
[i
].size
= AMD29LV016B_SIZE
*4;
250 flash_info
[i
].sector_count
= AMD29LV016B_SECTORS
;
251 sectsize
= (AMD29LV016B_SIZE
*4)/AMD29LV016B_SECTORS
;
252 printf("Bank %d: 4 x AMD 29LV017B\n", i
);
257 printf("Bank %d have unknown flash %08x\n", i
, id
);
258 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
262 for (j
= 0; j
< flash_info
[i
].sector_count
; j
++) {
263 flash_info
[i
].start
[j
] = flashbase
+ j
* sectsize
;
265 size
+= flash_info
[i
].size
;
267 flash_protect(FLAG_PROTECT_CLEAR
,
268 flash_info
[i
].start
[0],
269 flash_info
[i
].start
[0] + flash_info
[i
].size
- 1,
274 * Protect monitor and environment sectors
276 flash_protect(FLAG_PROTECT_SET
,
281 flash_protect(FLAG_PROTECT_SET
,
283 CFG_ENV_ADDR
+ CFG_ENV_SIZE
- 1,
289 /*-----------------------------------------------------------------------
291 void flash_print_info(flash_info_t
*info
)
295 switch (info
->flash_id
& FLASH_VENDMASK
) {
297 case (AMD_MANUFACT
& FLASH_VENDMASK
):
299 switch (info
->flash_id
& FLASH_TYPEMASK
) {
300 case (AMD_ID_LV016B
& FLASH_TYPEMASK
):
301 printf("4x AMD29LV017B (4x16Mbit)\n");
304 printf("Unknown Chip Type\n");
311 printf("Unknown Vendor ");
316 printf(" Size: %ld MB in %d Sectors\n",
317 info
->size
>> 20, info
->sector_count
);
319 printf(" Sector Start Addresses:");
320 for (i
= 0; i
< info
->sector_count
; i
++) {
324 printf (" %08lX%s", info
->start
[i
],
325 info
->protect
[i
] ? " (RO)" : " ");
332 /*-----------------------------------------------------------------------
335 /* this needs to be inlined, the SWTMRMMILLI register is reset by each read */
336 #define __udelay(delay) \
341 micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
345 milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
346 micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \
348 if ((delay) <= (micro + (milli * 1000))) { \
354 static u32
_amd_erase_flash(u32 addr
, u32 sector
)
359 *(volatile u32
*)(addr
+ 0x5554) = 0xAAAAAAAA;
360 *(volatile u32
*)(addr
+ 0xaaa8) = 0x55555555;
361 *(volatile u32
*)(addr
+ 0x5554) = 0x80808080;
363 *(volatile u32
*)(addr
+ 0x5554) = 0xAAAAAAAA;
364 *(volatile u32
*)(addr
+ 0xaaa8) = 0x55555555;
365 /* Sector erase command comes last */
366 *(volatile u32
*)(addr
+ sector
) = 0x30303030;
368 elapsed
= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
); /* dummy read */
371 while (((*(volatile u32
*)(addr
+ sector
)) & 0x80808080) != 0x80808080) {
373 elapsed
+= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
);
374 if (elapsed
> ((CFG_FLASH_ERASE_TOUT
/CFG_HZ
) * 1000)) {
375 *(volatile u32
*)(addr
) = 0xf0f0f0f0;
380 *(volatile u32
*)(addr
) = 0xf0f0f0f0;
385 extern int _amd_erase_flash_end
;
386 asm ("_amd_erase_flash_end:\n"
389 int flash_erase(flash_info_t
*info
, int s_first
, int s_last
)
391 u32 (*_erase_flash_ptr
)(u32 a
, u32 so
);
396 if ((s_first
< 0) || (s_first
> s_last
)) {
397 if (info
->flash_id
== FLASH_UNKNOWN
) {
398 printf("- missing\n");
400 printf("- no sectors to erase\n");
405 if ((info
->flash_id
& FLASH_VENDMASK
) == (AMD_MANUFACT
& FLASH_VENDMASK
)) {
406 size
= (unsigned)&_amd_erase_flash_end
- (unsigned)_amd_erase_flash
;
408 if (size
> PROBE_BUFFER_SIZE
) {
409 printf("_amd_erase_flash() routine too large (%d) %p - %p\n",
410 size
, &_amd_erase_flash_end
, _amd_erase_flash
);
414 memcpy(buffer
, _amd_erase_flash
, size
);
415 _erase_flash_ptr
= (void*)buffer
;
418 printf ("Can't erase unknown flash type - aborted\n");
423 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
424 if (info
->protect
[sect
]) {
430 printf ("- Warning: %d protected sectors will not be erased!\n", prot
);
436 /* Start erase on unprotected sectors */
437 for (sect
= s_first
; sect
<=s_last
; sect
++) {
439 if (info
->protect
[sect
] == 0) { /* not protected */
443 /* Disable interrupts which might cause a timeout here */
444 flag
= disable_interrupts();
446 res
= _erase_flash_ptr(info
->start
[0], info
->start
[sect
]-info
->start
[0]);
448 /* re-enable interrupts if necessary */
455 printf("Erase timed out, sector %d\n", sect
);
467 /*-----------------------------------------------------------------------
468 * Write a word to Flash, returns:
471 * 2 - Flash not erased
473 static int _amd_write_word(unsigned start
, unsigned dest
, unsigned data
)
475 volatile u32
*addr2
= (u32
*)start
;
476 volatile u32
*dest2
= (u32
*)dest
;
477 volatile u32
*data2
= (u32
*)&data
;
480 /* Check if Flash is (sufficiently) erased */
481 if ((*((volatile u32
*)dest
) & (u32
)data
) != (u32
)data
) {
485 addr2
[0x5554] = 0xAAAAAAAA;
486 addr2
[0xaaa8] = 0x55555555;
487 addr2
[0x5554] = 0xA0A0A0A0;
491 elapsed
= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
); /* dummy read */
494 /* data polling for D7 */
495 while ((dest2
[0] & 0x80808080) != (data2
[0] & 0x80808080)) {
496 elapsed
+= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
);
497 if (elapsed
> ((CFG_FLASH_WRITE_TOUT
/CFG_HZ
) * 1000)) {
498 addr2
[0] = 0xf0f0f0f0;
504 addr2
[0] = 0xf0f0f0f0;
509 extern int _amd_write_word_end
;
510 asm ("_amd_write_word_end:\n"
516 /*-----------------------------------------------------------------------
517 * Copy memory to flash, returns:
520 * 2 - Flash not erased
521 * 3 - Unsupported flash type
524 int write_buff(flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
529 u32 (*_write_word_ptr
)(unsigned start
, unsigned dest
, unsigned data
);
532 if ((info
->flash_id
& FLASH_VENDMASK
) == (AMD_MANUFACT
& FLASH_VENDMASK
)) {
533 size
= (unsigned)&_amd_write_word_end
- (unsigned)_amd_write_word
;
535 if (size
> PROBE_BUFFER_SIZE
) {
536 printf("_amd_write_word() routine too large (%d) %p - %p\n",
537 size
, &_amd_write_word_end
, _amd_write_word
);
541 memcpy(buffer
, _amd_write_word
, size
);
542 _write_word_ptr
= (void*)buffer
;
545 printf ("Can't program unknown flash type - aborted\n");
550 wp
= (addr
& ~3); /* get lower word aligned address */
554 * handle unaligned start bytes
556 if ((l
= addr
- wp
) != 0) {
558 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
559 data
|= (*(uchar
*)cp
) << (8*i
);
561 for (; i
<4 && cnt
>0; ++i
) {
562 data
|= *src
++ << (8*i
);
566 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
567 data
|= (*(uchar
*)cp
) << (8*i
);
570 /* Disable interrupts which might cause a timeout here */
571 flag
= disable_interrupts();
573 rc
= _write_word_ptr(info
->start
[0], wp
, data
);
575 /* re-enable interrupts if necessary */
586 * handle word aligned part
591 for (i
=0; i
<4; ++i
) {
592 data
|= *src
++ << (8*i
);
595 /* Disable interrupts which might cause a timeout here */
596 flag
= disable_interrupts();
598 rc
= _write_word_ptr(info
->start
[0], wp
, data
);
600 /* re-enable interrupts if necessary */
616 * handle unaligned tail bytes
619 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
620 data
|= *src
++ << (8*i
);
624 for (; i
<4; ++i
, ++cp
) {
625 data
|= (*(uchar
*)cp
) << (8*i
);
628 /* Disable interrupts which might cause a timeout here */
629 flag
= disable_interrupts();
631 rc
= _write_word_ptr(info
->start
[0], wp
, data
);
633 /* re-enable interrupts if necessary */