OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [flash/] [current/] [src/] [flash.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
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, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY 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        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas, Andrew Lunn, Bart Veer
44
// Date:         2000-07-26
45
// Purpose:      
46
// Description:  
47
//              
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
#include <pkgconf/system.h>
53
#include <pkgconf/io_flash.h>
54
#ifdef CYGPKG_KERNEL
55
#include <cyg/kernel/kapi.h>
56
#endif
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_tables.h>
61
#include <cyg/infra/cyg_ass.h>
62
#include <string.h>
63
 
64
#include <cyg/io/flash.h>
65
#include <cyg/io/flash_dev.h>
66
#include "flash_legacy.h"
67
 
68
// When this flag is set, do not actually jump to the relocated code.
69
// This can be used for running the function in place (RAM startup
70
// only), allowing calls to diag_printf() and similar.
71
#undef RAM_FLASH_DEV_DEBUG
72
#if !defined(CYG_HAL_STARTUP_RAM) && defined(RAM_FLASH_DEV_DEBUG)
73
# warning "Can only enable the flash debugging when configured for RAM startup"
74
#endif
75
 
76
// Optional verbosity. Using a macro here avoids lots of ifdefs in the
77
// rest of the code.
78
#ifdef CYGSEM_IO_FLASH_CHATTER
79
# define CHATTER(_dev_, _fmt_, ...) CYG_MACRO_START \
80
    if ((_dev_)->pf)                                \
81
        (*(_dev_)->pf)((_fmt_), ## __VA_ARGS__);    \
82
    CYG_MACRO_END
83
#else
84
# define CHATTER(_dev_, _fmt_, ...) CYG_EMPTY_STATEMENT
85
#endif
86
 
87
// Per-thread locking. Again using macros avoids lots of ifdefs
88
#ifdef CYGPKG_KERNEL
89
# define LOCK_INIT(_dev_)   cyg_mutex_init(&((_dev_)->mutex))
90
# define LOCK(_dev_)        cyg_mutex_lock(&((_dev_)->mutex))
91
# define UNLOCK(_dev_)      cyg_mutex_unlock(&((_dev_)->mutex))
92
#else
93
# define LOCK_INIT(_dev_)   CYG_EMPTY_STATEMENT
94
# define LOCK(_dev_)        CYG_EMPTY_STATEMENT
95
# define UNLOCK(_dev_)      CYG_EMPTY_STATEMENT
96
#endif
97
 
98
// Software write-protect. Very rarely used.
99
#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
100
# define CHECK_SOFT_WRITE_PROTECT(_addr_, _len_)    \
101
  CYG_MACRO_START                                   \
102
  if (plf_flash_query_soft_wp((_addr_), (_len_)))   \
103
    return CYG_FLASH_ERR_PROTECT;                   \
104
  CYG_MACRO_END
105
#else
106
#define CHECK_SOFT_WRITE_PROTECT(_addr_, _len_) CYG_EMPTY_STATEMENT
107
#endif
108
 
109
// Has the FLASH IO library been initialised?
110
static bool init;
111
 
112
// This array contains entries for all flash devices that are
113
// installed in the system.
114
__externC struct cyg_flash_dev cyg_flashdevtab[];
115
CYG_HAL_TABLE_BEGIN(cyg_flashdevtab, cyg_flashdev);
116
 
117
// end of the flashdev table
118
__externC struct cyg_flash_dev cyg_flashdevtab_end;
119
CYG_HAL_TABLE_END(cyg_flashdevtab_end, cyg_flashdev);
120
 
121
#if (1 == CYGHWR_IO_FLASH_DEVICE)
122
 
123
// Optimize the code for a single flash device, which is the common case.
124
// The flash subsystem must have been initialized, the single device must
125
// contain the specified address, and the device itself must have
126
// initialized successfully.
127
static struct cyg_flash_dev*
128
find_dev(cyg_flashaddr_t addr, int* stat)
129
{
130
  if (!init) {
131
    *stat = CYG_FLASH_ERR_NOT_INIT;
132
    return NULL;
133
  }
134
  if (! ((addr >= cyg_flashdevtab[0].start) && (addr <= cyg_flashdevtab[0].end))) {
135
    *stat = CYG_FLASH_ERR_INVALID;
136
    return NULL;
137
  }
138
  if (! cyg_flashdevtab[0].init) {
139
    *stat = CYG_FLASH_ERR_NOT_INIT;
140
    return NULL;
141
  }
142
  return &cyg_flashdevtab[0];
143
}
144
 
145
#else
146
 
147
// There are multiple devices. For convenience these are kept in a
148
// linked list, sorted by address. This is the head of the list
149
static struct cyg_flash_dev *flash_head = NULL;
150
 
151
static bool flash_sort_and_check(void)
152
{
153
  bool moved;
154
  struct cyg_flash_dev *dev, **previous_next;
155
 
156
  // Place all devices that initialised on the list, unsorted for now.
157
  for (dev = &cyg_flashdevtab[0]; dev != &cyg_flashdevtab_end; dev++) {
158
    if (dev->init) {
159
      dev->next  = flash_head;
160
      flash_head = dev;
161
    }
162
  }
163
 
164
  // If there are no valid devices, abort. This might happen if
165
  // all drivers failed to initialize.
166
  if (flash_head == NULL) {
167
    return false;
168
  }
169
 
170
  // Sort the linked list into ascending order of flash address. Use a
171
  // primitive ripple sort, but since we don't expect to have many
172
  // devices this should be OK. This loop may run safely with just one
173
  // entry on the list.
174
  do {
175
    moved=false;
176
    for (dev=flash_head, previous_next=&flash_head;
177
         dev->next;
178
         previous_next = &dev->next, dev=dev->next ){
179
      if (dev->start > dev->next->start) {
180
        *previous_next=dev->next;
181
        dev->next = (*previous_next)->next;
182
        (*previous_next)->next = dev;
183
        moved=true;
184
        break;
185
      }
186
    }
187
  } while (moved);
188
 
189
  // Now walk the linked list and see if there are any overlaps in the
190
  // addresses the devices claim to use using.
191
  for (dev=flash_head; dev->next; dev=dev->next){
192
    if (dev->end >= dev->next->start)
193
      return false;
194
  }
195
  return true;
196
}
197
 
198
// Find the device at the specified address, if any.
199
static struct cyg_flash_dev*
200
find_dev(cyg_flashaddr_t addr, int* stat)
201
{
202
  struct cyg_flash_dev*   dev;
203
  if (!init) {
204
    *stat = CYG_FLASH_ERR_NOT_INIT;
205
    return NULL;
206
  }
207
  for (dev = flash_head; dev; dev = dev->next) {
208
    if ((dev->start <= addr) && (addr <= dev->end)) {
209
      return dev;
210
    }
211
  }
212
  *stat = CYG_FLASH_ERR_INVALID;
213
  return NULL;
214
}
215
 
216
#endif
217
 
218
// Initialise all registered device. Any device that fails to
219
// initialise we leave dev->init as false. Then sort the devices into
220
// ascending order of address and put them into a linked list. Lastly
221
// check if we have any overlap of the addresses.
222
__externC int
223
cyg_flash_init(cyg_flash_printf *pf)
224
{
225
  int err;
226
  struct cyg_flash_dev * dev;
227
 
228
  CYG_ASSERT(&(cyg_flashdevtab[CYGHWR_IO_FLASH_DEVICE]) == &cyg_flashdevtab_end, "incorrect number of flash devices");
229
 
230
  // In case the printf function has changed.
231
  if (NULL != pf)
232
      cyg_flash_set_global_printf(pf);
233
 
234
  if (init) {
235
      return CYG_FLASH_ERR_OK;
236
  }
237
 
238
  for (dev = &cyg_flashdevtab[0]; dev != &cyg_flashdevtab_end; dev++) {
239
    LOCK_INIT(dev);
240
 
241
    err = dev->funs->flash_init(dev);
242
    if (err != CYG_FLASH_ERR_OK) {
243
      continue;
244
    }
245
    CYG_ASSERT(dev->funs, "No flash functions");
246
    CYG_ASSERT(dev->num_block_infos, "No number of block infos");
247
    CYG_ASSERT(dev->block_info, "No block infos");
248
    CYG_ASSERT(!(((cyg_flashaddr_t)dev->block_info >= dev->start) &&
249
                 ((cyg_flashaddr_t)dev->block_info < dev->end)),
250
               "Block info is in the flash");
251
    CYG_ASSERT(dev->funs->flash_erase_block, "No erase function");
252
    CYG_ASSERT(dev->funs->flash_program, "No program function");
253
#ifdef CYGDBG_USE_ASSERTS
254
    {
255
         int i;
256
         cyg_flashaddr_t addr = dev->start;
257
         for (i = 0; i < dev->num_block_infos; i++) {
258
              addr += dev->block_info[i].block_size * dev->block_info[i].blocks;
259
         }
260
         CYG_ASSERT(dev->end == addr-1, "Invalid end address");
261
    }
262
#endif
263
    dev->init = true;
264
  }
265
 
266
#if (1 == CYGHWR_IO_FLASH_DEVICE)
267
  // Make sure there is one device, otherwise we could end up
268
  // accessing a non-existent cyg_flash_dev structure.
269
  if (&(cyg_flashdevtab[0]) == &cyg_flashdevtab_end) {
270
      return CYG_FLASH_ERR_INVALID;
271
  }
272
#else
273
  // Place the devices on a sorted linked list and check that there
274
  // are no overlaps in the address space.
275
  if (! flash_sort_and_check() ) {
276
    return CYG_FLASH_ERR_INVALID;
277
  }
278
#endif
279
 
280
  // Only mark the flash subsystem as initialized if the world is
281
  // consistent.
282
  init = true;
283
  return CYG_FLASH_ERR_OK;
284
}
285
 
286
// Set a printf function to use for a particular device,
287
// which is associated with the supplied base address
288
__externC int
289
cyg_flash_set_printf(const cyg_flashaddr_t flash_base,
290
                     cyg_flash_printf *pf)
291
{
292
  struct cyg_flash_dev *dev;
293
  int                   stat = CYG_FLASH_ERR_OK;
294
 
295
  dev = find_dev(flash_base, &stat);
296
  if (dev) {
297
    // Locking may seem like overkill, but if there's any chance of CHATTER
298
    // mid-change then bad things are theoretically possible. But we only
299
    // lock if this device is usable, i.e. it's been initialised.
300
    if (dev->init) {
301
      LOCK(dev);
302
    }
303
    dev->pf = pf;
304
    if (dev->init) {
305
      UNLOCK(dev);
306
    }
307
  }
308
  return stat;
309
}
310
 
311
// Set a printf function to use for all flash devices.
312
// This overrides any previously set printf function.
313
__externC void
314
 cyg_flash_set_global_printf(cyg_flash_printf *pf)
315
{
316
  struct cyg_flash_dev *dev;
317
  for (dev = &cyg_flashdevtab[0]; dev != &cyg_flashdevtab_end; dev++) {
318
    // Locking may seem like overkill, but if there's any chance of CHATTER
319
    // mid-change then bad things are theoretically possible. But we only
320
    // lock if this device is usable, i.e. it's been initialised.
321
    if (dev->init) {
322
      LOCK(dev);
323
    }
324
    dev->pf = pf;
325
    if (dev->init) {
326
      UNLOCK(dev);
327
    }
328
  }
329
}
330
 
331
// Is the address within one of the flash drivers?
332
__externC int
333
cyg_flash_verify_addr(const cyg_flashaddr_t address)
334
{
335
  int stat = CYG_FLASH_ERR_OK;
336
  (void) find_dev(address, &stat);
337
  return stat;
338
}
339
 
340
// Return information about the Nth driver
341
__externC int
342
cyg_flash_get_info(cyg_uint32 Nth, cyg_flash_info_t * info)
343
{
344
  struct cyg_flash_dev * dev;
345
 
346
  if (!init) return CYG_FLASH_ERR_NOT_INIT;
347
 
348
#if (1 == CYGHWR_IO_FLASH_DEVICE)
349
  if ((0 == Nth) && cyg_flashdevtab[0].init) {
350
      dev = &(cyg_flashdevtab[0]);
351
  } else {
352
      return CYG_FLASH_ERR_INVALID;
353
  }
354
#else
355
  // Only initialized devices are on the list.
356
  for (dev = flash_head; dev && Nth; dev=dev->next, Nth--)
357
    ;
358
  if (!dev) {
359
      return CYG_FLASH_ERR_INVALID;
360
  }
361
#endif
362
  info->start = dev->start;
363
  info->end = dev->end;
364
  info->num_block_infos = dev->num_block_infos;
365
  info->block_info = dev->block_info;
366
  return CYG_FLASH_ERR_OK;
367
}
368
 
369
// Return information about the flash at the given address
370
__externC int
371
cyg_flash_get_info_addr(const cyg_flashaddr_t flash_base, cyg_flash_info_t * info)
372
{
373
  struct cyg_flash_dev *dev;
374
  int                   stat = CYG_FLASH_ERR_OK;
375
 
376
  dev = find_dev(flash_base, &stat);
377
  if (dev) {
378
    info->start = dev->start;
379
    info->end = dev->end;
380
    info->num_block_infos = dev->num_block_infos;
381
    info->block_info = dev->block_info;
382
  }
383
  return stat;
384
}
385
 
386
#ifdef CYGPKG_KERNEL
387
// Lock the mutex's for a range of addresses
388
__externC int
389
cyg_flash_mutex_lock(const cyg_flashaddr_t from, size_t len)
390
{
391
  struct cyg_flash_dev *    dev;
392
  int                       stat    = CYG_FLASH_ERR_OK;
393
 
394
  dev = find_dev(from, &stat);
395
  if (dev) {
396
    LOCK(dev);
397
    if (len > (dev->end + 1 - from)) {
398
      stat = cyg_flash_mutex_lock(dev->end + 1, len - (dev->end + 1 - from));
399
      if (CYG_FLASH_ERR_OK != stat) {
400
        // Something went wrong, unlock what we just locked
401
        UNLOCK(dev);
402
      }
403
    }
404
  }
405
  return stat;
406
}
407
 
408
// Unlock the mutex's for a range of addresses
409
__externC int
410
cyg_flash_mutex_unlock(const cyg_flashaddr_t from, size_t len)
411
{
412
  struct cyg_flash_dev *    dev;
413
  int                       stat = CYG_FLASH_ERR_OK;
414
 
415
  dev = find_dev(from, &stat);
416
  if (dev) {
417
    UNLOCK(dev);
418
    if (len > (dev->end + 1 - from)) {
419
      stat = cyg_flash_mutex_lock(dev->end + 1, len - (dev->end + 1 - from));
420
      if (CYG_FLASH_ERR_OK != stat) {
421
        // Something went wrong, relock what we just unlocked. This may not
422
        // be worth it since things must be pretty messed up, and could
423
        // conceivably end in deadlock if there is a concurrent call to
424
        // cyg_flash_mutex_lock();
425
        LOCK(dev);
426
      }
427
    }
428
  }
429
  return stat;
430
}
431
#endif
432
 
433
// Return the size of the block which is at the given address
434
static size_t
435
flash_block_size(struct cyg_flash_dev *dev, const cyg_flashaddr_t addr)
436
{
437
  int i;
438
  size_t offset;
439
 
440
  CYG_ASSERT((addr >= dev->start) && (addr <= dev->end), "Not inside device");
441
 
442
  offset = addr - dev->start;
443
  for (i=0; i < dev->num_block_infos; i++) {
444
    if (offset < (dev->block_info[i].blocks * dev->block_info[i].block_size))
445
      return dev->block_info[i].block_size;
446
    offset = offset -
447
      (dev->block_info[i].blocks * dev->block_info[i].block_size);
448
  }
449
  CYG_FAIL("Programming error");
450
  return 0;
451
}
452
 
453
// Return the size of the block which is at the given address
454
__externC size_t
455
cyg_flash_block_size(const cyg_flashaddr_t flash_base)
456
{
457
  struct cyg_flash_dev *    dev;
458
  int                       stat;
459
 
460
  dev = find_dev(flash_base, &stat);
461
  if (!dev) return stat;
462
  return flash_block_size(dev, flash_base);
463
}
464
 
465
// Return the first address of a block. The flash might not be aligned
466
// in terms of its block size. So we have to be careful and use
467
// offsets.
468
static inline cyg_flashaddr_t
469
flash_block_begin(cyg_flashaddr_t addr, struct cyg_flash_dev *dev)
470
{
471
  size_t block_size;
472
  cyg_flashaddr_t offset;
473
 
474
  block_size = flash_block_size(dev, addr);
475
 
476
  offset = addr - dev->start;
477
  offset = (offset / block_size) * block_size;
478
  return offset + dev->start;
479
}
480
 
481
 
482
__externC int
483
cyg_flash_erase(cyg_flashaddr_t flash_base,
484
                size_t len,
485
                cyg_flashaddr_t *err_address)
486
{
487
  cyg_flashaddr_t block, end_addr;
488
  struct cyg_flash_dev * dev;
489
  size_t erase_count;
490
  int stat = CYG_FLASH_ERR_OK;
491
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);
492
 
493
  dev = find_dev(flash_base, &stat);
494
  if (!dev) return stat;
495
 
496
  CHECK_SOFT_WRITE_PROTECT(flash_base, len);
497
 
498
  LOCK(dev);
499
 
500
  // Check whether or not we are going past the end of this device, on
501
  // to the next one. If so the next device will be handled by a
502
  // recursive call later on.
503
  if (len > (dev->end + 1 - flash_base)) {
504
      end_addr = dev->end;
505
  } else {
506
      end_addr = flash_base + len - 1;
507
  }
508
  // erase can only happen on a block boundary, so adjust for this
509
  block         = flash_block_begin(flash_base, dev);
510
  erase_count   = (end_addr + 1) - block;
511
 
512
  CHATTER(dev, "... Erase from %p-%p: ", (void*)block, (void*)end_addr);
513
 
514
  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
515
  FLASH_Enable(flash_base, end_addr);
516
  while (erase_count > 0) {
517
    int i;
518
    unsigned char *dp;
519
    bool erased = false;
520
    size_t block_size = flash_block_size(dev, block);
521
 
522
    // Pad to the block boundary, if necessary
523
    if (erase_count < block_size) {
524
        erase_count = block_size;
525
    }
526
 
527
    // If there is a read function it probably means the flash
528
    // cannot be read directly.
529
    if (!dev->funs->flash_read) {
530
      erased = true;
531
      dp = (unsigned char *)block;
532
      for (i = 0;  i < block_size;  i++) {
533
        if (*dp++ != (unsigned char)0xFF) {
534
          erased = false;
535
          break;
536
        }
537
      }
538
    }
539
    if (!erased) {
540
      stat = dev->funs->flash_erase_block(dev,block);
541
    }
542
    if (CYG_FLASH_ERR_OK != stat) {
543
        if (err_address)
544
            *err_address = block;
545
        break;
546
    }
547
    block       += block_size;
548
    erase_count -= block_size;
549
    CHATTER(dev, ".");
550
  }
551
  FLASH_Disable(flash_base, end_addr);
552
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
553
  CHATTER(dev, "\n");
554
  UNLOCK(dev);
555
  if (stat != CYG_FLASH_ERR_OK) {
556
    return stat;
557
  }
558
 
559
  // If there are multiple flash devices in series the erase operation
560
  // may touch successive devices. This can be handled by recursion.
561
  // The stack overheads should be minimal because the number of
562
  // devices will be small.
563
  if (len > (dev->end + 1 - flash_base)) {
564
    return cyg_flash_erase(dev->end+1,
565
                           len - (dev->end + 1 - flash_base),
566
                           err_address);
567
  }
568
  return CYG_FLASH_ERR_OK;
569
}
570
 
571
__externC int
572
cyg_flash_program(cyg_flashaddr_t flash_base,
573
                  const void *ram_base,
574
                  size_t len,
575
                  cyg_flashaddr_t *err_address)
576
{
577
  struct cyg_flash_dev * dev;
578
  cyg_flashaddr_t addr, end_addr, block;
579
  const unsigned char * ram = ram_base;
580
  size_t write_count, offset;
581
  int stat = CYG_FLASH_ERR_OK;
582
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);
583
 
584
  dev = find_dev(flash_base, &stat);
585
  if (!dev) return stat;
586
 
587
  CHECK_SOFT_WRITE_PROTECT(flash_base, len);
588
 
589
  LOCK(dev);
590
  addr = flash_base;
591
  if (len > (dev->end + 1 - flash_base)) {
592
    end_addr = dev->end;
593
  } else {
594
    end_addr = flash_base + len - 1;
595
  }
596
  write_count = (end_addr + 1) - flash_base;
597
 
598
  // The first write may be in the middle of a block. Do the necessary
599
  // adjustment here rather than inside the loop.
600
  block = flash_block_begin(flash_base, dev);
601
  if (addr == block) {
602
      offset = 0;
603
  } else {
604
      offset = addr - block;
605
  }
606
 
607
  CHATTER(dev, "... Program from %p-%p to %p: ", ram_base, ((CYG_ADDRESS)ram_base)+write_count, addr);
608
 
609
  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
610
  FLASH_Enable(flash_base, end_addr);
611
  while (write_count > 0) {
612
    size_t block_size = flash_block_size(dev, addr);
613
    size_t this_write;
614
    if (write_count > (block_size - offset)) {
615
        this_write = block_size - offset;
616
    } else {
617
        this_write = write_count;
618
    }
619
    // Only the first block may need the offset.
620
    offset       = 0;
621
 
622
    stat = dev->funs->flash_program(dev, addr, ram, this_write);
623
#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
624
    if (CYG_FLASH_ERR_OK == stat) // Claims to be OK
625
      if (!dev->funs->flash_read && memcmp((void *)addr, ram, this_write) != 0) {
626
        stat = CYG_FLASH_ERR_DRV_VERIFY;
627
        CHATTER(dev, "V");
628
      }
629
#endif
630
    if (CYG_FLASH_ERR_OK != stat) {
631
        if (err_address)
632
            *err_address = addr;
633
        break;
634
    }
635
    CHATTER(dev, ".");
636
    write_count -= this_write;
637
    addr        += this_write;
638
    ram         += this_write;
639
  }
640
  FLASH_Disable(flash_base, end_addr);
641
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
642
  CHATTER(dev, "\n");
643
  UNLOCK(dev);
644
  if (stat != CYG_FLASH_ERR_OK) {
645
    return (stat);
646
  }
647
  if (len > (dev->end + 1 - flash_base)) {
648
    return cyg_flash_program(dev->end+1, ram,
649
                             len - (dev->end + 1 - flash_base),
650
                             err_address);
651
  }
652
  return CYG_FLASH_ERR_OK;
653
}
654
 
