]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/flash/intel/28fxxx/v2_0/include/flash_28fxxx.inl
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / flash / intel / 28fxxx / v2_0 / include / flash_28fxxx.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 #ifdef DEBUG
74 typedef void (*call_t)(char* str, ...);
75 extern void diag_printf(char* str, ...);
76 call_t d_print = &diag_printf;
77 #else
78 #define d_print(fmt,args...)
79 #endif
80
81 //----------------------------------------------------------------------------
82 // Common device details.
83 #define FLASH_Read_ID                   FLASHWORD( 0x90 )
84 #define FLASH_Reset                     FLASHWORD( 0xFF )
85 #define FLASH_Program                   FLASHWORD( 0x40 )
86 #define FLASH_Program_M18               FLASHWORD( 0x41 )
87 #define FLASH_Write_Buffer              FLASHWORD( 0xE8 )
88 #define FLASH_Write_Buffer_M18          FLASHWORD( 0xE9 )
89 #define FLASH_Block_Erase               FLASHWORD( 0x20 )
90 #define FLASH_Confirm                   FLASHWORD( 0xD0 )
91 #define FLASH_Resume                    FLASHWORD( 0xD0 )
92
93 #define FLASH_Set_Lock                  FLASHWORD( 0x60 )
94 #define FLASH_Set_Lock_Confirm          FLASHWORD( 0x01 )
95 #define FLASH_Clear_Lock                FLASHWORD( 0x60 )
96 #define FLASH_Clear_Lock_Confirm        FLASHWORD( 0xd0 )
97
98 #define FLASH_Read_Status               FLASHWORD( 0x70 )
99 #define FLASH_Clear_Status              FLASHWORD( 0x50 )
100 #define FLASH_Status_Ready              FLASHWORD( 0x80 )
101
102 // Status that we read back:                         
103 #define FLASH_ErrorMask                 FLASHWORD( 0x7E )
104 #define FLASH_ErrorProgram              FLASHWORD( 0x10 )
105 #define FLASH_ErrorErase                FLASHWORD( 0x20 )
106 #define FLASH_ErrorLock                 FLASHWORD( 0x30 )
107 #define FLASH_ErrorLowVoltage           FLASHWORD( 0x08 )
108 #define FLASH_ErrorLocked               FLASHWORD( 0x02 )
109
110 // Platform code must define the below
111 // #define CYGNUM_FLASH_INTERLEAVE      : Number of interleaved devices (in parallel)
112 // #define CYGNUM_FLASH_SERIES          : Number of devices in series
113 // #define CYGNUM_FLASH_WIDTH           : Width of devices on platform
114 // #define CYGNUM_FLASH_BASE            : Address of first device
115
116 #define CYGNUM_FLASH_BLANK              (1)
117 #define CYGNUM_FLASH_DEVICES            (CYGNUM_FLASH_INTERLEAVE*CYGNUM_FLASH_SERIES)
118
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 static const flash_dev_info_t* flash_dev_info;
157 static const flash_dev_info_t supported_devices[] = {
158 #include <cyg/io/flash_28fxxx_parts.inl>
159 };
160 #define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
161
162 //----------------------------------------------------------------------------
163 // Functions that put the flash device into non-read mode must reside
164 // in RAM.
165 #ifndef MXCFLASH_SELECT_MULTI
166 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
167 int  flash_erase_block(void* block, unsigned int size) 
168     __attribute__ ((section (".2ram.flash_erase_block")));
169 int  flash_program_buf(void* addr, void* data, int len,
170                        unsigned long block_mask, int buffer_size)
171     __attribute__ ((section (".2ram.flash_program_buf")));
172 int  flash_lock_block(void* addr)
173     __attribute__ ((section (".2ram.flash_lock_block")));
174 int flash_unlock_block(void* block, int block_size, int blocks)
175     __attribute__ ((section (".2ram.flash_unlock_block")));
176 #else
177 void norflash_query(void* data);
178 int norflash_erase_block(void* block, unsigned int block_size);
179 int norflash_program_buf(void* addr, void* data, int len,
180                       unsigned long block_mask, int buffer_size);
181 int  norflash_lock_block(void* addr);
182 int norflash_unlock_block(void* block, int block_size, int blocks);
183 #endif //MXCFLASH_SELECT_MULTI
184
185 //----------------------------------------------------------------------------
186 // Initialize driver details
187 #ifndef MXCFLASH_SELECT_MULTI
188 int flash_hwr_init(void)
189 #else
190 int norflash_hwr_init(void)
191 #endif
192 {
193     int i;
194     flash_data_t id[2];
195
196     CYGHWR_FLASH_28FXXX_PLF_INIT();
197
198     flash_dev_query(id);
199
200     // Look through table for device data
201     flash_dev_info = supported_devices;
202     for (i = 0; i < NUM_DEVICES; i++) {
203         if (flash_dev_info->device_id == id[1])
204             break;
205         flash_dev_info++;
206     }
207
208     // Did we find the device? If not, return error.
209     if (NUM_DEVICES == i)
210         return FLASH_ERR_DRV_WRONG_PART;
211
212     // Hard wired for now
213     flash_info.block_size = flash_dev_info->block_size;
214     flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
215     flash_info.start = (void *)CYGNUM_FLASH_BASE;
216     flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
217
218     return FLASH_ERR_OK;
219 }
220
221 //----------------------------------------------------------------------------
222 // Map a hardware status to a package error
223 #ifndef MXCFLASH_SELECT_MULTI
224 int flash_hwr_map_error(int e)
225 #else
226 int norflash_hwr_map_error(int e)
227 #endif
228 {
229     return e;
230 }
231
232
233 //----------------------------------------------------------------------------
234 // See if a range of FLASH addresses overlaps currently running code
235 #ifndef MXCFLASH_SELECT_MULTI
236 bool flash_code_overlaps(void *start, void *end)
237 #else
238 bool norflash_code_overlaps(void *start, void *end)
239 #endif
240 {
241     extern unsigned char _stext[], _etext[];
242
243     return ((((unsigned long)&_stext >= (unsigned long)start) &&
244              ((unsigned long)&_stext < (unsigned long)end)) ||
245             (((unsigned long)&_etext >= (unsigned long)start) &&
246              ((unsigned long)&_etext < (unsigned long)end)));
247 }
248
249 //----------------------------------------------------------------------------
250 // Flash Query
251 //
252 // Only reads the manufacturer and part number codes for the first
253 // device(s) in series. It is assumed that any devices in series
254 // will be of the same type.
255
256 #ifndef MXCFLASH_SELECT_MULTI
257 void flash_query(void* data)
258 #else
259 void norflash_query(void* data)
260 #endif
261 {
262     volatile flash_data_t *ROM;
263     flash_data_t* id = (flash_data_t*) data;
264     flash_data_t w;
265
266     ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;
267
268     w = ROM[0];
269
270     CYGHWR_FLASH_WRITE_ENABLE();
271     
272     ROM[0] = FLASH_Read_ID;
273
274     // Manufacturers' code
275     id[0] = ROM[0];
276     // Part number
277     id[1] = ROM[1];
278
279     ROM[0] = FLASH_Reset;
280
281     CYGHWR_FLASH_WRITE_DISABLE();
282     
283     // Stall, waiting for flash to return to read mode.
284     while (w != ROM[0]);
285 }
286
287 //----------------------------------------------------------------------------
288 // Erase Block
289 #ifndef MXCFLASH_SELECT_MULTI
290 int flash_erase_block(void* block, unsigned int block_size)
291 #else
292 int norflash_erase_block(void* block, unsigned int block_size)
293 #endif
294 {
295     int res = FLASH_ERR_OK;
296     int timeout;
297     unsigned long len;
298     int len_ix = 1;
299     flash_data_t stat;
300     volatile flash_data_t *ROM;
301     volatile flash_data_t *b_p = (flash_data_t*) block;
302     volatile flash_data_t *b_v;
303     cyg_bool bootblock;
304
305     ROM = FLASH_P2V((unsigned long)block & flash_dev_info->base_mask);
306
307     // Is this the boot sector?
308     bootblock = (flash_dev_info->bootblock &&
309                  (flash_dev_info->bootblocks[0] == ((unsigned long)block - (unsigned long)ROM)));
310     if (bootblock) {
311         len = flash_dev_info->bootblocks[len_ix++];
312     } else {
313         len = flash_dev_info->block_size;
314     }
315
316     CYGHWR_FLASH_WRITE_ENABLE();
317     
318     while (len > 0) {
319         b_v = FLASH_P2V(b_p);
320
321         // Clear any error conditions
322         ROM[0] = FLASH_Clear_Status;
323
324         // Erase block
325         *b_v = FLASH_Block_Erase;
326         *b_v = FLASH_Confirm;
327
328         timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT ;
329         while(((stat = *b_v) & FLASH_Status_Ready) != FLASH_Status_Ready) {
330             if (--timeout == 0) break;
331         }
332     
333         // Restore ROM to "normal" mode
334         *b_v = FLASH_Reset;
335
336         if (stat & FLASH_ErrorMask) {
337             if (!(stat & FLASH_ErrorErase)) {
338                 res = FLASH_ERR_HWR;    // Unknown error
339              } else {
340                 if (stat & FLASH_ErrorLowVoltage)
341                     res = FLASH_ERR_LOW_VOLTAGE;
342                 else if (stat & FLASH_ErrorLocked)
343                     res = FLASH_ERR_PROTECT;
344                 else
345                     res = FLASH_ERR_ERASE;
346             }
347         }
348
349         // Check if block got erased
350         while (len > 0) {
351             b_v = FLASH_P2V(b_p++);
352             if (*b_v != FLASH_BlankValue ) {
353                 // Only update return value if erase operation was OK
354                 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
355                 return res;
356             }
357             len -= sizeof(*b_p);
358         }
359
360         if (bootblock)
361             len = flash_dev_info->bootblocks[len_ix++];
362     }
363
364     CYGHWR_FLASH_WRITE_DISABLE();
365     
366     return res;
367 }
368
369 //----------------------------------------------------------------------------
370 // Program Buffer
371
372 #ifndef MXCFLASH_SELECT_MULTI
373 int flash_program_buf(void* addr, void* data, int len,
374                   unsigned long block_mask, int buffer_size)
375 #else
376 int norflash_program_buf(void* addr, void* data, int len,
377                      unsigned long block_mask, int buffer_size)
378 #endif
379 {
380     flash_data_t stat = 0;
381     int timeout;
382
383     volatile flash_data_t* ROM;
384     volatile flash_data_t* BA;
385     volatile flash_data_t* addr_v;
386     volatile flash_data_t* addr_p = (flash_data_t*) addr;
387     volatile flash_data_t* data_p = (flash_data_t*) data;
388
389     int res = FLASH_ERR_OK;
390
391     // Base address of device(s) being programmed. 
392     ROM = FLASH_P2V((unsigned long)addr & flash_dev_info->base_mask);
393     BA = FLASH_P2V((unsigned long)addr & ~(flash_dev_info->block_size - 1));
394
395 #ifdef CYGPKG_HAL_ARM_MXC30031ADS
396     d_print("ROM=%p, BA=%p\n", ROM, BA);
397     ROM = BA;
398
399     CYGHWR_FLASH_WRITE_ENABLE();
400     
401     // Clear any error conditions
402     BA[0] = FLASH_Clear_Status;
403     addr_v = FLASH_P2V(addr_p);
404     d_print("%s: len=0x%x, *addr_v=0x%x, *data_p=0x%x, addr_v=%p, addr_p=%p\n", 
405              __FUNCTION__, len, *addr_v, *data_p, addr_v, addr_p);
406
407     while (len > 0) {
408         int wc = (len >= 0x400) ? 0x400: len;
409         len -= 0x400;
410
411         wc = (wc + 1) & ~0x1;
412
413         timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
414         do {
415             *addr_v = FLASH_Write_Buffer_M18;
416             if (--timeout == 0) {
417                 res = FLASH_ERR_DRV_TIMEOUT;
418                 d_print("flash_program_buf0: addr_v=0x%x, *addr_v=0x%x, *data_p=0x%x\n", 
419                          addr_v, *addr_v, *data_p);
420                 goto bad;
421             }
422         } while(((stat = *addr_v) & FLASH_Status_Ready) != FLASH_Status_Ready);
423
424         *addr_v = (wc / 2) - 1;
425         //memcpy(addr_v, data_p, wc);
426         for (; wc > 0; wc -= 2) {
427             *addr_v++ = *data_p++;
428         }
429
430         // confirm
431         *addr_p = FLASH_Confirm;
432         timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
433         while(((stat = *addr_p) & FLASH_Status_Ready) != FLASH_Status_Ready) {
434             if (--timeout == 0) {
435                 res = FLASH_ERR_DRV_TIMEOUT;
436                 d_print("flash_program_buf0: addr_v=0x%x, *addr_v=0x%x, *data_p=0x%x\n", 
437                          addr_v, *addr_v, *data_p);
438                 goto bad;
439             }
440         }
441         if (stat & FLASH_ErrorMask) {
442             if (!(stat & FLASH_ErrorProgram))
443                 res = FLASH_ERR_HWR;    // Unknown error
444             else {
445                 if (stat & FLASH_ErrorLowVoltage)
446                     res = FLASH_ERR_LOW_VOLTAGE;
447                 else if (stat & FLASH_ErrorLocked)
448                     res = FLASH_ERR_PROTECT;
449                 else
450                     res = FLASH_ERR_PROGRAM;
451             }
452             break;
453         }
454         addr_p[0] = FLASH_Clear_Status;
455         addr_p[0] = FLASH_Reset;
456
457         addr_p += 512;
458     }
459 #else //CYGPKG_HAL_ARM_MXC30031ADS
460
461     CYGHWR_FLASH_WRITE_ENABLE();
462     
463     // Clear any error conditions
464     ROM[0] = FLASH_Clear_Status;
465
466 #ifdef CYGHWR_DEVS_FLASH_INTEL_BUFFERED_WRITES
467     // FIXME: This code has not been adjusted to handle bootblock
468     // parts yet.
469     // FIXME: This code does not appear to work anymore
470     if (0 && flash_dev_info->buffered_w) {
471         int i, wc;
472         // Write any big chunks first
473         while (len >= buffer_size) {
474             wc = buffer_size;
475             if (wc > len) wc = len;
476             len -= wc;
477             wc = wc / ((CYGNUM_FLASH_WIDTH/8)*CYGNUM_FLASH_INTERLEAVE);  // Word count
478             timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
479             
480             *BA = FLASH_Write_Buffer;
481             while(((stat = BA[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
482                 if (--timeout == 0) {
483                     res = FLASH_ERR_DRV_TIMEOUT;
484                     goto bad;
485                 }
486                 *BA = FLASH_Write_Buffer;
487             }
488             *BA = FLASHWORD(wc-1);  // Count is 0..N-1
489             for (i = 0; i < wc;  i++) {
490                 addr_v = FLASH_P2V(addr_p++);
491                 *addr_v = *data_p++;
492             }
493             *BA = FLASH_Confirm;
494             
495             *BA = FLASH_Read_Status;
496             timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
497             while(((stat = BA[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
498                 if (--timeout == 0) {
499                     res = FLASH_ERR_DRV_TIMEOUT;
500                     goto bad;
501                 }
502             }
503         }
504     }
505 #endif // CYGHWR_DEVS_FLASH_INTEL_BUFFERED_WRITES
506
507     while (len > 0) {
508         addr_v = FLASH_P2V(addr_p++);
509         *addr_v  = FLASH_Program;
510         *addr_v = *data_p;
511         timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
512         while(((stat = *addr_v) & FLASH_Status_Ready) != FLASH_Status_Ready) {
513             if (--timeout == 0) {
514                 res = FLASH_ERR_DRV_TIMEOUT;
515                 d_print("flash_program_buf0: addr_v=0x%x, *addr_v=0x%x, *data_p=0x%x\n", 
516                          addr_v, *addr_v, *data_p);
517                 goto bad;
518             }
519         }
520         if (stat & FLASH_ErrorMask) {
521             if (!(stat & FLASH_ErrorProgram))
522                 res = FLASH_ERR_HWR;    // Unknown error
523             else {
524                 if (stat & FLASH_ErrorLowVoltage)
525                     res = FLASH_ERR_LOW_VOLTAGE;
526                 else if (stat & FLASH_ErrorLocked)
527                     res = FLASH_ERR_PROTECT;
528                 else
529                     res = FLASH_ERR_PROGRAM;
530             }
531             break;
532         }
533         ROM[0] = FLASH_Clear_Status;
534         ROM[0] = FLASH_Reset;
535         if (*addr_v != *data_p++) {
536         d_print("flash_program_buf: addr_v=0x%x, *addr_v=0x%x, *data_p=0x%x\n", 
537                  addr_v, *addr_v, *data_p);
538             res = FLASH_ERR_DRV_VERIFY;
539             break;
540         }
541         len -= sizeof( flash_data_t );
542     }
543 #endif //CYGPKG_HAL_ARM_MXC30031ADS
544     // Restore ROM to "normal" mode
545  bad:
546     ROM[0] = FLASH_Reset;            
547
548     CYGHWR_FLASH_WRITE_DISABLE();
549     
550     // Ideally, we'd want to return not only the failure code, but also
551     // the address/device that reported the error.
552     return res;
553 }
554
555 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
556 //----------------------------------------------------------------------------
557 // Lock block
558 #ifndef MXCFLASH_SELECT_MULTI
559 int flash_lock_block(void* block)
560 #else
561 int norflash_lock_block(void* block)
562 #endif
563 {
564     volatile flash_data_t *ROM;
565     int res = FLASH_ERR_OK;
566     flash_data_t state;
567     int timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
568     volatile flash_data_t* b_p = (flash_data_t*) block;
569     volatile flash_data_t *b_v;
570     cyg_bool bootblock;
571     int len, len_ix = 1;
572
573     if (!flash_dev_info->locking)
574         return res;
575
576     d_print("flash_lock_block %08x\n", block);
577
578     ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
579
580     // Is this the boot sector?
581     bootblock = (flash_dev_info->bootblock &&
582                  (flash_dev_info->bootblocks[0] == ((unsigned long)block - (unsigned long)ROM)));
583     if (bootblock) {
584         len = flash_dev_info->bootblocks[len_ix++];
585         d_print("\nboot block\n");
586     } else {
587         len = flash_dev_info->block_size;
588     }
589
590     CYGHWR_FLASH_WRITE_ENABLE();
591     
592     while (len > 0) {
593         b_v = FLASH_P2V(b_p);
594 #ifdef CYGPKG_HAL_ARM_MXC30031ADS
595         ROM = b_v;
596 #endif
597         // Clear any error conditions
598         ROM[0] = FLASH_Clear_Status;
599
600         // Set lock bit
601         *b_v = FLASH_Set_Lock;
602         *b_v = FLASH_Set_Lock_Confirm;  // Confirmation
603         while(((state = *b_v) & FLASH_Status_Ready) != FLASH_Status_Ready) {
604             if (--timeout == 0) {
605                 res = FLASH_ERR_DRV_TIMEOUT;
606                 break;
607             }
608         }
609
610         // Restore ROM to "normal" mode
611         ROM[0] = FLASH_Reset;
612
613         // Go to next block
614         b_p += len / sizeof( flash_data_t );
615         len = 0;
616
617         if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
618             res = FLASH_ERR_LOCK;
619
620         if (res != FLASH_ERR_OK)
621             break;
622             
623         if (bootblock)
624             len = flash_dev_info->bootblocks[len_ix++];
625     }
626
627     CYGHWR_FLASH_WRITE_DISABLE();
628     
629     return res;
630 }
631
632 //----------------------------------------------------------------------------
633 // Unlock block
634
635 #ifndef MXCFLASH_SELECT_MULTI
636 int flash_unlock_block(void* block, int block_size, int blocks)
637 #else
638 int norflash_unlock_block(void* block, int block_size, int blocks)
639 #endif
640 {
641     volatile flash_data_t *ROM;
642     int res = FLASH_ERR_OK;
643     flash_data_t state;
644     int timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
645     volatile flash_data_t* b_p = (flash_data_t*) block;
646     volatile flash_data_t *b_v;
647
648 #if (defined(CYGHWR_DEVS_FLASH_SHARP_LH28F016SCT_Z4) || defined(CYGHWR_DEVS_FLASH_SHARP_LH28F016SCT_95) )
649     // The Sharp device follows all the same rules as the Intel 28x part,
650     // except that the unlocking mechanism unlocks all blocks at once.  This
651     // is the way the Strata part seems to work.  I will replace the 
652     // flash_unlock_block function with one similar to the Strata function.
653     // As the Sharp part does not have the bootlock characteristics, I
654     // will ignore them.
655 //
656 // The difficulty with this operation is that the hardware does not support
657 // unlocking single blocks.  However, the logical layer would like this to
658 // be the case, so this routine emulates it.  The hardware can clear all of
659 // the locks in the device at once.  This routine will use that approach and
660 // then reset the regions which are known to be locked.
661 //
662
663 #define MAX_FLASH_BLOCKS (flash_dev_info->block_count * CYGNUM_FLASH_SERIES)
664
665     unsigned char is_locked[MAX_FLASH_BLOCKS];
666     int i;
667
668     // Get base address and map addresses to virtual addresses
669 #ifdef DEBUG
670     d_print("\nNow inside low level driver\n");
671 #endif
672     ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;
673     block = FLASH_P2V(block);
674
675     // Clear any error conditions
676     ROM[0] = FLASH_Clear_Status;
677
678     // Get current block lock state.  This needs to access each block on
679     // the device so currently locked blocks can be re-locked.
680     b_p = ROM;
681     for (i = 0;  i < blocks;  i++) {
682         b_v = FLASH_P2V( b_p );
683         *b_v = FLASH_Read_ID;
684         if (b_v == block) {
685             is_locked[i] = 0;
686         } else {
687             if(b_v[2]){ /* it is possible that one of the interleaved devices
688                          * is locked, but others are not.  Coming out of this
689                          * function, if one was locked, all will be locked.
690                          */
691                 is_locked[i] = 1;
692             }else{
693                 is_locked[i] = 0;
694             }
695         }
696 #ifdef DEBUG
697 #endif
698         b_p += block_size / sizeof(*b_p);
699     }
700     ROM[0] = FLASH_Reset;
701 #ifdef DEBUG
702     for (i = 0;  i < blocks;  i++) {
703         d_print("\nblock %d  %s", i,
704                 is_locked[i] ? "LOCKED" : "UNLOCKED");
705     }
706     d_print("\n");
707 #endif
708
709     // Clears all lock bits
710     ROM[0] = FLASH_Clear_Lock;
711     ROM[0] = FLASH_Clear_Lock_Confirm;  // Confirmation
712     timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
713     while(((state = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
714         if (--timeout == 0) break;
715     }
716
717     // Restore the lock state
718     b_p = ROM;
719     for (i = 0;  i < blocks;  i++) {
720         b_v = FLASH_P2V( b_p );
721         if (is_locked[i]) {
722             *b_v = FLASH_Set_Lock;
723             *b_v = FLASH_Set_Lock_Confirm;  // Confirmation
724             timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
725             while(((state = ROM[0]) & FLASH_Status_Ready)
726                   != FLASH_Status_Ready) {
727                 if (--timeout == 0){
728                     res = FLASH_ERR_DRV_TIMEOUT;
729                     break;
730                 }
731             }
732             if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
733                 res = FLASH_ERR_LOCK;
734             
735             if (res != FLASH_ERR_OK)
736                 break;
737
738         }
739         b_p += block_size / sizeof(*b_p);
740     }
741
742     // Restore ROM to "normal" mode
743     ROM[0] = FLASH_Reset;
744
745     return res;
746
747 #else // not CYGHWR_DEVS_FLASH_SHARP_LH28F016SCT_Z4
748
749     cyg_bool bootblock;
750     int len, len_ix = 1;
751
752     if (!flash_dev_info->locking)
753         return res;
754
755     ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
756
757 #ifdef DEBUG
758     d_print("flash_unlock_block dev %08x block %08x size %08x count %08x\n", ROM, block, block_size, blocks);
759 #endif
760
761     // Is this the boot sector?
762     bootblock = (flash_dev_info->bootblock &&
763                  (flash_dev_info->bootblocks[0] == ((unsigned long)block - (unsigned long)ROM)));
764     if (bootblock) {
765         len = flash_dev_info->bootblocks[len_ix++];
766         d_print("\nboot block\n");
767     } else {
768         len = flash_dev_info->block_size;
769     }
770
771     CYGHWR_FLASH_WRITE_ENABLE();
772     
773     while (len > 0) {
774
775         b_v = FLASH_P2V(b_p);
776
777         // Clear any error conditions
778 #ifdef CYGPKG_HAL_ARM_MXC30031ADS
779         ROM = b_v;
780 #endif
781         ROM[0] = FLASH_Clear_Status;
782
783         // Clear lock bit
784         *b_v = FLASH_Clear_Lock;
785         *b_v = FLASH_Clear_Lock_Confirm;  // Confirmation
786         while(((state = *b_v) & FLASH_Status_Ready) != FLASH_Status_Ready) {
787             if (--timeout == 0) {
788                 res = FLASH_ERR_DRV_TIMEOUT;
789                 break;
790             }
791         }
792
793         // Restore ROM to "normal" mode
794         ROM[0] = FLASH_Reset;
795
796         // Go to next block
797         b_p += len / sizeof( flash_data_t );
798         len = 0;
799
800         if (FLASH_ErrorLock == (state & FLASH_ErrorLock))
801             res = FLASH_ERR_LOCK;
802
803         if (res != FLASH_ERR_OK)
804             break;
805
806         if (bootblock)
807             len = flash_dev_info->bootblocks[len_ix++];
808     }
809
810     CYGHWR_FLASH_WRITE_DISABLE();
811     
812     return res;
813
814     // FIXME: Unlocking need to support some other parts in the future
815     // as well which take a little more diddling.
816 #if 0
817 //
818 // The difficulty with this operation is that the hardware does not support
819 // unlocking single blocks.  However, the logical layer would like this to
820 // be the case, so this routine emulates it.  The hardware can clear all of
821 // the locks in the device at once.  This routine will use that approach and
822 // then reset the regions which are known to be locked.
823 //
824
825 #define MAX_FLASH_BLOCKS (flash_dev_info->block_count * CYGNUM_FLASH_SERIES)
826
827     unsigned char is_locked[MAX_FLASH_BLOCKS];
828
829     // Get base address and map addresses to virtual addresses
830     ROM = FLASH_P2V( CYGNUM_FLASH_BASE_MASK & (unsigned int)block );
831     block = FLASH_P2V(block);
832
833     // Clear any error conditions
834     ROM[0] = FLASH_Clear_Status;
835
836     // Get current block lock state.  This needs to access each block on
837     // the device so currently locked blocks can be re-locked.
838     bp = ROM;
839     for (i = 0;  i < blocks;  i++) {
840         bpv = FLASH_P2V( bp );
841         *bpv = FLASH_Read_Query;
842         if (bpv == block) {
843             is_locked[i] = 0;
844         } else {
845             is_locked[i] = bpv[2];
846         }
847         bp += block_size / sizeof(*bp);
848     }
849
850     // Clears all lock bits
851     ROM[0] = FLASH_Clear_Locks;
852     ROM[0] = FLASH_Clear_Locks_Confirm;  // Confirmation
853     timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
854     while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
855         if (--timeout == 0) break;
856     }
857
858     // Restore the lock state
859     bp = ROM;
860     for (i = 0;  i < blocks;  i++) {
861         bpv = FLASH_P2V( bp );
862         if (is_locked[i]) {
863             *bpv = FLASH_Set_Lock;
864             *bpv = FLASH_Set_Lock_Confirm;  // Confirmation
865             timeout = CYGNUM_DEVS_FLASH_INTEL_28FXXX_TIMEOUT;
866             while(((stat = ROM[0]) & FLASH_Status_Ready) != FLASH_Status_Ready) {
867                 if (--timeout == 0) break;
868             }
869         }
870         bp += block_size / sizeof(*bp);
871     }
872
873     // Restore ROM to "normal" mode
874     ROM[0] = FLASH_Reset;
875 #endif
876 #endif // #CYGHWR_DEVS_FLASH_SHARP_LH28F016SCT_Z4
877 }
878 #endif // CYGHWR_IO_FLASH_BLOCK_LOCKING
879
880 #endif // CYGONCE_DEVS_FLASH_INTEL_28FXXX_INL