[PATCH RFC v3 2/4] nand: pl353: Add software ecc support
Added software ecc support. Signed-off-by: Punnaiah Choudary Kalluri --- drivers/mtd/nand/pl353_nand.c | 163 + 1 files changed, 163 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/nand/pl353_nand.c b/drivers/mtd/nand/pl353_nand.c index 0be8ca2..eca205f 100644 --- a/drivers/mtd/nand/pl353_nand.c +++ b/drivers/mtd/nand/pl353_nand.c @@ -319,6 +319,71 @@ static int pl353_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, } /** + * pl353_nand_read_page_raw - [Intern] read raw page data without ecc + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip->oob_poi + * @page: Page number to read + * + * Return: Always return zero + */ +static int pl353_nand_read_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + unsigned long data_phase_addr; + uint8_t *p; + + chip->read_buf(mtd, buf, mtd->writesize); + + p = chip->oob_poi; + chip->read_buf(mtd, p, + (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH)); + p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH); + + data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; + data_phase_addr |= PL353_NAND_CLEAR_CS; + chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; + + chip->read_buf(mtd, p, PL353_NAND_LAST_TRANSFER_LENGTH); + return 0; +} + +/** + * pl353_nand_write_page_raw - [Intern] raw page write function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip->oob_poi + * + * Return: Always return zero + */ +static int pl353_nand_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf, int oob_required) +{ + unsigned long data_phase_addr; + uint8_t *p; + + chip->write_buf(mtd, buf, mtd->writesize); + + p = chip->oob_poi; + chip->write_buf(mtd, p, + (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH)); + p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH); + + data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; + data_phase_addr |= PL353_NAND_CLEAR_CS; + data_phase_addr |= (1 << END_CMD_VALID_SHIFT); + chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; + + chip->write_buf(mtd, p, PL353_NAND_LAST_TRANSFER_LENGTH); + + return 0; +} + +/** * nand_write_page_hwecc - Hardware ECC based page write function * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -384,6 +449,39 @@ static int pl353_nand_write_page_hwecc(struct mtd_info *mtd, } /** + * pl353_nand_write_page_swecc - [REPLACABLE] software ecc based page write + * function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip->oob_poi + * + * Return: Always return zero + */ +static int pl353_nand_write_page_swecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, + int oob_required) +{ + 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; + + /* Software ecc calculation */ + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, _calc[i]); + + for (i = 0; i < chip->ecc.total; i++) + chip->oob_poi[eccpos[i]] = ecc_calc[i]; + + chip->ecc.write_page_raw(mtd, chip, buf, 1); + + return 0; +} + +/** * pl353_nand_read_page_hwecc - Hardware ECC based page read function * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -465,6 +563,52 @@ static int pl353_nand_read_page_hwecc(struct mtd_info *mtd, } /** + * pl353_nand_read_page_swecc - [REPLACABLE] software ecc based page read + * function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the buffer to store read data + * @oob_required: Caller requires OOB data read to chip->oob_poi + * @page:
[PATCH RFC v3 2/4] nand: pl353: Add software ecc support
Added software ecc support. Signed-off-by: Punnaiah Choudary Kalluri punn...@xilinx.com --- drivers/mtd/nand/pl353_nand.c | 163 + 1 files changed, 163 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/nand/pl353_nand.c b/drivers/mtd/nand/pl353_nand.c index 0be8ca2..eca205f 100644 --- a/drivers/mtd/nand/pl353_nand.c +++ b/drivers/mtd/nand/pl353_nand.c @@ -319,6 +319,71 @@ static int pl353_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, } /** + * pl353_nand_read_page_raw - [Intern] read raw page data without ecc + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip-oob_poi + * @page: Page number to read + * + * Return: Always return zero + */ +static int pl353_nand_read_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + unsigned long data_phase_addr; + uint8_t *p; + + chip-read_buf(mtd, buf, mtd-writesize); + + p = chip-oob_poi; + chip-read_buf(mtd, p, + (mtd-oobsize - PL353_NAND_LAST_TRANSFER_LENGTH)); + p += (mtd-oobsize - PL353_NAND_LAST_TRANSFER_LENGTH); + + data_phase_addr = (unsigned long __force)chip-IO_ADDR_R; + data_phase_addr |= PL353_NAND_CLEAR_CS; + chip-IO_ADDR_R = (void __iomem * __force)data_phase_addr; + + chip-read_buf(mtd, p, PL353_NAND_LAST_TRANSFER_LENGTH); + return 0; +} + +/** + * pl353_nand_write_page_raw - [Intern] raw page write function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip-oob_poi + * + * Return: Always return zero + */ +static int pl353_nand_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf, int oob_required) +{ + unsigned long data_phase_addr; + uint8_t *p; + + chip-write_buf(mtd, buf, mtd-writesize); + + p = chip-oob_poi; + chip-write_buf(mtd, p, + (mtd-oobsize - PL353_NAND_LAST_TRANSFER_LENGTH)); + p += (mtd-oobsize - PL353_NAND_LAST_TRANSFER_LENGTH); + + data_phase_addr = (unsigned long __force)chip-IO_ADDR_W; + data_phase_addr |= PL353_NAND_CLEAR_CS; + data_phase_addr |= (1 END_CMD_VALID_SHIFT); + chip-IO_ADDR_W = (void __iomem * __force)data_phase_addr; + + chip-write_buf(mtd, p, PL353_NAND_LAST_TRANSFER_LENGTH); + + return 0; +} + +/** * nand_write_page_hwecc - Hardware ECC based page write function * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -384,6 +449,39 @@ static int pl353_nand_write_page_hwecc(struct mtd_info *mtd, } /** + * pl353_nand_write_page_swecc - [REPLACABLE] software ecc based page write + * function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the data buffer + * @oob_required: Caller requires OOB data read to chip-oob_poi + * + * Return: Always return zero + */ +static int pl353_nand_write_page_swecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, + int oob_required) +{ + 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; + + /* Software ecc calculation */ + for (i = 0; eccsteps; eccsteps--, i += eccbytes, 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-ecc.write_page_raw(mtd, chip, buf, 1); + + return 0; +} + +/** * pl353_nand_read_page_hwecc - Hardware ECC based page read function * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure @@ -465,6 +563,52 @@ static int pl353_nand_read_page_hwecc(struct mtd_info *mtd, } /** + * pl353_nand_read_page_swecc - [REPLACABLE] software ecc based page read + * function + * @mtd: Pointer to the mtd info structure + * @chip: Pointer to the NAND chip info structure + * @buf: Pointer to the buffer to store read data + * @oob_required: Caller requires OOB data read to chip-oob_poi + * @page: Page number