aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/tango_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/tango_nand.c')
-rw-r--r--drivers/mtd/nand/tango_nand.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/tango_nand.c
index 05b6e1065203..49b286c6c10f 100644
--- a/drivers/mtd/nand/tango_nand.c
+++ b/drivers/mtd/nand/tango_nand.c
@@ -55,10 +55,10 @@
55 * byte 1 for other packets in the page (PKT_N, for N > 0) 55 * byte 1 for other packets in the page (PKT_N, for N > 0)
56 * ERR_COUNT_PKT_N is the max error count over all but the first packet. 56 * ERR_COUNT_PKT_N is the max error count over all but the first packet.
57 */ 57 */
58#define DECODE_OK_PKT_0(v) ((v) & BIT(7))
59#define DECODE_OK_PKT_N(v) ((v) & BIT(15))
60#define ERR_COUNT_PKT_0(v) (((v) >> 0) & 0x3f) 58#define ERR_COUNT_PKT_0(v) (((v) >> 0) & 0x3f)
61#define ERR_COUNT_PKT_N(v) (((v) >> 8) & 0x3f) 59#define ERR_COUNT_PKT_N(v) (((v) >> 8) & 0x3f)
60#define DECODE_FAIL_PKT_0(v) (((v) & BIT(7)) == 0)
61#define DECODE_FAIL_PKT_N(v) (((v) & BIT(15)) == 0)
62 62
63/* Offsets relative to pbus_base */ 63/* Offsets relative to pbus_base */
64#define PBUS_CS_CTRL 0x83c 64#define PBUS_CS_CTRL 0x83c
@@ -193,6 +193,8 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
193 chip->ecc.strength); 193 chip->ecc.strength);
194 if (res < 0) 194 if (res < 0)
195 mtd->ecc_stats.failed++; 195 mtd->ecc_stats.failed++;
196 else
197 mtd->ecc_stats.corrected += res;
196 198
197 bitflips = max(res, bitflips); 199 bitflips = max(res, bitflips);
198 buf += pkt_size; 200 buf += pkt_size;
@@ -202,9 +204,11 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
202 return bitflips; 204 return bitflips;
203} 205}
204 206
205static int decode_error_report(struct tango_nfc *nfc) 207static int decode_error_report(struct nand_chip *chip)
206{ 208{
207 u32 status, res; 209 u32 status, res;
210 struct mtd_info *mtd = nand_to_mtd(chip);
211 struct tango_nfc *nfc = to_tango_nfc(chip->controller);
208 212
209 status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS); 213 status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS);
210 if (status & PAGE_IS_EMPTY) 214 if (status & PAGE_IS_EMPTY)
@@ -212,10 +216,14 @@ static int decode_error_report(struct tango_nfc *nfc)
212 216
213 res = readl_relaxed(nfc->mem_base + ERROR_REPORT); 217 res = readl_relaxed(nfc->mem_base + ERROR_REPORT);
214 218
215 if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res)) 219 if (DECODE_FAIL_PKT_0(res) || DECODE_FAIL_PKT_N(res))
216 return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res)); 220 return -EBADMSG;
221
222 /* ERR_COUNT_PKT_N is max, not sum, but that's all we have */
223 mtd->ecc_stats.corrected +=
224 ERR_COUNT_PKT_0(res) + ERR_COUNT_PKT_N(res);
217 225
218 return -EBADMSG; 226 return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
219} 227}
220 228
221static void tango_dma_callback(void *arg) 229static void tango_dma_callback(void *arg)
@@ -282,7 +290,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
282 if (err) 290 if (err)
283 return err; 291 return err;
284 292
285 res = decode_error_report(nfc); 293 res = decode_error_report(chip);
286 if (res < 0) { 294 if (res < 0) {
287 chip->ecc.read_oob_raw(mtd, chip, page); 295 chip->ecc.read_oob_raw(mtd, chip, page);
288 res = check_erased_page(chip, buf); 296 res = check_erased_page(chip, buf);
@@ -663,6 +671,7 @@ static const struct of_device_id tango_nand_ids[] = {
663 { .compatible = "sigma,smp8758-nand" }, 671 { .compatible = "sigma,smp8758-nand" },
664 { /* sentinel */ } 672 { /* sentinel */ }
665}; 673};
674MODULE_DEVICE_TABLE(of, tango_nand_ids);
666 675
667static struct platform_driver tango_nand_driver = { 676static struct platform_driver tango_nand_driver = {
668 .probe = tango_nand_probe, 677 .probe = tango_nand_probe,