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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [flash/] [amd/] [am29xxxxx/] [v2_0/] [include/] [flash_am29xxxxx.inl] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL
2
#define CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL
3
//==========================================================================
4
//
5
//      am29xxxxx.inl
6
//
7
//      AMD AM29xxxxx 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):    gthomas
47
// Contributors: gthomas, jskov, Koichi Nagashima
48
// Date:         2001-02-21
49
// Purpose:
50
// Description:  AMD AM29xxxxx series flash device driver
51
// Notes:        While the parts support sector locking, some only do so
52
//               via crufty magic and the use of programmer hardware
53
//               (specifically by applying 12V to one of the address
54
//               pins) so the driver does not support write protection.
55
//
56
// FIXME:        Should support SW locking on the newer devices.
57
//
58
// FIXME:        Figure out how to do proper error checking when there are
59
//               devices in parallel. Presently the driver will return
60
//               driver timeout error on device errors which is not very
61
//               helpful.
62
//
63
//####DESCRIPTIONEND####
64
//
65
//==========================================================================
66
 
67
#include 
68
#include 
69
#include 
70
#include 
71
#include CYGHWR_MEMORY_LAYOUT_H
72
 
73
#define  _FLASH_PRIVATE_
74
#include 
75
 
76
//----------------------------------------------------------------------------
77
// Common device details.
78
#define FLASH_Read_ID                   FLASHWORD( 0x90 )
79
#define FLASH_WP_State                  FLASHWORD( 0x90 )
80
#define FLASH_Reset                     FLASHWORD( 0xF0 )
81
#define FLASH_Program                   FLASHWORD( 0xA0 )
82
#define FLASH_Block_Erase               FLASHWORD( 0x30 )
83
 
84
#define FLASH_Data                      FLASHWORD( 0x80 ) // Data complement
85
#define FLASH_Busy                      FLASHWORD( 0x40 ) // "Toggle" bit
86
#define FLASH_Err                       FLASHWORD( 0x20 )
87
#define FLASH_Sector_Erase_Timer        FLASHWORD( 0x08 )
88
 
89
#define FLASH_unlocked                  FLASHWORD( 0x00 )
90
 
91
#ifndef CYGNUM_FLASH_16AS8
92
#define _16AS8 0
93
#else
94
#define _16AS8 CYGNUM_FLASH_16AS8
95
#endif
96
 
97
#if (_16AS8 == 0)
98
# define FLASH_Setup_Addr1              (0x555)
99
# define FLASH_Setup_Addr2              (0x2AA)
100
# define FLASH_VendorID_Addr            (0)
101
# define FLASH_DeviceID_Addr            (1)
102
# define FLASH_DeviceID_Addr2           (0x0e)
103
# define FLASH_DeviceID_Addr3           (0x0f)
104
# define FLASH_WP_Addr                  (2)
105
#else
106
# define FLASH_Setup_Addr1              (0xAAA)
107
# define FLASH_Setup_Addr2              (0x555)
108
# define FLASH_VendorID_Addr            (0)
109
# define FLASH_DeviceID_Addr            (2)
110
# define FLASH_DeviceID_Addr2           (0x1c)
111
# define FLASH_DeviceID_Addr3           (0x1e)
112
# define FLASH_WP_Addr                  (4)
113
#endif
114
#define FLASH_Setup_Code1               FLASHWORD( 0xAA )
115
#define FLASH_Setup_Code2               FLASHWORD( 0x55 )
116
#define FLASH_Setup_Erase               FLASHWORD( 0x80 )
117
 
118
// Platform code must define the below
119
// #define CYGNUM_FLASH_INTERLEAVE      : Number of interleaved devices (in parallel)
120
// #define CYGNUM_FLASH_SERIES          : Number of devices in series
121
// #define CYGNUM_FLASH_WIDTH           : Width of devices on platform
122
// #define CYGNUM_FLASH_BASE            : Address of first device
123
 
124
#define CYGNUM_FLASH_BLANK              (1)
125
 
126
#ifndef FLASH_P2V
127
# define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_)))
128
#endif
129
#ifndef CYGHWR_FLASH_AM29XXXXX_PLF_INIT
130
# define CYGHWR_FLASH_AM29XXXXX_PLF_INIT()
131
#endif
132
 
133
//----------------------------------------------------------------------------
134
// Now that device properties are defined, include magic for defining
135
// accessor type and constants.
136
#include 
137
 
