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@xxxxxxxxx> --- 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 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox