/* 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>
*
u32 *eccstat, unsigned int bufnum)
{
u32 reg = eccstat[bufnum / 4];
- int errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
+ int errors;
- if (errors == 15) { /* uncorrectable */
- /* Blank pages fail hw ECC checks */
- if (is_blank(mtd, ctrl, bufnum))
- return 1;
+ errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
- /*
- * 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;
+ return errors;
}
/*
printf("%s: Write Protect Error\n", __func__);
if (ctrl->eccread) {
- int bufperpage = mtd->writesize / 512;
- int bufnum = (ctrl->page & priv->bufnum_mask) * bufperpage;
- int bufnum_end = bufnum + bufperpage - 1;
+ int errors;
+ int bufnum = ctrl->page & priv->bufnum_mask;
+ 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]);
- for (i = bufnum; i <= bufnum_end; i++) {
- if (check_read_ecc(mtd, ctrl, eccstat, i))
+ for (i = sector; i <= sector_end; 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;
+ }
+
+ mtd->ecc_stats.corrected += errors;
}
ctrl->eccread = 0;
/* READID must read all possible bytes while CEB is active */
case NAND_CMD_READID:
+ case NAND_CMD_PARAM: {
+ int timing = IFC_FIR_OP_RB;
+ if (command == NAND_CMD_PARAM)
+ timing = IFC_FIR_OP_RBCD;
+
out_be32(&ifc->ifc_nand.nand_fir0,
(IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
(IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+ (timing << IFC_NAND_FIR0_OP2_SHIFT));
out_be32(&ifc->ifc_nand.nand_fcr0,
- NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
- /* 4 bytes for manuf, device and exts */
- out_be32(&ifc->ifc_nand.nand_fbcr, 4);
- ctrl->read_bytes = 4;
+ command << IFC_NAND_FCR0_CMD0_SHIFT);
+ out_be32(&ifc->ifc_nand.row3, column);
+
+ /*
+ * although currently it's 8 bytes for READID, we always read
+ * the maximum 256 bytes(for PARAM)
+ */
+ out_be32(&ifc->ifc_nand.nand_fbcr, 256);
+ ctrl->read_bytes = 256;
set_addr(mtd, 0, 0, 0);
fsl_ifc_run_command(mtd);
return;
+ }
/* ERASE1 stores the block and page address */
case NAND_CMD_ERASE1:
if (priv->bank >= MAX_BANKS) {
printf("%s: address did not match any "
"chip selects\n", __func__);
+ kfree(priv);
return -ENODEV;
}