mtd/nand : Add function board_nand_init_tail() for some special NAND controllers
Subsystems (2)
PATCH 1/4 mtd/nand : Add function board_nand_init_tail() for some special NAND controllers
In some NAND controllers there is a size limitation of RAM buffer(2K bytes). To support large-page NAND chips with greater than 2K pagesize, we need a large buffer, but we don't know pagesize before calling nand_scan_ident(), for more flexible and to identify different cases of large-page greater than 2K bytes, we have a board_nand_init_tail() between nand_scan_ident() and nand_scan_tail().
--- drivers/mtd/nand/nand.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
drivers/mtd/nand/nand.c +13 -1
@@ -39,6 +39,13 @@ static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LISstatic const char default_nand_name[] ="nand" ;static __attribute__((unused))char dev_name[CONFIG_SYS_MAX_NAND_DEVICE ][8 ]; +int __board_nand_init_tail (struct mtd_info *mtd,struct nand_chip *nand) +{ +/* Allow for init at tail in controller-specific file for some reason */ +} +void board_nand_init_tail (struct mtd_info *mtd,struct nand_chip *nand) +__attribute__((weak,alias ("__board_nand_init_tail" ))); +static void nand_init_chip (struct mtd_info *mtd,struct nand_chip *nand,ulong base_addr) {
@@ -51,7 +58,12 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;if (board_nand_init (nand) ==0 ) { -if (nand_scan (mtd, maxchips) ==0 ) { +if (!nand_scan_ident (mtd, maxchips,NULL )) { +board_nand_init_tail (mtd, nand); +if (nand_scan_tail (mtd)) { + mtd->name =NULL ; +return ; + }if (!mtd->name) mtd->name = (char *)default_nand_name;#ifdef CONFIG_NEEDS_MANUAL_RELOC
Signature · 1 line
1.6.4
PATCH 2/4 mtd/nand: Fixup for support ONFI detect
There was a bug logically in the order of nand_flash_detect_onfi and checking nand_flash_ids. We should get NAND devices related informations first by ONFI method instead of querying nand_flash_ids table, if ONFI fails, then query nand_flash_ids table.
--- drivers/mtd/nand/nand_base.c | 48 +++++++++++++++++++++-------------------- 1 files changed, 25 insertions(+), 23 deletions(-)
drivers/mtd/nand/nand_base.c +25 -23
@@ -2585,36 +2585,38 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,return ERR_PTR (-ENODEV ); } -if (!type) - type = nand_flash_ids; + ret =nand_flash_detect_onfi (mtd, chip, &busw); +if (!ret) { +if (!type) + type = nand_flash_ids; -for (; type->name !=NULL ; type++) -if (*dev_id == type->id) -break ; +for (; type->name !=NULL ; type++) +if (*dev_id == type->id) +break ; -if (!type->name) { -/* supress warning if there is no nand */ -if (*maf_id !=0x00 && *maf_id !=0xff && - *dev_id !=0x00 && *dev_id !=0xff ) -printk (KERN_INFO "%s: unknown NAND device: " -"Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , - __func__, *maf_id, *dev_id); -return ERR_PTR (-ENODEV ); - } +if (!type->name) { +/* supress warning if there is no nand */ +if (*maf_id !=0x00 && *maf_id !=0xff && + *dev_id !=0x00 && *dev_id !=0xff ) { +printk (KERN_INFO "%s: unknown NAND device: " +"Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , + __func__, *maf_id, *dev_id); + } +return ERR_PTR (-ENODEV ); + } -if (!mtd->name) - mtd->name = type->name; +if (!mtd->name) + mtd->name = type->name; - chip->chipsize = (uint64_t )type->chipsize <<20 ; - chip->onfi_version =0 ; + chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; - ret =nand_flash_detect_onfi (mtd, chip, &busw); -if (!ret)nand_flash_detect_non_onfi (mtd, chip, type, &busw); -/* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK ; - chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; + }/* * Set chip as a default. Board drivers can override it, if necessary
Signature · 1 line
1.6.4
PATCH 3/4 mtd/nand: remove CONFIG_SYS_NAND_ONFI_DETECTION to enable ONFI detection
We should first try ONFI detection, if ONFI is not supported or fails, then try to check nand_flash_ids table.
--- drivers/mtd/nand/nand_base.c | 9 --------- include/linux/mtd/nand.h | 2 -- 2 files changed, 0 insertions(+), 11 deletions(-)
drivers/mtd/nand/nand_base.c +0 -9
@@ -2415,7 +2415,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } -#ifdef CONFIG_SYS_NAND_ONFI_DETECTION static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) {int i;
@@ -2493,14 +2492,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd,return 1 ; } -#else -static inline int nand_flash_detect_onfi (struct mtd_info *mtd, -struct nand_chip *chip, -int *busw) -{ -return 0 ; -} -#endif static void nand_flash_detect_non_onfi(struct mtd_info *mtd, struct nand_chip *chip,
include/linux/mtd/nand.h +0 -2
@@ -472,9 +472,7 @@ struct nand_chip {uint8_t cellinfo;int badblockpos;int onfi_version; -#ifdef CONFIG_SYS_NAND_ONFI_DETECTION struct nand_onfi_params onfi_params; -#endif int state;
Signature · 1 line
1.6.4
PATCH 4/4 mtd/nand: Add ONFI support for FSL NAND controller
- fix NAND_CMD_READID command for ONFI detect.
- add NAND_CMD_PARAM command to read the ONFI parameter page.
--- drivers/mtd/nand/fsl_elbc_nand.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-)
drivers/mtd/nand/fsl_elbc_nand.c +15 -1
@@ -350,7 +350,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,out_be32 (&lbc->fbcr,5 ); ctrl->read_bytes =5 ; ctrl->use_mdr =1 ; - ctrl->mdr =0 ; + ctrl->mdr = column;set_addr (mtd,0 ,0 ,0 );fsl_elbc_run_command (mtd);
@@ -480,6 +480,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,fsl_elbc_run_command (mtd);return ; +case NAND_CMD_PARAM : +dbg ("fsl_elbc_cmdfunc: NAND_CMD_PARAM.\n" ); +out_be32 (&lbc->fir, (FIR_OP_CM0 <<FIR_OP0_SHIFT ) | + (FIR_OP_UA <<FIR_OP1_SHIFT ) | + (FIR_OP_RBW <<FIR_OP2_SHIFT )); +out_be32 (&lbc->fcr,NAND_CMD_PARAM <<FCR_CMD0_SHIFT ); +out_be32 (&lbc->fbcr,256 ); + ctrl->read_bytes =256 ; + ctrl->use_mdr =1 ; + ctrl->mdr = column; +set_addr (mtd,0 ,0 ,0 ); +fsl_elbc_run_command (mtd); +return ; +default :printf ("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n" , command);
Signature · 1 line
1.6.4
PATCH 4/4 mtd/nand: Add ONFI support for FSL NAND controller
Quoted 28 lines · Shengzhou Liu
- fix
NAND_CMD_READIDcommand for ONFI detect.
- addNAND_CMD_PARAMcommand to read the ONFI parameter page.Signed-off-by Shengzhou Liu <[email protected]>--- drivers/mtd/nand/fsl_elbc_nand.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-)drivers/mtd/nand/fsl_elbc_nand.c +4
-1@@ -350,7 +350,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,out_be32 (&lbc->fbcr,5 ); ctrl->read_bytes =5 ; ctrl->use_mdr =1 ; - ctrl->mdr =0 ; + ctrl->mdr = column;set_addr (mtd,0 ,0 ,0 );fsl_elbc_run_command (mtd);@@ -480,6 +480,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,fsl_elbc_run_command (mtd);return ; +case NAND_CMD_PARAM : +dbg ("fsl_elbc_cmdfunc: NAND_CMD_PARAM.\n" ); + out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
drivers/mtd/nand/fsl_elbc_nand.c static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, · line 495
Quoted 10 lines
drivers/mtd/nand/fsl_elbc_nand.c +10
-0+ (FIR_OP_UA <<FIR_OP1_SHIFT ) | + (FIR_OP_RBW << FIR_OP2_SHIFT)); +out_be32 (&lbc->fcr,NAND_CMD_PARAM <<FCR_CMD0_SHIFT ); +out_be32 (&lbc->fbcr,256 ); + ctrl->read_bytes =256 ; + ctrl->use_mdr =1 ; + ctrl->mdr = column; +set_addr (mtd,0 ,0 ,0 ); +fsl_elbc_run_command (mtd); +return ;
This could share code with NAND_CMD_READID -- always read 256 bytes (we'll need to read more than 5 bytes for non-ONFI as well, when we pull in the newer Linux NAND code), and use "command << FCR_CMD0_SHIFT" for FCR.
BTW, has anyone tested the eLBC driver with 16-bit NAND? I think our read_byte() implementation is not going to do the right thing here -- it needs to read a 16-bit word when the chip is 16-bit, and discard the upper half.
-Scott
A message that is not in the archive (sent off-list or not yet received): 3F453DDFF675A64A89321A1F352810216B03B9@039-SN1MPN1-005.039d.mgd.msft.net
PATCH 4/4 mtd/nand: Add ONFI support for FSL NAND controller
Quoted 36 lines · On 12/03/2011 03:25 AM, Liu Shengzhou-B36685 wrote:
Quoted 36 lines
-----Original Message-----
From: Wood Scott-B07421
Sent: 2011?12?3? 2:45
To: Liu Shengzhou-B36685
Cc: u-boot at lists.denx.de; Gala Kumar-B11780
Subject: Re: [PATCH 4/4] mtd/nand: Add ONFI support for FSL NAND controllerdrivers/mtd/nand/fsl_elbc_nand.c static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, · line 495
Quoted 13 lines · Shengzhou Liu
drivers/mtd/nand/fsl_elbc_nand.c +13
-0+case NAND_CMD_PARAM : +dbg ("fsl_elbc_cmdfunc: NAND_CMD_PARAM.\n" ); +out_be32 (&lbc->fir, (FIR_OP_CM0 <<FIR_OP0_SHIFT ) | + (FIR_OP_UA <<FIR_OP1_SHIFT ) | + (FIR_OP_RBW <<FIR_OP2_SHIFT )); +out_be32 (&lbc->fcr,NAND_CMD_PARAM <<FCR_CMD0_SHIFT ); +out_be32 (&lbc->fbcr,256 ); + ctrl->read_bytes =256 ; + ctrl->use_mdr =1 ; + ctrl->mdr = column; +set_addr (mtd,0 ,0 ,0 ); +fsl_elbc_run_command (mtd); +return ;This could share code with
NAND_CMD_READID-- always read 256 bytes (we'll need to read more than 5 bytes for non-ONFI as well, when we pull
in the newer Linux NAND code), and use "command <<FCR_CMD0_SHIFT" for FCR.BTW, has anyone tested the eLBC driver with 16-bit NAND? I think our
read_byte()implementation is not going to do the right thing here -- it
needs to read a 16-bit word when the chip is 16-bit, and discard the upper half.
Quoted 4 lines
Quoted 1 line
-Scott
There was already
NAND_CMD_PARAMcommand which is called inmtd/nand/nand_base.c, it's not new created.NAND_CMD_PARAMis defined in spec, we should not share it withNAND_CMD_READID, if so, we'll have to intrusive tonand_base.c.
Huh?
All I'm saying is that you could do this in fsl_elbc_nand.c:
case NAND_CMD_READID: case NAND_CMD_PARAM: out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | (FIR_OP_UA << FIR_OP1_SHIFT) | (FIR_OP_RBW << FIR_OP2_SHIFT)); out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT); out_be32(&lbc->fbcr, 256); ctrl->read_bytes = 256; ctrl->use_mdr = 1; ctrl->mdr = column; set_addr(mtd, 0, 0, 0); fsl_elbc_run_command(mtd); return;
-Scott
PATCH 2/4 mtd/nand: Fixup for support ONFI detect
In reply to Shengzhou LiuQuoted 4 lines · Shengzhou Liu
There was a bug logically in the order of
nand_flash_detect_onfiand checkingnand_flash_ids. We should get NAND devices related informations first by ONFI method instead of queryingnand_flash_idstable, if ONFI fails, then querynand_flash_idstable.
ONFI issues should be taken care of with the patchset to sync NAND with Linux that was recently posted. It has some minor issues, which hopefully will be addressed by the next merge window.
I disagree that we should check ONFI first -- this is not what Linux does. U-Boot's problem is that it aborts before ever checking ONFI, if the device is not found in the table (and the Linux code suggests that ONFI devices won't be found in the table).
-Scott
A message that is not in the archive (sent off-list or not yet received): 3F453DDFF675A64A89321A1F352810216B0393@039-SN1MPN1-005.039d.mgd.msft.net
PATCH 2/4 mtd/nand: Fixup for support ONFI detect
Quoted 18 lines · On 12/03/2011 03:11 AM, Liu Shengzhou-B36685 wrote:
Quoted 18 lines
-----Original Message-----
From: Wood Scott-B07421
Sent: 2011?12?3? 2:32
To: Liu Shengzhou-B36685
Cc: u-boot at lists.denx.de; Gala Kumar-B11780
Subject: Re: [PATCH 2/4] mtd/nand: Fixup for support ONFI detectQuoted 3 lines · Shengzhou Liu
There was a bug logically in the order of
nand_flash_detect_onfiand checkingnand_flash_ids. We should get NAND devices related informations first by ONFI method instead of queryingnand_flash_idstable,
Quoted 1 line
if ONFI fails, then query
nand_flash_idstable.ONFI issues should be taken care of with the patchset to sync NAND with Linux that was recently posted. It has some minor issues, which hopefully will be addressed by the next merge window.
Quoted 8 lines
Quoted 6 lines
I disagree that we should check ONFI first -- this is not what Linux does. U-Boot's problem is that it aborts before ever checking ONFI, if the device is not found in the table (and the Linux code suggests that ONFI devices won't be found in the table).
-Scott
Currently in Linux, ONFI is detected first, if ONFI fails, then detect
nand_flash_idstable.
How do you get that impression from this code:?
for (; type->name != NULL; type++)
if (*dev_id == type->id)
break;
chip->onfi_version = 0;
if (!type->name || !type->pagesize) {
/* Check is chip is ONFI compliant */
ret = nand_flash_detect_onfi(mtd, chip, &busw);
if (ret)
goto ident_done;
}nand_flash_detect_onfi() is called only if there is no match found in the ID table.
Quoted 1 line
But in u-boot, it first detects
nand_flash_idstable, if not found in the table, it aborts, so ONFI never works.
Right, the problem is that it aborts, not that it checks the table first.
Quoted 4 lines
I think we should still check ONFI first to accord to what Linux does, because there many new NAND chips which not listed in the
nand_flash_idstable before known, if check ONFI first, it can automatically find related info without manual intervention.
The assumption in the Linux code appears to be that ONFI chips will never be in the ID table (or possibly that if they are, we don't need the ONFI data).
-Scott
PATCH 1/4 mtd/nand : Add function board_nand_init_tail() for some special NAND controllers
In reply to Shengzhou LiuHi,
Quoted 16 lines · Shengzhou Liu
In some NAND controllers there is a size limitation of RAM buffer(2K bytes). To support large-page NAND chips with greater than 2K pagesize, we need a large buffer, but we don't know pagesize before calling
nand_scan_ident(), for more flexible and to identify different cases of large-page greater than 2K bytes, we have aboard_nand_init_tail()betweennand_scan_ident()andnand_scan_tail().Signed-off-by Shengzhou Liu <[email protected]>--- drivers/mtd/nand/nand.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)drivers/mtd/nand/nand.c +0
-0
drivers/mtd/nand/nand.c static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIS · line 48
Quoted 10 lines
drivers/mtd/nand/nand.c +7
-0@@ -39,6 +39,13 @@ static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LISstatic const char default_nand_name[] ="nand" ;static __attribute__((unused))char dev_name[CONFIG_SYS_MAX_NAND_DEVICE ][8 ]; +int __board_nand_init_tail (struct mtd_info *mtd,struct nand_chip *nand) +{ +/* Allow for init at tail in controller-specific file for some reason */ +} +void board_nand_init_tail (struct mtd_info *mtd,struct nand_chip *nand) +__attribute__((weak,alias ("__board_nand_init_tail" ))); +
Something is wrong here...
You need to decide what should be the return type...
Either make it void and change the return type of the default function, or make it an int and add a return statement.
Quoted 17 lines
drivers/mtd/nand/nand.c +6
-1static void nand_init_chip (struct mtd_info *mtd,struct nand_chip *nand,ulong base_addr) {@@ -51,7 +58,12 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;if (board_nand_init (nand) ==0 ) { -if (nand_scan (mtd, maxchips) ==0 ) { +if (!nand_scan_ident (mtd, maxchips,NULL )) { +board_nand_init_tail (mtd, nand); +if (nand_scan_tail (mtd)) { + mtd->name =NULL ; +return ; + }if (!mtd->name) mtd->name = (char *)default_nand_name;#ifdef CONFIG_NEEDS_MANUAL_RELOC
Signature · 2 lines
Regards, Igor.