📄 amd29lvmtd.c.svn-base
字号:
/* amd29LvMtd.c - AMD AM29LV devices */
/* includes */
#include "board.h"
/* defines */
#define OK 0
#define ERROR -1
#define flOK OK
#define LOCAL static
#define FALSE 0
#define flTimedOut -1
#define flSectorNotFound -2
#define CACHE_PIPE_FLUSH sysWbFlush
#define DEBUGIT
typedef int BOOL;
typedef char INT8;
typedef short INT16;
typedef long INT32;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef int STATUS;
typedef int FLStatus;
typedef int FLBoolean;
typedef unsigned long CardAddress;
typedef struct tFlash FLFlash; /* Forward definition */
struct tFlash {
unsigned int type;
unsigned short flags;
unsigned long erasableBlockSize;
unsigned long chipSize;
unsigned int noOfChips;
unsigned int interleaving;
unsigned long baseAddress;
void * (*map)(FLFlash *, CardAddress, int);
FLStatus (*erase)(FLFlash *, int, int);
FLStatus (*write)(FLFlash *, CardAddress, const void *, int, int);
};
//#define FLASH_BASE_ADDR 0xbfc00000
#define AMD29LV_MTD_SECTOR_SIZE (0x10000) /* 64k */
#define AMD29LV_800_CHIP_SIZE (0x100000) /* 1MB */
#define AMD29LV_800_LAST_SECTOR_NUM (AMD29LV_800_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)
#define AMD29LV_160_CHIP_SIZE (0x200000) /* 2MB */
#define AMD29LV_160_LAST_SECTOR_NUM (AMD29LV_160_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)
#define AMD29LV_320_CHIP_SIZE (0x400000) /* 4MB */
#define AMD29LV_320_LAST_SECTOR_NUM (AMD29LV_320_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)
#define AMD29LV_640_CHIP_SIZE (0x800000) /* 8MB */
#define AMD29LV_640_LAST_SECTOR_NUM (AMD29LV_640_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)
#define AMD29LV_MTD_CHIP_CNT (1)
#define AMD29LV_MTD_INTERLEAVE (1)
// definition to support SST flash
#define FLASH_SST_SUPPORT 1
#define SST39VF_MTD_SECTOR_SIZE (0x1000) /* 64k */
#define SST39VF_400_CHIP_SIZE (0x80000) /* 512KB */
#define SST39VF_400_LAST_SECTOR_NUM (SST39VF_400_CHIP_SIZE / SST39VF_MTD_SECTOR_SIZE - 1)
#define SST39VF_800_CHIP_SIZE (0x100000) /* 1MB */
#define SST39VF_800_LAST_SECTOR_NUM (SST39VF_800_CHIP_SIZE / SST39VF_MTD_SECTOR_SIZE - 1)
#define SST39VF_1601_CHIP_SIZE (0x200000) /* 2MB */
#define SST39VF_1601_LAST_SECTOR_NUM (SST39VF_1601_CHIP_SIZE / SST39VF_MTD_SECTOR_SIZE - 1)
#define SST39VF_3201_CHIP_SIZE (0x400000) /* 4MB */
#define SST39VF_3201_LAST_SECTOR_NUM (SST39VF_3201_CHIP_SIZE / SST39VF_MTD_SECTOR_SIZE - 1)
#define SST39VF_MTD_CHIP_CNT (1)
#define SST39VF_MTD_INTERLEAVE (1)
/* Save the last erase block on each device discovered in the array
* for NVRAM */
#undef SAVE_NVRAM_REGION
#define DEBUG_READ 0x00000001
#define DEBUG_WRITE 0x00000002
#define DEBUG_PROGRAM 0x00000004
#define DEBUG_ERASE 0x00000008
#define DEBUG_ID 0x00000010
#define DEBUG_MAP 0x00000020
#define DEBUG_PROG16 0x00000040
#define DEBUG_ALWAYS 0xffffffff
#define DEBUG
#ifdef DEBUG
LOCAL UINT32 debug = 0;
#define DEBUG_PRINT(mask, string) \
if ((debug & mask) || (mask == DEBUG_ALWAYS)) \
printf string
#else
#define DEBUG_PRINT(mask, string)
#endif
/* local routines */
LOCAL FLStatus amd29lvSectorRangeErase(FLFlash* pVol, int, int);
LOCAL FLStatus amd29lvProgram(FLFlash*, CardAddress, const void *, int,
FLBoolean);
LOCAL void * amd29lvMap(FLFlash*, CardAddress, int);
LOCAL void flashReset(FLFlash*);
LOCAL void flashIdGet(FLFlash*, UINT16*, UINT16*);
LOCAL void flashUnlock(FLFlash*);
LOCAL STATUS flashCheck16Bits(FLFlash*, UINT32);
LOCAL inline STATUS flashProgram16Bits(FLFlash*, volatile UINT16*, UINT16);
LOCAL inline void flashRegWrite16Bits(FLFlash*, UINT32, UINT16);
LOCAL UINT16 flashRegRead16Bits(FLFlash*, UINT32);
LOCAL UINT16 flashRegRead8Bits(FLFlash*, UINT32);
LOCAL STATUS flashSectorErase(FLFlash*, int);
UINT16 DeviceID_cycle2, DeviceID_cycle3; //added for verify mx29LV640M T/B
/******************************************************************************
*
* amd29lvMTDIdentify - MTD identify routine (see TrueFFS Programmer's Guide)
*
* RETURNS: FLStatus
*
*/
FLStatus amd29lvMTDIdentify(FLFlash* pVol)
{
UINT16 manCode;
UINT16 devCode;
flashIdGet(pVol, &manCode, &devCode);
DEBUG_PRINT(DEBUG_ID,
("amd29lvMTDIdentify Manufacturer: 0x%02x\n\r",
manCode));
DEBUG_PRINT(DEBUG_ID,
("amd29lvMTDIdentify Device: 0x%02x\n\r",
devCode));
if (devCode == 0x22DA || /* amd29LV800BT */
devCode == 0x225B) /* amd29LV800BB */
{
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = AMD29LV_800_CHIP_SIZE - AMD29LV_MTD_SECTOR_SIZE;
#else
pVol->chipSize = AMD29LV_800_CHIP_SIZE;
#endif
pVol->noOfChips = AMD29LV_MTD_CHIP_CNT;
pVol->interleaving = AMD29LV_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
}
else
if (devCode == 0x22C4 || /* amd29LV160BT */
devCode == 0x2249) /* amd29LV160BB */
{
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = AMD29LV_160_CHIP_SIZE - AMD29LV_MTD_SECTOR_SIZE;
#else
pVol->chipSize = AMD29LV_160_CHIP_SIZE;
#endif
pVol->noOfChips = AMD29LV_MTD_CHIP_CNT;
pVol->interleaving = AMD29LV_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
}
else
if (devCode == 0x22A7 || /* amd29LV320BT */
devCode == 0x22A8 || /* amd29LV320BB */
devCode == 0x22F6 || /* SpansionS29AL032DT */
devCode == 0x22F9 ) /* SpansionS29AL032DB */
{
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = AMD29LV_320_CHIP_SIZE - AMD29LV_MTD_SECTOR_SIZE;
#else
pVol->chipSize = AMD29LV_320_CHIP_SIZE;
#endif
pVol->noOfChips = AMD29LV_MTD_CHIP_CNT;
pVol->interleaving = AMD29LV_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
}
else
if (devCode == 0x227E /* amd29LV640BT */
||devCode == 0x22CB) /* mx29lv640 bb */
{
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = AMD29LV_640_CHIP_SIZE - AMD29LV_MTD_SECTOR_SIZE;
#else
pVol->chipSize = AMD29LV_640_CHIP_SIZE;
#endif
pVol->noOfChips = AMD29LV_MTD_CHIP_CNT;
pVol->interleaving = AMD29LV_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
}
else
#if FLASH_SST_SUPPORT
if (0x2780 == devCode) { /* SST39VF400 */
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = SST39VF_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = SST39VF_400_CHIP_SIZE - SST39VF_MTD_SECTOR_SIZE;
#else
pVol->chipSize = SST39VF_400_CHIP_SIZE;
#endif
pVol->noOfChips = SST39VF_MTD_CHIP_CNT;
pVol->interleaving = SST39VF_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
} else
if (0x2781 == devCode) { /* SST39VF800 */
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = SST39VF_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = SST39VF_800_CHIP_SIZE - SST39VF_MTD_SECTOR_SIZE;
#else
pVol->chipSize = SST39VF_800_CHIP_SIZE;
#endif
pVol->noOfChips = SST39VF_MTD_CHIP_CNT;
pVol->interleaving = SST39VF_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
} else
if (0x234B == devCode) {
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = SST39VF_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = SST39VF_1601_CHIP_SIZE - SST39VF_MTD_SECTOR_SIZE;
#else
pVol->chipSize = SST39VF_1601_CHIP_SIZE;
#endif
pVol->noOfChips = SST39VF_MTD_CHIP_CNT;
pVol->interleaving = SST39VF_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
} else
if (0x235B == devCode) {
pVol->type = (manCode<<16)| (devCode&0xffff);
pVol->erasableBlockSize = SST39VF_MTD_SECTOR_SIZE;
#ifdef SAVE_NVRAM_REGION
pVol->chipSize = SST39VF_3201_CHIP_SIZE - SST39VF_MTD_SECTOR_SIZE;
#else
pVol->chipSize = SST39VF_3201_CHIP_SIZE;
#endif
pVol->noOfChips = SST39VF_MTD_CHIP_CNT;
pVol->interleaving = SST39VF_MTD_INTERLEAVE;
pVol->write = amd29lvProgram;
pVol->erase = amd29lvSectorRangeErase;
pVol->map = amd29lvMap;
} else
#endif
{
DEBUG_PRINT(DEBUG_ALWAYS,
("amd29lvMTDIdentify Device unknown: 0x%02x\n\r",
devCode));
return(ERROR);
}
DEBUG_PRINT(DEBUG_ID, ("amd29lvMTDIdentify succeeds!\n\r"));
return(flOK);
}
/******************************************************************************
* flashCheck16Bits - Wait for a flash operation to complete and determine the result
*
* Result: 0 = operation completed successfully
* 1 = timeout during operation
* 2 = error detected
*/
static STATUS flashCheck16Bits(FLFlash* pVol, UINT32 addr)
{
volatile UINT8 initialData;
volatile UINT8 nextData;
int start = get_sys_time();
/* Read the 'initial' value of the status register */
initialData = flashRegRead16Bits(pVol, addr);
while(!timeout(start, 30000))
{
nextData = flashRegRead16Bits(pVol, addr);
/* See if the toggle bit toggled.
* If it has not then the operation has completed successfully
*/
if ((initialData & (1<<6)) == (nextData & (1<<6)))
{
/* D6 has stopped toggling Operation complete */
return 0;
}
/* If still toggling then check D5 to see if an error was detected */
if (initialData & (1<<5))
{
volatile UINT8 value1 = flashRegRead16Bits(pVol, addr);
volatile UINT8 value2 = flashRegRead16Bits(pVol, addr);
if ((value1 & (1<<6)) == (value2 & (1<<6)))
{
/* DQ6 is not toggling, so ignore the error bit */
return 0;
}
else
{
/* DQ6 is still toggling so return the error */
if(value2 & (1<<2))
return 0;
}
}
/* Update the initial data for the next pass */
initialData = nextData;
//delay_msec(1);
}
/* Operation timed out before completion */
return 1;
}
/******************************************************************************
*
* amd29lvProgram - MTD write routine (see TrueFFS Programmer's Guide)
*
* RETURNS: FLStatus
*
*/
LOCAL FLStatus amd29lvProgram(FLFlash *pVol, CardAddress address,
const void * buffer, int length, FLBoolean overwrite)
{
volatile UINT16* pFlash;
UINT8* pBuffer;
UINT16 data;
STATUS rc = OK;
int i;
DEBUG_PRINT(DEBUG_PROGRAM,
("Program: 0x%08x, 0x%08x, %d\n\r", (unsigned int) address,
length, overwrite));
/* Check alignment */
pBuffer = (UINT8*)buffer;
#if 0
DEBUG_PRINT(DEBUG_PROGRAM,("\n\r"));
for(i=0;i<length;i++)
DEBUG_PRINT(DEBUG_PROGRAM, ("%02X", pBuffer[i]));
DEBUG_PRINT(DEBUG_PROGRAM, ("\n\r"));
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -