]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/intel/28fxxx/v2_0/include/flash_28fxxx_p30.inl
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / intel / 28fxxx / v2_0 / include / flash_28fxxx_p30.inl
1 #ifndef CYGONCE_DEVS_FLASH_INTEL_28FXXX_INL
2 #define CYGONCE_DEVS_FLASH_INTEL_28FXXX_INL
3 //==========================================================================
4 //
5 //      flash_28fxxx.inl
6 //
7 //      Intel 28Fxxx series flash driver
8 //
9 //==========================================================================
10 //####ECOSGPLCOPYRIGHTBEGIN####
11 // -------------------------------------------
12 // This file is part of eCos, the Embedded Configurable Operating System.
13 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14 // Copyright (C) 2002 Gary Thomas
15 //
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
19 //
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23 // for more details.
24 //
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 //
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
35 //
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
38 //
39 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40 // at http://sources.redhat.com/ecos/ecos-license/
41 // -------------------------------------------
42 //####ECOSGPLCOPYRIGHTEND####
43 //==========================================================================
44 //#####DESCRIPTIONBEGIN####
45 //
46 // Author(s):    jskov
47 // Contributors: jskov
48 // Date:         2001-03-21
49 // Purpose:
50 // Description:
51 //
52 // Notes:        Device table could use unions of flags to save some space
53 //
54 //####DESCRIPTIONEND####
55 //
56 //==========================================================================
57
58 #include <pkgconf/hal.h>
59 #include <pkgconf/io_flash.h>
60 #include <pkgconf/devs_flash_intel_28fxxx.h>
61
62 #include <cyg/hal/hal_arch.h>
63 #include <cyg/hal/hal_cache.h>
64 #include CYGHWR_MEMORY_LAYOUT_H
65
66 #include <cyg/hal/hal_io.h>
67
68 #define  _FLASH_PRIVATE_
69 #include <cyg/io/flash.h>
70
71 #define nDEBUG
72
73 #define nRAM_VERSION
74
75 typedef void (*call_t)(char* str, ...);
76 extern void diag_printf(char* str, ...);
77 call_t d_print = &diag_printf;
78
79 //----------------------------------------------------------------------------
80 // Common device details.
81
82 #define FLASH_BOOTBLOCKS_PER_BLOCK              4
83
84 #define FLASH_Read_ID                   FLASHWORD( 0x90 )
85 #define FLASH_Reset                     FLASHWORD( 0xFF )
86 #define FLASH_Program                   FLASHWORD( 0x40 )
87 #define FLASH_Write_Buffer              FLASHWORD( 0xe8 )
88 #define FLASH_Block_Erase               FLASHWORD( 0x20 )
89 #define FLASH_Confirm                   FLASHWORD( 0xD0 )
90 #define FLASH_Resume                    FLASHWORD( 0xD0 )
91
92 #define FLASH_Set_Lock                  FLASHWORD( 0x60 )
93 #define FLASH_Set_Lock_Confirm          FLASHWORD( 0x01 )
94 #define FLASH_Clear_Lock                FLASHWORD( 0x60 )
95 #define FLASH_Clear_Lock_Confirm        FLASHWORD( 0xd0 )
96 #define FLASH_Lock_State_Mask                   FLASHWORD( 0x03 )
97 #define FLASH_Status_Locked                             FLASHWORD( 0x01 )
98
99 #define FLASH_Read_Status               FLASHWORD( 0x70 )
100 #define FLASH_Clear_Status              FLASHWORD( 0x50 )
101 #define FLASH_Status_Ready              FLASHWORD( 0x80 )
102
103 // Status that we read back:
104 #define FLASH_ErrorMask                 FLASHWORD( 0x7E )
105 #define FLASH_ErrorProgram              FLASHWORD( 0x10 )
106 #define FLASH_ErrorErase                FLASHWORD( 0x20 )
107 #define FLASH_ErrorLock                 FLASHWORD( 0x30 )
108 #define FLASH_ErrorLowVoltage           FLASHWORD( 0x08 )
109 #define FLASH_ErrorLocked               FLASHWORD( 0x02 )
110
111 // Platform code must define the below
112 // #define CYGNUM_FLASH_INTERLEAVE      : Number of interleaved devices (in parallel)
113 // #define CYGNUM_FLASH_SERIES          : Number of devices in series
114 // #define CYGNUM_FLASH_WIDTH           : Width of devices on platform
115 // #define CYGNUM_FLASH_BASE            : Address of first device
116
117 #define CYGNUM_FLASH_BLANK              (1)
118 #define CYGNUM_FLASH_DEVICES            (CYGNUM_FLASH_INTERLEAVE*CYGNUM_FLASH_SERIES)
119
120 #ifndef FLASH_P2V
121 # define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_)))
122 #endif
123 #ifndef CYGHWR_FLASH_28FXXX_PLF_INIT
124 # define CYGHWR_FLASH_28FXXX_PLF_INIT()
125 #endif
126 #ifndef CYGHWR_FLASH_WRITE_ENABLE
127 #define CYGHWR_FLASH_WRITE_ENABLE()
128 #endif
129 #ifndef CYGHWR_FLASH_WRITE_DISABLE
130 #define CYGHWR_FLASH_WRITE_DISABLE()
131 #endif
132
133 //----------------------------------------------------------------------------
134 // Now that device properties are defined, include magic for defining
135 // accessor type and constants.
136 #include <cyg/io/flash_dev.h>
137
138 //----------------------------------------------------------------------------
139 // Information about supported devices
140 typedef struct flash_dev_info {
141     flash_data_t device_id;
142     cyg_uint32   block_size;
143     cyg_int32    block_count;
144     cyg_uint32   base_mask;
145     cyg_uint32   device_size;
146     cyg_bool     locking;               // supports locking
147     cyg_bool     buffered_w;            // supports buffered writes
148     cyg_bool     bootblock;
149     cyg_uint32   bootblocks[12];         // 0 is bootblock offset, 1-11 sub-sector sizes (or 0)
150     cyg_bool     banked;
151     cyg_uint32   banks[2];               // bank offets, highest to lowest (lowest should be 0)
152                                          // (only one entry for now, increase to support devices
153                                          // with more banks).
154 } flash_dev_info_t;
155
156 // Information about stacked die devices
157 typedef struct flash_stacked_die_dev_info {
158     flash_data_t device_id;
159     cyg_uint32   num_blocks_1;
160     cyg_uint32   num_blocks_2;
161     cyg_uint32  num_bytes_1;
162     cyg_uint32  num_bytes_2;
163     cyg_uint32  dev_size;
164     cyg_uint32  dev_start;
165 } flash_stacked_die_dev_info_t;
166
167 static const flash_dev_info_t* flash_dev_info;
168 static const flash_dev_info_t supported_devices[] = {
169 #include <cyg/io/flash_28fxxx_parts.inl>
170 };
171
172 static flash_stacked_die_dev_info_t sdi[CYGNUM_FLASH_SERIES];
173
174 #define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
175
176 #if 1
177 //----------------------------------------------------------------------------
178 // Functions that put the flash device into non-read mode must reside
179 // in RAM.
180
181 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
182
183 int flash_erase_block(void* block, unsigned int size)
184      __attribute__ ((section (".2ram.flash_erase_block")));
185 int flash_program_buf(void* addr, void* data, int len,
186                        unsigned long block_mask, int buffer_size)
187      __attribute__ ((section (".2ram.flash_program_buf")));
188 int flash_lock_block(void* addr)
189      __attribute__ ((section (".2ram.flash_lock_block")));
190 int flash_unlock_block(void* block, int block_size, int blocks, void *)
191      __attribute__ ((section (".2ram.flash_unlock_block")));
192 //----------------------------------------------------------------------------
193 #endif
194
195 // Initialize driver details
196 int
197 flash_hwr_init(void)
198 {
199         int i;
200         flash_data_t id[2];
201
202         CYGHWR_FLASH_28FXXX_PLF_INIT();
203
204         flash_dev_query(id);
205
206         // Look through table for device data
207         flash_dev_info = supported_devices;
208         for (i = 0; i < NUM_DEVICES; i++) {
209
210                 if (flash_dev_info->device_id == id[1])
211                         break;
212                 flash_dev_info++;
213         }
214
215         // Did we find the device? If not, return error.
216         if (NUM_DEVICES == i){
217                 return FLASH_ERR_DRV_WRONG_PART;
218         }
219
220         // Hard wired for now
221         flash_info.block_size = flash_dev_info->block_size;
222         flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
223         flash_info.start = (void *)CYGNUM_FLASH_BASE;
224         flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
225
226         return FLASH_ERR_OK;
227 }
228
229 //----------------------------------------------------------------------------
230 // Map a hardware status to a package error
231 int
232 flash_hwr_map_error(int e)
233 {
234         return e;
235 }
236
237 //----------------------------------------------------------------------------
238 // See if a range of FLASH addresses overlaps currently running code
239 bool
240 flash_code_overlaps(void *start, void *end)
241 {
242         extern unsigned char _stext[], _etext[];
243
244         return ((((unsigned long)&_stext >= (unsigned long)start) &&
245                  ((unsigned long)&_stext < (unsigned long)end)) ||
246                 (((unsigned long)&_etext >= (unsigned long)start) &&
247                  ((unsigned long)&_etext < (unsigned long)end)));
248 }
249
250 //----------------------------------------------------------------------------
251 // Flash Query
252 //
253 // Only reads the manufacturer and part number codes for the first
254 // device(s) in series. It is assumed that any devices in series
255 // will be of the same type.
256
257 void
258 flash_query(void* data)
259 {
260         volatile flash_data_t *ROM;
261         flash_data_t* id = (flash_data_t*) data;
262         flash_data_t w;
263         unsigned long flash_base;
264         unsigned long max_erase_time;
265         unsigned long dsize;
266         unsigned long max_write_buffer;
267         unsigned long block_size;
268         unsigned short  val1, val2;
269         unsigned long   nblocks1;                       // number of blocks in 1st section
270         unsigned long   nblocks2;                       // number of blocks in 2nd section
271         unsigned long   bsize1;                         // blocksize in 1st section
272         unsigned long   bsize2;                         // blocksize in 2nd section
273         int             j;
274
275         ROM = FLASH_P2V(CYGNUM_FLASH_BASE);
276
277         w = ROM[0];
278
279         CYGHWR_FLASH_WRITE_ENABLE();
280
281         ROM[0] = FLASH_Read_ID;
282
283         // Manufacturers' code
284         id[0] = ROM[0];
285         // Part number
286         id[1] = ROM[1];
287
288         ROM[0] = FLASH_Reset;
289         //Stall, waiting for flash to return to read mode.
290         while (w != ROM[0]);
291
292         flash_base = CYGNUM_FLASH_BASE;
293         for (j = 0; j < CYGNUM_FLASH_SERIES; j++) {
294                 ROM = FLASH_P2V(flash_base);
295                 ROM[0] =  0x0050;                               // clear status register
296                 ROM[0] =  0x0098;                               // read query
297                 ROM = FLASH_P2V(flash_base + (0x10 << 1));
298                 if (ROM[0] != 0x0051) {                 //Q
299 #ifdef RAM_VERSION
300                         d_print("error reading flash attribute space Q\n");
301 #endif
302                         ROM = FLASH_P2V(flash_base);
303                         ROM[0] = 0x00ff;                                // read array / reset
304                         //return        FLASH_ERR_DRV_WRONG_PART;
305                 } else {
306 #ifdef RAM_VERSION
307                         d_print("read flash attribute space Q ok\n");
308 #endif
309                 }
310                 ROM = FLASH_P2V(flash_base + (0x11 << 1));
311                 if (ROM[0] != 0x0052) {                 //R
312 #ifdef RAM_VERSION
313                         d_print("error reading flash attribute space R\n");
314 #endif
315                         ROM = FLASH_P2V(flash_base);
316                         ROM[0] = 0x00ff;                                // read array / reset
317                         //return        FLASH_ERR_DRV_WRONG_PART;
318                 } else {
319 #ifdef RAM_VERSION
320                         d_print("read flash attribute space R ok\n");
321 #endif
322                 }
323                 ROM = FLASH_P2V(flash_base + (0x12 << 1));
324                 if (ROM[0] != 0x0059) {                 //Y
325 #ifdef RAM_VERSION
326                         d_print("error reading flash attribute space Y\n");
327 #endif
328                         ROM = FLASH_P2V(flash_base);
329                         ROM[0] = 0x00ff;                // read array / reset
330                         //return        FLASH_ERR_DRV_WRONG_PART;
331                 } else {
332 #ifdef RAM_VERSION
333                         d_print("read flash attribute space Y ok\n");
334 #endif
335                 }
336                 ROM = FLASH_P2V(flash_base + (0x25 << 1));
337                 max_erase_time = ROM[0];        // "n" such that the max block erase time = 2^n
338                 max_erase_time = 1 << (max_erase_time & 0xffff);        // convert erase time 2^n to the number of seconds
339
340                 ROM = FLASH_P2V(flash_base + (0x27 << 1));
341                 dsize = ROM[0];                 // "n" such that the device size = 2^n in number of bytes
342                 dsize = 1 << (dsize & 0xffff);  // convert data size from 2^n to the number of bytes
343
344                 ROM = FLASH_P2V(flash_base + (0x2a << 1));
345                 max_write_buffer = ROM[0];      // "n" such that the max num of bytes in write buffer = 2^n
346                 max_write_buffer = (1 << (max_write_buffer & 0xffff)) / 2;  // convert from 2^n bytes to the number of words
347
348                 ROM = FLASH_P2V(flash_base + (0x2d << 1));
349                 val1    =       ROM[0];
350                 ROM = FLASH_P2V(flash_base + (0x2e << 1));
351                 val2    =       ROM[0];
352                 nblocks1        =       (val1 + (val2 << 8)) + 1;
353
354                 ROM = FLASH_P2V(flash_base + (0x31 << 1));
355                 val1    =       ROM[0]&0xff;
356                 ROM = FLASH_P2V(flash_base + (0x32 << 1));
357                 val2    =       ROM[0]&0xff;
358                 nblocks2        =       (val1 + (val2 << 8)) + 1;
359
360                 ROM = FLASH_P2V(flash_base + (0x2f << 1));
361                 val1    =       ROM[0]&0xff;
362                 ROM = FLASH_P2V(flash_base + (0x30 << 1));
363                 val2    =       ROM[0]&0xff;
364                 bsize1  =       (val1 + (val2 << 8)) * 256;
365
366                 ROM = FLASH_P2V(flash_base + (0x33 << 1));
367                 val1    =       ROM[0]&0xff;
368                 ROM = FLASH_P2V(flash_base + (0x34 << 1));
369                 val2    =       ROM[0]&0xff;
370                 bsize2  =       (val1 + (val2 << 8)) * 256;
371
372                 block_size = bsize1/2;
373
374                 ROM = FLASH_P2V(flash_base);
375                 ROM[0] = 0x00ff;                                // read array / reset
376
377                 sdi[j].device_id        = 0;
378                 sdi[j].num_blocks_1     = nblocks1;
379                 sdi[j].num_blocks_2     = nblocks2;
380                 sdi[j].num_bytes_1      = bsize1;
381                 sdi[j].num_bytes_2      = bsize2;
382                 sdi[j].dev_size         = dsize;
383                 sdi[j].dev_start        = flash_base;
384 #ifdef RAM_VERSION
385                 d_print("number of blocks in region 1: %d\n", sdi[j].num_blocks_1);
386                 d_print("number of blocks in region 2: %d\n", sdi[j].num_blocks_2);
387                 d_print("number of bytes in region 1: %lu  (0x%04X)\n", sdi[j].num_bytes_1, sdi[j].num_bytes_1);
388                 d_print("number of bytes in region 2: %lu  (0x%04X)\n", sdi[j].num_bytes_2, sdi[j].num_bytes_2);
389                 d_print("Device size = %ld Mbytes (0x%lx)\n",sdi[j].dev_size/1024/1024 ,sdi[j].dev_size);
390                 d_print("max. erase time is %d nseconds\n", max_erase_time);
391                 d_print("number of words for write buffer are %d\n\n\n\n", max_write_buffer);
392 #endif
393                 flash_info.buffer_size = max_write_buffer;
394                 flash_base += dsize;
395         }
396         CYGHWR_FLASH_WRITE_DISABLE();
397 }
398
399 //----------------------------------------------------------------------------
400 // Erase Block
401 int
402 flash_erase_block(void* block, unsigned int block_size)
403 {
404         int res = FLASH_ERR_OK;
405         int timeout;
406         unsigned long len;
407         flash_data_t stat;
408         volatile flash_data_t *ROM;
409         int j, die_number, blocks_to_do;
410         unsigned long   phys_block_length;
411         volatile flash_data_t *b_p = (flash_data_t*) block;
412         volatile flash_data_t *b_v;
413         cyg_bool bootblock;
414
415         ROM = FLASH_P2V((unsigned long)block & flash_dev_info->base_mask);
416
417         // check out which die we have to handle
418         die_number = 0;
419         for (j = 0; j < CYGNUM_FLASH_SERIES; j++) {
420                 if (((unsigned long)block >= sdi[j].dev_start) &&
421                     ((unsigned long)block < (sdi[j].dev_start + sdi[j].dev_size))) {
422                         die_number = j + 1;
423                         break;
424                 }
425         }
426         if (die_number == 0) {
427 #ifdef RAM_VERSION
428                 d_print("\n\ndid not found a valid die number \n\n");
429 #endif
430                 return  FLASH_ERR_DRV_WRONG_PART;
431         }
432
433         // check out which area we have to handle inside the die
434         if ((unsigned long)block < sdi[die_number - 1].dev_start +
435             sdi[die_number - 1].num_blocks_1 *
436             sdi[die_number - 1].num_bytes_1) {
437                 // we stay in flash region 1
438                 phys_block_length = sdi[die_number - 1].num_bytes_1;
439                 if (sdi[die_number - 1].num_bytes_1 > sdi[die_number - 1].num_bytes_2) {
440                         blocks_to_do = 1;               // this is no boot block area
441                         bootblock = 0;
442                 } else {
443                         blocks_to_do = FLASH_BOOTBLOCKS_PER_BLOCK; //sdi[die_number - 1].num_bytes_2 / sdi[die_number - 1].num_bytes_1; // this is a bootblock area
444                         bootblock = 1;
445                 }
446         } else {
447                 // we stay in flash region 2
448                 phys_block_length = sdi[die_number - 1].num_bytes_2;
449                 if (sdi[die_number - 1].num_bytes_2 > sdi[die_number - 1].num_bytes_1) {
450                         blocks_to_do = 1;               // this is no boot block area
451                         bootblock = 0;
452                 } else {
453                         blocks_to_do = FLASH_BOOTBLOCKS_PER_BLOCK; //sdi[die_number - 1].num_bytes_1 / sdi[die_number - 1].num_bytes_2; // this is a bootblock area
454                         bootblock = 1;
455                 }
456         }
457
458         len = phys_block_length;
459
460         CYGHWR_FLASH_WRITE_ENABLE();
461         while (len > 0) {
462                 b_v = FLASH_P2V(b_p);
463
464                 // Clear any error conditions
465                 *b_v = FLASH_Clear_Status;
466
467                 // Erase block
468                 *b_v = FLASH_Block_Erase;
469                 *b_v = FLASH_Confirm;
470
471                 timeout = 5000000;
472                 while (((stat = *b_v) & FLASH_Status_Ready) != FLASH_Status_Ready) {
473                         if (--timeout == 0) break;
474                 }
475
476                 // Restore ROM to "normal" mode
477                 *b_v = FLASH_Reset;
478
479                 if (stat & FLASH_ErrorMask) {
480                         if (!(stat & FLASH_ErrorErase)) {
481                                 res = FLASH_ERR_HWR;    // Unknown error
482                         } else {
483                                 if (stat & FLASH_ErrorLowVoltage)
484                                         res = FLASH_ERR_LOW_VOLTAGE;
485                                 else if (stat & FLASH_ErrorLocked)
486                                         res = FLASH_ERR_PROTECT;
487                                 else
488                                         res = FLASH_ERR_ERASE;
489                         }
490                 }
491
492                 // Check if block got erased
493
494                 while (len > 0) {
495                         b_v = FLASH_P2V(b_p);
496                         b_p++;
497                         if (*b_v != FLASH_BlankValue ) {
498                                 // Only update return value if erase operation was OK
499                                 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
500                                 return res;
501                         }
502                         len -= sizeof(*b_p);
503                 }
504
505                 blocks_to_do--;
506                 if (blocks_to_do) {
507                         len = phys_block_length;
508                 } else {
509                         len = 0;
510                 }
511         }
512
513         CYGHWR_FLASH_WRITE_DISABLE();
514
515         return res;
516 }
517
518 //----------------------------------------------------------------------------
519 // Program Buffer
520 int
521 flash_program_buf(void* addr, void* data, int len,
522                   unsigned long block_mask, int buffer_size)
523 {
524         flash_data_t stat = 0;
525         int timeout;
526         int words_to_write;
527         volatile flash_data_t* ROM;
528         int i;
529         volatile flash_data_t* addr_v;
530         volatile flash_data_t* addr_p = (flash_data_t*) addr;
531         volatile flash_data_t* data_p = (flash_data_t*) data;
532         int res = FLASH_ERR_OK;
533
534 #ifdef RAM_VERSION
535         d_print("programming at address: 0x%08X length: 0x%08X   buffer_size: 0x%08X\n",
536                 (unsigned long)addr, (unsigned long)len, (unsigned long)buffer_size);
537 #endif
538         // Base address of device(s) being programmed.
539         ROM = FLASH_P2V((unsigned long)addr & flash_dev_info->base_mask);
540
541         CYGHWR_FLASH_WRITE_ENABLE();
542
543         // Clear any error conditions
544         ROM[0] = FLASH_Clear_Status;
545         while (len > 0) {
546                 if (len/sizeof( flash_data_t ) >= buffer_size){
547                         words_to_write = buffer_size; //full buffer
548                 } else {
549                         words_to_write = len / sizeof( flash_data_t );
550                         if (len&1)
551                                 words_to_write++;
552                 }
553
554                 addr_v = FLASH_P2V(addr_p);
555                 addr_p += words_to_write;
556                 timeout = 5000000;
557
558                 while (--timeout>0) {
559                         *addr_v = FLASH_Write_Buffer;
560                         stat=*addr_v;
561                         //d_print("\nstatus after FLASH_WRITE_BUFFER command is 0x%08X\n", stat);
562                         if (stat & FLASH_Status_Ready)
563                                 break;
564                 }
565                 if (timeout==0){
566                         res = FLASH_ERR_DRV_TIMEOUT;
567                         goto bad;
568                 }
569
570                 *addr_v = words_to_write - 1;           // write word count
571
572                 for (i = 0; i < words_to_write; i++) {
573                         *(addr_v+i) = *(data_p+i);
574                 }
575
576                 *addr_v = FLASH_Confirm;
577
578                 timeout = 5000000;
579                 while (((stat = *addr_v) & FLASH_Status_Ready) != FLASH_Status_Ready) {
580                         if (--timeout == 0) {
581 #ifdef DEBUG
582                                 d_print("status is 0x%08X \n", stat);
583 #endif
584                                 res = FLASH_ERR_DRV_TIMEOUT;
585                                 goto bad;
586                         }
587                 }
588 #if 0
589                 d_print("address pointer : 0x%08X\n", (unsigned long)addr_v);
590                 d_print("status register is: 0x%08X\n", stat);
591 #endif
592                 if (stat & FLASH_ErrorMask) {
593                         if (!(stat & FLASH_ErrorProgram))
594                                 res = FLASH_ERR_HWR;    // Unknown error
595                         else {
596                                 if (stat & FLASH_ErrorLowVoltage)
597                                         res = FLASH_ERR_LOW_VOLTAGE;
598                                 else if (stat & FLASH_ErrorLocked)
599                                         res = FLASH_ERR_PROTECT;
600                                 else
601                                         res = FLASH_ERR_PROGRAM;
602                         }
603                         break;
604                 }
605                 *addr_v = FLASH_Clear_Status;
606                 *addr_v = FLASH_Reset;
607                 for (i = 0; i < words_to_write; i++) {
608                         if (*(addr_v+i) != *(data_p+i)) {
609                                 res = FLASH_ERR_DRV_VERIFY;
610                                 break;
611                         }
612                 }
613                 data_p += words_to_write;
614                 if (words_to_write == buffer_size) {
615                         len -= (buffer_size*sizeof(flash_data_t));
616                 } else {
617                         len = 0;
618                 }
619         }
620
621         // Restore ROM to "normal" mode
622  bad:
623         ROM[0] = FLASH_Reset;
624
625         CYGHWR_FLASH_WRITE_DISABLE();
626
627         // Ideally, we'd want to return not only the failure code, but also
628         // the address/device that reported the error.
629         return res;
630 }
631
632 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
633 //----------------------------------------------------------------------------
634 // Lock block
635 int
636 flash_lock_block(void* block)
637 {
638         volatile flash_data_t *ROM;
639         int res = FLASH_ERR_OK;
640         flash_data_t state;
641         int timeout = 5000000;
642         volatile flash_data_t* b_p = (flash_data_t*) block;
643         volatile flash_data_t *b_v;
644         cyg_bool bootblock;
645         int len;
646         int j, die_number, blocks_to_do;
647         unsigned long   phys_block_length;
648
649         if (!flash_dev_info->locking)
650                 return res;
651
652 #ifdef DEBUG
653         d_print("flash_lock_block %08x\n", block);
654 #endif
655         ROM = FLASH_P2V((unsigned long)block & flash_dev_info->base_mask);
656
657         // check out which die we have to handle
658         die_number = 0;
659         for (j = 0; j < CYGNUM_FLASH_SERIES; j++) {
660                 if (((unsigned long)block >= sdi[j].dev_start)&&((unsigned long)block < (sdi[j].dev_start + sdi[j].dev_size))) {
661                         die_number = j + 1;
662                         break;
663                 }
664         }
665         if (die_number == 0) {
666 #ifdef RAM_VERSION
667                 d_print("\n\ndid not found a valid die number \n\n");
668 #endif
669                 return  FLASH_ERR_DRV_WRONG_PART;
670         }
671
672         // check out which area we have to handle inside the die
673         if ((unsigned long)block < sdi[die_number - 1].dev_start +      sdi[die_number - 1].num_blocks_1 * sdi[die_number - 1].num_bytes_1) {
674                 // we stay in flash region 1
675                 phys_block_length = sdi[die_number - 1].num_bytes_1;
676                 if (sdi[die_number - 1].num_bytes_1 > sdi[die_number - 1].num_bytes_2) {
677                         blocks_to_do = 1;               // this is no boot block area
678                         bootblock = 0;
679                 } else {
680                         blocks_to_do = FLASH_BOOTBLOCKS_PER_BLOCK; //sdi[die_number - 1].num_bytes_2 / sdi[die_number - 1].num_bytes_1; // this is a bootblock area
681                         bootblock = 1;
682                 }
683         } else {
684                 // we stay in flash region 2
685                 phys_block_length = sdi[die_number - 1].num_bytes_2;
686                 if (sdi[die_number - 1].num_bytes_2 > sdi[die_number - 1].num_bytes_1) {
687                         blocks_to_do = 1;               // this is no boot block area
688                         bootblock = 0;
689                 } else {
690                         blocks_to_do = FLASH_BOOTBLOCKS_PER_BLOCK; //sdi[die_number - 1].num_bytes_1 / sdi[die_number - 1].num_bytes_2; // this is a bootblock area
691                         bootblock = 1;
692                 }
693         }
694         len = phys_block_length;
695
696         CYGHWR_FLASH_WRITE_ENABLE();
697
698         while (len > 0) {
699 #ifdef RAM_VERSION
700                 d_print("locking block at address 0x%08X\n", (unsigned long)b_p);
701 #endif
702                 b_v = FLASH_P2V(b_p);
703
704                 // Clear any error conditions
705                 *b_v = FLASH_Clear_Status;
706
707                 // Set lock bit
708                 *b_v = FLASH_Set_Lock;
709                 *b_v = FLASH_Set_Lock_Confirm;  // Confirmation
710                 *(b_v + 2) = FLASH_Read_ID ;
711                 while (((state = *(b_v + 2)) & FLASH_Lock_State_Mask) != FLASH_Status_Locked) {
712                         if (--timeout == 0) {
713                                 res = FLASH_ERR_DRV_TIMEOUT;
714                                 break;
715                         }
716                 }
717
718                 // Restore ROM to "normal" mode
719                 *b_v = FLASH_Reset;
720
721                 // Go to next block
722                 b_p += len / sizeof( flash_data_t );
723
724                 if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
725                         res = FLASH_ERR_LOCK;
726
727                 if (res != FLASH_ERR_OK)
728                         break;
729
730                 blocks_to_do--;
731                 if (blocks_to_do) {
732                         len = phys_block_length;
733                 } else {
734                         len = 0;
735                 }
736         }
737
738         CYGHWR_FLASH_WRITE_DISABLE();
739
740         return res;
741 }
742
743 //----------------------------------------------------------------------------
744 // Unlock block
745
746 int
747 flash_unlock_block(void* block, int block_size, int blocks, void *myprint)
748 {
749         volatile flash_data_t *ROM;
750         int res = FLASH_ERR_OK;
751         flash_data_t state;
752         int timeout = 5000000;
753         volatile flash_data_t* b_p = (flash_data_t*) block;
754         volatile flash_data_t *b_v;
755         int j, die_number, blocks_to_do;
756         unsigned long   phys_block_length;
757         cyg_bool bootblock;
758         int len;
759 #ifdef DEBUG
760         void (*func_ptr)(void) = myprint;
761 #endif
762
763 #ifdef DEBUG
764         d_print("flash_unlock_block function entered ....\n");
765 #endif
766         if (!flash_dev_info->locking)
767                 return res;
768
769         ROM = FLASH_P2V((unsigned long)block & flash_dev_info->base_mask);
770 #ifdef DEBUG
771         d_print("flash_unlock_block dev %08x block %08x size %08x count %08x\n", ROM, block, block_size, blocks);
772 #endif
773         // check out which die we have to handle
774         die_number = 0;
775         for (j = 0; j < CYGNUM_FLASH_SERIES; j++) {
776                 if (((unsigned long)block >= sdi[j].dev_start)&&((unsigned long)block < (sdi[j].dev_start + sdi[j].dev_size))) {
777                         die_number = j+1;
778                         break;
779                 }
780         }
781         if (die_number == 0) {
782 #ifdef RAM_VERSION
783                 d_print("\n\ndid not found a valid die number \n\n");
784 #endif
785                 return  FLASH_ERR_DRV_WRONG_PART;
786         }
787
788         // check out which area we have to handle inside the die
789         if ((unsigned long)block < sdi[die_number - 1].dev_start +      sdi[die_number - 1].num_blocks_1 * sdi[die_number - 1].num_bytes_1) {
790                 // we stay in flash region 1
791                 phys_block_length = sdi[die_number - 1].num_bytes_1;
792                 if (sdi[die_number - 1].num_bytes_1 > sdi[die_number - 1].num_bytes_2) {
793                         blocks_to_do = 1;               // this is no boot block area
794                         bootblock = 0;
795                 } else {
796                         blocks_to_do = FLASH_BOOTBLOCKS_PER_BLOCK; //sdi[die_number - 1].num_bytes_2 / sdi[die_number - 1].num_bytes_1; // this is a bootblock area
797                         bootblock = 1;
798                 }
799         } else {
800                 // we stay in flash region 2
801                 phys_block_length = sdi[die_number - 1].num_bytes_2;
802                 if (sdi[die_number - 1].num_bytes_2 > sdi[die_number - 1].num_bytes_1) {
803                         blocks_to_do = 1;               // this is no boot block area
804                         bootblock = 0;
805                 } else {
806                         blocks_to_do = FLASH_BOOTBLOCKS_PER_BLOCK; //sdi[die_number - 1].num_bytes_1 / sdi[die_number - 1].num_bytes_2; // this is a bootblock area
807                         bootblock = 1;
808                 }
809         }
810 #ifdef RAM_VERSION
811         d_print("\n\n");
812         d_print("unlocking block: ....... 0x%08X\n", (unsigned long)block);
813         d_print("block size: ............ 0x%08X\n", (unsigned long)block_size);
814         d_print("die number: ............ %d\n", die_number);
815         d_print("physical block length: . 0x%08X\n", phys_block_length);
816         d_print("blocks to do: .......... 0x%08X\n", blocks_to_do);
817 #endif
818         len = phys_block_length;
819
820         CYGHWR_FLASH_WRITE_ENABLE();
821
822         while (len > 0) {
823 #ifdef RAM_VERSION
824                 d_print("unlocking block at address 0x%08X\n", (unsigned long)b_p);
825 #endif
826                 b_v = FLASH_P2V(b_p);
827
828                 // Clear any error conditions
829                 *b_v = FLASH_Clear_Status;
830
831                 // Clear lock bit
832                 *b_v = FLASH_Clear_Lock;
833                 *b_v = FLASH_Clear_Lock_Confirm;  // Confirmation
834
835                 *(b_v+2) = FLASH_Read_ID;
836
837                 while ((state = *(b_v+2)) & FLASH_Lock_State_Mask)  {
838                         if (--timeout == 0) {
839                                 res = FLASH_ERR_DRV_TIMEOUT;
840                                 break;
841                         }
842                 }
843
844                 // Restore ROM to "normal" mode
845                 *b_v = FLASH_Reset;
846
847                 // Go to next block
848                 b_p += len / sizeof( flash_data_t );
849
850                 if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
851                         res = FLASH_ERR_LOCK;
852
853                 if (res != FLASH_ERR_OK)
854                         break;
855
856                 blocks_to_do--;
857                 if (blocks_to_do) {
858                         len = phys_block_length;
859                 } else {
860                         len = 0;
861                 }
862         }
863
864         CYGHWR_FLASH_WRITE_DISABLE();
865
866         return res;
867 }
868 #endif // CYGHWR_IO_FLASH_BLOCK_LOCKING
869 #endif // CYGONCE_DEVS_FLASH_INTEL_28FXXX_INL