Lines Matching +full:nand +full:- +full:ecc +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0+
11 #include <nand.h>
24 * ECC4 and ECC1 have 13 bytes and 3 bytes of ecc respectively for 512 bytes of
61 * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes. 13*8 bytes
62 * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 118
97 * ECC placement definitions in oobfree type format
98 * There are 13 bytes of ecc for every 512 byte block and it has to be read
101 * Managing the ecc bytes in the following way makes it easier for software to
102 * read ecc bytes consecutive to data bytes. This way is similar to
103 * oobfree structure maintained already in u-boot nand driver
171 IO_ADDR_W = (ulong)this->IO_ADDR_W; in fsmc_nand_hwcontrol()
180 writel(readl(&fsmc_regs_p->pc) | in fsmc_nand_hwcontrol()
181 FSMC_ENABLE, &fsmc_regs_p->pc); in fsmc_nand_hwcontrol()
183 writel(readl(&fsmc_regs_p->pc) & in fsmc_nand_hwcontrol()
184 ~FSMC_ENABLE, &fsmc_regs_p->pc); in fsmc_nand_hwcontrol()
186 this->IO_ADDR_W = (void *)IO_ADDR_W; in fsmc_nand_hwcontrol()
190 writeb(cmd, this->IO_ADDR_W); in fsmc_nand_hwcontrol()
196 /* The calculated ecc is actually the correction index in data */ in fsmc_bch8_correct_data()
201 num_err = (readl(&fsmc_regs_p->sts) >> 10) & 0xF; in fsmc_bch8_correct_data()
209 * would result in an ecc error because the oob data is also in fsmc_bch8_correct_data()
210 * erased to FF and the calculated ecc for an FF data is not in fsmc_bch8_correct_data()
230 return -EBADMSG; in fsmc_bch8_correct_data()
233 ecc1 = readl(&fsmc_regs_p->ecc1); in fsmc_bch8_correct_data()
234 ecc2 = readl(&fsmc_regs_p->ecc2); in fsmc_bch8_correct_data()
235 ecc3 = readl(&fsmc_regs_p->ecc3); in fsmc_bch8_correct_data()
236 ecc4 = readl(&fsmc_regs_p->sts); in fsmc_bch8_correct_data()
261 const u_char *data, u_char *ecc) in fsmc_read_hwecc() argument
272 * Busy waiting for ecc computation in fsmc_read_hwecc()
275 if (readl(&fsmc_regs_p->sts) & FSMC_CODE_RDY) in fsmc_read_hwecc()
279 ecc_tmp = readl(&fsmc_regs_p->ecc1); in fsmc_read_hwecc()
280 ecc[0] = (u_char) (ecc_tmp >> 0); in fsmc_read_hwecc()
281 ecc[1] = (u_char) (ecc_tmp >> 8); in fsmc_read_hwecc()
282 ecc[2] = (u_char) (ecc_tmp >> 16); in fsmc_read_hwecc()
283 ecc[3] = (u_char) (ecc_tmp >> 24); in fsmc_read_hwecc()
285 ecc_tmp = readl(&fsmc_regs_p->ecc2); in fsmc_read_hwecc()
286 ecc[4] = (u_char) (ecc_tmp >> 0); in fsmc_read_hwecc()
287 ecc[5] = (u_char) (ecc_tmp >> 8); in fsmc_read_hwecc()
288 ecc[6] = (u_char) (ecc_tmp >> 16); in fsmc_read_hwecc()
289 ecc[7] = (u_char) (ecc_tmp >> 24); in fsmc_read_hwecc()
291 ecc_tmp = readl(&fsmc_regs_p->ecc3); in fsmc_read_hwecc()
292 ecc[8] = (u_char) (ecc_tmp >> 0); in fsmc_read_hwecc()
293 ecc[9] = (u_char) (ecc_tmp >> 8); in fsmc_read_hwecc()
294 ecc[10] = (u_char) (ecc_tmp >> 16); in fsmc_read_hwecc()
295 ecc[11] = (u_char) (ecc_tmp >> 24); in fsmc_read_hwecc()
297 ecc_tmp = readl(&fsmc_regs_p->sts); in fsmc_read_hwecc()
298 ecc[12] = (u_char) (ecc_tmp >> 16); in fsmc_read_hwecc()
302 ecc_tmp = readl(&fsmc_regs_p->ecc1); in fsmc_read_hwecc()
303 ecc[0] = (u_char) (ecc_tmp >> 0); in fsmc_read_hwecc()
304 ecc[1] = (u_char) (ecc_tmp >> 8); in fsmc_read_hwecc()
305 ecc[2] = (u_char) (ecc_tmp >> 16); in fsmc_read_hwecc()
312 void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) in fsmc_enable_hwecc() argument
314 writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCPLEN_256, in fsmc_enable_hwecc()
315 &fsmc_regs_p->pc); in fsmc_enable_hwecc()
316 writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCEN, in fsmc_enable_hwecc()
317 &fsmc_regs_p->pc); in fsmc_enable_hwecc()
318 writel(readl(&fsmc_regs_p->pc) | FSMC_ECCEN, in fsmc_enable_hwecc()
319 &fsmc_regs_p->pc); in fsmc_enable_hwecc()
325 * @chip: nand chip info structure
327 * @oob_required: caller expects OOB data read to chip->oob_poi
330 * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
332 * data(512 byte) -> ecc(13 byte)
340 int i, j, s, stat, eccsize = chip->ecc.size; in fsmc_read_page_hwecc()
341 int eccbytes = chip->ecc.bytes; in fsmc_read_page_hwecc()
342 int eccsteps = chip->ecc.steps; in fsmc_read_page_hwecc()
344 uint8_t *ecc_calc = chip->buffers->ecccalc; in fsmc_read_page_hwecc()
345 uint8_t *ecc_code = chip->buffers->ecccode; in fsmc_read_page_hwecc()
349 /* Differentiate between small and large page ecc place definitions */ in fsmc_read_page_hwecc()
350 if (mtd->writesize == 512) in fsmc_read_page_hwecc()
357 chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); in fsmc_read_page_hwecc()
358 chip->ecc.hwctl(mtd, NAND_ECC_READ); in fsmc_read_page_hwecc()
359 chip->read_buf(mtd, p, eccsize); in fsmc_read_page_hwecc()
362 off = fsmc_eccpl->eccplace[group].offset; in fsmc_read_page_hwecc()
363 len = fsmc_eccpl->eccplace[group].length; in fsmc_read_page_hwecc()
368 * to read at least 13 bytes even in case of 16 bit NAND in fsmc_read_page_hwecc()
371 if (chip->options & NAND_BUSWIDTH_16) in fsmc_read_page_hwecc()
373 chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page); in fsmc_read_page_hwecc()
374 chip->read_buf(mtd, oob + j, len); in fsmc_read_page_hwecc()
379 chip->ecc.calculate(mtd, p, &ecc_calc[i]); in fsmc_read_page_hwecc()
381 stat = chip->ecc.correct(mtd, p, &ecc_code[i], in fsmc_read_page_hwecc()
384 mtd->ecc_stats.failed++; in fsmc_read_page_hwecc()
386 mtd->ecc_stats.corrected += stat; in fsmc_read_page_hwecc()
394 * fsmc_nand_switch_ecc - switch the ECC operation between different engines
396 * @eccstrength - the number of bits that could be corrected
397 * (1 - HW, 4 - SW BCH4)
401 struct nand_chip *nand; in fsmc_nand_switch_ecc() local
407 * 1 bit HW ECC. The BCH8 HW ECC (FSMC_VER8) from the ST-Ericsson in fsmc_nand_switch_ecc()
409 * function, as it doesn't need to switch to a different ECC layout. in fsmc_nand_switch_ecc()
412 nand = mtd_to_nand(mtd); in fsmc_nand_switch_ecc()
414 /* Setup the ecc configurations again */ in fsmc_nand_switch_ecc()
416 nand->ecc.mode = NAND_ECC_HW; in fsmc_nand_switch_ecc()
417 nand->ecc.bytes = 3; in fsmc_nand_switch_ecc()
418 nand->ecc.strength = 1; in fsmc_nand_switch_ecc()
419 nand->ecc.layout = &fsmc_ecc1_layout; in fsmc_nand_switch_ecc()
420 nand->ecc.calculate = fsmc_read_hwecc; in fsmc_nand_switch_ecc()
421 nand->ecc.correct = nand_correct_data; in fsmc_nand_switch_ecc()
427 nand->ecc.mode = NAND_ECC_SOFT_BCH; in fsmc_nand_switch_ecc()
428 nand->ecc.strength = 4; in fsmc_nand_switch_ecc()
429 nand->ecc.layout = NULL; in fsmc_nand_switch_ecc()
431 printf("Error: ECC strength %d not supported!\n", eccstrength); in fsmc_nand_switch_ecc()
434 /* Update NAND handling after ECC mode switch */ in fsmc_nand_switch_ecc()
441 int fsmc_nand_init(struct nand_chip *nand) in fsmc_nand_init() argument
445 u32 peripid2 = readl(&fsmc_regs_p->peripid2); in fsmc_nand_init()
450 writel(readl(&fsmc_regs_p->ctrl) | FSMC_WP, &fsmc_regs_p->ctrl); in fsmc_nand_init()
454 &fsmc_regs_p->pc); in fsmc_nand_init()
457 &fsmc_regs_p->pc); in fsmc_nand_init()
461 writel(readl(&fsmc_regs_p->pc) | FSMC_TCLR_1 | FSMC_TAR_1, in fsmc_nand_init()
462 &fsmc_regs_p->pc); in fsmc_nand_init()
464 &fsmc_regs_p->comm); in fsmc_nand_init()
466 &fsmc_regs_p->attrib); in fsmc_nand_init()
468 nand->options = 0; in fsmc_nand_init()
470 nand->options |= NAND_BUSWIDTH_16; in fsmc_nand_init()
472 nand->ecc.mode = NAND_ECC_HW; in fsmc_nand_init()
473 nand->ecc.size = 512; in fsmc_nand_init()
474 nand->ecc.calculate = fsmc_read_hwecc; in fsmc_nand_init()
475 nand->ecc.hwctl = fsmc_enable_hwecc; in fsmc_nand_init()
476 nand->cmd_ctrl = fsmc_nand_hwcontrol; in fsmc_nand_init()
477 nand->IO_ADDR_R = nand->IO_ADDR_W = in fsmc_nand_init()
479 nand->badblockbits = 7; in fsmc_nand_init()
481 mtd = nand_to_mtd(nand); in fsmc_nand_init()
485 nand->ecc.bytes = 13; in fsmc_nand_init()
486 nand->ecc.strength = 8; in fsmc_nand_init()
487 nand->ecc.correct = fsmc_bch8_correct_data; in fsmc_nand_init()
488 nand->ecc.read_page = fsmc_read_page_hwecc; in fsmc_nand_init()
489 if (mtd->writesize == 512) in fsmc_nand_init()
490 nand->ecc.layout = &fsmc_ecc4_sp_layout; in fsmc_nand_init()
492 if (mtd->oobsize == 224) in fsmc_nand_init()
493 nand->ecc.layout = &fsmc_ecc4_224_layout; in fsmc_nand_init()
495 nand->ecc.layout = &fsmc_ecc4_lp_layout; in fsmc_nand_init()
500 nand->ecc.bytes = 3; in fsmc_nand_init()
501 nand->ecc.strength = 1; in fsmc_nand_init()
502 nand->ecc.layout = &fsmc_ecc1_layout; in fsmc_nand_init()
503 nand->ecc.correct = nand_correct_data; in fsmc_nand_init()
507 /* Detect NAND chips */ in fsmc_nand_init()
509 return -ENXIO; in fsmc_nand_init()
512 return -ENXIO; in fsmc_nand_init()
515 return -ENXIO; in fsmc_nand_init()