138
//----------------------------------------------------------------------------
139
// Information about supported devices
140
typedef struct flash_dev_info {
141
    cyg_bool     long_device_id;
142
    flash_data_t device_id;
143
    flash_data_t device_id2;
144
    flash_data_t device_id3;
145
    cyg_uint32   block_size;
146
    cyg_int32    block_count;
147
    cyg_uint32   base_mask;
148
    cyg_uint32   device_size;
149
    cyg_bool     bootblock;
150
    cyg_uint32   bootblocks[64];         // 0 is bootblock offset, 1-11 sub-sector sizes (or 0)
151
    cyg_bool     banked;
152
    cyg_uint32   banks[8];               // bank offsets, highest to lowest (lowest should be 0)
153
                                         // (only one entry for now, increase to support devices
154
                                         // with more banks).
155
} flash_dev_info_t;
156
 
157
static const flash_dev_info_t* flash_dev_info;
158
static const flash_dev_info_t supported_devices[] = {
159
#include 
160
};
161
#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
162
 
163
//----------------------------------------------------------------------------
164
// Functions that put the flash device into non-read mode must reside
165
// in RAM.
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
    __attribute__ ((section (".2ram.flash_program_buf")));
171
static void _flash_query(void* data) __attribute__ ((section (".2ram._flash_query")));
172
static int  _flash_erase_block(void* block, unsigned int size)
173
    __attribute__ ((section (".2ram._flash_erase_block")));
174
static int  _flash_program_buf(void* addr, void* data, int len)
175
    __attribute__ ((section (".2ram._flash_program_buf")));
176
 
177
//----------------------------------------------------------------------------
178
// Flash Query
179
//
180
// Only reads the manufacturer and part number codes for the first
181
// device(s) in series. It is assumed that any devices in series
182
// will be of the same type.
183
 
184
static void
185
_flash_query(void* data)
186
{
187
    volatile flash_data_t *ROM;
188
    volatile flash_data_t *f_s1, *f_s2;
189
    flash_data_t* id = (flash_data_t*) data;
190
    flash_data_t w;
191
    long timeout = 500000;
192
 
193
    ROM = (flash_data_t*) CYGNUM_FLASH_BASE;
194
    f_s1 = FLASH_P2V(ROM+FLASH_Setup_Addr1);
195
    f_s2 = FLASH_P2V(ROM+FLASH_Setup_Addr2);
196
 
197
    *f_s1 = FLASH_Reset;
198
    w = *(FLASH_P2V(ROM));
199
 
200
    *f_s1 = FLASH_Setup_Code1;
201
    *f_s2 = FLASH_Setup_Code2;
202
    *f_s1 = FLASH_Read_ID;
203
 
204
    id[0] = -1;
205
    id[1] = -1;
206
 
207
    // Manufacturers' code
208
    id[0] = *(FLASH_P2V(ROM+FLASH_VendorID_Addr));
209
    // Part number
210
    id[1] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr));
211
    id[2] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr2));
212
    id[3] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr3));
213
 
214
 
215
    *(FLASH_P2V(ROM)) = FLASH_Reset;
216
 
217
    // Stall, waiting for flash to return to read mode.
218
    while ((--timeout != 0) && (w != *(FLASH_P2V(ROM)))) ;
219
}
220
 
221
void
222
flash_query(void* data)
223
{
224
    int cache_on;
225
 
226
    HAL_DCACHE_IS_ENABLED(cache_on);
227
    if (cache_on) {
228
        HAL_DCACHE_SYNC();
229
        HAL_DCACHE_DISABLE();
230
    }
231
    _flash_query(data);
232
    if (cache_on) {
233
        HAL_DCACHE_ENABLE();
234
    }
235
}
236
 
237
//----------------------------------------------------------------------------
238
// Initialize driver details
239
int
240
flash_hwr_init(void)
241
{
242
    flash_data_t id[4];
243
    int i;
244
 
245
    CYGHWR_FLASH_AM29XXXXX_PLF_INIT();
246
 
247
    flash_dev_query(id);
248
 
249
    // Look through table for device data
250
    flash_dev_info = supported_devices;
251
    for (i = 0; i < NUM_DEVICES; i++) {
252
        if (!flash_dev_info->long_device_id && flash_dev_info->device_id == id[1])
253
            break;
254
        else if ( flash_dev_info->long_device_id && flash_dev_info->device_id == id[1]
255
                  && flash_dev_info->device_id2 == id[2]
256
                  && flash_dev_info->device_id3 == id[3] )
257
            break;
258
        flash_dev_info++;
259
    }
260
 
261
    // Did we find the device? If not, return error.
262
    if (NUM_DEVICES == i)
263
        return FLASH_ERR_DRV_WRONG_PART;
264
 
265
    // Hard wired for now
266
    flash_info.block_size = flash_dev_info->block_size;
267
    flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
268
    flash_info.start = (void *)CYGNUM_FLASH_BASE;
269
    flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
270
    return FLASH_ERR_OK;
271
}
272
 
