]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/sacsng/flash.c
f37be294238ae6c6056569236208d958a10d1908
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,
25 #include <configs/sacsng.h>
31 #define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
34 #define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
38 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
40 /*-----------------------------------------------------------------------
43 static ulong
flash_get_size (vu_short
*addr
, flash_info_t
*info
);
44 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
46 /*-----------------------------------------------------------------------
49 unsigned long flash_init (void)
51 unsigned long size_b0
, size_b1
;
54 /* Init: no FLASHes known */
55 for (i
=0; i
<CFG_MAX_FLASH_BANKS
; ++i
) {
56 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
59 size_b0
= flash_get_size((vu_short
*)CFG_FLASH0_BASE
, &flash_info
[0]);
61 if (flash_info
[0].flash_id
== FLASH_UNKNOWN
) {
62 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
63 size_b0
, size_b0
<<20);
66 size_b1
= flash_get_size((vu_short
*)CFG_FLASH1_BASE
, &flash_info
[1]);
68 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
69 /* monitor protection ON by default */
70 flash_protect(FLAG_PROTECT_SET
,
72 CFG_MONITOR_BASE
+monitor_flash_len
-1,
76 #ifdef CONFIG_ENV_IS_IN_FLASH
77 /* ENV protection ON by default */
78 flash_protect(FLAG_PROTECT_SET
,
80 CFG_ENV_ADDR
+CFG_ENV_SIZE
-1,
85 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
86 /* monitor protection ON by default */
87 flash_protect(FLAG_PROTECT_SET
,
89 CFG_MONITOR_BASE
+monitor_flash_len
-1,
93 #ifdef CONFIG_ENV_IS_IN_FLASH
94 /* ENV protection ON by default */
95 flash_protect(FLAG_PROTECT_SET
,
97 CFG_ENV_ADDR
+CFG_ENV_SIZE
-1,
101 flash_info
[1].flash_id
= FLASH_UNKNOWN
;
102 flash_info
[1].sector_count
= -1;
105 flash_info
[0].size
= size_b0
;
106 flash_info
[1].size
= size_b1
;
109 * We only report the primary flash for U-Boot's use.
114 /*-----------------------------------------------------------------------
116 void flash_print_info (flash_info_t
*info
)
120 if (info
->flash_id
== FLASH_UNKNOWN
) {
121 printf ("missing or unknown FLASH type\n");
125 switch (info
->flash_id
& FLASH_VENDMASK
) {
126 case FLASH_MAN_AMD
: printf ("AMD "); break;
127 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
128 default: printf ("Unknown Vendor "); break;
131 switch (info
->flash_id
& FLASH_TYPEMASK
) {
132 case FLASH_AM400B
: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
134 case FLASH_AM400T
: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
136 case FLASH_AM800B
: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
138 case FLASH_AM800T
: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
140 case FLASH_AM160B
: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
142 case FLASH_AM160T
: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
144 case FLASH_AM320B
: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
146 case FLASH_AM320T
: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
148 default: printf ("Unknown Chip Type\n");
152 printf (" Size: %ld MB in %d Sectors\n",
153 info
->size
>> 20, info
->sector_count
);
155 printf (" Sector Start Addresses:");
156 for (i
=0; i
<info
->sector_count
; ++i
) {
161 info
->protect
[i
] ? " (RO)" : " "
168 /*-----------------------------------------------------------------------
172 /*-----------------------------------------------------------------------
176 * The following code cannot be run from FLASH!
179 static ulong
flash_get_size (vu_short
*addr
, flash_info_t
*info
)
183 ulong base
= (ulong
)addr
;
185 /* Write auto select command: read Manufacturer ID */
186 addr
[0x0555] = 0xAAAA;
187 addr
[0x02AA] = 0x5555;
188 addr
[0x0555] = 0x9090;
189 __asm__
__volatile__(" sync\n ");
193 printf("Flash manufacturer 0x%04X\n", value
);
196 if(value
== (ushort
)AMD_MANUFACT
) {
197 info
->flash_id
= FLASH_MAN_AMD
;
198 } else if (value
== (ushort
)FUJ_MANUFACT
) {
199 info
->flash_id
= FLASH_MAN_FUJ
;
202 printf("Unknown flash manufacturer 0x%04X\n", value
);
204 info
->flash_id
= FLASH_UNKNOWN
;
205 info
->sector_count
= 0;
207 return (0); /* no or unknown flash */
210 value
= addr
[1]; /* device ID */
212 printf("Flash type 0x%04X\n", value
);
215 if(value
== (ushort
)AMD_ID_LV400T
) {
216 info
->flash_id
+= FLASH_AM400T
;
217 info
->sector_count
= 11;
218 info
->size
= 0x00080000; /* => 0.5 MB */
219 } else if(value
== (ushort
)AMD_ID_LV400B
) {
220 info
->flash_id
+= FLASH_AM400B
;
221 info
->sector_count
= 11;
222 info
->size
= 0x00080000; /* => 0.5 MB */
223 } else if(value
== (ushort
)AMD_ID_LV800T
) {
224 info
->flash_id
+= FLASH_AM800T
;
225 info
->sector_count
= 19;
226 info
->size
= 0x00100000; /* => 1 MB */
227 } else if(value
== (ushort
)AMD_ID_LV800B
) {
228 info
->flash_id
+= FLASH_AM800B
;
229 info
->sector_count
= 19;
230 info
->size
= 0x00100000; /* => 1 MB */
231 } else if(value
== (ushort
)AMD_ID_LV160T
) {
232 info
->flash_id
+= FLASH_AM160T
;
233 info
->sector_count
= 35;
234 info
->size
= 0x00200000; /* => 2 MB */
235 } else if(value
== (ushort
)AMD_ID_LV160B
) {
236 info
->flash_id
+= FLASH_AM160B
;
237 info
->sector_count
= 35;
238 info
->size
= 0x00200000; /* => 2 MB */
239 } else if(value
== (ushort
)AMD_ID_LV320T
) {
240 info
->flash_id
+= FLASH_AM320T
;
241 info
->sector_count
= 67;
242 info
->size
= 0x00400000; /* => 4 MB */
243 } else if(value
== (ushort
)AMD_ID_LV320B
) {
244 info
->flash_id
+= FLASH_AM320B
;
245 info
->sector_count
= 67;
246 info
->size
= 0x00400000; /* => 4 MB */
249 printf("Unknown flash type 0x%04X\n", value
);
250 info
->size
= CFG_FLASH_SIZE
;
252 info
->flash_id
= FLASH_UNKNOWN
;
253 return (0); /* => no or unknown flash */
257 /* set up sector start address table */
258 if (info
->flash_id
& FLASH_BTYPE
) {
259 /* set sector offsets for bottom boot block type */
260 info
->start
[0] = base
+ 0x00000000;
261 info
->start
[1] = base
+ 0x00004000;
262 info
->start
[2] = base
+ 0x00006000;
263 info
->start
[3] = base
+ 0x00008000;
264 for (i
= 4; i
< info
->sector_count
; i
++) {
265 info
->start
[i
] = base
+ ((i
- 3) * 0x00010000);
268 /* set sector offsets for top boot block type */
269 i
= info
->sector_count
- 1;
270 info
->start
[i
--] = base
+ info
->size
- 0x00004000;
271 info
->start
[i
--] = base
+ info
->size
- 0x00006000;
272 info
->start
[i
--] = base
+ info
->size
- 0x00008000;
273 for (; i
>= 0; i
--) {
274 info
->start
[i
] = base
+ (i
* 0x00010000);
278 /* check for protected sectors */
279 for (i
= 0; i
< info
->sector_count
; i
++) {
280 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
281 /* D0 = 1 if protected */
282 addr
= (volatile unsigned short *)(info
->start
[i
]);
283 info
->protect
[i
] = addr
[2] & 1;
287 * Prevent writes to uninitialized FLASH.
289 if (info
->flash_id
!= FLASH_UNKNOWN
) {
290 addr
= (volatile unsigned short *)info
->start
[0];
294 addr
[0] = 0xF0F0; /* reset bank */
295 __asm__
__volatile__(" sync\n ");
300 /*-----------------------------------------------------------------------
303 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
305 vu_short
*addr
= (vu_short
*)(info
->start
[0]);
306 int flag
, prot
, sect
, l_sect
;
307 ulong start
, now
, last
;
309 if ((s_first
< 0) || (s_first
> s_last
)) {
310 if (info
->flash_id
== FLASH_UNKNOWN
) {
311 printf ("- missing\n");
313 printf ("- no sectors to erase\n");
318 if ((info
->flash_id
== FLASH_UNKNOWN
) ||
319 (info
->flash_id
> FLASH_AMD_COMP
)) {
320 printf ("Can't erase unknown flash type %08lx - aborted\n",
326 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
327 if (info
->protect
[sect
]) {
333 printf ("- Warning: %d protected sectors will not be erased!\n",
341 /* Disable interrupts which might cause a timeout here */
342 flag
= disable_interrupts();
344 addr
[0x0555] = 0xAAAA;
345 addr
[0x02AA] = 0x5555;
346 addr
[0x0555] = 0x8080;
347 addr
[0x0555] = 0xAAAA;
348 addr
[0x02AA] = 0x5555;
349 __asm__
__volatile__(" sync\n ");
351 /* Start erase on unprotected sectors */
352 for (sect
= s_first
; sect
<=s_last
; sect
++) {
353 if (info
->protect
[sect
] == 0) { /* not protected */
354 addr
= (vu_short
*)(info
->start
[sect
]);
360 /* re-enable interrupts if necessary */
364 /* wait at least 80us - let's wait 1 ms */
368 * We wait for the last triggered sector
373 start
= get_timer (0);
375 addr
= (vu_short
*)(info
->start
[l_sect
]);
376 while ((addr
[0] & 0x0080) != 0x0080) {
377 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
378 printf ("Timeout\n");
379 addr
[0] = 0xF0F0; /* reset bank */
380 __asm__
__volatile__(" sync\n ");
383 /* show that we're waiting */
384 if ((now
- last
) > 1000) { /* every second */
391 /* reset to read mode */
392 addr
= (vu_short
*)info
->start
[0];
393 addr
[0] = 0xF0F0; /* reset bank */
394 __asm__
__volatile__(" sync\n ");
400 /*-----------------------------------------------------------------------
401 * Copy memory to flash, returns:
404 * 2 - Flash not erased
407 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
412 wp
= (addr
& ~3); /* get lower word aligned address */
415 * handle unaligned start bytes
417 if ((l
= addr
- wp
) != 0) {
419 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
420 data
= (data
<< 8) | (*(uchar
*)cp
);
422 for (; i
<4 && cnt
>0; ++i
) {
423 data
= (data
<< 8) | *src
++;
427 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
428 data
= (data
<< 8) | (*(uchar
*)cp
);
431 if ((rc
= write_word(info
, wp
, data
)) != 0) {
438 * handle word aligned part
442 for (i
=0; i
<4; ++i
) {
443 data
= (data
<< 8) | *src
++;
445 if ((rc
= write_word(info
, wp
, data
)) != 0) {
457 * handle unaligned tail bytes
460 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
461 data
= (data
<< 8) | *src
++;
464 for (; i
<4; ++i
, ++cp
) {
465 data
= (data
<< 8) | (*(uchar
*)cp
);
468 return (write_word(info
, wp
, data
));
471 /*-----------------------------------------------------------------------
472 * Write a word to Flash, returns:
475 * 2 - Flash not erased
477 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
)
479 vu_short
*addr
= (vu_short
*)(info
->start
[0]);
484 /* Check if Flash is (sufficiently) erased */
485 if (((*(vu_long
*)dest
) & data
) != data
) {
488 /* Disable interrupts which might cause a timeout here */
489 flag
= disable_interrupts();
491 /* The original routine was designed to write 32 bit words to
492 * 32 bit wide memory. We have 16 bit wide memory so we do
493 * two writes. We write the LSB first at dest+2 and then the
494 * MSB at dest (lousy big endian).
497 for(j
= 0; j
< 2; j
++) {
498 addr
[0x0555] = 0xAAAA;
499 addr
[0x02AA] = 0x5555;
500 addr
[0x0555] = 0xA0A0;
501 __asm__
__volatile__(" sync\n ");
503 *((vu_short
*)dest
) = (ushort
)data
;
505 /* re-enable interrupts if necessary */
509 /* data polling for D7 */
510 start
= get_timer (0);
511 while (*(vu_short
*)dest
!= (ushort
)data
) {
512 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
522 /*-----------------------------------------------------------------------