655
__externC int
656
cyg_flash_read(const cyg_flashaddr_t flash_base,
657
               void *ram_base,
658
               size_t len,
659
               cyg_flashaddr_t *err_address)
660
{
661
  struct cyg_flash_dev * dev;
662
  cyg_flashaddr_t addr, end_addr;
663
  unsigned char * ram = (unsigned char *)ram_base;
664
  size_t read_count;
665
  int stat = CYG_FLASH_ERR_OK;
666
 
667
  dev = find_dev(flash_base, &stat);
668
  if (!dev) return stat;
669
 
670
  LOCK(dev);
671
  addr = flash_base;
672
  if (len > (dev->end + 1 - flash_base)) {
673
      end_addr = dev->end;
674
  } else {
675
      end_addr = flash_base + len - 1;
676
  }
677
  read_count = (end_addr + 1) - flash_base;
678
 
679
  //  CHATTER(dev, "... Read from %p-%p to %p: ", addr, end_addr, ram_base);
680
 
681
  // If the flash is directly accessible, just read it in one go. This
682
  // still happens with the mutex locked to protect against concurrent
683
  // programs/erases.
684
  if (! dev->funs->flash_read) {
685
      memcpy(ram, (void*)addr, read_count);
686
  } else {
687
#ifndef CYGHWR_IO_FLASH_INDIRECT_READS
688
      CYG_FAIL("read function supplied but indirect reads not enabled");
689
      stat = CYG_FLASH_ERR_PROTOCOL;
690
      if (err_address) {
691
          *err_address = addr;
692
      }
693
#else
694
      // We have to indirect through the device driver.
695
      // The first read may be in the middle of a block. Do the necessary
696
      // adjustment here rather than inside the loop.
697
      size_t            offset;
698
      cyg_flashaddr_t   block = flash_block_begin(flash_base, dev);
699
      HAL_FLASH_CACHES_STATE(d_cache, i_cache);
700
      if (addr == block) {
701
          offset = 0;
702
      } else {
703
          offset = addr - block;
704
      }
705
      HAL_FLASH_CACHES_OFF(d_cache, i_cache);
706
      FLASH_Enable(flash_base, end_addr);
707
      while (read_count > 0) {
708
          size_t block_size = flash_block_size(dev, addr);
709
          size_t this_read;
710
          if (read_count > (block_size - offset)) {
711
              this_read = block_size - offset;
712
          } else {
713
              this_read = read_count;
714
          }
715
          // Only the first block may need the offset
716
          offset      = 0;
717
 
718
          stat = dev->funs->flash_read(dev, addr, ram, this_read);
719
          if (CYG_FLASH_ERR_OK != stat && err_address) {
720
              *err_address = addr;
721
              break;
722
          }
723
          //          CHATTER(dev, ".");
724
          read_count  -= this_read;
725
          addr        += this_read;
726
          ram         += this_read;
727
      }
728
      FLASH_Disable(flash_base, end_addr);
729
      HAL_FLASH_CACHES_ON(d_cache, i_cache);
730
#endif      
731
  }
732
  //  CHATTER(dev, "\n");
733
  UNLOCK(dev);
734
  if (stat != CYG_FLASH_ERR_OK) {
735
    return (stat);
736
  }
737
  if (len > (dev->end + 1 - flash_base)) {
738
      return cyg_flash_read(dev->end+1, ram,
739
                            len - (dev->end + 1 - flash_base),
740
                            err_address);
741
  }
742
  return CYG_FLASH_ERR_OK;
743
}
744
 
