From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1b016Q-0000Po-9X for barebox@lists.infradead.org; Tue, 10 May 2016 06:25:07 +0000 From: Sascha Hauer Date: Tue, 10 May 2016 08:24:43 +0200 Message-Id: <1462861483-19983-4-git-send-email-s.hauer@pengutronix.de> In-Reply-To: <1462861483-19983-1-git-send-email-s.hauer@pengutronix.de> References: <1462861483-19983-1-git-send-email-s.hauer@pengutronix.de> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [PATCH 4/4] mtd: nand: nand_mxs: Add subpage read support To: Barebox List subpage read support can significantly speed up scanning UBI volumes, so add support for it. This is inspired by the corresponding Kernel commit. Unlike in the kernel we add subpage read support for i.MX28 aswell. Testing it on i.MX28 revealed no problems. Signed-off-by: Sascha Hauer --- drivers/mtd/nand/nand_mxs.c | 55 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index be7f88f..a9c6e96 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -665,8 +665,9 @@ static void mxs_nand_config_bch(struct mtd_info *mtd, int readlen) /* * Read a page from NAND. */ -static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) +static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, + uint8_t *buf, int oob_required, int page, + int readlen) { struct mxs_nand_info *nand_info = nand->priv; struct mxs_dma_desc *d; @@ -674,7 +675,17 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, uint32_t corrected = 0, failed = 0; uint8_t *status; unsigned int max_bitflips = 0; - int i, ret; + int i, ret, readtotal, nchunks, eccstrength, ecc_parity_size; + + eccstrength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); + + readlen = roundup(readlen, MXS_NAND_CHUNK_DATA_CHUNK_SIZE); + nchunks = mxs_nand_ecc_chunk_cnt(readlen); + ecc_parity_size = 13 * eccstrength / 8; + readtotal = MXS_NAND_METADATA_SIZE + + (MXS_NAND_CHUNK_DATA_CHUNK_SIZE + ecc_parity_size) * nchunks; + + mxs_nand_config_bch(mtd, readtotal); /* Compile the DMA descriptor - wait for ready. */ d = mxs_nand_get_dma_desc(nand_info); @@ -706,13 +717,13 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, GPMI_CTRL0_WORD_LENGTH | (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | GPMI_CTRL0_ADDRESS_NAND_DATA | - (mtd->writesize + mtd->oobsize); + readtotal; d->cmd.pio_words[1] = 0; d->cmd.pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC | GPMI_ECCCTRL_ECC_CMD_DECODE | GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE; - d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize; + d->cmd.pio_words[3] = readtotal; d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf; d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf; @@ -732,7 +743,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, GPMI_CTRL0_WORD_LENGTH | (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | GPMI_CTRL0_ADDRESS_NAND_DATA | - (mtd->writesize + mtd->oobsize); + readtotal; d->cmd.pio_words[1] = 0; d->cmd.pio_words[2] = 0; @@ -764,11 +775,11 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, /* Read DMA completed, now do the mark swapping. */ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); - memcpy(buf, nand_info->data_buf, mtd->writesize); + memcpy(buf, nand_info->data_buf, readlen); /* Loop over status bytes, accumulating ECC status. */ status = nand_info->oob_buf + mxs_nand_aux_status_offset(); - for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) { + for (i = 0; i < nchunks; i++) { if (status[i] == 0x00) continue; @@ -843,9 +854,34 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, rtn: mxs_nand_return_dma_descs(nand_info); + mxs_nand_config_bch(mtd, mtd->writesize + mtd->oobsize); + return ret ? ret : max_bitflips; } +static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, + uint8_t *buf, int oob_required, int page) +{ + return __mxs_nand_ecc_read_page(mtd, nand, buf, oob_required, page, + mtd->writesize); +} + +static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, + uint32_t offs, uint32_t len, uint8_t *buf, int page) +{ + /* + * For now always read from the beginning of a page. Allowing + * offsets here makes __mxs_nand_ecc_read_page() more + * complicated. + */ + if (offs) { + len += offs; + offs = 0; + } + + return __mxs_nand_ecc_read_page(mtd, chip, buf, 0, page, len); +} + /* * Write a page to NAND. */ @@ -1356,6 +1392,9 @@ static int mxs_nand_probe(struct device_d *dev) nand->ecc.size = 512; nand->ecc.strength = 8; + nand->ecc.read_subpage = gpmi_ecc_read_subpage; + nand->options |= NAND_SUBPAGE_READ; + /* first scan to find the device and get the page size */ err = nand_scan_ident(mtd, 4, NULL); if (err) -- 2.8.0.rc3 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox