📄 nflash.c
字号:
/*
*******************************************************************************
* Advanced Reality Tech. Inc. *
* Copyright (c) 2001, All Rights Reserved *
* *
* nflash module. *
* *
* File : nflash.C *
* By : thhuang *
* *
* History : 2001/11/01 File created. *
* 2002/01/11 check and set bad block added. *
* 2002/01/18 Sequential read supported. *
* 2002/08/01 Options for AR2000, AR2001 and AR2010. *
* *
*******************************************************************************
*/
#include "../include/nflash.h"
unsigned int seqIn, seqOut;
unsigned char *seqAddr;
static void nfshCommandLatch(unsigned char cmd);
static void nfshAddressLatch(unsigned long offset);
static void nfshBlockAddressLatch(unsigned long offset);
static void nfshInputDataLatch(unsigned char data[]);
static void nfshReadDataLatch(unsigned char data[]);
static unsigned char nfshStatusRead();
static unsigned int CountZero( unsigned char data );
//************************************** jason
//#define ECC_DEBUG 1
//#define ECC_CHECK 1 // if didn't define ECC_CHECK , then use the checksum method
#define K8M_byte 8*1024*1024
#define K16M_byte 16*1024*1024
#define K32M_byte 32*1024*1024
#define K64M_byte 64*1024*1024
#define K128M_byte 128*1024*1024
//***********************************************************
// Since NAND_File system structure , we only support the chip (block erase size=16k bytes)
// We don't support 1M,2M,4M,and 8M bytes NAND flash card .
// Note : The prg_cycle was different between (16M, 32M) and (64M, 128M).
flash_chip flash_table[] =
{
// evice_id prg_cycle block_size total_size device_name
0xece6 ,0 , 8*1024 , K8M_byte , "K9f6408" , //Samsung 8M
0xec73 ,0 , 16*1024 , K16M_byte , "K9f2808" , //Samsung 16M
0xec75 ,0 , 16*1024 , K32M_byte , "K9f5608" , //Samsung 32M
0xec76 ,1 , 16*1024 , K64M_byte , "K9d1208" , //Samsung 64M
0xec79 ,1 , 16*1024 , K128M_byte , "K9d1G08" , //Samsung 128M
0x98e6 ,0 , 8*1024 , K8M_byte , "TC58NS64" , //Toshiba 8M
0x9873 ,0 , 16*1024 , K16M_byte , "TC58NS128" , //Toshiba 16M
0x9875 ,0 , 16*1024 , K32M_byte , "TC58NS256" , //Toshiba 32M
0x9876 ,1 , 16*1024 , K64M_byte , "TH58NS512" , //Toshiba 64M
0x9879 ,1 , 16*1024 , K128M_byte , "TH58NS100" , //Toshiba 128M
0 ,0 ,0 ,0 ,0
};
flash_chip *current_nand_chip ;
//**********************************************************
//********************************************************
// Input : 256 bytes of data
// Output : 3 bytes of ECC code
// bit0 : p1b
// bit1 : p1
// bit2 : p2b
// bit3 : p2
// bit4 : p4b
// bit5 : p4
//
// bit8 : p8b
// bit9 : p8
// bit10 : p16b
// bit11 : p16
// bit12 : p32b
// bit13 : p32
// bit14 : p64b
// bit15 : p64
// bit16 : p128b
// bit17 : p128
// bit18 : p256b
// bit19 : p256
// bit20 : p512b
// bit21 : p512
// bit22 : p1024b
// bit23 : p1024
//
//********************************************************
// void ecc_gen(unsigned char *in_dat,unsigned char *out_dat)
#ifdef ECC_CHECK
void ecc_gen(unsigned char *in_dat , unsigned char *out_dat)
{
unsigned short ii,jj ;
unsigned char b_dat[8] ,temp , cur_ecc;
unsigned char ecc_dat[22] ;
for (ii=0;ii<22;ii++)
ecc_dat[ii] = 0 ;
for (ii=0;ii<256;ii++)
{
cur_ecc = 0 ;
temp = in_dat[ii] ;
for (jj=0;jj<8;jj++)
{
b_dat[jj] = (temp %2) ;
cur_ecc ^= b_dat[jj] ;
temp = temp >>1;
}
ecc_dat[0] ^= b_dat[0]^b_dat[2]^b_dat[4]^b_dat[6] ; //* p1b
ecc_dat[1] ^= b_dat[1]^b_dat[3]^b_dat[5]^b_dat[7] ; //* p1
ecc_dat[2] ^= b_dat[0]^b_dat[1]^b_dat[4]^b_dat[5] ; //* p2b
ecc_dat[3] ^= b_dat[2]^b_dat[3]^b_dat[6]^b_dat[7] ; //* p2
ecc_dat[4] ^= b_dat[0]^b_dat[1]^b_dat[2]^b_dat[3] ; //* p4b
ecc_dat[5] ^= b_dat[4]^b_dat[5]^b_dat[6]^b_dat[7] ; //* p4
if (ii & 0x01)
ecc_dat[9] ^= cur_ecc ; //* p8
else
ecc_dat[8] ^= cur_ecc ; //* p8b
if (ii & 0x02)
ecc_dat[11] ^= cur_ecc ; //* p16
else
ecc_dat[10] ^= cur_ecc ; //* p16b
if (ii & 0x04)
ecc_dat[13] ^= cur_ecc ; //* p32
else
ecc_dat[12] ^= cur_ecc ; //* p32b
if (ii & 0x08)
ecc_dat[15] ^= cur_ecc ; //* p64
else
ecc_dat[14] ^= cur_ecc ; //* p64b
if (ii & 0x10)
ecc_dat[17] ^= cur_ecc ; //* p128
else
ecc_dat[16] ^= cur_ecc ; //* p128b
if (ii & 0x20)
ecc_dat[19] ^= cur_ecc ; //* p256
else
ecc_dat[18] ^= cur_ecc ; //* p256b
if (ii & 0x40)
ecc_dat[21] ^= cur_ecc ; //* p512
else
ecc_dat[20] ^= cur_ecc ; //* p512b
if (ii & 0x80)
ecc_dat[23] ^= cur_ecc ; //* p1024
else
ecc_dat[22] ^= cur_ecc ; //* p1024b
}
out_dat[0]=0 ;
out_dat[0] |= ecc_dat[0]|(ecc_dat[1]<<1)|(ecc_dat[2]<<2);
out_dat[0] |= (ecc_dat[3]<<3)|(ecc_dat[4]<<4)|(ecc_dat[5]<<5) ;
out_dat[1] = 0 ;
out_dat[1] |= ecc_dat[8]|(ecc_dat[9]<<1)|(ecc_dat[10]<<2)|(ecc_dat[11]<<3) ;
out_dat[1] |= (ecc_dat[12]<<4)|(ecc_dat[13]<<5)|(ecc_dat[14]<<6)|(ecc_dat[15]<<7);
out_dat[2] = 0 ;
out_dat[2] |= ecc_dat[16]|(ecc_dat[17]<<1)|(ecc_dat[18]<<2)|(ecc_dat[19]<<3) ;
out_dat[2] |= (ecc_dat[20]<<4)|(ecc_dat[21]<<5)|(ecc_dat[22]<<6)|(ecc_dat[23]<<7) ;
}
#else
void ecc_gen(unsigned char *in_dat , unsigned char *out_dat)
{
unsigned long checksum ;
unsigned short ii ;
checksum = 0 ;
for (ii=0;ii<256;ii++)
checksum += in_dat[ii] ;
checksum += 0xff ;
for (ii=0;ii<3;ii++)
{
out_dat[ii] = (checksum & 0xff) ;
checksum = checksum >>8 ;
}
}
#endif
void check_busy(void)
{
unsigned long kk=0 ;
#ifdef AR2000
*(unsigned int *) _READYpoint &= 0x0fdfdfdfd ; // turn on SPS_RXD to be input
*(unsigned int *) _READYpoint |= 0x02020000 ; // turn on SPS_RXD to be input
#ifdef TARGET_BOARD_PR2000
while (!((*(unsigned int *) _READYpoint) & 0x02)) // check SPS_RXD
#else
while (!((*(unsigned int *) _READYpoint) & 0x20)) // check SPS_RXD
#endif
#else
#ifdef NANDBOOT
while (!((*(unsigned int *) _READYpoint) & 0x08)) // check SPS_RXD, P0.3
#else//NANDBOOT
#ifdef TARGET_BOARD_PR2001
while (!((*(unsigned int *) _READYpoint) & 0x02)) // check SPS_RXD
#elif defined(TARGET_BOARD_PR2001B) || defined(TARGET_BOARD_PR2001E) || defined(TARGET_BOARD_CHIPMOS) || defined(TARGET_BOARD_PR2001C) || defined(TARGET_BOARD_BR2001D)
while (!((*(unsigned int *) _READYpoint) & 0x08)) // check SPS_RXD
#else
while (!((*(unsigned int *) _READYpoint) & 0x08)) // check SPS_RXD
#endif
#endif//NORBOOT
#endif
{
if (kk++ >5000)
break ;
}
}
static void nfshCommandLatch(unsigned char cmd)
{
#ifdef AR2000
NFLASH_CLE = cmd;
#else
NFLASH_ALE_LOW;
NFLASH_CLE_HIGH;
NFLASH_CLE = cmd;
NFLASH_CLE_LOW;
#endif
}
static void nfshAddressLatch(unsigned long offset)
{
unsigned char addr7, addr16, addr24,addr32;
addr7 = (unsigned char)offset & 0xff;
addr16 = (unsigned char)(offset >> 9) & 0xff;
addr24 = (unsigned char)(offset >> 17) & 0xff;
addr32 = (unsigned char)(offset >> 25) & 0xff;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_HIGH;
#endif
NFLASH_ALE = addr7;
NFLASH_ALE = addr16;
NFLASH_ALE = addr24;
if (current_nand_chip->prg_addr)
{
NFLASH_ALE = addr32;
}
#ifndef AR2000
NFLASH_ALE_LOW;
#endif
}
static void nfshBlockAddressLatch(unsigned long offset)
{
unsigned char addr16, addr24 , addr32;
addr16 = (unsigned char)(offset >> 9) & 0xff;
addr24 = (unsigned char)(offset >> 17) & 0xff;
addr32 = (unsigned char)(offset >> 25) & 0xff;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_HIGH;
#endif
NFLASH_ALE = addr16;
NFLASH_ALE = addr24;
if (current_nand_chip->prg_addr)
{
NFLASH_ALE = addr32;
}
#ifndef AR2000
NFLASH_ALE_LOW;
#endif
}
static void nfshInputDataLatch(unsigned char data[])
{
register int i;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_LOW;
#endif
for(i=0; i<NFLASH_FRAME_SIZE; i++) {
NFLASH_DATA_WRITE = data[i];
}
}
static void nfshReadDataLatch(unsigned char data[])
{
register unsigned int readIndex;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_LOW;
#endif
for(readIndex=0; readIndex<NFLASH_FRAME_SIZE; readIndex++)
{
data[readIndex] = NFLASH_DATA_READ;
}
}
static void nfshReadDataLatchSeq(unsigned char data[])
{
register unsigned int readIndex;
register unsigned char readTemp;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_LOW;
#endif
for(readIndex=0; readIndex<NFLASH_FRAME_SIZE; readIndex++)
{
data[readIndex] = NFLASH_DATA_READ;
}
for(readIndex=NFLASH_FRAME_SIZE; readIndex<NFLASH_FRAME_SIZE+16; readIndex++)
{
readTemp = NFLASH_DATA_READ;
}
}
static void nfshReadSpareLatch(unsigned char data[])
{
register int i;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_LOW;
#endif
for(i=0; i<16; i++)
{
data[i] = NFLASH_DATA_READ;
}
}
// jason
static void nfshWriteSpareLatch(unsigned char data[])
{
register int i;
#ifndef AR2000
NFLASH_CLE_LOW;
NFLASH_ALE_LOW;
#endif
for(i=0; i<16; i++)
{
NFLASH_DATA_WRITE = data[i];
}
}
static unsigned char nfshStatusRead()
{
int i;
unsigned char status;
nfshCommandLatch(NFLASH_STATUS_READ);
status = NFLASH_DATA_READ;
return status;
}
static unsigned int CountZero( unsigned char data )
{
unsigned int Counter=0;
unsigned char Mask = 0x01;
while ( Mask )
{
if ( (data & Mask) == 0x00 )// Find zero
Counter++;
Mask = Mask << 1;
}
return Counter;
}
unsigned long nfshInit()
{
int chip_ID ;
unsigned short cou=0 ;
#ifndef AR2000
// configure device #4( PR2001 is #2 )
*(unsigned int *) NFLASH_DEVICE = 0x10000007;
#ifdef NANDBOOT
// switch DATAQ to be Nandflash R/B, input
*(unsigned int *) _READYpoint &= 0x00f7f7f7;
*(unsigned int *) _READYpoint |= 0x08080000;
// configure GPIO2, GPIO1, GPIO0, corresponds to CLE, ALE and Cs repectively
*(unsigned int *) (0xbfbf00a0) &= 0xf8f8f8f8;
*(unsigned int *) (0xbfbf00a0) |= 0x00070701;
#else//NANDBOOT
#ifdef TARGET_BOARD_PR2001
// switch DATAQ to be Nandflash R/B, input
*(unsigned int *) _READYpoint &= 0xfdfdfdfd;
*(unsigned int *) _READYpoint |= 0x02020000;
// configure SM_T, SM_R, SM_CLK as GPIO output, corresponds to CLE, ALE and Cs repectively
*(unsigned int *) (0xbfbf00b0) &= 0xcfcfcfcf;
*(unsigned int *) (0xbfbf00b0) |= 0x00303000;
NFLASH_DIS_CE;
#elif defined(TARGET_BOARD_PR2001B) || defined(TARGET_BOARD_PR2001E) || defined(TARGET_BOARD_CHIPMOS) || defined(TARGET_BOARD_PR2001C) || defined(TARGET_BOARD_BR2001D)
// switch DATAQ to be Nandflash R/B, input
*(unsigned int *) _READYpoint &= 0xf7f7f7f7;
*(unsigned int *) _READYpoint |= 0x08080000;
// configure SM_T, SM_R, SM_CLK as GPIO output, corresponds to CLE, ALE and Cs respectively
*(unsigned int *) (0xbfbf00a0) &= 0xf9f9f9f9;
*(unsigned int *) (0xbfbf00a0) |= 0x00060600;
NFLASH_DIS_CE;
#else
// switch DATAQ to be Nandflash R/B, input
*(unsigned int *) _READYpoint &= 0x00f7f7f7;
*(unsigned int *) _READYpoint |= 0x08080000;
// configure SM_T, SM_R, SM_CLK as GPIO output, corresponds to CLE, ALE and Cs respectively
*(unsigned int *) (0xbfbf00b0) &= 0xc7c7c7c7;
*(unsigned int *) (0xbfbf00b0) |= 0x00383808;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -