diff options
Diffstat (limited to 'drivers/mtd/nand/tango_nand.c')
-rw-r--r-- | drivers/mtd/nand/tango_nand.c | 23 |
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 | ||
205 | static int decode_error_report(struct tango_nfc *nfc) | 207 | static 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 | ||
221 | static void tango_dma_callback(void *arg) | 229 | static 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 | }; |
674 | MODULE_DEVICE_TABLE(of, tango_nand_ids); | ||
666 | 675 | ||
667 | static struct platform_driver tango_nand_driver = { | 676 | static struct platform_driver tango_nand_driver = { |
668 | .probe = tango_nand_probe, | 677 | .probe = tango_nand_probe, |