Lines Matching +full:nand +full:- +full:rb
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2009-2015 Freescale Semiconductor, Inc. and others
5 * Description: MPC5125, VF610, MCF54418 and Kinetis K70 Nand driver.
6 * Ported to U-Boot by Stefan Agner
17 * - Untested on MPC5125 and M54418.
18 * - DMA and pipelining not used.
19 * - 2K pages or less.
20 * - HW ECC: Only 2K page with 64+ OOB.
21 * - HW ECC: Only 24 and 32-bit error correction implemented.
31 #include <nand.h>
62 * - 31.4.7 Flash Command Code Description, Vybrid manual
63 * - 23.8.6 Flash Command Sequencer, MPC5125 manual
134 * ECC status - seems to consume 8 bytes (double word). The documented
139 #define ECC_SRAM_ADDR (PAGE_2K + OOB_MAX - 8)
201 return readl(nfc->regs + reg); in vf610_nfc_read()
208 writel(val, nfc->regs + reg); in vf610_nfc_write()
273 vf610_nfc_clear_status(nfc->regs); in vf610_nfc_done()
282 flash_id >>= (3 - col) * 8; in vf610_nfc_get_id()
327 if (column != -1) { in vf610_nfc_addr_cycle()
329 if (nfc->chip.options & NAND_BUSWIDTH_16) in vf610_nfc_addr_cycle()
334 if (page != -1) in vf610_nfc_addr_cycle()
351 /* Send command to NAND chip */
356 int trfr_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0; in vf610_nfc_command()
358 nfc->buf_offset = max(column, 0); in vf610_nfc_command()
359 nfc->alt_buf = ALT_BUF_DATA; in vf610_nfc_command()
365 nfc->buf_offset = 0; in vf610_nfc_command()
373 trfr_sz += nfc->write_sz; in vf610_nfc_command()
375 vf610_nfc_transfer_size(nfc->regs, trfr_sz); in vf610_nfc_command()
376 vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN, in vf610_nfc_command()
381 vf610_nfc_transfer_size(nfc->regs, 0); in vf610_nfc_command()
382 vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE); in vf610_nfc_command()
386 trfr_sz += mtd->oobsize; in vf610_nfc_command()
387 column = mtd->writesize; in vf610_nfc_command()
388 vf610_nfc_transfer_size(nfc->regs, trfr_sz); in vf610_nfc_command()
389 vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, in vf610_nfc_command()
396 trfr_sz += mtd->writesize + mtd->oobsize; in vf610_nfc_command()
397 vf610_nfc_transfer_size(nfc->regs, trfr_sz); in vf610_nfc_command()
399 vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, in vf610_nfc_command()
405 nfc->alt_buf = ALT_BUF_ONFI; in vf610_nfc_command()
407 vf610_nfc_transfer_size(nfc->regs, trfr_sz); in vf610_nfc_command()
408 vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM, in vf610_nfc_command()
416 vf610_nfc_transfer_size(nfc->regs, 0); in vf610_nfc_command()
417 vf610_nfc_send_commands(nfc->regs, command, in vf610_nfc_command()
423 nfc->alt_buf = ALT_BUF_ID; in vf610_nfc_command()
424 nfc->buf_offset = 0; in vf610_nfc_command()
425 vf610_nfc_transfer_size(nfc->regs, 0); in vf610_nfc_command()
426 vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE); in vf610_nfc_command()
432 nfc->alt_buf = ALT_BUF_STAT; in vf610_nfc_command()
433 vf610_nfc_transfer_size(nfc->regs, 0); in vf610_nfc_command()
434 vf610_nfc_send_command(nfc->regs, command, STATUS_READ_CMD_CODE); in vf610_nfc_command()
442 nfc->write_sz = 0; in vf610_nfc_command()
449 uint c = nfc->buf_offset; in vf610_nfc_read_buf()
452 if (nfc->alt_buf) in vf610_nfc_read_buf()
455 vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); in vf610_nfc_read_buf()
457 nfc->buf_offset += len; in vf610_nfc_read_buf()
465 uint c = nfc->buf_offset; in vf610_nfc_write_buf()
468 l = min_t(uint, len, mtd->writesize + mtd->oobsize - c); in vf610_nfc_write_buf()
469 vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l); in vf610_nfc_write_buf()
471 nfc->write_sz += l; in vf610_nfc_write_buf()
472 nfc->buf_offset += l; in vf610_nfc_write_buf()
480 uint c = nfc->buf_offset; in vf610_nfc_read_byte()
482 switch (nfc->alt_buf) { in vf610_nfc_read_byte()
492 c = nfc->buf_offset ^ 0x3; in vf610_nfc_read_byte()
493 /* fall-through */ in vf610_nfc_read_byte()
496 tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); in vf610_nfc_read_byte()
499 nfc->buf_offset++; in vf610_nfc_read_byte()
520 * This function supports Vybrid only (MPC5125 would have full RB and four CS)
560 int flips_threshold = nfc->chip.ecc.strength / 2; in vf610_nfc_correct_data()
570 vf610_nfc_read_buf(mtd, oob, mtd->oobsize); in vf610_nfc_correct_data()
576 flips = count_written_bits(dat, nfc->chip.ecc.size, flips_threshold); in vf610_nfc_correct_data()
577 flips += count_written_bits(oob, mtd->oobsize, flips_threshold); in vf610_nfc_correct_data()
580 return -EINVAL; in vf610_nfc_correct_data()
583 memset(dat, 0xff, nfc->chip.ecc.size); in vf610_nfc_correct_data()
584 memset(oob, 0xff, mtd->oobsize); in vf610_nfc_correct_data()
591 int eccsize = chip->ecc.size; in vf610_nfc_read_page()
596 vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize); in vf610_nfc_read_page()
598 stat = vf610_nfc_correct_data(mtd, buf, chip->oob_poi, page); in vf610_nfc_read_page()
601 mtd->ecc_stats.failed++; in vf610_nfc_read_page()
604 mtd->ecc_stats.corrected += stat; in vf610_nfc_read_page()
617 vf610_nfc_write_buf(mtd, buf, mtd->writesize); in vf610_nfc_write_page()
619 vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize); in vf610_nfc_write_page()
622 nfc->write_sz = mtd->writesize + mtd->oobsize; in vf610_nfc_write_page()
652 return -ENOMEM; in vf610_nfc_nand_init()
655 chip = &nfc->chip; in vf610_nfc_nand_init()
656 nfc->regs = addr; in vf610_nfc_nand_init()
662 chip->options |= NAND_BUSWIDTH_16; in vf610_nfc_nand_init()
664 chip->dev_ready = vf610_nfc_dev_ready; in vf610_nfc_nand_init()
665 chip->cmdfunc = vf610_nfc_command; in vf610_nfc_nand_init()
666 chip->read_byte = vf610_nfc_read_byte; in vf610_nfc_nand_init()
667 chip->read_word = vf610_nfc_read_word; in vf610_nfc_nand_init()
668 chip->read_buf = vf610_nfc_read_buf; in vf610_nfc_nand_init()
669 chip->write_buf = vf610_nfc_write_buf; in vf610_nfc_nand_init()
670 chip->select_chip = vf610_nfc_select_chip; in vf610_nfc_nand_init()
672 chip->options |= NAND_NO_SUBPAGE_WRITE; in vf610_nfc_nand_init()
674 chip->ecc.size = PAGE_2K; in vf610_nfc_nand_init()
690 err = -ENXIO; in vf610_nfc_nand_init()
699 chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB | in vf610_nfc_nand_init()
703 if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) { in vf610_nfc_nand_init()
704 dev_err(nfc->dev, "Unsupported flash page size\n"); in vf610_nfc_nand_init()
705 err = -ENXIO; in vf610_nfc_nand_init()
710 if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) { in vf610_nfc_nand_init()
711 dev_err(nfc->dev, "Unsupported flash with hwecc\n"); in vf610_nfc_nand_init()
712 err = -ENXIO; in vf610_nfc_nand_init()
716 if (chip->ecc.size != mtd->writesize) { in vf610_nfc_nand_init()
717 dev_err(nfc->dev, "ecc size: %d\n", chip->ecc.size); in vf610_nfc_nand_init()
718 dev_err(nfc->dev, "Step size needs to be page size\n"); in vf610_nfc_nand_init()
719 err = -ENXIO; in vf610_nfc_nand_init()
724 if (mtd->oobsize > 64) in vf610_nfc_nand_init()
725 mtd->oobsize = 64; in vf610_nfc_nand_init()
728 mtd->ecclayout = chip->ecc.layout; in vf610_nfc_nand_init()
729 chip->ecc.read_page = vf610_nfc_read_page; in vf610_nfc_nand_init()
730 chip->ecc.write_page = vf610_nfc_write_page; in vf610_nfc_nand_init()
731 chip->ecc.mode = NAND_ECC_HW; in vf610_nfc_nand_init()
733 chip->ecc.size = PAGE_2K; in vf610_nfc_nand_init()
734 chip->ecc.layout = &vf610_nfc_ecc; in vf610_nfc_nand_init()
736 chip->ecc.strength = 24; in vf610_nfc_nand_init()
737 chip->ecc.bytes = 45; in vf610_nfc_nand_init()
739 chip->ecc.strength = 32; in vf610_nfc_nand_init()
740 chip->ecc.bytes = 60; in vf610_nfc_nand_init()
771 .compatible = "fsl,vf610-nfc",
790 .name = "vf610-nfc-dt",
804 if (ret && ret != -ENODEV) in board_nand_init()
805 pr_err("Failed to initialize NAND controller. (error %d)\n", in board_nand_init()
813 printf("VF610 NAND init failed (err %d)\n", err); in board_nand_init()