745
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
746
__externC int
747
cyg_flash_lock(const cyg_flashaddr_t flash_base,
748
               size_t len,
749
               cyg_flashaddr_t *err_address)
750
{
751
  cyg_flashaddr_t block, end_addr;
752
  struct cyg_flash_dev * dev;
753
  size_t lock_count;
754
  int stat = CYG_FLASH_ERR_OK;
755
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);
756
 
757
  dev = find_dev(flash_base, &stat);
758
  if (!dev) return stat;
759
  if (!dev->funs->flash_block_lock) return CYG_FLASH_ERR_INVALID;
760
 
761
  CHECK_SOFT_WRITE_PROTECT(flash_base, len);
762
 
763
  LOCK(dev);
764
  if (len > (dev->end + 1 - flash_base)) {
765
      end_addr = dev->end;
766
  } else {
767
      end_addr = flash_base + len - 1;
768
  }
769
  block         = flash_block_begin(flash_base, dev);
770
  lock_count    = (end_addr + 1) - block;
771
 
772
  CHATTER(dev, "... Locking from %p-%p: ", (void*)block, (void*)end_addr);
773
 
774
  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
775
  FLASH_Enable(flash_base, end_addr);
776
  while (lock_count > 0) {
777
    size_t  block_size  = flash_block_size(dev, block);
778
    if (lock_count < block_size) {
779
        lock_count = block_size;
780
    }
781
    stat = dev->funs->flash_block_lock(dev,block);
782
 
783
    if (CYG_FLASH_ERR_OK != stat && err_address) {
784
      *err_address = block;
785
      break;
786
    }
787
    block       += block_size;
788
    lock_count  -= block_size;
789
    CHATTER(dev, ".");
790
  }
