diff options
Diffstat (limited to 'drivers/mtd/nand/mxs_nand.c')
-rw-r--r-- | drivers/mtd/nand/mxs_nand.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 9c144a21e1..1d689015a5 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -68,6 +68,8 @@ struct mxs_nand_info { }; struct nand_ecclayout fake_ecc_layout; +static int chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE; +static int galois_field = 13; /* * Cache management functions @@ -130,12 +132,12 @@ static void mxs_nand_return_dma_descs(struct mxs_nand_info *info) static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size) { - return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; + return page_data_size / chunk_data_size; } static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength) { - return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL; + return ecc_strength * galois_field; } static uint32_t mxs_nand_aux_status_offset(void) @@ -157,8 +159,8 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size, * (page oob size - meta data size) * (bits per byte) */ ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8) - / (MXS_NAND_BITS_PER_ECC_LEVEL * - mxs_nand_ecc_chunk_cnt(page_data_size)); + / (galois_field * + mxs_nand_ecc_chunk_cnt(page_data_size)); return round_down(ecc_strength, 2); } @@ -173,7 +175,7 @@ static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, uint32_t block_mark_chunk_bit_offset; uint32_t block_mark_bit_offset; - chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8; + chunk_data_size_in_bits = chunk_data_size * 8; chunk_ecc_size_in_bits = mxs_nand_ecc_size_in_bits(ecc_strength); chunk_total_size_in_bits = @@ -460,6 +462,9 @@ static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length) mxs_dma_desc_append(channel, d); + /* Invalidate caches */ + mxs_nand_inval_data_buf(nand_info); + /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) { @@ -626,6 +631,9 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, mxs_dma_desc_append(channel, d); + /* Invalidate caches */ + mxs_nand_inval_data_buf(nand_info); + /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) { @@ -972,6 +980,16 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd) struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; uint32_t tmp; + if (mtd->oobsize > MXS_NAND_CHUNK_DATA_CHUNK_SIZE) { + galois_field = 14; + chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 2; + } + + if (mtd->oobsize > chunk_data_size) { + printf("Not support the NAND chips whose oob size is larger then %d bytes!\n", chunk_data_size); + return -EINVAL; + } + /* Configure BCH and set NFC geometry */ mxs_reset_block(&bch_regs->hw_bch_ctrl_reg); @@ -981,16 +999,18 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd) 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 - >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT; + tmp |= chunk_data_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT; + tmp |= (14 == galois_field ? 1 : 0) << + BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET; 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 - >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT; + tmp |= chunk_data_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT; + tmp |= (14 == galois_field ? 1 : 0) << + BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET; writel(tmp, &bch_regs->hw_bch_flash0layout1); /* Set *all* chip selects to use layout 0 */ |