@ -16,7 +16,7 @@
*
*
* Interface to generic NAND code for M - Systems DiskOnChip devices
* Interface to generic NAND code for M - Systems DiskOnChip devices
*
*
* $ Id : diskonchip . c , v 1.45 2005 / 01 / 05 18 : 05 : 14 dwmw2 Exp $
* $ Id : diskonchip . c , v 1.55 2005 / 11 / 07 11 : 14 : 30 gleixner Exp $
*/
*/
# include <common.h>
# include <common.h>
@ -39,13 +39,13 @@
# include <linux/mtd/inftl.h>
# include <linux/mtd/inftl.h>
/* Where to look for the devices? */
/* Where to look for the devices? */
# ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS
# ifndef CONFIG_MTD_NAND_ DISKONCHIP_PROBE_ADDRESS
# define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0
# define CONFIG_MTD_NAND_ DISKONCHIP_PROBE_ADDRESS 0
# endif
# endif
static unsigned long __initdata doc_locations [ ] = {
static unsigned long __initdata doc_locations [ ] = {
# if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
# if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
# ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH
# ifdef CONFIG_MTD_NAND_ DISKONCHIP_PROBE_HIGH
0xfffc8000 , 0xfffca000 , 0xfffcc000 , 0xfffce000 ,
0xfffc8000 , 0xfffca000 , 0xfffcc000 , 0xfffce000 ,
0xfffd0000 , 0xfffd2000 , 0xfffd4000 , 0xfffd6000 ,
0xfffd0000 , 0xfffd2000 , 0xfffd4000 , 0xfffd6000 ,
0xfffd8000 , 0xfffda000 , 0xfffdc000 , 0xfffde000 ,
0xfffd8000 , 0xfffda000 , 0xfffdc000 , 0xfffde000 ,
@ -65,7 +65,7 @@ static unsigned long __initdata doc_locations[] = {
0xff000000 ,
0xff000000 ,
# elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
# elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
0xff000000 ,
0xff000000 ,
# # else
# else
# warning Unknown architecture for DiskOnChip. No default probe locations defined
# warning Unknown architecture for DiskOnChip. No default probe locations defined
# endif
# endif
0xffffffff } ;
0xffffffff } ;
@ -85,14 +85,10 @@ struct doc_priv {
struct mtd_info * nextdoc ;
struct mtd_info * nextdoc ;
} ;
} ;
/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL
MediaHeader . The spec says to just keep going , I think , but that ' s just
silly . */
# define MAX_MEDIAHEADER_SCAN 8
/* This is the syndrome computed by the HW ecc generator upon reading an empty
/* This is the syndrome computed by the HW ecc generator upon reading an empty
page , one with all 0xff for data and stored ecc code . */
page , one with all 0xff for data and stored ecc code . */
static u_char empty_read_syndrome [ 6 ] = { 0x26 , 0xff , 0x6d , 0x47 , 0x73 , 0x7a } ;
static u_char empty_read_syndrome [ 6 ] = { 0x26 , 0xff , 0x6d , 0x47 , 0x73 , 0x7a } ;
/* This is the ecc value computed by the HW ecc generator upon writing an empty
/* This is the ecc value computed by the HW ecc generator upon writing an empty
page , one with all 0xff for data . */
page , one with all 0xff for data . */
static u_char empty_write_ecc [ 6 ] = { 0x4b , 0x00 , 0xe2 , 0x0e , 0x93 , 0xf7 } ;
static u_char empty_write_ecc [ 6 ] = { 0x4b , 0x00 , 0xe2 , 0x0e , 0x93 , 0xf7 } ;
@ -103,7 +99,8 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
# define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
# define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
# define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
# define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
static void doc200x_hwcontrol ( struct mtd_info * mtd , int cmd ) ;
static void doc200x_hwcontrol ( struct mtd_info * mtd , int cmd ,
unsigned int bitmask ) ;
static void doc200x_select_chip ( struct mtd_info * mtd , int chip ) ;
static void doc200x_select_chip ( struct mtd_info * mtd , int chip ) ;
static int debug = 0 ;
static int debug = 0 ;
@ -115,23 +112,23 @@ module_param(try_dword, int, 0);
static int no_ecc_failures = 0 ;
static int no_ecc_failures = 0 ;
module_param ( no_ecc_failures , int , 0 ) ;
module_param ( no_ecc_failures , int , 0 ) ;
# ifdef CONFIG_MTD_PARTITIONS
static int no_autopart = 0 ;
static int no_autopart = 0 ;
module_param ( no_autopart , int , 0 ) ;
module_param ( no_autopart , int , 0 ) ;
# endif
# ifdef MTD_NAND_DISKONCHIP_BBTWRITE
static int show_firmware_partition = 0 ;
module_param ( show_firmware_partition , int , 0 ) ;
# ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE
static int inftl_bbt_write = 1 ;
static int inftl_bbt_write = 1 ;
# else
# else
static int inftl_bbt_write = 0 ;
static int inftl_bbt_write = 0 ;
# endif
# endif
module_param ( inftl_bbt_write , int , 0 ) ;
module_param ( inftl_bbt_write , int , 0 ) ;
static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS ;
static unsigned long doc_config_location = CONFIG_MTD_NAND_ DISKONCHIP_PROBE_ADDRESS ;
module_param ( doc_config_location , ulong , 0 ) ;
module_param ( doc_config_location , ulong , 0 ) ;
MODULE_PARM_DESC ( doc_config_location , " Physical memory address at which to probe for DiskOnChip " ) ;
MODULE_PARM_DESC ( doc_config_location , " Physical memory address at which to probe for DiskOnChip " ) ;
/* Sector size for HW ECC */
/* Sector size for HW ECC */
# define SECTOR_SIZE 512
# define SECTOR_SIZE 512
/* The sector bytes are packed into NB_DATA 10 bit words */
/* The sector bytes are packed into NB_DATA 10 bit words */
@ -213,8 +210,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
can be modified since pos is even */
can be modified since pos is even */
index = ( pos > > 3 ) ^ 1 ;
index = ( pos > > 3 ) ^ 1 ;
bitpos = pos & 7 ;
bitpos = pos & 7 ;
if ( ( index > = 0 & & index < SECTOR_SIZE ) | |
if ( ( index > = 0 & & index < SECTOR_SIZE ) | | index = = ( SECTOR_SIZE + 1 ) ) {
index = = ( SECTOR_SIZE + 1 ) ) {
val = ( uint8_t ) ( errval [ i ] > > ( 2 + bitpos ) ) ;
val = ( uint8_t ) ( errval [ i ] > > ( 2 + bitpos ) ) ;
parity ^ = val ;
parity ^ = val ;
if ( index < SECTOR_SIZE )
if ( index < SECTOR_SIZE )
@ -224,8 +220,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
bitpos = ( bitpos + 10 ) & 7 ;
bitpos = ( bitpos + 10 ) & 7 ;
if ( bitpos = = 0 )
if ( bitpos = = 0 )
bitpos = 8 ;
bitpos = 8 ;
if ( ( index > = 0 & & index < SECTOR_SIZE ) | |
if ( ( index > = 0 & & index < SECTOR_SIZE ) | | index = = ( SECTOR_SIZE + 1 ) ) {
index = = ( SECTOR_SIZE + 1 ) ) {
val = ( uint8_t ) ( errval [ i ] < < ( 8 - bitpos ) ) ;
val = ( uint8_t ) ( errval [ i ] < < ( 8 - bitpos ) ) ;
parity ^ = val ;
parity ^ = val ;
if ( index < SECTOR_SIZE )
if ( index < SECTOR_SIZE )
@ -261,7 +256,8 @@ static int _DoC_WaitReady(struct doc_priv *doc)
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
unsigned long timeo = jiffies + ( HZ * 10 ) ;
unsigned long timeo = jiffies + ( HZ * 10 ) ;
if ( debug ) printk ( " _DoC_WaitReady... \n " ) ;
if ( debug )
printk ( " _DoC_WaitReady... \n " ) ;
/* Out-of-line routine to wait for chip response */
/* Out-of-line routine to wait for chip response */
if ( DoC_is_MillenniumPlus ( doc ) ) {
if ( DoC_is_MillenniumPlus ( doc ) ) {
while ( ( ReadDOC ( docptr , Mplus_FlashControl ) & CDSN_CTRL_FR_B_MASK ) ! = CDSN_CTRL_FR_B_MASK ) {
while ( ( ReadDOC ( docptr , Mplus_FlashControl ) & CDSN_CTRL_FR_B_MASK ) ! = CDSN_CTRL_FR_B_MASK ) {
@ -306,7 +302,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc)
DoC_Delay ( doc , 2 ) ;
DoC_Delay ( doc , 2 ) ;
}
}
if ( debug ) printk ( " DoC_WaitReady OK \n " ) ;
if ( debug )
printk ( " DoC_WaitReady OK \n " ) ;
return ret ;
return ret ;
}
}
@ -316,7 +313,8 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
if ( debug ) printk ( " write_byte %02x \n " , datum ) ;
if ( debug )
printk ( " write_byte %02x \n " , datum ) ;
WriteDOC ( datum , docptr , CDSNSlowIO ) ;
WriteDOC ( datum , docptr , CDSNSlowIO ) ;
WriteDOC ( datum , docptr , 2 k_CDSN_IO ) ;
WriteDOC ( datum , docptr , 2 k_CDSN_IO ) ;
}
}
@ -331,35 +329,37 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
ReadDOC ( docptr , CDSNSlowIO ) ;
ReadDOC ( docptr , CDSNSlowIO ) ;
DoC_Delay ( doc , 2 ) ;
DoC_Delay ( doc , 2 ) ;
ret = ReadDOC ( docptr , 2 k_CDSN_IO ) ;
ret = ReadDOC ( docptr , 2 k_CDSN_IO ) ;
if ( debug ) printk ( " read_byte returns %02x \n " , ret ) ;
if ( debug )
printk ( " read_byte returns %02x \n " , ret ) ;
return ret ;
return ret ;
}
}
static void doc2000_writebuf ( struct mtd_info * mtd ,
static void doc2000_writebuf ( struct mtd_info * mtd , const u_char * buf , int len )
const u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int i ;
int i ;
if ( debug ) printk ( " writebuf of %d bytes: " , len ) ;
if ( debug )
printk ( " writebuf of %d bytes: " , len ) ;
for ( i = 0 ; i < len ; i + + ) {
for ( i = 0 ; i < len ; i + + ) {
WriteDOC_ ( buf [ i ] , docptr , DoC_2k_CDSN_IO + i ) ;
WriteDOC_ ( buf [ i ] , docptr , DoC_2k_CDSN_IO + i ) ;
if ( debug & & i < 16 )
if ( debug & & i < 16 )
printk ( " %02x " , buf [ i ] ) ;
printk ( " %02x " , buf [ i ] ) ;
}
}
if ( debug ) printk ( " \n " ) ;
if ( debug )
printk ( " \n " ) ;
}
}
static void doc2000_readbuf ( struct mtd_info * mtd ,
static void doc2000_readbuf ( struct mtd_info * mtd , u_char * buf , int len )
u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int i ;
int i ;
if ( debug ) printk ( " readbuf of %d bytes: " , len ) ;
if ( debug )
printk ( " readbuf of %d bytes: " , len ) ;
for ( i = 0 ; i < len ; i + + ) {
for ( i = 0 ; i < len ; i + + ) {
buf [ i ] = ReadDOC ( docptr , 2 k_CDSN_IO + i ) ;
buf [ i ] = ReadDOC ( docptr , 2 k_CDSN_IO + i ) ;
@ -374,7 +374,8 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd,
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int i ;
int i ;
if ( debug ) printk ( " readbuf_dword of %d bytes: " , len ) ;
if ( debug )
printk ( " readbuf_dword of %d bytes: " , len ) ;
if ( unlikely ( ( ( ( unsigned long ) buf ) | len ) & 3 ) ) {
if ( unlikely ( ( ( ( unsigned long ) buf ) | len ) & 3 ) ) {
for ( i = 0 ; i < len ; i + + ) {
for ( i = 0 ; i < len ; i + + ) {
@ -387,8 +388,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd,
}
}
}
}
static int doc2000_verifybuf ( struct mtd_info * mtd ,
static int doc2000_verifybuf ( struct mtd_info * mtd , const u_char * buf , int len )
const u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -408,12 +408,15 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
uint16_t ret ;
uint16_t ret ;
doc200x_select_chip ( mtd , nr ) ;
doc200x_select_chip ( mtd , nr ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_SETCLE ) ;
doc200x_hwcontrol ( mtd , NAND_CMD_READID ,
this - > write_byte ( mtd , NAND_CMD_READID ) ;
NAND_CTRL_CLE | NAND_CTRL_CHANGE ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_CLRCLE ) ;
doc200x_hwcontrol ( mtd , 0 , NAND_CTRL_ALE | NAND_CTRL_CHANGE ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_SETALE ) ;
doc200x_hwcontrol ( mtd , NAND_CMD_NONE , NAND_NCE | NAND_CTRL_CHANGE ) ;
this - > write_byte ( mtd , 0 ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_CLRALE ) ;
/* We cant' use dev_ready here, but at least we wait for the
* command to complete
*/
udelay ( 50 ) ;
ret = this - > read_byte ( mtd ) < < 8 ;
ret = this - > read_byte ( mtd ) < < 8 ;
ret | = this - > read_byte ( mtd ) ;
ret | = this - > read_byte ( mtd ) ;
@ -426,12 +429,13 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
} ident ;
} ident ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
doc200x_hwcontrol ( mtd , NAND_CTL_SETCLE ) ;
doc200x_hwcontrol ( mtd , NAND_CMD_READID ,
doc2000_write_byte ( mtd , NAND_CMD_READID ) ;
NAND_CTRL_CLE | NAND_CTRL_CHANGE ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_CLRCLE ) ;
doc200x_hwcontrol ( mtd , 0 , NAND_CTRL_ALE | NAND_CTRL_CHANGE ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_SETALE ) ;
doc200x_hwcontrol ( mtd , NAND_CMD_NONE ,
doc2000_write_byte ( mtd , 0 ) ;
NAND_NCE | NAND_CTRL_CHANGE ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_CLRALE ) ;
udelay ( 50 ) ;
ident . dword = readl ( docptr + DoC_2k_CDSN_IO ) ;
ident . dword = readl ( docptr + DoC_2k_CDSN_IO ) ;
if ( ( ( ident . byte [ 0 ] < < 8 ) | ident . byte [ 1 ] ) = = ret ) {
if ( ( ( ident . byte [ 0 ] < < 8 ) | ident . byte [ 1 ] ) = = ret ) {
@ -465,7 +469,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd)
printk ( KERN_DEBUG " Detected %d chips per floor. \n " , i ) ;
printk ( KERN_DEBUG " Detected %d chips per floor. \n " , i ) ;
}
}
static int doc200x_wait ( struct mtd_info * mtd , struct nand_chip * this , int state )
static int doc200x_wait ( struct mtd_info * mtd , struct nand_chip * this )
{
{
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -496,16 +500,15 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
/*ReadDOC(docptr, CDSNSlowIO); */
//ReadDOC(docptr, CDSNSlowIO);
/* 11.4.5 -- delay twice to allow extended length cycle */
/* 11.4.5 -- delay twice to allow extended length cycle */
DoC_Delay ( doc , 2 ) ;
DoC_Delay ( doc , 2 ) ;
ReadDOC ( docptr , ReadPipeInit ) ;
ReadDOC ( docptr , ReadPipeInit ) ;
/*return ReadDOC(docptr, Mil_CDSN_IO); */
//return ReadDOC(docptr, Mil_CDSN_IO);
return ReadDOC ( docptr , LastDataRead ) ;
return ReadDOC ( docptr , LastDataRead ) ;
}
}
static void doc2001_writebuf ( struct mtd_info * mtd ,
static void doc2001_writebuf ( struct mtd_info * mtd , const u_char * buf , int len )
const u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -518,8 +521,7 @@ static void doc2001_writebuf(struct mtd_info *mtd,
WriteDOC ( 0x00 , docptr , WritePipeTerm ) ;
WriteDOC ( 0x00 , docptr , WritePipeTerm ) ;
}
}
static void doc2001_readbuf ( struct mtd_info * mtd ,
static void doc2001_readbuf ( struct mtd_info * mtd , u_char * buf , int len )
u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -536,8 +538,7 @@ static void doc2001_readbuf(struct mtd_info *mtd,
buf [ i ] = ReadDOC ( docptr , LastDataRead ) ;
buf [ i ] = ReadDOC ( docptr , LastDataRead ) ;
}
}
static int doc2001_verifybuf ( struct mtd_info * mtd ,
static int doc2001_verifybuf ( struct mtd_info * mtd , const u_char * buf , int len )
const u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -567,36 +568,38 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
ret = ReadDOC ( docptr , Mplus_LastDataRead ) ;
ret = ReadDOC ( docptr , Mplus_LastDataRead ) ;
if ( debug ) printk ( " read_byte returns %02x \n " , ret ) ;
if ( debug )
printk ( " read_byte returns %02x \n " , ret ) ;
return ret ;
return ret ;
}
}
static void doc2001plus_writebuf ( struct mtd_info * mtd ,
static void doc2001plus_writebuf ( struct mtd_info * mtd , const u_char * buf , int len )
const u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int i ;
int i ;
if ( debug ) printk ( " writebuf of %d bytes: " , len ) ;
if ( debug )
printk ( " writebuf of %d bytes: " , len ) ;
for ( i = 0 ; i < len ; i + + ) {
for ( i = 0 ; i < len ; i + + ) {
WriteDOC_ ( buf [ i ] , docptr , DoC_Mil_CDSN_IO + i ) ;
WriteDOC_ ( buf [ i ] , docptr , DoC_Mil_CDSN_IO + i ) ;
if ( debug & & i < 16 )
if ( debug & & i < 16 )
printk ( " %02x " , buf [ i ] ) ;
printk ( " %02x " , buf [ i ] ) ;
}
}
if ( debug ) printk ( " \n " ) ;
if ( debug )
printk ( " \n " ) ;
}
}
static void doc2001plus_readbuf ( struct mtd_info * mtd ,
static void doc2001plus_readbuf ( struct mtd_info * mtd , u_char * buf , int len )
u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int i ;
int i ;
if ( debug ) printk ( " readbuf of %d bytes: " , len ) ;
if ( debug )
printk ( " readbuf of %d bytes: " , len ) ;
/* Start read pipeline */
/* Start read pipeline */
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
@ -615,18 +618,19 @@ static void doc2001plus_readbuf(struct mtd_info *mtd,
buf [ len - 1 ] = ReadDOC ( docptr , Mplus_LastDataRead ) ;
buf [ len - 1 ] = ReadDOC ( docptr , Mplus_LastDataRead ) ;
if ( debug & & i < 16 )
if ( debug & & i < 16 )
printk ( " %02x " , buf [ len - 1 ] ) ;
printk ( " %02x " , buf [ len - 1 ] ) ;
if ( debug ) printk ( " \n " ) ;
if ( debug )
printk ( " \n " ) ;
}
}
static int doc2001plus_verifybuf ( struct mtd_info * mtd ,
static int doc2001plus_verifybuf ( struct mtd_info * mtd , const u_char * buf , int len )
const u_char * buf , int len )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int i ;
int i ;
if ( debug ) printk ( " verifybuf of %d bytes: " , len ) ;
if ( debug )
printk ( " verifybuf of %d bytes: " , len ) ;
/* Start read pipeline */
/* Start read pipeline */
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
ReadDOC ( docptr , Mplus_ReadPipeInit ) ;
@ -652,7 +656,8 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int floor = 0 ;
int floor = 0 ;
if ( debug ) printk ( " select chip (%d) \n " , chip ) ;
if ( debug )
printk ( " select chip (%d) \n " , chip ) ;
if ( chip = = - 1 ) {
if ( chip = = - 1 ) {
/* Disable flash internally */
/* Disable flash internally */
@ -678,7 +683,8 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
int floor = 0 ;
int floor = 0 ;
if ( debug ) printk ( " select chip (%d) \n " , chip ) ;
if ( debug )
printk ( " select chip (%d) \n " , chip ) ;
if ( chip = = - 1 )
if ( chip = = - 1 )
return ;
return ;
@ -687,54 +693,42 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
chip - = ( floor * doc - > chips_per_floor ) ;
chip - = ( floor * doc - > chips_per_floor ) ;
/* 11.4.4 -- deassert CE before changing chip */
/* 11.4.4 -- deassert CE before changing chip */
doc200x_hwcontrol ( mtd , NAND_CTL_CLRNC E ) ;
doc200x_hwcontrol ( mtd , NAND_CMD_NONE , 0 | NAND_CTRL_CHANG E ) ;
WriteDOC ( floor , docptr , FloorSelect ) ;
WriteDOC ( floor , docptr , FloorSelect ) ;
WriteDOC ( chip , docptr , CDSNDeviceSelect ) ;
WriteDOC ( chip , docptr , CDSNDeviceSelect ) ;
doc200x_hwcontrol ( mtd , NAND_CTL_SETNC E ) ;
doc200x_hwcontrol ( mtd , NAND_CMD_NONE , NAND_NCE | NAND_CTRL_CHANG E ) ;
doc - > curchip = chip ;
doc - > curchip = chip ;
doc - > curfloor = floor ;
doc - > curfloor = floor ;
}
}
static void doc200x_hwcontrol ( struct mtd_info * mtd , int cmd )
# define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
static void doc200x_hwcontrol ( struct mtd_info * mtd , int cmd ,
unsigned int ctrl )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
switch ( cmd ) {
if ( ctrl & NAND_CTRL_CHANGE ) {
case NAND_CTL_SETNCE :
doc - > CDSNControl & = ~ CDSN_CTRL_MSK ;
doc - > CDSNControl | = CDSN_CTRL_CE ;
doc - > CDSNControl | = ctrl & CDSN_CTRL_MSK ;
break ;
if ( debug )
case NAND_CTL_CLRNCE :
printk ( " hwcontrol(%d): %02x \n " , cmd , doc - > CDSNControl ) ;
doc - > CDSNControl & = ~ CDSN_CTRL_CE ;
break ;
case NAND_CTL_SETCLE :
doc - > CDSNControl | = CDSN_CTRL_CLE ;
break ;
case NAND_CTL_CLRCLE :
doc - > CDSNControl & = ~ CDSN_CTRL_CLE ;
break ;
case NAND_CTL_SETALE :
doc - > CDSNControl | = CDSN_CTRL_ALE ;
break ;
case NAND_CTL_CLRALE :
doc - > CDSNControl & = ~ CDSN_CTRL_ALE ;
break ;
case NAND_CTL_SETWP :
doc - > CDSNControl | = CDSN_CTRL_WP ;
break ;
case NAND_CTL_CLRWP :
doc - > CDSNControl & = ~ CDSN_CTRL_WP ;
break ;
}
if ( debug ) printk ( " hwcontrol(%d): %02x \n " , cmd , doc - > CDSNControl ) ;
WriteDOC ( doc - > CDSNControl , docptr , CDSNControl ) ;
WriteDOC ( doc - > CDSNControl , docptr , CDSNControl ) ;
/* 11.4.3 -- 4 NOPs after CSDNControl write */
/* 11.4.3 -- 4 NOPs after CSDNControl write */
DoC_Delay ( doc , 4 ) ;
DoC_Delay ( doc , 4 ) ;
}
}
if ( cmd ! = NAND_CMD_NONE ) {
if ( DoC_is_2000 ( doc ) )
doc2000_write_byte ( mtd , cmd ) ;
else
doc2001_write_byte ( mtd , cmd ) ;
}
}
static void doc2001plus_command ( struct mtd_info * mtd , unsigned command , int column , int page_addr )
static void doc2001plus_command ( struct mtd_info * mtd , unsigned command , int column , int page_addr )
{
{
@ -757,9 +751,9 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
if ( command = = NAND_CMD_SEQIN ) {
if ( command = = NAND_CMD_SEQIN ) {
int readcmd ;
int readcmd ;
if ( column > = mtd - > oobblock ) {
if ( column > = mtd - > writesize ) {
/* OOB area */
/* OOB area */
column - = mtd - > oobblock ;
column - = mtd - > writesize ;
readcmd = NAND_CMD_READOOB ;
readcmd = NAND_CMD_READOOB ;
} else if ( column < 256 ) {
} else if ( column < 256 ) {
/* First 256 bytes --> READ0 */
/* First 256 bytes --> READ0 */
@ -794,7 +788,8 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
WriteDOC ( 0 , docptr , Mplus_WritePipeTerm ) ;
WriteDOC ( 0 , docptr , Mplus_WritePipeTerm ) ;
WriteDOC ( 0 , docptr , Mplus_WritePipeTerm ) ;
WriteDOC ( 0 , docptr , Mplus_WritePipeTerm ) ;
/* deassert ALE */
/* deassert ALE */
if ( command = = NAND_CMD_READ0 | | command = = NAND_CMD_READ1 | | command = = NAND_CMD_READOOB | | command = = NAND_CMD_READID )
if ( command = = NAND_CMD_READ0 | | command = = NAND_CMD_READ1 | |
command = = NAND_CMD_READOOB | | command = = NAND_CMD_READID )
WriteDOC ( 0 , docptr , Mplus_FlashControl ) ;
WriteDOC ( 0 , docptr , Mplus_FlashControl ) ;
}
}
@ -854,7 +849,8 @@ static int doc200x_dev_ready(struct mtd_info *mtd)
printk ( " not ready \n " ) ;
printk ( " not ready \n " ) ;
return 0 ;
return 0 ;
}
}
if ( debug ) printk ( " was ready \n " ) ;
if ( debug )
printk ( " was ready \n " ) ;
return 1 ;
return 1 ;
} else {
} else {
/* 11.4.2 -- must NOP four times before checking FR/B# */
/* 11.4.2 -- must NOP four times before checking FR/B# */
@ -866,7 +862,8 @@ static int doc200x_dev_ready(struct mtd_info *mtd)
}
}
/* 11.4.2 -- Must NOP twice if it's ready */
/* 11.4.2 -- Must NOP twice if it's ready */
DoC_Delay ( doc , 2 ) ;
DoC_Delay ( doc , 2 ) ;
if ( debug ) printk ( " was ready \n " ) ;
if ( debug )
printk ( " was ready \n " ) ;
return 1 ;
return 1 ;
}
}
}
}
@ -917,8 +914,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
}
}
/* This code is only called on write */
/* This code is only called on write */
static int doc200x_calculate_ecc ( struct mtd_info * mtd , const u_char * dat ,
static int doc200x_calculate_ecc ( struct mtd_info * mtd , const u_char * dat , unsigned char * ecc_code )
unsigned char * ecc_code )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -962,7 +958,8 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
often . It could be optimized away by examining the data in
often . It could be optimized away by examining the data in
the writebuf routine , and remembering the result . */
the writebuf routine , and remembering the result . */
for ( i = 0 ; i < 512 ; i + + ) {
for ( i = 0 ; i < 512 ; i + + ) {
if ( dat [ i ] = = 0xff ) continue ;
if ( dat [ i ] = = 0xff )
continue ;
emptymatch = 0 ;
emptymatch = 0 ;
break ;
break ;
}
}
@ -970,17 +967,20 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
/* If emptymatch still =1, we do have an all-0xff data buffer.
/* If emptymatch still =1, we do have an all-0xff data buffer.
Return all - 0xff ecc value instead of the computed one , so
Return all - 0xff ecc value instead of the computed one , so
it ' ll look just like a freshly - erased page . */
it ' ll look just like a freshly - erased page . */
if ( emptymatch ) memset ( ecc_code , 0xff , 6 ) ;
if ( emptymatch )
memset ( ecc_code , 0xff , 6 ) ;
# endif
# endif
return 0 ;
return 0 ;
}
}
static int doc200x_correct_data ( struct mtd_info * mtd , u_char * dat , u_char * read_ecc , u_char * calc_ecc )
static int doc200x_correct_data ( struct mtd_info * mtd , u_char * dat ,
u_char * read_ecc , u_char * isnull )
{
{
int i , ret = 0 ;
int i , ret = 0 ;
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
void __iomem * docptr = doc - > virtadr ;
void __iomem * docptr = doc - > virtadr ;
uint8_t calc_ecc [ 6 ] ;
volatile u_char dummy ;
volatile u_char dummy ;
int emptymatch = 1 ;
int emptymatch = 1 ;
@ -1013,7 +1013,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
all - 0xff data and stored ecc block . Check the stored ecc . */
all - 0xff data and stored ecc block . Check the stored ecc . */
if ( emptymatch ) {
if ( emptymatch ) {
for ( i = 0 ; i < 6 ; i + + ) {
for ( i = 0 ; i < 6 ; i + + ) {
if ( read_ecc [ i ] = = 0xff ) continue ;
if ( read_ecc [ i ] = = 0xff )
continue ;
emptymatch = 0 ;
emptymatch = 0 ;
break ;
break ;
}
}
@ -1024,7 +1025,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
often . It could be optimized away by examining the data in
often . It could be optimized away by examining the data in
the readbuf routine , and remembering the result . */
the readbuf routine , and remembering the result . */
for ( i = 0 ; i < 512 ; i + + ) {
for ( i = 0 ; i < 512 ; i + + ) {
if ( dat [ i ] = = 0xff ) continue ;
if ( dat [ i ] = = 0xff )
continue ;
emptymatch = 0 ;
emptymatch = 0 ;
break ;
break ;
}
}
@ -1033,7 +1035,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
erased block , in which case the ECC will not come out right .
erased block , in which case the ECC will not come out right .
We ' ll suppress the error and tell the caller everything ' s
We ' ll suppress the error and tell the caller everything ' s
OK . Because it is . */
OK . Because it is . */
if ( ! emptymatch ) ret = doc_ecc_decode ( rs_decoder , dat , calc_ecc ) ;
if ( ! emptymatch )
ret = doc_ecc_decode ( rs_decoder , dat , calc_ecc ) ;
if ( ret > 0 )
if ( ret > 0 )
printk ( KERN_ERR " doc200x_correct_data corrected %d errors \n " , ret ) ;
printk ( KERN_ERR " doc200x_correct_data corrected %d errors \n " , ret ) ;
}
}
@ -1048,13 +1051,22 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
return ret ;
return ret ;
}
}
/*u_char mydatabuf[528]; */
//u_char mydatabuf[528];
static struct nand_oobinfo doc200x_oobinfo = {
/* The strange out-of-order .oobfree list below is a (possibly unneeded)
. useecc = MTD_NANDECC_AUTOPLACE ,
* attempt to retain compatibility . It used to read :
* . oobfree = { { 8 , 8 } }
* Since that leaves two bytes unusable , it was changed . But the following
* scheme might affect existing jffs2 installs by moving the cleanmarker :
* . oobfree = { { 6 , 10 } }
* jffs2 seems to handle the above gracefully , but the current scheme seems
* safer . The only problem with it is that any code that parses oobfree must
* be able to handle out - of - order segments .
*/
static struct nand_ecclayout doc200x_oobinfo = {
. eccbytes = 6 ,
. eccbytes = 6 ,
. eccpos = { 0 , 1 , 2 , 3 , 4 , 5 } ,
. eccpos = { 0 , 1 , 2 , 3 , 4 , 5 } ,
. oobfree = { { 8 , 8 } }
. oobfree = { { 8 , 8 } , { 6 , 2 } }
} ;
} ;
/* Find the (I)NFTL Media Header, and optionally also the mirror media header.
/* Find the (I)NFTL Media Header, and optionally also the mirror media header.
@ -1063,28 +1075,28 @@ static struct nand_oobinfo doc200x_oobinfo = {
either " ANAND " or " BNAND " . If findmirror = 1 , also look for the mirror media
either " ANAND " or " BNAND " . If findmirror = 1 , also look for the mirror media
header . The page # s of the found media headers are placed in mh0_page and
header . The page # s of the found media headers are placed in mh0_page and
mh1_page in the DOC private structure . */
mh1_page in the DOC private structure . */
static int __init find_media_headers ( struct mtd_info * mtd , u_char * buf ,
static int __init find_media_headers ( struct mtd_info * mtd , u_char * buf , const char * id , int findmirror )
const char * id , int findmirror )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
unsigned offs , end = ( MAX_MEDIAHEADER_SCAN < < this - > phys_erase_shift ) ;
unsigned offs ;
int ret ;
int ret ;
size_t retlen ;
size_t retlen ;
end = min ( end , mtd - > size ) ; /* paranoia */
for ( offs = 0 ; offs < mtd - > size ; offs + = mtd - > erasesize ) {
for ( offs = 0 ; offs < end ; offs + = mtd - > erasesize ) {
ret = mtd - > read ( mtd , offs , mtd - > writesize , & retlen , buf ) ;
ret = mtd - > read ( mtd , offs , mtd - > oobblock , & retlen , buf ) ;
if ( retlen ! = mtd - > writesize )
if ( retlen ! = mtd - > oobblock ) continue ;
continue ;
if ( ret ) {
if ( ret ) {
printk ( KERN_WARNING " ECC error scanning DOC at 0x%x \n " ,
printk ( KERN_WARNING " ECC error scanning DOC at 0x%x \n " , offs ) ;
offs ) ;
}
}
if ( memcmp ( buf , id , 6 ) ) continue ;
if ( memcmp ( buf , id , 6 ) )
continue ;
printk ( KERN_INFO " Found DiskOnChip %s Media Header at 0x%x \n " , id , offs ) ;
printk ( KERN_INFO " Found DiskOnChip %s Media Header at 0x%x \n " , id , offs ) ;
if ( doc - > mh0_page = = - 1 ) {
if ( doc - > mh0_page = = - 1 ) {
doc - > mh0_page = offs > > this - > page_shift ;
doc - > mh0_page = offs > > this - > page_shift ;
if ( ! findmirror ) return 1 ;
if ( ! findmirror )
return 1 ;
continue ;
continue ;
}
}
doc - > mh1_page = offs > > this - > page_shift ;
doc - > mh1_page = offs > > this - > page_shift ;
@ -1097,8 +1109,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
/* Only one mediaheader was found. We want buf to contain a
/* Only one mediaheader was found. We want buf to contain a
mediaheader on return , so we ' ll have to re - read the one we found . */
mediaheader on return , so we ' ll have to re - read the one we found . */
offs = doc - > mh0_page < < this - > page_shift ;
offs = doc - > mh0_page < < this - > page_shift ;
ret = mtd - > read ( mtd , offs , mtd - > oobblock , & retlen , buf ) ;
ret = mtd - > read ( mtd , offs , mtd - > writesize , & retlen , buf ) ;
if ( retlen ! = mtd - > oobblock ) {
if ( retlen ! = mtd - > writesize ) {
/* Insanity. Give up. */
/* Insanity. Give up. */
printk ( KERN_ERR " Read DiskOnChip Media Header once, but can't reread it??? \n " ) ;
printk ( KERN_ERR " Read DiskOnChip Media Header once, but can't reread it??? \n " ) ;
return 0 ;
return 0 ;
@ -1106,8 +1118,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
return 1 ;
return 1 ;
}
}
static inline int __init nftl_partscan ( struct mtd_info * mtd ,
static inline int __init nftl_partscan ( struct mtd_info * mtd , struct mtd_partition * parts )
struct mtd_partition * parts )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -1115,19 +1126,23 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
u_char * buf ;
u_char * buf ;
struct NFTLMediaHeader * mh ;
struct NFTLMediaHeader * mh ;
const unsigned psize = 1 < < this - > page_shift ;
const unsigned psize = 1 < < this - > page_shift ;
int numparts = 0 ;
unsigned blocks , maxblocks ;
unsigned blocks , maxblocks ;
int offs , numheaders ;
int offs , numheaders ;
buf = kmalloc ( mtd - > oobblock , GFP_KERNEL ) ;
buf = kmalloc ( mtd - > writesize , GFP_KERNEL ) ;
if ( ! buf ) {
if ( ! buf ) {
printk ( KERN_ERR " DiskOnChip mediaheader kmalloc failed! \n " ) ;
printk ( KERN_ERR " DiskOnChip mediaheader kmalloc failed! \n " ) ;
return 0 ;
return 0 ;
}
}
if ( ! ( numheaders = find_media_headers ( mtd , buf , " ANAND " , 1 ) ) ) goto out ;
if ( ! ( numheaders = find_media_headers ( mtd , buf , " ANAND " , 1 ) ) )
goto out ;
mh = ( struct NFTLMediaHeader * ) buf ;
mh = ( struct NFTLMediaHeader * ) buf ;
/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
mh - > NumEraseUnits = le16_to_cpu ( mh - > NumEraseUnits ) ;
/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
mh - > FirstPhysicalEUN = le16_to_cpu ( mh - > FirstPhysicalEUN ) ;
mh - > FormattedSize = le32_to_cpu ( mh - > FormattedSize ) ;
printk ( KERN_INFO " DataOrgID = %s \n "
printk ( KERN_INFO " DataOrgID = %s \n "
" NumEraseUnits = %d \n "
" NumEraseUnits = %d \n "
" FirstPhysicalEUN = %d \n "
" FirstPhysicalEUN = %d \n "
@ -1136,7 +1151,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
mh - > DataOrgID , mh - > NumEraseUnits ,
mh - > DataOrgID , mh - > NumEraseUnits ,
mh - > FirstPhysicalEUN , mh - > FormattedSize ,
mh - > FirstPhysicalEUN , mh - > FormattedSize ,
mh - > UnitSizeFactor ) ;
mh - > UnitSizeFactor ) ;
/*#endif */
blocks = mtd - > size > > this - > phys_erase_shift ;
blocks = mtd - > size > > this - > phys_erase_shift ;
maxblocks = min ( 32768U , mtd - > erasesize - psize ) ;
maxblocks = min ( 32768U , mtd - > erasesize - psize ) ;
@ -1179,31 +1193,35 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
offs < < = this - > page_shift ;
offs < < = this - > page_shift ;
offs + = mtd - > erasesize ;
offs + = mtd - > erasesize ;
/*parts[0].name = " DiskOnChip Boot / Media Header partition"; */
if ( show_firmware_partition = = 1 ) {
/*parts[0].offset = 0; */
parts [ 0 ] . name = " DiskOnChip Firmware / Media Header partition " ;
/*parts[0].size = offs; */
parts [ 0 ] . offset = 0 ;
parts [ 0 ] . size = offs ;
numparts = 1 ;
}
parts [ 0 ] . name = " DiskOnChip BDTL partition " ;
parts [ numparts ] . name = " DiskOnChip BDTL partition " ;
parts [ 0 ] . offset = offs ;
parts [ numparts ] . offset = offs ;
parts [ 0 ] . size = ( mh - > NumEraseUnits - numheaders ) < < this - > bbt_erase_shift ;
parts [ numparts ] . size = ( mh - > NumEraseUnits - numheaders ) < < this - > bbt_erase_shift ;
offs + = parts [ numparts ] . size ;
numparts + + ;
offs + = parts [ 0 ] . size ;
if ( offs < mtd - > size ) {
if ( offs < mtd - > size ) {
parts [ 1 ] . name = " DiskOnChip Remainder partition " ;
parts [ numparts ] . name = " DiskOnChip Remainder partition " ;
parts [ 1 ] . offset = offs ;
parts [ numparts ] . offset = offs ;
parts [ 1 ] . size = mtd - > size - offs ;
parts [ numparts ] . size = mtd - > size - offs ;
ret = 2 ;
numparts + + ;
goto out ;
}
}
ret = 1 ;
ret = numparts ;
out :
out :
kfree ( buf ) ;
kfree ( buf ) ;
return ret ;
return ret ;
}
}
/* This is a stripped-down copy of the code in inftlmount.c */
/* This is a stripped-down copy of the code in inftlmount.c */
static inline int __init inftl_partscan ( struct mtd_info * mtd ,
static inline int __init inftl_partscan ( struct mtd_info * mtd , struct mtd_partition * parts )
struct mtd_partition * parts )
{
{
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
@ -1220,13 +1238,14 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
if ( inftl_bbt_write )
if ( inftl_bbt_write )
end - = ( INFTL_BBT_RESERVED_BLOCKS < < this - > phys_erase_shift ) ;
end - = ( INFTL_BBT_RESERVED_BLOCKS < < this - > phys_erase_shift ) ;
buf = kmalloc ( mtd - > oobblock , GFP_KERNEL ) ;
buf = kmalloc ( mtd - > writesize , GFP_KERNEL ) ;
if ( ! buf ) {
if ( ! buf ) {
printk ( KERN_ERR " DiskOnChip mediaheader kmalloc failed! \n " ) ;
printk ( KERN_ERR " DiskOnChip mediaheader kmalloc failed! \n " ) ;
return 0 ;
return 0 ;
}
}
if ( ! find_media_headers ( mtd , buf , " BNAND " , 0 ) ) goto out ;
if ( ! find_media_headers ( mtd , buf , " BNAND " , 0 ) )
goto out ;
doc - > mh1_page = doc - > mh0_page + ( 4096 > > this - > page_shift ) ;
doc - > mh1_page = doc - > mh0_page + ( 4096 > > this - > page_shift ) ;
mh = ( struct INFTLMediaHeader * ) buf ;
mh = ( struct INFTLMediaHeader * ) buf ;
@ -1237,8 +1256,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
mh - > FormatFlags = le32_to_cpu ( mh - > FormatFlags ) ;
mh - > FormatFlags = le32_to_cpu ( mh - > FormatFlags ) ;
mh - > PercentUsed = le32_to_cpu ( mh - > PercentUsed ) ;
mh - > PercentUsed = le32_to_cpu ( mh - > PercentUsed ) ;
/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
printk ( KERN_INFO " bootRecordID = %s \n "
printk ( KERN_INFO " bootRecordID = %s \n "
" NoOfBootImageBlocks = %d \n "
" NoOfBootImageBlocks = %d \n "
" NoOfBinaryPartitions = %d \n "
" NoOfBinaryPartitions = %d \n "
@ -1256,7 +1273,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
( ( unsigned char * ) & mh - > OsakVersion ) [ 2 ] & 0xf ,
( ( unsigned char * ) & mh - > OsakVersion ) [ 2 ] & 0xf ,
( ( unsigned char * ) & mh - > OsakVersion ) [ 3 ] & 0xf ,
( ( unsigned char * ) & mh - > OsakVersion ) [ 3 ] & 0xf ,
mh - > PercentUsed ) ;
mh - > PercentUsed ) ;
/*#endif */
vshift = this - > phys_erase_shift + mh - > BlockMultiplierBits ;
vshift = this - > phys_erase_shift + mh - > BlockMultiplierBits ;
@ -1282,8 +1298,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
ip - > spareUnits = le32_to_cpu ( ip - > spareUnits ) ;
ip - > spareUnits = le32_to_cpu ( ip - > spareUnits ) ;
ip - > Reserved0 = le32_to_cpu ( ip - > Reserved0 ) ;
ip - > Reserved0 = le32_to_cpu ( ip - > Reserved0 ) ;
/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
printk ( KERN_INFO " PARTITION[%d] -> \n "
printk ( KERN_INFO " PARTITION[%d] -> \n "
" virtualUnits = %d \n "
" virtualUnits = %d \n "
" firstUnit = %d \n "
" firstUnit = %d \n "
@ -1293,16 +1307,14 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
i , ip - > virtualUnits , ip - > firstUnit ,
i , ip - > virtualUnits , ip - > firstUnit ,
ip - > lastUnit , ip - > flags ,
ip - > lastUnit , ip - > flags ,
ip - > spareUnits ) ;
ip - > spareUnits ) ;
/*#endif */
/*
if ( ( show_firmware_partition = = 1 ) & &
if ( ( i = = 0 ) & & ( ip - > firstUnit > 0 ) ) {
( i = = 0 ) & & ( ip - > firstUnit > 0 ) ) {
parts [ 0 ] . name = " DiskOnChip IPL / Media Header partition " ;
parts [ 0 ] . name = " DiskOnChip IPL / Media Header partition " ;
parts [ 0 ] . offset = 0 ;
parts [ 0 ] . offset = 0 ;
parts [ 0 ] . size = mtd - > erasesize * ip - > firstUnit ;
parts [ 0 ] . size = mtd - > erasesize * ip - > firstUnit ;
numparts = 1 ;
numparts = 1 ;
}
}
*/
if ( ip - > flags & INFTL_BINARY )
if ( ip - > flags & INFTL_BINARY )
parts [ numparts ] . name = " DiskOnChip BDK partition " ;
parts [ numparts ] . name = " DiskOnChip BDK partition " ;
@ -1311,8 +1323,10 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
parts [ numparts ] . offset = ip - > firstUnit < < vshift ;
parts [ numparts ] . offset = ip - > firstUnit < < vshift ;
parts [ numparts ] . size = ( 1 + ip - > lastUnit - ip - > firstUnit ) < < vshift ;
parts [ numparts ] . size = ( 1 + ip - > lastUnit - ip - > firstUnit ) < < vshift ;
numparts + + ;
numparts + + ;
if ( ip - > lastUnit > lastvunit ) lastvunit = ip - > lastUnit ;
if ( ip - > lastUnit > lastvunit )
if ( ip - > flags & INFTL_LAST ) break ;
lastvunit = ip - > lastUnit ;
if ( ip - > flags & INFTL_LAST )
break ;
}
}
lastvunit + + ;
lastvunit + + ;
if ( ( lastvunit < < vshift ) < end ) {
if ( ( lastvunit < < vshift ) < end ) {
@ -1338,7 +1352,8 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd)
/* On NFTL, we have to find the media headers before we can read the
/* On NFTL, we have to find the media headers before we can read the
BBTs , since they ' re stored in the media header eraseblocks . */
BBTs , since they ' re stored in the media header eraseblocks . */
numparts = nftl_partscan ( mtd , parts ) ;
numparts = nftl_partscan ( mtd , parts ) ;
if ( ! numparts ) return - EIO ;
if ( ! numparts )
return - EIO ;
this - > bbt_td - > options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
this - > bbt_td - > options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
NAND_BBT_VERSION ;
NAND_BBT_VERSION ;
@ -1385,8 +1400,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
this - > bbt_td - > pages [ 0 ] = 2 ;
this - > bbt_td - > pages [ 0 ] = 2 ;
this - > bbt_md = NULL ;
this - > bbt_md = NULL ;
} else {
} else {
this - > bbt_td - > options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
this - > bbt_td - > options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION ;
NAND_BBT_VERSION ;
if ( inftl_bbt_write )
if ( inftl_bbt_write )
this - > bbt_td - > options | = NAND_BBT_WRITE ;
this - > bbt_td - > options | = NAND_BBT_WRITE ;
this - > bbt_td - > offs = 8 ;
this - > bbt_td - > offs = 8 ;
@ -1396,8 +1410,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
this - > bbt_td - > reserved_block_code = 0x01 ;
this - > bbt_td - > reserved_block_code = 0x01 ;
this - > bbt_td - > pattern = " MSYS_BBT " ;
this - > bbt_td - > pattern = " MSYS_BBT " ;
this - > bbt_md - > options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
this - > bbt_md - > options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION ;
NAND_BBT_VERSION ;
if ( inftl_bbt_write )
if ( inftl_bbt_write )
this - > bbt_md - > options | = NAND_BBT_WRITE ;
this - > bbt_md - > options | = NAND_BBT_WRITE ;
this - > bbt_md - > offs = 8 ;
this - > bbt_md - > offs = 8 ;
@ -1417,7 +1430,8 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
/* At least for now, require the INFTL Media Header. We could probably
/* At least for now, require the INFTL Media Header. We could probably
do without it for non - INFTL use , since all it gives us is
do without it for non - INFTL use , since all it gives us is
autopartitioning , but I want to give it more thought . */
autopartitioning , but I want to give it more thought . */
if ( ! numparts ) return - EIO ;
if ( ! numparts )
return - EIO ;
add_mtd_device ( mtd ) ;
add_mtd_device ( mtd ) ;
# ifdef CONFIG_MTD_PARTITIONS
# ifdef CONFIG_MTD_PARTITIONS
if ( ! no_autopart )
if ( ! no_autopart )
@ -1431,7 +1445,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
this - > write_byte = doc2000_write_byte ;
this - > read_byte = doc2000_read_byte ;
this - > read_byte = doc2000_read_byte ;
this - > write_buf = doc2000_writebuf ;
this - > write_buf = doc2000_writebuf ;
this - > read_buf = doc2000_readbuf ;
this - > read_buf = doc2000_readbuf ;
@ -1449,7 +1462,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
this - > write_byte = doc2001_write_byte ;
this - > read_byte = doc2001_read_byte ;
this - > read_byte = doc2001_read_byte ;
this - > write_buf = doc2001_writebuf ;
this - > write_buf = doc2001_writebuf ;
this - > read_buf = doc2001_readbuf ;
this - > read_buf = doc2001_readbuf ;
@ -1481,16 +1493,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
struct nand_chip * this = mtd - > priv ;
struct nand_chip * this = mtd - > priv ;
struct doc_priv * doc = this - > priv ;
struct doc_priv * doc = this - > priv ;
this - > write_byte = NULL ;
this - > read_byte = doc2001plus_read_byte ;
this - > read_byte = doc2001plus_read_byte ;
this - > write_buf = doc2001plus_writebuf ;
this - > write_buf = doc2001plus_writebuf ;
this - > read_buf = doc2001plus_readbuf ;
this - > read_buf = doc2001plus_readbuf ;
this - > verify_buf = doc2001plus_verifybuf ;
this - > verify_buf = doc2001plus_verifybuf ;
this - > scan_bbt = inftl_scan_bbt ;
this - > scan_bbt = inftl_scan_bbt ;
this - > hwcontro l = NULL ;
this - > cmd_ctr l = NULL ;
this - > select_chip = doc2001plus_select_chip ;
this - > select_chip = doc2001plus_select_chip ;
this - > cmdfunc = doc2001plus_command ;
this - > cmdfunc = doc2001plus_command ;
this - > enable_hwecc = doc2001plus_enable_hwecc ;
this - > ecc . hwctl = doc2001plus_enable_hwecc ;
doc - > chips_per_floor = 1 ;
doc - > chips_per_floor = 1 ;
mtd - > name = " DiskOnChip Millennium Plus " ;
mtd - > name = " DiskOnChip Millennium Plus " ;
@ -1498,7 +1509,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
return 1 ;
return 1 ;
}
}
static inline int __init doc_probe ( unsigned long physadr )
static int __init doc_probe ( unsigned long physadr )
{
{
unsigned char ChipID ;
unsigned char ChipID ;
struct mtd_info * mtd ;
struct mtd_info * mtd ;
@ -1527,16 +1538,12 @@ static inline int __init doc_probe(unsigned long physadr)
save_control = ReadDOC ( virtadr , DOCControl ) ;
save_control = ReadDOC ( virtadr , DOCControl ) ;
/* Reset the DiskOnChip ASIC */
/* Reset the DiskOnChip ASIC */
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET ,
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET , virtadr , DOCControl ) ;
virtadr , DOCControl ) ;
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET , virtadr , DOCControl ) ;
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET ,
virtadr , DOCControl ) ;
/* Enable the DiskOnChip ASIC */
/* Enable the DiskOnChip ASIC */
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL ,
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL , virtadr , DOCControl ) ;
virtadr , DOCControl ) ;
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL , virtadr , DOCControl ) ;
WriteDOC ( DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL ,
virtadr , DOCControl ) ;
ChipID = ReadDOC ( virtadr , ChipID ) ;
ChipID = ReadDOC ( virtadr , ChipID ) ;
@ -1556,15 +1563,13 @@ static inline int __init doc_probe(unsigned long physadr)
ReadDOC ( virtadr , Mplus_Power ) ;
ReadDOC ( virtadr , Mplus_Power ) ;
/* Reset the Millennium Plus ASIC */
/* Reset the Millennium Plus ASIC */
tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT ;
DOC_MODE_BDECT ;
WriteDOC ( tmp , virtadr , Mplus_DOCControl ) ;
WriteDOC ( tmp , virtadr , Mplus_DOCControl ) ;
WriteDOC ( ~ tmp , virtadr , Mplus_CtrlConfirm ) ;
WriteDOC ( ~ tmp , virtadr , Mplus_CtrlConfirm ) ;
mdelay ( 1 ) ;
mdelay ( 1 ) ;
/* Enable the Millennium Plus ASIC */
/* Enable the Millennium Plus ASIC */
tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT ;
DOC_MODE_BDECT ;
WriteDOC ( tmp , virtadr , Mplus_DOCControl ) ;
WriteDOC ( tmp , virtadr , Mplus_DOCControl ) ;
WriteDOC ( ~ tmp , virtadr , Mplus_CtrlConfirm ) ;
WriteDOC ( ~ tmp , virtadr , Mplus_CtrlConfirm ) ;
mdelay ( 1 ) ;
mdelay ( 1 ) ;
@ -1618,11 +1623,11 @@ static inline int __init doc_probe(unsigned long physadr)
if ( ChipID = = DOC_ChipID_DocMilPlus16 ) {
if ( ChipID = = DOC_ChipID_DocMilPlus16 ) {
WriteDOC ( ~ newval , virtadr , Mplus_AliasResolution ) ;
WriteDOC ( ~ newval , virtadr , Mplus_AliasResolution ) ;
oldval = ReadDOC ( doc - > virtadr , Mplus_AliasResolution ) ;
oldval = ReadDOC ( doc - > virtadr , Mplus_AliasResolution ) ;
WriteDOC ( newval , virtadr , Mplus_AliasResolution ) ; /* restore it */
WriteDOC ( newval , virtadr , Mplus_AliasResolution ) ; // restore it
} else {
} else {
WriteDOC ( ~ newval , virtadr , AliasResolution ) ;
WriteDOC ( ~ newval , virtadr , AliasResolution ) ;
oldval = ReadDOC ( doc - > virtadr , AliasResolution ) ;
oldval = ReadDOC ( doc - > virtadr , AliasResolution ) ;
WriteDOC ( newval , virtadr , AliasResolution ) ; /* restore it */
WriteDOC ( newval , virtadr , AliasResolution ) ; // restore it
}
}
newval = ~ newval ;
newval = ~ newval ;
if ( oldval = = newval ) {
if ( oldval = = newval ) {
@ -1634,16 +1639,13 @@ static inline int __init doc_probe(unsigned long physadr)
printk ( KERN_NOTICE " DiskOnChip found at 0x%lx \n " , physadr ) ;
printk ( KERN_NOTICE " DiskOnChip found at 0x%lx \n " , physadr ) ;
len = sizeof ( struct mtd_info ) +
len = sizeof ( struct mtd_info ) +
sizeof ( struct nand_chip ) +
sizeof ( struct nand_chip ) + sizeof ( struct doc_priv ) + ( 2 * sizeof ( struct nand_bbt_descr ) ) ;
sizeof ( struct doc_priv ) +
mtd = kzalloc ( len , GFP_KERNEL ) ;
( 2 * sizeof ( struct nand_bbt_descr ) ) ;
mtd = kmalloc ( len , GFP_KERNEL ) ;
if ( ! mtd ) {
if ( ! mtd ) {
printk ( KERN_ERR " DiskOnChip kmalloc (%d bytes) failed! \n " , len ) ;
printk ( KERN_ERR " DiskOnChip kmalloc (%d bytes) failed! \n " , len ) ;
ret = - ENOMEM ;
ret = - ENOMEM ;
goto fail ;
goto fail ;
}
}
memset ( mtd , 0 , len ) ;
nand = ( struct nand_chip * ) ( mtd + 1 ) ;
nand = ( struct nand_chip * ) ( mtd + 1 ) ;
doc = ( struct doc_priv * ) ( nand + 1 ) ;
doc = ( struct doc_priv * ) ( nand + 1 ) ;
@ -1655,17 +1657,19 @@ static inline int __init doc_probe(unsigned long physadr)
nand - > priv = doc ;
nand - > priv = doc ;
nand - > select_chip = doc200x_select_chip ;
nand - > select_chip = doc200x_select_chip ;
nand - > hwcontro l = doc200x_hwcontrol ;
nand - > cmd_ctr l = doc200x_hwcontrol ;
nand - > dev_ready = doc200x_dev_ready ;
nand - > dev_ready = doc200x_dev_ready ;
nand - > waitfunc = doc200x_wait ;
nand - > waitfunc = doc200x_wait ;
nand - > block_bad = doc200x_block_bad ;
nand - > block_bad = doc200x_block_bad ;
nand - > enable_hwecc = doc200x_enable_hwecc ;
nand - > ecc . hwctl = doc200x_enable_hwecc ;
nand - > calculate_ecc = doc200x_calculate_ecc ;
nand - > ecc . calculate = doc200x_calculate_ecc ;
nand - > correct_data = doc200x_correct_data ;
nand - > ecc . correct = doc200x_correct_data ;
nand - > autooob = & doc200x_oobinfo ;
nand - > ecc . layout = & doc200x_oobinfo ;
nand - > eccmode = NAND_ECC_HW6_512 ;
nand - > ecc . mode = NAND_ECC_HW_SYNDROME ;
nand - > options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME ;
nand - > ecc . size = 512 ;
nand - > ecc . bytes = 6 ;
nand - > options = NAND_USE_FLASH_BBT ;
doc - > physadr = physadr ;
doc - > physadr = physadr ;
doc - > virtadr = virtadr ;
doc - > virtadr = virtadr ;