3 * Yusdi Santoso, Adaptec Inc., yusdi_santoso@adaptec.com
5 * (C) Copyright 2000-2005
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.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 #include <asm/processor.h>
30 #include <asm/pci_io.h>
33 #define ROM_CS0_START 0xFF800000
34 #define ROM_CS1_START 0xFF000000
36 flash_info_t flash_info
[CONFIG_SYS_MAX_FLASH_BANKS
]; /* info for FLASH chips */
38 #if defined(CONFIG_ENV_IS_IN_FLASH)
39 # ifndef CONFIG_ENV_ADDR
40 # define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
42 # ifndef CONFIG_ENV_SIZE
43 # define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
45 # ifndef CONFIG_ENV_SECT_SIZE
46 # define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
50 /*-----------------------------------------------------------------------
53 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
55 /*flash command address offsets*/
61 #define FLASH_WORD_SIZE unsigned char
63 /*-----------------------------------------------------------------------
66 static unsigned long flash_id (unsigned char mfct
, unsigned char chip
)
67 __attribute__ ((const));
70 FLASH_WORD_SIZE extval
;
71 unsigned short intval
;
74 static unsigned long flash_id (unsigned char mfct
, unsigned char chip
)
76 static const map_entry mfct_map
[] = {
77 {(FLASH_WORD_SIZE
) AMD_MANUFACT
,
78 (unsigned short) ((unsigned long) FLASH_MAN_AMD
>> 16)},
79 {(FLASH_WORD_SIZE
) FUJ_MANUFACT
,
80 (unsigned short) ((unsigned long) FLASH_MAN_FUJ
>> 16)},
81 {(FLASH_WORD_SIZE
) STM_MANUFACT
,
82 (unsigned short) ((unsigned long) FLASH_MAN_STM
>> 16)},
83 {(FLASH_WORD_SIZE
) MT_MANUFACT
,
84 (unsigned short) ((unsigned long) FLASH_MAN_MT
>> 16)},
85 {(FLASH_WORD_SIZE
) INTEL_MANUFACT
,
86 (unsigned short) ((unsigned long) FLASH_MAN_INTEL
>> 16)},
87 {(FLASH_WORD_SIZE
) INTEL_ALT_MANU
,
88 (unsigned short) ((unsigned long) FLASH_MAN_INTEL
>> 16)}
91 static const map_entry chip_map
[] = {
92 {AMD_ID_F040B
, FLASH_AM040
},
93 {(FLASH_WORD_SIZE
) STM_ID_x800AB
, FLASH_STM800AB
}
97 unsigned long result
= FLASH_UNKNOWN
;
100 for (p
= &chip_map
[0];
101 p
< &chip_map
[sizeof chip_map
/ sizeof chip_map
[0]]; p
++)
102 if (p
->extval
== chip
) {
103 result
= FLASH_VENDMASK
| p
->intval
;
108 for (p
= &mfct_map
[0];
109 p
< &mfct_map
[sizeof mfct_map
/ sizeof mfct_map
[0]]; p
++)
110 if (p
->extval
== mfct
) {
111 result
&= ~FLASH_VENDMASK
;
112 result
|= (unsigned long) p
->intval
<< 16;
119 unsigned long flash_init (void)
123 static const ulong flash_banks
[] = CONFIG_SYS_FLASH_BANKS
;
125 /* Init: no FLASHes known */
126 for (i
= 0; i
< CONFIG_SYS_MAX_FLASH_BANKS
; i
++) {
127 flash_info_t
*const pflinfo
= &flash_info
[i
];
129 pflinfo
->flash_id
= FLASH_UNKNOWN
;
131 pflinfo
->sector_count
= 0;
134 /* Enable writes to Hidden Dragon flash */
136 register unsigned char temp
;
138 CONFIG_READ_BYTE (CONFIG_SYS_WINBOND_ISA_CFG_ADDR
+ WINBOND_CSCR
,
140 temp
&= ~0x20; /* clear BIOSWP bit */
141 CONFIG_WRITE_BYTE (CONFIG_SYS_WINBOND_ISA_CFG_ADDR
+ WINBOND_CSCR
,
145 for (i
= 0; i
< sizeof flash_banks
/ sizeof flash_banks
[0]; i
++) {
146 flash_info_t
*const pflinfo
= &flash_info
[i
];
147 const unsigned long base_address
= flash_banks
[i
];
148 volatile FLASH_WORD_SIZE
*const flash
=
149 (FLASH_WORD_SIZE
*) base_address
;
151 flash
[0xAAA << (3 * i
)] = 0xaa;
152 flash
[0x555 << (3 * i
)] = 0x55;
153 flash
[0xAAA << (3 * i
)] = 0x90;
154 __asm__
__volatile__ ("sync");
157 flash_id (flash
[0x0], flash
[0x2 + 14 * i
]);
159 switch (pflinfo
->flash_id
& FLASH_TYPEMASK
) {
161 pflinfo
->size
= 0x00080000;
162 pflinfo
->sector_count
= 8;
163 for (j
= 0; j
< 8; j
++) {
165 base_address
+ 0x00010000 * j
;
166 pflinfo
->protect
[j
] = flash
[(j
<< 16) | 0x2];
170 pflinfo
->size
= 0x00100000;
171 pflinfo
->sector_count
= 19;
172 pflinfo
->start
[0] = base_address
;
173 pflinfo
->start
[1] = base_address
+ 0x4000;
174 pflinfo
->start
[2] = base_address
+ 0x6000;
175 pflinfo
->start
[3] = base_address
+ 0x8000;
176 for (j
= 1; j
< 16; j
++) {
177 pflinfo
->start
[j
+ 3] =
178 base_address
+ 0x00010000 * j
;
182 /* The chip used is not listed in flash_id
183 TODO: Change this to explicitly detect the flash type
186 int sector_addr
= base_address
;
188 pflinfo
->size
= 0x00200000;
189 pflinfo
->sector_count
= 35;
190 pflinfo
->start
[0] = sector_addr
;
191 sector_addr
+= 0x4000; /* 16K */
192 pflinfo
->start
[1] = sector_addr
;
193 sector_addr
+= 0x2000; /* 8K */
194 pflinfo
->start
[2] = sector_addr
;
195 sector_addr
+= 0x2000; /* 8K */
196 pflinfo
->start
[3] = sector_addr
;
197 sector_addr
+= 0x8000; /* 32K */
199 for (j
= 4; j
< 35; j
++) {
200 pflinfo
->start
[j
] = sector_addr
;
201 sector_addr
+= 0x10000; /* 64K */
206 /* Protect monitor and environment sectors
208 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
209 flash_protect (FLAG_PROTECT_SET
,
210 CONFIG_SYS_MONITOR_BASE
,
211 CONFIG_SYS_MONITOR_BASE
+ monitor_flash_len
- 1,
215 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
216 flash_protect (FLAG_PROTECT_SET
,
218 CONFIG_ENV_ADDR
+ CONFIG_ENV_SIZE
- 1,
222 /* reset device to read mode */
223 flash
[0x0000] = 0xf0;
224 __asm__
__volatile__ ("sync");
227 /* only have 1 bank */
228 return flash_info
[0].size
;
231 /*-----------------------------------------------------------------------
233 void flash_print_info (flash_info_t
* info
)
235 static const char unk
[] = "Unknown";
236 const char *mfct
= unk
, *type
= unk
;
239 if (info
->flash_id
!= FLASH_UNKNOWN
) {
240 switch (info
->flash_id
& FLASH_VENDMASK
) {
254 mfct
= "Bright Microelectonics";
256 case FLASH_MAN_INTEL
:
261 switch (info
->flash_id
& FLASH_TYPEMASK
) {
263 type
= "AM29F040B (512K * 8, uniform sector size)";
266 type
= "AM29LV400B (4 Mbit, bottom boot sect)";
269 type
= "AM29LV400T (4 Mbit, top boot sector)";
272 type
= "AM29LV800B (8 Mbit, bottom boot sect)";
275 type
= "AM29LV800T (8 Mbit, top boot sector)";
278 type
= "AM29LV160T (16 Mbit, top boot sector)";
281 type
= "AM29LV320B (32 Mbit, bottom boot sect)";
284 type
= "AM29LV320T (32 Mbit, top boot sector)";
287 type
= "M29W800AB (8 Mbit, bottom boot sect)";
290 type
= "SST39LF/VF800 (8 Mbit, uniform sector size)";
293 type
= "SST39LF/VF160 (16 Mbit, uniform sector size)";
298 printf ("\n Brand: %s Type: %s\n"
299 " Size: %lu KB in %d Sectors\n",
300 mfct
, type
, info
->size
>> 10, info
->sector_count
);
302 printf (" Sector Start Addresses:");
304 for (i
= 0; i
< info
->sector_count
; i
++) {
307 unsigned long *flash
= (unsigned long *) info
->start
[i
];
310 * Check if whole sector is erased
312 size
= (i
!= (info
->sector_count
- 1)) ?
313 (info
->start
[i
+ 1] - info
->start
[i
]) >> 2 :
314 (info
->start
[0] + info
->size
- info
->start
[i
]) >> 2;
316 for (flash
= (unsigned long *) info
->start
[i
], erased
= 1;
317 (flash
!= (unsigned long *) info
->start
[i
] + size
)
319 erased
= *flash
== ~0x0UL
;
321 printf ("%s %08lX %s %s",
322 (i
% 5) ? "" : "\n ",
324 erased
? "E" : " ", info
->protect
[i
] ? "RO" : " ");
331 int flash_erase (flash_info_t
* info
, int s_first
, int s_last
)
333 volatile FLASH_WORD_SIZE
*addr
= (FLASH_WORD_SIZE
*) (info
->start
[0]);
334 int flag
, prot
, sect
, l_sect
;
335 ulong start
, now
, last
;
338 if ((s_first
< 0) || (s_first
> s_last
)) {
339 if (info
->flash_id
== FLASH_UNKNOWN
) {
340 printf ("- missing\n");
342 printf ("- no sectors to erase\n");
347 if ((info
->flash_id
== FLASH_UNKNOWN
) ||
348 (info
->flash_id
> (FLASH_MAN_STM
| FLASH_AMD_COMP
))) {
349 printf ("Can't erase unknown flash type - aborted\n");
354 for (sect
= s_first
; sect
<= s_last
; ++sect
) {
355 if (info
->protect
[sect
]) {
361 printf ("- Warning: %d protected sectors will not be erased!\n", prot
);
368 /* Check the ROM CS */
369 if ((info
->start
[0] >= ROM_CS1_START
)
370 && (info
->start
[0] < ROM_CS0_START
))
375 /* Disable interrupts which might cause a timeout here */
376 flag
= disable_interrupts ();
378 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00AA00AA;
379 addr
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00550055;
380 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00800080;
381 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00AA00AA;
382 addr
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00550055;
384 /* Start erase on unprotected sectors */
385 for (sect
= s_first
; sect
<= s_last
; sect
++) {
386 if (info
->protect
[sect
] == 0) { /* not protected */
387 addr
= (FLASH_WORD_SIZE
*) (info
->start
[0] +
388 ((info
->start
[sect
] -
389 info
->start
[0]) << sh8b
));
390 if (info
->flash_id
& FLASH_MAN_SST
) {
391 addr
[ADDR0
<< sh8b
] =
392 (FLASH_WORD_SIZE
) 0x00AA00AA;
393 addr
[ADDR1
<< sh8b
] =
394 (FLASH_WORD_SIZE
) 0x00550055;
395 addr
[ADDR0
<< sh8b
] =
396 (FLASH_WORD_SIZE
) 0x00800080;
397 addr
[ADDR0
<< sh8b
] =
398 (FLASH_WORD_SIZE
) 0x00AA00AA;
399 addr
[ADDR1
<< sh8b
] =
400 (FLASH_WORD_SIZE
) 0x00550055;
401 addr
[0] = (FLASH_WORD_SIZE
) 0x00500050; /* block erase */
402 udelay (30000); /* wait 30 ms */
404 addr
[0] = (FLASH_WORD_SIZE
) 0x00300030; /* sector erase */
409 /* re-enable interrupts if necessary */
411 enable_interrupts ();
413 /* wait at least 80us - let's wait 1 ms */
417 * We wait for the last triggered sector
422 start
= get_timer (0);
424 addr
= (FLASH_WORD_SIZE
*) (info
->start
[0] + ((info
->start
[l_sect
] -
427 while ((addr
[0] & (FLASH_WORD_SIZE
) 0x00800080) !=
428 (FLASH_WORD_SIZE
) 0x00800080) {
429 if ((now
= get_timer (start
)) > CONFIG_SYS_FLASH_ERASE_TOUT
) {
430 printf ("Timeout\n");
433 /* show that we're waiting */
434 if ((now
- last
) > 1000) { /* every second */
441 /* reset to read mode */
442 addr
= (FLASH_WORD_SIZE
*) info
->start
[0];
443 addr
[0] = (FLASH_WORD_SIZE
) 0x00F000F0; /* reset bank */
449 /*-----------------------------------------------------------------------
450 * Copy memory to flash, returns:
453 * 2 - Flash not erased
456 int write_buff (flash_info_t
* info
, uchar
* src
, ulong addr
, ulong cnt
)
461 wp
= (addr
& ~3); /* get lower word aligned address */
464 * handle unaligned start bytes
466 if ((l
= addr
- wp
) != 0) {
468 for (i
= 0, cp
= wp
; i
< l
; ++i
, ++cp
) {
469 data
= (data
<< 8) | (*(uchar
*) cp
);
471 for (; i
< 4 && cnt
> 0; ++i
) {
472 data
= (data
<< 8) | *src
++;
476 for (; cnt
== 0 && i
< 4; ++i
, ++cp
) {
477 data
= (data
<< 8) | (*(uchar
*) cp
);
480 if ((rc
= write_word (info
, wp
, data
)) != 0) {
487 * handle word aligned part
491 for (i
= 0; i
< 4; ++i
) {
492 data
= (data
<< 8) | *src
++;
494 if ((rc
= write_word (info
, wp
, data
)) != 0) {
506 * handle unaligned tail bytes
509 for (i
= 0, cp
= wp
; i
< 4 && cnt
> 0; ++i
, ++cp
) {
510 data
= (data
<< 8) | *src
++;
513 for (; i
< 4; ++i
, ++cp
) {
514 data
= (data
<< 8) | (*(uchar
*) cp
);
517 return (write_word (info
, wp
, data
));
520 /*-----------------------------------------------------------------------
521 * Write a word to Flash, returns:
524 * 2 - Flash not erased
526 static int write_word (flash_info_t
* info
, ulong dest
, ulong data
)
528 volatile FLASH_WORD_SIZE
*addr2
= (FLASH_WORD_SIZE
*) info
->start
[0];
529 volatile FLASH_WORD_SIZE
*dest2
;
530 volatile FLASH_WORD_SIZE
*data2
= (FLASH_WORD_SIZE
*) & data
;
536 /* Check the ROM CS */
537 if ((info
->start
[0] >= ROM_CS1_START
)
538 && (info
->start
[0] < ROM_CS0_START
))
543 dest2
= (FLASH_WORD_SIZE
*) (((dest
- info
->start
[0]) << sh8b
) +
546 /* Check if Flash is (sufficiently) erased */
547 if ((*dest2
& (FLASH_WORD_SIZE
) data
) != (FLASH_WORD_SIZE
) data
) {
550 /* Disable interrupts which might cause a timeout here */
551 flag
= disable_interrupts ();
553 for (i
= 0; i
< 4 / sizeof (FLASH_WORD_SIZE
); i
++) {
554 addr2
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00AA00AA;
555 addr2
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00550055;
556 addr2
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
) 0x00A000A0;
558 dest2
[i
<< sh8b
] = data2
[i
];
560 /* re-enable interrupts if necessary */
562 enable_interrupts ();
564 /* data polling for D7 */
565 start
= get_timer (0);
566 while ((dest2
[i
<< sh8b
] & (FLASH_WORD_SIZE
) 0x00800080) !=
567 (data2
[i
] & (FLASH_WORD_SIZE
) 0x00800080)) {
568 if (get_timer (start
) > CONFIG_SYS_FLASH_WRITE_TOUT
) {