1 #ifndef CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_INL
2 #define CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_INL
3 //==========================================================================
7 // Atmel AT49xxxx 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) 2003 Jonathan Larmour
15 // Copyright (C) 2003 Gary Thomas
17 // eCos is free software; you can redistribute it and/or modify it under
18 // the terms of the GNU General Public License as published by the Free
19 // Software Foundation; either version 2 or (at your option) any later version.
21 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
22 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 // You should have received a copy of the GNU General Public License along
27 // with eCos; if not, write to the Free Software Foundation, Inc.,
28 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
30 // As a special exception, if other files instantiate templates or use macros
31 // or inline functions from this file, or you compile this file and link it
32 // with other works to produce a work based on this file, this file does not
33 // by itself cause the resulting work to be covered by the GNU General Public
34 // License. However the source code for this file must still be made available
35 // in accordance with section (3) of the GNU General Public License.
37 // This exception does not invalidate any other reasons why a work based on
38 // this file might be covered by the GNU General Public License.
40 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
41 // at http://sources.redhat.com/ecos/ecos-license/
42 // -------------------------------------------
43 //####ECOSGPLCOPYRIGHTEND####
45 //==========================================================================
46 //#####DESCRIPTIONBEGIN####
48 // Author(s): Jani Monoses <jani@iv.ro>
49 // Contributors: Cristian Vlasin <cris@iv.ro>, tdrury, jlarmour
55 //####DESCRIPTIONEND####
57 //==========================================================================
59 #include <pkgconf/hal.h>
60 #include <pkgconf/devs_flash_atmel_at49xxxx.h>
61 #include <cyg/hal/hal_arch.h>
62 #include <cyg/hal/hal_cache.h>
63 #include <cyg/hal/hal_diag.h>
64 #include CYGHWR_MEMORY_LAYOUT_H
66 #define _FLASH_PRIVATE_
67 #include <cyg/io/flash.h>
70 //----------------------------------------------------------------------------
71 // Common device details.
72 #define FLASH_Read_ID FLASHWORD( 0x90 )
73 #define FLASH_Read_ID_Exit FLASHWORD( 0xF0 )
74 #define FLASH_Program FLASHWORD( 0xA0 )
75 #define FLASH_Sector_Erase FLASHWORD( 0x30 )
76 #define FLASH_Chip_Erase FLASHWORD( 0x10 )
78 #define FLASH_Busy FLASHWORD( 0x40 ) // "Toggle" bit, I/O 6
79 #define FLASH_InverseData FLASHWORD( 0x80 ) // I/O 7, Inverse data
81 #ifdef CYGHWR_DEVS_FLASH_ATMEL_AT49LV161
82 #define FLASH_Setup_Addr1 (0x555)
83 #define FLASH_Setup_Addr2 (0xAAA)
85 #define FLASH_Setup_Addr1 (0x5555)
86 #define FLASH_Setup_Addr2 (0x2AAA)
88 #define FLASH_Setup_Code1 FLASHWORD( 0xAA )
89 #define FLASH_Setup_Code2 FLASHWORD( 0x55 )
90 #define FLASH_Setup_Erase FLASHWORD( 0x80 )
92 #define CYGNUM_FLASH_BLANK (1)
94 #ifndef CYGNUM_FLASH_ID_MANUFACTURER
95 # define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0x1F)
98 //----------------------------------------------------------------------------
99 // Now that device properties are defined, include magic for defining
100 // accessor type and constants.
101 #include <cyg/io/flash_dev.h>
103 //----------------------------------------------------------------------------
104 // Information about supported devices
105 typedef struct flash_dev_info {
106 flash_data_t device_id;
107 #ifdef CYG_FLASH_LONG_DEVICE_NEEDED
108 cyg_bool long_device_id;
109 flash_data_t device_id2;
110 flash_data_t device_id3;
112 cyg_uint32 block_size;
113 cyg_int32 block_count;
114 cyg_uint32 base_mask;
115 cyg_uint32 device_size;
118 cyg_uint32 bootblocks[64]; // 0 is bootblock offset, 1-11 sub-sector sizes (or 0)
119 #ifdef NOTYET // FIXME: not supported yet (use am29xxxxx for template)
121 cyg_uint32 banks[8]; // bank offsets, highest to lowest (lowest should be 0)
122 // (only one entry for now, increase to support devices
127 static const flash_dev_info_t* flash_dev_info;
128 static const flash_dev_info_t supported_devices[] = {
129 #include <cyg/io/flash_at49xxxx_parts.inl>
131 #define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t))
133 //----------------------------------------------------------------------------
134 // Functions that put the flash device into non-read mode must reside
136 void flash_query(void* data) __attribute__ ((section (".2ram.flash_query")));
137 int flash_erase_block(void* block, unsigned int size)
138 __attribute__ ((section (".2ram.flash_erase_block")));
139 int flash_program_buf(void* addr, void* data, int len)
140 __attribute__ ((section (".2ram.flash_program_buf")));
141 static int wait_while_busy(int timeout, volatile flash_data_t* addr_ptr, flash_data_t value)
142 __attribute__ ((section (".2ram.text")));
144 //----------------------------------------------------------------------------
145 // Initialize driver details
152 #ifdef CYGHWR_FLASH_AT49XXXX_PLF_INIT
153 CYGHWR_FLASH_AT49XXXX_PLF_INIT();
158 // Check that flash_id data is matching the one the driver was
161 // Check manufacturer
162 if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER)
163 return FLASH_ERR_DRV_WRONG_PART;
165 // Look through table for device data
166 flash_dev_info = supported_devices;
167 #ifdef CYG_FLASH_LONG_DEVICE_NEEDED
168 for (i = 0; i < NUM_DEVICES; i++) {
169 if (!flash_dev_info->long_device_id && flash_dev_info->device_id == id[1])
171 else if ( flash_dev_info->long_device_id && flash_dev_info->device_id == id[1]
172 && flash_dev_info->device_id2 == id[2]
173 && flash_dev_info->device_id3 == id[3] )
178 for (i = 0; i < NUM_DEVICES; i++) {
179 if (flash_dev_info->device_id == id[1])
185 // Did we find the device? If not, return error.
186 if (NUM_DEVICES == i)
187 return FLASH_ERR_DRV_WRONG_PART;
189 // Hard wired for now
190 flash_info.block_size = flash_dev_info->block_size;
191 flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES;
192 flash_info.start = (void *)CYGNUM_FLASH_BASE;
193 flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES));
197 //----------------------------------------------------------------------------
198 // Map a hardware status to a package error
200 flash_hwr_map_error(int e)
206 //----------------------------------------------------------------------------
207 // See if a range of FLASH addresses overlaps currently running code
209 flash_code_overlaps(void *start, void *end)
211 extern unsigned char _stext[], _etext[];
213 return ((((unsigned long)&_stext >= (unsigned long)start) &&
214 ((unsigned long)&_stext < (unsigned long)end)) ||
215 (((unsigned long)&_etext >= (unsigned long)start) &&
216 ((unsigned long)&_etext < (unsigned long)end)));
219 //----------------------------------------------------------------------------
222 // Only reads the manufacturer and part number codes for the first
223 // device(s) in series. It is assumed that any devices in series
224 // will be of the same type.
227 flash_query(void* data)
229 volatile flash_data_t *ROM;
230 flash_data_t* id = (flash_data_t*) data;
232 ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE;
234 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
235 ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
236 ROM[FLASH_Setup_Addr1] = FLASH_Read_ID;
238 // FIXME: 10ms delay?
240 // Manufacturers' code
245 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
246 ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
247 ROM[FLASH_Setup_Addr1] = FLASH_Read_ID_Exit;
249 // FIXME: 10ms delay?
252 // Wait for completion. While programming/erasing check
253 // that i/o 7 is inverse of data as described in Atmels examples.
255 static int wait_while_busy(int timeout, volatile flash_data_t* addr_ptr, flash_data_t expected)
260 state = *addr_ptr & FLASH_InverseData;
261 if (state==(expected&FLASH_InverseData)) {
265 if (--timeout == 0) {
266 val=FLASH_ERR_DRV_TIMEOUT;
273 //----------------------------------------------------------------------------
276 flash_erase_block(void* block, unsigned int size)
278 volatile flash_data_t* ROM;
279 volatile flash_data_t* b_p = (volatile flash_data_t*) block;
281 int res = FLASH_ERR_OK;
282 unsigned int len = 0;
283 cyg_bool bootblock = false;
284 cyg_uint32 *bootblocks = (cyg_uint32 *)0;
286 // diag_printf("\nERASE: Block %p, size: %u\n",block,size);
288 // Base address of device(s) being programmed.
289 ROM = (volatile flash_data_t*) ((unsigned long)block & flash_dev_info->base_mask);
292 #if defined(CYGHWR_DEVS_FLASH_ATMEL_AT49XXXX_ERASE_BUG_WORKAROUND)
294 // Before erasing the data, overwrite it with all zeroes. This is a workaround
295 // for a silicon bug that affects erasing of some devices, see
296 // http://www.atmel.com/dyn/resources/prod_documents/doc6076.pdf.
297 for (len = size / sizeof *b_p; (FLASH_ERR_OK == res) && (len > 0); len--, b_p++) {
298 // Program data [byte] - 4 step sequence
299 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
300 ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
301 ROM[FLASH_Setup_Addr1] = FLASH_Program;
304 res = wait_while_busy(5000000, b_p, 0);
307 // Only update return value if operation was OK
308 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
311 if (FLASH_ERR_OK != res)
314 b_p = (volatile flash_data_t*) block;
316 #endif // defined(CYGHWR_DEVS_FLASH_ATMEL_AT49XXXX_ERASE_BUG_WORKAROUND)
318 // Assume not "boot" sector, full size
320 len = flash_dev_info->block_size;
322 // Is this in a "boot" sector?
323 if (flash_dev_info->bootblock) {
324 bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0];
325 while (*bootblocks != _LAST_BOOTBLOCK) {
326 if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) {
327 len = *bootblocks++; // Size of first sub-block
329 // diag_printf("\nERASE: Is Boot block - size: %d, ptr %p\n",len,b_p);
332 int ls = flash_dev_info->block_size;
334 while ((ls -= *bootblocks++) > 0) ;
340 //Erase sector 6-byte sequence
341 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
342 ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
343 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Erase;
344 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
345 ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
346 if (flash_dev_info->chip_erase) {
347 // Can only erase the entire device!
349 ROM[FLASH_Setup_Addr1] = FLASH_Chip_Erase;
351 res = FLASH_ERR_DRV_VERIFY;
354 *b_p = FLASH_Sector_Erase;
357 size -= len; // This much has been erased
359 res = wait_while_busy(66000000, b_p, FLASH_BlankValue);
361 // Verify erase operation
362 if (FLASH_ERR_OK == res) {
364 if (*b_p != FLASH_BlankValue) {
372 if (FLASH_ERR_OK != res)
377 // diag_printf("\nERASE: Is Boot block - size: %d, len %d, ptr %p\n",size,len,b_p);
383 //----------------------------------------------------------------------------
386 flash_program_buf(void* addr, void* data, int len)
388 volatile flash_data_t* ROM;
389 volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr;
390 volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;
391 int res = FLASH_ERR_OK;
393 // check the address is suitably aligned
394 if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1))
395 return FLASH_ERR_INVALID;
397 // Base address of device(s) being programmed.
398 ROM = (volatile flash_data_t*)((unsigned long)addr_ptr & flash_dev_info->base_mask);
400 while ((FLASH_ERR_OK == res) && (len > 0)) {
401 // Program data [byte] - 4 step sequence
402 ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1;
403 ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2;
404 ROM[FLASH_Setup_Addr1] = FLASH_Program;
405 addr_ptr[0] = data_ptr[0];
407 res = wait_while_busy(5000000,addr_ptr, data_ptr[0]);
409 if (*addr_ptr++ != *data_ptr++) {
410 // Only update return value if operation was OK
411 if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
415 len -= sizeof (*data_ptr);
421 #endif // CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_INL
423 // EOF flash_at49xxxx.inl