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: nicolas.ferre@atmel.com, linux-mtd@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org, dedekind1@gmail.com
Subject: Re: [PATCH v2 4/4] mtd: atmel_nand: enable Nand Flash Controller (NFC) write via sram
Date: Mon, 27 May 2013 18:01:42 +0800	[thread overview]
Message-ID: <51A32F06.9040807@atmel.com> (raw)
In-Reply-To: <20130524201150.GN24476@game.jcrosoft.org>

On 5/25/2013 4:11 AM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 17:51 Fri 17 May     , Josh Wu wrote:
>> This patch enable writing nand flash via NFC SRAM. It will minimize the CPU
>> overhead. The SRAM write only support ECC_NONE and ECC_HW with PMECC.
>>
>> This driver has been tested on SAMA5D3X-EK with JFFS2, YAFFS2, UBIFS and
>> mtd-utils.
>>
>> Here is part of mtd_speedtest (writing test) result, compare with non-NFC
>> writing, it reduces %65 cpu load with loss %12 speed.
> we may want to enable only read on sram and not write as the write speed can
> be critic on some system

I will add one more option to allow user to choose to use NFC write via 
sram.

Best Regards,
Josh Wu

>
> Best Regards,
> J.
>> - commands use to test:
>>    # insmod /mnt/mtd_speedtest.ko dev=2 &
>>    # top -n 30 -d 1 | grep speedtest
>>
>> - test result:
>> =================================================
>> mtd_speedtest: MTD device: 2
>> mtd_speedtest: MTD device size 41943040, eraseblock size 131072, page size 2048, count of eraseblocks 320, pages per eraseblock 64, OOB size 64
>> mtd_speedtest: testing eraseblock write speed
>>    509   495 root     D     1164   0%   7% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%   8% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     R     1164   0%   5% insmod /mnt/mtd_speedtest.ko dev=2
>> mtd_speedtest: eraseblock write speed is 5194 KiB/s
>> mtd_speedtest: testing page write speed
>>    509   495 root     D     1164   0%  32% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%  27% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%  25% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%  30% insmod /mnt/mtd_speedtest.ko dev=2
>> mtd_speedtest: page write speed is 5024 KiB/s
>>
>> Signed-off-by: Josh Wu <josh.wu@atmel.com>
>> ---
>> v1 --> v2:
>>    use NAND_ECC_WRITE instead of use new defined pass to pmecc_enable().
>>    report a error if use a partial page write via nfc sram.
>>
>>   drivers/mtd/nand/atmel_nand.c |   94 +++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 90 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
>> index c10cd71..4490bd6 100644
>> --- a/drivers/mtd/nand/atmel_nand.c
>> +++ b/drivers/mtd/nand/atmel_nand.c
>> @@ -99,6 +99,7 @@ struct atmel_nfc {
>>   
>>   	/* Point to the sram bank which include readed data via NFC */
>>   	void __iomem		*data_in_sram;
>> +	bool			will_write_sram;
>>   };
>>   
>>   struct atmel_nand_host {
>> @@ -218,6 +219,16 @@ static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
>>   		*t++ = readl_relaxed(s++);
>>   }
>>   
>> +static void memcpy32_toio(void __iomem *trg, const void *src, int size)
>> +{
>> +	int i;
>> +	u32 __iomem *t = trg;
>> +	const u32 *s = src;
>> +
>> +	for (i = 0; i < (size >> 2); i++)
>> +		writel_relaxed(*s++, t++);
>> +}
>> +
>>   /*
>>    * Minimal-overhead PIO for data access.
>>    */
>> @@ -339,7 +350,11 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
>>   		dma_dst_addr = phys_addr;
>>   	} else {
>>   		dma_src_addr = phys_addr;
>> -		dma_dst_addr = host->io_phys;
>> +
>> +		if (host->use_nfc_sram)
>> +			dma_dst_addr = nfc_sram_phys(host);
>> +		else
>> +			dma_dst_addr = host->io_phys;
>>   	}
>>   
>>   	tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
>> @@ -919,9 +934,10 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
>>   	int i, j;
>>   	unsigned long end_time;
>>   
>> -	pmecc_enable(host, NAND_ECC_WRITE);
>> -
>> -	chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
>> +	if (!host->use_nfc_sram) {
>> +		pmecc_enable(host, NAND_ECC_WRITE);
>> +		chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
>> +	}
>>   
>>   	end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
>>   	while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
>> @@ -1805,6 +1821,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
>>   	case NAND_CMD_SEQIN:
>>   	case NAND_CMD_RNDIN:
>>   		nfcwr = NFCADDR_CMD_NFCWR;
>> +		if (host->nfc.will_write_sram && command == NAND_CMD_SEQIN)
>> +			dataen = NFCADDR_CMD_DATAEN;
>>   		break;
>>   	default:
>>   		break;
>> @@ -1849,6 +1867,68 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
>>   	}
>>   }
>>   
>> +static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
>> +			uint32_t offset, int data_len, const uint8_t *buf,
>> +			int oob_required, int page, int cached, int raw)
>> +{
>> +	int cfg, len;
>> +	int status = 0;
>> +	struct atmel_nand_host *host = chip->priv;
>> +	void __iomem *sram = host->nfc.sram_bank0 + nfc_get_sram_off(host);
>> +
>> +	/* Subpage write is not supported */
>> +	if (offset || (data_len < mtd->writesize))
>> +		return -EINVAL;
>> +
>> +	cfg = nfc_readl(host->nfc.hsmc_regs, CFG);
>> +	len = mtd->writesize;
>> +
>> +	if (unlikely(raw)) {
>> +		len += mtd->oobsize;
>> +		nfc_writel(host->nfc.hsmc_regs, CFG, cfg | ATMEL_HSMC_WSPARE);
>> +	} else
>> +		nfc_writel(host->nfc.hsmc_regs, CFG, cfg & ~ATMEL_HSMC_WSPARE);
>> +
>> +	/* Copy page data to sram that will write to nand via NFC */
>> +	if (use_dma) {
>> +		if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0)
>> +			/* Fall back to use cpu copy */
>> +			memcpy32_toio(sram, buf, len);
>> +	} else {
>> +		memcpy32_toio(sram, buf, len);
>> +	}
>> +
>> +	if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
>> +		/*
>> +		 * When use NFC sram, need set up PMECC before send
>> +		 * NAND_CMD_SEQIN command. Since when the nand command
>> +		 * is sent, nfc will do transfer from sram and nand.
>> +		 */
>> +		pmecc_enable(host, NAND_ECC_WRITE);
>> +
>> +	host->nfc.will_write_sram = true;
>> +	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
>> +	host->nfc.will_write_sram = false;
>> +
>> +	if (likely(!raw))
>> +		/* Need to write ecc into oob */
>> +		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
>> +
>> +	if (status < 0)
>> +		return status;
>> +
>> +	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
>> +	status = chip->waitfunc(mtd, chip);
>> +
>> +	if ((status & NAND_STATUS_FAIL) && (chip->errstat))
>> +		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
>> +
>> +	if (status & NAND_STATUS_FAIL)
>> +		return -EIO;
>> +
>> +	return 0;
>> +}
>> +
>>   static int nfc_sram_init(struct mtd_info *mtd)
>>   {
>>   	struct nand_chip *chip = mtd->priv;
>> @@ -1887,10 +1967,16 @@ static int nfc_sram_init(struct mtd_info *mtd)
>>   
>>   	nfc_writel(host->nfc.hsmc_regs, CFG, cfg_nfc);
>>   
>> +	host->nfc.will_write_sram = false;
>>   	nfc_set_sram_bank(host, 0);
>>   
>>   	dev_info(host->dev, "Using NFC Sram\n");
>>   
>> +	/* Use Write page with NFC SRAM only for PMECC or ECC NONE. */
>> +	if ((chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) ||
>> +			chip->ecc.mode == NAND_ECC_NONE)
>> +		chip->write_page = nfc_sram_write_page;
>> +
>>   	return 0;
>>   }
>>   
>> -- 
>> 1.7.9.5
>>

