1 /********************************************************************
3 * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms
5 * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/flash.c,v $
8 * $Date: 2005/02/21 12:48:58 $
10 * Last ChangeLog Entry
12 * Revision 1.3 2005/02/21 12:48:58 mleeman
13 * update of copyright years (feedback wd)
15 * Revision 1.2 2005/02/21 11:04:04 mleeman
16 * remove dead code and Coding style (feedback wd)
18 * Revision 1.1 2005/02/14 09:23:46 mleeman
19 * - moved 'barcohydra' directory to a more generic barco; since we will be
20 * supporting and adding multiple boards
22 * Revision 1.2 2005/02/09 12:56:23 mleeman
23 * add generic header to track changes in sources
26 *******************************************************************/
30 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
32 * See file CREDITS for list of people who contributed to this
35 * This program is free software; you can redistribute it and/or
36 * modify it under the terms of the GNU General Public License as
37 * published by the Free Software Foundation; either version 2 of
38 * the License, or (at your option) any later version.
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
53 #include <asm/processor.h>
56 #define ROM_CS0_START 0xFF800000
57 #define ROM_CS1_START 0xFF000000
59 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
61 #if defined(CFG_ENV_IS_IN_FLASH)
63 # define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
66 # define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
68 # ifndef CFG_ENV_SECT_SIZE
69 # define CFG_ENV_SECT_SIZE CFG_ENV_SIZE
73 /*-----------------------------------------------------------------------
76 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
78 /*flash command address offsets*/
84 #define FLASH_WORD_SIZE unsigned char
86 /*-----------------------------------------------------------------------
89 static unsigned long flash_id(unsigned char mfct
, unsigned char chip
) __attribute__ ((const));
92 FLASH_WORD_SIZE extval
;
93 unsigned short intval
;
96 static unsigned long flash_id(unsigned char mfct
, unsigned char chip
)
98 static const map_entry mfct_map
[] = {
99 {(FLASH_WORD_SIZE
) AMD_MANUFACT
, (unsigned short) ((unsigned long) FLASH_MAN_AMD
>> 16)},
100 {(FLASH_WORD_SIZE
) FUJ_MANUFACT
, (unsigned short) ((unsigned long) FLASH_MAN_FUJ
>> 16)},
101 {(FLASH_WORD_SIZE
) STM_MANUFACT
, (unsigned short) ((unsigned long) FLASH_MAN_STM
>> 16)},
102 {(FLASH_WORD_SIZE
) MT_MANUFACT
, (unsigned short) ((unsigned long) FLASH_MAN_MT
>> 16)},
103 {(FLASH_WORD_SIZE
) INTEL_MANUFACT
,(unsigned short) ((unsigned long) FLASH_MAN_INTEL
>> 16)},
104 {(FLASH_WORD_SIZE
) INTEL_ALT_MANU
,(unsigned short) ((unsigned long) FLASH_MAN_INTEL
>> 16)}
107 static const map_entry chip_map
[] = {
108 {AMD_ID_F040B
, FLASH_AM040
},
109 {AMD_ID_F033C
, FLASH_AM033
},
110 {AMD_ID_F065D
, FLASH_AM065
},
111 {ATM_ID_LV040
, FLASH_AT040
},
112 {(FLASH_WORD_SIZE
) STM_ID_x800AB
, FLASH_STM800AB
}
116 unsigned long result
= FLASH_UNKNOWN
;
119 for(p
= &chip_map
[0]; p
< &chip_map
[sizeof chip_map
/ sizeof chip_map
[0]]; p
++){
120 if(p
->extval
== chip
){
121 result
= FLASH_VENDMASK
| p
->intval
;
127 for(p
= &mfct_map
[0]; p
< &mfct_map
[sizeof mfct_map
/ sizeof mfct_map
[0]]; p
++){
128 if(p
->extval
== mfct
){
129 result
&= ~FLASH_VENDMASK
;
130 result
|= (unsigned long) p
->intval
<< 16;
139 unsigned long flash_init(void)
143 static const ulong flash_banks
[] = CFG_FLASH_BANKS
;
145 /* Init: no FLASHes known */
146 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++){
147 flash_info_t
* const pflinfo
= &flash_info
[i
];
148 pflinfo
->flash_id
= FLASH_UNKNOWN
;
150 pflinfo
->sector_count
= 0;
153 /* Enable writes to Hydra/Argus flash */
155 register unsigned int temp
;
156 CONFIG_READ_WORD(PICR1
,temp
);
157 temp
|= PICR1_FLASH_WR_EN
;
158 CONFIG_WRITE_WORD(PICR1
,temp
);
161 for(i
= 0; i
< sizeof flash_banks
/ sizeof flash_banks
[0]; i
++){
162 flash_info_t
* const pflinfo
= &flash_info
[i
];
163 const unsigned long base_address
= flash_banks
[i
];
164 volatile FLASH_WORD_SIZE
* const flash
= (FLASH_WORD_SIZE
*) base_address
;
166 /* write autoselect sequence */
167 flash
[0x5555] = 0xaa;
168 flash
[0x2aaa] = 0x55;
169 flash
[0x5555] = 0x90;
170 __asm__
__volatile__("sync");
172 pflinfo
->flash_id
= flash_id(flash
[0x0], flash
[0x1]);
174 switch(pflinfo
->flash_id
& FLASH_TYPEMASK
){
176 pflinfo
->size
= 0x00200000;
177 pflinfo
->sector_count
= 64;
178 for(j
= 0; j
< 64; j
++){
179 pflinfo
->start
[j
] = base_address
+ 0x00010000 * j
;
180 pflinfo
->protect
[j
] = flash
[(j
<< 16) | 0x2];
184 pflinfo
->size
= 0x00800000;
185 pflinfo
->sector_count
=128;
186 for(j
= 0; j
< 128; j
++){
187 pflinfo
->start
[j
] = base_address
+ 0x00010000 * j
;
188 pflinfo
->protect
[j
] = flash
[(j
<< 16) | 0x2];
192 pflinfo
->size
= 0x00080000;
193 pflinfo
->sector_count
= 2;
194 pflinfo
->start
[0] = base_address
;
195 pflinfo
->start
[1] = base_address
+ 0x00004000;
196 pflinfo
->protect
[0] = ((flash
[0x02] & 0X01)==0) ? 0X02 : 0X01;
197 pflinfo
->protect
[1] = 0X02;
200 pflinfo
->size
= 0x00080000;
201 pflinfo
->sector_count
= 8;
202 for(j
= 0; j
< 8; j
++){
203 pflinfo
->start
[j
] = base_address
+ 0x00010000 * j
;
204 pflinfo
->protect
[j
] = flash
[(j
<< 16) | 0x2];
208 pflinfo
->size
= 0x00100000;
209 pflinfo
->sector_count
= 19;
210 pflinfo
->start
[0] = base_address
;
211 pflinfo
->start
[1] = base_address
+ 0x4000;
212 pflinfo
->start
[2] = base_address
+ 0x6000;
213 pflinfo
->start
[3] = base_address
+ 0x8000;
214 for(j
= 1; j
< 16; j
++){
215 pflinfo
->start
[j
+3] = base_address
+ 0x00010000 * j
;
219 /* Protect monitor and environment sectors */
220 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
221 flash_protect(FLAG_PROTECT_SET
,
223 CFG_MONITOR_BASE
+ monitor_flash_len
- 1,
227 #if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
228 flash_protect(FLAG_PROTECT_SET
,
230 CFG_ENV_ADDR
+ CFG_ENV_SIZE
- 1,
234 /* reset device to read mode */
235 flash
[0x0000] = 0xf0;
236 __asm__
__volatile__("sync");
239 return flash_info
[0].size
+ flash_info
[1].size
;
242 /*-----------------------------------------------------------------------
244 void flash_print_info(flash_info_t
*info
)
246 static const char unk
[] = "Unknown";
247 const char *mfct
= unk
, *type
= unk
;
250 if(info
->flash_id
!= FLASH_UNKNOWN
){
251 switch(info
->flash_id
& FLASH_VENDMASK
){
268 mfct
= "Bright Microelectonics";
270 case FLASH_MAN_INTEL
:
275 switch(info
->flash_id
& FLASH_TYPEMASK
){
277 type
= "AT49LV040 (512K * 8, uniform sector size)";
280 type
= "AM29F033C (4 Mbit * 8, uniform sector size)";
283 type
= "AM29F040B (512K * 8, uniform sector size)";
286 type
= "AM29F0465D ( 8 MBit * 8, uniform sector size) or part of AM29F652D( 16 MB)";
289 type
= "AM29LV400B (4 Mbit, bottom boot sect)";
292 type
= "AM29LV400T (4 Mbit, top boot sector)";
295 type
= "AM29LV800B (8 Mbit, bottom boot sect)";
298 type
= "AM29LV800T (8 Mbit, top boot sector)";
301 type
= "AM29LV160T (16 Mbit, top boot sector)";
304 type
= "AM29LV320B (32 Mbit, bottom boot sect)";
307 type
= "AM29LV320T (32 Mbit, top boot sector)";
310 type
= "M29W800AB (8 Mbit, bottom boot sect)";
313 type
= "SST39LF/VF800 (8 Mbit, uniform sector size)";
316 type
= "SST39LF/VF160 (16 Mbit, uniform sector size)";
322 "\n Brand: %s Type: %s\n"
323 " Size: %lu KB in %d Sectors\n",
330 printf (" Sector Start Addresses:");
332 for (i
= 0; i
< info
->sector_count
; i
++){
335 unsigned long * flash
= (unsigned long *) info
->start
[i
];
338 * Check if whole sector is erased
341 (i
!= (info
->sector_count
- 1)) ?
342 (info
->start
[i
+ 1] - info
->start
[i
]) >> 2 :
343 (info
->start
[0] + info
->size
- info
->start
[i
]) >> 2;
346 flash
= (unsigned long *) info
->start
[i
], erased
= 1;
347 (flash
!= (unsigned long *) info
->start
[i
] + size
) && erased
;
350 erased
= *flash
== ~0x0UL
;
355 (i
% 5) ? "" : "\n ",
358 info
->protect
[i
] ? "RO" : " "
366 int flash_erase(flash_info_t
*info
, int s_first
, int s_last
)
368 volatile FLASH_WORD_SIZE
*addr
= (FLASH_WORD_SIZE
*)(info
->start
[0]);
369 int flag
, prot
, sect
, l_sect
;
370 ulong start
, now
, last
;
373 if ((s_first
< 0) || (s_first
> s_last
)) {
374 if (info
->flash_id
== FLASH_UNKNOWN
) {
375 printf ("- missing\n");
377 printf ("- no sectors to erase\n");
382 if ((info
->flash_id
== FLASH_UNKNOWN
) ||
383 (info
->flash_id
> (FLASH_MAN_STM
| FLASH_AMD_COMP
))) {
384 printf ("Can't erase unknown flash type - aborted\n");
389 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
390 if (info
->protect
[sect
]) {
396 printf ("- Warning: %d protected sectors will not be erased!\n",
404 /* Check the ROM CS */
405 if ((info
->start
[0] >= ROM_CS1_START
) && (info
->start
[0] < ROM_CS0_START
)){
412 /* Disable interrupts which might cause a timeout here */
413 flag
= disable_interrupts();
415 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00AA00AA;
416 addr
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
)0x00550055;
417 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00800080;
418 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00AA00AA;
419 addr
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
)0x00550055;
421 /* Start erase on unprotected sectors */
422 for (sect
= s_first
; sect
<=s_last
; sect
++) {
423 if (info
->protect
[sect
] == 0) { /* not protected */
424 addr
= (FLASH_WORD_SIZE
*)(info
->start
[0] + (
425 (info
->start
[sect
] - info
->start
[0]) << sh8b
));
426 if (info
->flash_id
& FLASH_MAN_SST
){
427 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00AA00AA;
428 addr
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
)0x00550055;
429 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00800080;
430 addr
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00AA00AA;
431 addr
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
)0x00550055;
432 addr
[0] = (FLASH_WORD_SIZE
)0x00500050; /* block erase */
433 udelay(30000); /* wait 30 ms */
436 addr
[0] = (FLASH_WORD_SIZE
)0x00300030; /* sector erase */
441 /* re-enable interrupts if necessary */
446 /* wait at least 80us - let's wait 1 ms */
450 * We wait for the last triggered sector
456 start
= get_timer (0);
458 addr
= (FLASH_WORD_SIZE
*)(info
->start
[0] + (
459 (info
->start
[l_sect
] - info
->start
[0]) << sh8b
));
460 while ((addr
[0] & (FLASH_WORD_SIZE
)0x00800080) != (FLASH_WORD_SIZE
)0x00800080) {
461 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
462 printf ("Timeout\n");
465 /* show that we're waiting */
466 if ((now
- last
) > 1000) { /* every second */
473 /* reset to read mode */
474 addr
= (FLASH_WORD_SIZE
*)info
->start
[0];
475 addr
[0] = (FLASH_WORD_SIZE
)0x00F000F0; /* reset bank */
481 /*-----------------------------------------------------------------------
482 * Copy memory to flash, returns:
485 * 2 - Flash not erased
488 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
493 wp
= (addr
& ~3); /* get lower word aligned address */
496 * handle unaligned start bytes
498 if ((l
= addr
- wp
) != 0) {
500 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
501 data
= (data
<< 8) | (*(uchar
*)cp
);
503 for (; i
<4 && cnt
>0; ++i
) {
504 data
= (data
<< 8) | *src
++;
508 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
509 data
= (data
<< 8) | (*(uchar
*)cp
);
512 if ((rc
= write_word(info
, wp
, data
)) != 0) {
519 * handle word aligned part
523 for (i
=0; i
<4; ++i
) {
524 data
= (data
<< 8) | *src
++;
526 if ((rc
= write_word(info
, wp
, data
)) != 0) {
538 * handle unaligned tail bytes
541 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
542 data
= (data
<< 8) | *src
++;
545 for (; i
<4; ++i
, ++cp
) {
546 data
= (data
<< 8) | (*(uchar
*)cp
);
549 return (write_word(info
, wp
, data
));
552 /*-----------------------------------------------------------------------
553 * Write a word to Flash, returns:
556 * 2 - Flash not erased
558 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
)
560 volatile FLASH_WORD_SIZE
*addr2
= (FLASH_WORD_SIZE
*)info
->start
[0];
561 volatile FLASH_WORD_SIZE
*dest2
;
562 volatile FLASH_WORD_SIZE
*data2
= (FLASH_WORD_SIZE
*)&data
;
568 /* Check the ROM CS */
569 if ((info
->start
[0] >= ROM_CS1_START
) && (info
->start
[0] < ROM_CS0_START
)){
576 dest2
= (FLASH_WORD_SIZE
*)(((dest
- info
->start
[0]) << sh8b
) +
579 /* Check if Flash is (sufficiently) erased */
580 if ((*dest2
& (FLASH_WORD_SIZE
)data
) != (FLASH_WORD_SIZE
)data
) {
583 /* Disable interrupts which might cause a timeout here */
584 flag
= disable_interrupts();
586 for (i
=0; i
<4/sizeof(FLASH_WORD_SIZE
); i
++){
587 addr2
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00AA00AA;
588 addr2
[ADDR1
<< sh8b
] = (FLASH_WORD_SIZE
)0x00550055;
589 addr2
[ADDR0
<< sh8b
] = (FLASH_WORD_SIZE
)0x00A000A0;
591 dest2
[i
<< sh8b
] = data2
[i
];
593 /* re-enable interrupts if necessary */
598 /* data polling for D7 */
599 start
= get_timer (0);
600 while ((dest2
[i
<< sh8b
] & (FLASH_WORD_SIZE
)0x00800080) !=
601 (data2
[i
] & (FLASH_WORD_SIZE
)0x00800080)) {
602 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
611 /*----------------------------------------------------------------------- */