diff options
author | Josh Wu <josh.wu@atmel.com> | 2012-11-29 18:45:52 +0800 |
---|---|---|
committer | Josh Wu <josh.wu@atmel.com> | 2012-11-30 16:59:26 +0800 |
commit | 587aa30fdfb5bc27f9568b62395ff9855ae91b00 (patch) | |
tree | 9b9c97ce5d1500e468a3d2d1efa3abfd715a0cac | |
parent | 59f94a35a359800c5ef90d258583af7a1a702b63 (diff) |
MTD: at91: atmel_nand: since PMECC support different ecc
correctable bits(2, 4, 8, 12, 24), add code to choose
the ecc bits according to the ONFI parameter's minimum
required ecc_bits.
we'll check the ecc_bits (minimum required ecc correct bits) in ONFI parameter.
If ecc_bits is smaller compare with CONFIG_PMECC_CAP in config file, then use ecc_bits. otherwise use CONFIG_PMECC_CAP.
for non-ONFI support nand flash, we assume its minimum ecc_bits is 1.
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index e2f6c4f2a8..8a5dce2e58 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -675,6 +675,44 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) pmecc_writel(host->pmecc, ctrl, PMECC_CTRL_ENABLE); } +static int pmecc_choose_ecc_bits(int pre_ecc_bits, struct nand_chip *nand_chip) +{ + int ecc_bits = pre_ecc_bits; + + if (nand_chip->onfi_version) { + printk(KERN_WARNING "ONFI params, minimum required ECC: %d\n", + nand_chip->onfi_params.ecc_bits); + if (nand_chip->onfi_params.ecc_bits < ecc_bits) + ecc_bits = nand_chip->onfi_params.ecc_bits; + } else { + /* For non-ONFI support nand flash, we assume the software + * ecc can work. That means the ecc_bits = 1. + */ + ecc_bits = 1; + printk(KERN_WARNING "non-ONFI supported nand flash, assume minimum required ECC: 1\n"); + } + + if ((ecc_bits != 2) && (ecc_bits != 4) && (ecc_bits != 8) && (ecc_bits != 12) && + (ecc_bits != 24)) { + /* use the most fitable ecc bits (the near bigger one ) */ + if (ecc_bits < 2) + return 2; + else if (ecc_bits < 4) + return 4; + else if (ecc_bits < 8) + return 8; + else if (ecc_bits < 12) + return 12; + else if (ecc_bits < 24) + return 24; + else + /* not support by our pmecc hw */ + return pre_ecc_bits; + } else { + return ecc_bits; + } +} + static int atmel_pmecc_nand_init_params(struct nand_chip *nand, struct mtd_info *mtd) { @@ -688,7 +726,10 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, nand->ecc.correct = NULL; nand->ecc.hwctl = NULL; - cap = host->pmecc_corr_cap = CONFIG_PMECC_CAP; + /* Choose PMECC ecc bits according to ONFI parameters */ + host->pmecc_corr_cap = pmecc_choose_ecc_bits(CONFIG_PMECC_CAP, nand); + cap = host->pmecc_corr_cap; + sector_size = host->pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE; host->pmecc_index_table_offset = CONFIG_PMECC_INDEX_TABLE_OFFSET; |