1 #ifndef CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL
2 #define CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL
3 //==========================================================================
7 // AMD AM29xxxxx series flash driver
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, 2004 Gary Thomas
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.
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
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.
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.
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.
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####
47 // Contributors: gthomas, jskov, Koichi Nagashima
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.
56 // FIXME: Should support SW locking on the newer devices.
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
63 //####DESCRIPTIONEND####
65 //==========================================================================
67 #include <pkgconf/hal.h>
68 #include <pkgconf/devs_flash_amd_am29xxxxx.h>
69 #include <cyg/hal/hal_arch.h>
70 #include <cyg/hal/hal_cache.h>
71 #include <cyg/hal/hal_misc.h>
72 #include CYGHWR_MEMORY_LAYOUT_H
74 #define _FLASH_PRIVATE_
75 #include <cyg/io/flash.h>
77 //----------------------------------------------------------------------------
78 // Common device details.
79 #define FLASH_Read_ID FLASHWORD( 0x90 )
80 #define FLASH_WP_State FLASHWORD( 0x90 )
81 #define FLASH_Reset FLASHWORD( 0xF0 )
82 #define FLASH_Program FLASHWORD( 0xA0 )
83 #define FLASH_Block_Erase FLASHWORD( 0x30 )
84 #define FLASH_Load_Buffer FLASHWORD( 0x25 )
85 #define FLASH_Flush_Buffer FLASHWORD( 0x29 )
87 #define FLASH_Data FLASHWORD( 0x80 ) // Data complement
88 #define FLASH_Busy FLASHWORD( 0x40 ) // "Toggle" bit
89 #define FLASH_Err FLASHWORD( 0x20 )
90 #define FLASH_Sector_Erase_Timer FLASHWORD( 0x08 )
92 #define FLASH_unlocked FLASHWORD( 0x00 )
94 #ifndef CYGNUM_FLASH_16AS8
97 #define _16AS8 CYGNUM_FLASH_16AS8
101 # if (_16AS8 == 0)||CYGHWR_DEVS_FLASH_ST_M29W320D
102 # define FLASH_Setup_Addr1 (0x555)
103 # define FLASH_Setup_Addr2 (0x2AA)
104 # define FLASH_VendorID_Addr (0)
105 # define FLASH_DeviceID_Addr (1)
106 # define FLASH_DeviceID_Addr2 (0x0e)
107 # define FLASH_DeviceID_Addr3 (0x0f)
108 # define FLASH_WP_Addr (2)
110 # define FLASH_Setup_Addr1 (0xAAA)
111 # define FLASH_Setup_Addr2 (0x555)
112 # define FLASH_VendorID_Addr (0)
113 # define FLASH_DeviceID_Addr (2)
114 # define FLASH_DeviceID_Addr2 (0x1c)
115 # define FLASH_DeviceID_Addr3 (0x1e)
116 # define FLASH_WP_Addr (4)
119 #define FLASH_Setup_Code1 FLASHWORD( 0xAA )
120 #define FLASH_Setup_Code2 FLASHWORD( 0x55 )
121 #define FLASH_Setup_Erase FLASHWORD( 0x80 )
123 // Platform code must define the below
124 // #define CYGNUM_FLASH_INTERLEAVE : Number of interleaved devices (in parallel)
125 // #define CYGNUM_FLASH_SERIES : Number of devices in series
126 // #define CYGNUM_FLASH_WIDTH : Width of devices on platform
127 // #define CYGNUM_FLASH_BASE : Address of first device
129 // Platform code may define some or all of the below, to provide
130 // timeouts appropriate to the target hardware. The timeout
131 // values depend partly on the flash part being used, partly
132 // on the target (including bus and cpu speeds).
133 #ifndef CYGNUM_FLASH_TIMEOUT_QUERY
134 # define CYGNUM_FLASH_TIMEOUT_QUERY 500000
136 #ifndef CYGNUM_FLASH_TIMEOUT_ERASE_TIMER
137 # define CYGNUM_FLASH_TIMEOUT_ERASE_TIMER 10000000
139 #ifndef CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE
140 # define CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE 10000000
142 #ifndef CYGNUM_FLASH_TIMEOUT_PROGRAM
143 # define CYGNUM_FLASH_TIMEOUT_PROGRAM 10000000
146 #define CYGNUM_FLASH_BLANK (1)
149 # define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_)))
151 #ifndef CYGHWR_FLASH_AM29XXXXX_PLF_INIT
152 # define CYGHWR_FLASH_AM29XXXXX_PLF_INIT()
155 //----------------------------------------------------------------------------
156 // Now that device properties are defined, include magic for defining
157 // accessor type and constants.
158 #include <cyg/io/flash_dev.h>
160 //----------------------------------------------------------------------------
161 // Information about supported devices
162 typedef struct flash_dev_info {
163 cyg_bool long_device_id;
164 flash_data_t device_id;
165 flash_data_t device_id2;
166 flash_data_t device_id3;
167 cyg_uint32 block_size;
168 cyg_int32 block_count;
169 cyg_uint32 base_mask;
170 cyg_uint32 device_size;
172 cyg_uint32 bootblocks[64]; // 0 is bootblock offset, 1-11 sub-sector sizes (or 0)
174 cyg_uint32 banks[16]; // bank offsets, highest to lowest (lowest should be 0)
175 // (only one entry for now, increase to support devices
177 cyg_uint32 bufsiz; // write buffer size in units of flash_data_t
180 static const flash_dev_info_t* flash_dev_info;
181 static const flash_dev_info_t supported_devices[] = {
182 #include <cyg/io/flash_am29xxxxx_parts.inl>
184 #define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
186 //----------------------------------------------------------------------------
187 // Functions that put the flash device into non-read mode must reside
189 #ifndef MXCFLASH_SELECT_MULTI
190 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
191 int flash_erase_block(void* block, unsigned int size)
192 __attribute__ ((section (".2ram.flash_erase_block")));
193 int flash_program_buf(void* addr, void* data, int len)
194 __attribute__ ((section (".2ram.flash_program_buf")));
196 //----------------------------------------------------------------------------
197 // Auxiliary functions
198 static volatile flash_data_t * find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo)
199 __attribute__ ((section (".2ram.find_bank")));
200 static flash_data_t * find_sector(volatile flash_data_t * addr, unsigned long *remain_size)
201 __attribute__ ((section (".2ram.find_sector")));
204 void norflash_query(void* data);
205 int norflash_erase_block(void* block, unsigned int size);
206 int norflash_program_buf(void* addr, void* data, int len);
208 //----------------------------------------------------------------------------
209 // Auxiliary functions
210 static volatile flash_data_t * find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo);
211 static flash_data_t * find_sector(volatile flash_data_t * addr, unsigned long *remain_size);
212 #endif //MXCFLASH_SELECT_MULTI
214 //----------------------------------------------------------------------------
217 // Only reads the manufacturer and part number codes for the first
218 // device(s) in series. It is assumed that any devices in series
219 // will be of the same type.
222 #ifndef MXCFLASH_SELECT_MULTI
223 flash_query(void* data)
225 norflash_query(void* data)
228 volatile flash_data_t *ROM;
229 volatile flash_data_t *f_s1, *f_s2;
230 flash_data_t* id = (flash_data_t*) data;
232 long timeout = CYGNUM_FLASH_TIMEOUT_QUERY;
234 ROM = (flash_data_t*) CYGNUM_FLASH_BASE;
235 f_s1 = FLASH_P2V(ROM+FLASH_Setup_Addr1);
236 f_s2 = FLASH_P2V(ROM+FLASH_Setup_Addr2);
239 w = *(FLASH_P2V(ROM));
241 *f_s1 = FLASH_Setup_Code1;
242 *f_s2 = FLASH_Setup_Code2;
243 *f_s1 = FLASH_Read_ID;
248 // Manufacturers' code
249 id[0] = *(FLASH_P2V(ROM+FLASH_VendorID_Addr));
251 id[1] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr));
252 id[2] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr2));
253 id[3] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr3));
256 *(FLASH_P2V(ROM)) = FLASH_Reset;
258 // Stall, waiting for flash to return to read mode.
259 while ((--timeout != 0) && (w != *(FLASH_P2V(ROM)))) ;
263 //----------------------------------------------------------------------------
264 // Initialize driver details
266 #ifndef MXCFLASH_SELECT_MULTI
269 norflash_hwr_init(void)
275 CYGHWR_FLASH_AM29XXXXX_PLF_INIT();
279 // Look through table for device data
280 flash_dev_info = supported_devices;
281 for (i = 0; i < NUM_DEVICES; i++) {
282 if (!flash_dev_info->long_device_id && flash_dev_info->device_id == id[1])
284 else if ( flash_dev_info->long_device_id && flash_dev_info->device_id == id[1]
285 && flash_dev_info->device_id2 == id[2]
286 && flash_dev_info->device_id3 == id[3] )
291 // Did we find the device? If not, return error.
292 if (NUM_DEVICES == i)
293 return FLASH_ERR_DRV_WRONG_PART;
295 // Hard wired for now
296 flash_info.block_size = flash_dev_info->block_size;
297 flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
298 flash_info.start = (void *)CYGNUM_FLASH_BASE;
299 flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
303 //----------------------------------------------------------------------------
304 // Map a hardware status to a package error
306 #ifndef MXCFLASH_SELECT_MULTI
307 flash_hwr_map_error(int e)
309 norflash_hwr_map_error(int e)
316 //----------------------------------------------------------------------------
317 // See if a range of FLASH addresses overlaps currently running code
319 #ifndef MXCFLASH_SELECT_MULTI
320 flash_code_overlaps(void *start, void *end)
322 norflash_code_overlaps(void *start, void *end)
325 extern unsigned char _stext[], _etext[];
327 return ((((unsigned long)&_stext >= (unsigned long)start) &&
328 ((unsigned long)&_stext < (unsigned long)end)) ||
329 (((unsigned long)&_etext >= (unsigned long)start) &&
330 ((unsigned long)&_etext < (unsigned long)end)));
333 //----------------------------------------------------------------------------
337 #ifndef MXCFLASH_SELECT_MULTI
338 flash_erase_block(void* block, unsigned int size)
340 norflash_erase_block(void* block, unsigned int size)
343 volatile flash_data_t* ROM, *BANK;
344 volatile flash_data_t* b_p = (flash_data_t*) block;
345 volatile flash_data_t *b_v;
346 volatile flash_data_t *f_s0, *f_s1, *f_s2;
347 int timeout = CYGNUM_FLASH_TIMEOUT_QUERY;
349 int res = FLASH_ERR_OK;
351 cyg_bool bootblock = false;
352 cyg_uint32 *bootblocks = (cyg_uint32 *)0;
353 CYG_ADDRWORD bank_offset;
354 ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
355 BANK = find_bank(ROM, block, &bank_offset);
357 f_s0 = FLASH_P2V(BANK);
358 f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
359 f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
361 // Assume not "boot" sector, full size
363 len = flash_dev_info->block_size;
365 // Is this in a "boot" sector?
366 if (flash_dev_info->bootblock) {
367 bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0];
368 while (*bootblocks != _LAST_BOOTBLOCK) {
369 if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) {
370 len = *bootblocks++; // Size of first sub-block
374 int ls = flash_dev_info->block_size;
376 while ((ls -= *bootblocks++) > 0) ;
381 #define CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT
384 #ifndef CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT
385 // First check whether the block is protected
386 *f_s1 = FLASH_Setup_Code1;
387 *f_s2 = FLASH_Setup_Code2;
388 *f_s1 = FLASH_WP_State;
389 state = *FLASH_P2V(b_p+FLASH_WP_Addr);
392 if (FLASH_unlocked != state)
393 return FLASH_ERR_PROTECT;
396 b_v = FLASH_P2V(b_p);
398 // Send erase block command - six step sequence
399 *f_s1 = FLASH_Setup_Code1;
400 *f_s2 = FLASH_Setup_Code2;
401 *f_s1 = FLASH_Setup_Erase;
402 *f_s1 = FLASH_Setup_Code1;
403 *f_s2 = FLASH_Setup_Code2;
404 *b_v = FLASH_Block_Erase;
406 // Now poll for the completion of the sector erase timer (50us)
407 timeout = CYGNUM_FLASH_TIMEOUT_ERASE_TIMER; // how many retries?
410 if ((state & FLASH_Sector_Erase_Timer)
411 == FLASH_Sector_Erase_Timer) break;
413 if (--timeout == 0) {
414 res = FLASH_ERR_DRV_TIMEOUT;
419 // Then wait for erase completion.
420 if (FLASH_ERR_OK == res) {
421 timeout = CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE;
424 if (FLASH_BlankValue == state) {
428 // Don't check for FLASH_Err here since it will fail
429 // with devices in parallel because these may finish
430 // at different times.
432 if (--timeout == 0) {
433 res = FLASH_ERR_DRV_TIMEOUT;
439 if (FLASH_ERR_OK != res)
440 *FLASH_P2V(ROM) = FLASH_Reset;
442 size -= len; // This much has been erased
444 // Verify erase operation
446 b_v = FLASH_P2V(b_p++);
447 if (*b_v != FLASH_BlankValue) {
448 // Only update return value if erase operation was OK
449 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
463 //----------------------------------------------------------------------------
466 #ifndef MXCFLASH_SELECT_MULTI
467 flash_program_buf(void* addr, void* data, int len)
469 norflash_program_buf(void* addr, void* data, int len)
472 volatile flash_data_t* ROM;
473 volatile flash_data_t* BANK;
474 volatile flash_data_t* SECT=NULL;
475 volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;
476 volatile flash_data_t* addr_p = (flash_data_t*) addr;
477 volatile flash_data_t* addr_v = FLASH_P2V(addr_p);
478 volatile flash_data_t *f_s1, *f_s2;
479 CYG_ADDRWORD bank_offset;
481 int res = FLASH_ERR_OK;
482 const CYG_ADDRWORD mask =
483 flash_dev_info->bufsiz * sizeof (flash_data_t) - 1;
484 unsigned long rem_sect_size;
487 // check the address is suitably aligned
488 if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1))
489 return FLASH_ERR_INVALID;
491 // Base address of device(s) being programmed.
492 ROM = (volatile flash_data_t*)((unsigned long)addr_p & flash_dev_info->base_mask);
493 BANK = find_bank(ROM, addr, &bank_offset);
495 f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
496 f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
498 remain = len % sizeof (flash_data_t);
499 len /= sizeof (flash_data_t);
505 addr_v = FLASH_P2V(addr_p);
507 if (flash_dev_info->bufsiz > 1) {
508 // Assume buffer size is power of two
511 if (rem_sect_size == 0) {
512 SECT = find_sector(addr_v, &rem_sect_size);
513 rem_sect_size /= sizeof (flash_data_t);
516 // Compute word count to write
517 nwords = flash_dev_info->bufsiz
518 - (((CYG_ADDRWORD) addr_v & mask) / sizeof (flash_data_t));
522 // Initiate buffered write
523 *f_s1 = FLASH_Setup_Code1;
524 *f_s2 = FLASH_Setup_Code2;
525 *SECT = FLASH_Load_Buffer;
526 *SECT = FLASHWORD(nwords - 1); // All devices need to see this
528 // Load data into write buffer, flush buffer
529 for(i = 0; i < nwords; i++)
530 *addr_v++ = *data_ptr++;
531 --addr_v; --data_ptr;
532 *SECT = FLASH_Flush_Buffer;
533 rem_sect_size -= nwords;
535 // Program data [byte] - 4 step sequence
536 *f_s1 = FLASH_Setup_Code1;
537 *f_s2 = FLASH_Setup_Code2;
538 *f_s1 = FLASH_Program;
545 timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM;
548 if (*data_ptr == state) {
552 // Can't check for FLASH_Err since it'll fail in parallel
555 if (--timeout == 0) {
556 res = FLASH_ERR_DRV_TIMEOUT;
561 if (FLASH_ERR_OK != res)
562 *FLASH_P2V(ROM) = FLASH_Reset;
564 if (*addr_v != *data_ptr++) {
565 // Only update return value if erase operation was OK
566 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
572 // Program remaining bytes if len not a multiple of flash word size
573 if ((FLASH_ERR_OK == res) && remain)
575 // construct final word to be programmed with 0xff in the
577 flash_data_t final = (flash_data_t)-1;
578 unsigned char *src = (unsigned char *) data_ptr;
579 unsigned char *dst = (unsigned char *) &final;
584 addr_v = FLASH_P2V(addr_p);
586 // Program data [byte] - 4 step sequence
587 *f_s1 = FLASH_Setup_Code1;
588 *f_s2 = FLASH_Setup_Code2;
589 *f_s1 = FLASH_Program;
592 timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM;
594 flash_data_t state = *addr_v;
595 if (final == state) {
599 // Can't check for FLASH_Err since it'll fail in parallel
602 if (--timeout == 0) {
603 res = FLASH_ERR_DRV_TIMEOUT;
608 if (FLASH_ERR_OK != res)
609 *FLASH_P2V(ROM) = FLASH_Reset;
611 if (*addr_v != final) {
612 // Only update return value if write operation was OK
613 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
617 // Ideally, we'd want to return not only the failure code, but also
618 // the address/device that reported the error.
622 static volatile flash_data_t *
623 find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo)
625 volatile flash_data_t * res = base;
627 if (flash_dev_info->banked) {
629 *bo = (unsigned long)addr & ~(flash_dev_info->block_size-1);
630 *bo -= (unsigned long) base;
632 if (*bo >= flash_dev_info->banks[b]) {
633 res = (volatile flash_data_t*) ((unsigned long)base + flash_dev_info->banks[b]);
643 static flash_data_t *
644 find_sector(volatile flash_data_t * addr, unsigned long *remain_size)
646 const CYG_ADDRESS mask = flash_dev_info->block_size - 1;
647 const CYG_ADDRESS a = (CYG_ADDRESS) addr;
648 const CYG_ADDRESS base = a & flash_dev_info->base_mask;
649 CYG_ADDRESS res = a & ~mask;
651 *remain_size = flash_dev_info->block_size - (a & mask);
653 if (flash_dev_info->bootblock) {
654 cyg_uint32 * bootblocks = flash_dev_info->bootblocks;
655 while (*bootblocks != _LAST_BOOTBLOCK) {
656 if (*bootblocks++ == (res - base)) { /* Matching offset marker */
657 while (res + *bootblocks <= a) {
658 res += *bootblocks++;
660 *remain_size = *bootblocks - (a - res);
663 int ls = flash_dev_info->block_size;
665 while ((ls -= *bootblocks++) > 0) ;
670 return (flash_data_t *) res;
673 #endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL