]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/icecube/flash.c
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,
26 #ifndef CONFIG_FLASH_CFI_DRIVER
27 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
29 /* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
30 * has nothing to do with the flash chip being 8-bit or 16-bit.
32 #ifdef CONFIG_FLASH_16BIT
33 typedef unsigned short FLASH_PORT_WIDTH
;
34 typedef volatile unsigned short FLASH_PORT_WIDTHV
;
35 #define FLASH_ID_MASK 0xFFFF
37 typedef unsigned char FLASH_PORT_WIDTH
;
38 typedef volatile unsigned char FLASH_PORT_WIDTHV
;
39 #define FLASH_ID_MASK 0xFF
42 #define FPW FLASH_PORT_WIDTH
43 #define FPWV FLASH_PORT_WIDTHV
45 #define ORMASK(size) ((-size) & OR_AM_MSK)
47 #define FLASH_CYCLE1 0x0555
48 #define FLASH_CYCLE2 0x02aa
50 /*-----------------------------------------------------------------------
53 static ulong
flash_get_size(FPWV
*addr
, flash_info_t
*info
);
54 static void flash_reset(flash_info_t
*info
);
55 static int write_word_amd(flash_info_t
*info
, FPWV
*dest
, FPW data
);
56 static flash_info_t
*flash_get_info(ulong base
);
58 /*-----------------------------------------------------------------------
61 * sets up flash_info and returns size of FLASH (bytes)
63 unsigned long flash_init (void)
65 unsigned long size
= 0;
67 extern void flash_preinit(void);
68 extern void flash_afterinit(ulong
);
69 ulong flashbase
= CFG_FLASH_BASE
;
73 /* Init: no FLASHes known */
74 for (i
=0; i
< CFG_MAX_FLASH_BANKS
; ++i
) {
75 memset(&flash_info
[i
], 0, sizeof(flash_info_t
));
78 flash_get_size((FPW
*)flashbase
, &flash_info
[i
]);
80 size
+= flash_info
[i
].size
;
81 flashbase
+= 0x800000;
83 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
84 /* monitor protection ON by default */
85 flash_protect(FLAG_PROTECT_SET
,
87 CFG_MONITOR_BASE
+monitor_flash_len
-1,
88 flash_get_info(CFG_MONITOR_BASE
));
91 #ifdef CFG_ENV_IS_IN_FLASH
92 /* ENV protection ON by default */
93 flash_protect(FLAG_PROTECT_SET
,
95 CFG_ENV_ADDR
+CFG_ENV_SIZE
-1,
96 flash_get_info(CFG_ENV_ADDR
));
100 flash_afterinit(size
);
101 return size
? size
: 1;
104 /*-----------------------------------------------------------------------
106 static void flash_reset(flash_info_t
*info
)
108 FPWV
*base
= (FPWV
*)(info
->start
[0]);
110 /* Put FLASH back in read mode */
111 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
)
112 *base
= (FPW
)0x00FF00FF; /* Intel Read Mode */
113 else if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
)
114 *base
= (FPW
)0x00F000F0; /* AMD Read Mode */
117 /*-----------------------------------------------------------------------
120 static flash_info_t
*flash_get_info(ulong base
)
125 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++) {
126 info
= & flash_info
[i
];
128 info
->start
[0] <= base
&& base
<= info
->start
[0] + info
->size
- 1)
132 return i
== CFG_MAX_FLASH_BANKS
? 0 : info
;
135 /*-----------------------------------------------------------------------
138 void flash_print_info (flash_info_t
*info
)
144 uchar botbootletter
[] = "B";
145 uchar topbootletter
[] = "T";
146 uchar botboottype
[] = "bottom boot sector";
147 uchar topboottype
[] = "top boot sector";
149 if (info
->flash_id
== FLASH_UNKNOWN
) {
150 printf ("missing or unknown FLASH type\n");
154 switch (info
->flash_id
& FLASH_VENDMASK
) {
155 case FLASH_MAN_AMD
: printf ("AMD "); break;
156 case FLASH_MAN_BM
: printf ("BRIGHT MICRO "); break;
157 case FLASH_MAN_FUJ
: printf ("FUJITSU "); break;
158 case FLASH_MAN_SST
: printf ("SST "); break;
159 case FLASH_MAN_STM
: printf ("STM "); break;
160 case FLASH_MAN_INTEL
: printf ("INTEL "); break;
161 default: printf ("Unknown Vendor "); break;
164 /* check for top or bottom boot, if it applies */
165 if (info
->flash_id
& FLASH_BTYPE
) {
166 boottype
= botboottype
;
167 bootletter
= botbootletter
;
170 boottype
= topboottype
;
171 bootletter
= topbootletter
;
174 switch (info
->flash_id
& FLASH_TYPEMASK
) {
175 case FLASH_AMDLV065D
:
176 fmt
= "29LV065 (64 Mbit, uniform sectors)\n";
179 fmt
= "Unknown Chip Type\n";
183 printf (fmt
, bootletter
, boottype
);
185 printf (" Size: %ld MB in %d Sectors\n",
189 printf (" Sector Start Addresses:");
191 for (i
=0; i
<info
->sector_count
; ++i
) {
196 printf (" %08lX%s", info
->start
[i
],
197 info
->protect
[i
] ? " (RO)" : " ");
203 /*-----------------------------------------------------------------------
207 * The following code cannot be run from FLASH!
210 ulong
flash_get_size (FPWV
*addr
, flash_info_t
*info
)
215 /* Write auto select command: read Manufacturer ID */
216 /* Write auto select command sequence and test FLASH answer */
217 addr
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* for AMD, Intel ignores this */
218 addr
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* for AMD, Intel ignores this */
219 addr
[FLASH_CYCLE1
] = (FPW
)0x00900090; /* selects Intel or AMD */
221 /* The manufacturer codes are only 1 byte, so just use 1 byte.
222 * This works for any bus width and any FLASH device width.
225 switch (addr
[0] & 0xff) {
227 case (uchar
)AMD_MANUFACT
:
228 info
->flash_id
= FLASH_MAN_AMD
;
231 case (uchar
)INTEL_MANUFACT
:
232 info
->flash_id
= FLASH_MAN_INTEL
;
236 info
->flash_id
= FLASH_UNKNOWN
;
237 info
->sector_count
= 0;
242 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
243 if (info
->flash_id
!= FLASH_UNKNOWN
) switch ((FPW
)addr
[1]) {
245 case (FPW
)AMD_ID_LV065D
:
246 info
->flash_id
+= FLASH_AMDLV065D
;
247 info
->sector_count
= 128;
248 info
->size
= 0x00800000;
249 for( i
= 0; i
< info
->sector_count
; i
++ )
250 info
->start
[i
] = (ulong
)addr
+ (i
* 0x10000);
251 break; /* => 8 or 16 MB */
254 info
->flash_id
= FLASH_UNKNOWN
;
255 info
->sector_count
= 0;
257 return (0); /* => no or unknown flash */
260 /* test for real flash at bank 1 */
261 addr2
= (FPW
*)((ulong
)addr
| 0x800000);
263 ((addr2
[0] & 0xff) == (addr
[0] & 0xff)) && ((FPW
)addr2
[1] == (FPW
)addr
[1])) {
264 /* Seems 2 banks are the same space (8Mb chip is installed,
265 * J24 in default position (CS0)). Disable this (first) bank.
267 info
->flash_id
= FLASH_UNKNOWN
;
268 info
->sector_count
= 0;
271 /* Put FLASH back in read mode */
277 /*-----------------------------------------------------------------------
280 int flash_erase (flash_info_t
*info
, int s_first
, int s_last
)
283 int flag
, prot
, sect
;
284 int intel
= (info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
;
285 ulong start
, now
, last
;
288 if ((s_first
< 0) || (s_first
> s_last
)) {
289 if (info
->flash_id
== FLASH_UNKNOWN
) {
290 printf ("- missing\n");
292 printf ("- no sectors to erase\n");
297 switch (info
->flash_id
& FLASH_TYPEMASK
) {
298 case FLASH_AMDLV065D
:
302 printf ("Can't erase unknown flash type %08lx - aborted\n",
308 for (sect
=s_first
; sect
<=s_last
; ++sect
) {
309 if (info
->protect
[sect
]) {
315 printf ("- Warning: %d protected sectors will not be erased!\n",
323 /* Start erase on unprotected sectors */
324 for (sect
= s_first
; sect
<=s_last
&& rcode
== 0; sect
++) {
326 if (info
->protect
[sect
] != 0) /* protected, skip it */
329 /* Disable interrupts which might cause a timeout here */
330 flag
= disable_interrupts();
332 addr
= (FPWV
*)(info
->start
[sect
]);
334 *addr
= (FPW
)0x00500050; /* clear status register */
335 *addr
= (FPW
)0x00200020; /* erase setup */
336 *addr
= (FPW
)0x00D000D0; /* erase confirm */
339 /* must be AMD style if not Intel */
340 FPWV
*base
; /* first address in bank */
342 base
= (FPWV
*)(info
->start
[0]);
343 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
344 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
345 base
[FLASH_CYCLE1
] = (FPW
)0x00800080; /* erase mode */
346 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
347 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
348 *addr
= (FPW
)0x00300030; /* erase sector */
351 /* re-enable interrupts if necessary */
355 start
= get_timer(0);
357 /* wait at least 50us for AMD, 80us for Intel.
362 while ((*addr
& (FPW
)0x00800080) != (FPW
)0x00800080) {
363 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
364 printf ("Timeout\n");
368 *addr
= (FPW
)0x00B000B0;
371 flash_reset(info
); /* reset to read mode */
372 rcode
= 1; /* failed */
376 /* show that we're waiting */
377 if ((get_timer(last
)) > CFG_HZ
) {/* every second */
383 /* show that we're waiting */
384 if ((get_timer(last
)) > CFG_HZ
) { /* every second */
389 flash_reset(info
); /* reset to read mode */
396 /*-----------------------------------------------------------------------
397 * Copy memory to flash, returns:
400 * 2 - Flash not erased
402 int write_buff (flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
404 FPW data
= 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
405 int bytes
; /* number of bytes to program in current word */
406 int left
; /* number of bytes left to program */
409 for (left
= cnt
, res
= 0;
410 left
> 0 && res
== 0;
411 addr
+= sizeof(data
), left
-= sizeof(data
) - bytes
) {
413 bytes
= addr
& (sizeof(data
) - 1);
414 addr
&= ~(sizeof(data
) - 1);
416 /* combine source and destination data so can program
417 * an entire word of 16 or 32 bits
419 for (i
= 0; i
< sizeof(data
); i
++) {
421 if (i
< bytes
|| i
- bytes
>= left
)
422 data
+= *((uchar
*)addr
+ i
);
427 /* write one word to the flash */
428 switch (info
->flash_id
& FLASH_VENDMASK
) {
430 res
= write_word_amd(info
, (FPWV
*)addr
, data
);
433 /* unknown flash type, error! */
434 printf ("missing or unknown FLASH type\n");
435 res
= 1; /* not really a timeout, but gives error */
443 /*-----------------------------------------------------------------------
444 * Write a word to Flash for AMD FLASH
445 * A word is 16 or 32 bits, whichever the bus width of the flash bank
446 * (not an individual chip) is.
451 * 2 - Flash not erased
453 static int write_word_amd (flash_info_t
*info
, FPWV
*dest
, FPW data
)
457 int res
= 0; /* result, assume success */
458 FPWV
*base
; /* first address in flash bank */
460 /* Check if Flash is (sufficiently) erased */
461 if ((*dest
& data
) != data
) {
466 base
= (FPWV
*)(info
->start
[0]);
468 /* Disable interrupts which might cause a timeout here */
469 flag
= disable_interrupts();
471 base
[FLASH_CYCLE1
] = (FPW
)0x00AA00AA; /* unlock */
472 base
[FLASH_CYCLE2
] = (FPW
)0x00550055; /* unlock */
473 base
[FLASH_CYCLE1
] = (FPW
)0x00A000A0; /* selects program mode */
475 *dest
= data
; /* start programming the data */
477 /* re-enable interrupts if necessary */
481 start
= get_timer (0);
483 /* data polling for D7 */
484 while (res
== 0 && (*dest
& (FPW
)0x00800080) != (data
& (FPW
)0x00800080)) {
485 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
486 *dest
= (FPW
)0x00F000F0; /* reset bank */
493 #endif /*CONFIG_FLASH_CFI_DRIVER*/