Mercurial > nand-ecoscentric
changeset 1108:d67e080dcd49
* include/flash_at49xxxx.inl: Reorganise to support boot blocks,
multiple flash types from the same driver, and do proper
verification.
* include/flash_at49xxxx_parts.inl: New file to describe flash
part information.
| author | jlarmour |
|---|---|
| date | Tue, 15 Jul 2003 01:52:21 +0000 |
| parents | b7ec9459b80d |
| children | 765b70faae43 |
| files | packages/devs/flash/atmel/at49xxxx/current/ChangeLog packages/devs/flash/atmel/at49xxxx/current/include/flash_at49xxxx.inl packages/devs/flash/atmel/at49xxxx/current/include/flash_at49xxxx_parts.inl |
| diffstat | 3 files changed, 321 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/devs/flash/atmel/at49xxxx/current/ChangeLog +++ b/packages/devs/flash/atmel/at49xxxx/current/ChangeLog @@ -1,3 +1,11 @@ +2003-07-15 Jonathan Larmour <jifl@eCosCentric.com> + + * include/flash_at49xxxx.inl: Reorganise to support boot blocks, + multiple flash types from the same driver, and do proper + verification. + * include/flash_at49xxxx_parts.inl: New file to describe flash + part information. + 2003-06-10 Øyvind Harboe <oyvind.harboe@zylin.com> * include/flash_at49xxxx.inl: wait_while_busy needs to be in RAM
--- a/packages/devs/flash/atmel/at49xxxx/current/include/flash_at49xxxx.inl +++ b/packages/devs/flash/atmel/at49xxxx/current/include/flash_at49xxxx.inl @@ -11,6 +11,7 @@ // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003 Jonathan Larmour // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -44,7 +45,7 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): Jani Monoses <jani@iv.ro> -// Contributors: Cristian Vlasin <cris@iv.ro>, tdrury +// Contributors: Cristian Vlasin <cris@iv.ro>, tdrury, jlarmour // Date: 2002-06-24 // Purpose: // Description: @@ -77,39 +78,11 @@ #define FLASH_Setup_Code2 FLASHWORD( 0x55 ) #define FLASH_Setup_Erase FLASHWORD( 0x80 ) -// Platform code must define the below -// #define CYGNUM_FLASH_INTERLEAVE : Number of interleaved devices (in parallel) -// #define CYGNUM_FLASH_SERIES : Number of devices in series -// #define CYGNUM_FLASH_BASE : Address of first device -// And select one of the below device variants +#define CYGNUM_FLASH_BLANK (1) -#ifdef CYGPKG_DEVS_FLASH_ATMEL_AT49LV8011 -# define FLASH_BLOCK_SIZE (0x10000*CYGNUM_FLASH_INTERLEAVE) -# define FLASH_NUM_REGIONS (14) -# define CYGNUM_FLASH_WIDTH (16) -# define CYGNUM_FLASH_BLANK (1) -# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0x1F) -# define CYGNUM_FLASH_ID_DEVICE FLASHWORD(0xCB) +#ifndef CYGNUM_FLASH_ID_MANUFACTURER +# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0x1F) #endif -#ifdef CYGPKG_DEVS_FLASH_ATMEL_AT49LV8011T -# define FLASH_BLOCK_SIZE (0x10000*CYGNUM_FLASH_INTERLEAVE) -# define FLASH_NUM_REGIONS (14) -# define CYGNUM_FLASH_WIDTH (16) -# define CYGNUM_FLASH_BLANK (1) -# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0x1F) -# define CYGNUM_FLASH_ID_DEVICE FLASHWORD(0x4A) -#endif -#ifdef CYGPKG_DEVS_FLASH_ATMEL_AT49LV1614 -// NOTE: the smaller plane A of the flash is ignored for now (tdrury) -# define FLASH_BLOCK_SIZE (0x10000*CYGNUM_FLASH_INTERLEAVE) -# define FLASH_NUM_REGIONS (31) -# define CYGNUM_FLASH_WIDTH (16) -# define CYGNUM_FLASH_BLANK (1) -# define CYGNUM_FLASH_ID_MANUFACTURER FLASHWORD(0x1F) -# define CYGNUM_FLASH_ID_DEVICE FLASHWORD(0xC0) -#endif - -#define FLASH_DEVICE_SIZE (FLASH_BLOCK_SIZE*FLASH_NUM_REGIONS) //---------------------------------------------------------------------------- // Now that device properties are defined, include magic for defining @@ -117,6 +90,35 @@ #include <cyg/io/flash_dev.h> //---------------------------------------------------------------------------- +// Information about supported devices +typedef struct flash_dev_info { + flash_data_t device_id; +#ifdef CYG_FLASH_LONG_DEVICE_NEEDED + cyg_bool long_device_id; + flash_data_t device_id2; + flash_data_t device_id3; +#endif + cyg_uint32 block_size; + cyg_int32 block_count; + cyg_uint32 base_mask; + cyg_uint32 device_size; + cyg_bool bootblock; + cyg_uint32 bootblocks[64]; // 0 is bootblock offset, 1-11 sub-sector sizes (or 0) +#ifdef NOTYET // FIXME: not supported yet (use am29xxxxx for template) + cyg_bool banked; + cyg_uint32 banks[8]; // bank offsets, highest to lowest (lowest should be 0) + // (only one entry for now, increase to support devices + // with more banks). +#endif +} flash_dev_info_t; + +static const flash_dev_info_t* flash_dev_info; +static const flash_dev_info_t supported_devices[] = { +#include <cyg/io/flash_at49xxxx_parts.inl> +}; +#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t)) + +//---------------------------------------------------------------------------- // Functions that put the flash device into non-read mode must reside // in RAM. void flash_query(void* data) __attribute__ ((section (".2ram.flash_query"))); @@ -132,21 +134,51 @@ static int wait_while_busy(int timeout, int flash_hwr_init(void) { - flash_data_t id[2]; + flash_data_t id[4]; + int i; + +#ifdef CYGHWR_FLASH_AT49XXXX_PLF_INIT + CYGHWR_FLASH_AT49XXXX_PLF_INIT(); +#endif flash_dev_query(id); // Check that flash_id data is matching the one the driver was // configured for. - if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER - || id[1] != CYGNUM_FLASH_ID_DEVICE) + + // Check manufacturer + if (id[0] != CYGNUM_FLASH_ID_MANUFACTURER) + return FLASH_ERR_DRV_WRONG_PART; + + // Look through table for device data + flash_dev_info = supported_devices; +#ifdef CYG_FLASH_LONG_DEVICE_NEEDED + for (i = 0; i < NUM_DEVICES; i++) { + if (!flash_dev_info->long_device_id && flash_dev_info->device_id == id[1]) + break; + else if ( flash_dev_info->long_device_id && flash_dev_info->device_id == id[1] + && flash_dev_info->device_id2 == id[2] + && flash_dev_info->device_id3 == id[3] ) + break; + flash_dev_info++; + } +#else + for (i = 0; i < NUM_DEVICES; i++) { + if (flash_dev_info->device_id == id[1]) + break; + flash_dev_info++; + } +#endif + + // Did we find the device? If not, return error. + if (NUM_DEVICES == i) return FLASH_ERR_DRV_WRONG_PART; // Hard wired for now - flash_info.block_size = FLASH_BLOCK_SIZE; - flash_info.blocks = FLASH_NUM_REGIONS; + flash_info.block_size = flash_dev_info->block_size; + flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES; flash_info.start = (void *)CYGNUM_FLASH_BASE; - flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (FLASH_NUM_REGIONS * FLASH_BLOCK_SIZE * CYGNUM_FLASH_SERIES)); + flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES)); return FLASH_ERR_OK; } @@ -184,7 +216,6 @@ flash_query(void* data) { volatile flash_data_t *ROM; flash_data_t* id = (flash_data_t*) data; - int i; ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE; @@ -226,43 +257,76 @@ static int wait_while_busy(int timeout, //---------------------------------------------------------------------------- // Erase Block int -flash_erase_block(void* block, unsigned int len) +flash_erase_block(void* block, unsigned int size) { - volatile flash_data_t* ROM; - volatile flash_data_t* addr_ptr = (volatile flash_data_t*) block; + volatile flash_data_t* ROM; + volatile flash_data_t* b_p = (volatile flash_data_t*) block; - int res = FLASH_ERR_OK; - int i; - - flash_data_t state, prev_state; + int res = FLASH_ERR_OK; + int len = 0; + cyg_bool bootblock = false; + cyg_uint32 *bootblocks = (cyg_uint32 *)0; -// diag_printf("\nERASE: Block %p, len: %u\n",addr_ptr,len); + // diag_printf("\nERASE: Block %p, size: %u\n",block,size); - // Base address of device(s) being programmed. - ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE; + // Base address of device(s) being programmed. + ROM = (volatile flash_data_t*) ((unsigned long)block & flash_dev_info->base_mask); - //Erase sector 6-byte sequence + // Assume not "boot" sector, full size + bootblock = false; + len = flash_dev_info->block_size; + + // Is this in a "boot" sector? + if (flash_dev_info->bootblock) { + bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0]; + while (*bootblocks != _LAST_BOOTBLOCK) { + if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) { + len = *bootblocks++; // Size of first sub-block + bootblock = true; + // diag_printf("\nERASE: Is Boot block - size: %d, ptr %p\n",len,b_p); + break; + } else { + int ls = flash_dev_info->block_size; + // Skip over segment + while ((ls -= *bootblocks++) > 0) ; + } + } + } + + while (size > 0) { + //Erase sector 6-byte sequence ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; ROM[FLASH_Setup_Addr1] = FLASH_Setup_Erase; ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; - addr_ptr[0] = FLASH_Sector_Erase; + *b_p = FLASH_Sector_Erase; + + res = wait_while_busy(5000000,b_p); + + size -= len; // This much has been erased - res = wait_while_busy(5000000,addr_ptr); -#if 0 - // Verify loaded data bytes - for (i = 0; i < len;) { - if (*addr_ptr != FLASH_BlankValue) { - // Only update return value if erase operation was OK - if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; - break; - } - addr_ptr++; - i += sizeof(*addr_ptr); + // Verify erase operation + if (FLASH_ERR_OK == res) { + while (len > 0) { + if (*b_p != FLASH_BlankValue) { + // Only update return value if erase operation was OK + res = FLASH_ERR_DRV_VERIFY; + } + len -= sizeof(*b_p); + b_p++; + } } -#endif + + if (FLASH_ERR_OK != res) + break; + + if (bootblock) { + len = *bootblocks++; + // diag_printf("\nERASE: Is Boot block - size: %d, len %d, ptr %p\n",size,len,b_p); + } + } return res; } @@ -271,49 +335,39 @@ flash_erase_block(void* block, unsigned int flash_program_buf(void* addr, void* data, int len) { - volatile flash_data_t* ROM; - volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr; - volatile flash_data_t* data_ptr = (volatile flash_data_t*) data; - - int res = FLASH_ERR_OK; + volatile flash_data_t* ROM; + volatile flash_data_t* addr_ptr = (volatile flash_data_t*) addr; + volatile flash_data_t* data_ptr = (volatile flash_data_t*) data; + int res = FLASH_ERR_OK; - // Base address of device(s) being programmed. - ROM = (volatile flash_data_t*) CYGNUM_FLASH_BASE; + // check the address is suitably aligned + if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1)) + return FLASH_ERR_INVALID; - while ((FLASH_ERR_OK == res) && (len > 0)) { - // Program data [byte] - 4 step sequence - ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; - ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; - ROM[FLASH_Setup_Addr1] = FLASH_Program; - addr_ptr[0] = data_ptr[0]; + // Base address of device(s) being programmed. + ROM = (volatile flash_data_t*)((unsigned long)addr_ptr & flash_dev_info->base_mask); - addr_ptr++; - data_ptr++; - - //if (*data_ptr++ == 0) - // *addr_ptr = 0; - - len -= sizeof (flash_data_t); + while ((FLASH_ERR_OK == res) && (len > 0)) { + // Program data [byte] - 4 step sequence + ROM[FLASH_Setup_Addr1] = FLASH_Setup_Code1; + ROM[FLASH_Setup_Addr2] = FLASH_Setup_Code2; + ROM[FLASH_Setup_Addr1] = FLASH_Program; + addr_ptr[0] = data_ptr[0]; + + res = wait_while_busy(5000000,addr_ptr); - res = wait_while_busy(5000000,addr_ptr); -// if (res==FLASH_ERR_DRV_TIMEOUT) break; - - } -#if 0 - // Verify loaded data bytes - for (i = 0; (i<len);) { - if (*addr_ptr != *data_ptr) { - // Only update return value if erase operation was OK - if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; - break; - } - addr_ptr++; - data_ptr++; - i += sizeof(*data_ptr); + if (*addr_ptr++ != *data_ptr++) { + // Only update return value if operation was OK + if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; + break; } -#endif + + len -= sizeof (*data_ptr); + } return res; } #endif // CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_INL + +// EOF flash_at49xxxx.inl
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/atmel/at49xxxx/current/include/flash_at49xxxx_parts.inl @@ -0,0 +1,160 @@ +#ifndef CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_PARTS_INL +#define CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_PARTS_INL +//========================================================================== +// +// at49xxxx_parts.inl +// +// Atmel AT49xxxx series part descriptions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003 Jonathan Larmour +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### + +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour,Jani Monoses <jani@iv.ro> +// Contributors: Jani Monoses <jani@iv.ro>, Cristian Vlasin <cris@iv.ro>, tdrury +// Date: 2003-07-14 +// Purpose: Should be included from the flash_at49xxxx.inl file only. +// Description: Atmel AT49xxxx part descriptions +// +// FIXME: Add configury for selecting bottom/top bootblocks +//####DESCRIPTIONEND#### +// +//========================================================================== + +// +// Note: 'bootblocks' are a set of blocks which are treated by +// the driver as a single larger block. This simplifies the driver +// so as to only have to deal with single size blocks (even though +// the physical device may differ). The data structure is laid out as: +// <address of start of boot block area 1> +// <size of sub-block 1> +// <size of sub-block 2> +// ... +// <size of sub-block n> +// <address of start of boot block area 2> +// <size of sub-block 1> +// <size of sub-block 2> +// ... +// <size of sub-block n> +// _LAST_BOOTBLOCK +// +// Finally, when specifying a device with bootblocks, the total number +// of blocks should reflect this collapse, i.e. if the device has 15 +// full size blocks and 8 blocks which are 1/8 each, then the total +// should be 16 blocks. + +#define _LAST_BOOTBLOCK (-1) + +// Platform code must define the below +// #define CYGNUM_FLASH_INTERLEAVE : Number of interleaved devices (in parallel) +// #define CYGNUM_FLASH_SERIES : Number of devices in series +// #define CYGNUM_FLASH_WIDTH : Width of devices on platform +// #define CYGNUM_FLASH_BASE : Address of first device +// And select one of the below device variants + +#if defined(CYGHWR_DEVS_FLASH_ATMEL_AT49LV8011) || \ + defined(CYGHWR_DEVS_FLASH_ATMEL_AT49BV8011) + { // AT49BV/LV8011 + // the following ID is true for both 8 and 16 bit CYGNUM_FLASH_WIDTH + device_id : FLASHWORD(0xCB), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + } + }, +#endif +#if defined(CYGHWR_DEVS_FLASH_ATMEL_AT49LV8011T) || \ + defined(CYGHWR_DEVS_FLASH_ATMEL_AT49BV8011T) + { // AT49BV/LV8011 + // the following ID is true for both 8 and 16 bit CYGNUM_FLASH_WIDTH + device_id : FLASHWORD(0x4A), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x0E0000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + } + }, +#endif +#if defined(CYGHWR_DEVS_FLASH_ATMEL_AT49BV1604A) || \ + defined(CYGHWR_DEVS_FLASH_ATMEL_AT49BV1614A) || \ + defined(CYGHWR_DEVS_FLASH_ATMEL_AT49LV1614A) + { // AT49BV/LV8011 + // the following ID is true for both 8 and 16 bit CYGNUM_FLASH_WIDTH + device_id : FLASHWORD(0xC0), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 32, + device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + } + }, +#endif + +#endif // ifndef CYGONCE_DEVS_FLASH_ATMEL_AT49XXXX_PARTS_INL + +// EOF flash_at49xxxx_parts.inl