791
  FLASH_Disable(flash_base, end_addr);
792
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
793
  CHATTER(dev, "\n");
794
  UNLOCK(dev);
795
  if (stat != CYG_FLASH_ERR_OK) {
796
    return stat;
797
  }
798
 
799
  // Recurse if necessary for the next device
800
  if (len > (dev->end + 1 - flash_base)) {
801
    return cyg_flash_lock(dev->end+1,
802
                          len - (dev->end + 1 - flash_base),
803
                          err_address);
804
  }
805
 
806
  return CYG_FLASH_ERR_OK;
807
}
808
 
809
__externC int
810
cyg_flash_unlock(const cyg_flashaddr_t flash_base,
811
                 size_t len,
812
                 cyg_flashaddr_t *err_address)
813
{
814
  cyg_flashaddr_t block, end_addr;
815
  struct cyg_flash_dev * dev;
816
  size_t unlock_count;
817
  int stat = CYG_FLASH_ERR_OK;
818
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);
819
 
820
  dev = find_dev(flash_base, &stat);
821
  if (!dev) return stat;
822
  if (!dev->funs->flash_block_unlock) return CYG_FLASH_ERR_INVALID;
823
 
824
  CHECK_SOFT_WRITE_PROTECT(flash_base, len);
825
 
826
  LOCK(dev);