273
//----------------------------------------------------------------------------
274
// Map a hardware status to a package error
275
int
276
flash_hwr_map_error(int e)
277
{
278
    return e;
279
}
280
 
281
 
282
//----------------------------------------------------------------------------
283
// See if a range of FLASH addresses overlaps currently running code
284
bool
285
flash_code_overlaps(void *start, void *end)
286
{
287
    extern unsigned char _stext[], _etext[];
288
 
289
    return ((((unsigned long)&_stext >= (unsigned long)start) &&
290
             ((unsigned long)&_stext < (unsigned long)end)) ||
291
            (((unsigned long)&_etext >= (unsigned long)start) &&
292
             ((unsigned long)&_etext < (unsigned long)end)));
293
}
294
 
295
//----------------------------------------------------------------------------
296
// Erase Block
297
 
298
static int
299
_flash_erase_block(void* block, unsigned int size)
300
{
301
    volatile flash_data_t* ROM, *BANK;
302
    volatile flash_data_t* b_p = (flash_data_t*) block;
303
    volatile flash_data_t *b_v;
304
    volatile flash_data_t *f_s0, *f_s1, *f_s2;
305
    int timeout = 50000;
306
    int len = 0;
307
    int res = FLASH_ERR_OK;
308
    flash_data_t state;
309
    cyg_bool bootblock = false;
310
    cyg_uint32 *bootblocks = (cyg_uint32 *)0;
311
    CYG_ADDRWORD bank_offset;
312
 
313
    BANK = ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
314
 
315
    // If this is a banked device, find the bank where commands should
316
    // be addressed to.
317
    if (flash_dev_info->banked) {
318
        int b = 0;
319
        bank_offset = (unsigned long)block & ~(flash_dev_info->block_size-1);
320
        bank_offset -= (unsigned long) ROM;
321
        for(;;) {
322
            if (bank_offset >= flash_dev_info->banks[b]) {
323
                BANK = (volatile flash_data_t*) ((unsigned long)ROM + flash_dev_info->banks[b]);
324
                break;
325
            }
326
            b++;
327
        }
328
    }
329
 
330
    f_s0 = FLASH_P2V(BANK);
331
    f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
332
    f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
333
 
334
    // Assume not "boot" sector, full size
335
    bootblock = false;
336
    len = flash_dev_info->block_size;
337
 
338
    // Is this in a "boot" sector?
339
    if (flash_dev_info->bootblock) {
340
        bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0];
341
        while (*bootblocks != _LAST_BOOTBLOCK) {
342
            if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) {
343
                len = *bootblocks++;  // Size of first sub-block
344
                bootblock = true;
345
                break;
346
            } else {
347
                int ls = flash_dev_info->block_size;
348
                // Skip over segment
349
                while ((ls -= *bootblocks++) > 0) ;
350
            }
351
        }
352
    }
353
 
354
    while (size > 0) {
355
#ifndef CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT
356
        // First check whether the block is protected
357
        *f_s1 = FLASH_Setup_Code1;
358
        *f_s2 = FLASH_Setup_Code2;
359
        *f_s1 = FLASH_WP_State;
360
        state = *FLASH_P2V(b_p+FLASH_WP_Addr);
361
        *f_s0 = FLASH_Reset;
362
 
363
        if (FLASH_unlocked != state)
364
            return FLASH_ERR_PROTECT;
365
#endif
366
 
367
        b_v = FLASH_P2V(b_p);
368
 
369
        // Send erase block command - six step sequence
370
        *f_s1 = FLASH_Setup_Code1;
371
        *f_s2 = FLASH_Setup_Code2;
372
        *f_s1 = FLASH_Setup_Erase;
373
        *f_s1 = FLASH_Setup_Code1;
374
        *f_s2 = FLASH_Setup_Code2;
375
        *b_v = FLASH_Block_Erase;
376
 
377
        // Now poll for the completion of the sector erase timer (50us)
378
        timeout = 10000000;              // how many retries?
379
        while (true) {
380
            state = *b_v;
381
            if ((state & FLASH_Sector_Erase_Timer)
382
                                == FLASH_Sector_Erase_Timer) break;
383
 
384
            if (--timeout == 0) {
385
                res = FLASH_ERR_DRV_TIMEOUT;
386
                break;
387
            }
388
        }
389
 
390
        // Then wait for erase completion.
391
        if (FLASH_ERR_OK == res) {
392
            timeout = 10000000;
393
            while (true) {
394
                state = *b_v;
395
                if (FLASH_BlankValue == state) {
396
                    break;
397
                }
398
 
399
                // Don't check for FLASH_Err here since it will fail
400
                // with devices in parallel because these may finish
401
                // at different times.
402
 
403
                if (--timeout == 0) {
404
                    res = FLASH_ERR_DRV_TIMEOUT;
405
                    break;
406
                }
407
            }
408
        }
409
 
410
        if (FLASH_ERR_OK != res)
411
            *FLASH_P2V(ROM) = FLASH_Reset;
412
 
413
        size -= len;  // This much has been erased
414
 
415
        // Verify erase operation
416
        while (len > 0) {
417
            b_v = FLASH_P2V(b_p++);
418
            if (*b_v != FLASH_BlankValue) {
419
                // Only update return value if erase operation was OK
420
                if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
421
                return res;
422
            }
423
            len -= sizeof(*b_p);
424
        }
425
 
426
        if (bootblock) {
427
            len = *bootblocks++;
428
        }
429
    }
