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;
176 extern int _probe_flash_end
;
177 asm ("_probe_flash_end:\n"
180 static int identify_flash(unsigned address
, int width
)
188 u32 (*_probe_flash_ptr
)(u32 a
, u32 bw
, int il
);
190 size
= (unsigned)&_probe_flash_end
- (unsigned)_probe_flash
;
192 if (size
> PROBE_BUFFER_SIZE
) {
193 printf("_probe_flash() routine too large (%d) %p - %p\n",
194 size
, &_probe_flash_end
, _probe_flash
);
198 memcpy(buffer
, _probe_flash
, size
);
199 _probe_flash_ptr
= (void*)buffer
;
201 is
= disable_interrupts();
202 res
= _probe_flash_ptr(address
, width
, 1);
209 device
= res
& 0xffff;
215 ulong
flash_init(void)
220 for (i
= 0; i
< SC520_MAX_FLASH_BANKS
; i
++) {
225 memset(flash_info
[i
].protect
, 0, CONFIG_SYS_MAX_FLASH_SECT
);
228 flashbase
= SC520_FLASH_BANK0_BASE
;
231 flashbase
= SC520_FLASH_BANK1_BASE
;
234 flashbase
= SC520_FLASH_BANK2_BASE
;
237 panic("configured too many flash banks!\n");
240 id
= identify_flash(flashbase
, 4);
241 switch (id
& 0x00ff00ff) {
243 /* 29LV016B/29LV017B */
244 flash_info
[i
].flash_id
=
245 (AMD_MANUFACT
& FLASH_VENDMASK
) |
246 (AMD_ID_LV016B
& FLASH_TYPEMASK
);
248 flash_info
[i
].size
= AMD29LV016B_SIZE
*4;
249 flash_info
[i
].sector_count
= AMD29LV016B_SECTORS
;
250 sectsize
= (AMD29LV016B_SIZE
*4)/AMD29LV016B_SECTORS
;
251 printf("Bank %d: 4 x AMD 29LV017B\n", i
);
256 printf("Bank %d have unknown flash %08x\n", i
, id
);
257 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
261 for (j
= 0; j
< flash_info
[i
].sector_count
; j
++) {
262 flash_info
[i
].start
[j
] = flashbase
+ j
* sectsize
;
264 size
+= flash_info
[i
].size
;
266 flash_protect(FLAG_PROTECT_CLEAR
,
267 flash_info
[i
].start
[0],
268 flash_info
[i
].start
[0] + flash_info
[i
].size
- 1,
273 * Protect monitor and environment sectors
275 flash_protect(FLAG_PROTECT_SET
,
279 #ifdef CONFIG_ENV_ADDR
280 flash_protect(FLAG_PROTECT_SET
,
282 CONFIG_ENV_ADDR
+ CONFIG_ENV_SIZE
- 1,
288 /*-----------------------------------------------------------------------
290 void flash_print_info(flash_info_t
*info
)
294 switch (info
->flash_id
& FLASH_VENDMASK
) {
296 case (AMD_MANUFACT
& FLASH_VENDMASK
):
298 switch (info
->flash_id
& FLASH_TYPEMASK
) {
299 case (AMD_ID_LV016B
& FLASH_TYPEMASK
):
300 printf("4x AMD29LV017B (4x16Mbit)\n");
303 printf("Unknown Chip Type\n");
310 printf("Unknown Vendor ");
315 printf(" Size: %ld MB in %d Sectors\n",
316 info
->size
>> 20, info
->sector_count
);
318 printf(" Sector Start Addresses:");
319 for (i
= 0; i
< info
->sector_count
; i
++) {
323 printf (" %08lX%s", info
->start
[i
],
324 info
->protect
[i
] ? " (RO)" : " ");
331 /*-----------------------------------------------------------------------
334 /* this needs to be inlined, the SWTMRMMILLI register is reset by each read */
335 #define __udelay(delay) \
340 micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
344 milli += *(volatile u16*)(0xfffef000+SC520_SWTMRMILLI); \
345 micro = *(volatile u16*)(0xfffef000+SC520_SWTMRMICRO); \
347 if ((delay) <= (micro + (milli * 1000))) { \
353 static u32
_amd_erase_flash(u32 addr
, u32 sector
)
358 *(volatile u32
*)(addr
+ 0x5554) = 0xAAAAAAAA;
359 *(volatile u32
*)(addr
+ 0xaaa8) = 0x55555555;
360 *(volatile u32
*)(addr
+ 0x5554) = 0x80808080;
362 *(volatile u32
*)(addr
+ 0x5554) = 0xAAAAAAAA;
363 *(volatile u32
*)(addr
+ 0xaaa8) = 0x55555555;
364 /* Sector erase command comes last */
365 *(volatile u32
*)(addr
+ sector
) = 0x30303030;
367 elapsed
= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
); /* dummy read */
370 while (((*(volatile u32
*)(addr
+ sector
)) & 0x80808080) != 0x80808080) {
372 elapsed
+= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
);
373 if (elapsed
> ((CONFIG_SYS_FLASH_ERASE_TOUT
/CONFIG_SYS_HZ
) * 1000)) {
374 *(volatile u32
*)(addr
) = 0xf0f0f0f0;
379 *(volatile u32
*)(addr
) = 0xf0f0f0f0;
384 extern int _amd_erase_flash_end
;
385 asm ("_amd_erase_flash_end:\n"
388 int flash_erase(flash_info_t
*info
, int s_first
, int s_last
)
390 u32 (*_erase_flash_ptr
)(u32 a
, u32 so
);
395 if ((s_first
< 0) || (s_first
> s_last
)) {
396 if (info
->flash_id
== FLASH_UNKNOWN
) {
397 printf("- missing\n");
399 printf("- no sectors to erase\n");
404 if ((info
->flash_id
& FLASH_VENDMASK
) == (AMD_MANUFACT
& FLASH_VENDMASK
)) {
405 size
= (unsigned)&_amd_erase_flash_end
- (unsigned)_amd_erase_flash
;
407 if (size
> PROBE_BUFFER_SIZE
) {
408 printf("_amd_erase_flash() routine too large (%d) %p - %p\n",
409 size
, &_amd_erase_flash_end
, _amd_erase_flash
);
413 memcpy(buffer
, _amd_erase_flash
, size
);
414 _erase_flash_ptr
= (void*)buffer
;
417 printf ("Can't erase unknown flash type - aborted\n");
422 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
423 if (info
->protect
[sect
]) {
429 printf ("- Warning: %d protected sectors will not be erased!\n", prot
);
435 /* Start erase on unprotected sectors */
436 for (sect
= s_first
; sect
<=s_last
; sect
++) {
438 if (info
->protect
[sect
] == 0) { /* not protected */
442 /* Disable interrupts which might cause a timeout here */
443 flag
= disable_interrupts();
445 res
= _erase_flash_ptr(info
->start
[0], info
->start
[sect
]-info
->start
[0]);
447 /* re-enable interrupts if necessary */
454 printf("Erase timed out, sector %d\n", sect
);
466 /*-----------------------------------------------------------------------
467 * Write a word to Flash, returns:
470 * 2 - Flash not erased
472 static int _amd_write_word(unsigned start
, unsigned dest
, unsigned data
)
474 volatile u32
*addr2
= (u32
*)start
;
475 volatile u32
*dest2
= (u32
*)dest
;
476 volatile u32
*data2
= (u32
*)&data
;
479 /* Check if Flash is (sufficiently) erased */
480 if ((*((volatile u32
*)dest
) & (u32
)data
) != (u32
)data
) {
484 addr2
[0x5554] = 0xAAAAAAAA;
485 addr2
[0xaaa8] = 0x55555555;
486 addr2
[0x5554] = 0xA0A0A0A0;
490 elapsed
= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
); /* dummy read */
493 /* data polling for D7 */
494 while ((dest2
[0] & 0x80808080) != (data2
[0] & 0x80808080)) {
495 elapsed
+= *(volatile u16
*)(0xfffef000+SC520_SWTMRMILLI
);
496 if (elapsed
> ((CONFIG_SYS_FLASH_WRITE_TOUT
/CONFIG_SYS_HZ
) * 1000)) {
497 addr2
[0] = 0xf0f0f0f0;
503 addr2
[0] = 0xf0f0f0f0;
508 extern int _amd_write_word_end
;
509 asm ("_amd_write_word_end:\n"
513 /*-----------------------------------------------------------------------
514 * Copy memory to flash, returns:
517 * 2 - Flash not erased
518 * 3 - Unsupported flash type
521 int write_buff(flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
526 u32 (*_write_word_ptr
)(unsigned start
, unsigned dest
, unsigned data
);
529 if ((info
->flash_id
& FLASH_VENDMASK
) == (AMD_MANUFACT
& FLASH_VENDMASK
)) {
530 size
= (unsigned)&_amd_write_word_end
- (unsigned)_amd_write_word
;
532 if (size
> PROBE_BUFFER_SIZE
) {
533 printf("_amd_write_word() routine too large (%d) %p - %p\n",
534 size
, &_amd_write_word_end
, _amd_write_word
);
538 memcpy(buffer
, _amd_write_word
, size
);
539 _write_word_ptr
= (void*)buffer
;
542 printf ("Can't program unknown flash type - aborted\n");
547 wp
= (addr
& ~3); /* get lower word aligned address */
551 * handle unaligned start bytes
553 if ((l
= addr
- wp
) != 0) {
555 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
556 data
|= (*(uchar
*)cp
) << (8*i
);
558 for (; i
<4 && cnt
>0; ++i
) {
559 data
|= *src
++ << (8*i
);
563 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
564 data
|= (*(uchar
*)cp
) << (8*i
);
567 /* Disable interrupts which might cause a timeout here */
568 flag
= disable_interrupts();
570 rc
= _write_word_ptr(info
->start
[0], wp
, data
);
572 /* re-enable interrupts if necessary */
583 * handle word aligned part
588 for (i
=0; i
<4; ++i
) {
589 data
|= *src
++ << (8*i
);
592 /* Disable interrupts which might cause a timeout here */
593 flag
= disable_interrupts();
595 rc
= _write_word_ptr(info
->start
[0], wp
, data
);
597 /* re-enable interrupts if necessary */
613 * handle unaligned tail bytes
616 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
617 data
|= *src
++ << (8*i
);
621 for (; i
<4; ++i
, ++cp
) {
622 data
|= (*(uchar
*)cp
) << (8*i
);
625 /* Disable interrupts which might cause a timeout here */
626 flag
= disable_interrupts();
628 rc
= _write_word_ptr(info
->start
[0], wp
, data
);
630 /* re-enable interrupts if necessary */