summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/atmel_nand.c58
1 files changed, 16 insertions, 42 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 438a967bd6..db13f5b7e4 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -107,8 +107,6 @@ struct atmel_nand_host {
void *ecc_code;
};
-static struct nand_ecclayout atmel_pmecc_oobinfo;
-
/*
* Enable NAND.
*/
@@ -201,22 +199,6 @@ static int pmecc_get_ecc_bytes(int cap, int sector_size)
return (m * cap + 7) / 8;
}
-static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
- int oobsize, int ecc_len)
-{
- int i;
-
- layout->eccbytes = ecc_len;
-
- /* ECC will occupy the last ecc_len bytes continuously */
- for (i = 0; i < ecc_len; i++)
- layout->eccpos[i] = oobsize - ecc_len + i;
-
- layout->oobfree[0].offset = 2;
- layout->oobfree[0].length =
- oobsize - ecc_len - layout->oobfree[0].offset;
-}
-
static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
{
int table_size;
@@ -574,7 +556,7 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
- int i, err_nbr, ret, bitflips = 0;
+ int i, err_nbr, ret, max_bitflips = 0;
uint8_t *buf_pos;
uint8_t *ecc_code = host->ecc_code;
@@ -583,7 +565,7 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf)
if (ret)
return ret;
- for (i = 0; i < nand_chip->ecc.bytes; i++)
+ for (i = 0; i < nand_chip->ecc.bytes * nand_chip->ecc.steps; i++)
if (ecc_code[i] != 0xff)
goto normal_check;
/* Erased page, return OK */
@@ -608,13 +590,13 @@ normal_check:
pmecc_correct_data(mtd, buf_pos, ecc_code, i,
host->pmecc_bytes_per_sector, err_nbr);
mtd->ecc_stats.corrected += err_nbr;
- bitflips += err_nbr;
+ max_bitflips = max(max_bitflips, err_nbr);
}
}
pmecc_stat >>= 1;
}
- return bitflips;
+ return max_bitflips;
}
static int atmel_nand_pmecc_read_page(struct nand_chip *chip, uint8_t *buf,
@@ -622,7 +604,6 @@ static int atmel_nand_pmecc_read_page(struct nand_chip *chip, uint8_t *buf,
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct atmel_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
uint32_t stat;
int ret;
@@ -636,7 +617,7 @@ static int atmel_nand_pmecc_read_page(struct nand_chip *chip, uint8_t *buf,
nand_read_page_op(chip, page, 0, NULL, 0);
- chip->legacy.read_buf(chip, buf, eccsize);
+ chip->legacy.read_buf(chip, buf, mtd->writesize);
chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
ret = wait_on_timeout(PMECC_MAX_TIMEOUT_MS,
@@ -711,7 +692,7 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct atmel_nand_host *host = nand_chip->priv;
uint32_t val = 0;
- struct nand_ecclayout *ecc_layout;
+ int eccbytes;
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
@@ -758,11 +739,10 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
| PMECC_CFG_AUTO_DISABLE);
pmecc_writel(host->ecc, CFG, val);
- ecc_layout = host->ecclayout;
+ eccbytes = host->pmecc_sector_number * host->pmecc_bytes_per_sector;
pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1);
- pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]);
- pmecc_writel(host->ecc, EADDR,
- ecc_layout->eccpos[ecc_layout->eccbytes - 1]);
+ pmecc_writel(host->ecc, SADDR, mtd->oobsize - eccbytes);
+ pmecc_writel(host->ecc, EADDR, mtd->oobsize - 1);
/* See datasheet about PMECC Clock Control Register */
pmecc_writel(host->ecc, CLK, 2);
pmecc_writel(host->ecc, IDR, 0xff);
@@ -914,9 +894,6 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
host->board->pmecc_lookup_table_offset = 0;
}
- /* ECC is calculated for the whole page (1 step) */
- nand_chip->ecc.size = mtd->writesize;
-
/* set ECC page size and oob layout */
switch (mtd->writesize) {
case 2048:
@@ -932,18 +909,16 @@ static int __init atmel_pmecc_nand_init_params(struct device_d *dev,
host->pmecc_index_of = host->pmecc_rom_base +
host->board->pmecc_lookup_table_offset;
- nand_chip->ecc.steps = 1;
- nand_chip->ecc.bytes = host->pmecc_bytes_per_sector *
- host->pmecc_sector_number;
+ nand_chip->ecc.steps = host->pmecc_sector_number;
+ nand_chip->ecc.bytes = host->pmecc_bytes_per_sector;
+ nand_chip->ecc.size = sector_size;
+ nand_chip->ecc.strength = cap;
+
if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
dev_err(host->dev, "No room for ECC bytes\n");
return -EINVAL;
}
- pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
- mtd->oobsize,
- nand_chip->ecc.bytes);
- host->ecclayout = &atmel_pmecc_oobinfo;
- mtd_set_ecclayout(mtd, host->ecclayout);
+ mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
break;
case 512:
case 1024:
@@ -1016,7 +991,6 @@ static int atmel_nand_read_page(struct nand_chip *chip, uint8_t *buf,
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct atmel_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
uint32_t *eccpos = host->ecclayout->eccpos;
uint8_t *p = buf;
@@ -1027,7 +1001,7 @@ static int atmel_nand_read_page(struct nand_chip *chip, uint8_t *buf,
nand_read_page_op(chip, page, 0, NULL, 0);
/* read the page */
- chip->legacy.read_buf(chip, p, eccsize);
+ chip->legacy.read_buf(chip, p, mtd->writesize);
/* move to ECC position if needed */
if (eccpos[0] != 0) {