827
  if (len > (dev->end + 1 - flash_base)) {
828
      end_addr = dev->end;
829
  } else {
830
      end_addr = flash_base + len - 1;
831
  }
832
  block         = flash_block_begin(flash_base, dev);
833
  unlock_count  = (end_addr + 1) - block;
834
 
835
  CHATTER(dev, "... Unlocking from %p-%p: ", (void*)block, (void*)end_addr);
836
 
837
  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
838
  FLASH_Enable(flash_base, end_addr);
839
  while (unlock_count > 0) {
840
    size_t    block_size  = flash_block_size(dev, block);
841
    if (unlock_count < block_size) {
842
        unlock_count = block_size;
843
    }
844
    stat = dev->funs->flash_block_unlock(dev,block);
845
 
846
    if (CYG_FLASH_ERR_OK != stat && err_address) {
847
      *err_address = block;
848
      break;
849
    }
850
    block           += block_size;
851
    unlock_count    -= block_size;
852
 
853
    CHATTER(dev, ".");
854
  }
855
  FLASH_Disable(flash_base, end_addr);
856
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
857
  CHATTER(dev, "\n");
858
  UNLOCK(dev);
859
  if (stat != CYG_FLASH_ERR_OK) {
860
    return stat;
861
  }
862
 
863
  // Recurse if necessary for the next device
