📄 flash.c
字号:
/* ############################################################################ (c) Copyright Virata Limited 2001## Virata Limited Confidential and Proprietary## The following software source code ("Software") is strictly confidential and# is proprietary to Virata Limited ("Virata"). It may only be read, used,# copied, adapted, modified or otherwise dealt with by you if you have# entered into a confidentiality agreement with Virata and then subject to the# terms of that confidentiality agreement and any other applicable agreement# between you and Virata. If you are in any doubt as to whether you are# entitled to access, read, use, copy, adapt, modify or otherwise deal with# the Software or whether you are entitled to disclose the Software to any# other person you should contact Virata. If you have not entered into a# confidentiality agreement with Virata granting access to this Software you# should forthwith return all media, copies and printed listings containing# the Software to Virata.## Virata reserves the right to take legal action against you should you breach# the above provisions.## If you are unsure, or to report violations, please contact# support@virata.com# ##########################################################################*//*********************************************************************** * * * ATMOS Flash Filing System support code * * * * FLASH.C * * * ***********************************************************************//*** To add a new FLASH device...**** 1. Define an ID.** 2. Add an entry to the flash type table.** 3. Write sector, byte and erase routines as required (many chips** can actually use the same one).** 4. Update read_chip_id_info () to handle the new chip, particularly** with respect to sector protection.***//*** Notes about the FLASH_AMD_NO_SWAP macro**** Some reference designs need to share GPIO lines between the flash and** other system components. (An example is the RD6400.) Thus we may need to** ensure that all flash reads/writes are atomic in nature, especially if ** the other system components in question are used very often. For AMD** flash parts, defining the FLASH_AMD_NO_SWAP macro in the hardware file** allows this to happen (by lengthening the FIQ critical section as ** necessary). **** DEVELOPER BEWARE:** The design choice implied by this change should only be used IF tying** up the system for flash reads/writes is acceptable (e.g. only occurring at** start-of-day and/or during flashfs updates/rewrites). **** Note: we may wish to consider changing this macro to FLASH_NO_SWAP,** if another design using non-AMD parts finds this tactic useful. Note** that .hw files defining this macro would also need to be changed.*/#include <stdlib.h>#include <string.h>#include <atypes.h>#include <rom.h>#include <assert.h>#if !defined (BOOT_ROM) || !defined (NO_CONFIGINFO_FLASH)#include <timelib.h>#endif#include "config.h"#include "flash.h"#include "stdio.h"/*====================================================================*//* Type and macro definitions *//*====================================================================*//*** Some systems have windowed flash where a large FLASH device is accessed through** a series of smaller windows. (1 << FLASH_WINDOW_BITS) defines the size of the** window in bytes.**** All FLASH devices are assumed to be accessed through the *same* window which** is assumed to be the same size. Windowed access is slower than direct access.*//*The following should be defined as necessary when using windowed flash:FLASH_WINDOW_BITS - Number of bits in window (ie 1Mb => 20 bits)FLASH_WINDOW_SELECT_REGISTER - Address of window select registerFLASH_WINDOW_REGISTER_OFFSET - Offset of window select bits in registerFLASH_WINDOW_REGISTER_SHARED - Define if register is shared (ie only some of the bits are for the flash select and other bits are for other functions. If dedictated register don't define this.FLASH_WINDOW_REGISTER_BITS - Number of bits in register used to select windowFLASH_WINDOW_REGISTER_SIZE - Size (type) of window register (BYTE, WORD, etc) FLASH_COMBINED_PAGE_WINDOW_REGISTER - A combined window/select register (that is write-only)*/#ifdef FLASH_WINDOW_BITS#define WINDOWED_FLASH 1/*** Just check that it *is* possible to select a flash window.*/#ifndef FLASH_WINDOW_SELECT_REGISTER#error "No register defined for selection of the flash window but windowed flash required."#endif/* If size not specified assume the window register has size 1 byte */#ifndef FLASH_WINDOW_REGISTER_SIZE #define FLASH_WINDOW_REGISTER_SIZE BYTE#endif/* Check to see if bit-offset in register is specified */ #ifndef FLASH_WINDOW_REGISTER_OFFSET #define FLASH_WINDOW_REGISTER_OFFSET 0#endif/* Use number of bits and bit offset to define bit mask for window register */#ifdef FLASH_WINDOW_REGISTER_BITS #define FLASH_WINDOW_REGISTER_MASK (((1 << FLASH_WINDOW_REGISTER_BITS) -1) << FLASH_WINDOW_REGISTER_OFFSET)#else #ifdef FLASH_WINDOW_REGISTER_SHARED #error "No flash window register bits specified, using default mask" #endif #define FLASH_WINDOW_REGISTER_MASK 0xffffffff#endif#if defined (FLASH_WINDOW_REGISTER_SHARED) && defined (FLASH_COMBINED_PAGE_WINDOW_REGISTER)#error "Read/write combined window/page register unsupported"#endif#define FLASH_WINDOW_SIZE (1 << FLASH_WINDOW_BITS)#define FLASH_WINDOW_MASK (FLASH_WINDOW_SIZE - 1)/* If the window register is shared we must perform a read/modify/write operation. in this case we call a function due to complexity of critical sections etc. If the register is not shared we will use a macro for speed */#if defined (FLASH_WINDOW_REGISTER_SHARED) #define FLASH_WINDOW_SELECT(addr) flash_window_select(addr) #elif defined (FLASH_COMBINED_PAGE_WINDOW_REGISTER) #define FLASH_WINDOW_SELECT(addr) (* (FLASH_WINDOW_REGISTER_SIZE *) FLASH_WINDOW_SELECT_REGISTER = \ pageRegister | \ ((addr) >> (FLASH_WINDOW_BITS - FLASH_WINDOW_REGISTER_OFFSET) & \ FLASH_WINDOW_REGISTER_MASK) )#else #define FLASH_WINDOW_SELECT(addr) (* (FLASH_WINDOW_REGISTER_SIZE *) FLASH_WINDOW_SELECT_REGISTER = \ ((addr) >> (FLASH_WINDOW_BITS - FLASH_WINDOW_REGISTER_OFFSET) & \ FLASH_WINDOW_REGISTER_MASK) )#endif#endif/* ID's read from the supported FLASH chips in the system */#define UNKNOWN_CHIP_ID (0xffff) /* Anything but one of the following */#define AT29C040_CHIP_ID (0x1f5b)#define AT29C040A_CHIP_ID (0x1fa4)#define AT29C1024_CHIP_ID (0x1f25)#define AT49BV1614_CHIP_ID (0x1fc0)#define AT49BV1614T_CHIP_ID (0x1fc2)#define AM29F040_CHIP_ID (0x01a4)#define AM29LV081B_CHIP_ID (0x0138)#define AM29LV040B_CHIP_ID (0x014F)#define AM29LV017B_CHIP_ID (0x01c8)#define AM29LV116BB_CHIP_ID (0x014c)#define AM29LV116BT_CHIP_ID (0x01c7)#define AM29LV800BB_CHIP_ID (0x015b)#define AM29LV800BT_CHIP_ID (0x01da)#define AM29LV160BB_CHIP_ID (0x0149)#define AM29LV160BT_CHIP_ID (0x01c4)#define MT28F008B3B_CHIP_ID (0x8999)#define MT28F008B3T_CHIP_ID (0x8998)#define INT28F800B5B_CHIP_ID (0x899d)#define INT28F320J5_CHIP_ID (0x8914)#define W29C040_CHIP_ID (0xda46)#define MX29L1611B_CHIP_ID (0xc2f8)#define M29W008T_CHIP_ID (0x20D2)#define M29W008B_CHIP_ID (0x20DC)#define M29W040B_CHIP_ID (0x20E3)#define M29W800AT_CHIP_ID (0x20D7)#define M29W800AB_CHIP_ID (0x205B)#define BM29F040_CHIP_ID (0xAD40) #define MX29F040_CHIP_ID (0xC2A4) #define EN29F040_CHIP_ID (0x7F7F) #define AC29F040_CHIP_ID (0x3786) #define MX29F800B_CHIP_ID (0xC258) #define SST39VF080Q_CHIP_ID (0xBFD8) #define SST39VF016Q_CHIP_ID (0xBFD9) #define SST28SF040A_CHIP_ID (0xBF04) #define LH28F160BVE_CHIP_ID (0xb049)/* 'tuning' variables used in loops to cause the Atmos kernel to schedule *//* other runnable proccesses. This keeps the 'world alive' during updates. */#define AMD_BYTES_PER_KEEP_ALIVE 2048 /* every 2k bytes, wake up others */#define MICRON_BYTES_PER_KEEP_ALIVE 2048 /* every 2k bytes, wake up others */#define ATMEL_SECTORS_PER_KEEP_ALIVE 10 /* a little less than 10ms / sector */#define SST_SECTORS_PER_KEEP_ALIVE 10 /* a little less than 10ms / sector *//*** The number of bytes, on chips that support single writes to anywhere in** flash, that can be written without having to change the flash sector. ** (This is an optimisation which can save having to erase and rewrite a ** complete sector, for example AMD chips but not Atmel PEROMs.)*/#define SMALL_WRITE_LIMIT 25/*** Name: FlashSector**** Flash chips are commonly divided into sectors. Some chips have all** sectors one size, others have small sectors at one or both ends to provide** BOOT ROM capability.*/typedef struct flash_sector_tag{ /* ** The size of a sector within a flash chip. Much of the code assumes ** that sectors are a power of two in length. */ U32 size; U32 numberSectors;} FlashSector;/*** Increase as required: the number of different sized blocks of ** sectors within a flash device.*/#define NUMBER_DIFFERENT_SECTOR_SIZES 4/*** Name: FlashType**** The characteristics of each supported flash device type. Unused sector** definitions should be zero. The sum of sector.size * sector.numberSectors** should equal size. The sector sizes should be in the order that they occur** within the device.**** The function pointers remove chip dependencies within the main body of the code.*/typedef struct flash_type_tag{ BITS id; BOOL is16Bit; /* 16 bit device operating in 8 bit mode */ BOOL true16; /* 16 bit device operating in 16 bit mode */ U32 size; const char * manufacturer; const char * partname; FlashSector sectors [NUMBER_DIFFERENT_SECTOR_SIZES]; /* ** Required: program a sector */ int (*program_sector) (U32 logicalAddress, BYTE *source, U32 length); /* ** Optional (may be NULL): program single byte, if absent ** the whole sector is read and rewritten. If the flash chip ** supports writing a single byte it can save needless sector ** reprogramming and is, therefore, faster. To support this ** operation the flash is expected to be erased to 0xff and ** single bits may be reset. */ int (*program_byte) (U32 logicalAddress, BYTE value); /* ** Optional: erase a sector to 0xff, if absent program_sector ** called with source of buffer filled with 0xff. ** IMPORTANT: length <= LARGEST_PEROM_SECTOR_SIZE */ int (*erase_sector) (U32 logicalAddress, U32 length);} FlashType;/*** Name: FlashDevice**** The compile-time configuration of a flash device in memory.*/typedef struct flash_device_tag{ /* Is this a 16-bit device? */ BOOL Is16; /* 0 == 8 bit, 1 == 16 bit */ /* ** From where to read FLASH */ volatile BYTE * physicalBaseRead; /* ** Where to write FLASH. Presented as a different address to read, ** though it may be the same, because the hardware may have subtlely ** different timing when writing (e.g. WRITE may go low before CS which ** on some FLASH chips violates timings). */ volatile BYTE * physicalBaseWrite; U32 size; BYTE flashPage; U32 logicalBase;} FlashDevice;/*** Name: ActualFlashType**** The actual configuration of a flash device in memory. Although this** could be merged with FlashDevice that would mean that the "fixed" and** "variable" elements were mixed unnecesarily.*/typedef struct actual_flash_type_tag{ /* ** Index into flashTypes, set to NUMBER_FLASH_TYPES after flash_initialise ** has been called. */ BYTE typeIndex; /* ** A bit mask of protected BOOT blocks, etc. set to one (1) when the relevant ** sector is protected. ** NB The current definition assumes that flash chips have a maximum of ** thirty-two protectable sectors in them. */ U32 writeMask;} ActualFlashType;/*** Macro to read one byte of flash, this can be replaced during simulation** Note that _addr is offset within the device.*/#ifdef WINDOWED_FLASH#define FLASH_READ_RAW(_addr, _device) (FLASH_WINDOW_SELECT(_addr), \ flashDevices [_device].physicalBaseRead [_addr & FLASH_WINDOW_MASK])#else#define FLASH_READ_RAW(_addr, _device) flashDevices [_device].physicalBaseRead [_addr]#endif#define FLASH_READ_RAW16(_addr, _device) *(volatile U16*)(flashDevices [_device].physicalBaseRead + (_addr & ~1))#ifdef ETHER8X10 /* Macro to write one byte to flash */ /* On the StrongArm, bytes come out on the appropriate data byte lane and */ /* are not, as on the ARM610, replicated across all lanes. So the hardware */ /* maps A0:A1 from A22:A23 on write only. */ #define FLASH_WRITE_RAW(_byte, _addr, _device) flashDevices [_device].physicalBaseWrite [((_addr) & ~3) | (((_addr) & 3) << 22)] = _byte#else /* ETHER8X10 */#ifdef WINDOWED_FLASH #define FLASH_WRITE_RAW(_byte, _addr, _device) (FLASH_WINDOW_SELECT (_addr), \ flashDevices [_device].physicalBaseWrite [_addr & FLASH_WINDOW_MASK] = _byte)#else #define FLASH_WRITE_RAW(_byte, _addr, _device) flashDevices [_device].physicalBaseWrite [_addr] = _byte#endif#endif /* ETHER8X10 */#define FLASH_WRITE_RAW16(_word, _addr, _device) *(volatile U16*)(flashDevices[_device].physicalBaseWrite + (_addr & ~1)) = _word/*====================================================================*//* Forward definitions of procedures in this module *//*====================================================================*//*** Chip specific write/erase routines.*/#ifndef FLASH_NO_AMD_SUPPORTstatic int program_AMD_sector(U32 addr, BYTE *source, U32 sectorSize);static int erase_AMD_sector(U32 addr, U32 sectorSize);static int program_AMD_byte(U32 addr, BYTE byte);static int program_AMD_sector16(U32 addr, BYTE *source, U32 sectorSize); // Added by APSstatic int erase_AMD_sector16(U32 addr, U32 sectorSize); // Added by APSstatic int program_AMD_word(U32 addr, U16 data); // Added by APS#endif#ifndef FLASH_NO_ATMEL_SUPPORTstatic int program_ATMEL_sector(U32 addr, BYTE *source, U32 sector);static int program_ATMEL_sector16(U32 addr, BYTE *source, U32 sector);#endif#ifndef FLASH_NO_INTEL_SUPPORT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -