Lines Matching +full:col +full:- +full:offset
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.
66 #define COMMAND_NADDR_BYTES(x) GENMASK(13, 13 - (x) + 1)
135 * ECC status - seems to consume 8 bytes (double word). The documented
138 * Calculate an offset to store the ECC status at the end of the buffer.
140 #define ECC_SRAM_ADDR (PAGE_2K + OOB_MAX - 8)
175 return readl(nfc->regs + reg); in vf610_nfc_read()
180 writel(val, nfc->regs + reg); in vf610_nfc_write()
237 memcpy(dst + i, &val, min(sizeof(val), len - i)); in vf610_nfc_rd_from_sram()
272 memcpy(&val, src + i, min(sizeof(val), len - i)); in vf610_nfc_wr_to_sram()
303 if (!wait_for_completion_timeout(&nfc->cmd_done, timeout)) in vf610_nfc_done()
304 dev_warn(nfc->dev, "Timeout while waiting for BUSY.\n"); in vf610_nfc_done()
314 complete(&nfc->cmd_done); in vf610_nfc_irq()
326 static inline void vf610_nfc_run(struct vf610_nfc *nfc, u32 col, u32 row, in vf610_nfc_run() argument
330 COL_ADDR_SHIFT, col); in vf610_nfc_run()
339 dev_dbg(nfc->dev, in vf610_nfc_run()
340 "col 0x%04x, row 0x%08x, cmd1 0x%08x, cmd2 0x%08x, len %d\n", in vf610_nfc_run()
341 col, row, cmd1, cmd2, trfr_sz); in vf610_nfc_run()
349 if (*op_id + 1 >= subop->ninstrs) in vf610_get_next_instr()
354 return &subop->instrs[*op_id]; in vf610_get_next_instr()
362 int op_id = -1, trfr_sz = 0, offset = 0; in vf610_nfc_cmd() local
363 u32 col = 0, row = 0, cmd1 = 0, cmd2 = 0, code = 0; in vf610_nfc_cmd() local
374 return -EINVAL; in vf610_nfc_cmd()
376 if (instr && instr->type == NAND_OP_CMD_INSTR) { in vf610_nfc_cmd()
377 cmd2 |= instr->ctx.cmd.opcode << CMD_BYTE1_SHIFT; in vf610_nfc_cmd()
383 if (instr && instr->type == NAND_OP_ADDR_INSTR) { in vf610_nfc_cmd()
388 u8 val = instr->ctx.addr.addrs[i]; in vf610_nfc_cmd()
391 col |= COL_ADDR(i, val); in vf610_nfc_cmd()
393 row |= ROW_ADDR(i - 2, val); in vf610_nfc_cmd()
400 if (instr && instr->type == NAND_OP_DATA_OUT_INSTR) { in vf610_nfc_cmd()
402 offset = nand_subop_get_data_start_off(subop, op_id); in vf610_nfc_cmd()
403 force8bit = instr->ctx.data.force_8bit; in vf610_nfc_cmd()
409 vf610_nfc_wr_to_sram(nfc->regs + NFC_MAIN_AREA(0) + offset, in vf610_nfc_cmd()
410 instr->ctx.data.buf.out + offset, in vf610_nfc_cmd()
411 trfr_sz, !nfc->data_access); in vf610_nfc_cmd()
417 if (instr && instr->type == NAND_OP_CMD_INSTR) { in vf610_nfc_cmd()
418 cmd1 |= instr->ctx.cmd.opcode << CMD_BYTE2_SHIFT; in vf610_nfc_cmd()
424 if (instr && instr->type == NAND_OP_WAITRDY_INSTR) { in vf610_nfc_cmd()
430 if (instr && instr->type == NAND_OP_DATA_IN_INSTR) { in vf610_nfc_cmd()
432 offset = nand_subop_get_data_start_off(subop, op_id); in vf610_nfc_cmd()
433 force8bit = instr->ctx.data.force_8bit; in vf610_nfc_cmd()
438 if (force8bit && (chip->options & NAND_BUSWIDTH_16)) in vf610_nfc_cmd()
443 vf610_nfc_run(nfc, col, row, cmd1, cmd2, trfr_sz); in vf610_nfc_cmd()
445 if (instr && instr->type == NAND_OP_DATA_IN_INSTR) { in vf610_nfc_cmd()
450 vf610_nfc_rd_from_sram(instr->ctx.data.buf.in + offset, in vf610_nfc_cmd()
451 nfc->regs + NFC_MAIN_AREA(0) + offset, in vf610_nfc_cmd()
452 trfr_sz, !nfc->data_access); in vf610_nfc_cmd()
455 if (force8bit && (chip->options & NAND_BUSWIDTH_16)) in vf610_nfc_cmd()
485 if (nfc->variant != NFC_VFC610) in vf610_nfc_select_target()
501 vf610_nfc_select_target(chip, op->cs); in vf610_nfc_exec_op()
515 int flips_threshold = nfc->chip.ecc.strength / 2; in vf610_nfc_correct_data()
523 nfc->data_access = true; in vf610_nfc_correct_data()
524 nand_read_oob_op(&nfc->chip, page, 0, oob, mtd->oobsize); in vf610_nfc_correct_data()
525 nfc->data_access = false; in vf610_nfc_correct_data()
531 return nand_check_erased_ecc_chunk(dat, nfc->chip.ecc.size, oob, in vf610_nfc_correct_data()
532 mtd->oobsize, NULL, 0, in vf610_nfc_correct_data()
542 if (chip->options & NAND_ROW_ADDR_3) { in vf610_nfc_fill_row()
553 int trfr_sz = mtd->writesize + mtd->oobsize; in vf610_nfc_read_page()
557 vf610_nfc_select_target(chip, chip->cur_cs); in vf610_nfc_read_page()
569 vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); in vf610_nfc_read_page()
577 vf610_nfc_rd_from_sram(buf, nfc->regs + NFC_MAIN_AREA(0), in vf610_nfc_read_page()
578 mtd->writesize, false); in vf610_nfc_read_page()
580 vf610_nfc_rd_from_sram(chip->oob_poi, in vf610_nfc_read_page()
581 nfc->regs + NFC_MAIN_AREA(0) + in vf610_nfc_read_page()
582 mtd->writesize, in vf610_nfc_read_page()
583 mtd->oobsize, false); in vf610_nfc_read_page()
585 stat = vf610_nfc_correct_data(chip, buf, chip->oob_poi, page); in vf610_nfc_read_page()
588 mtd->ecc_stats.failed++; in vf610_nfc_read_page()
591 mtd->ecc_stats.corrected += stat; in vf610_nfc_read_page()
601 int trfr_sz = mtd->writesize + mtd->oobsize; in vf610_nfc_write_page()
606 vf610_nfc_select_target(chip, chip->cur_cs); in vf610_nfc_write_page()
620 vf610_nfc_wr_to_sram(nfc->regs + NFC_MAIN_AREA(0), buf, in vf610_nfc_write_page()
621 mtd->writesize, false); in vf610_nfc_write_page()
626 vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); in vf610_nfc_write_page()
635 return -EIO; in vf610_nfc_write_page()
646 nfc->data_access = true; in vf610_nfc_read_page_raw()
648 nfc->data_access = false; in vf610_nfc_read_page_raw()
660 nfc->data_access = true; in vf610_nfc_write_page_raw()
661 ret = nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); in vf610_nfc_write_page_raw()
663 ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, in vf610_nfc_write_page_raw()
665 nfc->data_access = false; in vf610_nfc_write_page_raw()
678 nfc->data_access = true; in vf610_nfc_read_oob()
680 nfc->data_access = false; in vf610_nfc_read_oob()
691 nfc->data_access = true; in vf610_nfc_write_oob()
692 ret = nand_prog_page_begin_op(chip, page, mtd->writesize, in vf610_nfc_write_oob()
693 chip->oob_poi, mtd->oobsize); in vf610_nfc_write_oob()
694 nfc->data_access = false; in vf610_nfc_write_oob()
703 { .compatible = "fsl,vf610-nfc", .data = (void *)NFC_VFC610 },
725 if (nfc->chip.options & NAND_BUSWIDTH_16) in vf610_nfc_init_controller()
730 if (nfc->chip.ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { in vf610_nfc_init_controller()
731 /* Set ECC status offset in SRAM */ in vf610_nfc_init_controller()
750 if (chip->bbt_options & NAND_BBT_USE_FLASH) in vf610_nfc_attach_chip()
751 chip->bbt_options |= NAND_BBT_NO_OOB; in vf610_nfc_attach_chip()
754 if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) { in vf610_nfc_attach_chip()
755 dev_err(nfc->dev, "Unsupported flash page size\n"); in vf610_nfc_attach_chip()
756 return -ENXIO; in vf610_nfc_attach_chip()
759 if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) in vf610_nfc_attach_chip()
762 if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) { in vf610_nfc_attach_chip()
763 dev_err(nfc->dev, "Unsupported flash with hwecc\n"); in vf610_nfc_attach_chip()
764 return -ENXIO; in vf610_nfc_attach_chip()
767 if (chip->ecc.size != mtd->writesize) { in vf610_nfc_attach_chip()
768 dev_err(nfc->dev, "Step size needs to be page size\n"); in vf610_nfc_attach_chip()
769 return -ENXIO; in vf610_nfc_attach_chip()
773 if (mtd->oobsize > 64) in vf610_nfc_attach_chip()
774 mtd->oobsize = 64; in vf610_nfc_attach_chip()
778 if (chip->ecc.strength == 32) { in vf610_nfc_attach_chip()
779 nfc->ecc_mode = ECC_60_BYTE; in vf610_nfc_attach_chip()
780 chip->ecc.bytes = 60; in vf610_nfc_attach_chip()
781 } else if (chip->ecc.strength == 24) { in vf610_nfc_attach_chip()
782 nfc->ecc_mode = ECC_45_BYTE; in vf610_nfc_attach_chip()
783 chip->ecc.bytes = 45; in vf610_nfc_attach_chip()
785 dev_err(nfc->dev, "Unsupported ECC strength\n"); in vf610_nfc_attach_chip()
786 return -ENXIO; in vf610_nfc_attach_chip()
789 chip->ecc.read_page = vf610_nfc_read_page; in vf610_nfc_attach_chip()
790 chip->ecc.write_page = vf610_nfc_write_page; in vf610_nfc_attach_chip()
791 chip->ecc.read_page_raw = vf610_nfc_read_page_raw; in vf610_nfc_attach_chip()
792 chip->ecc.write_page_raw = vf610_nfc_write_page_raw; in vf610_nfc_attach_chip()
793 chip->ecc.read_oob = vf610_nfc_read_oob; in vf610_nfc_attach_chip()
794 chip->ecc.write_oob = vf610_nfc_write_oob; in vf610_nfc_attach_chip()
796 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()
831 return -EINVAL; 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(&pdev->dev, NULL); in vf610_nfc_probe()
838 if (IS_ERR(nfc->clk)) in vf610_nfc_probe()
839 return PTR_ERR(nfc->clk); in vf610_nfc_probe()
841 err = clk_prepare_enable(nfc->clk); in vf610_nfc_probe()
843 dev_err(nfc->dev, "Unable to enable clock!\n"); in vf610_nfc_probe()
847 of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev); in vf610_nfc_probe()
849 err = -ENODEV; in vf610_nfc_probe()
853 nfc->variant = (enum vf610_nfc_variant)of_id->data; in vf610_nfc_probe()
855 for_each_available_child_of_node(nfc->dev->of_node, child) { in vf610_nfc_probe()
856 if (of_device_is_compatible(child, "fsl,vf610-nfc-nandcs")) { in vf610_nfc_probe()
859 dev_err(nfc->dev, in vf610_nfc_probe()
861 err = -EINVAL; in vf610_nfc_probe()
871 dev_err(nfc->dev, "NAND chip sub-node missing!\n"); in vf610_nfc_probe()
872 err = -ENODEV; in vf610_nfc_probe()
876 chip->options |= NAND_NO_SUBPAGE_WRITE; in vf610_nfc_probe()
878 init_completion(&nfc->cmd_done); in vf610_nfc_probe()
880 err = devm_request_irq(nfc->dev, irq, vf610_nfc_irq, 0, DRV_NAME, nfc); in vf610_nfc_probe()
882 dev_err(nfc->dev, "Error requesting IRQ!\n"); in vf610_nfc_probe()
888 nand_controller_init(&nfc->base); in vf610_nfc_probe()
889 nfc->base.ops = &vf610_nfc_controller_ops; in vf610_nfc_probe()
890 chip->controller = &nfc->base; in vf610_nfc_probe()
908 clk_disable_unprepare(nfc->clk); in vf610_nfc_probe()
915 struct nand_chip *chip = &nfc->chip; in vf610_nfc_remove()
921 clk_disable_unprepare(nfc->clk); in vf610_nfc_remove()
930 clk_disable_unprepare(nfc->clk); in vf610_nfc_suspend()
939 err = clk_prepare_enable(nfc->clk); in vf610_nfc_resume()