1 /************************************************************************/
3 /* AMD CFI Enabled Flash Memory Drivers */
4 /* File name: CFIFLASH.C */
5 /* Revision: 1.0 5/07/98 */
7 /* Copyright (c) 1998 ADVANCED MICRO DEVICES, INC. All Rights Reserved. */
8 /* This software is unpublished and contains the trade secrets and */
9 /* confidential proprietary information of AMD. Unless otherwise */
10 /* provided in the Software Agreement associated herewith, it is */
11 /* licensed in confidence "AS IS" and is not to be reproduced in whole */
12 /* or part by any means except for backup. Use, duplication, or */
13 /* disclosure by the Government is subject to the restrictions in */
14 /* paragraph (b) (3) (B) of the Rights in Technical Data and Computer */
15 /* Software clause in DFAR 52.227-7013 (a) (Oct 1988). */
16 /* Software owned by */
17 /* Advanced Micro Devices, Inc., */
20 /* Sunnyvale, CA 94088-3453. */
21 /************************************************************************/
22 /* This software constitutes a basic shell of source code for */
23 /* programming all AMD Flash components. AMD */
24 /* will not be responsible for misuse or illegal use of this */
25 /* software for devices not supported herein. AMD is providing */
26 /* this source code "AS IS" and will not be responsible for */
27 /* issues arising from incorrect user implementation of the */
28 /* source code herein. It is the user's responsibility to */
29 /* properly design-in this source code. */
31 /************************************************************************/
35 #include "lib_types.h"
36 #include "lib_printf.h"
37 #include "lib_string.h"
38 #include "cfe_timer.h"
40 #define CFI_USLEEP(x) cfe_usleep(x)
43 #include <linux/param.h>
44 #include <linux/sched.h>
45 #include <linux/timer.h>
46 #include <asm/delay.h>
47 #include <bcm_map_part.h>
48 #define CFI_USLEEP(x) udelay(x)
53 #include "flash_api.h"
60 #define MAXSECTORS 1024 /* maximum number of sectors supported */
62 /* Standard Boolean declarations */
66 /* Define different type of flash */
67 #define FLASH_UNDEFINED 0
72 /* Command codes for the flash_command routine */
73 #define FLASH_RESET 0 /* reset to read mode */
74 #define FLASH_READ_ID 1 /* read device ID */
75 #define FLASH_CFIQUERY 2 /* CFI query */
76 #define FLASH_UB 3 /* go into unlock bypass mode */
77 #define FLASH_PROG 4 /* program a unsigned short */
78 #define FLASH_UBRESET 5 /* reset to read mode from unlock bypass mode */
79 #define FLASH_SERASE 6 /* sector erase */
81 /* Return codes from flash_status */
82 #define STATUS_READY 0 /* ready for action */
83 #define STATUS_TIMEOUT 1 /* operation timed out */
85 /* A list of AMD compatible device ID's - add others as needed */
86 #define ID_AM29DL800T 0x224A
87 #define ID_AM29DL800B 0x22CB
88 #define ID_AM29LV800T 0x22DA
89 #define ID_AM29LV800B 0x225B
90 #define ID_AM29LV400B 0x22BA
91 #define ID_AM29LV200BT 0x223B
93 #define ID_AM29LV160B 0x2249
94 #define ID_AM29LV160T 0x22C4
96 #define ID_AM29LV320T 0x22F6
97 #define ID_MX29LV320AT 0x22A7
98 #define ID_AM29LV320B 0x22F9
99 #define ID_MX29LV320AB 0x22A8
101 #define ID_AM29LV320M 0x227E
102 #define ID_AM29LV320MB 0x2200
103 #define ID_AM29LV320MT 0x2201
105 #define ID_SST39VF200A 0x2789
106 #define ID_SST39VF400A 0x2780
107 #define ID_SST39VF800A 0x2781
108 #define ID_SST39VF1601 0x234B
109 #define ID_SST39VF3201 0x235B
110 // add SST and ST flash device id
111 #define ID_SST39VF3202 0x235A
112 #define ID_M29W320ET 0x2256
113 /* A list of Intel compatible device ID's - add others as needed */
114 #define ID_I28F160C3T 0x88C2
115 #define ID_I28F160C3B 0x88C3
116 #define ID_I28F320C3T 0x88C4
117 #define ID_I28F320C3B 0x88C5
119 #define CFI_FLASH_DEVICES \
120 {{ID_AM29DL800T, "AM29DL800T"}, \
121 {ID_AM29DL800B, "AM29DL800B"}, \
122 {ID_AM29LV800T, "AM29LV800T"}, \
123 {ID_AM29LV800B, "AM29LV800B"}, \
124 {ID_AM29LV400B, "AM29LV400B"}, \
125 {ID_AM29LV200BT, "AM29LV200BT"}, \
126 {ID_AM29LV160B, "AM29LV160B"}, \
127 {ID_AM29LV160T, "AM29LV160T"}, \
128 {ID_AM29LV320T, "AM29LV320T"}, \
129 {ID_MX29LV320AT, "MX29LV320AT"}, \
130 {ID_AM29LV320B, "AM29LV320B"}, \
131 {ID_MX29LV320AB, "MX29LV320AB"}, \
132 {ID_AM29LV320M, "AM29LV320M"}, \
133 {ID_AM29LV320MB, "AM29LV320MB"}, \
134 {ID_AM29LV320MT, "AM29LV320MT"}, \
135 {ID_SST39VF200A, "SST39VF200A"}, \
136 {ID_SST39VF400A, "SST39VF400A"}, \
137 {ID_SST39VF800A, "SST39VF800A"}, \
138 {ID_SST39VF1601, "SST39VF1601"}, \
139 {ID_SST39VF3201, "SST39VF3201"}, \
140 {ID_SST39VF3202, "SST39VF3202"}, \
141 {ID_M29W320ET, "M29W320ET"}, \
142 {ID_I28F160C3T, "I28F160C3T"}, \
143 {ID_I28F160C3B, "I28F160C3B"}, \
144 {ID_I28F320C3T, "I28F320C3T"}, \
145 {ID_I28F320C3B, "I28F320C3B"}, \
150 /* A structure for identifying a flash part. There is one for each
151 * of the flash part definitions. We need to keep track of the
152 * sector organization, the address register used, and the size
156 char *name; /* "Am29DL800T", etc. */
157 unsigned long addr; /* physical address, once translated */
158 int areg; /* Can be set to zero for all parts */
159 int nsect; /* # of sectors -- 19 in LV, 22 in DL */
160 int bank1start; /* first sector # in bank 1 */
161 int bank2start; /* first sector # in bank 2, if DL part */
163 long size; /* # of bytes in this sector */
164 long base; /* offset from beginning of device */
165 int bank; /* 1 or 2 for DL; 1 for LV */
166 } sec[MAXSECTORS]; /* per-sector info */
170 * This structure holds all CFI query information as defined
171 * in the JEDEC standard. All information up to
172 * primary_extended_query is standard among all manufactures
173 * with CFI enabled devices.
177 int num_erase_blocks; /* Number of sector defs. */
178 long device_size; /* Device size in bytes */
180 unsigned long sector_size; /* byte size of sector */
181 int num_sectors; /* Num sectors of this size */
182 } erase_block[8]; /* Max of 256, but 8 is good */
185 struct flash_name_from_id {
186 unsigned short fnfi_id;
192 int cfi_flash_init(flash_device_info_t **flash_info);
193 static int cfi_flash_sector_erase_int(unsigned short sector);
194 static int cfi_flash_read_buf(unsigned short sector, int offset,
195 unsigned char *buffer, int numbytes);
196 static int cfi_flash_write_buf(unsigned short sector, int offset,
197 unsigned char *buffer, int numbytes);
198 static int cfi_flash_get_numsectors(void);
199 static int cfi_flash_get_sector_size(unsigned short sector);
200 static unsigned char *cfi_flash_get_memptr(unsigned short sector);
201 static int cfi_flash_get_blk(int addr);
202 static int cfi_flash_get_total_size(void);
203 static void cfi_flash_command(int command, unsigned short sector, int offset,
204 unsigned short data);
205 static int cfi_flash_write(unsigned short sector, int offset, unsigned char *buf,
207 static int cfi_flash_wait(unsigned short sector, int offset,unsigned short data);
208 static unsigned short cfi_flash_get_device_id(void);
209 static int cfi_flash_get_cfi(struct cfi_query *query, unsigned short *cfi_struct,
214 static flash_device_info_t flash_cfi_dev =
218 cfi_flash_sector_erase_int,
221 cfi_flash_get_numsectors,
222 cfi_flash_get_sector_size,
223 cfi_flash_get_memptr,
225 cfi_flash_get_total_size,
226 cfi_flash_get_total_size
229 /*********************************************************************/
230 /* 'meminfo' should be a pointer, but most C compilers will not */
231 /* allocate static storage for a pointer without calling */
232 /* non-portable functions such as 'new'. We also want to avoid */
233 /* the overhead of passing this pointer for every driver call. */
234 /* Systems with limited heap space will need to do this. */
235 /*********************************************************************/
236 static struct flashinfo meminfo; /* Flash information structure */
237 static int flashFamily = FLASH_UNDEFINED;
238 static int totalSize = 0;
239 static struct cfi_query query;
241 static unsigned short cfi_data_struct_29W160[] = {
242 0x0020, 0x0049, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
243 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
244 0x0051, 0x0052, 0x0059, 0x0002, 0x0000, 0x0040, 0x0000, 0x0000,
245 0x0000, 0x0000, 0x0000, 0x0027, 0x0036, 0x0000, 0x0000, 0x0004,
246 0x0000, 0x000a, 0x0000, 0x0004, 0x0000, 0x0003, 0x0000, 0x0015,
247 0x0002, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0040,
248 0x0000, 0x0001, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0080,
249 0x0000, 0x001e, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff,
250 0x0050, 0x0052, 0x0049, 0x0031, 0x0030, 0x0000, 0x0002, 0x0001,
251 0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0002,
252 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
253 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
254 0xffff, 0x0888, 0x252b, 0x8c84, 0x7dbc, 0xffff, 0xffff, 0xffff,
255 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
256 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
257 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
260 static UINT16 cfi_data_struct_29W200[] = {
261 0x0020, 0x0049, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
262 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
263 0x0051, 0x0052, 0x0059, 0x0002, 0x0000, 0x0040, 0x0000, 0x0000,
264 0x0000, 0x0000, 0x0000, 0x0027, 0x0036, 0x0000, 0x0000, 0x0004,
265 0x0000, 0x000a, 0x0000, 0x0004, 0x0000, 0x0003, 0x0000, 0x0015,
266 0x0002, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0040,
267 0x0000, 0x0001, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0080,
268 0x0000, 0x0002, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff,
269 0x0050, 0x0052, 0x0049, 0x0031, 0x0030, 0x0000, 0x0002, 0x0001,
270 0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0002,
271 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
272 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
273 0xffff, 0x0888, 0x252b, 0x8c84, 0x7dbc, 0xffff, 0xffff, 0xffff,
274 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
275 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
276 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
279 static UINT16 cfi_data_struct_26LV800B[] = {
280 0x0020, 0x0049, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
281 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
282 0x0051, 0x0052, 0x0059, 0x0002, 0x0000, 0x0040, 0x0000, 0x0000,
283 0x0000, 0x0000, 0x0000, 0x0027, 0x0036, 0x0000, 0x0000, 0x0004,
284 0x0000, 0x000a, 0x0000, 0x0004, 0x0000, 0x0003, 0x0000, 0x0015,
285 0x0002, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0040,
286 0x0000, 0x0001, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0080,
287 0x0000, 0x000e, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff,
288 0x0050, 0x0052, 0x0049, 0x0031, 0x0030, 0x0000, 0x0002, 0x0001,
289 0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0002,
290 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
291 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
292 0xffff, 0x0888, 0x252b, 0x8c84, 0x7dbc, 0xffff, 0xffff, 0xffff,
293 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
294 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
295 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
299 /*********************************************************************/
300 /* Init_flash is used to build a sector table from the information */
301 /* provided through the CFI query. This information is translated */
302 /* from erase_block information to base:offset information for each */
303 /* individual sector. This information is then stored in the meminfo */
304 /* structure, and used throughout the driver to access sector */
307 /* This is more efficient than deriving the sector base:offset */
308 /* information every time the memory map switches (since on the */
309 /* development platform can only map 64k at a time). If the entire */
310 /* flash memory array can be mapped in, then the addition static */
311 /* allocation for the meminfo structure can be eliminated, but the */
312 /* drivers will have to be re-written. */
314 /* The meminfo struct occupies 653 bytes of heap space, depending */
315 /* on the value of the define MAXSECTORS. Adjust to suit */
317 /*********************************************************************/
318 int cfi_flash_init(flash_device_info_t **flash_info)
320 struct flash_name_from_id fnfi[] = CFI_FLASH_DEVICES;
321 struct flash_name_from_id *fnfi_ptr;
322 int i=0, j=0, count=0;
324 unsigned short device_id;
325 int flipCFIGeometry = FALSE;
327 *flash_info = &flash_cfi_dev;
330 * a single 8k sector for sector 0. This is to allow
331 * the system to perform memory mapping to the device,
332 * even though the actual physical layout is unknown.
333 * Once mapped in, the CFI query will produce all
334 * relevant information.
339 meminfo.bank1start = 0;
340 meminfo.bank2start = 0;
342 meminfo.sec[0].size = 8192;
343 meminfo.sec[0].base = 0x00000;
344 meminfo.sec[0].bank = 1;
346 cfi_flash_command(FLASH_RESET, 0, 0, 0);
348 flash_cfi_dev.flash_device_id = device_id = cfi_flash_get_device_id();
349 flash_cfi_dev.flash_device_name[0] = '\0';
355 flashFamily = FLASH_INTEL;
371 // add ST flash device id here
373 // add ST flash device id here
374 flashFamily = FLASH_AMD;
381 // add SST flash device id here
383 // add SST flash device id here
384 flashFamily = FLASH_SST;
387 return FLASH_API_ERROR;
390 if (cfi_flash_get_cfi(&query, 0, flashFamily) == -1) {
394 cfi_flash_get_cfi(&query, cfi_data_struct_29W160, flashFamily);
397 cfi_flash_get_cfi(&query, cfi_data_struct_29W200, flashFamily);
400 cfi_flash_get_cfi(&query, cfi_data_struct_26LV800B, flashFamily);
401 strcpy( flash_cfi_dev.flash_device_name, "MX26LV800B" );
404 return FLASH_API_ERROR;
408 // need to determine if it top or bottom boot here
426 flipCFIGeometry = FALSE;
436 // add SST and ST flash device id here
439 // add SST and ST flash device id here
440 flipCFIGeometry = TRUE;
443 return FLASH_API_ERROR;
446 count=0;basecount=0L;
448 if (!flipCFIGeometry)
451 for (i=0; i<query.num_erase_blocks && basecount < query.device_size; i++) {
452 for(j=0; j<query.erase_block[i].num_sectors; j++) {
453 meminfo.sec[count].size = (int) query.erase_block[i].sector_size;
454 meminfo.sec[count].base = (int) basecount;
455 basecount += (int) query.erase_block[i].sector_size;
462 for (i = (query.num_erase_blocks - 1); i >= 0 && basecount < query.device_size; i--) {
463 for(j=0; j<query.erase_block[i].num_sectors; j++) {
464 meminfo.sec[count].size = (int) query.erase_block[i].sector_size;
465 meminfo.sec[count].base = (int) basecount;
466 basecount += (int) query.erase_block[i].sector_size;
472 meminfo.nsect = count;
473 totalSize = meminfo.sec[count-1].base + meminfo.sec[count-1].size;
475 if( flash_cfi_dev.flash_device_name[0] == '\0' ) {
476 for( fnfi_ptr = fnfi; fnfi_ptr->fnfi_id != 0; fnfi_ptr++ ) {
477 if( fnfi_ptr->fnfi_id == device_id ) {
478 strcpy( flash_cfi_dev.flash_device_name, fnfi_ptr->fnfi_name );
484 return (FLASH_API_OK);
487 /*********************************************************************/
488 /* Flash_sector_erase_int() is identical to flash_sector_erase(), */
489 /* except it will wait until the erase is completed before returning */
490 /* control to the calling function. This can be used in cases which */
491 /* require the program to hold until a sector is erased, without */
492 /* adding the wait check external to this function. */
493 /*********************************************************************/
494 static int cfi_flash_sector_erase_int(unsigned short sector)
498 for( i = 0; i < 3; i++ ) {
499 cfi_flash_command(FLASH_SERASE, sector, 0, 0);
500 if (cfi_flash_wait(sector, 0, 0xffff) == STATUS_READY)
504 return(FLASH_API_OK);
507 /*********************************************************************/
508 /* flash_read_buf() reads buffer of data from the specified */
509 /* offset from the sector parameter. */
510 /*********************************************************************/
511 static int cfi_flash_read_buf(unsigned short sector, int offset,
512 unsigned char *buffer, int numbytes)
516 fwp = (unsigned char *) cfi_flash_get_memptr(sector);
519 *buffer++ = *(fwp + offset);
524 return (FLASH_API_OK);
527 /*********************************************************************/
528 /* flash_write_buf() utilizes */
529 /* the unlock bypass mode of the flash device. This can remove */
530 /* significant overhead from the bulk programming operation, and */
531 /* when programming bulk data a sizeable performance increase can be */
533 /*********************************************************************/
534 static int cfi_flash_write_buf(unsigned short sector, int offset,
535 unsigned char *buffer, int numbytes)
537 int ret = FLASH_API_ERROR;
539 unsigned char *p = cfi_flash_get_memptr(sector) + offset;
541 /* After writing the flash block, compare the contents to the source
542 * buffer. Try to write the sector successfully up to three times.
544 for( i = 0; i < 3; i++ ) {
545 ret = cfi_flash_write(sector, offset, buffer, numbytes);
546 if( !memcmp( p, buffer, numbytes ) )
548 /* Erase and try again */
549 flash_sector_erase_int(sector);
550 ret = FLASH_API_ERROR;
553 if( ret == FLASH_API_ERROR )
554 printk( "Flash write error. Verify failed\n" );
559 /*********************************************************************/
560 /* Usefull funtion to return the number of sectors in the device. */
561 /* Can be used for functions which need to loop among all the */
562 /* sectors, or wish to know the number of the last sector. */
563 /*********************************************************************/
564 static int cfi_flash_get_numsectors(void)
566 return meminfo.nsect;
569 /*********************************************************************/
570 /* flash_get_sector_size() is provided for cases in which the size */
571 /* of a sector is required by a host application. The sector size */
572 /* (in bytes) is returned in the data location pointed to by the */
573 /* 'size' parameter. */
574 /*********************************************************************/
575 static int cfi_flash_get_sector_size(unsigned short sector)
577 return meminfo.sec[sector].size;
580 /*********************************************************************/
581 /* The purpose of flash_get_memptr() is to return a memory pointer */
582 /* which points to the beginning of memory space allocated for the */
583 /* flash. All function pointers are then referenced from this */
586 /* Different systems will implement this in different ways: */
587 /* possibilities include: */
588 /* - A direct memory pointer */
589 /* - A pointer to a memory map */
590 /* - A pointer to a hardware port from which the linear */
591 /* address is translated */
592 /* - Output of an MMU function / service */
594 /* Also note that this function expects the pointer to a specific */
595 /* sector of the device. This can be provided by dereferencing */
596 /* the pointer from a translated offset of the sector from a */
597 /* global base pointer (e.g. flashptr = base_pointer + sector_offset)*/
599 /* Important: Many AMD flash devices need both bank and or sector */
600 /* address bits to be correctly set (bank address bits are A18-A16, */
601 /* and sector address bits are A18-A12, or A12-A15). Flash parts */
602 /* which do not need these bits will ignore them, so it is safe to */
603 /* assume that every part will require these bits to be set. */
604 /*********************************************************************/
605 static unsigned char *cfi_flash_get_memptr(unsigned short sector)
607 unsigned char *memptr = (unsigned char*)
608 (FLASH_BASE + meminfo.sec[sector].base);
613 /*********************************************************************/
614 /* The purpose of flash_get_blk() is to return a the block number */
615 /* for a given memory address. */
616 /*********************************************************************/
617 static int cfi_flash_get_blk(int addr)
620 int last_blk = cfi_flash_get_numsectors();
621 int relative_addr = addr - (int) FLASH_BASE;
623 for(blk_start=0, i=0; i < relative_addr && blk_start < last_blk; blk_start++)
624 i += cfi_flash_get_sector_size(blk_start);
626 if( i > relative_addr )
628 blk_start--; // last blk, dec by 1
631 if( blk_start == last_blk )
633 printk("Address is too big.\n");
640 /************************************************************************/
641 /* The purpose of flash_get_total_size() is to return the total size of */
643 /************************************************************************/
644 static int cfi_flash_get_total_size(void)
649 /*********************************************************************/
650 /* Flash_command() is the main driver function. It performs */
651 /* every possible command available to AMD B revision */
652 /* flash parts. Note that this command is not used directly, but */
653 /* rather called through the API wrapper functions provided below. */
654 /*********************************************************************/
655 static void cfi_flash_command(int command, unsigned short sector, int offset,
658 volatile unsigned short *flashptr;
659 volatile unsigned short *flashbase;
661 flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
662 flashbase = (unsigned short *) cfi_flash_get_memptr(0);
664 switch (flashFamily) {
665 case FLASH_UNDEFINED:
666 /* These commands should work for AMD, Intel and SST flashes */
673 flashptr[0x5555] = 0xAA; /* unlock 1 */
674 flashptr[0x2AAA] = 0x55; /* unlock 2 */
675 flashptr[0x5555] = 0x90;
678 flashbase[0x5555] = 0xAA; /* unlock 1 */
679 flashbase[0x2AAA] = 0x55; /* unlock 2 */
680 flashbase[0x5555] = 0x90;
692 flashptr[0x555] = 0xAA; /* unlock 1 */
693 flashptr[0x2AA] = 0x55; /* unlock 2 */
694 flashptr[0x555] = 0x90;
697 flashptr[0x55] = 0x98;
700 flashptr[0x555] = 0xAA; /* unlock 1 */
701 flashptr[0x2AA] = 0x55; /* unlock 2 */
702 flashptr[0x555] = 0x20;
706 flashptr[offset/2] = data;
713 flashptr[0x555] = 0xAA; /* unlock 1 */
714 flashptr[0x2AA] = 0x55; /* unlock 2 */
715 flashptr[0x555] = 0x80;
716 flashptr[0x555] = 0xAA;
717 flashptr[0x2AA] = 0x55;
737 flashptr[offset/2] = data;
752 flashbase[0x5555] = 0xAA; /* unlock 1 */
753 flashbase[0x2AAA] = 0x55; /* unlock 2 */
754 flashbase[0x5555] = 0xf0;
757 flashbase[0x5555] = 0xAA; /* unlock 1 */
758 flashbase[0x2AAA] = 0x55; /* unlock 2 */
759 flashbase[0x5555] = 0x90;
762 flashbase[0x5555] = 0xAA; /* unlock 1 */
763 flashbase[0x2AAA] = 0x55; /* unlock 2 */
764 flashbase[0x5555] = 0x98;
769 flashbase[0x5555] = 0xAA; /* unlock 1 */
770 flashbase[0x2AAA] = 0x55; /* unlock 2 */
771 flashbase[0x5555] = 0xa0;
772 flashptr[offset/2] = data;
777 flashbase[0x5555] = 0xAA; /* unlock 1 */
778 flashbase[0x2AAA] = 0x55; /* unlock 2 */
779 flashbase[0x5555] = 0x80;
780 flashbase[0x5555] = 0xAA;
781 flashbase[0x2AAA] = 0x55;
793 /*********************************************************************/
794 /* flash_write extends the functionality of flash_program() by */
795 /* providing an faster way to program multiple data words, without */
796 /* needing the function overhead of looping algorithms which */
797 /* program word by word. This function utilizes fast pointers */
798 /* to quickly loop through bulk data. */
799 /*********************************************************************/
800 static int cfi_flash_write(unsigned short sector, int offset, unsigned char *buf,
804 src = (unsigned short *)buf;
806 if ((nbytes | offset) & 1) {
807 return FLASH_API_ERROR;
810 cfi_flash_command(FLASH_UB, 0, 0, 0);
812 cfi_flash_command(FLASH_PROG, sector, offset, *src);
813 if (cfi_flash_wait(sector, offset, *src) != STATUS_READY)
819 cfi_flash_command(FLASH_UBRESET, 0, 0, 0);
821 return (unsigned char*)src - buf;
824 /*********************************************************************/
825 /* flash_wait utilizes the DQ6, DQ5, and DQ2 polling algorithms */
826 /* described in the flash data book. It can quickly ascertain the */
827 /* operational status of the flash device, and return an */
828 /* appropriate status code (defined in flash.h) */
829 /*********************************************************************/
830 static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data)
832 volatile unsigned short *flashptr; /* flash window */
835 flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
837 if (flashFamily == FLASH_AMD || flashFamily == FLASH_SST) {
838 #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
840 d1 = flashptr[offset/2];
843 } while (!(d1 & 0x20));
845 d1 = flashptr[offset/2];
849 /* If the word written does not yet compare, try for another 100ms.
850 * This check is done for SST39VF800A.
853 for( i = 0; i < 10000; i++ ) {
854 d1 = flashptr[offset/2];
860 d1 = flashptr[offset/2];
863 cfi_flash_command(FLASH_RESET, 0, 0, 0);
864 return STATUS_TIMEOUT;
869 d1 = *flashptr; /* read data */
870 d1 ^= *flashptr; /* read it again and see what toggled */
871 if (d1 == 0) /* no toggles, nothing's happening */
873 } while (!(d1 & 0x20));
875 d1 = *flashptr; /* read data */
876 d1 ^= *flashptr; /* read it again and see what toggled */
879 cfi_flash_command(FLASH_RESET, 0, 0, 0);
880 return STATUS_TIMEOUT;
883 } else if (flashFamily == FLASH_INTEL) {
885 /* Wait for completion */
886 while(!(*flashptr & 0x80));
887 if (*flashptr & 0x30) {
889 cfi_flash_command(FLASH_RESET, 0, 0, 0);
890 return STATUS_TIMEOUT;
893 cfi_flash_command(FLASH_RESET, 0, 0, 0);
899 /*********************************************************************/
900 /* flash_get_device_id() will perform an autoselect sequence on the */
901 /* flash device, and return the device id of the component. */
902 /* This function automatically resets to read mode. */
903 /*********************************************************************/
904 static unsigned short cfi_flash_get_device_id(void)
906 volatile unsigned short *fwp; /* flash window */
907 unsigned short answer;
909 fwp = (unsigned short *) cfi_flash_get_memptr(0);
911 cfi_flash_command(FLASH_READ_ID, 0, 0, 0);
913 if (answer == ID_AM29LV320M) {
914 answer = *(fwp + 0xe);
915 answer = *(fwp + 0xf);
918 cfi_flash_command(FLASH_RESET, 0, 0, 0);
919 return( (unsigned short) answer );
922 /*********************************************************************/
923 /* flash_get_cfi() is the main CFI workhorse function. Due to it's */
924 /* complexity and size it need only be called once upon */
925 /* initializing the flash system. Once it is called, all operations */
926 /* are performed by looking at the meminfo structure. */
927 /* All possible care was made to make this algorithm as efficient as */
928 /* possible. 90% of all operations are memory reads, and all */
929 /* calculations are done using bit-shifts when possible */
930 /*********************************************************************/
931 static int cfi_flash_get_cfi(struct cfi_query *query, unsigned short *cfi_struct,
934 volatile unsigned short *fwp; /* flash window */
937 cfi_flash_command(FLASH_CFIQUERY, 0, 0, 0);
940 fwp = (unsigned short *) cfi_flash_get_memptr(0);
944 /* Initial house-cleaning */
945 for(i=0; i < 8; i++) {
946 query->erase_block[i].sector_size = 0;
947 query->erase_block[i].num_sectors = 0;
950 /* If not 'QRY', then we dont have a CFI enabled device in the socket */
951 if( fwp[0x10] != 'Q' &&
954 cfi_flash_command(FLASH_RESET, 0, 0, 0);
955 return(FLASH_API_ERROR);
959 query->device_size = (int) (((int)1) << temp);
961 query->num_erase_blocks = fwp[0x2C];
962 if(flashFamily == FLASH_SST)
963 query->num_erase_blocks = 1;
965 for(i=0; i < query->num_erase_blocks; i++) {
966 query->erase_block[i].num_sectors =
967 fwp[(0x2D+(4*i))] + (fwp[0x2E + (4*i)] << 8);
968 query->erase_block[i].num_sectors++;
969 query->erase_block[i].sector_size =
970 256 * (256 * fwp[(0x30+(4*i))] + fwp[(0x2F+(4*i))]);
973 cfi_flash_command(FLASH_RESET, 0, 0, 0);
974 return(FLASH_API_OK);