source: SVN/cambria/redboot/packages/io/flash/current/src/flash.c @ 1

Last change on this file since 1 was 1, checked in by Tim Harvey, 2 years ago

restored latest version of files from server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 20.3 KB
Line 
1//==========================================================================
2//
3//      flash.c
4//
5//      Flash programming
6//
7//==========================================================================
8//####ECOSGPLCOPYRIGHTBEGIN####
9// -------------------------------------------
10// This file is part of eCos, the Embedded Configurable Operating System.
11// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12// Copyright (C) 2003 Gary Thomas
13//
14// eCos is free software; you can redistribute it and/or modify it under
15// the terms of the GNU General Public License as published by the Free
16// Software Foundation; either version 2 or (at your option) any later version.
17//
18// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19// WARRANTY; without even the implied warranty of MERCHANTABILITY or
20// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21// for more details.
22//
23// You should have received a copy of the GNU General Public License along
24// with eCos; if not, write to the Free Software Foundation, Inc.,
25// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26//
27// As a special exception, if other files instantiate templates or use macros
28// or inline functions from this file, or you compile this file and link it
29// with other works to produce a work based on this file, this file does not
30// by itself cause the resulting work to be covered by the GNU General Public
31// License. However the source code for this file must still be made available
32// in accordance with section (3) of the GNU General Public License.
33//
34// This exception does not invalidate any other reasons why a work based on
35// this file might be covered by the GNU General Public License.
36//
37// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38// at http://sources.redhat.com/ecos/ecos-license/
39// -------------------------------------------
40//####ECOSGPLCOPYRIGHTEND####
41//==========================================================================
42//#####DESCRIPTIONBEGIN####
43//
44// Author(s):    gthomas
45// Contributors: gthomas
46// Date:         2000-07-26
47// Purpose:     
48// Description: 
49//             
50//####DESCRIPTIONEND####
51//
52//==========================================================================
53
54#include <pkgconf/system.h>
55#include <pkgconf/io_flash.h>
56
57#include <cyg/hal/hal_arch.h>
58#include <cyg/hal/hal_intr.h>
59#include <cyg/hal/hal_cache.h>
60#include <cyg/hal/hal_endian.h>
61#include <cyg/infra/diag.h>
62#include <string.h>
63
64#define  _FLASH_PRIVATE_
65#include <cyg/io/flash.h>
66
67// When this flag is set, do not actually jump to the relocated code.
68// This can be used for running the function in place (RAM startup only),
69// allowing calls to diag_printf() and similar.
70#undef RAM_FLASH_DEV_DEBUG
71#if !defined(CYG_HAL_STARTUP_RAM) && defined(RAM_FLASH_DEV_DEBUG)
72# warning "Can only enable the flash debugging when configured for RAM startup"
73#endif
74
75struct flash_info flash_info;
76
77// These are the functions in the HW specific driver we need to call.
78typedef void code_fun(void*);
79
80externC code_fun intel_flash_query;
81externC code_fun flash_erase_block;
82externC code_fun flash_program_buf;
83externC code_fun flash_read_buf;
84externC code_fun flash_lock_block;
85externC code_fun flash_unlock_block;
86
87externC code_fun amd_flash_query;
88externC code_fun amd_flash_erase_block;
89externC code_fun amd_flash_program_buf;
90externC code_fun amd_flash_read_buf;
91externC code_fun amd_flash_lock_block;
92externC code_fun amd_flash_unlock_block;
93
94extern int amd_flash_code_overlaps(void *, void*);
95extern int amd_flash_hwr_init(struct cfi_qry *cfi);
96extern int amd_flash_hwr_map_error(int);
97
98extern int intel_flash_code_overlaps(void *, void*);
99extern int intel_flash_hwr_init(void);
100extern int intel_flash_hwr_map_error(int);
101
102static struct cfi_qry flash_cfi;
103
104static void* __anonymizer(void* p);
105
106int
107_flash_hwr_map_error(int err) {
108    switch (flash_cfi.p_id) {
109    case CFI_CMDSET_AMD_STANDARD:
110      err = amd_flash_hwr_map_error(err);
111      break;
112    case CFI_CMDSET_INTEL_EXTENDED:
113      err = intel_flash_hwr_map_error(err);
114      break;
115    }
116
117    return err;
118}
119
120int
121flash_code_overlaps(void *start, void *end)
122{
123    switch (flash_cfi.p_id) {
124    case CFI_CMDSET_AMD_STANDARD:
125      return amd_flash_code_overlaps(start, end);
126      break;
127    case CFI_CMDSET_INTEL_EXTENDED:
128      return intel_flash_code_overlaps(start, end);
129      break;
130    }
131    return 0;
132}
133
134int cfi_query(struct cfi_qry *)  __attribute__ ((section (".2ram.cfi_query")));
135int
136cfi_query(struct cfi_qry *cfi)
137{
138        volatile flash_t *BA = FLASH_P2V( CYGNUM_FLASH_BASE );
139        unsigned int i;
140        unsigned char *data = (unsigned char *) cfi;
141
142        BA[0] = AMD_CMD_RESET;
143        BA[0] = FLASH_CMD_RESET;
144
145        // Enter CFI mode
146        BA[FLASH_OFFSET_CFI] = FLASH_CMD_CFI;
147
148        // Read CFI
149        for (i = 0; i < sizeof(struct cfi_qry); i++)
150                *data++ = (unsigned char) BA[FLASH_OFFSET_CFI_RESP + i];
151
152        // byteswap
153        cfi->p_id = CYG_LE16_TO_CPU(cfi->p_id);
154        cfi->p_adr = CYG_LE16_TO_CPU(cfi->p_adr);
155        cfi->a_id = CYG_LE16_TO_CPU(cfi->a_id);
156        cfi->a_adr = CYG_LE16_TO_CPU(cfi->a_adr);
157        cfi->interface_desc = CYG_LE16_TO_CPU(cfi->interface_desc);
158        cfi->max_buf_write_size = CYG_LE16_TO_CPU(cfi->max_buf_write_size);
159
160        // exit CFI mode
161        BA[0] = AMD_CMD_RESET;
162        // small delay required for Spansion or we don't exit CFI (??)
163        for (i = 0;  i < 5;  i++);
164        BA[0] = FLASH_CMD_RESET;
165
166        return 0;
167}
168
169int
170flash_init(_printf *pf)
171{
172    int err;
173    typedef void code_fun(struct cfi_qry *);
174    code_fun *_cfi_query;
175    int d_cache, i_cache;
176
177    if (flash_info.init) return FLASH_ERR_OK;
178    flash_info.pf = pf; // Do this before calling into the driver
179
180    memset(&flash_cfi, 0, sizeof(flash_cfi));
181    _cfi_query = (code_fun*) __anonymizer(&cfi_query);
182    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
183    (*_cfi_query)(&flash_cfi);
184    HAL_FLASH_CACHES_ON(d_cache, i_cache);
185
186    switch (flash_cfi.p_id) {
187    case CFI_CMDSET_AMD_STANDARD:
188      err = amd_flash_hwr_init(&flash_cfi);
189      break;
190    case CFI_CMDSET_INTEL_EXTENDED:
191      err = intel_flash_hwr_init();
192      break;
193    default:
194      diag_printf("Unsupported FLASH: CFI_ID=0x%04x\n", flash_cfi.p_id);
195      err = 1;
196      break;
197    }
198
199    if (err != FLASH_ERR_OK)
200      return err;
201    flash_info.block_mask = ~(flash_info.block_size-1);
202    flash_info.init = 1;
203    return FLASH_ERR_OK;
204}
205
206// Use this function to make function pointers anonymous - forcing the
207// compiler to use jumps instead of branches when calling driver
208// services.
209static void* __anonymizer(void* p)
210{
211  return p;
212}
213
214// FIXME: Want to change all drivers to use this function. But it may
215// make sense to wait till device structure pointer arguments get
216// added as well.
217void
218flash_dev_query(void* data)
219{
220    typedef void code_fun(void*);
221    code_fun *_flash_query;
222    int d_cache, i_cache;
223
224    switch (flash_cfi.p_id) {
225    case CFI_CMDSET_AMD_STANDARD:
226      _flash_query = (code_fun*) __anonymizer(&amd_flash_query);
227      break;
228    case CFI_CMDSET_INTEL_EXTENDED:
229      _flash_query = (code_fun*) __anonymizer(&intel_flash_query);
230      break;
231    default:
232      return;
233    }
234
235    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
236    (*_flash_query)(data);
237    HAL_FLASH_CACHES_ON(d_cache, i_cache);
238}
239
240int
241flash_verify_addr(void *target)
242{
243    if (!flash_info.init) {
244        return FLASH_ERR_NOT_INIT;
245    }
246    if (((CYG_ADDRESS)target >= (CYG_ADDRESS)flash_info.start) &&
247        ((CYG_ADDRESS)target <= ( ((CYG_ADDRESS)flash_info.end) - 1) )) {
248        return FLASH_ERR_OK;
249    } else {
250        return FLASH_ERR_INVALID;
251    }
252}
253
254int
255flash_get_limits(void *target, void **start, void **end)
256{
257    if (!flash_info.init) {
258        return FLASH_ERR_NOT_INIT;
259    }
260    *start = flash_info.start;
261    *end = flash_info.end;
262    return FLASH_ERR_OK;
263}
264
265int
266flash_get_block_info(int *block_size, int *blocks)
267{
268    if (!flash_info.init) {
269        return FLASH_ERR_NOT_INIT;
270    }
271    *block_size = flash_info.block_size;
272    *blocks = flash_info.blocks;
273    return FLASH_ERR_OK;
274}
275
276int
277flash_erase(void *addr, int len, void **err_addr)
278{
279    unsigned short *block, *end_addr;
280    int stat = 0;
281    typedef int code_fun(unsigned short *, unsigned int);
282    code_fun *_flash_erase_block;
283    int d_cache, i_cache;
284
285    if (!flash_info.init) {
286        return FLASH_ERR_NOT_INIT;
287    }
288
289#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
290    if (plf_flash_query_soft_wp(addr,len))
291        return FLASH_ERR_PROTECT;
292#endif
293
294    switch (flash_cfi.p_id) {
295    case CFI_CMDSET_AMD_STANDARD:
296      _flash_erase_block = (code_fun*) __anonymizer(&amd_flash_erase_block);
297      break;
298    case CFI_CMDSET_INTEL_EXTENDED:
299      _flash_erase_block = (code_fun*) __anonymizer(&flash_erase_block);
300      break;
301    default:
302      return FLASH_ERR_INVALID;
303    }
304
305    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
306    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
307
308    /* Check to see if end_addr overflowed */
309    if( (end_addr < block) && (len > 0) ){
310        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
311    }
312
313#ifdef CYGSEM_IO_FLASH_CHATTER
314    (*flash_info.pf)("... Erase from %p-%p: ", (void*)block, (void*)end_addr);
315#endif
316
317    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
318    FLASH_Enable(block, end_addr);
319    while (block < end_addr) {
320        // Supply the blocksize for a gross check for erase success
321        unsigned short *tmp_block;
322#if !defined(CYGSEM_IO_FLASH_READ_INDIRECT)
323        int i;
324        unsigned char *dp;
325        bool erased = true;
326
327        dp = (unsigned char *)block;
328        for (i = 0;  i < flash_info.block_size;  i++) {
329            if (*dp++ != (unsigned char)0xFF) {
330                erased = false;
331                break;
332            }
333        }
334#else
335        bool erased = false;
336#endif
337
338        if (!erased) {
339            stat = (*_flash_erase_block)(block, flash_info.block_size);
340            stat = _flash_hwr_map_error(stat);
341        }
342        if (stat) {
343            *err_addr = (void *)block;
344            break;
345        }
346
347        // Check to see if block will overflow
348        tmp_block = block + flash_info.block_size / sizeof(*block);
349        if(tmp_block < block){
350            // If block address overflows, set block value to end on this loop
351            block = end_addr;
352        }
353        else{
354            block = tmp_block;
355        }
356#ifdef CYGSEM_IO_FLASH_CHATTER
357        (*flash_info.pf)(".");
358#endif
359    }
360    FLASH_Disable(block, end_addr);
361    HAL_FLASH_CACHES_ON(d_cache, i_cache);
362#ifdef CYGSEM_IO_FLASH_CHATTER
363    (*flash_info.pf)("\n");
364#endif
365    return (stat);
366}
367
368int
369flash_program(void *_addr, void *_data, int len, void **err_addr)
370{
371    int stat = 0;
372    int size;
373    typedef int code_fun(void *, void *, int, unsigned long, int);
374    code_fun *_flash_program_buf;
375    unsigned char *addr = (unsigned char *)_addr;
376    unsigned char *data = (unsigned char *)_data;
377    CYG_ADDRESS tmp;
378    int d_cache, i_cache;
379
380    if (!flash_info.init) {
381        return FLASH_ERR_NOT_INIT;
382    }
383
384#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
385    if (plf_flash_query_soft_wp(addr,len))
386        return FLASH_ERR_PROTECT;
387#endif
388
389    switch (flash_cfi.p_id) {
390    case CFI_CMDSET_AMD_STANDARD:
391      _flash_program_buf = (code_fun*) __anonymizer(&amd_flash_program_buf);
392      break;
393    case CFI_CMDSET_INTEL_EXTENDED:
394      _flash_program_buf = (code_fun*) __anonymizer(&flash_program_buf);
395      break;
396    default:
397      return FLASH_ERR_INVALID;
398    }
399
400#ifdef CYGSEM_IO_FLASH_CHATTER
401    (*flash_info.pf)("... Program from %p-%p at %p: ", (void*)data, 
402                     (void*)(((CYG_ADDRESS)data)+len), (void*)addr);
403#endif
404
405    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
406    FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
407    while (len > 0) {
408        size = len;
409        if (size > flash_info.block_size) size = flash_info.block_size;
410
411        tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
412        if (tmp) {
413                tmp = flash_info.block_size - tmp;
414                if (size>(int)tmp) size = tmp;
415
416        }
417
418        stat = (*_flash_program_buf)(addr, data, size, 
419                                     flash_info.block_mask, flash_info.buffer_size);
420        stat = _flash_hwr_map_error(stat);
421#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
422            if (memcmp(addr, data, size) != 0) {
423                stat = 0x0BAD;
424#ifdef CYGSEM_IO_FLASH_CHATTER
425                (*flash_info.pf)("V");
426#endif
427            }
428#endif
429        if (stat) {
430            *err_addr = (void *)addr;
431            break;
432        }
433#ifdef CYGSEM_IO_FLASH_CHATTER
434        (*flash_info.pf)(".");
435#endif
436        len -= size;
437        addr += size/sizeof(*addr);
438        data += size/sizeof(*data);
439    }
440    FLASH_Disable((unsigned short*)addr, (unsigned short *)(addr+len));
441    HAL_FLASH_CACHES_ON(d_cache, i_cache);
442#ifdef CYGSEM_IO_FLASH_CHATTER
443    (*flash_info.pf)("\n");
444#endif
445    return (stat);
446}
447
448int
449flash_read(void *_addr, void *_data, int len, void **err_addr)
450{
451#ifdef CYGSEM_IO_FLASH_READ_INDIRECT
452    int stat = 0;
453    int size;
454    typedef int code_fun(void *, void *, int, unsigned long, int);
455    code_fun *_flash_read_buf;
456    unsigned char *addr = (unsigned char *)_addr;
457    unsigned char *data = (unsigned char *)_data;
458    CYG_ADDRESS tmp;
459    int d_cache, i_cache;
460
461    if (!flash_info.init) {
462        return FLASH_ERR_NOT_INIT;
463    }
464
465    switch (flash_cfi.p_id) {
466    case CFI_CMDSET_AMD_STANDARD:
467      _flash_read_buf = (code_fun*) __anonymizer(&amd_flash_read_buf);
468      break;
469    case CFI_CMDSET_INTEL_EXTENDED:
470      _flash_read_buf = (code_fun*) __anonymizer(&flash_read_buf);
471      break;
472    }
473
474#ifdef CYGSEM_IO_FLASH_CHATTER
475    (*flash_info.pf)("... Read from %p-%p at %p: ", (void*)data, 
476                     (void*)(((CYG_ADDRESS)data)+len), (void*)addr);
477#endif
478
479    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
480    FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
481    while (len > 0) {
482        size = len;
483        if (size > flash_info.block_size) size = flash_info.block_size;
484
485        tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
486        if (tmp) {
487                tmp = flash_info.block_size - tmp;
488                if (size>tmp) size = tmp;
489
490        }
491
492        stat = (*_flash_read_buf)(addr, data, size, 
493                                     flash_info.block_mask, flash_info.buffer_size);
494        stat = _flash_hwr_map_error(stat);
495#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM_
496        if (0 == stat) // Claims to be OK
497            if (memcmp(addr, data, size) != 0) {               
498                stat = 0x0BAD;
499#ifdef CYGSEM_IO_FLASH_CHATTER
500                (*flash_info.pf)("V");
501#endif
502            }
503#endif
504        if (stat) {
505            *err_addr = (void *)addr;
506            break;
507        }
508#ifdef CYGSEM_IO_FLASH_CHATTER
509        (*flash_info.pf)(".");
510#endif
511        len -= size;
512        addr += size/sizeof(*addr);
513        data += size/sizeof(*data);
514    }
515    FLASH_Disable((unsigned short*)addr, (unsigned short *)(addr+len));
516    HAL_FLASH_CACHES_ON(d_cache, i_cache);
517#ifdef CYGSEM_IO_FLASH_CHATTER
518    (*flash_info.pf)("\n");
519#endif
520    return (stat);
521#else // CYGSEM_IO_FLASH_READ_INDIRECT
522    // Direct access to FLASH memory is possible - just move the requested bytes
523    if (!flash_info.init) {
524        return FLASH_ERR_NOT_INIT;
525    }
526    memcpy(_data, _addr, len);
527    return FLASH_ERR_OK;
528#endif
529}
530
531#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
532
533int
534flash_lock(void *addr, int len, void **err_addr)
535{
536    unsigned short *block, *end_addr;
537    int stat = 0;
538    typedef int code_fun(unsigned short *);
539    code_fun *_flash_lock_block;
540    int d_cache, i_cache;
541
542    if (!flash_info.init) {
543        return FLASH_ERR_NOT_INIT;
544    }
545
546#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
547    if (plf_flash_query_soft_wp(addr,len))
548        return FLASH_ERR_PROTECT;
549#endif
550
551    switch (flash_cfi.p_id) {
552    case CFI_CMDSET_AMD_STANDARD:
553      _flash_lock_block = (code_fun*) __anonymizer(&amd_flash_lock_block);
554      break;
555    case CFI_CMDSET_INTEL_EXTENDED:
556      _flash_lock_block = (code_fun*) __anonymizer(&flash_lock_block);
557      break;
558    default:
559      return FLASH_ERR_INVALID;
560    }
561
562    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
563    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
564
565    /* Check to see if end_addr overflowed */
566    if( (end_addr < block) && (len > 0) ){
567        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
568    }
569
570#ifdef CYGSEM_IO_FLASH_CHATTER
571    (*flash_info.pf)("... Lock from %p-%p: ", block, end_addr);
572#endif
573
574    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
575    FLASH_Enable(block, end_addr);
576    while (block < end_addr) {
577        unsigned short *tmp_block;
578        stat = (*_flash_lock_block)(block);
579        stat = _flash_hwr_map_error(stat);
580        if (stat) {
581            *err_addr = (void *)block;
582            break;
583        }
584
585        // Check to see if block will overflow
586        tmp_block = block + flash_info.block_size / sizeof(*block);
587        if(tmp_block < block){
588            // If block address overflows, set block value to end on this loop
589            block = end_addr;
590        }
591        else{
592            block = tmp_block;
593        }
594#ifdef CYGSEM_IO_FLASH_CHATTER
595        (*flash_info.pf)(".");
596#endif
597    }
598    FLASH_Disable(block, end_addr);
599    HAL_FLASH_CACHES_ON(d_cache, i_cache);
600#ifdef CYGSEM_IO_FLASH_CHATTER
601    (*flash_info.pf)("\n");
602#endif
603    return (stat);
604}
605
606int
607flash_unlock(void *addr, int len, void **err_addr)
608{
609    unsigned short *block, *end_addr;
610    int stat = 0;
611    typedef int code_fun(unsigned short *, int, int);
612    code_fun *_flash_unlock_block;
613    int d_cache, i_cache;
614
615    if (!flash_info.init) {
616        return FLASH_ERR_NOT_INIT;
617    }
618
619#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
620    if (plf_flash_query_soft_wp(addr,len))
621        return FLASH_ERR_PROTECT;
622#endif
623
624    switch (flash_cfi.p_id) {
625    case CFI_CMDSET_AMD_STANDARD:
626      _flash_unlock_block = (code_fun*) __anonymizer(&amd_flash_unlock_block);
627      break;
628    case CFI_CMDSET_INTEL_EXTENDED:
629      _flash_unlock_block = (code_fun*) __anonymizer(&flash_unlock_block);
630      break;
631    default:
632      return FLASH_ERR_INVALID;
633    }
634
635    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
636    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
637
638    /* Check to see if end_addr overflowed */
639    if( (end_addr < block) && (len > 0) ){
640        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
641    }
642
643#ifdef CYGSEM_IO_FLASH_CHATTER
644    (*flash_info.pf)("... Unlock from %p-%p: ", block, end_addr);
645#endif
646
647    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
648    FLASH_Enable(block, end_addr);
649    while (block < end_addr) {
650        unsigned short *tmp_block;
651        stat = (*_flash_unlock_block)(block, flash_info.block_size, flash_info.blocks);
652        stat = _flash_hwr_map_error(stat);
653        if (stat) {
654            *err_addr = (void *)block;
655            break;
656        }
657
658        tmp_block = block + flash_info.block_size / sizeof(*block);
659        if(tmp_block < block){
660            // If block address overflows, set block value to end on this loop
661            block = end_addr;
662        }
663        else{
664            block = tmp_block;
665        }
666#ifdef CYGSEM_IO_FLASH_CHATTER
667        (*flash_info.pf)(".");
668#endif
669    }
670    FLASH_Disable(block, end_addr);
671    HAL_FLASH_CACHES_ON(d_cache, i_cache);
672#ifdef CYGSEM_IO_FLASH_CHATTER
673    (*flash_info.pf)("\n");
674#endif
675    return (stat);
676}
677#endif
678
679char *
680flash_errmsg(int err)
681{
682    switch (err) {
683    case FLASH_ERR_OK:
684        return "No error - operation complete";
685    case FLASH_ERR_ERASE_SUSPEND:
686        return "Device is in erase suspend state";
687    case FLASH_ERR_PROGRAM_SUSPEND:
688        return "Device is in program suspend state";
689    case FLASH_ERR_INVALID:
690        return "Invalid FLASH address";
691    case FLASH_ERR_ERASE:
692        return "Error trying to erase";
693    case FLASH_ERR_LOCK:
694        return "Error trying to lock/unlock";
695    case FLASH_ERR_PROGRAM:
696        return "Error trying to program";
697    case FLASH_ERR_PROTOCOL:
698        return "Generic error";
699    case FLASH_ERR_PROTECT:
700        return "Device/region is write-protected";
701    case FLASH_ERR_NOT_INIT:
702        return "FLASH sub-system not initialized";
703    case FLASH_ERR_DRV_VERIFY:
704        return "Data verify failed after operation";
705    case FLASH_ERR_DRV_TIMEOUT:
706        return "Driver timed out waiting for device";
707    case FLASH_ERR_DRV_WRONG_PART:
708        return "Driver does not support device";
709    case FLASH_ERR_LOW_VOLTAGE:
710        return "Device reports low voltage";
711    case FLASH_ERR_BLOCK_LOCKED:
712        return "Device block is locked";
713    default:
714        return "Unknown error";
715    }
716}
717
718// EOF io/flash/..../flash.c
Note: See TracBrowser for help on using the repository browser.