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 # define FLASH_Setup_Addr1 (0x555)
102 # define FLASH_Setup_Addr2 (0x2AA)
103 # define FLASH_VendorID_Addr (0)
104 # define FLASH_DeviceID_Addr (1)
105 # define FLASH_DeviceID_Addr2 (0x0e)
106 # define FLASH_DeviceID_Addr3 (0x0f)
107 # define FLASH_WP_Addr (2)
109 # define FLASH_Setup_Addr1 (0xAAA)
110 # define FLASH_Setup_Addr2 (0x555)
111 # define FLASH_VendorID_Addr (0)
112 # define FLASH_DeviceID_Addr (2)
113 # define FLASH_DeviceID_Addr2 (0x1c)
114 # define FLASH_DeviceID_Addr3 (0x1e)
115 # define FLASH_WP_Addr (4)
117 #define FLASH_Setup_Code1 FLASHWORD( 0xAA )
118 #define FLASH_Setup_Code2 FLASHWORD( 0x55 )
119 #define FLASH_Setup_Erase FLASHWORD( 0x80 )
121 // Platform code must define the below
122 // #define CYGNUM_FLASH_INTERLEAVE : Number of interleaved devices (in parallel)
123 // #define CYGNUM_FLASH_SERIES : Number of devices in series
124 // #define CYGNUM_FLASH_WIDTH : Width of devices on platform
125 // #define CYGNUM_FLASH_BASE : Address of first device
127 // Platform code may define some or all of the below, to provide
128 // timeouts appropriate to the target hardware. The timeout
129 // values depend partly on the flash part being used, partly
130 // on the target (including bus and cpu speeds).
131 #ifndef CYGNUM_FLASH_TIMEOUT_QUERY
132 # define CYGNUM_FLASH_TIMEOUT_QUERY 500000
134 #ifndef CYGNUM_FLASH_TIMEOUT_ERASE_TIMER
135 # define CYGNUM_FLASH_TIMEOUT_ERASE_TIMER 10000000
137 #ifndef CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE
138 # define CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE 10000000
140 #ifndef CYGNUM_FLASH_TIMEOUT_PROGRAM
141 # define CYGNUM_FLASH_TIMEOUT_PROGRAM 10000000
144 #define CYGNUM_FLASH_BLANK (1)
147 # define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_)))
149 #ifndef CYGHWR_FLASH_AM29XXXXX_PLF_INIT
150 # define CYGHWR_FLASH_AM29XXXXX_PLF_INIT()
153 //----------------------------------------------------------------------------
154 // Now that device properties are defined, include magic for defining
155 // accessor type and constants.
156 #include <cyg/io/flash_dev.h>
158 //----------------------------------------------------------------------------
159 // Information about supported devices
160 typedef struct flash_dev_info {
161 cyg_bool long_device_id;
162 flash_data_t device_id;
163 flash_data_t device_id2;
164 flash_data_t device_id3;
165 cyg_uint32 block_size;
166 cyg_int32 block_count;
167 cyg_uint32 base_mask;
168 cyg_uint32 device_size;
170 cyg_uint32 bootblocks[64]; // 0 is bootblock offset, 1-11 sub-sector sizes (or 0)
172 cyg_uint32 banks[16]; // bank offsets, highest to lowest (lowest should be 0)
173 // (only one entry for now, increase to support devices
175 cyg_uint32 bufsiz; // write buffer size in units of flash_data_t
178 static const flash_dev_info_t* flash_dev_info;
179 static const flash_dev_info_t supported_devices[] = {
180 #include <cyg/io/flash_am29xxxxx_parts.inl>
182 #define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
184 //----------------------------------------------------------------------------
185 // Functions that put the flash device into non-read mode must reside
187 #ifndef MXCFLASH_SELECT_MULTI
188 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
189 int flash_erase_block(void* block, unsigned int size)
190 __attribute__ ((section (".2ram.flash_erase_block")));
191 int flash_program_buf(void* addr, void* data, int len)
192 __attribute__ ((section (".2ram.flash_program_buf")));
194 //----------------------------------------------------------------------------
195 // Auxiliary functions
196 static volatile flash_data_t * find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo)
197 __attribute__ ((section (".2ram.find_bank")));
198 static flash_data_t * find_sector(volatile flash_data_t * addr, unsigned long *remain_size)
199 __attribute__ ((section (".2ram.find_sector")));
202 void norflash_query(void* data);
203 int norflash_erase_block(void* block, unsigned int size);
204 int norflash_program_buf(void* addr, void* data, int len);
206 //----------------------------------------------------------------------------
207 // Auxiliary functions
208 static volatile flash_data_t * find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo);
209 static flash_data_t * find_sector(volatile flash_data_t * addr, unsigned long *remain_size);
210 #endif //MXCFLASH_SELECT_MULTI
212 //----------------------------------------------------------------------------
215 // Only reads the manufacturer and part number codes for the first
216 // device(s) in series. It is assumed that any devices in series
217 // will be of the same type.
220 #ifndef MXCFLASH_SELECT_MULTI
221 flash_query(void* data)
223 norflash_query(void* data)
226 volatile flash_data_t *ROM;
227 volatile flash_data_t *f_s1, *f_s2;
228 flash_data_t* id = (flash_data_t*) data;
230 long timeout = CYGNUM_FLASH_TIMEOUT_QUERY;
232 ROM = (flash_data_t*) CYGNUM_FLASH_BASE;
233 f_s1 = FLASH_P2V(ROM+FLASH_Setup_Addr1);
234 f_s2 = FLASH_P2V(ROM+FLASH_Setup_Addr2);
237 w = *(FLASH_P2V(ROM));
239 *f_s1 = FLASH_Setup_Code1;
240 *f_s2 = FLASH_Setup_Code2;
241 *f_s1 = FLASH_Read_ID;
246 // Manufacturers' code
247 id[0] = *(FLASH_P2V(ROM+FLASH_VendorID_Addr));
249 id[1] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr));
250 id[2] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr2));
251 id[3] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr3));
254 *(FLASH_P2V(ROM)) = FLASH_Reset;
256 // Stall, waiting for flash to return to read mode.
257 while ((--timeout != 0) && (w != *(FLASH_P2V(ROM)))) ;
261 //----------------------------------------------------------------------------
262 // Initialize driver details
264 #ifndef MXCFLASH_SELECT_MULTI
267 norflash_hwr_init(void)
273 CYGHWR_FLASH_AM29XXXXX_PLF_INIT();
277 // Look through table for device data
278 flash_dev_info = supported_devices;
279 for (i = 0; i < NUM_DEVICES; i++) {
280 if (!flash_dev_info->long_device_id && flash_dev_info->device_id == id[1])
282 else if ( flash_dev_info->long_device_id && flash_dev_info->device_id == id[1]
283 && flash_dev_info->device_id2 == id[2]
284 && flash_dev_info->device_id3 == id[3] )
289 // Did we find the device? If not, return error.
290 if (NUM_DEVICES == i)
291 return FLASH_ERR_DRV_WRONG_PART;
293 // Hard wired for now
294 flash_info.block_size = flash_dev_info->block_size;
295 flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
296 flash_info.start = (void *)CYGNUM_FLASH_BASE;
297 flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
301 //----------------------------------------------------------------------------
302 // Map a hardware status to a package error
304 #ifndef MXCFLASH_SELECT_MULTI
305 flash_hwr_map_error(int e)
307 norflash_hwr_map_error(int e)
314 //----------------------------------------------------------------------------
315 // See if a range of FLASH addresses overlaps currently running code
317 #ifndef MXCFLASH_SELECT_MULTI
318 flash_code_overlaps(void *start, void *end)
320 norflash_code_overlaps(void *start, void *end)
323 extern unsigned char _stext[], _etext[];
325 return ((((unsigned long)&_stext >= (unsigned long)start) &&
326 ((unsigned long)&_stext < (unsigned long)end)) ||
327 (((unsigned long)&_etext >= (unsigned long)start) &&
328 ((unsigned long)&_etext < (unsigned long)end)));
331 //----------------------------------------------------------------------------
335 #ifndef MXCFLASH_SELECT_MULTI
336 flash_erase_block(void* block, unsigned int size)
338 norflash_erase_block(void* block, unsigned int size)
341 volatile flash_data_t* ROM, *BANK;
342 volatile flash_data_t* b_p = (flash_data_t*) block;
343 volatile flash_data_t *b_v;
344 volatile flash_data_t *f_s0, *f_s1, *f_s2;
345 int timeout = CYGNUM_FLASH_TIMEOUT_QUERY;
347 int res = FLASH_ERR_OK;
349 cyg_bool bootblock = false;
350 cyg_uint32 *bootblocks = (cyg_uint32 *)0;
351 CYG_ADDRWORD bank_offset;
352 ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);
353 BANK = find_bank(ROM, block, &bank_offset);
355 f_s0 = FLASH_P2V(BANK);
356 f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
357 f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
359 // Assume not "boot" sector, full size
361 len = flash_dev_info->block_size;
363 // Is this in a "boot" sector?
364 if (flash_dev_info->bootblock) {
365 bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0];
366 while (*bootblocks != _LAST_BOOTBLOCK) {
367 if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) {
368 len = *bootblocks++; // Size of first sub-block
372 int ls = flash_dev_info->block_size;
374 while ((ls -= *bootblocks++) > 0) ;
379 #define CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT
382 #ifndef CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT
383 // First check whether the block is protected
384 *f_s1 = FLASH_Setup_Code1;
385 *f_s2 = FLASH_Setup_Code2;
386 *f_s1 = FLASH_WP_State;
387 state = *FLASH_P2V(b_p+FLASH_WP_Addr);
390 if (FLASH_unlocked != state)
391 return FLASH_ERR_PROTECT;
394 b_v = FLASH_P2V(b_p);
396 // Send erase block command - six step sequence
397 *f_s1 = FLASH_Setup_Code1;
398 *f_s2 = FLASH_Setup_Code2;
399 *f_s1 = FLASH_Setup_Erase;
400 *f_s1 = FLASH_Setup_Code1;
401 *f_s2 = FLASH_Setup_Code2;
402 *b_v = FLASH_Block_Erase;
404 // Now poll for the completion of the sector erase timer (50us)
405 timeout = CYGNUM_FLASH_TIMEOUT_ERASE_TIMER; // how many retries?
408 if ((state & FLASH_Sector_Erase_Timer)
409 == FLASH_Sector_Erase_Timer) break;
411 if (--timeout == 0) {
412 res = FLASH_ERR_DRV_TIMEOUT;
417 // Then wait for erase completion.
418 if (FLASH_ERR_OK == res) {
419 timeout = CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE;
422 if (FLASH_BlankValue == state) {
426 // Don't check for FLASH_Err here since it will fail
427 // with devices in parallel because these may finish
428 // at different times.
430 if (--timeout == 0) {
431 res = FLASH_ERR_DRV_TIMEOUT;
437 if (FLASH_ERR_OK != res)
438 *FLASH_P2V(ROM) = FLASH_Reset;
440 size -= len; // This much has been erased
442 // Verify erase operation
444 b_v = FLASH_P2V(b_p++);
445 if (*b_v != FLASH_BlankValue) {
446 // Only update return value if erase operation was OK
447 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
461 //----------------------------------------------------------------------------
464 #ifndef MXCFLASH_SELECT_MULTI
465 flash_program_buf(void* addr, void* data, int len)
467 norflash_program_buf(void* addr, void* data, int len)
470 volatile flash_data_t* ROM;
471 volatile flash_data_t* BANK;
472 volatile flash_data_t* SECT=NULL;
473 volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;
474 volatile flash_data_t* addr_p = (flash_data_t*) addr;
475 volatile flash_data_t* addr_v = FLASH_P2V(addr_p);
476 volatile flash_data_t *f_s1, *f_s2;
477 CYG_ADDRWORD bank_offset;
479 int res = FLASH_ERR_OK;
480 const CYG_ADDRWORD mask =
481 flash_dev_info->bufsiz * sizeof (flash_data_t) - 1;
482 unsigned long rem_sect_size;
484 // check the address is suitably aligned
485 if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1))
486 return FLASH_ERR_INVALID;
488 // Base address of device(s) being programmed.
489 ROM = (volatile flash_data_t*)((unsigned long)addr_p & flash_dev_info->base_mask);
490 BANK = find_bank(ROM, addr, &bank_offset);
492 f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
493 f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
495 len /= sizeof (flash_data_t);
501 addr_v = FLASH_P2V(addr_p);
503 if (flash_dev_info->bufsiz > 1) {
504 // Assume buffer size is power of two
507 if (rem_sect_size == 0) {
508 SECT = find_sector(addr_v, &rem_sect_size);
509 rem_sect_size /= sizeof (flash_data_t);
512 // Compute word count to write
513 nwords = flash_dev_info->bufsiz
514 - (((CYG_ADDRWORD) addr_v & mask) / sizeof (flash_data_t));
518 // Initiate buffered write
519 *f_s1 = FLASH_Setup_Code1;
520 *f_s2 = FLASH_Setup_Code2;
521 *SECT = FLASH_Load_Buffer;
522 *SECT = FLASHWORD(nwords - 1); // All devices need to see this
524 // Load data into write buffer, flush buffer
525 for(i = 0; i < nwords; i++)
526 *addr_v++ = *data_ptr++;
527 --addr_v; --data_ptr;
528 *SECT = FLASH_Flush_Buffer;
529 rem_sect_size -= nwords;
531 // Program data [byte] - 4 step sequence
532 *f_s1 = FLASH_Setup_Code1;
533 *f_s2 = FLASH_Setup_Code2;
534 *f_s1 = FLASH_Program;
541 timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM;
544 if (*data_ptr == state) {
548 // Can't check for FLASH_Err since it'll fail in parallel
551 if (--timeout == 0) {
552 res = FLASH_ERR_DRV_TIMEOUT;
557 if (FLASH_ERR_OK != res)
558 *FLASH_P2V(ROM) = FLASH_Reset;
560 if (*addr_v != *data_ptr++) {
561 // Only update return value if erase operation was OK
562 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
568 // Ideally, we'd want to return not only the failure code, but also
569 // the address/device that reported the error.
573 static volatile flash_data_t *
574 find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo)
576 volatile flash_data_t * res = base;
578 if (flash_dev_info->banked) {
580 *bo = (unsigned long)addr & ~(flash_dev_info->block_size-1);
581 *bo -= (unsigned long) base;
583 if (*bo >= flash_dev_info->banks[b]) {
584 res = (volatile flash_data_t*) ((unsigned long)base + flash_dev_info->banks[b]);
594 static flash_data_t *
595 find_sector(volatile flash_data_t * addr, unsigned long *remain_size)
597 const CYG_ADDRESS mask = flash_dev_info->block_size - 1;
598 const CYG_ADDRESS a = (CYG_ADDRESS) addr;
599 const CYG_ADDRESS base = a & flash_dev_info->base_mask;
600 CYG_ADDRESS res = a & ~mask;
602 *remain_size = flash_dev_info->block_size - (a & mask);
604 if (flash_dev_info->bootblock) {
605 cyg_uint32 * bootblocks = flash_dev_info->bootblocks;
606 while (*bootblocks != _LAST_BOOTBLOCK) {
607 int ls = flash_dev_info->block_size;
609 if (*bootblocks++ == (res - base)) {
610 while (res + *bootblocks < a) {
611 res += *bootblocks++;
615 while ((ls -= *bootblocks++) > 0) ;
619 if (*bootblocks != _LAST_BOOTBLOCK)
620 *remain_size = *bootblocks - (a - res);
623 return (flash_data_t *) res;
626 #endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL