Lines Matching +full:hardware +full:- +full:wise
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2009-2015 Freescale Semiconductor, Inc. and others
15 * - Untested on MPC5125 and M54418.
16 * - DMA and pipelining not used.
17 * - 2K pages or less.
18 * - HW ECC: Only 2K page with 64+ OOB.
19 * - HW ECC: Only 24 and 32-bit error correction implemented.
67 #define COMMAND_NADDR_BYTES(x) GENMASK(13, 13 - (x) + 1)
136 * ECC status - seems to consume 8 bytes (double word). The documented
141 #define ECC_SRAM_ADDR (PAGE_2K + OOB_MAX - 8)
176 return readl(nfc->regs + reg); in vf610_nfc_read()
181 writel(val, nfc->regs + reg); in vf610_nfc_write()
227 * write and read side (e.g. page wise data access).
238 memcpy(dst + i, &val, min(sizeof(val), len - i)); in vf610_nfc_rd_from_sram()
262 * write and read side (e.g. page wise data access).
273 memcpy(&val, src + i, min(sizeof(val), len - i)); in vf610_nfc_wr_to_sram()
304 if (!wait_for_completion_timeout(&nfc->cmd_done, timeout)) in vf610_nfc_done()
305 dev_warn(nfc->dev, "Timeout while waiting for BUSY.\n"); in vf610_nfc_done()
315 complete(&nfc->cmd_done); in vf610_nfc_irq()
340 dev_dbg(nfc->dev, in vf610_nfc_run()
350 if (*op_id + 1 >= subop->ninstrs) in vf610_get_next_instr()
355 return &subop->instrs[*op_id]; in vf610_get_next_instr()
363 int op_id = -1, trfr_sz = 0, offset = 0; in vf610_nfc_cmd()
368 * Some ops are optional, but the hardware requires the operations in vf610_nfc_cmd()
375 return -EINVAL; in vf610_nfc_cmd()
377 if (instr && instr->type == NAND_OP_CMD_INSTR) { in vf610_nfc_cmd()
378 cmd2 |= instr->ctx.cmd.opcode << CMD_BYTE1_SHIFT; in vf610_nfc_cmd()
384 if (instr && instr->type == NAND_OP_ADDR_INSTR) { in vf610_nfc_cmd()
389 u8 val = instr->ctx.addr.addrs[i]; in vf610_nfc_cmd()
394 row |= ROW_ADDR(i - 2, val); in vf610_nfc_cmd()
401 if (instr && instr->type == NAND_OP_DATA_OUT_INSTR) { in vf610_nfc_cmd()
404 force8bit = instr->ctx.data.force_8bit; in vf610_nfc_cmd()
410 vf610_nfc_wr_to_sram(nfc->regs + NFC_MAIN_AREA(0) + offset, in vf610_nfc_cmd()
411 instr->ctx.data.buf.out + offset, in vf610_nfc_cmd()
412 trfr_sz, !nfc->data_access); in vf610_nfc_cmd()
418 if (instr && instr->type == NAND_OP_CMD_INSTR) { in vf610_nfc_cmd()
419 cmd1 |= instr->ctx.cmd.opcode << CMD_BYTE2_SHIFT; in vf610_nfc_cmd()
425 if (instr && instr->type == NAND_OP_WAITRDY_INSTR) { in vf610_nfc_cmd()
431 if (instr && instr->type == NAND_OP_DATA_IN_INSTR) { in vf610_nfc_cmd()
434 force8bit = instr->ctx.data.force_8bit; in vf610_nfc_cmd()
439 if (force8bit && (chip->options & NAND_BUSWIDTH_16)) in vf610_nfc_cmd()
446 if (instr && instr->type == NAND_OP_DATA_IN_INSTR) { in vf610_nfc_cmd()
451 vf610_nfc_rd_from_sram(instr->ctx.data.buf.in + offset, in vf610_nfc_cmd()
452 nfc->regs + NFC_MAIN_AREA(0) + offset, in vf610_nfc_cmd()
453 trfr_sz, !nfc->data_access); in vf610_nfc_cmd()
456 if (force8bit && (chip->options & NAND_BUSWIDTH_16)) in vf610_nfc_cmd()
486 if (nfc->variant != NFC_VFC610) in vf610_nfc_select_target()
502 vf610_nfc_select_target(chip, op->cs); in vf610_nfc_exec_op()
516 int flips_threshold = nfc->chip.ecc.strength / 2; in vf610_nfc_correct_data()
524 nfc->data_access = true; in vf610_nfc_correct_data()
525 nand_read_oob_op(&nfc->chip, page, 0, oob, mtd->oobsize); in vf610_nfc_correct_data()
526 nfc->data_access = false; in vf610_nfc_correct_data()
532 return nand_check_erased_ecc_chunk(dat, nfc->chip.ecc.size, oob, in vf610_nfc_correct_data()
533 mtd->oobsize, NULL, 0, in vf610_nfc_correct_data()
543 if (chip->options & NAND_ROW_ADDR_3) { in vf610_nfc_fill_row()
554 int trfr_sz = mtd->writesize + mtd->oobsize; in vf610_nfc_read_page()
558 vf610_nfc_select_target(chip, chip->cur_cs); in vf610_nfc_read_page()
570 vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); in vf610_nfc_read_page()
578 vf610_nfc_rd_from_sram(buf, nfc->regs + NFC_MAIN_AREA(0), in vf610_nfc_read_page()
579 mtd->writesize, false); in vf610_nfc_read_page()
581 vf610_nfc_rd_from_sram(chip->oob_poi, in vf610_nfc_read_page()
582 nfc->regs + NFC_MAIN_AREA(0) + in vf610_nfc_read_page()
583 mtd->writesize, in vf610_nfc_read_page()
584 mtd->oobsize, false); in vf610_nfc_read_page()
586 stat = vf610_nfc_correct_data(chip, buf, chip->oob_poi, page); in vf610_nfc_read_page()
589 mtd->ecc_stats.failed++; in vf610_nfc_read_page()
592 mtd->ecc_stats.corrected += stat; in vf610_nfc_read_page()
602 int trfr_sz = mtd->writesize + mtd->oobsize; in vf610_nfc_write_page()
607 vf610_nfc_select_target(chip, chip->cur_cs); in vf610_nfc_write_page()
621 vf610_nfc_wr_to_sram(nfc->regs + NFC_MAIN_AREA(0), buf, in vf610_nfc_write_page()
622 mtd->writesize, false); in vf610_nfc_write_page()
627 vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); in vf610_nfc_write_page()
636 return -EIO; in vf610_nfc_write_page()
647 nfc->data_access = true; in vf610_nfc_read_page_raw()
649 nfc->data_access = false; in vf610_nfc_read_page_raw()
661 nfc->data_access = true; in vf610_nfc_write_page_raw()
662 ret = nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); in vf610_nfc_write_page_raw()
664 ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, in vf610_nfc_write_page_raw()
666 nfc->data_access = false; in vf610_nfc_write_page_raw()
679 nfc->data_access = true; in vf610_nfc_read_oob()
681 nfc->data_access = false; in vf610_nfc_read_oob()
692 nfc->data_access = true; in vf610_nfc_write_oob()
693 ret = nand_prog_page_begin_op(chip, page, mtd->writesize, in vf610_nfc_write_oob()
694 chip->oob_poi, mtd->oobsize); in vf610_nfc_write_oob()
695 nfc->data_access = false; in vf610_nfc_write_oob()
704 { .compatible = "fsl,vf610-nfc", .data = (void *)NFC_VFC610 },
726 if (nfc->chip.options & NAND_BUSWIDTH_16) in vf610_nfc_init_controller()
731 if (nfc->chip.ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { in vf610_nfc_init_controller()
751 if (chip->bbt_options & NAND_BBT_USE_FLASH) in vf610_nfc_attach_chip()
752 chip->bbt_options |= NAND_BBT_NO_OOB; in vf610_nfc_attach_chip()
755 if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) { in vf610_nfc_attach_chip()
756 dev_err(nfc->dev, "Unsupported flash page size\n"); in vf610_nfc_attach_chip()
757 return -ENXIO; in vf610_nfc_attach_chip()
760 if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) in vf610_nfc_attach_chip()
763 if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) { in vf610_nfc_attach_chip()
764 dev_err(nfc->dev, "Unsupported flash with hwecc\n"); in vf610_nfc_attach_chip()
765 return -ENXIO; in vf610_nfc_attach_chip()
768 if (chip->ecc.size != mtd->writesize) { in vf610_nfc_attach_chip()
769 dev_err(nfc->dev, "Step size needs to be page size\n"); in vf610_nfc_attach_chip()
770 return -ENXIO; in vf610_nfc_attach_chip()
774 if (mtd->oobsize > 64) in vf610_nfc_attach_chip()
775 mtd->oobsize = 64; in vf610_nfc_attach_chip()
779 if (chip->ecc.strength == 32) { in vf610_nfc_attach_chip()
780 nfc->ecc_mode = ECC_60_BYTE; in vf610_nfc_attach_chip()
781 chip->ecc.bytes = 60; in vf610_nfc_attach_chip()
782 } else if (chip->ecc.strength == 24) { in vf610_nfc_attach_chip()
783 nfc->ecc_mode = ECC_45_BYTE; in vf610_nfc_attach_chip()
784 chip->ecc.bytes = 45; in vf610_nfc_attach_chip()
786 dev_err(nfc->dev, "Unsupported ECC strength\n"); in vf610_nfc_attach_chip()
787 return -ENXIO; in vf610_nfc_attach_chip()
790 chip->ecc.read_page = vf610_nfc_read_page; in vf610_nfc_attach_chip()
791 chip->ecc.write_page = vf610_nfc_write_page; in vf610_nfc_attach_chip()
792 chip->ecc.read_page_raw = vf610_nfc_read_page_raw; in vf610_nfc_attach_chip()
793 chip->ecc.write_page_raw = vf610_nfc_write_page_raw; in vf610_nfc_attach_chip()
794 chip->ecc.read_oob = vf610_nfc_read_oob; in vf610_nfc_attach_chip()
795 chip->ecc.write_oob = vf610_nfc_write_oob; in vf610_nfc_attach_chip()
797 chip->ecc.size = PAGE_2K; in vf610_nfc_attach_chip()
817 nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL); in vf610_nfc_probe()
819 return -ENOMEM; in vf610_nfc_probe()
821 nfc->dev = &pdev->dev; in vf610_nfc_probe()
822 chip = &nfc->chip; in vf610_nfc_probe()
825 mtd->owner = THIS_MODULE; in vf610_nfc_probe()
826 mtd->dev.parent = nfc->dev; in vf610_nfc_probe()
827 mtd->name = DRV_NAME; in vf610_nfc_probe()
833 nfc->regs = devm_platform_ioremap_resource(pdev, 0); in vf610_nfc_probe()
834 if (IS_ERR(nfc->regs)) in vf610_nfc_probe()
835 return PTR_ERR(nfc->regs); in vf610_nfc_probe()
837 nfc->clk = devm_clk_get_enabled(&pdev->dev, NULL); in vf610_nfc_probe()
838 if (IS_ERR(nfc->clk)) { in vf610_nfc_probe()
839 dev_err(nfc->dev, "Unable to get and enable clock!\n"); in vf610_nfc_probe()
840 return PTR_ERR(nfc->clk); in vf610_nfc_probe()
843 nfc->variant = (enum vf610_nfc_variant)device_get_match_data(&pdev->dev); in vf610_nfc_probe()
844 if (!nfc->variant) in vf610_nfc_probe()
845 return -ENODEV; in vf610_nfc_probe()
847 for_each_available_child_of_node(nfc->dev->of_node, child) { in vf610_nfc_probe()
848 if (of_device_is_compatible(child, "fsl,vf610-nfc-nandcs")) { in vf610_nfc_probe()
851 dev_err(nfc->dev, in vf610_nfc_probe()
854 return -EINVAL; in vf610_nfc_probe()
862 dev_err(nfc->dev, "NAND chip sub-node missing!\n"); in vf610_nfc_probe()
863 return -ENODEV; in vf610_nfc_probe()
866 chip->options |= NAND_NO_SUBPAGE_WRITE; in vf610_nfc_probe()
868 init_completion(&nfc->cmd_done); in vf610_nfc_probe()
870 err = devm_request_irq(nfc->dev, irq, vf610_nfc_irq, 0, DRV_NAME, nfc); in vf610_nfc_probe()
872 dev_err(nfc->dev, "Error requesting IRQ!\n"); in vf610_nfc_probe()
878 nand_controller_init(&nfc->base); in vf610_nfc_probe()
879 nfc->base.ops = &vf610_nfc_controller_ops; in vf610_nfc_probe()
880 chip->controller = &nfc->base; in vf610_nfc_probe()
903 struct nand_chip *chip = &nfc->chip; in vf610_nfc_remove()
916 clk_disable_unprepare(nfc->clk); in vf610_nfc_suspend()
925 err = clk_prepare_enable(nfc->clk); in vf610_nfc_resume()