static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd) { uint32_t ecc_strength; ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7; }
/* * Nominally, the purpose of this function is to look for or create the bad * block table. In fact, since the we call this function at the very end of * the initialization process started by nand_scan(), and we don't have a * more formal mechanism, we "hook" this function to continue init process. * * At this point, the physical NAND Flash chips have been identified and * counted, so we know the physical geometry. This enables us to make some * important configuration decisions. * * The return value of this function propogates directly back to this driver's * call to nand_scan(). Anything other than zero will cause this driver to * tear everything down and declare failure. */ static int mxs_nand_scan_bbt(struct mtd_info *mtd) { struct nand_chip *nand = mtd->priv; struct mxs_nand_info *nand_info = nand->priv; uint32_t tmp; /* Configure BCH and set NFC geometry */ if (readl(&bch_regs->hw_bch_ctrl_reg) & (BCH_CTRL_SFTRST | BCH_CTRL_CLKGATE)) /* When booting from NAND the BCH engine will already * be operational and obviously does not like being reset here. * There will be occasional read errors upon boot when this * reset is done. */ mxs_reset_block(&bch_regs->hw_bch_ctrl_reg); readl(&bch_regs->hw_bch_ctrl_reg); debug("mtd->writesize=%d\n", mtd->writesize); debug("mtd->oobsize=%d\n", mtd->oobsize); debug("ecc_strength=%d\n", mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize)); /* Configure layout 0 */ tmp = (mxs_nand_ecc_chunk_cnt(mtd) - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET; tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET; tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET; tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE; writel(tmp, &bch_regs->hw_bch_flash0layout0); tmp = (mtd->writesize + mtd->oobsize) << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET; tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET; tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE; writel(tmp, &bch_regs->hw_bch_flash0layout1); /* Set *all* chip selects to use layout 0 */ writel(0, &bch_regs->hw_bch_layoutselect); /* Enable BCH complete interrupt */ writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set); /* Hook some operations at the MTD level. */ if (mtd->read_oob != mxs_nand_hook_read_oob) { nand_info->hooked_read_oob = mtd->read_oob; mtd->read_oob = mxs_nand_hook_read_oob; } if (mtd->write_oob != mxs_nand_hook_write_oob) { nand_info->hooked_write_oob = mtd->write_oob; mtd->write_oob = mxs_nand_hook_write_oob; } if (mtd->block_markbad != mxs_nand_hook_block_markbad) { nand_info->hooked_block_markbad = mtd->block_markbad; mtd->block_markbad = mxs_nand_hook_block_markbad; } /* We use the reference implementation for bad block management. */ return nand_default_bbt(mtd); }