864
  if (len > (dev->end + 1 - flash_base)) {
865
    return cyg_flash_lock(dev->end+1,
866
                          len - (dev->end + 1 - flash_base),
867
                          err_address);
868
  }
869
  return CYG_FLASH_ERR_OK;
870
}
871
#endif
872
 
873
const char *
874
cyg_flash_errmsg(const int err)
875
{
876
    switch (err) {
877
    case CYG_FLASH_ERR_OK:
878
        return "No error - operation complete";
879
    case CYG_FLASH_ERR_ERASE_SUSPEND:
880
        return "Device is in erase suspend state";
881
    case CYG_FLASH_ERR_PROGRAM_SUSPEND:
882
        return "Device is in program suspend state";
883
    case CYG_FLASH_ERR_INVALID:
884
        return "Invalid FLASH address";
885
    case CYG_FLASH_ERR_ERASE:
886
        return "Error trying to erase";
887
    case CYG_FLASH_ERR_LOCK:
888
        return "Error trying to lock/unlock";
889
    case CYG_FLASH_ERR_PROGRAM:
890
        return "Error trying to program";
891
    case CYG_FLASH_ERR_PROTOCOL:
892
        return "Generic error";
893
    case CYG_FLASH_ERR_PROTECT:
894
        return "Device/region is write-protected";
895
    case CYG_FLASH_ERR_NOT_INIT:
896
        return "FLASH sub-system not initialized";
897
    case CYG_FLASH_ERR_DRV_VERIFY:
898
        return "Data verify failed after operation";
899
    case CYG_FLASH_ERR_DRV_TIMEOUT:
900
        return "Driver timed out waiting for device";
901
    case CYG_FLASH_ERR_DRV_WRONG_PART:
902
        return "Driver does not support device";
903
    case CYG_FLASH_ERR_LOW_VOLTAGE:
904
        return "Device reports low voltage";
905
    default:
906
        return "Unknown error";
907
    }
908
}
909
 
