/*
Change from n2048.c 2004-08-28, by wangtao
*/
/************************************************************************/
/* */
/* FAT-FTL Lite Software Development Kit */
/* Copyright (C) M-Systems Ltd. 1995-1997 */
/* */
/************************************************************************/
#include "tffs/flflash.h"
#include "tffs/reedsol.h"
#include "vxWorks.h"
#include "stdio.h"
#include "cacheLib.h"
#include "tyLib.h"
#include "sysLib.h"
#include "logLib.h"
#include "stdlib.h"
#include "string.h"
#include "intLib.h"
#include "taskLib.h"
#include "iv.h"
/*******************************************************************************
* 调试环境:
* K9F2808U0C_Y,IBM-PPC405EP,Tornado2.2
*
* 硬件说明:
* CLE和ALE分别由A3和A2控制,CE连接到RCS2,Ready/Busy需要外接上拉电阻;
* Read操作时,K9F2808U0C_Y,P型号在Busy状态时必须保持CS低电平状态;
* /WP写保护信号应该连接到复位信号,保证在上电或掉电时为低电平的写保护状态;
* FLASH芯片是8bit接口,而硬件是16bit接口,因此涉及到char和short的强制转换;
*
* 软件:
* 为了解决16bit操作的Endian问题,采用sysPciOutWord和sysPciInWord函数作为端口访问函数;
* 如果RCS2的配置是8bit模式,就不需要考虑Endian问题,否则需要做char和short的强制转换;
*******************************************************************************/
#define FADDR_BASE 0xfd800000
#define FADDR_CLE (FADDR_BASE + 0x8)
#define FADDR_ALE (FADDR_BASE + 0x4)
#define PAGES_PER_BLOCK 32 /* 32 pages per block on a single chip*/
#define NFLASH_K9F_SECTORSIZE 0x200
#define NFLASH_K9F_TAILSIZE 16
#define NFLASH_K9F_SECTORHALFSIZE 0x100
#define NFLASH_K9F2808U0X 0xEC73
#define NFL_K9F2808_CHIPSIZE (15 * 1024 * 1024) /* Total 16MB on K9F2808 chip. */
#define NFL_K9F2808_PAGENUM (NFL_K9F2808_CHIPSIZE / 512)
#define NFL_K9F2808_BLOCKNUM (NFL_K9F2808_PAGENUM / PAGES_PER_BLOCK)
#define NFLASH_K9F5608U0X 0xEC75
#define NFL_K9F5608_CHIPSIZE (32 * 1024 * 1024) /* Total 32MB on K9F5608 chip. */
#define NFL_K9F5608_PAGENUM (NFL_K9F5608_CHIPSIZE / 512)
#define NFL_K9F5608_BLOCKNUM (NFL_K9F2808_PAGENUM / PAGES_PER_BLOCK)
#define OUT_WORD(addr, data) sysPciOutWord(addr, data)
#define IN_WORD(addr) sysPciInWord(addr)
#define FLASH_DEBUG
#ifdef FLASH_DEBUG
int glFlashDebugLevel=0;
#define DEBUG_FL(fmt,args...) if(glFlashDebugLevel>0) printf(fmt,##args);
#else
#define DEBUG_FL(fmt,args...)
#endif
LOCAL char flDataBuffer[10000]; /* define a map buffer. */
#define VERIFY_AFTER_WRITE
#ifdef VERIFY_AFTER_WRITE
LOCAL unsigned char flReadback[NFLASH_K9F_SECTORSIZE];
LOCAL unsigned char flExtraReadBack[NFLASH_K9F_TAILSIZE];
#endif
/* The following is the ecc function. */
typedef enum {
ECC_NO_ERROR = 0, /* no error */
ECC_CORRECTABLE_ERROR = 1, /* one bit data error */
ECC_ECC_ERROR = 2, /* one bit ECC error */
ECC_UNCORRECTABLE_ERROR = 3 /* uncorrectable error */
} eccdiff_t;
/****************************************************************************
* NAME make_ecc_512
* DESCRIPTION
* This function generates 3 byte ECC for 512 byte data.
* (Software ECC)
* PARAMETERS
* ecc_buf the location where ECC should be stored
* data_buf given data
* RETURN VALUES none
*
****/
void make_ecc_512(unsigned char * ecc_buf, unsigned char * data_buf)
{
unsigned long i, ALIGN_FACTOR;
unsigned long tmp;
unsigned long uiparity = 0;
unsigned long parityCol, ecc = 0;
unsigned long parityCol4321 = 0, parityCol4343 = 0, parityCol4242 = 0, parityColTot = 0;
unsigned long *Data;
unsigned long Xorbit=0;
ALIGN_FACTOR = (unsigned long)data_buf % 4 ;
Data = (unsigned long *)(data_buf + ALIGN_FACTOR);
for( i = 0; i < 16; i++)
{
parityCol = *Data++;
tmp = *Data++; parityCol ^= tmp; parityCol4242 ^= tmp;
tmp = *Data++; parityCol ^= tmp; parityCol4343 ^= tmp;
tmp = *Data++; parityCol ^= tmp; parityCol4343 ^= tmp; parityCol4242 ^= tmp;
tmp = *Data++; parityCol ^= tmp; parityCol4321 ^= tmp;
tmp = *Data++; parityCol ^= tmp; parityCol4242 ^= tmp; parityCol4321 ^= tmp;
tmp = *Data++; parityCol ^= tmp; parityCol4343 ^= tmp; parityCol4321 ^= tmp;
tmp = *Data++; parityCol ^= tmp; parityCol4242 ^= tmp; parityCol4343 ^= tmp; parityCol4321 ^= tmp;
parityColTot ^= parityCol;
tmp = (parityCol >> 16) ^ parityCol;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp >> 4) ^ tmp;
tmp = ((tmp >> 2) ^ tmp) & 0x03;
if ((tmp == 0x01) || (tmp == 0x02))
{
uiparity ^= i;
Xorbit ^= 0x01;
}
}
tmp = (parityCol4321 >> 16) ^ parityCol4321;
tmp = (tmp << 8) ^ tmp;
tmp = (tmp >> 4) ^ tmp;
tmp = (tmp >> 2) ^ tmp;
ecc |= ((tmp << 1) ^ tmp) & 0x200; // p128
tmp = (parityCol4343 >> 16) ^ parityCol4343;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp << 4) ^ tmp;
tmp = (tmp << 2) ^ tmp;
ecc |= ((tmp << 1) ^ tmp) & 0x80; // p64
tmp = (parityCol4242 >> 16) ^ parityCol4242;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp << 4) ^ tmp;
tmp = (tmp >> 2) ^ tmp;
ecc |= ((tmp << 1) ^ tmp) & 0x20; // p32
tmp = parityColTot & 0xFFFF0000;
tmp = tmp >> 16;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp >> 4) ^ tmp;
tmp = (tmp << 2) ^ tmp;
ecc |= ((tmp << 1) ^ tmp) & 0x08; // p16
tmp = parityColTot & 0xFF00FF00;
tmp = (tmp >> 16) ^ tmp;
tmp = (tmp >> 8);
tmp = (tmp >> 4) ^ tmp;
tmp = (tmp >> 2) ^ tmp;
ecc |= ((tmp << 1) ^ tmp) & 0x02; // p8
tmp = parityColTot & 0xF0F0F0F0 ;
tmp = (tmp << 16) ^ tmp;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp << 2) ^ tmp;
ecc |= ((tmp << 1) ^ tmp) & 0x800000; // p4
tmp = parityColTot & 0xCCCCCCCC ;
tmp = (tmp << 16) ^ tmp;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp << 4) ^ tmp;
tmp = (tmp >> 2);
ecc |= ((tmp << 1) ^ tmp) & 0x200000; // p2
tmp = parityColTot & 0xAAAAAAAA ;
tmp = (tmp << 16) ^ tmp;
tmp = (tmp >> 8) ^ tmp;
tmp = (tmp >> 4) ^ tmp;
tmp = (tmp << 2) ^ tmp;
ecc |= (tmp & 0x80000); // p1
ecc |= (uiparity & 0x01) <<11;
ecc |= (uiparity & 0x02) <<12;
ecc |= (uiparity & 0x04) <<13;
ecc |= (uiparity & 0x08) <<14;
if (Xorbit)
{
ecc |= (ecc ^ 0x00AAAAAA)>>1;
}
else
{
ecc |= (ecc >> 1);
}
ecc = ~ecc;
*(ecc_buf + 2) = (unsigned char) (ecc >> 16);
*(ecc_buf + 1) = (unsigned char) (ecc >> 8);
*(ecc_buf + 0) = (unsigned char) (ecc);
}
/****************************************************************************
* NAME compare_ecc_512
* DESCRIPTION
* This function compares two ECCs and indicates if there is an error.
* PARAMETERS
* ecc_data1 one ECC to be compared
* ecc_data2 the other ECC to be compared
* page_data content of data page
* offset where the error occurred
* corrected correct data
* RETURN VALUES
* Upon successful completion, compare_ecc returns SSR_SUCCESS.
* Otherwise, corresponding error code is returned.
****/
eccdiff_t compare_ecc_512(unsigned char *iEccdata1, unsigned char *iEccdata2,
unsigned char *pPagedata, long pOffset, unsigned char pCorrected)
{
unsigned long iCompecc = 0, iEccsum = 0;
unsigned long iFindbyte = 0;
unsigned long iIndex;
unsigned long nT1 = 0, nT2 =0;
unsigned char iNewvalue;
unsigned char iFindbit = 0;
unsigned char *pEcc1 = (unsigned char *)iEccdata1;
unsigned char *pEcc2 = (unsigned char *)iEccdata2;
for ( iIndex = 0; iIndex <2; iIndex++)
{
nT1 ^= (((*pEcc1) >> iIndex) & 0x01);
nT2 ^= (((*pEcc2) >> iIndex) & 0x01);
}
for (iIndex = 0; iIndex < 3; iIndex++)
iCompecc |= ((~(*pEcc1++) ^ ~(*pEcc2++)) << iIndex * 8);
for(iIndex = 0; iIndex < 24; iIndex++)
iEccsum += ((iCompecc >> iIndex) & 0x01);
switch (iEccsum)
{
case 0 :
printf("RESULT : no error\n");
return ECC_NO_ERROR;
case 1 :
printf("RESULT : ECC code 1 bit fail\n");
return ECC_ECC_ERROR;
case 12 :
if (nT1 != nT2)
{
iFindbyte = ((iCompecc >> 17 & 1) << 8) + ((iCompecc >> 15 & 1) << 7) + ((iCompecc >> 13 & 1) << 6)
+ ((iCompecc >> 11 & 1) << 5) + ((iCompecc >> 9 & 1) << 4) + ((iCompecc >> 7 & 1) << 3)
+ ((iCompecc >> 5 & 1) << 2) + ((iCompecc >> 3 & 1) << 1) + (iCompecc >> 1 & 1);
iFindbit = (unsigned char)(((iCompecc >> 23 & 1) << 2) + ((iCompecc >> 21 & 1) << 1) + (iCompecc >> 19 & 1));
iNewvalue = (unsigned char)(pPagedata[iFindbyte] ^ (1 << iFindbit));
printf("iCompecc = %d\n",iCompecc);
printf("RESULT : one bit error\r\n");
printf("byte = %d, bit = %d\r\n", iFindbyte, iFindbit);
printf("corrupted = %x, corrected = %x\r\n", pPagedata[iFindbyte], iNewvalue);
if (pOffset != NULL) pOffset = iFindbyte;
if (pCorrected != NULL) pCorrected = iNewvalue;
return ECC_CORRECTABLE_ERROR;
}
else
return ECC_UNCORRECTABLE_ERROR;
default :
printf("RESULT : unrecoverable error\n");
return ECC_UNCORRECTABLE_ERROR;
}
}
/*****************************************************************************
* readOnePage, call by MTD read routine.
*
* Parameters:
* vol : Pointer identifying drive
* address : Address to read from.
* buffer : buffer to Write from.
* length : number of bytes to read (up to sector size).
* modes : EDC flag etc.
*/
LOCAL FLStatus readOnePage (FLFlash* pVol,
CardAddress address, char FAR1 *buffer, int length, int modes)
{
short command, addressLSB;
int i;
/* Set Read Pointer first. */
if (modes & EXTRA)
{ /* Read spare area. */
command = 0x50;
addressLSB = address & 0x0F; /* Only have 16 bytes. */
}
else if(address & NFLASH_K9F_SECTORHALFSIZE)
{ /* 256-512 area. */
command = 0x01;
addressLSB = address & 0xFF;
}
else
{ /* 0-256 area. */
command = 0x00;
addressLSB = address & 0xFF;
}
OUT_WORD(FADDR_CLE, command);
OUT_WORD(FADDR_ALE, addressLSB);
OUT_WORD(FADDR_ALE, (unsigned short)(address >> 9));
OUT_WORD(FADDR_ALE, (unsigned short)(address >> 17));
sysUsDelay(20);
for(i=0; i *buffer++ = (unsigned char)IN_WORD(FADDR_BASE);
return flOK;
}
/*****************************************************************************
* writeOnePage, call by MTD Write routine.
*
* Parameters:
* vol : Pointer identifying drive
* address : Address to read from.
* buffer : buffer to Write from.
* length : number of bytes to read (up to sector size).
* modes : EDC flag etc.
*
*/
LOCAL FLStatus writeOnePage(FLFlash* pVol,
CardAddress address, const char FAR1 *buffer, int length, int modes)
{
short command, addressLSB;
int i;
if (flWriteProtected(pVol->socket))
return flWriteProtect;
/* Set Write Pointer first. */
if (modes & EXTRA) /* Program spare area. */
{
command = 0x50;
addressLSB = address & 0x0F; /* Only have 16 bytes. */
}
else if(address & NFLASH_K9F_SECTORHALFSIZE)
{ /* 256-512 area. */
command = 0x01;
addressLSB = address & 0xFF;
}
else
{ /* 0-256 area. */
command = 0x00;
addressLSB = address & 0xFF;
}
OUT_WORD(FADDR_CLE, command);
OUT_WORD(FADDR_CLE, 0x80);
OUT_WORD(FADDR_ALE, addressLSB);
OUT_WORD(FADDR_ALE, (unsigned short)(address >> 9));
OUT_WORD(FADDR_ALE, (unsigned short)(address >> 17));
for(i=0; i OUT_WORD(FADDR_BASE, (short)*buffer++);
OUT_WORD(FADDR_CLE, 0x10);
OUT_WORD(FADDR_CLE, 0x70);
while(1)
{
command = IN_WORD(FADDR_BASE);
if(command & 0x40) break;
}
/* Check status register. */
if(command & 0x1) return flWriteFault;
return flOK;
}
/* The Following is Core MTD methods - read, write and erase */
/*****************************************************************************
* nandMTDRead, Read data from flash. This routine is registered as MTD read routine.
*
* Parameters:
* vol : Pointer identifying drive
* address : Address to read from.
* buffer : buffer to read to.
* length : number of bytes to read (up to sector size).
* modes : EDC flag etc.
*
* Returns:
* FLStatus: 0 on success, otherwise failed.
*/
static FLStatus nandMTDRead( FLFlash* pVol,
CardAddress address, void FAR1 *buffer, int length, int modes)
{
char FAR1 *pReadPtr;
int readLen, i;
unsigned char verifyByte, verifyMask;
FLStatus status = flOK;
/* read in sectors; first and last might be partial */
int pagesize = modes & EXTRA ? NFLASH_K9F_TAILSIZE : NFLASH_K9F_SECTORSIZE;
DEBUG_FL("Read, addr:%x, buf:%x, len:%x, mode:%x.\n", address, buffer, length, modes);
if(address > pVol->chipSize)
printf("************************************ Read PTR exceed the chip size 0x%0x.\n******************", address);
readLen = pagesize - (address & (pagesize - 1));
pReadPtr = (char FAR1 *)buffer;
while(length > 0)
{
if (readLen > length) readLen = length;
readOnePage(pVol, address, pReadPtr, readLen, modes);
#ifdef VERIFY_AFTER_WRITE
readOnePage (pVol, address, (char FAR1 *)flReadback, readLen, modes); // Read again for compare.
for(i=0; i < readLen; i++)
{
if(pReadPtr[i] != flReadback[i]) // Compare, if error, try to correct it.
{
readOnePage (pVol, address+i, &verifyByte, 1, modes); // Read 3rd times.
verifyMask = pReadPtr[i] ^ flReadback[i]; // Mask right bit.
if((pReadPtr[i] & verifyMask) == (verifyByte & verifyMask))
{
printf("Read Error, 1st is right. At 0x%x, Read1=0x%x, Read2=0x%x, len=0x%x.\n", address+i, pReadPtr[i], flReadback[i], readLen);
taskDelay(100);
continue; // 1st == 3rd, 1st is right.
}
if((flReadback[i] & verifyMask) == (verifyByte & verifyMask)) // 2nd == 3rd, 2nd and 3rd is right, replace 1st data.
{
printf("Read Error, 2nd is right. At 0x%x, Read1=0x%x, Read2=0x%x, len=0x%x.\n", address+i, pReadPtr[i], flReadback[i], readLen);
taskDelay(100);
pReadPtr[i] = flReadback[i];
continue;
}
else
{
printf("Read Error, return faule. At 0x%x, Read1=0x%x, Read2=0x%x, len=0x%x.\n", address+i, pReadPtr[i], flReadback[i], readLen );
taskDelay(100);
return flReadFault; // 3 times not equal, return fault.
}
}
} // Verify OK.
#endif
length -= readLen;
address += readLen;
pReadPtr += readLen;
readLen = pagesize;
}
return status ;
}
/*****************************************************************************
* nandMTDWrite, Write datas to chip. This routine is registered as MTD write routine.
*
* Parameter:
* vol : Pointer identifying drive
* address : Address of sector to write to.
* buffer : buffer to write from.
* length : number of bytes to write (May larger than sector size).
* modes : OVERWRITE, EDC flags etc.
*
* Returns:
* FLStatus: 0 on success, otherwise failed.
*/
static FLStatus nandMTDWrite( FLFlash* pVol,
CardAddress address, const char FAR1 *buffer, int length, int modes)
{
int writeLen, i, verifyCount;
const char FAR1 *pWritePtr;
unsigned char verifyByte, verifyMask;
FLStatus status = flOK;
/* write in sectors; first and last might be partial sector*/
int pagesize = modes & EXTRA ? NFLASH_K9F_TAILSIZE : NFLASH_K9F_SECTORSIZE;
DEBUG_FL("Write, addr:%x, buf:%x, len:%x, mode:%x. ", address, buffer, length, modes);
if(address > pVol->chipSize)
printf("************************************ Write PTR exceed the chip size, 0x%x.\n******************", address);
writeLen = pagesize - ((unsigned short)address & (pagesize - 1));
pWritePtr = (const char FAR1 *)buffer;
for ( ; length > 0 ; )
{
if (writeLen > length) writeLen = length;
status = writeOnePage(pVol, address, pWritePtr, writeLen, modes);
if (status != flOK)
{
printf("\n\n************************Write Error at %x, %x, %x, %x. **********************\n\n",
address, buffer, length, modes);
taskDelay(100);
break;
}
#ifdef VERIFY_AFTER_WRITE
readOnePage (pVol, address, (char FAR1 *)flReadback, writeLen, modes); // Read back 1st for compare.
readOnePage (pVol, (address & 0xFFFFFFF0), (char FAR1 *)flExtraReadBack, NFLASH_K9F_TAILSIZE, EXTRA);
verifyCount=0;
for(i=0; i < writeLen; i++)
{
if(pWritePtr[i] != flReadback[i]) // Compare, if error, try to verify it.
{
readOnePage (pVol, address+i, &verifyByte, 1, modes); // Read 2rd times.
verifyMask = pWritePtr[i] ^ flReadback[i]; // Mask right bit.
if((pWritePtr[i] & verifyMask) == (verifyByte & verifyMask))
{
printf("Write verify Error, Corrected. At 0x%x, Write to = 0x%x.\n", address+i, pWritePtr[i]);
taskDelay(100);
continue; // Write == 2nd Read, Write is correct.
}
if((flReadback[i] & verifyMask) == (verifyByte & verifyMask)) // 1st Read == 2nd Read, Write is Error, Correct it at Extra area.
{
while(1)
if ((flExtraReadBack[verifyCount * 4] != 0xFF) && (flExtraReadBack[verifyCount*4 + 1] != 0xFF))
{
verifyCount ++; // This is ocuppied by other, Find next.
if(verifyCount > 3)
{
printf("Write Error, This page 0x%x must be bad.\n", (address >> 9));
taskDelay(100);
return flWriteFault; // This page must be bad.
}
}
else
{
flExtraReadBack[verifyCount*4] = 0; // Store Mark;
flExtraReadBack[verifyCount*4 + 1] = (unsigned char)(((address+i) & 0x100) ? 0x1 : 0); // Store Address MSB
flExtraReadBack[verifyCount*4 + 2] = (unsigned char)((address+i) & 0xFF); // Store Address LSB
flExtraReadBack[verifyCount*4 + 3] = pWritePtr[i]; // Store Data.
printf("Write Error, Store data 0x%x at 0x%x, Read back=0x%x.\n", pWritePtr[i], address+i, flReadback[i]);
taskDelay(100);
break;
}
}
else // 2 times read is not equal, return fault.
{
printf("Write Error At 0x%x, Write to = 0x%x, Read back = 0x%x.\n", address+i, pWritePtr[i], flReadback[i] );
taskDelay(100);
return flWriteFault;
}
}
}
if(verifyCount) // Write Back verify value.
writeOnePage(pVol, (address & 0xFFFFFFF0), (char FAR1 *)flExtraReadBack, NFLASH_K9F_TAILSIZE, EXTRA);
#endif
length -= writeLen;
address += writeLen;
pWritePtr += writeLen;
writeLen = pagesize;
}
DEBUG_FL("Done.\n");
return status;
}
/*****************************************************************************
* nandMTDErase, Erase number of blocks. This routine is registered as MTD erase routine.
*
* Parameters:
* vol : Pointer identifying drive
* blockNo : First block to erase.
* blocksToErase : Number of blocks to erase.
*
* Returns:
* FLStatus : 0 on success, otherwise failed.
*
*/
static FLStatus nandMTDErase( FLFlash* pVol, int blockNo, int blocksToErase)
{
int i;
char status;
DEBUG_FL("Erase, from:%x, num:%x. ", blockNo, blocksToErase);
if (flWriteProtected(pVol->socket)) return flWriteProtect;
/*
if ((blockNo + blocksToErase) > BLOCK_NUM )
return flBadParameter;
*/
blockNo *= PAGES_PER_BLOCK; /* Change to page. */
for ( i=0; i < blocksToErase; i++, blockNo+=PAGES_PER_BLOCK )
{
OUT_WORD(FADDR_CLE, 0x60);
OUT_WORD(FADDR_ALE, (short)(blockNo & 0xff)); /* A9-A23 */
OUT_WORD(FADDR_ALE, (short)(blockNo >> 8));
OUT_WORD(FADDR_CLE, 0xD0);
OUT_WORD(FADDR_CLE, 0x70);
while(1)
{
taskDelay(1);
status = IN_WORD(FADDR_BASE);
if(status & 0x40) break;
}
if(status & 0x1)
{
DEBUG_FL("\n\n*****************************Debug: erase block 0x%x failed.**************************\n\n", (blockNo/PAGES_PER_BLOCK));
/*nfChipReset(); If Erase Error, Reset Chip. */
return flWriteFault;
}
} /* block loop */
DEBUG_FL("Done.\n");
return flOK;
}
/*****************************************************************************
* nandMTDMap, Map through buffer. This routine is registered as MTD map routine.
*
* Parameters:
* vol : Pointer identifying drive
* address : Flash address to be mapped.
* length : number of bytes to map.
*
* Returns:
* Pointer to the buffer data was mapped to.
*/
static void FAR0 * nandMTDMap ( FLFlash* pVol, CardAddress address, int length )
{
DEBUG_FL("Map___");
nandMTDRead(pVol, address, flDataBuffer, length, 0);
pVol->socket->remapped = TRUE;
return (void FAR0 *)flDataBuffer;
}
/*****************************************************************************
* cdsnIdentify, Identify flash. This routine is registered as MTD identification routine.
*
* Returns:
* FLStatus: 0 on success, otherwise failed.
*/
FLStatus cdsnIdentify(FLFlash* pVol)
{
unsigned char byte;
unsigned short value;
OUT_WORD(FADDR_CLE, 0xFF); /* Reset chip first. */
taskDelay(1);
OUT_WORD(FADDR_CLE, 0x90);
OUT_WORD(FADDR_ALE, 0x00);
byte = (char)IN_WORD(FADDR_BASE);
value = byte * 256;
byte = (char)IN_WORD(FADDR_BASE);
value += byte;
DEBUG_FL("Identfy, Flash ID:%04x.\n", value);
switch(value)
{
case NFLASH_K9F2808U0X:
pVol->type = NFLASH_K9F2808U0X;
pVol->chipSize = NFL_K9F2808_CHIPSIZE; /* 16MB */
pVol->flags |= BIG_PAGE;
break;
case NFLASH_K9F5608U0X:
pVol->type = NFLASH_K9F5608U0X;
pVol->chipSize = NFL_K9F5608_CHIPSIZE; /* 32MB */
pVol->flags |= BIG_PAGE;
break;
default: /* No chip identified */
DEBUG_FL("Debug: Did not identify flash media, id:0x%x.\n", value);
return flUnknownMedia;
}
/* set flash parameters*/
flSetWindowBusWidth(pVol->socket, 8);/* use 8-bits bus */
flSetWindowSpeed(pVol->socket, 120); /* 120 nsec. */
flSetWindowSize(pVol->socket, 2); /* 64KB, 4 KBytes unit */
pVol->interleaving = 1; /* */
pVol->noOfChips = 1; /* Only have 1 chip */
pVol->erasableBlockSize = PAGES_PER_BLOCK * NFLASH_K9F_SECTORSIZE;
/* Register our flash handlers */
pVol->write = nandMTDWrite;
pVol->erase = nandMTDErase;
/* pVol->read = nandMTDRead;*/
pVol->map = nandMTDMap;
pVol->flags |= SUSPEND_FOR_WRITE; /*NFTL_ENABLED; mask at 20040905*/
return flOK;
}