Lines Matching full:ecc
172 * struct sunxi_nand_hw_ecc - stores information related to HW ECC support
174 * @mode: the sunxi ECC mode field deduced from ECC requirements
593 bool ecc) in sunxi_nfc_randomizer_state() argument
602 if (ecc) { in sunxi_nfc_randomizer_state()
613 bool ecc) in sunxi_nfc_randomizer_config() argument
623 state = sunxi_nfc_randomizer_state(nand, page, ecc); in sunxi_nfc_randomizer_config()
660 bool ecc, int page) in sunxi_nfc_randomizer_write_buf() argument
662 sunxi_nfc_randomizer_config(nand, page, ecc); in sunxi_nfc_randomizer_write_buf()
669 int len, bool ecc, int page) in sunxi_nfc_randomizer_read_buf() argument
671 sunxi_nfc_randomizer_config(nand, page, ecc); in sunxi_nfc_randomizer_read_buf()
680 struct sunxi_nand_hw_ecc *data = nand->ecc.priv; in sunxi_nfc_hw_ecc_enable()
689 if (nand->ecc.size == 512) in sunxi_nfc_hw_ecc_enable()
764 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_correct() local
783 memset(data, pattern, ecc->size); in sunxi_nfc_hw_ecc_correct()
786 memset(oob, pattern, ecc->bytes + 4); in sunxi_nfc_hw_ecc_correct()
804 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_chunk() local
812 sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); in sunxi_nfc_hw_ecc_read_chunk()
814 if (data_off + ecc->size != oob_off) in sunxi_nfc_hw_ecc_read_chunk()
830 *cur_off = oob_off + ecc->bytes + 4; in sunxi_nfc_hw_ecc_read_chunk()
845 ecc->size, false); in sunxi_nfc_hw_ecc_read_chunk()
848 ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
850 nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
853 ret = nand_check_erased_ecc_chunk(data, ecc->size, in sunxi_nfc_hw_ecc_read_chunk()
854 oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
855 NULL, 0, ecc->strength); in sunxi_nfc_hw_ecc_read_chunk()
859 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
864 sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
882 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_extra_oob() local
883 int offset = ((ecc->bytes + 4) * ecc->steps); in sunxi_nfc_hw_ecc_read_extra_oob()
910 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_chunks_dma() local
920 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, in sunxi_nfc_hw_ecc_read_chunks_dma()
952 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_chunks_dma()
953 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_chunks_dma()
962 /* ECC errors are handled in the second loop. */ in sunxi_nfc_hw_ecc_read_chunks_dma()
970 oob, ecc->bytes + 4, false); in sunxi_nfc_hw_ecc_read_chunks_dma()
984 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_chunks_dma()
985 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_chunks_dma()
999 data, ecc->size, in sunxi_nfc_hw_ecc_read_chunks_dma()
1005 oob, ecc->bytes + 4, false); in sunxi_nfc_hw_ecc_read_chunks_dma()
1007 ret = nand_check_erased_ecc_chunk(data, ecc->size, in sunxi_nfc_hw_ecc_read_chunks_dma()
1008 oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunks_dma()
1010 ecc->strength); in sunxi_nfc_hw_ecc_read_chunks_dma()
1033 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_chunk() local
1039 sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); in sunxi_nfc_hw_ecc_write_chunk()
1041 if (data_off + ecc->size != oob_off) in sunxi_nfc_hw_ecc_write_chunk()
1060 *cur_off = oob_off + ecc->bytes + 4; in sunxi_nfc_hw_ecc_write_chunk()
1070 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_extra_oob() local
1071 int offset = ((ecc->bytes + 4) * ecc->steps); in sunxi_nfc_hw_ecc_write_extra_oob()
1091 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_page() local
1102 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_read_page()
1103 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_page()
1104 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_page()
1137 nand->ecc.steps); in sunxi_nfc_hw_ecc_read_page_dma()
1150 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_subpage() local
1160 for (i = data_offs / ecc->size; in sunxi_nfc_hw_ecc_read_subpage()
1161 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { in sunxi_nfc_hw_ecc_read_subpage()
1162 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_subpage()
1163 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_subpage()
1185 int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); in sunxi_nfc_hw_ecc_read_subpage_dma()
1206 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_page() local
1215 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_write_page()
1216 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_write_page()
1217 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_write_page()
1243 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_subpage() local
1252 for (i = data_offs / ecc->size; in sunxi_nfc_hw_ecc_write_subpage()
1253 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { in sunxi_nfc_hw_ecc_write_subpage()
1254 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_write_subpage()
1255 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_write_subpage()
1277 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_page_dma() local
1287 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, in sunxi_nfc_hw_ecc_write_page_dma()
1292 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_write_page_dma()
1293 const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4)); in sunxi_nfc_hw_ecc_write_page_dma()
1340 return nand->ecc.read_page(nand, buf, 1, page); in sunxi_nfc_hw_ecc_read_oob()
1350 ret = nand->ecc.write_page(nand, buf, 1, page); in sunxi_nfc_hw_ecc_write_oob()
1553 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_ooblayout_ecc() local
1555 if (section >= ecc->steps) in sunxi_nand_ooblayout_ecc()
1558 oobregion->offset = section * (ecc->bytes + 4) + 4; in sunxi_nand_ooblayout_ecc()
1559 oobregion->length = ecc->bytes; in sunxi_nand_ooblayout_ecc()
1568 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_ooblayout_free() local
1570 if (section > ecc->steps) in sunxi_nand_ooblayout_free()
1578 if (!section && ecc->mode == NAND_ECC_HW) { in sunxi_nand_ooblayout_free()
1585 oobregion->offset = section * (ecc->bytes + 4); in sunxi_nand_ooblayout_free()
1587 if (section < ecc->steps) in sunxi_nand_ooblayout_free()
1596 .ecc = sunxi_nand_ooblayout_ecc,
1600 static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc) in sunxi_nand_hw_ecc_ctrl_cleanup() argument
1602 kfree(ecc->priv); in sunxi_nand_hw_ecc_ctrl_cleanup()
1606 struct nand_ecc_ctrl *ecc, in sunxi_nand_hw_ecc_ctrl_init() argument
1617 if (ecc->options & NAND_ECC_MAXIMIZE) { in sunxi_nand_hw_ecc_ctrl_init()
1620 ecc->size = 1024; in sunxi_nand_hw_ecc_ctrl_init()
1621 nsectors = mtd->writesize / ecc->size; in sunxi_nand_hw_ecc_ctrl_init()
1626 /* 4 non-ECC bytes are added before each ECC bytes section */ in sunxi_nand_hw_ecc_ctrl_init()
1633 ecc->strength = bytes * 8 / fls(8 * ecc->size); in sunxi_nand_hw_ecc_ctrl_init()
1636 if (strengths[i] > ecc->strength) in sunxi_nand_hw_ecc_ctrl_init()
1641 ecc->strength = 0; in sunxi_nand_hw_ecc_ctrl_init()
1643 ecc->strength = strengths[i - 1]; in sunxi_nand_hw_ecc_ctrl_init()
1646 if (ecc->size != 512 && ecc->size != 1024) in sunxi_nand_hw_ecc_ctrl_init()
1653 /* Prefer 1k ECC chunk over 512 ones */ in sunxi_nand_hw_ecc_ctrl_init()
1654 if (ecc->size == 512 && mtd->writesize > 512) { in sunxi_nand_hw_ecc_ctrl_init()
1655 ecc->size = 1024; in sunxi_nand_hw_ecc_ctrl_init()
1656 ecc->strength *= 2; in sunxi_nand_hw_ecc_ctrl_init()
1659 /* Add ECC info retrieval from DT */ in sunxi_nand_hw_ecc_ctrl_init()
1661 if (ecc->strength <= strengths[i]) { in sunxi_nand_hw_ecc_ctrl_init()
1663 * Update ecc->strength value with the actual strength in sunxi_nand_hw_ecc_ctrl_init()
1664 * that will be used by the ECC engine. in sunxi_nand_hw_ecc_ctrl_init()
1666 ecc->strength = strengths[i]; in sunxi_nand_hw_ecc_ctrl_init()
1679 /* HW ECC always request ECC bytes for 1024 bytes blocks */ in sunxi_nand_hw_ecc_ctrl_init()
1680 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8); in sunxi_nand_hw_ecc_ctrl_init()
1682 /* HW ECC always work with even numbers of ECC bytes */ in sunxi_nand_hw_ecc_ctrl_init()
1683 ecc->bytes = ALIGN(ecc->bytes, 2); in sunxi_nand_hw_ecc_ctrl_init()
1685 nsectors = mtd->writesize / ecc->size; in sunxi_nand_hw_ecc_ctrl_init()
1687 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) { in sunxi_nand_hw_ecc_ctrl_init()
1692 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob; in sunxi_nand_hw_ecc_ctrl_init()
1693 ecc->write_oob = sunxi_nfc_hw_ecc_write_oob; in sunxi_nand_hw_ecc_ctrl_init()
1695 ecc->priv = data; in sunxi_nand_hw_ecc_ctrl_init()
1698 ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma; in sunxi_nand_hw_ecc_ctrl_init()
1699 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma; in sunxi_nand_hw_ecc_ctrl_init()
1700 ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma; in sunxi_nand_hw_ecc_ctrl_init()
1703 ecc->read_page = sunxi_nfc_hw_ecc_read_page; in sunxi_nand_hw_ecc_ctrl_init()
1704 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage; in sunxi_nand_hw_ecc_ctrl_init()
1705 ecc->write_page = sunxi_nfc_hw_ecc_write_page; in sunxi_nand_hw_ecc_ctrl_init()
1709 ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage; in sunxi_nand_hw_ecc_ctrl_init()
1710 ecc->read_oob_raw = nand_read_oob_std; in sunxi_nand_hw_ecc_ctrl_init()
1711 ecc->write_oob_raw = nand_write_oob_std; in sunxi_nand_hw_ecc_ctrl_init()
1721 static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) in sunxi_nand_ecc_cleanup() argument
1723 switch (ecc->mode) { in sunxi_nand_ecc_cleanup()
1725 sunxi_nand_hw_ecc_ctrl_cleanup(ecc); in sunxi_nand_ecc_cleanup()
1735 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_attach_chip() local
1747 if (!ecc->size) { in sunxi_nand_attach_chip()
1748 ecc->size = nand->base.eccreq.step_size; in sunxi_nand_attach_chip()
1749 ecc->strength = nand->base.eccreq.strength; in sunxi_nand_attach_chip()
1752 if (!ecc->size || !ecc->strength) in sunxi_nand_attach_chip()
1755 switch (ecc->mode) { in sunxi_nand_attach_chip()
1757 ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np); in sunxi_nand_attach_chip()
1990 * Set the ECC mode to the default value in case nothing is specified in sunxi_nand_chip_init()
1993 nand->ecc.mode = NAND_ECC_HW; in sunxi_nand_chip_init()
2047 sunxi_nand_ecc_cleanup(&sunxi_nand->nand.ecc); in sunxi_nand_chips_cleanup()