[PATCH 2/2] ARM: i.MX: xload: consider ECC strength when reading page

Andrej Picej andrej.picej at norik.com
Mon Jun 7 02:09:51 PDT 2021


Some NAND update tools/flashers do not take the full advantage of NAND's
entire page area for ECC purposes. For example, they might only use 2112
bytes of available 2176 bytes. In this case, ECC parameters have to be
read from the FCB table and taken into account in GPMI NAND xloader to
properly calculate page data length so DMA chain can be executed
correctly.

Tested on PHYTEC phyCARD i.MX6Q board with following NANDs:
- Samsung K9K8G08U0E (pagesize: 0x800, oobsize: 0x40)
- Winbond W29N08GVSIAA (pagesize: 0x800, oobsize: 0x40) and
- Spansion S34ML08G201FI00 (pagesize: 0x800, oobsize: 0x80).

All NANDs having set ECC strength to 4 (13 bytes) despite Spansion NAND
chip supporting ECC strength of 9 (29 bytes).

Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
 arch/arm/mach-imx/xload-gpmi-nand.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 661302762..f8c456927 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -87,6 +87,7 @@ struct mxs_dma_chan {
 #define	NAND_ONFI_CRC_BASE			0x4f4e
 
 #define apbh_dma_is_imx23(aphb) ((apbh)->id == IMX23_DMA)
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 /* udelay() is not available in PBL, need to improvise */
 static void __udelay(int us)
@@ -324,6 +325,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
 		int oobsize, int pagenum, void *databuf, int raw)
 {
 	void __iomem *bch_regs = info->bch_base;
+	struct fcb_block *fcb = &info->fcb;
 	unsigned column = 0;
 	struct mxs_dma_cmd *d;
 	int cmd_queue_len;
@@ -332,10 +334,17 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
 	uint8_t	*status;
 	int i;
 	int timeout;
+	int readtotal, nchunks, eccstrength;
 	int descnum = 0;
 	int max_pagenum = info->nand_size /
 		info->organization.pagesize;
 
+	eccstrength = fcb->EccBlockNEccType << 1;
+	nchunks = writesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	readtotal = fcb->MetadataBytes;
+	readtotal += fcb->EccBlockNSize * nchunks;
+	readtotal += DIV_ROUND_UP(13 * eccstrength * nchunks, 8);
+
 	memset(info->desc, 0,
 		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
 
@@ -418,12 +427,12 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
 			GPMI_CTRL0_WORD_LENGTH |
 			GPMI_CTRL0_CS(info->cs) |
 			GPMI_CTRL0_ADDRESS_NAND_DATA |
-			(writesize + oobsize);
+			readtotal;
 		d->pio_words[1] = 0;
 		d->pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC |
 			GPMI_ECCCTRL_ECC_CMD_DECODE |
 			GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
-		d->pio_words[3] = writesize + oobsize;
+		d->pio_words[3] = readtotal;
 		d->pio_words[4] = (dma_addr_t)databuf;
 		d->pio_words[5] = (dma_addr_t)(databuf + writesize);
 
@@ -436,7 +445,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
 			GPMI_CTRL0_WORD_LENGTH |
 			GPMI_CTRL0_CS(info->cs) |
 			GPMI_CTRL0_ADDRESS_NAND_DATA |
-			(writesize + oobsize);
+			readtotal;
 	}
 
 	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
-- 
2.25.1




More information about the barebox mailing list