All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Wu <josh.wu@atmel.com>
To: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: hongxu.cn@gmail.com, nicolas.ferre@atmel.com,
	linux-mtd@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org, dedekind1@gmail.com
Subject: Re: [PATCH v5] MTD: atmel_nand: Update driver to support Programmable Multibit ECC controller
Date: Mon, 07 May 2012 10:47:30 +0800	[thread overview]
Message-ID: <4FA737C2.9040806@atmel.com> (raw)
In-Reply-To: <20120503134254.GA7788@game.jcrosoft.org>

Hi, J.C.

On 5/3/2012 9:42 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 20:37 Thu 03 May     , Josh Wu wrote:
>> The Programmable Multibit ECC (PMECC) controller is a programmable binary
>> BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller
>> can be used to support both SLC and MLC NAND Flash devices. It supports to
>> generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data.
>>
>> To use this driver, the user needs to pass in the correction capability and
>> the sector size.
>>
>> This driver has been tested on AT91SAM9X5-EK and AT91SAM9N12-EK with JFFS2,
>> YAFFS2, UBIFS and mtd-utils.
>>
>> Signed-off-by: Hong Xu<hong.xu@atmel.com>
>> Signed-off-by: Josh Wu<josh.wu@atmel.com>
>> ---
>> Hi,
>>
>> Since Hong Xu will not work on pmecc part. so I send out this patch base Hong Xu's latest work.
>>
>> Changes since v4,
>> 	fix typo and checkpatch warnings.
>> 	fix according to JC's suggestion. replace cpu_is_xxx() with DT
>> 	modify dt binding atmel nand document to add pmecc support.
>> 	tested in sam9263 without break hw ecc.
>> 	add ecc.strength.
>>
>>   .../devicetree/bindings/mtd/atmel-nand.txt         |    5 +
>>   drivers/mtd/nand/atmel_nand.c                      |  955 ++++++++++++++++++--
>>   drivers/mtd/nand/atmel_nand_ecc.h                  |  123 ++-
>>   3 files changed, 1004 insertions(+), 79 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
>> index a200695..8936175 100644
>> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
>> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
>> @@ -16,9 +16,14 @@ Optional properties:
>>   - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
>>     Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
>>     "soft_bch".
>> +- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
>> +  Controller. Supported values are: 2, 4, 8, 12, 24.
> you need to use it in the code instead of hardcoding it so
>> +- atmel,sector-size : sector size for ECC computation. Supported values are:
>> +  512, 1024.
>>   - nand-bus-width : 8 or 16 bus width if not present 8
>>   - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
>>
>> +
>>   Examples:
>>   nand0: nand@40000000,0 {
>>   	compatible = "atmel,at91rm9200-nand";
> <snip>
>> +
>> +	cap = host->correction_cap;
>> +	sector_size = host->sector_size;
>> +	dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n",
>> +		 cap, sector_size);
>> +
>> +	/* Sanity check */
>> +	if ((sector_size != 512)&&  (sector_size != 1024)) {
>> +		dev_err(host->dev, "Unsupported PMECC sector size: %d; " \
>> +			"Valid sector size: 512 or 1024 bytes\n", sector_size);
>> +		return -EINVAL;
>> +	}
>> +	if ((cap != 2)&&  (cap != 4)&&  (cap != 8)&&  (cap != 12)&&
>> +	    (cap != 24)) {
>> +		dev_err(host->dev, "Unsupported PMECC correction capability," \
>> +			" Valid one is either 2, 4, 8, 12 or 24\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	nand_chip =&host->nand_chip;
>> +	mtd =&host->mtd;
>> +
>> +	nand_chip->ecc.mode = NAND_ECC_SOFT;	/* By default */
>> +
>> +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> +	if (!regs) {
>> +		dev_warn(host->dev, "Can't get I/O resource regs, " \
>> +				"rolling back on software ECC\n");
>> +		return 0;
>> +	}
>> +
>> +	host->ecc = ioremap(regs->start, resource_size(regs));
>> +	if (host->ecc == NULL) {
>> +		dev_err(host->dev, "ioremap failed\n");
>> +		err_no = -EIO;
>> +		goto err_pmecc_ioremap;
>> +	}
>> +
>> +	regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> +	regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
>> +	if (regs_pmerr&&  regs_rom) {
>> +		host->pmerrloc_base = ioremap(regs_pmerr->start,
>> +			resource_size(regs_pmerr));
>> +		host->rom_base = ioremap(regs_rom->start,
>> +			resource_size(regs_rom));
>> +
>> +		if (host->pmerrloc_base&&  host->rom_base) {
>> +			nand_chip->ecc.mode = NAND_ECC_HW;
>> +			nand_chip->ecc.read_page =
>> +				atmel_nand_pmecc_read_page;
>> +			nand_chip->ecc.write_page =
>> +				atmel_nand_pmecc_write_page;
>> +		} else {
>> +			dev_err(host->dev, "Can not get I/O resource" \
>> +				" for HW PMECC controller!\n");
>> +			err_no = -EIO;
>> +			goto err_pmloc_ioremap;
>> +		}
>> +	}
>> +
>> +	/* ECC is calculated for the whole page (1 step) */
>> +	nand_chip->ecc.size = mtd->writesize;
>> +
>> +	/* set ECC page size and oob layout */
>> +	switch (mtd->writesize) {
>> +	case 2048:
>> +		host->degree = GF_DIMENSION_13;
>> +		host->cw_len = (1<<  host->degree) - 1;
>> +		host->cap = cap;
>> +		host->sector_number = mtd->writesize / sector_size;
>> +		host->ecc_bytes_per_sector = pmecc_get_ecc_bytes(
>> +			host->cap, sector_size);
>> +		host->alpha_to = pmecc_get_alpha_to(host);
>> +		host->index_of = pmecc_get_index_of(host);
>> +
>> +		nand_chip->ecc.steps = 1;
>> +		nand_chip->ecc.strength = cap;
>> +		nand_chip->ecc.bytes = host->ecc_bytes_per_sector *
>> +				       host->sector_number;
>> +		if (nand_chip->ecc.bytes>  mtd->oobsize - 2) {
>> +			dev_err(host->dev, "No room for ECC bytes\n");
>> +			err_no = -EINVAL;
>> +			goto err;
>> +		}
>> +		pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
>> +					mtd->oobsize,
>> +					nand_chip->ecc.bytes);
>> +		nand_chip->ecc.layout =&atmel_pmecc_oobinfo;
>> +		break;
>> +	case 512:
>> +	case 1024:
>> +	case 4096:
>> +		/* TODO */
>> +		dev_warn(host->dev, "Only 2048 page size is currently " \
>> +			"supported for PMECC, rolling back to Software ECC\n");
>> +	default:
>> +		/* page size not handled by HW ECC */
>> +		/* switching back to soft ECC */
>> +		nand_chip->ecc.mode = NAND_ECC_SOFT;
>> +		nand_chip->ecc.calculate = NULL;
>> +		nand_chip->ecc.correct = NULL;
>> +		nand_chip->ecc.hwctl = NULL;
>> +		nand_chip->ecc.read_page = NULL;
>> +		nand_chip->ecc.write_page = NULL;
>> +		nand_chip->ecc.postpad = 0;
>> +		nand_chip->ecc.prepad = 0;
>> +		nand_chip->ecc.bytes = 0;
>> +		err_no = 0;
>> +		goto err;
>> +	}
>> +
>> +	atmel_pmecc_core_init(mtd);
>> +
>> +	return 0;
>> +
>> +err:
>> +err_pmloc_ioremap:
>> +	iounmap(host->ecc);
>> +	if (host->pmerrloc_base)
>> +		iounmap(host->pmerrloc_base);
>> +	if (host->rom_base)
>> +		iounmap(host->rom_base);
>> +err_pmecc_ioremap:
>> +	return err_no;
>> +}
>> +
>> +/*
>>    * Calculate HW ECC
>>    *
>>    * function called after a write
>> @@ -474,6 +1212,15 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
>>   }
>>
>>   #if defined(CONFIG_OF)
>> +static int cpu_has_pmecc(void)
>> +{
>> +	unsigned long dt_root;
>> +
>> +	dt_root = of_get_flat_dt_root();
>> +	return of_flat_dt_is_compatible(dt_root, "atmel,at91sam9n12") ||
>> +		of_flat_dt_is_compatible(dt_root, "atmel,at91sam9x5");
> you need to detect it at probe time
OK. I will do it.
> and you need to put the first compatbile only no need to put a list
Do you mean only need check the compatible string "atmel,at91sam9n12"? 
Since 9x5 and 9n12 both support pmecc. so I check whether is 9n12 or 9x5.

or you mean the 9n12 is subset from 9x5. I checked at91sam9n12ek.dts, 
there is no compatible string like: "atmel,at91sam9x5".
>
> Best Regards,
> J.
Thanks.
Best Regards,
Josh Wu

WARNING: multiple messages have this Message-ID (diff)
From: josh.wu@atmel.com (Josh Wu)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v5] MTD: atmel_nand: Update driver to support Programmable Multibit ECC controller
Date: Mon, 07 May 2012 10:47:30 +0800	[thread overview]
Message-ID: <4FA737C2.9040806@atmel.com> (raw)
In-Reply-To: <20120503134254.GA7788@game.jcrosoft.org>

Hi, J.C.

On 5/3/2012 9:42 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 20:37 Thu 03 May     , Josh Wu wrote:
>> The Programmable Multibit ECC (PMECC) controller is a programmable binary
>> BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller
>> can be used to support both SLC and MLC NAND Flash devices. It supports to
>> generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data.
>>
>> To use this driver, the user needs to pass in the correction capability and
>> the sector size.
>>
>> This driver has been tested on AT91SAM9X5-EK and AT91SAM9N12-EK with JFFS2,
>> YAFFS2, UBIFS and mtd-utils.
>>
>> Signed-off-by: Hong Xu<hong.xu@atmel.com>
>> Signed-off-by: Josh Wu<josh.wu@atmel.com>
>> ---
>> Hi,
>>
>> Since Hong Xu will not work on pmecc part. so I send out this patch base Hong Xu's latest work.
>>
>> Changes since v4,
>> 	fix typo and checkpatch warnings.
>> 	fix according to JC's suggestion. replace cpu_is_xxx() with DT
>> 	modify dt binding atmel nand document to add pmecc support.
>> 	tested in sam9263 without break hw ecc.
>> 	add ecc.strength.
>>
>>   .../devicetree/bindings/mtd/atmel-nand.txt         |    5 +
>>   drivers/mtd/nand/atmel_nand.c                      |  955 ++++++++++++++++++--
>>   drivers/mtd/nand/atmel_nand_ecc.h                  |  123 ++-
>>   3 files changed, 1004 insertions(+), 79 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
>> index a200695..8936175 100644
>> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
>> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
>> @@ -16,9 +16,14 @@ Optional properties:
>>   - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
>>     Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
>>     "soft_bch".
>> +- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
>> +  Controller. Supported values are: 2, 4, 8, 12, 24.
> you need to use it in the code instead of hardcoding it so
>> +- atmel,sector-size : sector size for ECC computation. Supported values are:
>> +  512, 1024.
>>   - nand-bus-width : 8 or 16 bus width if not present 8
>>   - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
>>
>> +
>>   Examples:
>>   nand0: nand at 40000000,0 {
>>   	compatible = "atmel,at91rm9200-nand";
> <snip>
>> +
>> +	cap = host->correction_cap;
>> +	sector_size = host->sector_size;
>> +	dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n",
>> +		 cap, sector_size);
>> +
>> +	/* Sanity check */
>> +	if ((sector_size != 512)&&  (sector_size != 1024)) {
>> +		dev_err(host->dev, "Unsupported PMECC sector size: %d; " \
>> +			"Valid sector size: 512 or 1024 bytes\n", sector_size);
>> +		return -EINVAL;
>> +	}
>> +	if ((cap != 2)&&  (cap != 4)&&  (cap != 8)&&  (cap != 12)&&
>> +	    (cap != 24)) {
>> +		dev_err(host->dev, "Unsupported PMECC correction capability," \
>> +			" Valid one is either 2, 4, 8, 12 or 24\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	nand_chip =&host->nand_chip;
>> +	mtd =&host->mtd;
>> +
>> +	nand_chip->ecc.mode = NAND_ECC_SOFT;	/* By default */
>> +
>> +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> +	if (!regs) {
>> +		dev_warn(host->dev, "Can't get I/O resource regs, " \
>> +				"rolling back on software ECC\n");
>> +		return 0;
>> +	}
>> +
>> +	host->ecc = ioremap(regs->start, resource_size(regs));
>> +	if (host->ecc == NULL) {
>> +		dev_err(host->dev, "ioremap failed\n");
>> +		err_no = -EIO;
>> +		goto err_pmecc_ioremap;
>> +	}
>> +
>> +	regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> +	regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
>> +	if (regs_pmerr&&  regs_rom) {
>> +		host->pmerrloc_base = ioremap(regs_pmerr->start,
>> +			resource_size(regs_pmerr));
>> +		host->rom_base = ioremap(regs_rom->start,
>> +			resource_size(regs_rom));
>> +
>> +		if (host->pmerrloc_base&&  host->rom_base) {
>> +			nand_chip->ecc.mode = NAND_ECC_HW;
>> +			nand_chip->ecc.read_page =
>> +				atmel_nand_pmecc_read_page;
>> +			nand_chip->ecc.write_page =
>> +				atmel_nand_pmecc_write_page;
>> +		} else {
>> +			dev_err(host->dev, "Can not get I/O resource" \
>> +				" for HW PMECC controller!\n");
>> +			err_no = -EIO;
>> +			goto err_pmloc_ioremap;
>> +		}
>> +	}
>> +
>> +	/* ECC is calculated for the whole page (1 step) */
>> +	nand_chip->ecc.size = mtd->writesize;
>> +
>> +	/* set ECC page size and oob layout */
>> +	switch (mtd->writesize) {
>> +	case 2048:
>> +		host->degree = GF_DIMENSION_13;
>> +		host->cw_len = (1<<  host->degree) - 1;
>> +		host->cap = cap;
>> +		host->sector_number = mtd->writesize / sector_size;
>> +		host->ecc_bytes_per_sector = pmecc_get_ecc_bytes(
>> +			host->cap, sector_size);
>> +		host->alpha_to = pmecc_get_alpha_to(host);
>> +		host->index_of = pmecc_get_index_of(host);
>> +
>> +		nand_chip->ecc.steps = 1;
>> +		nand_chip->ecc.strength = cap;
>> +		nand_chip->ecc.bytes = host->ecc_bytes_per_sector *
>> +				       host->sector_number;
>> +		if (nand_chip->ecc.bytes>  mtd->oobsize - 2) {
>> +			dev_err(host->dev, "No room for ECC bytes\n");
>> +			err_no = -EINVAL;
>> +			goto err;
>> +		}
>> +		pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
>> +					mtd->oobsize,
>> +					nand_chip->ecc.bytes);
>> +		nand_chip->ecc.layout =&atmel_pmecc_oobinfo;
>> +		break;
>> +	case 512:
>> +	case 1024:
>> +	case 4096:
>> +		/* TODO */
>> +		dev_warn(host->dev, "Only 2048 page size is currently " \
>> +			"supported for PMECC, rolling back to Software ECC\n");
>> +	default:
>> +		/* page size not handled by HW ECC */
>> +		/* switching back to soft ECC */
>> +		nand_chip->ecc.mode = NAND_ECC_SOFT;
>> +		nand_chip->ecc.calculate = NULL;
>> +		nand_chip->ecc.correct = NULL;
>> +		nand_chip->ecc.hwctl = NULL;
>> +		nand_chip->ecc.read_page = NULL;
>> +		nand_chip->ecc.write_page = NULL;
>> +		nand_chip->ecc.postpad = 0;
>> +		nand_chip->ecc.prepad = 0;
>> +		nand_chip->ecc.bytes = 0;
>> +		err_no = 0;
>> +		goto err;
>> +	}
>> +
>> +	atmel_pmecc_core_init(mtd);
>> +
>> +	return 0;
>> +
>> +err:
>> +err_pmloc_ioremap:
>> +	iounmap(host->ecc);
>> +	if (host->pmerrloc_base)
>> +		iounmap(host->pmerrloc_base);
>> +	if (host->rom_base)
>> +		iounmap(host->rom_base);
>> +err_pmecc_ioremap:
>> +	return err_no;
>> +}
>> +
>> +/*
>>    * Calculate HW ECC
>>    *
>>    * function called after a write
>> @@ -474,6 +1212,15 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
>>   }
>>
>>   #if defined(CONFIG_OF)
>> +static int cpu_has_pmecc(void)
>> +{
>> +	unsigned long dt_root;
>> +
>> +	dt_root = of_get_flat_dt_root();
>> +	return of_flat_dt_is_compatible(dt_root, "atmel,at91sam9n12") ||
>> +		of_flat_dt_is_compatible(dt_root, "atmel,at91sam9x5");
> you need to detect it at probe time
OK. I will do it.
> and you need to put the first compatbile only no need to put a list
Do you mean only need check the compatible string "atmel,at91sam9n12"? 
Since 9x5 and 9n12 both support pmecc. so I check whether is 9n12 or 9x5.

or you mean the 9n12 is subset from 9x5. I checked at91sam9n12ek.dts, 
there is no compatible string like: "atmel,at91sam9x5".
>
> Best Regards,
> J.
Thanks.
Best Regards,
Josh Wu

  reply	other threads:[~2012-05-07  2:47 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-03 12:37 [PATCH v5] MTD: atmel_nand: Update driver to support Programmable Multibit ECC controller Josh Wu
2012-05-03 12:37 ` Josh Wu
2012-05-03 13:42 ` Jean-Christophe PLAGNIOL-VILLARD
2012-05-03 13:42   ` Jean-Christophe PLAGNIOL-VILLARD
2012-05-07  2:47   ` Josh Wu [this message]
2012-05-07  2:47     ` Josh Wu
2012-05-03 15:25 ` Ivan Djelic
2012-05-03 15:25   ` Ivan Djelic
2012-05-07 10:43   ` Josh Wu
2012-05-07 10:43     ` Josh Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4FA737C2.9040806@atmel.com \
    --to=josh.wu@atmel.com \
    --cc=dedekind1@gmail.com \
    --cc=hongxu.cn@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=nicolas.ferre@atmel.com \
    --cc=plagnioj@jcrosoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.