430
    return res;
431
}
432
 
433
int
434
flash_erase_block(void* block, unsigned int size)
435
{
436
    int ret, cache_on;
437
    HAL_DCACHE_IS_ENABLED(cache_on);
438
    if (cache_on) {
439
        HAL_DCACHE_SYNC();
440
        HAL_DCACHE_DISABLE();
441
    }
442
    ret = _flash_erase_block(block, size);
443
    if (cache_on) {
444
        HAL_DCACHE_ENABLE();
445
    }
446
    return ret;
447
}
448
 
449
//----------------------------------------------------------------------------
450
// Program Buffer
451
static int
452
_flash_program_buf(void* addr, void* data, int len)
453
{
454
    volatile flash_data_t* ROM;
455
    volatile flash_data_t* BANK;
456
    volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;
457
    volatile flash_data_t* addr_v;
458
    volatile flash_data_t* addr_p = (flash_data_t*) addr;
459
    volatile flash_data_t *f_s1, *f_s2;
460
    CYG_ADDRWORD bank_offset;
461
    int timeout;
462
    int res = FLASH_ERR_OK;
463
 
464
    // check the address is suitably aligned
465
    if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1))
466
        return FLASH_ERR_INVALID;
467
 
468
    // Base address of device(s) being programmed.
469
    BANK = ROM = (volatile flash_data_t*)((unsigned long)addr_p & flash_dev_info->base_mask);
470
 
471
    // If this is a banked device, find the bank where commands should
472
    // be addressed to.
473
    if (flash_dev_info->banked) {
474
        int b = 0;
475
        bank_offset = (unsigned long)addr & ~(flash_dev_info->block_size-1);
476
        bank_offset -= (unsigned long) ROM;
477
        for(;;) {
478
            if (bank_offset >= flash_dev_info->banks[b]) {
479
                BANK = (volatile flash_data_t*) ((unsigned long)ROM + flash_dev_info->banks[b]);
480
                break;
481
            }
482
            b++;
483
        }
484
    }
485
 
486
    f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
487
    f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
488
 
489
    while (len > 0) {
490
        flash_data_t state;
491
 
492
        addr_v = FLASH_P2V(addr_p++);
493
 
494
        // Program data [byte] - 4 step sequence
495
        *f_s1 = FLASH_Setup_Code1;
496
        *f_s2 = FLASH_Setup_Code2;
497
        *f_s1 = FLASH_Program;
498
        *addr_v = *data_ptr;
499
 
500
        timeout = 10000000;
501
        while (true) {
502
            state = *addr_v;
503
            if (*data_ptr == state) {
504
                break;
505
            }
506
 
507
            // Can't check for FLASH_Err since it'll fail in parallel
508
            // configurations.
509
 
510
            if (--timeout == 0) {
511
                res = FLASH_ERR_DRV_TIMEOUT;
512
                break;
513
            }
514
        }
515
 
516
        if (FLASH_ERR_OK != res)
517
            *FLASH_P2V(ROM) = FLASH_Reset;
518
 
519
        if (*addr_v != *data_ptr++) {
520
            // Only update return value if erase operation was OK
521
            if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
522
            break;
523
        }
524
        len -= sizeof(*data_ptr);
525
    }
526
 
527
    // Ideally, we'd want to return not only the failure code, but also
528
    // the address/device that reported the error.
529
    return res;
530
}
531
 
532
int
533
flash_program_buf(void* addr, void* data, int len)
534
{
535
    int ret, cache_on;
536
    HAL_DCACHE_IS_ENABLED(cache_on);
537
    if (cache_on) {
538
        HAL_DCACHE_SYNC();
539
        HAL_DCACHE_DISABLE();
540
    }
541
    ret = _flash_program_buf(addr, data, len);
542
    if (cache_on) {
543
        HAL_DCACHE_ENABLE();
544
    }
545
    return ret;
546
}
547
#endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL

powered by: WebSVN 2.1.0

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