[U-Boot] [PATCH v2] mtd: resync with Linux-3.7.1

Scott Wood scottwood at freescale.com
Fri Jan 18 23:33:04 CET 2013


On 01/18/2013 06:00:28 AM, Sergey Lapin wrote:
> diff --git a/drivers/mtd/nand/bfin_nand.c  
> b/drivers/mtd/nand/bfin_nand.c
> index c7ddbb2..7e755e8 100644
> --- a/drivers/mtd/nand/bfin_nand.c
> +++ b/drivers/mtd/nand/bfin_nand.c
> @@ -374,9 +374,11 @@ int board_nand_init(struct nand_chip *chip)
>  		if (!NAND_IS_512()) {
>  			chip->ecc.bytes = 3;
>  			chip->ecc.size = 256;
> +			chip->ecc.strength = 1;
>  		} else {
>  			chip->ecc.bytes = 6;
>  			chip->ecc.size = 512;
> +			chip->ecc.strength = 2;
>  		}

Hmm, I'm not sure that ecc.strength should be set to 2 here, if it's  
really two separate 256-byte regions each of which can correct 1 bit.   
2 bit correction can only be done under certain circumstances (i.e. the  
errors are not in the same half).

Linux does the same thing you've done, but that was also a "fix all the  
drivers" patch, so I'd like the input of someone familiar with the  
hardware.  CCing Mike Frysinger.  Maybe the driver should be reporting  
an ECC block size of 256 bytes?  Or at least internally return the  
number of bitflips from the half that had more bitflips.

>  		chip->ecc.mode = NAND_ECC_HW;
>  		chip->ecc.calculate = bfin_nfc_calculate_ecc;
> diff --git a/drivers/mtd/nand/davinci_nand.c  
> b/drivers/mtd/nand/davinci_nand.c
> index 04b24f3..9777878 100644
> --- a/drivers/mtd/nand/davinci_nand.c
> +++ b/drivers/mtd/nand/davinci_nand.c
> @@ -613,6 +613,7 @@ void davinci_nand_init(struct nand_chip *nand)
>  	nand->ecc.mode = NAND_ECC_HW;
>  	nand->ecc.size = 512;
>  	nand->ecc.bytes = 3;
> +	nand->ecc.strength = 4;
>  	nand->ecc.calculate = nand_davinci_calculate_ecc;
>  	nand->ecc.correct  = nand_davinci_correct_data;
>  	nand->ecc.hwctl  = nand_davinci_enable_hwecc;

This is in the 1-bit ECC #ifdef, so ecc.strength should be 1, and later  
in CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST in should be set to 4.

> diff --git a/drivers/mtd/nand/diskonchip.c  
> b/drivers/mtd/nand/diskonchip.c
> index 104d97f..4cd741e 100644
> --- a/drivers/mtd/nand/diskonchip.c
> +++ b/drivers/mtd/nand/diskonchip.c
> @@ -1658,6 +1658,7 @@ static int __init doc_probe(unsigned long  
> physadr)
>  	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
>  	nand->ecc.size		= 512;
>  	nand->ecc.bytes		= 6;
> +	nand->ecc.strength	= 2;
>  	nand->bbt_options	= NAND_BBT_USE_FLASH;
> 
>  	doc->physadr		= physadr;
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c  
> b/drivers/mtd/nand/fsl_elbc_nand.c
> index 65edbf5..c3f350d 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -781,6 +781,12 @@ static int fsl_elbc_chip_init(int devnum, u8  
> *addr)
>  		nand->ecc.size = 512;
>  		nand->ecc.bytes = 3;
>  		nand->ecc.steps = 1;
> +		chip->ecc.strength = 1;
> +		/*
> +		 * FIXME: can hardware ecc correct 4 bitflips if page  
> size is
> +		 * 2k?  Then does hardware report number of corrections  
> for this
> +		 * case?  If so, ecc_stats reporting needs to be fixed  
> as well.
> +		 */

It can correct 1 bitflip per 512 bytes.  This is a similar situation to  
blackfin (as far as I can tell), except that we report the actual  
hardware ECC block size, so ecc.strength = 1 is clearly correct.

As for ecc_stats, read_page() is supposed to return the number of  
bitflips from the ECC block with the most bitflips (see the generic  
read_page implementations).  This change was made to fsl_elbc_nand.c in  
Linux.  Note that all of the conversions of read_page() functions to  
simply return zero seem to be incorrect, and should be returning  
max_bitflips.

> diff --git a/drivers/mtd/nand/fsl_ifc_nand.c  
> b/drivers/mtd/nand/fsl_ifc_nand.c
> index 5d47b40..823a2eb 100644
> --- a/drivers/mtd/nand/fsl_ifc_nand.c
> +++ b/drivers/mtd/nand/fsl_ifc_nand.c
> @@ -871,6 +871,7 @@ int board_nand_init(struct nand_chip *nand)
>  	/* Hardware generates ECC per 512 Bytes */
>  	nand->ecc.size = 512;
>  	nand->ecc.bytes = 8;
> +	nand->ecc.strength = 1;
> 
>  	switch (csor & CSOR_NAND_PGS_MASK) {
>  	case CSOR_NAND_PGS_512:

IFC has ECC strength of 4 or 8 depending on ECC mode.  It also needs  
max_bitflips handling in read_page().

> diff --git a/drivers/mtd/nand/jz4740_nand.c  
> b/drivers/mtd/nand/jz4740_nand.c
> index 3ec34f3..3f64dc3 100644
> --- a/drivers/mtd/nand/jz4740_nand.c
> +++ b/drivers/mtd/nand/jz4740_nand.c
> @@ -253,6 +253,11 @@ int board_nand_init(struct nand_chip *nand)
>  	nand->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
>  	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
>  	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
> +	nand->ecc.strength	= 2;
> +	/*
> +	 * FIXME: ecc_strength value of 2 bits per 512 bytes of data is  
> a
> +	 * conservative guess, given 9 ecc bytes and reed-solomon alg.
> +	 */
>  	nand->ecc.layout	= &qi_lb60_ecclayout_2gb;
>  	nand->chip_delay	= 50;
>  	nand->options		= NAND_USE_FLASH_BBT;

The Linux driver sets ecc.strength to 4, though that may have been  
after Linux 3.7.

> diff --git a/drivers/mtd/nand/tegra_nand.c  
> b/drivers/mtd/nand/tegra_nand.c
> index 854fd21..6afbec6 100644
> --- a/drivers/mtd/nand/tegra_nand.c
> +++ b/drivers/mtd/nand/tegra_nand.c
> @@ -1014,6 +1014,7 @@ int tegra_nand_init(struct nand_chip *nand, int  
> devnum)
>  	nand->ecc.write_page_raw = nand_write_page_raw;
>  	nand->ecc.read_oob = nand_read_oob;
>  	nand->ecc.write_oob = nand_write_oob;
> +	nand->ecc.strength = 1;
>  	nand->select_chip = nand_select_chip;
>  	nand->dev_ready  = nand_dev_ready;
>  	nand->priv = &nand_ctrl;

Jim, does ecc.strength = 1 look correct for Tegra?  It has more ECC  
bytes than I'd expect for 1-bit correction (does "4 symbol correct ECC"  
mean "4-bit correctable ECC"?).

-Scott


More information about the U-Boot mailing list