Hi Scott, On Mon, 30 May 2016 13:57:58 -0500 Scott Wood <o...@buserror.net> wrote:
> Updates the NAND code to match Linux v4.6. The previous sync was from > Linux v4.1 in commit d3963721d93fafa. > > Note that none of the individual NAND drivers tracked Linux closely > enough to be synced themselves, other than manually applying a few > cross-tree changes. Nice work! I'll port my sunxi NAND controller driver on top of these changes and test it. Thanks a lot. Boris > > Signed-off-by: Scott Wood <o...@buserror.net> > --- > drivers/mtd/nand/atmel_nand.c | 6 +- > drivers/mtd/nand/davinci_nand.c | 6 +- > drivers/mtd/nand/denali.c | 39 +++-- > drivers/mtd/nand/denali.h | 1 - > drivers/mtd/nand/denali_spl.c | 2 +- > drivers/mtd/nand/mpc5121_nfc.c | 1 - > drivers/mtd/nand/mxc_nand.c | 5 +- > drivers/mtd/nand/mxc_nand_spl.c | 2 +- > drivers/mtd/nand/mxs_nand.c | 2 +- > drivers/mtd/nand/nand_base.c | 329 > ++++++++++++++++++++++++++++------------ > drivers/mtd/nand/nand_bbt.c | 30 ++-- > drivers/mtd/nand/nand_bch.c | 29 ++-- > drivers/mtd/nand/nand_ids.c | 10 +- > drivers/mtd/nand/ndfc.c | 2 +- > drivers/mtd/nand/omap_gpmc.c | 2 +- > drivers/mtd/nand/s3c2410_nand.c | 2 +- > drivers/mtd/nand/vf610_nfc.c | 1 - > include/linux/mtd/mtd.h | 5 + > include/linux/mtd/nand.h | 65 +++++--- > include/linux/mtd/nand_bch.h | 10 +- > 20 files changed, 347 insertions(+), 202 deletions(-) > > diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c > index a81b96d..75e8307 100644 > --- a/drivers/mtd/nand/atmel_nand.c > +++ b/drivers/mtd/nand/atmel_nand.c > @@ -513,7 +513,7 @@ normal_check: > if (err_nbr == -1) { > dev_err(host->dev, "PMECC: Too many errors\n"); > mtd->ecc_stats.failed++; > - return -EIO; > + return -EBADMSG; > } else { > pmecc_correct_data(mtd, buf_pos, ecc, i, > host->pmecc_bytes_per_sector, err_nbr); > @@ -562,7 +562,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info > *mtd, > stat = pmecc_readl(host->pmecc, isr); > if (stat != 0) > if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0) > - return -EIO; > + return -EBADMSG; > > return 0; > } > @@ -1112,7 +1112,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, > u_char *dat, > * We can't correct so many errors */ > dev_warn(host->dev, "atmel_nand : multiple errors detected." > " Unable to correct.\n"); > - return -EIO; > + return -EBADMSG; > } > > /* if there's a single bit error : we can correct it */ > diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c > index be9d666..48a8ca7 100644 > --- a/drivers/mtd/nand/davinci_nand.c > +++ b/drivers/mtd/nand/davinci_nand.c > @@ -243,7 +243,7 @@ static int nand_davinci_correct_data(struct mtd_info > *mtd, u_char *dat, > "%d\n", find_byte, find_bit); > return 1; > } else { > - return -1; > + return -EBADMSG; > } > } else if (!(diff & (diff - 1))) { > /* Single bit ECC error in the ECC itself, > @@ -254,7 +254,7 @@ static int nand_davinci_correct_data(struct mtd_info > *mtd, u_char *dat, > } else { > /* Uncorrectable error */ > MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); > - return -1; > + return -EBADMSG; > } > } > return 0; > @@ -701,7 +701,7 @@ static int nand_davinci_4bit_correct_data(struct mtd_info > *mtd, uint8_t *dat, > return 0; > } else if (iserror == ECC_STATE_TOO_MANY_ERRS) { > val = __raw_readl(&davinci_emif_regs->nanderrval1); > - return -1; > + return -EBADMSG; > } > > numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16) > diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c > index 3ae7545..601e744 100644 > --- a/drivers/mtd/nand/denali.c > +++ b/drivers/mtd/nand/denali.c > @@ -48,8 +48,10 @@ static int onfi_timing_mode = NAND_DEFAULT_TIMINGS; > * this macro allows us to convert from an MTD structure to our own > * device context (denali) structure. > */ > -#define mtd_to_denali(m) \ > - container_of(mtd_to_nand(m), struct denali_nand_info, nand) > +static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) > +{ > + return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); > +} > > /* > * These constants are defined by the driver to enable common driver > @@ -866,8 +868,7 @@ static int write_page(struct mtd_info *mtd, struct > nand_chip *chip, > * by write_page above. > */ > static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, > - const uint8_t *buf, int oob_required, > - int page) > + const uint8_t *buf, int oob_required, int page) > { > struct denali_nand_info *denali = mtd_to_denali(mtd); > > @@ -891,8 +892,8 @@ static int denali_write_page(struct mtd_info *mtd, struct > nand_chip *chip, > * write_page() function above. > */ > static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip > *chip, > - const uint8_t *buf, int oob_required, > - int page) > + const uint8_t *buf, int oob_required, > + int page) > { > struct denali_nand_info *denali = mtd_to_denali(mtd); > > @@ -991,7 +992,7 @@ static int denali_read_page(struct mtd_info *mtd, struct > nand_chip *chip, > debug(" ECC error cause by erased block\n"); > /* false alarm, return the 0xFF */ > } else { > - return -EIO; > + return -EBADMSG; > } > } > memcpy(buf, denali->buf.dma_buf, mtd->writesize); > @@ -1176,12 +1177,13 @@ static struct nand_ecclayout nand_oob; > > static int denali_init(struct denali_nand_info *denali) > { > + struct mtd_info *mtd = nand_to_mtd(&denali->nand); > int ret; > > denali_hw_init(denali); > > - denali->mtd->name = "denali-nand"; > - denali->mtd->owner = THIS_MODULE; > + mtd->name = "denali-nand"; > + mtd->owner = THIS_MODULE; > > /* register the driver with the NAND core subsystem */ > denali->nand.select_chip = denali_select_chip; > @@ -1195,7 +1197,7 @@ static int denali_init(struct denali_nand_info *denali) > * this is the first stage in a two step process to register > * with the nand subsystem > */ > - if (nand_scan_ident(denali->mtd, denali->max_banks, NULL)) { > + if (nand_scan_ident(mtd, denali->max_banks, NULL)) { > ret = -ENXIO; > goto fail; > } > @@ -1241,13 +1243,13 @@ static int denali_init(struct denali_nand_info > *denali) > nand_oob.eccbytes = denali->nand.ecc.bytes; > denali->nand.ecc.layout = &nand_oob; > > - writel(denali->mtd->erasesize / denali->mtd->writesize, > + writel(mtd->erasesize / mtd->writesize, > denali->flash_reg + PAGES_PER_BLOCK); > writel(denali->nand.options & NAND_BUSWIDTH_16 ? 1 : 0, > denali->flash_reg + DEVICE_WIDTH); > - writel(denali->mtd->writesize, > + writel(mtd->writesize, > denali->flash_reg + DEVICE_MAIN_AREA_SIZE); > - writel(denali->mtd->oobsize, > + writel(mtd->oobsize, > denali->flash_reg + DEVICE_SPARE_AREA_SIZE); > if (readl(denali->flash_reg + DEVICES_CONNECTED) == 0) > writel(1, denali->flash_reg + DEVICES_CONNECTED); > @@ -1260,12 +1262,12 @@ static int denali_init(struct denali_nand_info > *denali) > denali->nand.ecc.read_oob = denali_read_oob; > denali->nand.ecc.write_oob = denali_write_oob; > > - if (nand_scan_tail(denali->mtd)) { > + if (nand_scan_tail(mtd)) { > ret = -ENXIO; > goto fail; > } > > - ret = nand_register(0, denali->mtd); > + ret = nand_register(0, mtd); > > fail: > return ret; > @@ -1280,13 +1282,6 @@ static int __board_nand_init(void) > return -ENOMEM; > > /* > - * If CONFIG_SYS_NAND_SELF_INIT is defined, each driver is responsible > - * for instantiating struct nand_chip, while drivers/mtd/nand/nand.c > - * still provides a "struct mtd_info nand_info" instance. > - */ > - denali->mtd = &denali->nand.mtd; > - > - /* > * In the future, these base addresses should be taken from > * Device Tree or platform data. > */ > diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h > index db1457a..0e098bd 100644 > --- a/drivers/mtd/nand/denali.h > +++ b/drivers/mtd/nand/denali.h > @@ -436,7 +436,6 @@ struct nand_buf { > #define DT 3 > > struct denali_nand_info { > - struct mtd_info *mtd; > struct nand_chip nand; > int flash_bank; /* currently selected chip */ > int status; > diff --git a/drivers/mtd/nand/denali_spl.c b/drivers/mtd/nand/denali_spl.c > index 1587413..c693032 100644 > --- a/drivers/mtd/nand/denali_spl.c > +++ b/drivers/mtd/nand/denali_spl.c > @@ -41,7 +41,7 @@ static int wait_for_irq(uint32_t irq_mask) > > if (intr_status & INTR_STATUS__ECC_UNCOR_ERR) { > debug("Uncorrected ECC detected\n"); > - return -EIO; > + return -EBADMSG; > } > > if (intr_status & irq_mask) > diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c > index 362d393..8a8775c 100644 > --- a/drivers/mtd/nand/mpc5121_nfc.c > +++ b/drivers/mtd/nand/mpc5121_nfc.c > @@ -100,7 +100,6 @@ > #define NFC_WPC_UNLOCK (1 << 2) > > struct mpc5121_nfc_prv { > - struct mtd_info mtd; > struct nand_chip chip; > int irq; > void __iomem *regs; > diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c > index d4e14b5..7221d0b 100644 > --- a/drivers/mtd/nand/mxc_nand.c > +++ b/drivers/mtd/nand/mxc_nand.c > @@ -19,7 +19,6 @@ > #define DRIVER_NAME "mxc_nand" > > struct mxc_nand_host { > - struct mtd_info mtd; > struct nand_chip *nand; > > struct mxc_nand_regs __iomem *regs; > @@ -681,7 +680,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, > u_char *dat, > mtd->writesize / nand_chip->subpagesize > - subpages); > } > - return -1; > + return -EBADMSG; > } > ecc_status >>= 4; > subpages--; > @@ -713,7 +712,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, > u_char *dat, > if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { > MTDDEBUG(MTD_DEBUG_LEVEL0, > "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); > - return -1; > + return -EBADMSG; > } > > return 0; > diff --git a/drivers/mtd/nand/mxc_nand_spl.c b/drivers/mtd/nand/mxc_nand_spl.c > index 6ac2c96..841fb5b 100644 > --- a/drivers/mtd/nand/mxc_nand_spl.c > +++ b/drivers/mtd/nand/mxc_nand_spl.c > @@ -232,7 +232,7 @@ static int nfc_read_page(unsigned int page_address, > unsigned char *buf) > nfc_nand_read_page(page_address); > > if (nfc_nand_check_ecc()) > - return -1; > + return -EBADMSG; > > src = (u32 *)&nfc->main_area[0][0]; > dst = (u32 *)buf; > diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c > index 5291330..7be1f86 100644 > --- a/drivers/mtd/nand/mxs_nand.c > +++ b/drivers/mtd/nand/mxs_nand.c > @@ -961,7 +961,7 @@ static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, > struct nand_chip *nand, > * Thus, this function is only called when we want *all* blocks to look good, > * so it *always* return success. > */ > -static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) > +static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs) > { > return 0; > } > diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c > index 62e70a7..74c563c 100644 > --- a/drivers/mtd/nand/nand_base.c > +++ b/drivers/mtd/nand/nand_base.c > @@ -1,6 +1,4 @@ > /* > - * drivers/mtd/nand.c > - * > * Overview: > * This is the generic MTD driver for NAND flash devices. It should be > * capable of working with almost all NAND chips currently available. > @@ -45,8 +43,6 @@ > #include <asm/io.h> > #include <asm/errno.h> > > -static bool is_module_text_address(unsigned long addr) {return 0;} > - > /* Define default oob placement schemes for large and small page devices */ > static struct nand_ecclayout nand_oob_8 = { > .eccbytes = 3, > @@ -343,13 +339,12 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t > *buf, int len) > * nand_block_bad - [DEFAULT] Read bad block marker from the chip > * @mtd: MTD device structure > * @ofs: offset from device start > - * @getchip: 0, if the chip is already selected > * > * Check, if the block is bad. > */ > -static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) > +static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) > { > - int page, chipnr, res = 0, i = 0; > + int page, res = 0, i = 0; > struct nand_chip *chip = mtd_to_nand(mtd); > u16 bad; > > @@ -358,15 +353,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t > ofs, int getchip) > > page = (int)(ofs >> chip->page_shift) & chip->pagemask; > > - if (getchip) { > - chipnr = (int)(ofs >> chip->chip_shift); > - > - nand_get_device(mtd, FL_READING); > - > - /* Select the NAND device */ > - chip->select_chip(mtd, chipnr); > - } > - > do { > if (chip->options & NAND_BUSWIDTH_16) { > chip->cmdfunc(mtd, NAND_CMD_READOOB, > @@ -391,11 +377,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t > ofs, int getchip) > i++; > } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); > > - if (getchip) { > - chip->select_chip(mtd, -1); > - nand_release_device(mtd); > - } > - > return res; > } > > @@ -533,14 +514,12 @@ static int nand_block_isreserved(struct mtd_info *mtd, > loff_t ofs) > * nand_block_checkbad - [GENERIC] Check if a block is marked bad > * @mtd: MTD device structure > * @ofs: offset from device start > - * @getchip: 0, if the chip is already selected > * @allowbbt: 1, if its allowed to access the bbt area > * > * Check, if the block is bad. Either by reading the bad block table or > * calling of the scan function. > */ > -static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, > - int allowbbt) > +static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int > allowbbt) > { > struct nand_chip *chip = mtd_to_nand(mtd); > > @@ -551,17 +530,22 @@ static int nand_block_checkbad(struct mtd_info *mtd, > loff_t ofs, int getchip, > } > > if (!chip->bbt) > - return chip->block_bad(mtd, ofs, getchip); > + return chip->block_bad(mtd, ofs); > > /* Return info from the table */ > return nand_isbad_bbt(mtd, ofs, allowbbt); > } > > -/* Wait for the ready pin, after a command. The timeout is caught later. */ > +/** > + * nand_wait_ready - [GENERIC] Wait for the ready pin after commands. > + * @mtd: MTD device structure > + * > + * Wait for the ready pin after a command, and warn if a timeout occurs. > + */ > void nand_wait_ready(struct mtd_info *mtd) > { > struct nand_chip *chip = mtd_to_nand(mtd); > - u32 timeo = (CONFIG_SYS_HZ * 20) / 1000; > + u32 timeo = (CONFIG_SYS_HZ * 400) / 1000; > u32 time_start; > > time_start = get_timer(0); > @@ -571,6 +555,9 @@ void nand_wait_ready(struct mtd_info *mtd) > if (chip->dev_ready(mtd)) > break; > } > + > + if (!chip->dev_ready(mtd)) > + pr_warn("timeout while waiting for chip to become ready\n"); > } > EXPORT_SYMBOL_GPL(nand_wait_ready); > > @@ -871,15 +858,13 @@ static void panic_nand_wait(struct mtd_info *mtd, > struct nand_chip *chip, > * @mtd: MTD device structure > * @chip: NAND chip structure > * > - * Wait for command done. This applies to erase and program only. Erase can > - * take up to 400ms and program up to 20ms according to general NAND and > - * SmartMedia specs. > + * Wait for command done. This applies to erase and program only. > */ > static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) > { > > - int status, state = chip->state; > - unsigned long timeo = (state == FL_ERASING ? 400 : 20); > + int status; > + unsigned long timeo = 400; > > led_trigger_event(nand_led_trigger, LED_FULL); > > @@ -912,6 +897,135 @@ static int nand_wait(struct mtd_info *mtd, struct > nand_chip *chip) > return status; > } > > +#define BITS_PER_BYTE 8 > + > +/** > + * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data > + * @buf: buffer to test > + * @len: buffer length > + * @bitflips_threshold: maximum number of bitflips > + * > + * Check if a buffer contains only 0xff, which means the underlying region > + * has been erased and is ready to be programmed. > + * The bitflips_threshold specify the maximum number of bitflips before > + * considering the region is not erased. > + * Note: The logic of this function has been extracted from the memweight > + * implementation, except that nand_check_erased_buf function exit before > + * testing the whole buffer if the number of bitflips exceed the > + * bitflips_threshold value. > + * > + * Returns a positive number of bitflips less than or equal to > + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the > + * threshold. > + */ > +static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) > +{ > + const unsigned char *bitmap = buf; > + int bitflips = 0; > + int weight; > + > + for (; len && ((uintptr_t)bitmap) % sizeof(long); > + len--, bitmap++) { > + weight = hweight8(*bitmap); > + bitflips += BITS_PER_BYTE - weight; > + if (unlikely(bitflips > bitflips_threshold)) > + return -EBADMSG; > + } > + > + for (; len >= 4; len -= 4, bitmap += 4) { > + weight = hweight32(*((u32 *)bitmap)); > + bitflips += 32 - weight; > + if (unlikely(bitflips > bitflips_threshold)) > + return -EBADMSG; > + } > + > + for (; len > 0; len--, bitmap++) { > + weight = hweight8(*bitmap); > + bitflips += BITS_PER_BYTE - weight; > + if (unlikely(bitflips > bitflips_threshold)) > + return -EBADMSG; > + } > + > + return bitflips; > +} > + > +/** > + * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only > + * 0xff data > + * @data: data buffer to test > + * @datalen: data length > + * @ecc: ECC buffer > + * @ecclen: ECC length > + * @extraoob: extra OOB buffer > + * @extraooblen: extra OOB length > + * @bitflips_threshold: maximum number of bitflips > + * > + * Check if a data buffer and its associated ECC and OOB data contains only > + * 0xff pattern, which means the underlying region has been erased and is > + * ready to be programmed. > + * The bitflips_threshold specify the maximum number of bitflips before > + * considering the region as not erased. > + * > + * Note: > + * 1/ ECC algorithms are working on pre-defined block sizes which are usually > + * different from the NAND page size. When fixing bitflips, ECC engines > will > + * report the number of errors per chunk, and the NAND core infrastructure > + * expect you to return the maximum number of bitflips for the whole page. > + * This is why you should always use this function on a single chunk and > + * not on the whole page. After checking each chunk you should update your > + * max_bitflips value accordingly. > + * 2/ When checking for bitflips in erased pages you should not only check > + * the payload data but also their associated ECC data, because a user > might > + * have programmed almost all bits to 1 but a few. In this case, we > + * shouldn't consider the chunk as erased, and checking ECC bytes prevent > + * this case. > + * 3/ The extraoob argument is optional, and should be used if some of your > OOB > + * data are protected by the ECC engine. > + * It could also be used if you support subpages and want to attach some > + * extra OOB data to an ECC chunk. > + * > + * Returns a positive number of bitflips less than or equal to > + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the > + * threshold. In case of success, the passed buffers are filled with 0xff. > + */ > +int nand_check_erased_ecc_chunk(void *data, int datalen, > + void *ecc, int ecclen, > + void *extraoob, int extraooblen, > + int bitflips_threshold) > +{ > + int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; > + > + data_bitflips = nand_check_erased_buf(data, datalen, > + bitflips_threshold); > + if (data_bitflips < 0) > + return data_bitflips; > + > + bitflips_threshold -= data_bitflips; > + > + ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); > + if (ecc_bitflips < 0) > + return ecc_bitflips; > + > + bitflips_threshold -= ecc_bitflips; > + > + extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, > + bitflips_threshold); > + if (extraoob_bitflips < 0) > + return extraoob_bitflips; > + > + if (data_bitflips) > + memset(data, 0xff, datalen); > + > + if (ecc_bitflips) > + memset(ecc, 0xff, ecclen); > + > + if (extraoob_bitflips) > + memset(extraoob, 0xff, extraooblen); > + > + return data_bitflips + ecc_bitflips + extraoob_bitflips; > +} > +EXPORT_SYMBOL(nand_check_erased_ecc_chunk); > + > /** > * nand_read_page_raw - [INTERN] read raw page data without ecc > * @mtd: mtd info structure > @@ -1103,6 +1217,16 @@ static int nand_read_subpage(struct mtd_info *mtd, > struct nand_chip *chip, > > stat = chip->ecc.correct(mtd, p, > &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); > + if (stat == -EBADMSG && > + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { > + /* check for empty pages with bitflips */ > + stat = nand_check_erased_ecc_chunk(p, chip->ecc.size, > + &chip->buffers->ecccode[i], > + chip->ecc.bytes, > + NULL, 0, > + chip->ecc.strength); > + } > + > if (stat < 0) { > mtd->ecc_stats.failed++; > } else { > @@ -1152,6 +1276,15 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, > struct nand_chip *chip, > int stat; > > stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); > + if (stat == -EBADMSG && > + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { > + /* check for empty pages with bitflips */ > + stat = nand_check_erased_ecc_chunk(p, eccsize, > + &ecc_code[i], eccbytes, > + NULL, 0, > + chip->ecc.strength); > + } > + > if (stat < 0) { > mtd->ecc_stats.failed++; > } else { > @@ -1204,6 +1337,15 @@ static int nand_read_page_hwecc_oob_first(struct > mtd_info *mtd, > chip->ecc.calculate(mtd, p, &ecc_calc[i]); > > stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); > + if (stat == -EBADMSG && > + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { > + /* check for empty pages with bitflips */ > + stat = nand_check_erased_ecc_chunk(p, eccsize, > + &ecc_code[i], eccbytes, > + NULL, 0, > + chip->ecc.strength); > + } > + > if (stat < 0) { > mtd->ecc_stats.failed++; > } else { > @@ -1231,6 +1373,7 @@ static int nand_read_page_syndrome(struct mtd_info > *mtd, struct nand_chip *chip, > int i, eccsize = chip->ecc.size; > int eccbytes = chip->ecc.bytes; > int eccsteps = chip->ecc.steps; > + int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad; > uint8_t *p = buf; > uint8_t *oob = chip->oob_poi; > unsigned int max_bitflips = 0; > @@ -1250,19 +1393,29 @@ static int nand_read_page_syndrome(struct mtd_info > *mtd, struct nand_chip *chip, > chip->read_buf(mtd, oob, eccbytes); > stat = chip->ecc.correct(mtd, p, oob, NULL); > > - if (stat < 0) { > - mtd->ecc_stats.failed++; > - } else { > - mtd->ecc_stats.corrected += stat; > - max_bitflips = max_t(unsigned int, max_bitflips, stat); > - } > - > oob += eccbytes; > > if (chip->ecc.postpad) { > chip->read_buf(mtd, oob, chip->ecc.postpad); > oob += chip->ecc.postpad; > } > + > + if (stat == -EBADMSG && > + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { > + /* check for empty pages with bitflips */ > + stat = nand_check_erased_ecc_chunk(p, chip->ecc.size, > + oob - eccpadbytes, > + eccpadbytes, > + NULL, 0, > + chip->ecc.strength); > + } > + > + if (stat < 0) { > + mtd->ecc_stats.failed++; > + } else { > + mtd->ecc_stats.corrected += stat; > + max_bitflips = max_t(unsigned int, max_bitflips, stat); > + } > } > > /* Calculate remaining oob bytes */ > @@ -1361,8 +1514,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, > loff_t from, > int ret = 0; > uint32_t readlen = ops->len; > uint32_t oobreadlen = ops->ooblen; > - uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ? > - mtd->oobavail : mtd->oobsize; > + uint32_t max_oobsize = mtd_oobavail(mtd, ops); > > uint8_t *bufpoi, *oob, *buf; > int use_bufpoi; > @@ -1712,10 +1864,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, > loff_t from, > > stats = mtd->ecc_stats; > > - if (ops->mode == MTD_OPS_AUTO_OOB) > - len = chip->ecc.layout->oobavail; > - else > - len = mtd->oobsize; > + len = mtd_oobavail(mtd, ops); > > if (unlikely(ops->ooboffs >= len)) { > pr_debug("%s: attempt to start read outside oob\n", > @@ -1845,8 +1994,7 @@ out: > * Not for syndrome calculating ECC controllers, which use a special oob > layout. > */ > static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, > - const uint8_t *buf, int oob_required, > - int page) > + const uint8_t *buf, int oob_required, int page) > { > chip->write_buf(mtd, buf, mtd->writesize); > if (oob_required) > @@ -1861,6 +2009,7 @@ static int nand_write_page_raw(struct mtd_info *mtd, > struct nand_chip *chip, > * @chip: nand chip info structure > * @buf: data buffer > * @oob_required: must write chip->oob_poi to OOB > + * @page: page number to write > * > * We need a special oob layout and handling even when ECC isn't checked. > */ > @@ -1907,8 +2056,8 @@ static int nand_write_page_raw_syndrome(struct mtd_info > *mtd, > * @page: page number to write > */ > static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip > *chip, > - const uint8_t *buf, int oob_required, > - int page) > + const uint8_t *buf, int oob_required, > + int page) > { > int i, eccsize = chip->ecc.size; > int eccbytes = chip->ecc.bytes; > @@ -2029,6 +2178,7 @@ static int nand_write_subpage_hwecc(struct mtd_info > *mtd, > * @chip: nand chip info structure > * @buf: data buffer > * @oob_required: must write chip->oob_poi to OOB > + * @page: page number to write > * > * The hw generator calculates the error syndrome automatically. Therefore we > * need a special oob layout and handling. > @@ -2103,7 +2253,7 @@ static int nand_write_page(struct mtd_info *mtd, struct > nand_chip *chip, > oob_required, page); > else if (subpage) > status = chip->ecc.write_subpage(mtd, chip, offset, data_len, > - buf, oob_required, page); > + buf, oob_required, page); > else > status = chip->ecc.write_page(mtd, chip, buf, oob_required, > page); > @@ -2145,7 +2295,6 @@ static int nand_write_page(struct mtd_info *mtd, struct > nand_chip *chip, > * @oob: oob data buffer > * @len: oob data write length > * @ops: oob ops structure > - * @page: page number to write > */ > static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, > struct mtd_oob_ops *ops) > @@ -2214,8 +2363,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, > loff_t to, > uint32_t writelen = ops->len; > > uint32_t oobwritelen = ops->ooblen; > - uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ? > - mtd->oobavail : mtd->oobsize; > + uint32_t oobmaxlen = mtd_oobavail(mtd, ops); > > uint8_t *oob = ops->oobbuf; > uint8_t *buf = ops->datbuf; > @@ -2404,10 +2552,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, > loff_t to, > pr_debug("%s: to = 0x%08x, len = %i\n", > __func__, (unsigned int)to, (int)ops->ooblen); > > - if (ops->mode == MTD_OPS_AUTO_OOB) > - len = chip->ecc.layout->oobavail; > - else > - len = mtd->oobsize; > + len = mtd_oobavail(mtd, ops); > > /* Do not allow write past end of page */ > if ((ops->ooboffs + ops->ooblen) > len) { > @@ -2597,7 +2742,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct > erase_info *instr, > > /* Check if we have a bad block, we do not erase bad blocks! */ > if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) << > - chip->page_shift, 0, allowbbt)) { > + chip->page_shift, allowbbt)) { > pr_warn("%s: attempt to erase a bad block at page > 0x%08x\n", > __func__, page); > instr->state = MTD_ERASE_FAILED; > @@ -2684,7 +2829,20 @@ static void nand_sync(struct mtd_info *mtd) > */ > static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) > { > - return nand_block_checkbad(mtd, offs, 1, 0); > + struct nand_chip *chip = mtd_to_nand(mtd); > + int chipnr = (int)(offs >> chip->chip_shift); > + int ret; > + > + /* Select the NAND device */ > + nand_get_device(mtd, FL_READING); > + chip->select_chip(mtd, chipnr); > + > + ret = nand_block_checkbad(mtd, offs, 0); > + > + chip->select_chip(mtd, -1); > + nand_release_device(mtd); > + > + return ret; > } > > /** > @@ -2756,9 +2914,6 @@ static int nand_onfi_get_features(struct mtd_info *mtd, > struct nand_chip *chip, > return -EINVAL; > #endif > > - /* clear the sub feature parameters */ > - memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); > - > chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); > for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) > *subfeature_param++ = chip->read_byte(mtd); > @@ -3491,7 +3646,7 @@ static struct nand_flash_dev > *nand_get_flash_type(struct mtd_info *mtd, > if (find_full_id_nand(mtd, chip, type, id_data, &busw)) > goto ident_done; > } else if (*dev_id == type->dev_id) { > - break; > + break; > } > } > > @@ -3514,10 +3669,7 @@ static struct nand_flash_dev > *nand_get_flash_type(struct mtd_info *mtd, > > chip->chipsize = (uint64_t)type->chipsize << 20; > > - if (!type->pagesize && chip->init_size) { > - /* Set the pagesize, oobsize, erasesize by the driver */ > - busw = chip->init_size(mtd, chip, id_data); > - } else if (!type->pagesize) { > + if (!type->pagesize) { > /* Decode parameters from extended ID */ > nand_decode_ext_id(mtd, chip, id_data, &busw); > } else { > @@ -3621,7 +3773,6 @@ ident_done: > * This is the first phase of the normal nand_scan() function. It reads the > * flash ID and sets up MTD fields accordingly. > * > - * The mtd->owner field must be set to the module of the caller. > */ > int nand_scan_ident(struct mtd_info *mtd, int maxchips, > struct nand_flash_dev *table) > @@ -3797,7 +3948,7 @@ int nand_scan_tail(struct mtd_info *mtd) > ecc->write_oob = nand_write_oob_std; > if (!ecc->read_subpage) > ecc->read_subpage = nand_read_subpage; > - if (!ecc->write_subpage) > + if (!ecc->write_subpage && ecc->hwctl && ecc->calculate) > ecc->write_subpage = nand_write_subpage_hwecc; > > case NAND_ECC_HW_SYNDROME: > @@ -3875,10 +4026,8 @@ int nand_scan_tail(struct mtd_info *mtd) > } > > /* See nand_bch_init() for details. */ > - ecc->bytes = DIV_ROUND_UP( > - ecc->strength * fls(8 * ecc->size), 8); > - ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, > - &ecc->layout); > + ecc->bytes = 0; > + ecc->priv = nand_bch_init(mtd); > if (!ecc->priv) { > pr_warn("BCH ECC initialization failed!\n"); > BUG(); > @@ -3913,11 +4062,11 @@ int nand_scan_tail(struct mtd_info *mtd) > * The number of bytes available for a client to place data into > * the out of band area. > */ > - ecc->layout->oobavail = 0; > - for (i = 0; ecc->layout->oobfree[i].length > - && i < ARRAY_SIZE(ecc->layout->oobfree); i++) > - ecc->layout->oobavail += ecc->layout->oobfree[i].length; > - mtd->oobavail = ecc->layout->oobavail; > + mtd->oobavail = 0; > + if (ecc->layout) { > + for (i = 0; ecc->layout->oobfree[i].length; i++) > + mtd->oobavail += ecc->layout->oobfree[i].length; > + } > > /* ECC sanity check: warn if it's too weak */ > if (!nand_ecc_strength_good(mtd)) > @@ -4002,18 +4151,6 @@ int nand_scan_tail(struct mtd_info *mtd) > } > EXPORT_SYMBOL(nand_scan_tail); > > -/* > - * is_module_text_address() isn't exported, and it's mostly a pointless > - * test if this is a module _anyway_ -- they'd have to try _really_ hard > - * to call us from in-kernel code if the core NAND support is modular. > - */ > -#ifdef MODULE > -#define caller_is_module() (1) > -#else > -#define caller_is_module() \ > - is_module_text_address((unsigned long)__builtin_return_address(0)) > -#endif > - > /** > * nand_scan - [NAND Interface] Scan for the NAND device > * @mtd: MTD device structure > @@ -4021,19 +4158,12 @@ EXPORT_SYMBOL(nand_scan_tail); > * > * This fills out all the uninitialized function pointers with the defaults. > * The flash ID is read and the mtd/chip structures are filled with the > - * appropriate values. The mtd->owner field must be set to the module of the > - * caller. > + * appropriate values. > */ > int nand_scan(struct mtd_info *mtd, int maxchips) > { > int ret; > > - /* Many callers got this wrong, so check for it for a while... */ > - if (!mtd->owner && caller_is_module()) { > - pr_crit("%s called with NULL mtd->owner!\n", __func__); > - BUG(); > - } > - > ret = nand_scan_ident(mtd, maxchips, NULL); > if (!ret) > ret = nand_scan_tail(mtd); > @@ -4041,9 +4171,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips) > } > EXPORT_SYMBOL(nand_scan); > > -module_init(nand_base_init); > -module_exit(nand_base_exit); > - > MODULE_LICENSE("GPL"); > MODULE_AUTHOR("Steven J. Hill <sjh...@realitydiluted.com>"); > MODULE_AUTHOR("Thomas Gleixner <t...@linutronix.de>"); > diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c > index 152f3bc..74c4c9a 100644 > --- a/drivers/mtd/nand/nand_bbt.c > +++ b/drivers/mtd/nand/nand_bbt.c > @@ -1,6 +1,4 @@ > /* > - * drivers/mtd/nand_bbt.c > - * > * Overview: > * Bad block table support for the NAND driver > * > @@ -65,7 +63,6 @@ > #include <linux/mtd/mtd.h> > #include <linux/mtd/bbm.h> > #include <linux/mtd/nand.h> > -#include <linux/mtd/nand_ecc.h> > #include <linux/bitops.h> > #include <linux/string.h> > > @@ -718,7 +715,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, > /* Must we save the block contents? */ > if (td->options & NAND_BBT_SAVECONTENT) { > /* Make it block aligned */ > - to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1)); > + to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1); > len = 1 << this->bbt_erase_shift; > res = mtd_read(mtd, to, len, &retlen, buf); > if (res < 0) { > @@ -1073,15 +1070,15 @@ static void verify_bbt_descr(struct mtd_info *mtd, > struct nand_bbt_descr *bd) > * The bad block table memory is allocated here. It must be freed by calling > * the nand_free_bbt function. > */ > -int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) > +static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) > { > struct nand_chip *this = mtd_to_nand(mtd); > - int len, res = 0; > + int len, res; > uint8_t *buf; > struct nand_bbt_descr *td = this->bbt_td; > struct nand_bbt_descr *md = this->bbt_md; > > - len = mtd->size >> (this->bbt_erase_shift + 2); > + len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1; > /* > * Allocate memory (2bit per block) and clear the memory bad block > * table. > @@ -1097,10 +1094,9 @@ int nand_scan_bbt(struct mtd_info *mtd, struct > nand_bbt_descr *bd) > if (!td) { > if ((res = nand_memory_bbt(mtd, bd))) { > pr_err("nand_bbt: can't scan flash and build the > RAM-based BBT\n"); > - kfree(this->bbt); > - this->bbt = NULL; > + goto err; > } > - return res; > + return 0; > } > verify_bbt_descr(mtd, td); > verify_bbt_descr(mtd, md); > @@ -1110,9 +1106,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct > nand_bbt_descr *bd) > len += (len >> this->page_shift) * mtd->oobsize; > buf = vmalloc(len); > if (!buf) { > - kfree(this->bbt); > - this->bbt = NULL; > - return -ENOMEM; > + res = -ENOMEM; > + goto err; > } > > /* Is the bbt at a given page? */ > @@ -1124,6 +1119,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct > nand_bbt_descr *bd) > } > > res = check_create(mtd, buf, bd); > + if (res) > + goto err; > > /* Prevent the bbt regions from erasing / writing */ > mark_bbt_region(mtd, td); > @@ -1131,6 +1128,11 @@ int nand_scan_bbt(struct mtd_info *mtd, struct > nand_bbt_descr *bd) > mark_bbt_region(mtd, md); > > vfree(buf); > + return 0; > + > +err: > + kfree(this->bbt); > + this->bbt = NULL; > return res; > } > > @@ -1369,5 +1371,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) > > return ret; > } > - > -EXPORT_SYMBOL(nand_scan_bbt); > diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c > index d7f6ce0..c145203 100644 > --- a/drivers/mtd/nand/nand_bch.c > +++ b/drivers/mtd/nand/nand_bch.c > @@ -86,7 +86,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned > char *buf, > } > } else if (count < 0) { > printk(KERN_ERR "ecc unrecoverable error\n"); > - count = -1; > + count = -EBADMSG; > } > return count; > } > @@ -94,9 +94,6 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned > char *buf, > /** > * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction > * @mtd: MTD block structure > - * @eccsize: ecc block size in bytes > - * @eccbytes: ecc length in bytes > - * @ecclayout: output default layout > * > * Returns: > * a pointer to a new NAND BCH control structure, or NULL upon failure > @@ -110,14 +107,21 @@ int nand_bch_correct_data(struct mtd_info *mtd, > unsigned char *buf, > * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > > 512*8) > * @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits) > */ > -struct nand_bch_control * > -nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int > eccbytes, > - struct nand_ecclayout **ecclayout) > +struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) > { > + struct nand_chip *nand = mtd_to_nand(mtd); > unsigned int m, t, eccsteps, i; > - struct nand_ecclayout *layout; > + struct nand_ecclayout *layout = nand->ecc.layout; > struct nand_bch_control *nbc = NULL; > unsigned char *erased_page; > + unsigned int eccsize = nand->ecc.size; > + unsigned int eccbytes = nand->ecc.bytes; > + unsigned int eccstrength = nand->ecc.strength; > + > + if (!eccbytes && eccstrength) { > + eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8); > + nand->ecc.bytes = eccbytes; > + } > > if (!eccsize || !eccbytes) { > printk(KERN_WARNING "ecc parameters not supplied\n"); > @@ -145,7 +149,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, > unsigned int eccbytes, > eccsteps = mtd->writesize/eccsize; > > /* if no ecc placement scheme was provided, build one */ > - if (!*ecclayout) { > + if (!layout) { > > /* handle large page devices only */ > if (mtd->oobsize < 64) { > @@ -171,7 +175,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, > unsigned int eccbytes, > layout->oobfree[0].offset = 2; > layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; > > - *ecclayout = layout; > + nand->ecc.layout = layout; > } > > /* sanity checks */ > @@ -179,7 +183,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, > unsigned int eccbytes, > printk(KERN_WARNING "eccsize %u is too large\n", eccsize); > goto fail; > } > - if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) { > + if (layout->eccbytes != (eccsteps*eccbytes)) { > printk(KERN_WARNING "invalid ecc layout\n"); > goto fail; > } > @@ -203,6 +207,9 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, > unsigned int eccbytes, > for (i = 0; i < eccbytes; i++) > nbc->eccmask[i] ^= 0xff; > > + if (!eccstrength) > + nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize); > + > return nbc; > fail: > nand_bch_free(nbc); > diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c > index fdd0074..561d2cd 100644 > --- a/drivers/mtd/nand/nand_ids.c > +++ b/drivers/mtd/nand/nand_ids.c > @@ -1,6 +1,4 @@ > /* > - * drivers/mtd/nandids.c > - * > * Copyright (C) 2002 Thomas Gleixner (t...@linutronix.de) > * > * This program is free software; you can redistribute it and/or modify > @@ -41,6 +39,10 @@ struct nand_flash_dev nand_flash_ids[] = { > * listed by full ID. We list them first so that we can easily identify > * the most specific match. > */ > + {"TC58NVG0S3E 1G 3.3V 8-bit", > + { .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} }, > + SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), > + 2 }, > {"TC58NVG2S0F 4G 3.3V 8-bit", > { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, > SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) }, > @@ -58,8 +60,8 @@ struct nand_flash_dev nand_flash_ids[] = { > SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, > {"H27UCG8T2ATR-BC 64G 3.3V 8-bit", > { .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} }, > - SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K), > - 4 }, > + SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640, > + NAND_ECC_INFO(40, SZ_1K), 4 }, > > LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), > LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), > diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c > index ee353c7..0a9849e 100644 > --- a/drivers/mtd/nand/ndfc.c > +++ b/drivers/mtd/nand/ndfc.c > @@ -1,6 +1,6 @@ > /* > * Overview: > - * Platform independend driver for NDFC (NanD Flash Controller) > + * Platform independent driver for NDFC (NanD Flash Controller) > * integrated into IBM/AMCC PPC4xx cores > * > * (C) Copyright 2006-2009 > diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c > index cac9eea..37c4341 100644 > --- a/drivers/mtd/nand/omap_gpmc.c > +++ b/drivers/mtd/nand/omap_gpmc.c > @@ -163,7 +163,7 @@ static int __maybe_unused omap_correct_data(struct > mtd_info *mtd, uint8_t *dat, > return 0; > printf("Error: Bad compare! failed\n"); > /* detected 2 bit error */ > - return -1; > + return -EBADMSG; > } > } > return 0; > diff --git a/drivers/mtd/nand/s3c2410_nand.c b/drivers/mtd/nand/s3c2410_nand.c > index 2a0da6e..dd742a6 100644 > --- a/drivers/mtd/nand/s3c2410_nand.c > +++ b/drivers/mtd/nand/s3c2410_nand.c > @@ -104,7 +104,7 @@ static int s3c24x0_nand_correct_data(struct mtd_info > *mtd, u_char *dat, > return 0; > > printf("s3c24x0_nand_correct_data: not implemented\n"); > - return -1; > + return -EBADMSG; > } > #endif > > diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c > index dfbefc6..f99bdaf 100644 > --- a/drivers/mtd/nand/vf610_nfc.c > +++ b/drivers/mtd/nand/vf610_nfc.c > @@ -146,7 +146,6 @@ enum vf610_nfc_alt_buf { > }; > > struct vf610_nfc { > - struct mtd_info *mtd; > struct nand_chip chip; > void __iomem *regs; > uint buf_offset; > diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h > index 9da77ec..cf20674 100644 > --- a/include/linux/mtd/mtd.h > +++ b/include/linux/mtd/mtd.h > @@ -278,6 +278,11 @@ struct mtd_info { > int usecount; > }; > > +static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) > +{ > + return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; > +} > + > int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); > #ifndef __UBOOT__ > int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, > diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h > index 34945fd..b5a02c3 100644 > --- a/include/linux/mtd/nand.h > +++ b/include/linux/mtd/nand.h > @@ -25,6 +25,8 @@ > > struct mtd_info; > struct nand_flash_dev; > +struct device_node; > + > /* Scan and identify a NAND device */ > extern int nand_scan(struct mtd_info *mtd, int max_chips); > /* > @@ -144,6 +146,14 @@ typedef enum { > /* Enable Hardware ECC before syndrome is read back from flash */ > #define NAND_ECC_READSYN 2 > > +/* > + * Enable generic NAND 'page erased' check. This check is only done when > + * ecc.correct() returns -EBADMSG. > + * Set this flag if your implementation does not fix bitflips in erased > + * pages and you want to rely on the default implementation. > + */ > +#define NAND_ECC_GENERIC_ERASED_CHECK BIT(0) > + > /* Bit mask for flags passed to do_nand_read_ecc */ > #define NAND_GET_DEVICE 0x80 > > @@ -179,6 +189,12 @@ typedef enum { > /* Device supports subpage reads */ > #define NAND_SUBPAGE_READ 0x00001000 > > +/* > + * Some MLC NANDs need data scrambling to limit bitflips caused by repeated > + * patterns. > + */ > +#define NAND_NEED_SCRAMBLING 0x00002000 > + > /* Options valid for Samsung large page devices */ > #define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG > > @@ -203,6 +219,11 @@ typedef enum { > * before calling nand_scan_tail. > */ > #define NAND_BUSWIDTH_AUTO 0x00080000 > +/* > + * This option could be defined by controller drivers to protect against > + * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers > + */ > +#define NAND_USE_BOUNCE_BUFFER 0x00100000 > > /* Options set by nand scan */ > /* bbt has already been read */ > @@ -292,15 +313,15 @@ struct nand_onfi_params { > __le16 t_r; > __le16 t_ccs; > __le16 src_sync_timing_mode; > - __le16 src_ssync_features; > + u8 src_ssync_features; > __le16 clk_pin_capacitance_typ; > __le16 io_pin_capacitance_typ; > __le16 input_pin_capacitance_typ; > u8 input_pin_capacitance_max; > u8 driver_strength_support; > __le16 t_int_r; > - __le16 t_ald; > - u8 reserved4[7]; > + __le16 t_adl; > + u8 reserved4[8]; > > /* vendor */ > __le16 vendor_revision; > @@ -423,7 +444,7 @@ struct nand_jedec_params { > __le16 input_pin_capacitance_typ; > __le16 clk_pin_capacitance_typ; > u8 driver_strength_support; > - __le16 t_ald; > + __le16 t_adl; > u8 reserved4[36]; > > /* ECC and endurance block */ > @@ -466,12 +487,19 @@ struct nand_hw_control { > * @total: total number of ECC bytes per page > * @prepad: padding information for syndrome based ECC generators > * @postpad: padding information for syndrome based ECC generators > + * @options: ECC specific options (see NAND_ECC_XXX flags defined above) > * @layout: ECC layout control struct pointer > * @priv: pointer to private ECC control data > * @hwctl: function to control hardware ECC generator. Must only > * be provided if an hardware ECC is available > * @calculate: function for ECC calculation or readback from ECC > hardware > - * @correct: function for ECC correction, matching to ECC generator (sw/hw) > + * @correct: function for ECC correction, matching to ECC generator (sw/hw). > + * Should return a positive number representing the number of > + * corrected bitflips, -EBADMSG if the number of bitflips exceed > + * ECC strength, or any other error code if the error is not > + * directly related to correction. > + * If -EBADMSG is returned the input buffers should be left > + * untouched. > * @read_page_raw: function to read a raw page without ECC. This function > * should hide the specific layout used by the ECC > * controller and always return contiguous in-band and > @@ -509,6 +537,7 @@ struct nand_ecc_ctrl { > int strength; > int prepad; > int postpad; > + unsigned int options; > struct nand_ecclayout *layout; > void *priv; > void (*hwctl)(struct mtd_info *mtd, int mode); > @@ -556,6 +585,7 @@ struct nand_buffers { > > /** > * struct nand_chip - NAND Private Flash Chip Data > + * @mtd: MTD device registered to the MTD framework > * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines > of the > * flash device > * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O > lines of the > @@ -571,10 +601,6 @@ struct nand_buffers { > * @block_markbad: [REPLACEABLE] mark a block bad > * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for > controlling > * ALE/CLE/nCE. Also used to write command and address > - * @init_size: [BOARDSPECIFIC] hardwarespecific function for > setting > - * mtd->oobsize, mtd->writesize and so on. > - * @id_data contains the 8 bytes values of NAND_CMD_READID. > - * Return with the bus width. > * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for > accessing > * device ready/busy line. If set to NULL no access to > * ready/busy is available and the ready/busy information > @@ -669,11 +695,9 @@ struct nand_chip { > 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); > void (*select_chip)(struct mtd_info *mtd, int chip); > - int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); > + int (*block_bad)(struct mtd_info *mtd, loff_t ofs); > int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); > void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); > - int (*init_size)(struct mtd_info *mtd, struct nand_chip *this, > - u8 *id_data); > int (*dev_ready)(struct mtd_info *mtd); > void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, > int page_addr); > @@ -873,7 +897,6 @@ struct nand_manufacturers { > extern struct nand_flash_dev nand_flash_ids[]; > extern struct nand_manufacturers nand_manuf_ids[]; > > -extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); > extern int nand_default_bbt(struct mtd_info *mtd); > extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); > extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs); > @@ -898,7 +921,6 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t > from, size_t len, > * @chip_delay: R/B delay value in us > * @options: Option flags, e.g. 16bit buswidth > * @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH > - * @ecclayout: ECC layout info structure > * @part_probe_types: NULL-terminated array of probe types > */ > struct platform_nand_chip { > @@ -906,7 +928,6 @@ struct platform_nand_chip { > int chip_offset; > int nr_partitions; > struct mtd_partition *partitions; > - struct nand_ecclayout *ecclayout; > int chip_delay; > unsigned int options; > unsigned int bbt_options; > @@ -955,15 +976,6 @@ struct platform_nand_data { > struct platform_nand_ctrl ctrl; > }; > > -/* Some helpers to access the data structures */ > -static inline > -struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd) > -{ > - struct nand_chip *chip = mtd->priv; > - > - return chip->priv; > -} > - > #ifdef CONFIG_SYS_NAND_ONFI_DETECTION > /* return the supported features. */ > static inline int onfi_feature(struct nand_chip *chip) > @@ -1081,4 +1093,9 @@ struct nand_sdr_timings { > > /* get timing characteristics from ONFI timing mode. */ > const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int > mode); > + > +int nand_check_erased_ecc_chunk(void *data, int datalen, > + void *ecc, int ecclen, > + void *extraoob, int extraooblen, > + int threshold); > #endif /* __LINUX_MTD_NAND_H */ > diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h > index d8754dd..8ea6b04 100644 > --- a/include/linux/mtd/nand_bch.h > +++ b/include/linux/mtd/nand_bch.h > @@ -32,9 +32,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, u_char > *dat, u_char *read_ecc, > /* > * Initialize BCH encoder/decoder > */ > -struct nand_bch_control * > -nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, > - unsigned int eccbytes, struct nand_ecclayout **ecclayout); > +struct nand_bch_control *nand_bch_init(struct mtd_info *mtd); > /* > * Release BCH encoder/decoder resources > */ > @@ -55,12 +53,10 @@ static inline int > nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, > unsigned char *read_ecc, unsigned char *calc_ecc) > { > - return -1; > + return -ENOTSUPP; > } > > -static inline struct nand_bch_control * > -nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, > - unsigned int eccbytes, struct nand_ecclayout **ecclayout) > +static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) > { > return NULL; > } -- Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot