?? amd.c
字號:
//****************************************************************************
//
// AMD.c - The amd flash function definition.
//
// Copyright (c) 2006 Cirrus Logic, Inc.
//
//****************************************************************************
#include "ep93xx.h"
#include "flash.h"
#include "amd.h"
#include <string.h>
#define AMD_compatible_MAX 3
static struct sFlashManufactureId sAMD_ManufactureId[AMD_compatible_MAX]={
{0x0001,"AMD"},
{0x0004,"Spansion"},
{0x0020,"ST"}
};
//****************************************************************************
// Name : AmdFlashQuery
// Description: This routine read the flash manufactureid and deviceid.
// Return : 0 - succuss.
// 1 - failure.
// Note(s) :
//****************************************************************************
int AmdFlashQuery(struct FlashInfo *pInfo)
{
volatile unsigned short *ptr16 = (volatile unsigned short *)pInfo->FlashBase;
volatile unsigned long *ptr32 = (volatile unsigned long *)pInfo->FlashBase;
unsigned short usByteWidth = pInfo->ByteWidth;
int iIdx, iResult;
int timeout = 500000;
if (usByteWidth == 1){
unsigned short usWord;
usWord = *ptr16;
// Query 16 bitwidth id.
*(ptr16 + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(ptr16 + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(ptr16 + AMD_SETUP_ADDR1) = AMD_READ_ID;
pInfo->ManufactureId = *(ptr16 + AMD_VENDORID_ADDR);
pInfo->DeviceId[0] = *(ptr16 + AMD_DEVICEID_ADDR1);
// Query 16 bitwidth flash.
*(ptr16 + AMD_QUERY_ADDR) = AMD_READ_QUERY;
pInfo->pQuery->DeviceSize = 1 << (*(ptr16 + 0x27) & 0xFF);
pInfo->pQuery->NumEraseBlocks = *(ptr16 + 0x2c) & 0xFFFF;
for(iIdx = 0; iIdx < pInfo->pQuery->NumEraseBlocks; iIdx++){
pInfo->pQuery->sBlockInfo[iIdx].blocks =
(*(ptr16 + 0x2d + (iIdx<<2)) & 0xFFFF) + 1;
pInfo->pQuery->sBlockInfo[iIdx].block_size =
(((*(ptr16 + 0x30 + (iIdx<<2)) & 0xFFFF) << 8) +
(*(ptr16 + 0x2f + (iIdx<<2)) & 0xFFFF)) << 8;
}
// Put the FLASH into read array mode.
*ptr16 = AMD_RESET;
// Stall, waiting for flash to return to read mode.
while ((--timeout != 0) && (usWord != *ptr16));
iResult = 0;
} else if (usByteWidth == 2){
unsigned long ulWord;
ulWord = *ptr32;
// Query 16 bitwidth id.
*(ptr32 + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(ptr32 + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(ptr32 + AMD_SETUP_ADDR1) = (AMD_READ_ID << 16) | AMD_READ_ID;
pInfo->ManufactureId = (unsigned short) ((*(ptr32 + AMD_VENDORID_ADDR) >> 16)
& ((*(ptr32 + AMD_VENDORID_ADDR)) & 0xFFFF));
pInfo->DeviceId[0] = (unsigned short) (*(ptr32 + AMD_DEVICEID_ADDR1) );
// Query 32 bitwidth flash.
*(ptr32 + AMD_QUERY_ADDR) = (AMD_READ_QUERY << 16) | AMD_READ_QUERY;
pInfo->pQuery->DeviceSize = 2 << (*(ptr32 + 0x27) & 0xFF);
pInfo->pQuery->NumEraseBlocks = *(ptr32 + 0x2c) & 0xFFFF;
for(iIdx = 0; iIdx < pInfo->pQuery->NumEraseBlocks; iIdx++){
pInfo->pQuery->sBlockInfo[iIdx].blocks =
(*(ptr32 + 0x2d + (iIdx<<2)) & 0xFFFF) + 1;
pInfo->pQuery->sBlockInfo[iIdx].block_size =
(((*(ptr32 + 0x30 + (iIdx<<2)) & 0xFFFF) << 8) +
(*(ptr32 + 0x2f + (iIdx<<2)) & 0xFFFF)) << 8;
}
// Put the FLASH into read array mode.
*ptr32 = (AMD_RESET << 16) | AMD_RESET;
// Stall, waiting for flash to return to read mode.
while ((--timeout != 0) && (ulWord != *ptr32));
iResult = 0;
} else{
// No such parameter.
iResult = 1;
}
//if(pInfo->ManufactureId == 0x0001) return 0;
//else return 1;
for(iIdx=0;iIdx<AMD_compatible_MAX;iIdx++)
{
if(pInfo->ManufactureId == sAMD_ManufactureId[iIdx].manufacture_id)
{
return 0;
}
}
return 1;
}
//****************************************************************************
// Name : AmdFlashEraseSector
// Description: This routine erase the specified sector of amd.
// Arguments : iOffset - the offset address.
// len - the length.
// Return : 0 - succuss.
// 1 - failure.
// Note(s) :
//****************************************************************************
int AmdFlashEraseSector(struct FlashInfo *pInfo, int iSector)
{
volatile unsigned short *ptr16 = (volatile unsigned short *)pInfo->FlashBase;
volatile unsigned long *ptr32 = (volatile unsigned long *)pInfo->FlashBase;
unsigned short usByteWidth = pInfo->ByteWidth;
int iResult = FLASH_ERR_OK;
int timeout = 50000;
if (usByteWidth == 1){
// Send erase block command - six step sequence
*(ptr16 + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(ptr16 + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(ptr16 + AMD_SETUP_ADDR1) = AMD_SETUP_ERASE;
*(ptr16 + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(ptr16 + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(ptr16 + (iSector >> 1)) = AMD_BLOCK_ERASE;
// Now poll for the completion of the sector erase timer (50us)
timeout = 10000000; // how many retries?
while (1) {
if (((*(ptr16 + (iSector >> 1))) & AMD_SECTOR_ERASE_TIMER)
== AMD_SECTOR_ERASE_TIMER) break;
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
// Then wait for erase completion.
if (FLASH_ERR_OK == iResult) {
timeout = 10000000;
while (1) {
if (0xffff == (*(ptr16 + (iSector >> 1)))) {
break;
}
// Don't check for FLASH_Err here since it will fail
// with devices in parallel because these may finish
// at different times.
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
}
if (FLASH_ERR_OK != iResult)
*ptr16 = AMD_RESET;
} else if (usByteWidth == 2){
// Send erase block command - six step sequence
*(ptr32 + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(ptr32 + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(ptr32 + AMD_SETUP_ADDR1) = (AMD_SETUP_ERASE << 16) | AMD_SETUP_ERASE;
*(ptr32 + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(ptr32 + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(ptr32 + (iSector >> 2)) = (AMD_BLOCK_ERASE << 16) | AMD_BLOCK_ERASE;
// Now poll for the completion of the sector erase timer (50us)
timeout = 10000000; // how many retries?
while (1) {
if (((*(ptr32 + (iSector >> 2))) & AMD_SECTOR_ERASE_TIMER)
== AMD_SECTOR_ERASE_TIMER) break;
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
// Then wait for erase completion.
if (FLASH_ERR_OK == iResult) {
timeout = 10000000;
while (1) {
if (0xffffffff == (*(ptr32 + (iSector >> 2)))) {
break;
}
// Don't check for FLASH_Err here since it will fail
// with devices in parallel because these may finish
// at different times.
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
}
if (FLASH_ERR_OK != iResult)
*ptr32 = (AMD_RESET << 16) | AMD_RESET;
} else{
// No such parameter.
return 1;
}
return iResult;
}
//****************************************************************************
// Name : GetSectorIndex
// Description: This routine erase the sectors of intel.
// Arguments : iOffset - the offset address.
// len - the length.
// Return : 0 - succuss.
// 1 - failure.
// Note(s) :
//****************************************************************************
int Amd_GetSectorIndex(struct FlashInfo *pInfo,long lStartAddress,
unsigned long * pulSectorBase,int * piCurEraseRegion,
int * piCurEraseBlock )
{
unsigned short usByteWidth = pInfo->ByteWidth;
int i, j;
long iEraseBase = lStartAddress;
*pulSectorBase = 0;
if (usByteWidth == 1)
{
for(i = 0; i < pInfo->pQuery->NumEraseBlocks; i++)
{
for(j = 0; j< pInfo->pQuery->sBlockInfo[i].blocks; j++)
{
if(iEraseBase >= pInfo->pQuery->sBlockInfo[i].block_size)
{
*pulSectorBase = *pulSectorBase + pInfo->pQuery->sBlockInfo[i].block_size;
iEraseBase = iEraseBase - pInfo->pQuery->sBlockInfo[i].block_size;
}
else
{
*piCurEraseRegion = i;
*piCurEraseBlock = j;
return 0;
}
}
}
}
else if (usByteWidth == 2)
{
for(i = 0; i < pInfo->pQuery->NumEraseBlocks; i++)
{
for(j = 0; j< pInfo->pQuery->sBlockInfo[i].blocks; j++)
{
if(iEraseBase >= pInfo->pQuery->sBlockInfo[i].block_size*2)
{
*pulSectorBase = *pulSectorBase + pInfo->pQuery->sBlockInfo[i].block_size*2;
iEraseBase = iEraseBase - pInfo->pQuery->sBlockInfo[i].block_size*2;
}
else
{
*piCurEraseRegion = i;
*piCurEraseBlock = j;
return 0;
}
}
}
}
else
{
// No such parameter.
return 1;
}
return 1;
}
//****************************************************************************
// Name : AmdFlashErase
// Description: This routine erase the amd flash.
// Arguments : iOffset - the offset address.
// len - the length.
// Return : 0 - succuss.
// 1 - failure.
// Note(s) :
//****************************************************************************
int AmdFlashErase(struct FlashInfo *pInfo, int iOffset, int len)
{
volatile unsigned short *ptr16 = (volatile unsigned short *)pInfo->FlashBase;
volatile unsigned long *ptr32 = (volatile unsigned long *)pInfo->FlashBase;
unsigned short usByteWidth = pInfo->ByteWidth;
long i, j,iIdx;
//long iEraseLen = len;
//long iEraseBase = iOffset;
unsigned long pulSectorBase=0,pulSectorEnd=0;
int piCurEraseRegionStart=0,piCurEraseBlockStart=0,piCurEraseRegionEnd=0,piCurEraseBlockEnd=0;
if(Amd_GetSectorIndex(pInfo,iOffset,&pulSectorBase,
&piCurEraseRegionStart, &piCurEraseBlockStart)==1)
return 1;
if(Amd_GetSectorIndex(pInfo,iOffset+len,&pulSectorEnd,
&piCurEraseRegionEnd, &piCurEraseBlockEnd)==1)
return 1;
if (usByteWidth == 1)
{
if(piCurEraseRegionStart!=piCurEraseRegionEnd)
{
for(i = piCurEraseRegionStart; i <= piCurEraseRegionEnd; i++)
{
if(i==piCurEraseRegionStart)
{
for(j = piCurEraseBlockStart; j< pInfo->pQuery->sBlockInfo[i].blocks; j++)
{
AmdFlashEraseSector(pInfo,pulSectorBase);
//
//#if 1
for(iIdx = 0; iIdx < (pInfo->pQuery->sBlockInfo[i].block_size>>1); iIdx++)
{
if(*(ptr16 + (pulSectorBase >> 1) + iIdx) != 0xffff)
{
return 1;
}
}
//#endif
pulSectorBase = pulSectorBase + pInfo->pQuery->sBlockInfo[i].block_size;
}
}
else if(i==piCurEraseRegionEnd)
{
for(j = 0; j<= piCurEraseBlockEnd; j++)
{
AmdFlashEraseSector(pInfo,pulSectorBase);
//
//#if 1
for(iIdx = 0; iIdx < (pInfo->pQuery->sBlockInfo[i].block_size>>1); iIdx++)
{
if(*(ptr16 + (pulSectorBase >> 1) + iIdx) != 0xffff)
{
return 1;
}
}
//#endif
pulSectorBase = pulSectorBase + pInfo->pQuery->sBlockInfo[i].block_size;
}
}
else
{
for(j = 0; j< pInfo->pQuery->sBlockInfo[i].blocks; j++)
{
AmdFlashEraseSector(pInfo,pulSectorBase);
//
//#if 1
for(iIdx = 0; iIdx < (pInfo->pQuery->sBlockInfo[i].block_size>>1); iIdx++)
{
if(*(ptr16 + (pulSectorBase >> 1) + iIdx) != 0xffff)
{
return 1;
}
}
//#endif
pulSectorBase = pulSectorBase + pInfo->pQuery->sBlockInfo[i].block_size;
}
}
}
}
else
{
for(j = piCurEraseBlockStart; j<= piCurEraseBlockEnd; j++)
{
AmdFlashEraseSector(pInfo,pulSectorBase);
//
//#if 1
for(iIdx = 0; iIdx < (pInfo->pQuery->sBlockInfo[piCurEraseRegionStart].block_size>>1); iIdx++)
{
if(*(ptr16 + (pulSectorBase >> 1) + iIdx) != 0xffff)
{
return 1;
}
}
//#endif
pulSectorBase = pulSectorBase + pInfo->pQuery->sBlockInfo[piCurEraseRegionStart].block_size;
}
}
return 0;
}
//
//32 bit
//
else if (usByteWidth == 2)
{
if(piCurEraseRegionStart!=piCurEraseRegionEnd)
{
for(i = piCurEraseRegionStart; i <= piCurEraseRegionEnd; i++)
{
if(i==piCurEraseRegionStart)
{
for(j = piCurEraseBlockStart; j< pInfo->pQuery->sBlockInfo[i].blocks; j++)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -