Based on BBrezillons work, minus per-partition support. Changes to support that would be quite invasive while it hasn't been solved yet for Linux.
Signed-off-by: Roy Spliet <r.spl...@ultimaker.com> --- drivers/mtd/nand/nand_base.c | 255 ++++++++++++++++++++++++++++++++++--------- include/linux/mtd/nand.h | 96 ++++++++++++++++ 2 files changed, 299 insertions(+), 52 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 83586cc..5196c0c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1185,6 +1185,62 @@ EXPORT_SYMBOL(nand_lock); #endif /** + * nand_rnd_is_activ - check wether a region of a NAND page requires NAND + * randomizer to be disabled + * @mtd: mtd info + * @page: NAND page + * @column: offset within the page + * @len: len of the region + * + * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of + * error. + * + * In case of success len will contain the size of the region: + * - if the requested region fits in a NAND random region len will not change + * - else len will be replaced by the available length within the NAND random + * region + */ +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len) +{ + struct nand_chip *chip = mtd->priv; + struct nand_rnd_layout *layout = chip->rnd.layout; + struct nand_rndfree *range; + int ret = 1; + int tmp; + int i; + + if (!len || *len < 0 || column < 0 || + column + *len > mtd->writesize + mtd->oobsize) + return -EINVAL; + + if (layout) { + for (i = 0; i < layout->nranges; i++) { + range = &layout->ranges[i]; + if (column + *len <= range->offset) { + break; + } else if (column >= range->offset + range->length) { + continue; + } else if (column < range->offset) { + tmp = range->offset - column; + if (*len > tmp) + *len = tmp; + break; + } else { + tmp = range->offset + range->length - column; + if (*len > tmp) + *len = tmp; + ret = 0; + break; + } + + } + } + + return ret; +} +EXPORT_SYMBOL(nand_rnd_is_activ); + +/** * nand_page_is_empty - check wether a NAND page contains only FFs * @mtd: mtd info * @data: data buffer @@ -1329,9 +1385,13 @@ EXPORT_SYMBOL(nand_pst_create); static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - chip->read_buf(mtd, buf, mtd->writesize); - if (oob_required) - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, page, 0, NAND_RND_READ); + nand_rnd_read_buf(mtd, buf, mtd->writesize); + if (oob_required){ + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ); + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize); + } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); return 0; } @@ -1352,29 +1412,40 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; uint8_t *oob = chip->oob_poi; - int steps, size; + int steps, size, column = 0; for (steps = chip->ecc.steps; steps > 0; steps--) { - chip->read_buf(mtd, buf, eccsize); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, buf, eccsize); buf += eccsize; + column += eccsize; if (chip->ecc.prepad) { - chip->read_buf(mtd, oob, chip->ecc.prepad); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, chip->ecc.prepad); oob += chip->ecc.prepad; + column += chip->ecc.prepad; } - chip->read_buf(mtd, oob, eccbytes); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, eccbytes); oob += eccbytes; + column += eccbytes; if (chip->ecc.postpad) { - chip->read_buf(mtd, oob, chip->ecc.postpad); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, chip->ecc.postpad); oob += chip->ecc.postpad; + column += chip->ecc.postpad; } } size = mtd->oobsize - (oob - chip->oob_poi); - if (size) - chip->read_buf(mtd, oob, size); + if (size) { + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, size); + } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); return 0; } @@ -1462,7 +1533,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1); p = bufpoi + data_col_addr; - chip->read_buf(mtd, p, datafrag_len); + nand_rnd_config(mtd, -1, data_col_addr, NAND_RND_READ); + nand_rnd_read_buf(mtd, p, datafrag_len); /* Calculate ECC */ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) @@ -1481,7 +1553,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, } if (gaps) { chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_READ); + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize); } else { /* * Send the command to read the particular ECC bytes take care @@ -1496,7 +1569,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1); - chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); + nand_rnd_config(mtd, -1, mtd->writesize + aligned_pos, NAND_RND_READ); + nand_rnd_read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); } for (i = 0; i < eccfrag_len; i++) @@ -1515,6 +1589,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, max_bitflips = max_t(unsigned int, max_bitflips, stat); } } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); + return max_bitflips; } @@ -1539,13 +1615,17 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; unsigned int max_bitflips = 0; + int column = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, p, eccsize); chip->ecc.calculate(mtd, p, &ecc_calc[i]); + column += eccsize; } - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize); for (i = 0; i < chip->ecc.total; i++) ecc_code[i] = chip->oob_poi[eccpos[i]]; @@ -1564,6 +1644,8 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, max_bitflips = max_t(unsigned int, max_bitflips, stat); } } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); + return max_bitflips; } @@ -1592,11 +1674,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *ecc_calc = chip->buffers->ecccalc; unsigned int max_bitflips = 0; + int column = 0; /* Read the OOB area first */ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ); + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + column = 0; for (i = 0; i < chip->ecc.total; i++) ecc_code[i] = chip->oob_poi[eccpos[i]]; @@ -1605,7 +1690,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, int stat; chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, p, eccsize); chip->ecc.calculate(mtd, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); @@ -1616,6 +1702,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, max_bitflips = max_t(unsigned int, max_bitflips, stat); } } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); + return max_bitflips; } @@ -1639,20 +1727,26 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *p = buf; uint8_t *oob = chip->oob_poi; unsigned int max_bitflips = 0; + int column = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; chip->ecc.hwctl(mtd, NAND_ECC_READ); - chip->read_buf(mtd, p, eccsize); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, p, eccsize); + column += eccsize; if (chip->ecc.prepad) { - chip->read_buf(mtd, oob, chip->ecc.prepad); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, chip->ecc.prepad); oob += chip->ecc.prepad; } chip->ecc.hwctl(mtd, NAND_ECC_READSYN); - chip->read_buf(mtd, oob, eccbytes); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, eccbytes); + column += eccbytes; stat = chip->ecc.correct(mtd, p, oob, NULL); if (stat < 0) { @@ -1665,15 +1759,20 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, oob += eccbytes; if (chip->ecc.postpad) { - chip->read_buf(mtd, oob, chip->ecc.postpad); + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, chip->ecc.postpad); + column += chip->ecc.postpad; oob += chip->ecc.postpad; } } /* Calculate remaining oob bytes */ i = mtd->oobsize - (oob - chip->oob_poi); - if (i) - chip->read_buf(mtd, oob, i); + if (i) { + nand_rnd_config(mtd, page, column, NAND_RND_READ); + nand_rnd_read_buf(mtd, oob, i); + } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); return max_bitflips; } @@ -1685,9 +1784,11 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, * @ops: oob ops structure * @len: size of oob to transfer */ -static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, +static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob, struct mtd_oob_ops *ops, size_t len) { + struct nand_chip *chip = mtd->priv; + switch (ops->mode) { case MTD_OPS_PLACE_OOB: @@ -1804,6 +1905,7 @@ read_retry: * Now read the page into the buffer. Absent an error, * the read methods return max bitflips per ecc step. */ + nand_rnd_config(mtd, page, -1, NAND_RND_READ); if (unlikely(ops->mode == MTD_OPS_RAW)) ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, oob_required, @@ -1816,6 +1918,8 @@ read_retry: else ret = chip->ecc.read_page(mtd, chip, bufpoi, oob_required, page); + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); + if (ret < 0) { if (!aligned) /* Invalidate page cache */ @@ -1843,7 +1947,7 @@ read_retry: int toread = min(oobreadlen, max_oobsize); if (toread) { - oob = nand_transfer_oob(chip, + oob = nand_transfer_oob(mtd, oob, ops, toread); oobreadlen -= toread; } @@ -1960,7 +2064,9 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) { chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ); + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); return 0; } @@ -1979,7 +2085,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; int eccsize = chip->ecc.size; uint8_t *bufpoi = buf; - int i, toread, sndrnd = 0, pos; + int i, toread, sndrnd = 0, pos = eccsize; chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); for (i = 0; i < chip->ecc.steps; i++) { @@ -1992,12 +2098,17 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, } else sndrnd = 1; toread = min_t(int, length, chunk); - chip->read_buf(mtd, bufpoi, toread); + nand_rnd_config(mtd, page, pos, NAND_RND_READ); + nand_rnd_read_buf(mtd, bufpoi, toread); bufpoi += toread; length -= toread; } - if (length > 0) - chip->read_buf(mtd, bufpoi, length); + if (length > 0){ + pos = mtd->writesize + mtd->oobsize - length; + nand_rnd_config(mtd, page, pos, NAND_RND_READ); + nand_rnd_read_buf(mtd, bufpoi, length); + } + nand_rnd_config(mtd, -1, -1, NAND_RND_READ); return 0; } @@ -2016,7 +2127,9 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int length = mtd->oobsize; chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); - chip->write_buf(mtd, buf, length); + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, buf, length); + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE); /* Send command to program the OOB data */ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); @@ -2071,12 +2184,18 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, } else sndcmd = 1; len = min_t(int, length, chunk); - chip->write_buf(mtd, bufpoi, len); + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, bufpoi, len); bufpoi += len; length -= len; } - if (length > 0) - chip->write_buf(mtd, bufpoi, length); + + if (length > 0){ + pos = mtd->writesize + mtd->oobsize - length; + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, bufpoi, length); + } + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(mtd, chip); @@ -2147,7 +2266,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, break; len = min(len, readlen); - buf = nand_transfer_oob(chip, buf, ops, len); + buf = nand_transfer_oob(mtd, buf, ops, len); if (chip->options & NAND_NEED_READRDY) { /* Apply delay or wait for ready/busy pin */ @@ -2265,29 +2384,39 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; uint8_t *oob = chip->oob_poi; - int steps, size; + int steps, size, column = 0; for (steps = chip->ecc.steps; steps > 0; steps--) { - chip->write_buf(mtd, buf, eccsize); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, buf, eccsize); buf += eccsize; + column += eccsize; if (chip->ecc.prepad) { - chip->write_buf(mtd, oob, chip->ecc.prepad); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, chip->ecc.prepad); oob += chip->ecc.prepad; + column += chip->ecc.prepad; } - chip->write_buf(mtd, oob, eccbytes); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, eccbytes); oob += eccbytes; + column += eccbytes; if (chip->ecc.postpad) { - chip->write_buf(mtd, oob, chip->ecc.postpad); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, chip->ecc.postpad); oob += chip->ecc.postpad; + column += chip->ecc.postpad; } } size = mtd->oobsize - (oob - chip->oob_poi); - if (size) - chip->write_buf(mtd, oob, size); + if (size) { + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, size); + } return 0; } @@ -2334,17 +2463,21 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_calc = chip->buffers->ecccalc; const uint8_t *p = buf; uint32_t *eccpos = chip->ecc.layout->eccpos; + int column = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_WRITE); - chip->write_buf(mtd, p, eccsize); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, p, eccsize); chip->ecc.calculate(mtd, p, &ecc_calc[i]); + column += eccsize; } for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize); return 0; } @@ -2380,7 +2513,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, chip->ecc.hwctl(mtd, NAND_ECC_WRITE); /* write data (untouched subpages already masked by 0xFF) */ - chip->write_buf(mtd, buf, ecc_size); + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, buf, ecc_size); + offset += ecc_size; + /* mask ECC of un-touched subpages by padding 0xFF */ if ((step < start_step) || (step > end_step)) @@ -2405,7 +2541,8 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, chip->oob_poi[eccpos[i]] = ecc_calc[i]; /* write OOB buffer to NAND device */ - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize); return 0; } @@ -2430,31 +2567,42 @@ static int nand_write_page_syndrome(struct mtd_info *mtd, int eccsteps = chip->ecc.steps; const uint8_t *p = buf; uint8_t *oob = chip->oob_poi; + int column = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_WRITE); - chip->write_buf(mtd, p, eccsize); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, p, eccsize); + column += eccsize; if (chip->ecc.prepad) { - chip->write_buf(mtd, oob, chip->ecc.prepad); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, chip->ecc.prepad); oob += chip->ecc.prepad; + column += chip->ecc.prepad; } chip->ecc.calculate(mtd, p, oob); - chip->write_buf(mtd, oob, eccbytes); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, eccbytes); oob += eccbytes; + column += eccbytes; if (chip->ecc.postpad) { - chip->write_buf(mtd, oob, chip->ecc.postpad); + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, chip->ecc.postpad); oob += chip->ecc.postpad; + column += chip->ecc.postpad; } } /* Calculate remaining oob bytes */ i = mtd->oobsize - (oob - chip->oob_poi); - if (i) - chip->write_buf(mtd, oob, i); + if (i) { + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE); + nand_rnd_write_buf(mtd, oob, i); + } return 0; } @@ -2485,6 +2633,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); + nand_rnd_config(mtd, page, 0, NAND_RND_WRITE); if (unlikely(raw)) status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); @@ -2494,6 +2643,8 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, else status = chip->ecc.write_page(mtd, chip, buf, oob_required); + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE); + if (status < 0) return status; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index ef6a783..6465a52 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -565,6 +565,64 @@ void nand_page_set_status(struct mtd_info *mtd, int page, int nand_pst_create(struct mtd_info *mtd); +/* + * Constants for randomizer modes + */ +typedef enum { + NAND_RND_NONE, + NAND_RND_SOFT, + NAND_RND_HW, +} nand_rnd_modes_t; + +/* + * Constants for randomizer actions + */ +enum nand_rnd_action { + NAND_RND_NO_ACTION, + NAND_RND_READ, + NAND_RND_WRITE, +}; + +/** + * struct nand_rndfree - Structure defining a NAND page region where the + * randomizer should be disabled + * @offset: range offset + * @length: range length + */ +struct nand_rndfree { + u32 offset; + u32 length; +}; + +/** + * struct nand_rnd_layout - Structure defining rndfree regions + * @nranges: number of ranges + * @ranges: array defining the rndfree regions + */ +struct nand_rnd_layout { + int nranges; + struct nand_rndfree ranges[0]; +}; + +/** + * struct nand_rnd_ctrl - Randomizer Control structure + * @mode: Randomizer mode + * @config: function to prepare the randomizer (i.e.: set the appropriate + * seed/init value). + * @read_buf: function that read from the NAND and descramble the retrieved + * data. + * @write_buf: function that scramble data before writing it to the NAND. + */ +struct nand_rnd_ctrl { + nand_rnd_modes_t mode; + struct nand_rnd_layout *layout; + void *priv; + int (*config)(struct mtd_info *mtd, int page, int column, + enum nand_rnd_action action); + void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); + void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); +}; + /** * struct nand_buffers - buffer structure for read/write * @ecccalc: buffer pointer for calculated ECC, size is oobsize. @@ -763,6 +821,8 @@ struct nand_chip { struct nand_buffers *buffers; struct nand_hw_control hwcontrol; + struct nand_rnd_ctrl rnd; + uint8_t *bbt; struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_md; @@ -894,6 +954,42 @@ extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf); +static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column, + enum nand_rnd_action action) +{ + struct nand_chip *chip = mtd->priv; + + if (chip->rnd.config) + return chip->rnd.config(mtd, page, column, action); + + return 0; +} + +static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf, + int len) +{ + struct nand_chip *chip = mtd->priv; + + if (chip->rnd.write_buf) + chip->rnd.write_buf(mtd, buf, len); + else + chip->write_buf(mtd, buf, len); +} + +static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf, + int len) +{ + struct nand_chip *chip = mtd->priv; + + if (chip->rnd.read_buf) + chip->rnd.read_buf(mtd, buf, len); + else + chip->read_buf(mtd, buf, len); +} + +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len); + + #ifdef __UBOOT__ /* * Constants for oob configuration -- 2.4.2 -- IMAGINE IT >> MAKE IT Meet us online at Twitter <http://twitter.com/ultimaker>, Facebook <http://facebook.com/ultimaker>, Google+ <http://google.com/+Ultimaker> www.ultimaker.com _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot