Lines Matching full:ecc
172 * struct sunxi_nand_hw_ecc - stores information related to HW ECC support
185 * @ecc: ECC controller structure
195 struct sunxi_nand_hw_ecc ecc; member
603 bool ecc) in sunxi_nfc_randomizer_state() argument
612 if (ecc) { in sunxi_nfc_randomizer_state()
623 bool ecc) in sunxi_nfc_randomizer_config() argument
633 state = sunxi_nfc_randomizer_state(nand, page, ecc); in sunxi_nfc_randomizer_config()
670 bool ecc, int page) in sunxi_nfc_randomizer_write_buf() argument
672 sunxi_nfc_randomizer_config(nand, page, ecc); in sunxi_nfc_randomizer_write_buf()
679 int len, bool ecc, int page) in sunxi_nfc_randomizer_read_buf() argument
681 sunxi_nfc_randomizer_config(nand, page, ecc); in sunxi_nfc_randomizer_read_buf()
692 writel(sunxi_nand->ecc.ecc_ctl, nfc->regs + NFC_REG_ECC_CTL); in sunxi_nfc_hw_ecc_enable()
763 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_correct() local
782 memset(data, pattern, ecc->size); in sunxi_nfc_hw_ecc_correct()
785 memset(oob, pattern, ecc->bytes + 4); in sunxi_nfc_hw_ecc_correct()
803 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_chunk() local
811 sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); in sunxi_nfc_hw_ecc_read_chunk()
813 if (data_off + ecc->size != oob_off) in sunxi_nfc_hw_ecc_read_chunk()
829 *cur_off = oob_off + ecc->bytes + 4; in sunxi_nfc_hw_ecc_read_chunk()
844 ecc->size, false); in sunxi_nfc_hw_ecc_read_chunk()
847 ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
849 nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
852 ret = nand_check_erased_ecc_chunk(data, ecc->size, in sunxi_nfc_hw_ecc_read_chunk()
853 oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
854 NULL, 0, ecc->strength); in sunxi_nfc_hw_ecc_read_chunk()
858 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); in sunxi_nfc_hw_ecc_read_chunk()
863 sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunk()
881 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_extra_oob() local
882 int offset = ((ecc->bytes + 4) * ecc->steps); in sunxi_nfc_hw_ecc_read_extra_oob()
909 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_chunks_dma() local
919 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks, in sunxi_nfc_hw_ecc_read_chunks_dma()
956 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_chunks_dma()
957 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_chunks_dma()
966 /* ECC errors are handled in the second loop. */ in sunxi_nfc_hw_ecc_read_chunks_dma()
974 oob, ecc->bytes + 4, false); in sunxi_nfc_hw_ecc_read_chunks_dma()
988 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_chunks_dma()
989 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_chunks_dma()
1003 data, ecc->size, in sunxi_nfc_hw_ecc_read_chunks_dma()
1009 oob, ecc->bytes + 4, false); in sunxi_nfc_hw_ecc_read_chunks_dma()
1011 ret = nand_check_erased_ecc_chunk(data, ecc->size, in sunxi_nfc_hw_ecc_read_chunks_dma()
1012 oob, ecc->bytes + 4, in sunxi_nfc_hw_ecc_read_chunks_dma()
1014 ecc->strength); in sunxi_nfc_hw_ecc_read_chunks_dma()
1037 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_chunk() local
1043 sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); in sunxi_nfc_hw_ecc_write_chunk()
1045 if (data_off + ecc->size != oob_off) in sunxi_nfc_hw_ecc_write_chunk()
1064 *cur_off = oob_off + ecc->bytes + 4; in sunxi_nfc_hw_ecc_write_chunk()
1074 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_extra_oob() local
1075 int offset = ((ecc->bytes + 4) * ecc->steps); in sunxi_nfc_hw_ecc_write_extra_oob()
1095 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_page() local
1106 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_read_page()
1107 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_page()
1108 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_page()
1141 nand->ecc.steps); in sunxi_nfc_hw_ecc_read_page_dma()
1154 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_read_subpage() local
1164 for (i = data_offs / ecc->size; in sunxi_nfc_hw_ecc_read_subpage()
1165 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { in sunxi_nfc_hw_ecc_read_subpage()
1166 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_read_subpage()
1167 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_read_subpage()
1189 int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size); in sunxi_nfc_hw_ecc_read_subpage_dma()
1210 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_page() local
1219 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_write_page()
1220 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_write_page()
1221 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_write_page()
1247 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_subpage() local
1256 for (i = data_offs / ecc->size; in sunxi_nfc_hw_ecc_write_subpage()
1257 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { in sunxi_nfc_hw_ecc_write_subpage()
1258 int data_off = i * ecc->size; in sunxi_nfc_hw_ecc_write_subpage()
1259 int oob_off = i * (ecc->bytes + 4); in sunxi_nfc_hw_ecc_write_subpage()
1281 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nfc_hw_ecc_write_page_dma() local
1292 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps, in sunxi_nfc_hw_ecc_write_page_dma()
1297 for (i = 0; i < ecc->steps; i++) { in sunxi_nfc_hw_ecc_write_page_dma()
1298 const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4)); in sunxi_nfc_hw_ecc_write_page_dma()
1350 return nand->ecc.read_page(nand, buf, 1, page); in sunxi_nfc_hw_ecc_read_oob()
1360 ret = nand->ecc.write_page(nand, buf, 1, page); in sunxi_nfc_hw_ecc_write_oob()
1563 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_ooblayout_ecc() local
1565 if (section >= ecc->steps) in sunxi_nand_ooblayout_ecc()
1568 oobregion->offset = section * (ecc->bytes + 4) + 4; in sunxi_nand_ooblayout_ecc()
1569 oobregion->length = ecc->bytes; in sunxi_nand_ooblayout_ecc()
1578 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_ooblayout_free() local
1580 if (section > ecc->steps) in sunxi_nand_ooblayout_free()
1588 if (!section && ecc->engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { in sunxi_nand_ooblayout_free()
1597 * past the end of the ECC data. in sunxi_nand_ooblayout_free()
1599 if (section == ecc->steps && ecc->engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) in sunxi_nand_ooblayout_free()
1602 oobregion->offset = section * (ecc->bytes + 4); in sunxi_nand_ooblayout_free()
1604 if (section < ecc->steps) in sunxi_nand_ooblayout_free()
1613 .ecc = sunxi_nand_ooblayout_ecc,
1618 struct nand_ecc_ctrl *ecc, in sunxi_nand_hw_ecc_ctrl_init() argument
1629 if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) { in sunxi_nand_hw_ecc_ctrl_init()
1632 ecc->size = 1024; in sunxi_nand_hw_ecc_ctrl_init()
1633 nsectors = mtd->writesize / ecc->size; in sunxi_nand_hw_ecc_ctrl_init()
1638 /* 4 non-ECC bytes are added before each ECC bytes section */ in sunxi_nand_hw_ecc_ctrl_init()
1645 ecc->strength = bytes * 8 / fls(8 * ecc->size); in sunxi_nand_hw_ecc_ctrl_init()
1648 if (strengths[i] > ecc->strength) in sunxi_nand_hw_ecc_ctrl_init()
1653 ecc->strength = 0; in sunxi_nand_hw_ecc_ctrl_init()
1655 ecc->strength = strengths[i - 1]; in sunxi_nand_hw_ecc_ctrl_init()
1658 if (ecc->size != 512 && ecc->size != 1024) in sunxi_nand_hw_ecc_ctrl_init()
1661 /* Prefer 1k ECC chunk over 512 ones */ in sunxi_nand_hw_ecc_ctrl_init()
1662 if (ecc->size == 512 && mtd->writesize > 512) { in sunxi_nand_hw_ecc_ctrl_init()
1663 ecc->size = 1024; in sunxi_nand_hw_ecc_ctrl_init()
1664 ecc->strength *= 2; in sunxi_nand_hw_ecc_ctrl_init()
1667 /* Add ECC info retrieval from DT */ in sunxi_nand_hw_ecc_ctrl_init()
1669 if (ecc->strength <= strengths[i]) { in sunxi_nand_hw_ecc_ctrl_init()
1671 * Update ecc->strength value with the actual strength in sunxi_nand_hw_ecc_ctrl_init()
1672 * that will be used by the ECC engine. in sunxi_nand_hw_ecc_ctrl_init()
1674 ecc->strength = strengths[i]; in sunxi_nand_hw_ecc_ctrl_init()
1684 /* HW ECC always request ECC bytes for 1024 bytes blocks */ in sunxi_nand_hw_ecc_ctrl_init()
1685 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8); in sunxi_nand_hw_ecc_ctrl_init()
1687 /* HW ECC always work with even numbers of ECC bytes */ in sunxi_nand_hw_ecc_ctrl_init()
1688 ecc->bytes = ALIGN(ecc->bytes, 2); in sunxi_nand_hw_ecc_ctrl_init()
1690 nsectors = mtd->writesize / ecc->size; in sunxi_nand_hw_ecc_ctrl_init()
1692 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) in sunxi_nand_hw_ecc_ctrl_init()
1695 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob; in sunxi_nand_hw_ecc_ctrl_init()
1696 ecc->write_oob = sunxi_nfc_hw_ecc_write_oob; in sunxi_nand_hw_ecc_ctrl_init()
1700 ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma; in sunxi_nand_hw_ecc_ctrl_init()
1701 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma; in sunxi_nand_hw_ecc_ctrl_init()
1702 ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma; in sunxi_nand_hw_ecc_ctrl_init()
1705 ecc->read_page = sunxi_nfc_hw_ecc_read_page; in sunxi_nand_hw_ecc_ctrl_init()
1706 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage; in sunxi_nand_hw_ecc_ctrl_init()
1707 ecc->write_page = sunxi_nfc_hw_ecc_write_page; in sunxi_nand_hw_ecc_ctrl_init()
1711 ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage; in sunxi_nand_hw_ecc_ctrl_init()
1712 ecc->read_oob_raw = nand_read_oob_std; in sunxi_nand_hw_ecc_ctrl_init()
1713 ecc->write_oob_raw = nand_write_oob_std; in sunxi_nand_hw_ecc_ctrl_init()
1715 sunxi_nand->ecc.ecc_ctl = NFC_ECC_MODE(i) | NFC_ECC_EXCEPTION | in sunxi_nand_hw_ecc_ctrl_init()
1718 if (ecc->size == 512) in sunxi_nand_hw_ecc_ctrl_init()
1719 sunxi_nand->ecc.ecc_ctl |= NFC_ECC_BLOCK_512; in sunxi_nand_hw_ecc_ctrl_init()
1728 struct nand_ecc_ctrl *ecc = &nand->ecc; in sunxi_nand_attach_chip() local
1740 if (!ecc->size) { in sunxi_nand_attach_chip()
1741 ecc->size = requirements->step_size; in sunxi_nand_attach_chip()
1742 ecc->strength = requirements->strength; in sunxi_nand_attach_chip()
1745 if (!ecc->size || !ecc->strength) in sunxi_nand_attach_chip()
1748 switch (ecc->engine_type) { in sunxi_nand_attach_chip()
1750 ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np); in sunxi_nand_attach_chip()
2000 * Set the ECC mode to the default value in case nothing is specified in sunxi_nand_chip_init()
2003 nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in sunxi_nand_chip_init()