RE: [LINUX PATCH v12 3/3] mtd: rawnand: arasan: Add support for Arasan NAND Flash Controller

From: Naga Sureshkumar Relli
Date: Thu Nov 15 2018 - 04:34:27 EST


Hi Boris & Miquel,

I am updating the driver by addressing your comments, and I have one concern, especially in anfc_read_page_hwecc(),
there I am checking for erased pages bit flips.
Since Arasan NAND controller doesn't have multibit error detection beyond 24-bit( it can correct up to 24 bit),
i.e. there is no indication from controller to detect uncorrectable error beyond 24bit.
So I took some error count as default value(MULTI_BIT_ERR_CNT 16, I put this based on the error count that
I got while reading erased page on Micron device).
And during a page read, will just read the error count register and compare this value with the default error count(16) and if it is more
Than default then I am checking for erased page bit flips.
I am doubting that this will not work in all cases.
In my case it is just working because the error count that it got on an erased page is 16.
Could you please suggest a way to do detect erased_page bit flips when reading a page with HW-ECC?.

> +
> +/*
> + * Arasan NAND controller can't detect errors beyond 24-bit in BCH
> + * For an erased page we observed that multibit error count as 16
> + * with 24-bit ECC. so if the count is equal to or greater than 16
> + * then we can say that its an uncorrectable ECC error.
> + */
> +#define MULTI_BIT_ERR_CNT 16
> +
>
> +}
> +
> +static int anfc_read_page_hwecc(struct nand_chip *chip, u8 *buf,
> + int oob_required, int page)
> +{
> + struct anfc_nand_controller *nfc = to_anfc(chip->controller);
> + struct anfc_nand_chip *achip = to_anfc_nand(chip);
> + struct mtd_info *mtd = nand_to_mtd(chip);
> + u8 *ecc_code = chip->ecc.code_buf;
> + u8 *p;
> + int eccsize = chip->ecc.size;
> + int eccbytes = chip->ecc.bytes;
> + int stat = 0, i;
> + u32 ret;
> + unsigned int max_bitflips = 0;
> + u32 eccsteps = chip->ecc.steps;
> + u32 one_bit_err = 0, multi_bit_err = 0;
> +
> + anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDOUT,
> NAND_CMD_RNDOUTSTART);
> + anfc_config_ecc(nfc, true);
> +
> + ret = nand_read_page_op(chip, page, 0, buf, mtd->writesize);
> + if (ret)
> + return ret;
> +
> + anfc_config_ecc(nfc, false);
> + if (achip->strength) {
> + /*
> + * In BCH mode Arasan NAND controller can correct ECC upto
> + * 24-bit Beyond that, it can't even detect errors.
> + */
> + multi_bit_err = readl(nfc->base + ECC_ERR_CNT_OFST);
> + multi_bit_err = ((multi_bit_err & PAGE_ERR_CNT_MASK) >> 8);
> + } else {
> + /*
> + * In Hamming mode Arasan NAND controller can correct ECC upto
> + * 1-bit and can detect upto 2-bit errors.
> + */
> + one_bit_err = readl(nfc->base + ECC_ERR_CNT_1BIT_OFST);
> + multi_bit_err = readl(nfc->base + ECC_ERR_CNT_2BIT_OFST);
> + /* Clear ecc error count register 1Bit, 2Bit */
> + writel(0x0, nfc->base + ECC_ERR_CNT_1BIT_OFST);
> + writel(0x0, nfc->base + ECC_ERR_CNT_2BIT_OFST);
> + }
> +
> + if (oob_required)
> + chip->ecc.read_oob(chip, page);
> +
> + if (multi_bit_err >= MULTI_BIT_ERR_CNT) {
> + if (!oob_required)
> + chip->ecc.read_oob(chip, page);
> +
> + mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
> + chip->ecc.total);
> + p = buf;
> + for (i = 0; eccsteps; eccsteps--, i += eccbytes,
> + p += eccsize) {
> + stat = nand_check_erased_ecc_chunk(p,
> + chip->ecc.size,
> + &ecc_code[i],
> + eccbytes,
> + 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);
> + }
> + }
> + }
> +
> + return max_bitflips;
> +}
> +
> +

Thanks,
Naga Sureshkumar Relli.