X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=drivers%2Fmtd%2Fnand%2Fatmel_nand.c;h=0d4f327ed71e2196b01e88eeaab1486f7ae0229f;hp=3b6093a81b1dac898d059004bd992eeaacf75278;hb=4ac34aa16e84b992e6a4794692801f673535bf0e;hpb=667af36905157b65fd79493e7f821db606ebbd33 diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 3b6093a81b..0d4f327ed7 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -44,6 +44,7 @@ struct atmel_nand_host { u8 pmecc_corr_cap; u16 pmecc_sector_size; u32 pmecc_index_table_offset; + u32 pmecc_version; int pmecc_bytes_per_sector; int pmecc_sector_number; @@ -486,6 +487,10 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, int i, err_nbr, eccbytes; uint8_t *buf_pos; + /* SAMA5D4 PMECC IP can correct errors for all 0xff page */ + if (host->pmecc_version >= PMECC_VERSION_SAMA5D4) + goto normal_check; + eccbytes = nand_chip->ecc.bytes; for (i = 0; i < eccbytes; i++) if (ecc[i] != 0xff) @@ -763,6 +768,62 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, } #endif +#if defined(NO_GALOIS_TABLE_IN_ROM) +static uint16_t *pmecc_galois_table; +static inline int deg(unsigned int poly) +{ + /* polynomial degree is the most-significant bit index */ + return fls(poly) - 1; +} + +static int build_gf_tables(int mm, unsigned int poly, + int16_t *index_of, int16_t *alpha_to) +{ + unsigned int i, x = 1; + const unsigned int k = 1 << deg(poly); + unsigned int nn = (1 << mm) - 1; + + /* primitive polynomial must be of degree m */ + if (k != (1u << mm)) + return -EINVAL; + + for (i = 0; i < nn; i++) { + alpha_to[i] = x; + index_of[x] = i; + if (i && (x == 1)) + /* polynomial is not primitive (a^i=1 with 0pmecc_sector_size; /* TODO: need check whether cap & sector_size is validate */ - +#if defined(NO_GALOIS_TABLE_IN_ROM) + /* + * As pmecc_rom_base is the begin of the gallois field table, So the + * index offset just set as 0. + */ + host->pmecc_index_table_offset = 0; +#else if (host->pmecc_sector_size == 512) host->pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_512; else host->pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_1024; +#endif MTDDEBUG(MTD_DEBUG_LEVEL1, "Initialize PMECC params, cap: %d, sector: %d\n", @@ -823,7 +891,17 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, host->pmecc = (struct pmecc_regs __iomem *) ATMEL_BASE_PMECC; host->pmerrloc = (struct pmecc_errloc_regs __iomem *) ATMEL_BASE_PMERRLOC; +#if defined(NO_GALOIS_TABLE_IN_ROM) + pmecc_galois_table = create_lookup_table(host->pmecc_sector_size); + if (!pmecc_galois_table) { + dev_err(host->dev, "out of memory\n"); + return -ENOMEM; + } + + host->pmecc_rom_base = (void __iomem *)pmecc_galois_table; +#else host->pmecc_rom_base = (void __iomem *) ATMEL_BASE_ROM; +#endif /* ECC is calculated for the whole page (1 step) */ nand->ecc.size = mtd->writesize; @@ -888,6 +966,10 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, nand->ecc.write_page = atmel_nand_pmecc_write_page; nand->ecc.strength = cap; + /* Check the PMECC ip version */ + host->pmecc_version = pmecc_readl(host->pmerrloc, version); + dev_dbg(host->dev, "PMECC IP version is: %x\n", host->pmecc_version); + atmel_pmecc_core_init(mtd); return 0; @@ -1296,9 +1378,7 @@ int spl_nand_erase_one(int block, int page) hwctrl(&mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE | NAND_CTRL_CHANGE); #endif - hwctrl(&mtd, NAND_CMD_ERASE2, NAND_CTRL_CLE | NAND_CTRL_CHANGE); - udelay(2000); while (!this->dev_ready(&mtd)) ; @@ -1374,6 +1454,9 @@ int board_nand_init(struct nand_chip *nand) nand->dev_ready = at91_nand_wait_ready; #endif nand->chip_delay = 20; +#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT + nand->bbt_options |= NAND_BBT_USE_FLASH; +#endif #ifdef CONFIG_ATMEL_NAND_HWECC #ifdef CONFIG_ATMEL_NAND_HW_PMECC @@ -1440,6 +1523,9 @@ int atmel_nand_chip_init(int devnum, ulong base_addr) nand->dev_ready = at91_nand_ready; #endif nand->chip_delay = 75; +#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT + nand->bbt_options |= NAND_BBT_USE_FLASH; +#endif ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL); if (ret)