Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310208
b: refs/heads/master
c: 3f91e94
h: refs/heads/master
v: v3
  • Loading branch information
Mike Dunn authored and David Woodhouse committed May 14, 2012
1 parent d3a6959 commit cb67fad
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d062d4ede877fcd2ecc4c6262abad09a6f32950a
refs/heads/master: 3f91e94f7f511de74c0d2abe08672ccdbdd1961c
9 changes: 6 additions & 3 deletions trunk/drivers/mtd/nand/atmel_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
uint8_t *oob = chip->oob_poi;
uint8_t *ecc_pos;
int stat;
unsigned int max_bitflips = 0;

/*
* Errata: ALE is incorrectly wired up to the ECC controller
Expand Down Expand Up @@ -371,18 +372,20 @@ static int atmel_nand_read_page(struct mtd_info *mtd,
/* check if there's an error */
stat = chip->ecc.correct(mtd, p, oob, NULL);

if (stat < 0)
if (stat < 0) {
mtd->ecc_stats.failed++;
else
} else {
mtd->ecc_stats.corrected += stat;
max_bitflips = max_t(unsigned int, max_bitflips, stat);
}

/* get back to oob start (end of page) */
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);

/* read the oob */
chip->read_buf(mtd, oob, mtd->oobsize);

return 0;
return max_bitflips;
}

/*
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/mtd/nand/bcm_umi_bch.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
uint8_t eccCalc[NAND_ECC_NUM_BYTES];
int sectorOobSize = mtd->oobsize / eccsteps;
int stat;
unsigned int max_bitflips = 0;

for (sectorIdx = 0; sectorIdx < eccsteps;
sectorIdx++, datap += eccsize) {
Expand Down Expand Up @@ -177,9 +178,10 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
}
#endif
mtd->ecc_stats.corrected += stat;
max_bitflips = max_t(unsigned int, max_bitflips, stat);
}
}
return 0;
return max_bitflips;
}

/****************************************************************************
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/mtd/nand/cafe_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
{
struct cafe_priv *cafe = mtd->priv;
unsigned int max_bitflips = 0;

cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
cafe_readl(cafe, NAND_ECC_RESULT),
Expand Down Expand Up @@ -449,10 +450,11 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
} else {
dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n);
mtd->ecc_stats.corrected += n;
max_bitflips = max_t(unsigned int, max_bitflips, n);
}
}

return 0;
return max_bitflips;
}

static struct nand_ecclayout cafe_oobinfo_2048 = {
Expand Down
10 changes: 7 additions & 3 deletions trunk/drivers/mtd/nand/denali.c
Original file line number Diff line number Diff line change
Expand Up @@ -924,9 +924,10 @@ bool is_erased(uint8_t *buf, int len)
#define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)

static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
uint32_t irq_status)
uint32_t irq_status, unsigned int *max_bitflips)
{
bool check_erased_page = false;
unsigned int bitflips = 0;

if (irq_status & INTR_STATUS__ECC_ERR) {
/* read the ECC errors. we'll ignore them for now */
Expand Down Expand Up @@ -965,6 +966,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
/* correct the ECC error */
buf[offset] ^= err_correction_value;
denali->mtd.ecc_stats.corrected++;
bitflips++;
}
} else {
/* if the error is not correctable, need to
Expand All @@ -984,6 +986,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
clear_interrupts(denali);
denali_set_intr_modes(denali, true);
}
*max_bitflips = bitflips;
return check_erased_page;
}

Expand Down Expand Up @@ -1121,6 +1124,7 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
{
unsigned int max_bitflips;
struct denali_nand_info *denali = mtd_to_denali(mtd);

dma_addr_t addr = denali->buf.dma_buf;
Expand Down Expand Up @@ -1153,7 +1157,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,

memcpy(buf, denali->buf.buf, mtd->writesize);

check_erased_page = handle_ecc(denali, buf, irq_status);
check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips);
denali_enable_dma(denali, false);

if (check_erased_page) {
Expand All @@ -1167,7 +1171,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
denali->mtd.ecc_stats.failed++;
}
}
return 0;
return max_bitflips;
}

static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/mtd/nand/docg4.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
struct docg4_priv *doc = nand->priv;
void __iomem *docptr = doc->virtadr;
uint16_t status, edc_err, *buf16;
int bits_corrected = 0;

dev_dbg(doc->dev, "%s: page %08x\n", __func__, page);

Expand Down Expand Up @@ -772,7 +773,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,

/* If bitflips are reported, attempt to correct with ecc */
if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) {
int bits_corrected = correct_data(mtd, buf, page);
bits_corrected = correct_data(mtd, buf, page);
if (bits_corrected == -EBADMSG)
mtd->ecc_stats.failed++;
else
Expand All @@ -781,7 +782,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
}

