mirror of
https://github.com/Stichting-MINIX-Research-Foundation/u-boot.git
synced 2025-09-09 03:58:18 -04:00
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
* 'master' of git://git.denx.de/u-boot-nand-flash: cmd_nand.c: Fix 'nand dump' after latest MTD resync mtd/nand:Fix wrong usage of is_blank() in fsl_ifc_run_command mtd/nand: Fix IFC driver to support 2K NAND page nand: reinstate lazy bad block scanning Revert "nand: make 1-bit software ECC configurable"
This commit is contained in:
commit
e91004201c
@ -48,7 +48,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
|
|||||||
|
|
||||||
last = off;
|
last = off;
|
||||||
|
|
||||||
datbuf = malloc(nand->writesize + nand->oobsize);
|
datbuf = malloc(nand->writesize);
|
||||||
oobbuf = malloc(nand->oobsize);
|
oobbuf = malloc(nand->oobsize);
|
||||||
if (!datbuf || !oobbuf) {
|
if (!datbuf || !oobbuf) {
|
||||||
puts("No memory for page buffer\n");
|
puts("No memory for page buffer\n");
|
||||||
@ -59,7 +59,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
|
|||||||
struct mtd_oob_ops ops;
|
struct mtd_oob_ops ops;
|
||||||
memset(&ops, 0, sizeof(ops));
|
memset(&ops, 0, sizeof(ops));
|
||||||
ops.datbuf = datbuf;
|
ops.datbuf = datbuf;
|
||||||
ops.oobbuf = oobbuf; /* must exist, but oob data will be appended to ops.datbuf */
|
ops.oobbuf = oobbuf;
|
||||||
ops.len = nand->writesize;
|
ops.len = nand->writesize;
|
||||||
ops.ooblen = nand->oobsize;
|
ops.ooblen = nand->oobsize;
|
||||||
ops.mode = MTD_OOB_RAW;
|
ops.mode = MTD_OOB_RAW;
|
||||||
@ -85,6 +85,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
|
|||||||
}
|
}
|
||||||
puts("OOB:\n");
|
puts("OOB:\n");
|
||||||
i = nand->oobsize >> 3;
|
i = nand->oobsize >> 3;
|
||||||
|
p = oobbuf;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
||||||
|
@ -39,7 +39,7 @@ COBJS-y += nand_bbt.o
|
|||||||
COBJS-y += nand_ids.o
|
COBJS-y += nand_ids.o
|
||||||
COBJS-y += nand_util.o
|
COBJS-y += nand_util.o
|
||||||
endif
|
endif
|
||||||
COBJS-$(CONFIG_MTD_ECC_SOFT) += nand_ecc.o
|
COBJS-y += nand_ecc.o
|
||||||
COBJS-y += nand_base.o
|
COBJS-y += nand_base.o
|
||||||
COBJS-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
|
COBJS-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Integrated Flash Controller NAND Machine Driver
|
/* Integrated Flash Controller NAND Machine Driver
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 Freescale Semiconductor, Inc
|
* Copyright (c) 2012 Freescale Semiconductor, Inc
|
||||||
*
|
*
|
||||||
* Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
|
* Authors: Dipen Dudhat <Dipen.Dudhat@freescale.com>
|
||||||
*
|
*
|
||||||
@ -221,24 +221,11 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
|
|||||||
u32 *eccstat, unsigned int bufnum)
|
u32 *eccstat, unsigned int bufnum)
|
||||||
{
|
{
|
||||||
u32 reg = eccstat[bufnum / 4];
|
u32 reg = eccstat[bufnum / 4];
|
||||||
int errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
|
int errors;
|
||||||
|
|
||||||
if (errors == 15) { /* uncorrectable */
|
errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
|
||||||
/* Blank pages fail hw ECC checks */
|
|
||||||
if (is_blank(mtd, ctrl, bufnum))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/*
|
return errors;
|
||||||
* We disable ECCER reporting in hardware due to
|
|
||||||
* erratum IFC-A002770 -- so report it now if we
|
|
||||||
* see an uncorrectable error in ECCSTAT.
|
|
||||||
*/
|
|
||||||
ctrl->status |= IFC_NAND_EVTER_STAT_ECCER;
|
|
||||||
} else if (errors > 0) {
|
|
||||||
mtd->ecc_stats.corrected += errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -279,16 +266,33 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
|
|||||||
printf("%s: Write Protect Error\n", __func__);
|
printf("%s: Write Protect Error\n", __func__);
|
||||||
|
|
||||||
if (ctrl->eccread) {
|
if (ctrl->eccread) {
|
||||||
int bufperpage = mtd->writesize / 512;
|
int errors;
|
||||||
int bufnum = (ctrl->page & priv->bufnum_mask) * bufperpage;
|
int bufnum = ctrl->page & priv->bufnum_mask;
|
||||||
int bufnum_end = bufnum + bufperpage - 1;
|
int sector = bufnum * chip->ecc.steps;
|
||||||
|
int sector_end = sector + chip->ecc.steps - 1;
|
||||||
|
|
||||||
for (i = bufnum / 4; i <= bufnum_end / 4; i++)
|
for (i = sector / 4; i <= sector_end / 4; i++)
|
||||||
eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
|
eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
|
||||||
|
|
||||||
for (i = bufnum; i <= bufnum_end; i++) {
|
for (i = sector; i <= sector_end; i++) {
|
||||||
if (check_read_ecc(mtd, ctrl, eccstat, i))
|
errors = check_read_ecc(mtd, ctrl, eccstat, i);
|
||||||
|
|
||||||
|
if (errors == 15) {
|
||||||
|
/*
|
||||||
|
* Uncorrectable error.
|
||||||
|
* OK only if the whole page is blank.
|
||||||
|
*
|
||||||
|
* We disable ECCER reporting due to erratum
|
||||||
|
* IFC-A002770 -- so report it now if we
|
||||||
|
* see an uncorrectable error in ECCSTAT.
|
||||||
|
*/
|
||||||
|
if (!is_blank(mtd, ctrl, bufnum))
|
||||||
|
ctrl->status |=
|
||||||
|
IFC_NAND_EVTER_STAT_ECCER;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mtd->ecc_stats.corrected += errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl->eccread = 0;
|
ctrl->eccread = 0;
|
||||||
@ -448,21 +452,19 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
|||||||
out_be32(&ifc->ifc_nand.nand_fir1,
|
out_be32(&ifc->ifc_nand.nand_fir1,
|
||||||
(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
|
(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
|
||||||
|
|
||||||
if (column >= mtd->writesize) {
|
if (column >= mtd->writesize)
|
||||||
/* OOB area --> READOOB */
|
nand_fcr0 |=
|
||||||
column -= mtd->writesize;
|
NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
|
||||||
nand_fcr0 |= NAND_CMD_READOOB <<
|
else
|
||||||
IFC_NAND_FCR0_CMD0_SHIFT;
|
nand_fcr0 |=
|
||||||
ctrl->oob = 1;
|
NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
|
||||||
} else if (column < 256) {
|
|
||||||
/* First 256 bytes --> READ0 */
|
|
||||||
nand_fcr0 |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
|
|
||||||
} else {
|
|
||||||
/* Second 256 bytes --> READ1 */
|
|
||||||
nand_fcr0 |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (column >= mtd->writesize) {
|
||||||
|
/* OOB area --> READOOB */
|
||||||
|
column -= mtd->writesize;
|
||||||
|
ctrl->oob = 1;
|
||||||
|
}
|
||||||
out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
|
out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
|
||||||
set_addr(mtd, column, page_addr, ctrl->oob);
|
set_addr(mtd, column, page_addr, ctrl->oob);
|
||||||
return;
|
return;
|
||||||
@ -471,7 +473,8 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
|||||||
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
|
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
|
||||||
case NAND_CMD_PAGEPROG:
|
case NAND_CMD_PAGEPROG:
|
||||||
if (ctrl->oob)
|
if (ctrl->oob)
|
||||||
out_be32(&ifc->ifc_nand.nand_fbcr, ctrl->index);
|
out_be32(&ifc->ifc_nand.nand_fbcr,
|
||||||
|
ctrl->index - ctrl->column);
|
||||||
else
|
else
|
||||||
out_be32(&ifc->ifc_nand.nand_fbcr, 0);
|
out_be32(&ifc->ifc_nand.nand_fbcr, 0);
|
||||||
|
|
||||||
|
@ -479,6 +479,11 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|||||||
{
|
{
|
||||||
struct nand_chip *chip = mtd->priv;
|
struct nand_chip *chip = mtd->priv;
|
||||||
|
|
||||||
|
if (!(chip->options & NAND_BBT_SCANNED)) {
|
||||||
|
chip->options |= NAND_BBT_SCANNED;
|
||||||
|
chip->scan_bbt(mtd);
|
||||||
|
}
|
||||||
|
|
||||||
if (!chip->bbt)
|
if (!chip->bbt)
|
||||||
return chip->block_bad(mtd, ofs, getchip);
|
return chip->block_bad(mtd, ofs, getchip);
|
||||||
|
|
||||||
@ -3028,10 +3033,6 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||||||
chip->ecc.mode = NAND_ECC_SOFT;
|
chip->ecc.mode = NAND_ECC_SOFT;
|
||||||
|
|
||||||
case NAND_ECC_SOFT:
|
case NAND_ECC_SOFT:
|
||||||
if (!mtd_nand_has_ecc_soft()) {
|
|
||||||
printk(KERN_WARNING "CONFIG_MTD_ECC_SOFT not enabled\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
chip->ecc.calculate = nand_calculate_ecc;
|
chip->ecc.calculate = nand_calculate_ecc;
|
||||||
chip->ecc.correct = nand_correct_data;
|
chip->ecc.correct = nand_correct_data;
|
||||||
chip->ecc.read_page = nand_read_page_swecc;
|
chip->ecc.read_page = nand_read_page_swecc;
|
||||||
@ -3170,10 +3171,9 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||||||
|
|
||||||
/* Check, if we should skip the bad block table scan */
|
/* Check, if we should skip the bad block table scan */
|
||||||
if (chip->options & NAND_SKIP_BBTSCAN)
|
if (chip->options & NAND_SKIP_BBTSCAN)
|
||||||
return 0;
|
chip->options |= NAND_BBT_SCANNED;
|
||||||
|
|
||||||
/* Build bad block table */
|
return 0;
|
||||||
return chip->scan_bbt(mtd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,6 +232,8 @@ typedef enum {
|
|||||||
#define NAND_CREATE_EMPTY_BBT 0x01000000
|
#define NAND_CREATE_EMPTY_BBT 0x01000000
|
||||||
|
|
||||||
/* Options set by nand scan */
|
/* Options set by nand scan */
|
||||||
|
/* bbt has already been read */
|
||||||
|
#define NAND_BBT_SCANNED 0x40000000
|
||||||
/* Nand scan has allocated controller struct */
|
/* Nand scan has allocated controller struct */
|
||||||
#define NAND_CONTROLLER_ALLOC 0x80000000
|
#define NAND_CONTROLLER_ALLOC 0x80000000
|
||||||
|
|
||||||
|
@ -15,10 +15,6 @@
|
|||||||
|
|
||||||
struct mtd_info;
|
struct mtd_info;
|
||||||
|
|
||||||
#if defined(CONFIG_MTD_ECC_SOFT)
|
|
||||||
|
|
||||||
static inline int mtd_nand_has_ecc_soft(void) { return 1; }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate 3 byte ECC code for 256 byte block
|
* Calculate 3 byte ECC code for 256 byte block
|
||||||
*/
|
*/
|
||||||
@ -29,25 +25,4 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
|
|||||||
*/
|
*/
|
||||||
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
|
int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static inline int mtd_nand_has_ecc_soft(void) { return 0; }
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
nand_correct_data(struct mtd_info *mtd,
|
|
||||||
u_char *dat,
|
|
||||||
u_char *read_ecc,
|
|
||||||
u_char *calc_ecc)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __MTD_NAND_ECC_H__ */
|
#endif /* __MTD_NAND_ECC_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user