WARNING: multiple messages have this Message-ID (diff)
From: josh.wu@atmel.com (Josh Wu)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 4/4] mtd: atmel_nand: enable Nand Flash Controller (NFC) write via sram
Date: Mon, 27 May 2013 18:01:42 +0800	[thread overview]
Message-ID: <51A32F06.9040807@atmel.com> (raw)
In-Reply-To: <20130524201150.GN24476@game.jcrosoft.org>

On 5/25/2013 4:11 AM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 17:51 Fri 17 May     , Josh Wu wrote:
>> This patch enable writing nand flash via NFC SRAM. It will minimize the CPU
>> overhead. The SRAM write only support ECC_NONE and ECC_HW with PMECC.
>>
>> This driver has been tested on SAMA5D3X-EK with JFFS2, YAFFS2, UBIFS and
>> mtd-utils.
>>
>> Here is part of mtd_speedtest (writing test) result, compare with non-NFC
>> writing, it reduces %65 cpu load with loss %12 speed.
> we may want to enable only read on sram and not write as the write speed can
> be critic on some system

I will add one more option to allow user to choose to use NFC write via 
sram.

Best Regards,
Josh Wu

>
> Best Regards,
> J.
>> - commands use to test:
>>    # insmod /mnt/mtd_speedtest.ko dev=2 &
>>    # top -n 30 -d 1 | grep speedtest
>>
>> - test result:
>> =================================================
>> mtd_speedtest: MTD device: 2
>> mtd_speedtest: MTD device size 41943040, eraseblock size 131072, page size 2048, count of eraseblocks 320, pages per eraseblock 64, OOB size 64
>> mtd_speedtest: testing eraseblock write speed
>>    509   495 root     D     1164   0%   7% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%   8% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     R     1164   0%   5% insmod /mnt/mtd_speedtest.ko dev=2
>> mtd_speedtest: eraseblock write speed is 5194 KiB/s
>> mtd_speedtest: testing page write speed
>>    509   495 root     D     1164   0%  32% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%  27% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%  25% insmod /mnt/mtd_speedtest.ko dev=2
>>    509   495 root     D     1164   0%  30% insmod /mnt/mtd_speedtest.ko dev=2
>> mtd_speedtest: page write speed is 5024 KiB/s
>>
>> Signed-off-by: Josh Wu <josh.wu@atmel.com>
>> ---
>> v1 --> v2:
>>    use NAND_ECC_WRITE instead of use new defined pass to pmecc_enable().
>>    report a error if use a partial page write via nfc sram.
>>
>>   drivers/mtd/nand/atmel_nand.c |   94 +++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 90 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
>> index c10cd71..4490bd6 100644
>> --- a/drivers/mtd/nand/atmel_nand.c
>> +++ b/drivers/mtd/nand/atmel_nand.c
>> @@ -99,6 +99,7 @@ struct atmel_nfc {
>>   
>>   	/* Point to the sram bank which include readed data via NFC */
>>   	void __iomem		*data_in_sram;
>> +	bool			will_write_sram;
>>   };
>>   
>>   struct atmel_nand_host {
>> @@ -218,6 +219,16 @@ static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
>>   		*t++ = readl_relaxed(s++);
>>   }
>>   
>> +static void memcpy32_toio(void __iomem *trg, const void *src, int size)
>> +{
>> +	int i;
>> +	u32 __iomem *t = trg;
>> +	const u32 *s = src;
>> +
>> +	for (i = 0; i < (size >> 2); i++)
>> +		writel_relaxed(*s++, t++);
>> +}
>> +
>>   /*
>>    * Minimal-overhead PIO for data access.
>>    */
>> @@ -339,7 +350,11 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
>>   		dma_dst_addr = phys_addr;
>>   	} else {
>>   		dma_src_addr = phys_addr;
>> -		dma_dst_addr = host->io_phys;
>> +
>> +		if (host->use_nfc_sram)
>> +			dma_dst_addr = nfc_sram_phys(host);
>> +		else
>> +			dma_dst_addr = host->io_phys;
>>   	}
>>   
>>   	tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
>> @@ -919,9 +934,10 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
>>   	int i, j;
>>   	unsigned long end_time;
>>   
>> -	pmecc_enable(host, NAND_ECC_WRITE);
>> -
>> -	chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
>> +	if (!host->use_nfc_sram) {
>> +		pmecc_enable(host, NAND_ECC_WRITE);
>> +		chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
>> +	}
>>   
>>   	end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
>>   	while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
>> @@ -1805,6 +1821,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
>>   	case NAND_CMD_SEQIN:
>>   	case NAND_CMD_RNDIN:
>>   		nfcwr = NFCADDR_CMD_NFCWR;
>> +		if (host->nfc.will_write_sram && command == NAND_CMD_SEQIN)
>> +			dataen = NFCADDR_CMD_DATAEN;
>>   		break;
>>   	default:
>>   		break;
>> @@ -1849,6 +1867,68 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
>>   	}
>>   }
>>   
>> +static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
>> +			uint32_t offset, int data_len, const uint8_t *buf,
>> +			int oob_required, int page, int cached, int raw)
>> +{
>> +	int cfg, len;
>> +	int status = 0;
>> +	struct atmel_nand_host *host = chip->priv;
>> +	void __iomem *sram = host->nfc.sram_bank0 + nfc_get_sram_off(host);
>> +
>> +	/* Subpage write is not supported */
>> +	if (offset || (data_len < mtd->writesize))
>> +		return -EINVAL;
>> +
>> +	cfg = nfc_readl(host->nfc.hsmc_regs, CFG);
>> +	len = mtd->writesize;
>> +
>> +	if (unlikely(raw)) {
>> +		len += mtd->oobsize;
>> +		nfc_writel(host->nfc.hsmc_regs, CFG, cfg | ATMEL_HSMC_WSPARE);
>> +	} else
>> +		nfc_writel(host->nfc.hsmc_regs, CFG, cfg & ~ATMEL_HSMC_WSPARE);
>> +
>> +	/* Copy page data to sram that will write to nand via NFC */
>> +	if (use_dma) {
>> +		if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0)
>> +			/* Fall back to use cpu copy */
>> +			memcpy32_toio(sram, buf, len);
>> +	} else {
>> +		memcpy32_toio(sram, buf, len);
>> +	}
>> +
>> +	if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
>> +		/*
>> +		 * When use NFC sram, need set up PMECC before send
>> +		 * NAND_CMD_SEQIN command. Since when the nand command
>> +		 * is sent, nfc will do transfer from sram and nand.
>> +		 */
>> +		pmecc_enable(host, NAND_ECC_WRITE);
>> +
>> +	host->nfc.will_write_sram = true;
>> +	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
>> +	host->nfc.will_write_sram = false;
>> +
>> +	if (likely(!raw))
>> +		/* Need to write ecc into oob */
>> +		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
>> +
>> +	if (status < 0)
>> +		return status;
>> +
>> +	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
>> +	status = chip->waitfunc(mtd, chip);
>> +
>> +	if ((status & NAND_STATUS_FAIL) && (chip->errstat))
>> +		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
>> +
>> +	if (status & NAND_STATUS_FAIL)
>> +		return -EIO;
>> +
>> +	return 0;
>> +}
>> +
>>   static int nfc_sram_init(struct mtd_info *mtd)
>>   {
>>   	struct nand_chip *chip = mtd->priv;
>> @@ -1887,10 +1967,16 @@ static int nfc_sram_init(struct mtd_info *mtd)
>>   
>>   	nfc_writel(host->nfc.hsmc_regs, CFG, cfg_nfc);
>>   
>> +	host->nfc.will_write_sram = false;
>>   	nfc_set_sram_bank(host, 0);
>>   
>>   	dev_info(host->dev, "Using NFC Sram\n");
>>   
>> +	/* Use Write page with NFC SRAM only for PMECC or ECC NONE. */
>> +	if ((chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) ||
>> +			chip->ecc.mode == NAND_ECC_NONE)
>> +		chip->write_page = nfc_sram_write_page;
>> +
>>   	return 0;
>>   }
>>   
>> -- 
>> 1.7.9.5
>>

  reply	other threads:[~2013-05-27 10:01 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-17  9:51 [PATCH v2 0/4] mtd: atmel_nand: enable Nand Flash Controller (NFC) support Josh Wu
2013-05-17  9:51 ` Josh Wu
2013-05-17  9:51 ` [PATCH v2 1/4] mtd: atmel_nand: replace pmecc enable code with one function Josh Wu
2013-05-17  9:51   ` Josh Wu
2013-05-17  9:51 ` [PATCH v2 2/4] mtd: atmel_nand: add Nand Flash Controller (NFC) support Josh Wu
2013-05-17  9:51   ` Josh Wu
2013-05-24 20:09   ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-24 20:09     ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-27  9:56     ` Josh Wu
2013-05-27  9:56       ` Josh Wu
2013-05-27 10:26       ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-27 10:26         ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-30  6:14         ` Josh Wu
2013-05-30  6:14           ` Josh Wu
2013-05-30 16:54           ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-30 16:54             ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-17  9:51 ` [PATCH v2 3/4] mtd: atmel_nand: enable Nand Flash Controller (NFC) read data via sram Josh Wu
2013-05-17  9:51   ` Josh Wu
2013-05-17  9:51 ` [PATCH v2 4/4] mtd: atmel_nand: enable Nand Flash Controller (NFC) write " Josh Wu
2013-05-17  9:51   ` Josh Wu
2013-05-24 20:11   ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-24 20:11     ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-27 10:01     ` Josh Wu [this message]
2013-05-27 10:01       ` Josh Wu
2013-05-24 19:55 ` [PATCH v2 0/4] mtd: atmel_nand: enable Nand Flash Controller (NFC) support Jean-Christophe PLAGNIOL-VILLARD
2013-05-24 19:55   ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-27  9:59   ` Josh Wu
2013-05-27  9:59     ` 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=51A32F06.9040807@atmel.com \
    --to=josh.wu@atmel.com \
    --cc=dedekind1@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.