writew(0, docptr + DOC_DATAEND);
return 0;
return bits_corrected;
}


Expand Down
21 changes: 14 additions & 7 deletions trunk/drivers/mtd/nand/fsl_elbc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ struct fsl_elbc_fcm_ctrl {
unsigned int use_mdr; /* Non zero if the MDR is to be set */
unsigned int oob; /* Non zero if operating on OOB data */
unsigned int counter; /* counter for the initializations */
unsigned int max_bitflips; /* Saved during READ0 cmd */
};

/* These map to the positions used by the FCM hardware ECC generator */
Expand Down Expand Up @@ -253,6 +254,8 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
if (chip->ecc.mode != NAND_ECC_HW)
return 0;

elbc_fcm_ctrl->max_bitflips = 0;

if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) {
uint32_t lteccr = in_be32(&lbc->lteccr);
/*
Expand All @@ -262,11 +265,16 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
* bits 28-31 are uncorrectable errors, marked elsewhere.
* for small page nand only 1 bit is used.
* if the ELBC doesn't have the lteccr register it reads 0
* FIXME: 4 bits can be corrected on NANDs with 2k pages, so
* count the number of sub-pages with bitflips and update
* ecc_stats.corrected accordingly.
*/
if (lteccr & 0x000F000F)
out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */
if (lteccr & 0x000F0000)
if (lteccr & 0x000F0000) {
mtd->ecc_stats.corrected++;
elbc_fcm_ctrl->max_bitflips = 1;
}
}

return 0;
Expand Down Expand Up @@ -743,13 +751,17 @@ static int fsl_elbc_read_page(struct mtd_info *mtd,
uint8_t *buf,
int page)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;

fsl_elbc_read_buf(mtd, buf, mtd->writesize);
fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);

if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
mtd->ecc_stats.failed++;

return 0;
return elbc_fcm_ctrl->max_bitflips;
}

/* ECC will be calculated automatically, and errors will be detected in
Expand Down Expand Up @@ -814,11 +826,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
chip->ecc.size = 512;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
/*
* FIXME: can hardware ecc correct 4 bitflips if page size is
* 2k? Then does hardware report number of corrections for this
* case? If so, ecc_stats reporting needs to be fixed as well.
*/
} else {
/* otherwise fall back to default software ECC */
chip->ecc.mode = NAND_ECC_SOFT;
Expand Down
9 changes: 8 additions & 1 deletion trunk/drivers/mtd/nand/fsl_ifc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct fsl_ifc_nand_ctrl {
unsigned int oob; /* Non zero if operating on OOB data */
unsigned int eccread; /* Non zero for a full-page ECC read */
unsigned int counter; /* counter for the initializations */
unsigned int max_bitflips; /* Saved during READ0 cmd */
};

static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl;
Expand Down Expand Up @@ -262,6 +263,8 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER)
dev_err(priv->dev, "NAND Flash Write Protect Error\n");

nctrl->max_bitflips = 0;

if (nctrl->eccread) {
int errors;
int bufnum = nctrl->page & priv->bufnum_mask;
Expand Down Expand Up @@ -290,6 +293,9 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
}

mtd->ecc_stats.corrected += errors;
nctrl->max_bitflips = max_t(unsigned int,
nctrl->max_bitflips,
errors);
}

nctrl->eccread = 0;
Expand Down Expand Up @@ -698,6 +704,7 @@ static int fsl_ifc_read_page(struct mtd_info *mtd,
{
struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;

fsl_ifc_read_buf(mtd, buf, mtd->writesize);
fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
Expand All @@ -708,7 +715,7 @@ static int fsl_ifc_read_page(struct mtd_info *mtd,
if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
mtd->ecc_stats.failed++;

return 0;
return nctrl->max_bitflips;
}

/* ECC will be calculated automatically, and errors will be detected in
Expand Down
9 changes: 6 additions & 3 deletions trunk/drivers/mtd/nand/fsmc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
*/
uint16_t ecc_oob[7];
uint8_t *oob = (uint8_t *)&ecc_oob[0];
unsigned int max_bitflips = 0;

for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
Expand Down Expand Up @@ -748,13 +749,15 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
chip->ecc.calculate(mtd, p, &ecc_calc[i]);

stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
if (stat < 0)
if (stat < 0) {
mtd->ecc_stats.failed++;
else
} else {
mtd->ecc_stats.corrected += stat;
max_bitflips = max_t(unsigned int, max_bitflips, stat);
}
}

return 0;
return max_bitflips;
}

/*
Expand Down
Loading

0 comments on commit cb67fad

Please sign in to comment.