and added files
[bcm963xx.git] / shared / src / 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
101 #define ID_AM29LV320M   0x227E
102 #define ID_AM29LV320MB  0x2200
103 #define ID_AM29LV320MT  0x2201
104
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
118
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"},    \
146           {0, ""}                           \
147         }
148
149 /** Structs. **/
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
153  * of the sectors.
154  */
155 struct flashinfo {
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 */
162  struct {
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 */
167 };
168
169 /*
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.
174  */
175
176 struct cfi_query {
177     int num_erase_blocks;       /* Number of sector defs. */
178         long device_size;               /* Device size in bytes */
179     struct {
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 */
183 };
184
185 struct flash_name_from_id {
186     unsigned short fnfi_id;
187     char fnfi_name[30];
188 };
189
190
191 /** Prototypes. **/
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,
206     int nbytes);
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,
210     int flashFamily);
211
212
213 /** Variables. **/
214 static flash_device_info_t flash_cfi_dev =
215     {
216         0xffff,
217         "",
218         cfi_flash_sector_erase_int,
219         cfi_flash_read_buf,
220         cfi_flash_write_buf,
221         cfi_flash_get_numsectors,
222         cfi_flash_get_sector_size,
223         cfi_flash_get_memptr,
224         cfi_flash_get_blk,
225         cfi_flash_get_total_size,
226         cfi_flash_get_total_size
227     };
228
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;
240
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
258 };
259
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
277 };
278
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
296 };
297
298
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        */
305 /* information.                                                      */
306 /*                                                                   */
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.                               */
313 /*                                                                   */
314 /* The meminfo struct occupies 653 bytes of heap space, depending    */
315 /* on the value of the define MAXSECTORS.  Adjust to suit            */
316 /* application                                                       */ 
317 /*********************************************************************/
318 int cfi_flash_init(flash_device_info_t **flash_info)
319 {
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;
323     int basecount=0L;
324     unsigned short device_id;
325     int flipCFIGeometry = FALSE;
326
327     *flash_info = &flash_cfi_dev;
328
329     /* First, assume
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.
335      */
336     meminfo.addr = 0L;
337     meminfo.areg = 0;
338     meminfo.nsect = 1;
339     meminfo.bank1start = 0;
340     meminfo.bank2start = 0;
341     
342     meminfo.sec[0].size = 8192;
343     meminfo.sec[0].base = 0x00000;
344     meminfo.sec[0].bank = 1;
345         
346     cfi_flash_command(FLASH_RESET, 0, 0, 0);
347
348     flash_cfi_dev.flash_device_id = device_id = cfi_flash_get_device_id();
349     flash_cfi_dev.flash_device_name[0] = '\0';
350     switch (device_id) {
351         case ID_I28F160C3B:
352         case ID_I28F320C3B:
353         case ID_I28F160C3T:
354         case ID_I28F320C3T:
355             flashFamily = FLASH_INTEL;
356             break;
357         case ID_AM29DL800B:
358         case ID_AM29LV800B:
359         case ID_AM29LV400B:   
360         case ID_AM29LV160B:
361         case ID_AM29LV320B:
362         case ID_MX29LV320AB:
363         case ID_AM29LV320MB:
364         case ID_AM29DL800T:
365         case ID_AM29LV800T:
366         case ID_AM29LV160T:
367         case ID_AM29LV320T:
368         case ID_MX29LV320AT:
369         case ID_AM29LV320MT:
370         case ID_AM29LV200BT:
371     // add ST flash device id  here
372         case ID_M29W320ET: 
373     // add ST flash device id  here
374             flashFamily = FLASH_AMD;
375             break;
376         case ID_SST39VF200A:
377         case ID_SST39VF400A:
378         case ID_SST39VF800A:
379         case ID_SST39VF1601:
380         case ID_SST39VF3201:
381     // add SST flash device id here
382         case ID_SST39VF3202:
383     // add SST flash device id here
384             flashFamily = FLASH_SST;
385             break;
386         default:
387             return FLASH_API_ERROR;           
388     }
389
390     if (cfi_flash_get_cfi(&query, 0, flashFamily) == -1) {
391         switch(device_id) {
392         case ID_AM29LV160T:
393         case ID_AM29LV160B:
394             cfi_flash_get_cfi(&query, cfi_data_struct_29W160, flashFamily);
395             break;
396         case ID_AM29LV200BT:
397             cfi_flash_get_cfi(&query, cfi_data_struct_29W200, flashFamily);
398             break;
399         case ID_AM29LV800B:
400             cfi_flash_get_cfi(&query, cfi_data_struct_26LV800B, flashFamily);
401             strcpy( flash_cfi_dev.flash_device_name, "MX26LV800B" ); 
402             break;
403         default:
404             return FLASH_API_ERROR;           
405         }
406     }
407
408     // need to determine if it top or bottom boot here
409     switch (device_id)
410     {
411         case ID_AM29DL800B:
412         case ID_AM29LV800B:
413         case ID_AM29LV400B:   
414         case ID_AM29LV160B:
415         case ID_AM29LV320B:
416         case ID_MX29LV320AB:
417         case ID_AM29LV320MB:
418         case ID_I28F160C3B:
419         case ID_I28F320C3B:
420         case ID_I28F160C3T:
421         case ID_I28F320C3T:
422         case ID_SST39VF3201:
423         case ID_SST39VF200A:
424         case ID_SST39VF400A:
425         case ID_SST39VF800A:
426             flipCFIGeometry = FALSE;
427             break;
428         case ID_AM29DL800T:
429         case ID_AM29LV800T:
430         case ID_AM29LV160T:
431         case ID_AM29LV320T:
432         case ID_MX29LV320AT:
433         case ID_AM29LV320MT:
434         case ID_AM29LV200BT:
435         case ID_SST39VF1601:
436     // add SST and ST flash device id here
437         case ID_SST39VF3202:
438         case ID_M29W320ET: 
439     // add SST and ST flash device id here
440             flipCFIGeometry = TRUE;
441             break;
442         default:
443             return FLASH_API_ERROR;           
444     }
445
446     count=0;basecount=0L;
447
448     if (!flipCFIGeometry)
449     {
450
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;
456                 count++;
457             }
458         }
459     }
460     else
461     {
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;
467                 count++;
468             }
469         }
470     }
471
472     meminfo.nsect = count;
473     totalSize = meminfo.sec[count-1].base + meminfo.sec[count-1].size;
474
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 ); 
479                 break;
480             }
481         }
482     }
483
484     return (FLASH_API_OK);
485 }
486
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)
495 {
496     int i;
497
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)
501             break;
502     }
503
504     return(FLASH_API_OK);
505 }
506
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)
513 {
514     unsigned char *fwp;
515
516     fwp = (unsigned char *) cfi_flash_get_memptr(sector);
517
518     while (numbytes) {
519         *buffer++ = *(fwp + offset);
520         numbytes--;
521         fwp++;
522     }
523
524     return (FLASH_API_OK);
525 }
526
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 */
532 /* observed.                                                         */
533 /*********************************************************************/
534 static int cfi_flash_write_buf(unsigned short sector, int offset,
535     unsigned char *buffer, int numbytes)
536 {
537     int ret = FLASH_API_ERROR;
538     int i;
539     unsigned char *p = cfi_flash_get_memptr(sector) + offset;
540
541     /* After writing the flash block, compare the contents to the source
542      * buffer.  Try to write the sector successfully up to three times.
543      */
544     for( i = 0; i < 3; i++ ) {
545         ret = cfi_flash_write(sector, offset, buffer, numbytes);
546         if( !memcmp( p, buffer, numbytes ) )
547             break;
548         /* Erase and try again */
549         flash_sector_erase_int(sector);
550         ret = FLASH_API_ERROR;
551     }
552
553     if( ret == FLASH_API_ERROR )
554         printk( "Flash write error.  Verify failed\n" );
555
556     return( ret );
557 }
558
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)
565 {
566     return meminfo.nsect;
567 }
568
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)
576 {
577     return meminfo.sec[sector].size;
578 }
579
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       */
584 /* pointer.                                  */
585 /*                                                                   */
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                            */
593 /*                                                                   */
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)*/
598 /*                                                                   */
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)
606 {
607     unsigned char *memptr = (unsigned char*)
608         (FLASH_BASE + meminfo.sec[sector].base);
609
610     return (memptr);
611 }
612
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)
618 {
619     int blk_start, i;
620     int last_blk = cfi_flash_get_numsectors();
621     int relative_addr = addr - (int) FLASH_BASE;
622
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);
625
626     if( i > relative_addr )
627     {
628         blk_start--;        // last blk, dec by 1
629     }
630     else
631         if( blk_start == last_blk )
632         {
633             printk("Address is too big.\n");
634             blk_start = -1;
635         }
636
637     return( blk_start );
638 }
639
640 /************************************************************************/
641 /* The purpose of flash_get_total_size() is to return the total size of */
642 /* the flash                                                            */
643 /************************************************************************/
644 static int cfi_flash_get_total_size(void)
645 {
646     return totalSize;
647 }
648
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,
656     unsigned short data)
657 {
658     volatile unsigned short *flashptr;
659     volatile unsigned short *flashbase;
660
661     flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
662     flashbase = (unsigned short *) cfi_flash_get_memptr(0);
663     
664     switch (flashFamily) {
665     case FLASH_UNDEFINED:
666         /* These commands should work for AMD, Intel and SST flashes */
667         switch (command) {
668         case FLASH_RESET:
669             flashptr[0] = 0xF0;
670             flashptr[0] = 0xFF;
671             break;
672         case FLASH_READ_ID:
673             flashptr[0x5555] = 0xAA;       /* unlock 1 */
674             flashptr[0x2AAA] = 0x55;       /* unlock 2 */
675             flashptr[0x5555] = 0x90;
676             break;
677         case FLASH_CFIQUERY:
678             flashbase[0x5555] = 0xAA;       /* unlock 1 */
679             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
680             flashbase[0x5555] = 0x90;
681             break;
682         default:
683             break;
684         }
685         break;
686     case FLASH_AMD:
687         switch (command) {
688         case FLASH_RESET:
689             flashptr[0] = 0xF0;
690             break;
691         case FLASH_READ_ID:
692             flashptr[0x555] = 0xAA;       /* unlock 1 */
693             flashptr[0x2AA] = 0x55;       /* unlock 2 */
694             flashptr[0x555] = 0x90;
695             break;
696         case FLASH_CFIQUERY:
697             flashptr[0x55] = 0x98;
698             break;
699         case FLASH_UB:
700             flashptr[0x555] = 0xAA;       /* unlock 1 */
701             flashptr[0x2AA] = 0x55;       /* unlock 2 */
702             flashptr[0x555] = 0x20;
703             break;
704         case FLASH_PROG:
705             flashptr[0] = 0xA0;
706             flashptr[offset/2] = data;
707             break;
708         case FLASH_UBRESET:
709             flashptr[0] = 0x90;
710             flashptr[0] = 0x00;
711             break;
712         case FLASH_SERASE:
713             flashptr[0x555] = 0xAA;       /* unlock 1 */
714             flashptr[0x2AA] = 0x55;       /* unlock 2 */
715             flashptr[0x555] = 0x80;
716             flashptr[0x555] = 0xAA;
717             flashptr[0x2AA] = 0x55;
718             flashptr[0] = 0x30;
719             break;
720         default:
721             break;
722         }
723         break;
724     case FLASH_INTEL:
725         switch (command) {
726         case FLASH_RESET:
727             flashptr[0] = 0xFF;
728             break;
729         case FLASH_READ_ID:
730             flashptr[0] = 0x90;
731             break;
732         case FLASH_CFIQUERY:
733             flashptr[0] = 0x98;
734             break;
735         case FLASH_PROG:
736             flashptr[0] = 0x40;
737             flashptr[offset/2] = data;
738             break;
739         case FLASH_SERASE:
740             flashptr[0] = 0x60;
741             flashptr[0] = 0xD0;
742             flashptr[0] = 0x20;
743             flashptr[0] = 0xD0;
744             break;
745         default:
746             break;
747         }
748         break;
749     case FLASH_SST:
750         switch (command) {
751         case FLASH_RESET:
752             flashbase[0x5555] = 0xAA;       /* unlock 1 */
753             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
754             flashbase[0x5555] = 0xf0;
755             break;
756         case FLASH_READ_ID:
757             flashbase[0x5555] = 0xAA;       /* unlock 1 */
758             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
759             flashbase[0x5555] = 0x90;
760             break;
761         case FLASH_CFIQUERY:
762             flashbase[0x5555] = 0xAA;       /* unlock 1 */
763             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
764             flashbase[0x5555] = 0x98;
765             break;
766         case FLASH_UB:
767             break;
768         case FLASH_PROG:
769             flashbase[0x5555] = 0xAA;       /* unlock 1 */
770             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
771             flashbase[0x5555] = 0xa0;
772             flashptr[offset/2] = data;
773             break;
774         case FLASH_UBRESET:
775             break;
776         case FLASH_SERASE:
777             flashbase[0x5555] = 0xAA;       /* unlock 1 */
778             flashbase[0x2AAA] = 0x55;       /* unlock 2 */
779             flashbase[0x5555] = 0x80;
780             flashbase[0x5555] = 0xAA;
781             flashbase[0x2AAA] = 0x55;
782             flashptr[0] = 0x30;
783             break;
784         default:
785             break;
786         }
787         break;
788     default:
789         break;
790     }
791 }
792
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,
801     int nbytes)
802 {
803     unsigned short *src;
804     src = (unsigned short *)buf;
805
806     if ((nbytes | offset) & 1) {
807         return FLASH_API_ERROR;
808     }
809
810     cfi_flash_command(FLASH_UB, 0, 0, 0);
811     while (nbytes > 0) {
812         cfi_flash_command(FLASH_PROG, sector, offset, *src);
813         if (cfi_flash_wait(sector, offset, *src) != STATUS_READY)
814             break;
815         offset +=2;
816         nbytes -=2;
817         src++;
818     }
819     cfi_flash_command(FLASH_UBRESET, 0, 0, 0);
820     
821     return (unsigned char*)src - buf;
822 }
823
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)
831 {
832     volatile unsigned short *flashptr; /* flash window */
833     unsigned short d1;
834
835     flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
836
837     if (flashFamily == FLASH_AMD || flashFamily == FLASH_SST) {
838 #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
839         do {
840             d1 = flashptr[offset/2];
841             if (d1 == data)
842                 return STATUS_READY;
843         } while (!(d1 & 0x20));
844
845         d1 = flashptr[offset/2];
846
847         if (d1 != data) {
848
849             /* If the word written does not yet compare, try for another 100ms.
850              * This check is done for SST39VF800A.
851              */
852             int i;
853             for( i = 0; i < 10000; i++ ) {
854                 d1 = flashptr[offset/2];
855                 if (d1 == data)
856                     return STATUS_READY;
857                 CFI_USLEEP(10);
858             }
859
860             d1 = flashptr[offset/2];
861
862             if (d1 != data) {
863                 cfi_flash_command(FLASH_RESET, 0, 0, 0);
864                 return STATUS_TIMEOUT;
865             }
866         }
867 #else
868         do {
869             d1 = *flashptr;    /* read data */
870             d1 ^= *flashptr;   /* read it again and see what toggled */
871             if (d1 == 0)       /* no toggles, nothing's happening */
872                 return STATUS_READY;
873         } while (!(d1 & 0x20));
874
875         d1 = *flashptr;        /* read data */
876         d1 ^= *flashptr;   /* read it again and see what toggled */
877
878         if (d1 != 0) {
879             cfi_flash_command(FLASH_RESET, 0, 0, 0);
880             return STATUS_TIMEOUT;
881         }
882 #endif
883     } else if (flashFamily == FLASH_INTEL) {
884         flashptr[0] = 0x70;
885         /* Wait for completion */
886         while(!(*flashptr & 0x80));
887         if (*flashptr & 0x30) {
888             flashptr[0] = 0x50;
889             cfi_flash_command(FLASH_RESET, 0, 0, 0);
890             return STATUS_TIMEOUT;
891         }
892         flashptr[0] = 0x50;
893         cfi_flash_command(FLASH_RESET, 0, 0, 0);
894     }
895     
896     return STATUS_READY;
897 }
898
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)
905 {
906     volatile unsigned short *fwp; /* flash window */
907     unsigned short answer;
908     
909     fwp = (unsigned short *) cfi_flash_get_memptr(0);
910     
911     cfi_flash_command(FLASH_READ_ID, 0, 0, 0);
912     answer = *(fwp + 1);
913     if (answer == ID_AM29LV320M) {
914         answer = *(fwp + 0xe);
915         answer = *(fwp + 0xf);
916     }
917     
918     cfi_flash_command(FLASH_RESET, 0, 0, 0);
919     return( (unsigned short) answer );
920 }
921
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,
932     int flashFamily)
933 {
934     volatile unsigned short *fwp; /* flash window */
935     int i=0, temp=0;
936
937     cfi_flash_command(FLASH_CFIQUERY, 0, 0, 0);
938     
939     if (cfi_struct == 0)
940         fwp = (unsigned short *) cfi_flash_get_memptr(0);
941     else
942         fwp = cfi_struct;
943     
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;
948     }
949     
950     /* If not 'QRY', then we dont have a CFI enabled device in the socket */
951     if( fwp[0x10] != 'Q' &&
952         fwp[0x11] != 'R' &&
953         fwp[0x12] != 'Y') {
954         cfi_flash_command(FLASH_RESET, 0, 0, 0);
955         return(FLASH_API_ERROR);
956     }
957     
958     temp = fwp[0x27];
959     query->device_size = (int) (((int)1) << temp);
960     
961     query->num_erase_blocks = fwp[0x2C];
962     if(flashFamily == FLASH_SST)
963         query->num_erase_blocks = 1;
964     
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))]);
971     }
972     
973     cfi_flash_command(FLASH_RESET, 0, 0, 0);
974     return(FLASH_API_OK);
975 }
976