#include #include #include #include #include #include #include #include #include #include #include "nand.h" /** * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * * Not for syndrome calculating ecc controllers which need a special oob layout */ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_READ); chip->read_buf(mtd, p, eccsize); chip->ecc.calculate(mtd, p, &ecc_calc[i]); } chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); for (i = 0; i < chip->ecc.total; i++) ecc_code[i] = chip->oob_poi[eccpos[i]]; eccsteps = chip->ecc.steps; p = buf; for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); if (stat < 0) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; } return 0; } /** * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer */ #ifdef CONFIG_MTD_WRITE static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *ecc_calc = chip->buffers->ecccalc; const uint8_t *p = buf; uint32_t *eccpos = chip->ecc.layout->eccpos; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_WRITE); chip->write_buf(mtd, p, eccsize); chip->ecc.calculate(mtd, p, &ecc_calc[i]); } 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); } #endif void nand_init_ecc_hw(struct nand_chip *chip) { /* Use standard hwecc read page function ? */ if (!chip->ecc.read_page) chip->ecc.read_page = nand_read_page_hwecc; #ifdef CONFIG_NAND_READ_OOB if (!chip->ecc.read_oob) chip->ecc.read_oob = nand_read_oob_std; #endif #ifdef CONFIG_MTD_WRITE if (!chip->ecc.write_oob) chip->ecc.write_oob = nand_write_oob_std; if (!chip->ecc.write_page) chip->ecc.write_page = nand_write_page_hwecc; #endif }