* [RFC PATCH 0/2] mtd: nand: optimize subpage writes
@ 2014-06-30 10:33 Pekon Gupta
2014-06-30 10:34 ` [RFC PATCH 1/2] mtd: nand: clean nand_write_subpage_hwecc to reduce local variables Pekon Gupta
2014-06-30 10:34 ` [RFC PATCH 2/2] mtd: nand: refactor nand_write_subpage_hwecc to write only relevant subpage data Pekon Gupta
0 siblings, 2 replies; 3+ messages in thread
From: Pekon Gupta @ 2014-06-30 10:33 UTC (permalink / raw)
To: Brian Norris; +Cc: linux-mtd, Pekon Gupta, Ezequiel Garcia, Artem Bityutskiy
This patch cleans and fixes nand_write_subpage_hwecc() for devices supporting
subpages. Devices supporting subpage write must support NAND_CMD_RNDIN(0x80)
As per datasheet following devices support above command
Macronix MX30LF1G08 Figure 13. AC Waveforms for Random Data In (For Page Program)
Samsung K9F1G08U0E Figure 4.9 Page Program Operation with Random Data Input
Micron MT29F[2G|4G]xx Section RANDOM DATA INPUT 85h
Spansion S34ML[xx]G2 Figure 6.11 Page Program Operation with Random Data Input
Toshiba TC58NVG1S3ETAI0 Section: Random Column Address Change in Auto Page Program Operation
- This series needs testing with multiple drivers and above devices to check
full compliance and working of subpage writes.
- Use 'ubiformat -s <subpage-size>' option to format a UBIFS image on subpages
supporting device
Pekon Gupta (2):
mtd: nand: clean nand_write_subpage_hwecc to reduce local variables
mtd: nand: refactor nand_write_subpage_hwecc to write only relevant
subpage data
drivers/mtd/nand/nand_base.c | 51 +++++++++++++++++++-------------------------
1 file changed, 22 insertions(+), 29 deletions(-)
--
1.8.5.1.163.gd7aced9
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/2] mtd: nand: clean nand_write_subpage_hwecc to reduce local variables
2014-06-30 10:33 [RFC PATCH 0/2] mtd: nand: optimize subpage writes Pekon Gupta
@ 2014-06-30 10:34 ` Pekon Gupta
2014-06-30 10:34 ` [RFC PATCH 2/2] mtd: nand: refactor nand_write_subpage_hwecc to write only relevant subpage data Pekon Gupta
1 sibling, 0 replies; 3+ messages in thread
From: Pekon Gupta @ 2014-06-30 10:34 UTC (permalink / raw)
To: Brian Norris; +Cc: linux-mtd, Pekon Gupta, Ezequiel Garcia, Artem Bityutskiy
Use 'struct nand_ecc_ctrl *' instead of 'struct nand_chip *' for de-referenceing
ECC variables.
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
drivers/mtd/nand/nand_base.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index c5c1b1f..fdbd8c6 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2106,25 +2106,23 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
{
uint8_t *oob_buf = chip->oob_poi;
uint8_t *ecc_calc = chip->buffers->ecccalc;
- int ecc_size = chip->ecc.size;
- int ecc_bytes = chip->ecc.bytes;
- int ecc_steps = chip->ecc.steps;
+ struct nand_ecc_ctrl *ecc = &chip->ecc;
uint32_t *eccpos = chip->ecc.layout->eccpos;
- uint32_t start_step = offset / ecc_size;
- uint32_t end_step = (offset + data_len - 1) / ecc_size;
- int oob_bytes = mtd->oobsize / ecc_steps;
+ uint32_t start_step = offset / ecc->size;
+ uint32_t end_step = (offset + data_len - 1) / ecc->size;
+ int oob_bytes = mtd->oobsize / ecc->steps;
int step, i;
- for (step = 0; step < ecc_steps; step++) {
+ for (step = 0; step < ecc->steps; step++) {
/* configure controller for WRITE access */
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
/* write data (untouched subpages already masked by 0xFF) */
- chip->write_buf(mtd, buf, ecc_size);
+ chip->write_buf(mtd, buf, ecc->size);
/* mask ECC of un-touched subpages by padding 0xFF */
if ((step < start_step) || (step > end_step))
- memset(ecc_calc, 0xff, ecc_bytes);
+ memset(ecc_calc, 0xff, ecc->bytes);
else
chip->ecc.calculate(mtd, buf, ecc_calc);
@@ -2133,9 +2131,9 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
if (!oob_required || (step < start_step) || (step > end_step))
memset(oob_buf, 0xff, oob_bytes);
- buf += ecc_size;
- ecc_calc += ecc_bytes;
- oob_buf += oob_bytes;
+ buf += ecc->size;
+ ecc_calc += ecc->bytes;
+ oob_buf += oob_bytes;
}
/* copy calculated ECC for whole page to chip->buffer->oob */
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [RFC PATCH 2/2] mtd: nand: refactor nand_write_subpage_hwecc to write only relevant subpage data
2014-06-30 10:33 [RFC PATCH 0/2] mtd: nand: optimize subpage writes Pekon Gupta
2014-06-30 10:34 ` [RFC PATCH 1/2] mtd: nand: clean nand_write_subpage_hwecc to reduce local variables Pekon Gupta
@ 2014-06-30 10:34 ` Pekon Gupta
1 sibling, 0 replies; 3+ messages in thread
From: Pekon Gupta @ 2014-06-30 10:34 UTC (permalink / raw)
To: Brian Norris; +Cc: linux-mtd, Pekon Gupta, Ezequiel Garcia, Artem Bityutskiy
Current nand_write_subpage_hwecc() code extends the subpage data to page-sized
one by padding it with 0xff. And then whole chunk is written to NAND device
using normal PAGE_PROGRAM sequence as below.
<NAND_CMD_SEQIN(0x80)>
<row-addr>
<column-addr>
<data1>
<data2>
...
<dataN>
<OOB-data>
<NAND_CMD_PAGEPROG(0x10)>
However many NAND devices support NAND_CMD_RNDIN(0x85) 'Random Input' command
which allows changing the column-address during PAGE_PROGRAM operation and write
only relevant data to NAND device, thereby avoiding the need for padding. This
patch uses below sequence to optimizes data writes for devices supporting subpages.
<NAND_CMD_SEQIN(0x80)>
<row-addr>
<NAND_CMD_RNDIN(0x85)>
<column-addr = subpageX>
<data1>
<data2>
...
<dataN>
<NAND_CMD_RNDIN(0x85)>
<column-addr = subpageY>
<data1>
<data2>
...
<dataM>
...
<NAND_CMD_RNDIN(0x85)>
<column-addr = oob-offset>
<OOB-data>
<NAND_CMD_PAGEPROG(0x10)>
*Note*
nand_chip-ecc->size may be different from nand_chip->subpagesize. That means
a single subpage can be further divided into more than one ECC sectors, as per
capacity of ECC engine. nand_chip->ecc->size is an attribute of ECC engine and
not NAND device. However same is not take care for reads in nand_read_subpage()
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
drivers/mtd/nand/nand_base.c | 37 ++++++++++++++++---------------------
1 file changed, 16 insertions(+), 21 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index fdbd8c6..41b844d 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2110,40 +2110,35 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint32_t start_step = offset / ecc->size;
uint32_t end_step = (offset + data_len - 1) / ecc->size;
- int oob_bytes = mtd->oobsize / ecc->steps;
int step, i;
- for (step = 0; step < ecc->steps; step++) {
+ buf += (start_step * ecc->size);
+ ecc_calc += (start_step * ecc->bytes);
+ eccpos += (start_step * ecc->bytes);
+ for (step = start_step; step < end_step; step++) {
/* configure controller for WRITE access */
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
- /* write data (untouched subpages already masked by 0xFF) */
+ /* write data */
+ chip->cmdfunc(mtd, NAND_CMD_RNDIN, (step * ecc->size), -1);
chip->write_buf(mtd, buf, ecc->size);
- /* mask ECC of un-touched subpages by padding 0xFF */
- if ((step < start_step) || (step > end_step))
- memset(ecc_calc, 0xff, ecc->bytes);
- else
- chip->ecc.calculate(mtd, buf, ecc_calc);
+ /* calculate ECC */
+ chip->ecc.calculate(mtd, buf, ecc_calc);
- /* mask OOB of un-touched subpages by padding 0xFF */
- /* if oob_required, preserve OOB metadata of written subpage */
- if (!oob_required || (step < start_step) || (step > end_step))
- memset(oob_buf, 0xff, oob_bytes);
+ /* copy calculated ECC to OOB buffer as per ecc-layout */
+ for (i = 0; i < ecc->bytes; i++)
+ oob_buf[eccpos[i]] = ecc_calc[i];
buf += ecc->size;
ecc_calc += ecc->bytes;
- oob_buf += oob_bytes;
+ eccpos += ecc->bytes;
}
- /* copy calculated ECC for whole page to chip->buffer->oob */
- /* this include masked-value(0xFF) for unwritten subpages */
- ecc_calc = chip->buffers->ecccalc;
- for (i = 0; i < chip->ecc.total; i++)
- chip->oob_poi[eccpos[i]] = ecc_calc[i];
-
- /* write OOB buffer to NAND device */
- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+ /* write _complete_ OOB buffer to NAND device,
+ * unused OOB bytes are already padded with 0xFF */
+ chip->cmdfunc(mtd, NAND_CMD_RNDIN, mtd->writesize, -1);
+ chip->write_buf(mtd, oob_buf, mtd->oobsize);
return 0;
}
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-06-30 10:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-30 10:33 [RFC PATCH 0/2] mtd: nand: optimize subpage writes Pekon Gupta
2014-06-30 10:34 ` [RFC PATCH 1/2] mtd: nand: clean nand_write_subpage_hwecc to reduce local variables Pekon Gupta
2014-06-30 10:34 ` [RFC PATCH 2/2] mtd: nand: refactor nand_write_subpage_hwecc to write only relevant subpage data Pekon Gupta
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.