910
// Dummy routines to put into the device function tables, to handle
911
// unsupported/unnecessary functionality. For example not all devices
912
// support block locking.
913
//
914
// A dummy initialization routine, for platforms where everything is
915
// done statically and there is no need to check device ids or
916
// anything similar.
917
int
918
cyg_flash_devfn_init_nop(struct cyg_flash_dev* dev)
919
{
920
    CYG_UNUSED_PARAM(struct cyg_flash_dev*, dev);
921
    return CYG_FLASH_ERR_OK;
922
}
923
 
924
// A dummy query routine. The implementation of this is specific to
925
// each device driver, so some device drivers may choose to do
926
// nothing.
927
size_t
928
cyg_flash_devfn_query_nop(struct cyg_flash_dev* dev, void* data, size_t len)
929
{
930
    CYG_UNUSED_PARAM(struct cyg_flash_dev*, dev);
931
    CYG_UNUSED_PARAM(void*, data);
932
    CYG_UNUSED_PARAM(size_t, len);
933
    return 0;
934
}
935
 
936
// Dummy lock/unlock routines
937
int
938
cyg_flash_devfn_lock_nop(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr)
939
{
940
    CYG_UNUSED_PARAM(struct cyg_flash_dev*, dev);
941
    CYG_UNUSED_PARAM(cyg_flashaddr_t, addr);
942
#if defined(CYGHWR_IO_FLASH_BLOCK_LOCKING) && (1 < CYGHWR_IO_FLASH_DEVICE)
943
// If we've been built with locking, and there's more than one flash
944
// device in the system, then this is probably only being called because
945
// we can't tell what devices do and don't support locking, and for a _nop
946
// function this is the device that doesn't support locking. So we don't
947
// complain if we're asked to.
948
    return CYG_FLASH_ERR_OK;
949
#else
950
    return CYG_FLASH_ERR_DRV_WRONG_PART;
951
#endif
952
}
953
 
