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 * Yoo. Jonghoon, IPone, yooth@ipone.co.kr
26 * U-Boot port on RPXlite board
28 * Some of flash control words are modified. (from 2x16bit device
30 * RPXLite board I tested has only 4 AM29LV800BB devices. Other devices
33 * (?) Does an RPXLite board which
34 * does not use AM29LV800 flash memory exist ?
38 /* Yes,Yoo.They do use other FLASH for the board.
40 * Sam Song, IEMC. SHU, samsongshu@yahoo.com.cn
41 * U-Boot port on RPXlite DW version board
43 * By now,it uses 4 AM29DL323DB90VI devices(4x8bit).
44 * The total FLASH has 16MB(4x4MB).
45 * I just made some necessary changes on the basis of Wolfgang and Yoo's job.
52 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
54 /*-----------------------------------------------------------------------
55 * Functions vu_long : volatile unsigned long IN include/common.h
57 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
);
58 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
);
59 static void flash_get_offsets (ulong base
, flash_info_t
*info
);
61 unsigned long flash_init (void)
63 unsigned long size_b0
;
66 /* Init: no FLASHes known */
67 for (i
=0; i
<CFG_MAX_FLASH_BANKS
; ++i
) {
68 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
71 size_b0
= flash_get_size((vu_long
*)CFG_FLASH_BASE
, &flash_info
[0]);
72 flash_get_offsets (CFG_FLASH_BASE
, &flash_info
[0]);
74 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
75 /* If Monitor is in the cope of FLASH,then
76 * protect this area by default in case for
77 * other occupation. [SAM] */
79 /* monitor protection ON by default */
80 flash_protect(FLAG_PROTECT_SET
,
82 CFG_MONITOR_BASE
+CFG_MONITOR_LEN
-1,
85 flash_info
[0].size
= size_b0
;
89 static void flash_get_offsets (ulong base
, flash_info_t
*info
)
93 /* set up sector start address table */
94 if (info
->flash_id
& FLASH_BTYPE
) {
95 info
->start
[0] = base
+ 0x00000000;
96 info
->start
[1] = base
+ 0x00008000;
97 info
->start
[2] = base
+ 0x00010000;
98 info
->start
[3] = base
+ 0x00018000;
99 info
->start
[4] = base
+ 0x00020000;
100 info
->start
[5] = base
+ 0x00028000;
101 info
->start
[6] = base
+ 0x00030000;
102 info
->start
[7] = base
+ 0x00038000;
104 for (i
= 8; i
< info
->sector_count
; i
++) {
105 info
->start
[i
] = base
+ ((i
-7) * 0x00040000);
108 i
= info
->sector_count
- 1;
109 info
->start
[i
--] = base
+ info
->size
- 0x00010000;
110 info
->start
[i
--] = base
+ info
->size
- 0x00018000;
111 info
->start
[i
--] = base
+ info
->size
- 0x00020000;
112 for (; i
>= 0; i
--) {
113 info
->start
[i
] = base
+ i
* 0x00040000;
119 void flash_print_info (flash_info_t
*info
)
123 if (info
->flash_id
== FLASH_UNKNOWN
) {
124 printf ("missing or unknown FLASH type\n");
128 switch (info
->flash_id
& FLASH_VENDMASK
) {
129 case FLASH_MAN_AMD
: printf ("AMD "); break;
130 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
131 default: printf ("Unknown Vendor "); break;
134 switch (info
->flash_id
& FLASH_TYPEMASK
) {
135 case FLASH_AM400B
: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
137 case FLASH_AM400T
: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
139 case FLASH_AM800B
: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
141 case FLASH_AM800T
: printf ("AM29LV800T (8 Mbit, top boot sector)\n");
143 case FLASH_AM160B
: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
145 case FLASH_AM160T
: printf ("AM29LV160T (16 Mbit, top boot sector)\n");
147 case FLASH_AM320B
: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
149 case FLASH_AM320T
: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
151 case FLASH_AMDL323B
: printf ("AM29DL323B (32 Mbit, bottom boot sector)\n");
153 /* I just add the FLASH_AMDL323B for RPXlite_DW BOARD. [SAM] */
154 default: printf ("Unknown Chip Type\n");
157 printf (" Size: %ld MB in %d Sectors\n",info
->size
>> 20, info
->sector_count
);
158 printf (" Sector Start Addresses:");
159 for (i
=0; i
<info
->sector_count
; ++i
) {
162 printf (" %08lX%s",info
->start
[i
],info
->protect
[i
] ? " (RO)" : " ");
168 static ulong
flash_get_size (vu_long
*addr
, flash_info_t
*info
)
172 ulong base
= (ulong
)addr
;
174 /* Write auto select command: read Manufacturer ID */
175 addr
[0xAAA] = 0x00AA00AA ;
176 addr
[0x555] = 0x00550055 ;
177 addr
[0xAAA] = 0x00900090 ;
180 switch (value
& 0x00FF00FF) {
181 case AMD_MANUFACT
: /* AMD_MANUFACT =0x00010001 in flash.h */
182 info
->flash_id
= FLASH_MAN_AMD
; /* FLASH_MAN_AMD=0x00000000 in flash.h */
185 info
->flash_id
= FLASH_MAN_FUJ
;
188 info
->flash_id
= FLASH_UNKNOWN
;
189 info
->sector_count
= 0;
191 return (0); /* no or unknown flash */
194 value
= addr
[2] ; /* device ID */
195 switch (value
& 0x00FF00FF) {
196 case (AMD_ID_LV400T
& 0x00FF00FF):
197 info
->flash_id
+= FLASH_AM400T
;
198 info
->sector_count
= 11;
199 info
->size
= 0x00100000;
201 case (AMD_ID_LV400B
& 0x00FF00FF):
202 info
->flash_id
+= FLASH_AM400B
;
203 info
->sector_count
= 11;
204 info
->size
= 0x00100000;
206 case (AMD_ID_LV800T
& 0x00FF00FF):
207 info
->flash_id
+= FLASH_AM800T
;
208 info
->sector_count
= 19;
209 info
->size
= 0x00200000;
211 case (AMD_ID_LV800B
& 0x00FF00FF):
212 info
->flash_id
+= FLASH_AM800B
;
213 info
->sector_count
= 19;
214 info
->size
= 0x00400000; /* Size doubled by yooth */
216 case (AMD_ID_LV160T
& 0x00FF00FF):
217 info
->flash_id
+= FLASH_AM160T
;
218 info
->sector_count
= 35;
219 info
->size
= 0x00400000;
221 case (AMD_ID_LV160B
& 0x00FF00FF):
222 info
->flash_id
+= FLASH_AM160B
;
223 info
->sector_count
= 35;
224 info
->size
= 0x00400000;
226 case (AMD_ID_DL323B
& 0x00FF00FF):
227 info
->flash_id
+= FLASH_AMDL323B
;
228 info
->sector_count
= 71;
229 info
->size
= 0x01000000;
230 break; /* => 16 MB(4x4MB) */
231 /* AMD_ID_DL323B= 0x22532253 FLASH_AMDL323B= 0x0013
232 * AMD_ID_DL323B could be found in <flash.h>.[SAM]
233 * So we could get : flash_id = 0x00000013.
234 * The first four-bit represents VEDOR ID,leaving others for FLASH ID. */
236 info
->flash_id
= FLASH_UNKNOWN
;
237 return (0); /* => no or unknown flash */
240 /* set up sector start address table */
241 if (info
->flash_id
& FLASH_BTYPE
) {
242 /* FLASH_BTYPE=0x0001 mask for bottom boot sector type.If the last bit equals 1,
243 * it means bottom boot flash. GOOD IDEA! [SAM]
246 /* set sector offsets for bottom boot block type */
247 info
->start
[0] = base
+ 0x00000000;
248 info
->start
[1] = base
+ 0x00008000;
249 info
->start
[2] = base
+ 0x00010000;
250 info
->start
[3] = base
+ 0x00018000;
251 info
->start
[4] = base
+ 0x00020000;
252 info
->start
[5] = base
+ 0x00028000;
253 info
->start
[6] = base
+ 0x00030000;
254 info
->start
[7] = base
+ 0x00038000;
256 for (i
= 8; i
< info
->sector_count
; i
++) {
257 info
->start
[i
] = base
+ ((i
-7) * 0x00040000) ;
260 /* set sector offsets for top boot block type */
261 i
= info
->sector_count
- 1;
262 info
->start
[i
--] = base
+ info
->size
- 0x00010000;
263 info
->start
[i
--] = base
+ info
->size
- 0x00018000;
264 info
->start
[i
--] = base
+ info
->size
- 0x00020000;
265 for (; i
>= 0; i
--) {
266 info
->start
[i
] = base
+ i
* 0x00040000;
270 /* check for protected sectors */
271 for (i
= 0; i
< info
->sector_count
; i
++) {
272 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
273 /* D0 = 1 if protected */
274 addr
= (volatile unsigned long *)(info
->start
[i
]);
275 /* info->protect[i] = addr[4] & 1 ; */
276 /* Mask it for disorder FLASH protection **[Sam]** */
280 * Prevent writes to uninitialized FLASH.
282 if (info
->flash_id
!= FLASH_UNKNOWN
) {
283 addr
= (volatile unsigned long *)info
->start
[0];
285 *addr
= 0xF0F0F0F0; /* reset bank */
290 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
292 vu_long
*addr
= (vu_long
*)(info
->start
[0]);
293 int flag
, prot
, sect
, l_sect
;
294 ulong start
, now
, last
;
296 if ((s_first
< 0) || (s_first
> s_last
)) {
297 if (info
->flash_id
== FLASH_UNKNOWN
) {
298 printf ("- missing\n");
300 printf ("- no sectors to erase\n");
305 if ((info
->flash_id
== FLASH_UNKNOWN
) ||
306 (info
->flash_id
> FLASH_AMD_COMP
)) {
307 printf ("Can't erase unknown flash type %08lx - aborted\n",
313 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
314 if (info
->protect
[sect
]) {
320 printf ("- Warning: %d protected sectors will not be erased!\n",
328 /* Disable interrupts which might cause a timeout here */
329 flag
= disable_interrupts();
331 addr
[0xAAA] = 0xAAAAAAAA;
332 addr
[0x555] = 0x55555555;
333 addr
[0xAAA] = 0x80808080;
334 addr
[0xAAA] = 0xAAAAAAAA;
335 addr
[0x555] = 0x55555555;
337 /* Start erase on unprotected sectors */
338 for (sect
= s_first
; sect
<=s_last
; sect
++) {
339 if (info
->protect
[sect
] == 0) { /* not protected */
340 addr
= (vu_long
*)(info
->start
[sect
]) ;
341 addr
[0] = 0x30303030 ;
346 /* re-enable interrupts if necessary */
350 /* wait at least 80us - let's wait 1 ms */
354 * We wait for the last triggered sector
359 start
= get_timer (0);
361 addr
= (vu_long
*)(info
->start
[l_sect
]);
362 while ((addr
[0] & 0x80808080) != 0x80808080) {
363 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
364 printf ("Timeout\n");
367 /* show that we're waiting */
368 if ((now
- last
) > 1000) { /* every second */
375 /* reset to read mode */
376 addr
= (vu_long
*)info
->start
[0];
377 addr
[0] = 0xF0F0F0F0; /* reset bank */
383 /*-----------------------------------------------------------------------
384 * Copy memory to flash, returns:
387 * 2 - Flash not erased
390 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
395 wp
= (addr
& ~3); /* get lower word aligned address */
398 * handle unaligned start bytes
400 if ((l
= addr
- wp
) != 0) {
402 for (i
=0, cp
=wp
; i
<l
; ++i
, ++cp
) {
403 data
= (data
<< 8) | (*(uchar
*)cp
);
405 for (; i
<4 && cnt
>0; ++i
) {
406 data
= (data
<< 8) | *src
++;
410 for (; cnt
==0 && i
<4; ++i
, ++cp
) {
411 data
= (data
<< 8) | (*(uchar
*)cp
);
414 if ((rc
= write_word(info
, wp
, data
)) != 0) {
421 * handle word aligned part
425 for (i
=0; i
<4; ++i
) {
426 data
= (data
<< 8) | *src
++;
428 if ((rc
= write_word(info
, wp
, data
)) != 0) {
440 * handle unaligned tail bytes
443 for (i
=0, cp
=wp
; i
<4 && cnt
>0; ++i
, ++cp
) {
444 data
= (data
<< 8) | *src
++;
447 for (; i
<4; ++i
, ++cp
) {
448 data
= (data
<< 8) | (*(uchar
*)cp
);
450 return (write_word(info
, wp
, data
));
453 /*-----------------------------------------------------------------------
454 * Write a word to Flash, returns:
457 * 2 - Flash not erased
459 static int write_word (flash_info_t
*info
, ulong dest
, ulong data
)
461 vu_long
*addr
= (vu_long
*)(info
->start
[0]);
465 /* Check if Flash is (sufficiently) erased */
466 if ((*((vu_long
*)dest
) & data
) != data
) {
469 /* Disable interrupts which might cause a timeout here */
470 flag
= disable_interrupts();
472 addr
[0xAAA] = 0xAAAAAAAA;
473 addr
[0x555] = 0x55555555;
474 addr
[0xAAA] = 0xA0A0A0A0;
476 *((vu_long
*)dest
) = data
;
478 /* re-enable interrupts if necessary */
482 /* data polling for D7 */
483 start
= get_timer (0);
484 while ((*((vu_long
*)dest
) & 0x80808080) != (data
& 0x80808080)) {
485 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {