www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / shared / opensource / flash / cfiflash.c
1 /************************************************************************/
2 /*                                                                      */
3 /*  AMD CFI Enabled Flash Memory Drivers                                */
4 /*  File name: CFIFLASH.C                                               */
5 /*  Revision:  1.0  5/07/98                                             */
6 /*                                                                      */
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.,                                        */
18 /* One AMD Place,                                                       */
19 /* P.O. Box 3453                                                        */
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.                                */
30 /*                                                                      */ 
31 /************************************************************************/                        
32
33 /** Includes. */
34 #ifdef _CFE_                                                
35 #include "lib_types.h"
36 #include "lib_printf.h"
37 #include "lib_string.h"
38 #include "cfe_timer.h"
39 #include "bcm_map.h"
40 #define CFI_USLEEP(x) cfe_usleep(x)
41 #define printk  printf
42 #else       // linux
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)
49 #endif
50
51 #include "bcmtypes.h"
52 #include "board.h"
53 #include "flash_api.h"
54
55 /** Defines. **/
56 #ifndef NULL
57 #define NULL 0
58 #endif
59
60 #define MAXSECTORS  1024      /* maximum number of sectors supported */
61
62 /* Standard Boolean declarations */
63 #define TRUE            1
64 #define FALSE           0
65
66 /* Define different type of flash */
67 #define FLASH_UNDEFINED 0
68 #define FLASH_AMD       1
69 #define FLASH_INTEL     2
70 #define FLASH_SST       3
71
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 */
80
81 /* Return codes from flash_status */
82 #define STATUS_READY    0       /* ready for action */
83 #define STATUS_TIMEOUT  1       /* operation timed out */
84
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
92
93 #define ID_AM29LV160B   0x2249
94 #define ID_AM29LV160T   0x22C4
95
96 #define ID_AM29LV320T   0x22F6
97 #define ID_MX29LV320AT  0x22A7
98 #define ID_AM29LV320B   0x22F9
99 #define ID_MX29LV320AB  0x22A8
100 #define ID_MX29LV640BT  0x22C9
101
102 #define ID_AM29LV320M   0x227E
103 #define ID_AM29LV320MB  0x2200
104 #define ID_AM29LV320MT  0x2201
105
106 #define ID_SST39VF200A  0x2789
107 #define ID_SST39VF400A  0x2780
108 #define ID_SST39VF800A  0x2781
109 #define ID_SST39VF1601  0x234B
110 #define ID_SST39VF3201  0x235B
111 // add SST and ST flash device id 
112 #define ID_SST39VF3202  0x235A
113 #define ID_M29W320ET    0x2256
114 #define ID_SST39VF6401  0x236B
115 /* A list of Intel compatible device ID's - add others as needed */
116 #define ID_I28F160C3T   0x88C2
117 #define ID_I28F160C3B   0x88C3
118 #define ID_I28F320C3T   0x88C4
119 #define ID_I28F320C3B   0x88C5
120 #define ID_I28F640J3    0x0017
121
122 #define CFI_FLASH_DEVICES                   \
123          {{ID_AM29DL800T, "AM29DL800T"},    \
124           {ID_AM29DL800B, "AM29DL800B"},    \
125           {ID_AM29LV800T, "AM29LV800T"},    \
126           {ID_AM29LV800B, "AM29LV800B"},    \
127           {ID_AM29LV400B, "AM29LV400B"},    \
128           {ID_AM29LV200BT, "AM29LV200BT"},  \
129           {ID_AM29LV160B, "AM29LV160B"},    \
130           {ID_AM29LV160T, "AM29LV160T"},    \
131           {ID_AM29LV320T, "AM29LV320T"},    \
132           {ID_MX29LV320AT, "MX29LV320AT"},  \
133           {ID_AM29LV320B, "AM29LV320B"},    \
134           {ID_MX29LV320AB, "MX29LV320AB"},  \
135           {ID_AM29LV320M, "AM29LV320M"},    \
136           {ID_AM29LV320MB, "AM29LV320MB"},  \
137           {ID_AM29LV320MT, "AM29LV320MT"},  \
138           {ID_MX29LV640BT, "MX29LV640BT"},  \
139           {ID_SST39VF200A, "SST39VF200A"},  \
140           {ID_SST39VF400A, "SST39VF400A"},  \
141           {ID_SST39VF800A, "SST39VF800A"},  \
142           {ID_SST39VF1601, "SST39VF1601"},  \
143           {ID_SST39VF3201, "SST39VF3201"},  \
144           {ID_SST39VF3202, "SST39VF3202"},  \
145           {ID_M29W320ET,   "M29W320ET"},    \
146           {ID_SST39VF6401, "SST39VF6401"},  \
147           {ID_I28F160C3T, "I28F160C3T"},    \
148           {ID_I28F160C3B, "I28F160C3B"},    \
149           {ID_I28F320C3T, "I28F320C3T"},    \
150           {ID_I28F320C3B, "I28F320C3B"},    \
151           {ID_I28F640J3,  "I28F640J3"},     \
152           {0, ""}                           \
153         }
154
155 /** Structs. **/
156 /* A structure for identifying a flash part.  There is one for each
157  * of the flash part definitions.  We need to keep track of the
158  * sector organization, the address register used, and the size
159  * of the sectors.
160  */
161 struct flashinfo {
162      char *name;         /* "Am29DL800T", etc. */
163      unsigned long addr; /* physical address, once translated */
164      int areg;           /* Can be set to zero for all parts */
165      int nsect;          /* # of sectors -- 19 in LV, 22 in DL */
166      int bank1start;     /* first sector # in bank 1 */
167      int bank2start;     /* first sector # in bank 2, if DL part */
168  struct {
169     long size;           /* # of bytes in this sector */
170     long base;           /* offset from beginning of device */
171     int bank;            /* 1 or 2 for DL; 1 for LV */
172      } sec[MAXSECTORS];  /* per-sector info */
173 };
174
175 /*
176  * This structure holds all CFI query information as defined
177  * in the JEDEC standard. All information up to 
178  * primary_extended_query is standard among all manufactures
179  * with CFI enabled devices.
180  */
181
182 struct cfi_query {
183     int num_erase_blocks;       /* Number of sector defs. */
184         long device_size;               /* Device size in bytes */
185     struct {
186       unsigned long sector_size;    /* byte size of sector */
187       int num_sectors;      /* Num sectors of this size */
188     } erase_block[8];       /* Max of 256, but 8 is good */
189 };
190
191 struct flash_name_from_id {
192     unsigned short fnfi_id;
193     char fnfi_name[30];
194 };
195
196
197 /** Prototypes. **/
198 int cfi_flash_init(flash_device_info_t **flash_info);
199 static int cfi_flash_sector_erase_int(unsigned short sector);
200 static int cfi_flash_read_buf(unsigned short sector, int offset,
201     unsigned char *buffer, int numbytes);
202 static int cfi_flash_write_buf(unsigned short sector, int offset,
203     unsigned char *buffer, int numbytes);
204 static int cfi_flash_get_numsectors(void);
205 static int cfi_flash_get_sector_size(unsigned short sector);
206 static unsigned char *cfi_flash_get_memptr(unsigned short sector);
207 static int cfi_flash_get_blk(int addr);
208 static int cfi_flash_get_total_size(void);
209 static void cfi_flash_command(int command, unsigned short sector, int offset,
210     unsigned short data);
211 static int cfi_flash_write(unsigned short sector, int offset, unsigned char *buf,
212     int nbytes);
213 static int cfi_flash_wait(unsigned short sector, int offset,unsigned short data);
214 static unsigned short cfi_flash_get_device_id(void);
215 static int cfi_flash_get_cfi(struct cfi_query *query, unsigned short *cfi_struct,
216     int flashFamily);
217
218
219 /** Variables. **/
220 static flash_device_info_t flash_cfi_dev =
221     {
222         0xffff,
223         "",
224         cfi_flash_sector_erase_int,
225         cfi_flash_read_buf,
226         cfi_flash_write_buf,
227         cfi_flash_get_numsectors,
228         cfi_flash_get_sector_size,
229         cfi_flash_get_memptr,
230         cfi_flash_get_blk,
231         cfi_flash_get_total_size,
232         cfi_flash_get_total_size
233     };
234
235 /*********************************************************************/
236 /* 'meminfo' should be a pointer, but most C compilers will not      */
237 /* allocate static storage for a pointer without calling             */
238 /* non-portable functions such as 'new'.  We also want to avoid      */
239 /* the overhead of passing this pointer for every driver call.       */
240 /* Systems with limited heap space will need to do this.             */
241 /*********************************************************************/
242 static struct flashinfo meminfo; /* Flash information structure */
243 static int flashFamily = FLASH_UNDEFINED;
244 static int totalSize = 0;
245 static struct cfi_query query;
246
247 static unsigned short cfi_data_struct_29W160[] = {
248     0x0020, 0x0049, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
249     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
250     0x0051, 0x0052, 0x0059, 0x0002, 0x0000, 0x0040, 0x0000, 0x0000,
251     0x0000, 0x0000, 0x0000, 0x0027, 0x0036, 0x0000, 0x0000, 0x0004,
252     0x0000, 0x000a, 0x0000, 0x0004, 0x0000, 0x0003, 0x0000, 0x0015,
253     0x0002, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0040,
254     0x0000, 0x0001, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0080,
255     0x0000, 0x001e, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff,
256     0x0050, 0x0052, 0x0049, 0x0031, 0x0030, 0x0000, 0x0002, 0x0001,
257     0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0002,
258     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
259     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
260     0xffff, 0x0888, 0x252b, 0x8c84, 0x7dbc, 0xffff, 0xffff, 0xffff,
261     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
262     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
263     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
264 };
265
266 static UINT16 cfi_data_struct_29W200[] = {
267     0x0020, 0x0049, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
268     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
269     0x0051, 0x0052, 0x0059, 0x0002, 0x0000, 0x0040, 0x0000, 0x0000,
270     0x0000, 0x0000, 0x0000, 0x0027, 0x0036, 0x0000, 0x0000, 0x0004,
271     0x0000, 0x000a, 0x0000, 0x0004, 0x0000, 0x0003, 0x0000, 0x0015,
272     0x0002, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0040,
273     0x0000, 0x0001, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0080,
274     0x0000, 0x0002, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff,
275     0x0050, 0x0052, 0x0049, 0x0031, 0x0030, 0x0000, 0x0002, 0x0001,
276     0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0002,
277     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
278     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
279     0xffff, 0x0888, 0x252b, 0x8c84, 0x7dbc, 0xffff, 0xffff, 0xffff,
280     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
281     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
282     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
283 };
284
285 static UINT16 cfi_data_struct_26LV800B[] = {
286     0x0020, 0x0049, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
287     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
288     0x0051, 0x0052, 0x0059, 0x0002, 0x0000, 0x0040, 0x0000, 0x0000,
289     0x0000, 0x0000, 0x0000, 0x0027, 0x0036, 0x0000, 0x0000, 0x0004,
290     0x0000, 0x000a, 0x0000, 0x0004, 0x0000, 0x0003, 0x0000, 0x0015,
291     0x0002, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0040,
292     0x0000, 0x0001, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0080,
293     0x0000, 0x000e, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff,
294     0x0050, 0x0052, 0x0049, 0x0031, 0x0030, 0x0000, 0x0002, 0x0001,
295     0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0002,
296     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
297     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
298     0xffff, 0x0888, 0x252b, 0x8c84, 0x7dbc, 0xffff, 0xffff, 0xffff,
299     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
300     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
301     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
302 };
303
304
305 /*********************************************************************/
306 /* Init_flash is used to build a sector table from the information   */
307 /* provided through the CFI query.  This information is translated   */
308 /* from erase_block information to base:offset information for each  */
309 /* individual sector. This information is then stored in the meminfo */
310 /* structure, and used throughout the driver to access sector        */
311 /* information.                                                      */
312 /*                                                                   */
313 /* This is more efficient than deriving the sector base:offset       */
314 /* information every time the memory map switches (since on the      */
315 /* development platform can only map 64k at a time).  If the entire  */
316 /* flash memory array can be mapped in, then the addition static     */
317 /* allocation for the meminfo structure can be eliminated, but the   */
318 /* drivers will have to be re-written.                               */
319 /*                                                                   */
320 /* The meminfo struct occupies 653 bytes of heap space, depending    */
321 /* on the value of the define MAXSECTORS.  Adjust to suit            */
322 /* application                                                       */ 
323 /*********************************************************************/
324 int cfi_flash_init(flash_device_info_t **flash_info)
325 {
326     struct flash_name_from_id fnfi[] = CFI_FLASH_DEVICES;
327     struct flash_name_from_id *fnfi_ptr;
328     int i=0, j=0, count=0;
329     int basecount=0L;
330     unsigned short device_id;
331     int flipCFIGeometry = FALSE;
332
333     *flash_info = &flash_cfi_dev;
334
335     /* First, assume
336      * a single 8k sector for sector 0.  This is to allow
337      * the system to perform memory mapping to the device,
338      * even though the actual physical layout is unknown.
339      * Once mapped in, the CFI query will produce all
340      * relevant information.
341      */
342     meminfo.addr = 0L;
343     meminfo.areg = 0;
344     meminfo.nsect = 1;
345     meminfo.bank1start = 0;
346     meminfo.bank2start = 0;
347     
348     meminfo.sec[0].size = 8192;
349     meminfo.sec[0].base = 0x00000;
350     meminfo.sec[0].bank = 1;
351         
352     cfi_flash_command(FLASH_RESET, 0, 0, 0);
353
354     flash_cfi_dev.flash_device_id = device_id = cfi_flash_get_device_id();
355     flash_cfi_dev.flash_device_name[0] = '\0';
356     switch (device_id) {
357         case ID_I28F160C3B:
358         case ID_I28F320C3B:
359         case ID_I28F160C3T:
360         case ID_I28F320C3T:
361         case ID_I28F640J3:
362             flashFamily = FLASH_INTEL;
363             break;
364         case ID_AM29DL800B:
365         case ID_AM29LV800B:
366         case ID_AM29LV400B:   
367         case ID_AM29LV160B:
368         case ID_AM29LV320B:
369         case ID_MX29LV320AB:
370         case ID_AM29LV320MB:
371         case ID_AM29DL800T:
372         case ID_AM29LV800T:
373         case ID_AM29LV160T:
374         case ID_AM29LV320T:
375         case ID_MX29LV320AT:
376         case ID_AM29LV320MT:
377         case ID_AM29LV200BT:
378         case ID_MX29LV640BT:
379     // add ST flash device id  here
380         case ID_M29W320ET: 
381     // add ST flash device id  here
382             flashFamily = FLASH_AMD;
383             break;
384         case ID_SST39VF200A:
385         case ID_SST39VF400A:
386         case ID_SST39VF800A:
387         case ID_SST39VF1601:
388         case ID_SST39VF3201:
389     // add SST flash device id here
390         case ID_SST39VF3202:
391     // add SST flash device id here
392         case ID_SST39VF6401:
393             flashFamily = FLASH_SST;
394             break;
395         default:
396             return FLASH_API_ERROR;           
397     }
398
399     if (cfi_flash_get_cfi(&query, 0, flashFamily) == -1) {
400         switch(device_id) {
401         case ID_AM29LV160T:
402         case ID_AM29LV160B:
403             cfi_flash_get_cfi(&query, cfi_data_struct_29W160, flashFamily);
404             break;
405         case ID_AM29LV200BT:
406             cfi_flash_get_cfi(&query, cfi_data_struct_29W200, flashFamily);
407             break;
408         case ID_AM29LV800B:
409             cfi_flash_get_cfi(&query, cfi_data_struct_26LV800B, flashFamily);
410             strcpy( flash_cfi_dev.flash_device_name, "MX26LV800B" ); 
411             break;
412         default:
413             return FLASH_API_ERROR;           
414         }
415     }
416
417     // need to determine if it top or bottom boot here
418     switch (device_id)
419     {
420         case ID_AM29DL800B:
421         case ID_AM29LV800B:
422         case ID_AM29LV400B:   
423         case ID_AM29LV160B:
424         case ID_AM29LV320B:
425         case ID_MX29LV320AB:
426         case ID_AM29LV320MB:
427         case ID_I28F160C3B:
428         case ID_I28F320C3B:
429         case ID_I28F640J3:
430         case ID_I28F160C3T:
431         case ID_I28F320C3T:
432         case ID_SST39VF3201:
433         case ID_SST39VF6401:
434         case ID_SST39VF200A:
435         case ID_SST39VF400A:
436         case ID_SST39VF800A:
437             flipCFIGeometry = FALSE;
438             break;
439         case ID_AM29DL800T:
440         case ID_AM29LV800T:
441         case ID_AM29LV160T:
442         case ID_AM29LV320T:
443         case ID_MX29LV320AT:
444         case ID_AM29LV320MT:
445         case ID_AM29LV200BT:
446         case ID_SST39VF1601:
447         case ID_MX29LV640BT:
448     // add SST and ST flash device id here
449         case ID_SST39VF3202:
450         case ID_M29W320ET: 
451     // add SST and ST flash device id here
452             flipCFIGeometry = TRUE;
453             break;
454         default:
455             return FLASH_API_ERROR;           
456     }
457
458     count=0;basecount=0L;
459
460     if (!flipCFIGeometry)
461     {
462
463        for (i=0; i<query.num_erase_blocks && basecount < query.device_size; i++) {
464             for(j=0; j<query.erase_block[i].num_sectors; j++) {
465                 meminfo.sec[count].size = (int) query.erase_block[i].sector_size;
466                 meminfo.sec[count].base = (int) basecount;
467                 basecount += (int) query.erase_block[i].sector_size;
468                 count++;
469             }
470         }
471     }
472     else
473     {
474         for (i = (query.num_erase_blocks - 1); i >= 0 && basecount < query.device_size; i--) {
475             for(j=0; j<query.erase_block[i].num_sectors; j++) {
476                 meminfo.sec[count].size = (int) query.erase_block[i].sector_size;
477                 meminfo.sec[count].base = (int) basecount;
478                 basecount += (int) query.erase_block[i].sector_size;
479                 count++;
480             }
481         }
482     }
483
484     meminfo.nsect = count;
485     totalSize = meminfo.sec[count-1].base + meminfo.sec[count-1].size;
486
487     if( flash_cfi_dev.flash_device_name[0] == '\0' ) {
488         for( fnfi_ptr = fnfi; fnfi_ptr->fnfi_id != 0; fnfi_ptr++ ) {
489             if( fnfi_ptr->fnfi_id == device_id ) {
490                 strcpy( flash_cfi_dev.flash_device_name, fnfi_ptr->fnfi_name ); 
491                 break;
492             }
493         }
494     }
495
496     return (FLASH_API_OK);
497 }
498
499 /*********************************************************************/
500 /* Flash_sector_erase_int() is identical to flash_sector_erase(),    */
501 /* except it will wait until the erase is completed before returning */
502 /* control to the calling function.  This can be used in cases which */
503 /* require the program to hold until a sector is erased, without     */
504 /* adding the wait check external to this function.                  */
505 /*********************************************************************/
506 static int cfi_flash_sector_erase_int(unsigned short sector)
507 {
508     int i;
509
510     for( i = 0; i < 3; i++ ) {
511         cfi_flash_command(FLASH_SERASE, sector, 0, 0);
512         if (cfi_flash_wait(sector, 0, 0xffff) == STATUS_READY)
513             break;
514     }
515  
516     return(FLASH_API_OK);
517 }
518
519 /*********************************************************************/
520 /* flash_read_buf() reads buffer of data from the specified          */
521 /* offset from the sector parameter.                                 */
522 /*********************************************************************/
523 static int cfi_flash_read_buf(unsigned short sector, int offset,
524     unsigned char *buffer, int numbytes)
525 {
526     unsigned char *fwp;
527
528     fwp = (unsigned char *) cfi_flash_get_memptr(sector);
529
530     while (numbytes) {
531         *buffer++ = *(fwp + offset);
532         numbytes--;
533         fwp++;
534     }
535
536     return (FLASH_API_OK);
537 }
538
539 /*********************************************************************/
540 /* flash_write_buf() utilizes                                        */
541 /* the unlock bypass mode of the flash device.  This can remove      */
542 /* significant overhead from the bulk programming operation, and     */
543 /* when programming bulk data a sizeable performance increase can be */
544 /* observed.                                                         */
545 /*********************************************************************/
546 static int cfi_flash_write_buf(unsigned short sector, int offset,
547     unsigned char *buffer, int numbytes)
548 {
549     int ret = FLASH_API_ERROR;
550     int i;
551     unsigned char *p = cfi_flash_get_memptr(sector) + offset;
552 #ifdef _CFE_                                                
553     printk("Flash writing sector %d %x\n", sector, p);
554 #endif
555     /* After writing the flash block, compare the contents to the source
556      * buffer.  Try to write the sector successfully up to three times.
557      */
558     for( i = 0; i < 3; i++ ) {
559         ret = cfi_flash_write(sector, offset, buffer, numbytes);
560         if( !memcmp( p, buffer, numbytes ) )
561             break;
562         /* Erase and try again */
563         flash_sector_erase_int(sector);
564         ret = FLASH_API_ERROR;
565     }
566     // printk( "%c", i==0 ? '*' : ' ' );
567
568     if( ret == FLASH_API_ERROR )
569         printk( "Flash write sector %d error.  Verify failed\n", sector );
570
571     return( ret );
572 }
573
574 /*********************************************************************/
575 /* Usefull funtion to return the number of sectors in the device.    */
576 /* Can be used for functions which need to loop among all the        */
577 /* sectors, or wish to know the number of the last sector.           */
578 /*********************************************************************/
579 static int cfi_flash_get_numsectors(void)
580 {
581     return meminfo.nsect;
582 }
583
584 /*********************************************************************/
585 /* flash_get_sector_size() is provided for cases in which the size   */
586 /* of a sector is required by a host application.  The sector size   */
587 /* (in bytes) is returned in the data location pointed to by the     */
588 /* 'size' parameter.                                                 */
589 /*********************************************************************/
590 static int cfi_flash_get_sector_size(unsigned short sector)
591 {
592     return meminfo.sec[sector].size;
593 }
594
595 /*********************************************************************/
596 /* The purpose of flash_get_memptr() is to return a memory pointer   */
597 /* which points to the beginning of memory space allocated for the   */
598 /* flash.  All function pointers are then referenced from this       */
599 /* pointer.                                  */
600 /*                                                                   */
601 /* Different systems will implement this in different ways:          */
602 /* possibilities include:                                            */
603 /*  - A direct memory pointer                                        */
604 /*  - A pointer to a memory map                                      */
605 /*  - A pointer to a hardware port from which the linear             */
606 /*    address is translated                                          */
607 /*  - Output of an MMU function / service                            */
608 /*                                                                   */
609 /* Also note that this function expects the pointer to a specific    */
610 /* sector of the device.  This can be provided by dereferencing      */
611 /* the pointer from a translated offset of the sector from a         */
612 /* global base pointer (e.g. flashptr = base_pointer + sector_offset)*/
613 /*                                                                   */
614 /* Important: Many AMD flash devices need both bank and or sector    */
615 /* address bits to be correctly set (bank address bits are A18-A16,  */
616 /* and sector address bits are A18-A12, or A12-A15).  Flash parts    */
617 /* which do not need these bits will ignore them, so it is safe to   */
618 /* assume that every part will require these bits to be set.         */
619 /*********************************************************************/
620 static unsigned char *cfi_flash_get_memptr(unsigned short sector)
621 {
622     unsigned char *memptr = (unsigned char*)
623         (FLASH_BASE + meminfo.sec[sector].base);
624
625     return (memptr);
626 }
627
628 /*********************************************************************/
629 /* The purpose of flash_get_blk() is to return a the block number    */
630 /* for a given memory address.                                       */
631 /*********************************************************************/
632 static int cfi_flash_get_blk(int addr)
633 {
634     int blk_start, i;
635     int last_blk = cfi_flash_get_numsectors();
636     int relative_addr = addr - (int) FLASH_BASE;
637
638     for(blk_start=0, i=0; i < relative_addr && blk_start < last_blk; blk_start++)
639         i += cfi_flash_get_sector_size(blk_start);
640
641     if( i > relative_addr )
642     {
643         blk_start--;        // last blk, dec by 1
644     }
645     else
646         if( blk_start == last_blk )
647         {
648             printk("Address is too big.\n");
649             blk_start = -1;
650         }
651
652     return( blk_start );
653 }
654
655 /************************************************************************/
656 /* The purpose of flash_get_total_size() is to return the total size of */
657 /* the flash                                                            */
658 /************************************************************************/
659 static int cfi_flash_get_total_size(void)
660 {
661     return totalSize;
662 }
663
664 /*********************************************************************/
665 /* Flash_command() is the main driver function.  It performs         */
666 /* every possible command available to AMD B revision                */
667 /* flash parts. Note that this command is not used directly, but     */
668 /* rather called through the API wrapper functions provided below.   */
669 /*********************************************************************/
670 static void cfi_flash_command(int command, unsigned short sector, int offset,
671     unsigned short data)
672 {
673     volatile unsigned short *flashptr;
674     volatile unsigned short *flashbase;
675
676     flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
677     flashbase = (unsigned short *) cfi_flash_get_memptr(0);
678     
679     switch (flashFamily) {
680     case FLASH_UNDEFINED:
681         /* These commands should work for AMD, Intel and SST flashes */
682         switch (command) {
683         case FLASH_RESET:
684             flashptr[0] = 0xF0;
685             flashptr[0] = 0xFF;
686             break;
687         case FLASH_READ_ID:
688             flashptr[0x5555] = 0xAA;       /* unlock 1 */
689             flashptr[0x2AAA] = 0x55;       /* unlock 2 */
690             flashptr[0x5555] = 0x90;
691             break;
692         case FLASH_CFIQUERY:
693             flashbase[0x5555] = 0xAA;       /* unlock 1 */
694             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
695             flashbase[0x5555] = 0x90;
696             break;
697         default:
698             break;
699         }
700         break;
701     case FLASH_AMD:
702         switch (command) {
703         case FLASH_RESET:
704             flashptr[0] = 0xF0;
705             break;
706         case FLASH_READ_ID:
707             flashptr[0x555] = 0xAA;       /* unlock 1 */
708             flashptr[0x2AA] = 0x55;       /* unlock 2 */
709             flashptr[0x555] = 0x90;
710             break;
711         case FLASH_CFIQUERY:
712             flashptr[0x55] = 0x98;
713             break;
714         case FLASH_UB:
715             flashptr[0x555] = 0xAA;       /* unlock 1 */
716             flashptr[0x2AA] = 0x55;       /* unlock 2 */
717             flashptr[0x555] = 0x20;
718             break;
719         case FLASH_PROG:
720             flashptr[0] = 0xA0;
721             flashptr[offset/2] = data;
722             break;
723         case FLASH_UBRESET:
724             flashptr[0] = 0x90;
725             flashptr[0] = 0x00;
726             break;
727         case FLASH_SERASE:
728             flashptr[0x555] = 0xAA;       /* unlock 1 */
729             flashptr[0x2AA] = 0x55;       /* unlock 2 */
730             flashptr[0x555] = 0x80;
731             flashptr[0x555] = 0xAA;
732             flashptr[0x2AA] = 0x55;
733             flashptr[0] = 0x30;
734             break;
735         default:
736             break;
737         }
738         break;
739     case FLASH_INTEL:
740         switch (command) {
741         case FLASH_RESET:
742             flashptr[0] = 0xFF;
743             break;
744         case FLASH_READ_ID:
745             flashptr[0] = 0x90;
746             break;
747         case FLASH_CFIQUERY:
748             flashptr[0] = 0x98;
749             break;
750         case FLASH_PROG:
751             flashptr[0] = 0x40;
752             flashptr[offset/2] = data;
753             break;
754         case FLASH_SERASE:
755             //flashptr[0] = 0x60; Block Unlock is not required.
756             //flashptr[0] = 0xD0;
757             flashptr[0] = 0x20;
758             flashptr[0] = 0xD0;
759             break;
760         default:
761             break;
762         }
763         break;
764     case FLASH_SST:
765         switch (command) {
766         case FLASH_RESET:
767             flashbase[0x5555] = 0xAA;       /* unlock 1 */
768             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
769             flashbase[0x5555] = 0xf0;
770             break;
771         case FLASH_READ_ID:
772             flashbase[0x5555] = 0xAA;       /* unlock 1 */
773             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
774             flashbase[0x5555] = 0x90;
775             break;
776         case FLASH_CFIQUERY:
777             flashbase[0x5555] = 0xAA;       /* unlock 1 */
778             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
779             flashbase[0x5555] = 0x98;
780             break;
781         case FLASH_UB:
782             break;
783         case FLASH_PROG:
784             flashbase[0x5555] = 0xAA;       /* unlock 1 */
785             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
786             flashbase[0x5555] = 0xa0;
787             flashptr[offset/2] = data;
788             break;
789         case FLASH_UBRESET:
790             break;
791         case FLASH_SERASE:
792             flashbase[0x5555] = 0xAA;       /* unlock 1 */
793             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
794             flashbase[0x5555] = 0x80;
795             flashbase[0x5555] = 0xAA;
796             flashbase[0x2AAA] = 0x55;
797             flashptr[0] = 0x30;
798             break;
799         default:
800             break;
801         }
802         break;
803     default:
804         break;
805     }
806 }
807
808 /*********************************************************************/
809 /* flash_write extends the functionality of flash_program() by       */
810 /* providing an faster way to program multiple data words, without   */
811 /* needing the function overhead of looping algorithms which         */
812 /* program word by word.  This function utilizes fast pointers       */
813 /* to quickly loop through bulk data.                                */
814 /*********************************************************************/
815 static int cfi_flash_write(unsigned short sector, int offset, unsigned char *buf,
816     int nbytes)
817 {
818     unsigned short *src;
819     src = (unsigned short *)buf;
820
821     if ((nbytes | offset) & 1) {
822         return FLASH_API_ERROR;
823     }
824
825     cfi_flash_command(FLASH_UB, 0, 0, 0);
826     while (nbytes > 0) {
827         cfi_flash_command(FLASH_PROG, sector, offset, *src);
828         if (cfi_flash_wait(sector, offset, *src) != STATUS_READY)
829             break;
830         offset +=2;
831         nbytes -=2;
832         src++;
833     }
834     cfi_flash_command(FLASH_UBRESET, 0, 0, 0);
835     
836     return (unsigned char*)src - buf;
837 }
838
839 /*********************************************************************/
840 /* flash_wait utilizes the DQ6, DQ5, and DQ2 polling algorithms      */
841 /* described in the flash data book.  It can quickly ascertain the   */
842 /* operational status of the flash device, and return an             */
843 /* appropriate status code (defined in flash.h)                      */
844 /*********************************************************************/
845 static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data)
846 {
847     volatile unsigned short *flashptr; /* flash window */
848     unsigned short d1;
849
850     flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
851
852     if (flashFamily == FLASH_AMD || flashFamily == FLASH_SST) {
853 /* 6338 and 6358 for different reasons do a 'double read' when reading 16 bit from EBI */
854 #if defined(_BCM96338_) || defined(CONFIG_BCM96338) || defined(_BCM96358_) || defined(CONFIG_BCM96358)
855         do {
856             d1 = flashptr[offset/2];
857             if (d1 == data)
858                 return STATUS_READY;
859         } while (!(d1 & 0x20));
860
861         d1 = flashptr[offset/2];
862
863         if (d1 != data) {
864
865             /* If the word written does not yet compare, try for another 100ms.
866              * This check is done for SST39VF800A.
867              */
868             int i;
869             for( i = 0; i < 10000; i++ ) {
870                 d1 = flashptr[offset/2];
871                 if (d1 == data)
872                     return STATUS_READY;
873                 CFI_USLEEP(10);
874             }
875
876             d1 = flashptr[offset/2];
877
878             if (d1 != data) {
879                 cfi_flash_command(FLASH_RESET, 0, 0, 0);
880                 return STATUS_TIMEOUT;
881             }
882         }
883 #else
884         do {
885             d1 = *flashptr;    /* read data */
886             d1 ^= *flashptr;   /* read it again and see what toggled */
887             if (d1 == 0)       /* no toggles, nothing's happening */
888                 return STATUS_READY;
889         } while (!(d1 & 0x20));
890
891         d1 = *flashptr;        /* read data */
892         d1 ^= *flashptr;   /* read it again and see what toggled */
893
894         if (d1 != 0) {
895             cfi_flash_command(FLASH_RESET, 0, 0, 0);
896             return STATUS_TIMEOUT;
897         }
898 #endif
899     } else if (flashFamily == FLASH_INTEL) {
900         flashptr[0] = 0x70;
901         /* Wait for completion */
902         while(!(*flashptr & 0x80));
903         if (*flashptr & 0x30) {
904             flashptr[0] = 0x50;
905             printk("CFI: Wait error &d\n", *flashptr);
906             cfi_flash_command(FLASH_RESET, 0, 0, 0);
907             return STATUS_TIMEOUT;
908         }
909         flashptr[0] = 0x50;
910         cfi_flash_command(FLASH_RESET, 0, 0, 0);
911     }
912     
913     return STATUS_READY;
914 }
915
916 /*********************************************************************/
917 /* flash_get_device_id() will perform an autoselect sequence on the  */
918 /* flash device, and return the device id of the component.          */
919 /* This function automatically resets to read mode.                  */
920 /*********************************************************************/
921 static unsigned short cfi_flash_get_device_id(void)
922 {
923     volatile unsigned short *fwp; /* flash window */
924     unsigned short answer;
925     
926     fwp = (unsigned short *) cfi_flash_get_memptr(0);
927     
928     cfi_flash_command(FLASH_READ_ID, 0, 0, 0);
929     answer = *(fwp + 1);
930     if (answer == ID_AM29LV320M) {
931         answer = *(fwp + 0xe);
932         answer = *(fwp + 0xf);
933     }
934     
935     cfi_flash_command(FLASH_RESET, 0, 0, 0);
936     return( (unsigned short) answer );
937 }
938
939 /*********************************************************************/
940 /* flash_get_cfi() is the main CFI workhorse function.  Due to it's  */
941 /* complexity and size it need only be called once upon              */
942 /* initializing the flash system.  Once it is called, all operations */
943 /* are performed by looking at the meminfo structure.                */
944 /* All possible care was made to make this algorithm as efficient as */
945 /* possible.  90% of all operations are memory reads, and all        */
946 /* calculations are done using bit-shifts when possible              */
947 /*********************************************************************/
948 static int cfi_flash_get_cfi(struct cfi_query *query, unsigned short *cfi_struct,
949     int flashFamily)
950 {
951     volatile unsigned short *fwp; /* flash window */
952     int i=0, temp=0;
953
954     cfi_flash_command(FLASH_CFIQUERY, 0, 0, 0);
955     
956     if (cfi_struct == 0)
957         fwp = (unsigned short *) cfi_flash_get_memptr(0);
958     else
959         fwp = cfi_struct;
960     
961     /* Initial house-cleaning */
962     for(i=0; i < 8; i++) {
963         query->erase_block[i].sector_size = 0;
964         query->erase_block[i].num_sectors = 0;
965     }
966     
967     /* If not 'QRY', then we dont have a CFI enabled device in the socket */
968     if( fwp[0x10] != 'Q' &&
969         fwp[0x11] != 'R' &&
970         fwp[0x12] != 'Y') {
971         cfi_flash_command(FLASH_RESET, 0, 0, 0);
972         return(FLASH_API_ERROR);
973     }
974     
975     temp = fwp[0x27];
976     query->device_size = (int) (((int)1) << temp);
977     
978     query->num_erase_blocks = fwp[0x2C];
979     if(flashFamily == FLASH_SST)
980         query->num_erase_blocks = 1;
981     
982     for(i=0; i < query->num_erase_blocks; i++) {
983         query->erase_block[i].num_sectors =
984             fwp[(0x2D+(4*i))] + (fwp[0x2E + (4*i)] << 8);
985         query->erase_block[i].num_sectors++;
986         query->erase_block[i].sector_size =
987             256 * (256 * fwp[(0x30+(4*i))] + fwp[(0x2F+(4*i))]);
988     }
989     
990     cfi_flash_command(FLASH_RESET, 0, 0, 0);
991     return(FLASH_API_OK);
992 }
993