954
int
955
cyg_flash_devfn_unlock_nop(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr)
956
{
957
    CYG_UNUSED_PARAM(struct cyg_flash_dev*, dev);
958
    CYG_UNUSED_PARAM(cyg_flashaddr_t, addr);
959
#if defined(CYGHWR_IO_FLASH_BLOCK_LOCKING) && (1 < CYGHWR_IO_FLASH_DEVICE)
960
// If we've been built with locking, and there's more than one flash
961
// device in the system, then this is probably only being called because
962
// we can't tell what devices do and don't support locking, and for a _nop
963
// function this is the device that doesn't support locking. So we don't
964
// complain if we're asked to.
965
    return CYG_FLASH_ERR_OK;
966
#else
967
    return CYG_FLASH_ERR_DRV_WRONG_PART;
968
#endif
969
}
970
 
971
// On some architectures there are problems calling the .2ram
972
// functions from the main ones. Specifically the compiler may issue a
973
// short call, even though the flash and ram are too far apart. The
974
// solution is to indirect via a function pointer, but the simplistic
975
// approach is vulnerable to compiler optimization. Hence the function
976
// pointer is passed through an anonymizer.
977
void*
978
cyg_flash_anonymizer(void* fn)
979
{
980
    return fn;
981
}
982
 
983
// EOF io/flash/..../flash.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.