📄 nanddriver.c
字号:
/*----------------------------------------------------------------------*/
static void tffsset16 (unsigned char FAR0 *dst,
unsigned char val,
int len)
{
register unsigned short wval = ((unsigned short)val << 8) | val;
register int i = 0;
/* set data in 16-bit words */
for (i = 0; i < (len >> 1); i++)
*((unsigned short *) dst + i) = wval;
/* set last byte (if any) */
if (len & 1)
*(dst + len-1) = val;
}
/*----------------------------------------------------------------------*/
/* m a p C o n t I n t e r f a c e */
/* */
/* Select flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address in flash. */
/* */
/* Returns: */
/* Pointer to the mapped window. */
/* */
/*----------------------------------------------------------------------*/
static Interface mapContInterface(FLFlash vol, CardAddress address)
{
Interface interface = (Interface) flMap(vol.socket,(CardAddress)0);
LEushort tmp;
toLE2(*((LEushort FAR0 *) &tmp), (unsigned short)(address / (vol.chipSize * vol.interleaving)));
/* Select flash device with 16-bit write */
*((unsigned short *) &interface->deviceSelector) = *((unsigned short *) &tmp);
return interface;
}
/*----------------------------------------------------------------------*/
/* w a i t F o r R e a d y */
/* */
/* Wait for the selected device to be ready. */
/* */
/* Parameters: */
/* Interface : Pointer tot the window. */
/* */
/* Returns: */
/* TRUE if device is ready, FALSE if timeout error. */
/* */
/*----------------------------------------------------------------------*/
static FLBoolean waitForReady (Interface interface)
{
int i;
for( i = 0; i < 20000; i++)
{
if( (~interface->signals.w & DBL(RB)) == 0)
return TRUE ; /* ready at last..*/
}
#ifdef DEBUG_PRINT
DEBUG_PRINT("Debug: timeout error in NFDC 2048.\n");
#endif
return FALSE; /* timeout error */
}
/*----------------------------------------------------------------------*/
/* c o m m a n d */
/* */
/* Latch command byte to selected flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* Interface : Pointer to window. */
/* code : Command to set. */
/* */
/*----------------------------------------------------------------------*/
static void command(FLFlash vol, Interface interface, unsigned char code)
{
interface->signals.w = DBL( CLE | NOT_WP | CE ) ;
if ( vol.interleaving == 1 ) /* 8-bit */
interface->io[0].b = code ;
else /* 16-bit */
interface->io[0].w = DBL( code ) ;
interface->signals.w = DBL( NOT_WP ) ;
}
#endif
/*----------------------------------------------------------------------*/
/* m a k e C o m m a n d */
/* */
/* Set Page Pointer to Area A, B or C in page. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* cmd : receives command relevant to area */
/* addr : receives the address to the right area. */
/* modes : mode of operation (EXTRA ...) */
/* */
/*----------------------------------------------------------------------*/
static void makeCommand (FLFlash vol, PointerOp *cmd, CardAddress *addr , int modes )
{
unsigned short offset;
if ( !(vol.flags & BIG_PAGE) )
{
if (modes & EXTRA) {
offset = *addr & (SECTOR_SIZE - 1);
*cmd = AREA_C;
if (vol.interleaving == 1) {
if (offset < 8) /* First half of extra area */
*addr += 0x100; /* ... assigned to 2nd page */
else /* Second half of extra area */
*addr -= 8; /* ... assigned to 1st page */
}
}
else
*cmd = AREA_A;
}
else
{
offset = (unsigned short)(*addr) & thisVars->pageMask ; /* offset within device Page */
*addr -= offset; /* align at device Page*/
if (vol.interleaving == 2 && offset >= 512)
offset += 16; /* leave room for 1st extra area */
if (modes & EXTRA)
offset += SECTOR_SIZE;
if ( offset < thisVars->pageAreaSize ) /* starting in area A*/
*cmd = AREA_A ;
else if ( offset < thisVars->pageSize ) /* starting in area B */
*cmd = AREA_B ;
else /* got into area C*/
*cmd = AREA_C ;
offset &= (thisVars->pageAreaSize - 1) ; /* offset within area of device Page*/
*addr += offset ;
}
}
/*----------------------------------------------------------------------*/
/* s e t A d d r e s s */
/* */
/* Latch address to selected flash device. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* Interface : Pointer to window. */
/* address : address to set. */
/* */
/*----------------------------------------------------------------------*/
static void setAddress(FLFlash vol, CardAddress address )
{
address &= (vol.chipSize * vol.interleaving - 1) ; /* address within flash device*/
address /= vol.interleaving ; /* .................... chip */
if ( vol.flags & BIG_PAGE )
{
/*
bits 0..7 stays as are
bit 8 is thrown away from address
bits 31..9 -> bits 30..8
*/
address = ((address >> 9) << 8) | ((unsigned char)address) ;
}
/* send address to flash in the following sequence: */
/* bits 7...0 first */
/* bits 15...8 next */
/* bits 23..16 finally */
WRITE_NAND_ADDRESS((unsigned char)address);
WRITE_NAND_ADDRESS((unsigned char)(address >> 8));
WRITE_NAND_ADDRESS((unsigned char)(address >> 16));
#if 0
TFFS_CDSN_DEBUG_PRINT((DEBUG_TFFS_READ | DEBUG_TFFS_WRITE), ("%s: col %x row1 %x row2 %x.\n",
__FUNCTION__,
(unsigned char)address,
(unsigned char)(address >> 8),
(unsigned char)(address >> 16)));
#endif
}
/*----------------------------------------------------------------------*/
/* r e a d C o m m a n d */
/* */
/* Issue read command. */
/* */
/* Parametes: */
/* vol : Pointer identifying drive */
/* Interface : Pointer to window. */
/* cmd : Command to issue (according to area). */
/* addr : address to read from. */
/* */
/*----------------------------------------------------------------------*/
static void readCommand (FLFlash vol, PointerOp cmd, CardAddress addr)
{
WRITE_NAND_COMMAND(cmd);
#if 0
TFFS_CDSN_DEBUG_PRINT(DEBUG_TFFS_READ, ("%s: cmd %x.\n", __FUNCTION__, cmd));
#endif
setAddress (&vol, addr);
nand_flash_wait_ready();
}
/*----------------------------------------------------------------------*/
/* w r i t e C o m m a n d */
/* */
/* Issue write command. */
/* */
/* Parametes: */
/* vol : Pointer identifying drive */
/* interface : Pointer to window. */
/* cmd : Command to issue (according to area). */
/* addr : address to write to. */
/* */
/*----------------------------------------------------------------------*/
static void writeCommand (FLFlash vol, PointerOp cmd, CardAddress addr)
{
if (vol.flags & FULL_PAGE)
{
nand_flash_reset_chip();
}
WRITE_NAND_COMMAND(cmd); /* move flash pointer to respective area of the page */
#if 0
TFFS_CDSN_DEBUG_PRINT(DEBUG_TFFS_WRITE, ("%s: cmd %x.\n", __FUNCTION__, cmd));
#endif
WRITE_NAND_COMMAND(CMD_WRITE); /* start data loading for write */
setAddress (&vol, addr) ;
}
/*----------------------------------------------------------------------*/
/* w r i t e E x e c u t e */
/* */
/* Execute write. */
/* */
/* Parametes: */
/* vol : Pointer identifying drive */
/* interface : Pointer to window. */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
static FLStatus writeExecute (FLFlash vol)
{
WRITE_NAND_COMMAND(CMD_WRITE2); /* execute page program*/
if (nand_flash_wait_ready() == ERROR)
{
TFFS_CDSN_DEBUG_PRINT(DEBUG_TFFS_ALWAYS, ("%s: time out.\n", __FUNCTION__));
return flTimedOut;
}
if( readStatus() & NAND_FLASH_IO_0)
{
TFFS_CDSN_DEBUG_PRINT(DEBUG_TFFS_ALWAYS, ("%s: write failed.\n", __FUNCTION__));
return flWriteFault ;
}
return flOK ;
}
/*----------------------------------------------------------------------*/
/* r e a d O n e S e c t o r */
/* */
/* Read up to one 512-byte block from flash. */
/* */
/* 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 readOneSector (FLFlash vol,
CardAddress address, /* starting flash address*/
char FAR1 *buffer, /* target buffer */
int length, /* bytes to read */
int modes) /* EDC flag etc.*/
{
FLStatus status = flOK;
PointerOp cmd;
CardAddress addr = address;
ENABLE_NAND_CE;
/* move flash pointer to areas A,B or C of page*/
makeCommand (&vol, &cmd, &addr, modes) ;
readCommand (&vol, cmd, addr);
tffscpy8b((unsigned char*)buffer, (const unsigned char *) AT91_NANDFLASH_BASE, length );
DISABLE_NAND_CE;
return status;
}
/*----------------------------------------------------------------------*/
/* w r i t e O n e S e c t o r */
/* */
/* Write data in one 512-byte block to flash. */
/* Assuming that EDC mode never requested on partial block writes. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* address : Address of sector to write to. */
/* buffer : buffer to write from. */
/* length : number of bytes to write (up to sector size). */
/* modes : OVERWRITE, EDC flags etc. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
static FLStatus writeOneSector(FLFlash vol,
CardAddress address, /* target flash addres */
const char FAR1 *buffer, /* source RAM buffer */
int length, /* bytes to write (up to BLOCK) */
int modes) /* OVERWRITE, EDC flags etc. */
{
FLStatus status;
PointerOp cmd;
if (flWriteProtected(vol.socket))
return flWriteProtect;
ENABLE_NAND_CE;
/* move flash pointer to areas A,B or C of page */
makeCommand (&vol, &cmd, &address, modes) ;
writeCommand(&vol, cmd, address);
/* load data and syndrom*/
tffscpy8b((unsigned char FAR0 *)AT91_NANDFLASH_BASE,
(const unsigned char *)buffer,
length);
if(modes & EDC)
{
unsigned short extraBytes[SYNDROM_BYTES / sizeof(unsigned short) + 1];
/* Read the ECC syndrom*/
extraBytes[0] = extraBytes[1] = extraBytes[2] = 0xffff;
extraBytes[SYNDROM_BYTES / sizeof(unsigned short)] = 0x5555; /* Anand mark */
tffscpy8b((unsigned char FAR0 *) AT91_NANDFLASH_BASE, (const unsigned char *)extraBytes,
sizeof extraBytes);
}
status = writeExecute(&vol);
DISABLE_NAND_CE;
return status;
}
/*觚
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -