diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-19 15:47:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-19 15:47:41 -0500 |
commit | ca2a88f56aa385890c7fd4ce9d2722b0848ca990 (patch) | |
tree | 935fd9cec938677d6529db203f24d803ed5f0b19 /drivers/mtd/nand/atmel_nand.c | |
parent | 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 (diff) | |
parent | d4d4f1bf6a343b25220fdcdf559fd593dd3e25a7 (diff) |
Merge tag 'for-linus-20121219' of git://git.infradead.org/linux-mtd
Pull MTD updates from David Woodhouse:
- Various cleanups especially in NAND tests
- Add support for NAND flash on BCMA bus
- DT support for sh_flctl and denali NAND drivers
- Kill obsolete/superceded drivers (fortunet, nomadik_nand)
- Fix JFFS2 locking bug in ENOMEM failure path
- New SPI flash chips, as usual
- Support writing in 'reliable mode' for DiskOnChip G4
- Debugfs support in nandsim
* tag 'for-linus-20121219' of git://git.infradead.org/linux-mtd: (96 commits)
mtd: nand: typo in nand_id_has_period() comments
mtd: nand/gpio: use io{read,write}*_rep accessors
mtd: block2mtd: throttle writes by calling balance_dirty_pages_ratelimited.
mtd: nand: gpmi: reset BCH earlier, too, to avoid NAND startup problems
mtd: nand/docg4: fix and improve read of factory bbt
mtd: nand/docg4: reserve bb marker area in ecclayout
mtd: nand/docg4: add support for writing in reliable mode
mtd: mxc_nand: reorder part_probes to let cmdline override other sources
mtd: mxc_nand: fix unbalanced clk_disable() in error path
mtd: nandsim: Introduce debugfs infrastructure
mtd: physmap_of: error checking to prevent a NULL pointer dereference
mtg: docg3: potential divide by zero in doc_write_oob()
mtd: bcm47xxnflash: writing support
mtd: tests/read: initialize buffer for whole next page
mtd: at91: atmel_nand: return bit flips for the PMECC read_page()
mtd: fix recovery after failed write-buffer operation in cfi_cmdset_0002.c
mtd: nand: onfi need to be probed in 8 bits mode
mtd: nand: add NAND_BUSWIDTH_AUTO to autodetect bus width
mtd: nand: print flash size during detection
mted: nand_wait_ready timeout fix
...
Diffstat (limited to 'drivers/mtd/nand/atmel_nand.c')
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 92623ac2015a..90bdca61c797 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -331,13 +331,13 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
331 | * 12-bits 20-bytes 21-bytes | 331 | * 12-bits 20-bytes 21-bytes |
332 | * 24-bits 39-bytes 42-bytes | 332 | * 24-bits 39-bytes 42-bytes |
333 | */ | 333 | */ |
334 | static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size) | 334 | static int pmecc_get_ecc_bytes(int cap, int sector_size) |
335 | { | 335 | { |
336 | int m = 12 + sector_size / 512; | 336 | int m = 12 + sector_size / 512; |
337 | return (m * cap + 7) / 8; | 337 | return (m * cap + 7) / 8; |
338 | } | 338 | } |
339 | 339 | ||
340 | static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, | 340 | static void pmecc_config_ecc_layout(struct nand_ecclayout *layout, |
341 | int oobsize, int ecc_len) | 341 | int oobsize, int ecc_len) |
342 | { | 342 | { |
343 | int i; | 343 | int i; |
@@ -353,7 +353,7 @@ static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, | |||
353 | oobsize - ecc_len - layout->oobfree[0].offset; | 353 | oobsize - ecc_len - layout->oobfree[0].offset; |
354 | } | 354 | } |
355 | 355 | ||
356 | static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) | 356 | static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) |
357 | { | 357 | { |
358 | int table_size; | 358 | int table_size; |
359 | 359 | ||
@@ -375,7 +375,7 @@ static void pmecc_data_free(struct atmel_nand_host *host) | |||
375 | kfree(host->pmecc_delta); | 375 | kfree(host->pmecc_delta); |
376 | } | 376 | } |
377 | 377 | ||
378 | static int __devinit pmecc_data_alloc(struct atmel_nand_host *host) | 378 | static int pmecc_data_alloc(struct atmel_nand_host *host) |
379 | { | 379 | { |
380 | const int cap = host->pmecc_corr_cap; | 380 | const int cap = host->pmecc_corr_cap; |
381 | 381 | ||
@@ -724,6 +724,7 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | |||
724 | struct atmel_nand_host *host = nand_chip->priv; | 724 | struct atmel_nand_host *host = nand_chip->priv; |
725 | int i, err_nbr, eccbytes; | 725 | int i, err_nbr, eccbytes; |
726 | uint8_t *buf_pos; | 726 | uint8_t *buf_pos; |
727 | int total_err = 0; | ||
727 | 728 | ||
728 | eccbytes = nand_chip->ecc.bytes; | 729 | eccbytes = nand_chip->ecc.bytes; |
729 | for (i = 0; i < eccbytes; i++) | 730 | for (i = 0; i < eccbytes; i++) |
@@ -751,12 +752,13 @@ normal_check: | |||
751 | pmecc_correct_data(mtd, buf_pos, ecc, i, | 752 | pmecc_correct_data(mtd, buf_pos, ecc, i, |
752 | host->pmecc_bytes_per_sector, err_nbr); | 753 | host->pmecc_bytes_per_sector, err_nbr); |
753 | mtd->ecc_stats.corrected += err_nbr; | 754 | mtd->ecc_stats.corrected += err_nbr; |
755 | total_err += err_nbr; | ||
754 | } | 756 | } |
755 | } | 757 | } |
756 | pmecc_stat >>= 1; | 758 | pmecc_stat >>= 1; |
757 | } | 759 | } |
758 | 760 | ||
759 | return 0; | 761 | return total_err; |
760 | } | 762 | } |
761 | 763 | ||
762 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | 764 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, |
@@ -768,6 +770,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
768 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 770 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
769 | uint32_t stat; | 771 | uint32_t stat; |
770 | unsigned long end_time; | 772 | unsigned long end_time; |
773 | int bitflips = 0; | ||
771 | 774 | ||
772 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | 775 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); |
773 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 776 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); |
@@ -790,11 +793,14 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
790 | } | 793 | } |
791 | 794 | ||
792 | stat = pmecc_readl_relaxed(host->ecc, ISR); | 795 | stat = pmecc_readl_relaxed(host->ecc, ISR); |
793 | if (stat != 0) | 796 | if (stat != 0) { |
794 | if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0) | 797 | bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]); |
795 | return -EIO; | 798 | if (bitflips < 0) |
799 | /* uncorrectable errors */ | ||
800 | return 0; | ||
801 | } | ||
796 | 802 | ||
797 | return 0; | 803 | return bitflips; |
798 | } | 804 | } |
799 | 805 | ||
800 | static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | 806 | static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, |
@@ -1206,7 +1212,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
1206 | } | 1212 | } |
1207 | 1213 | ||
1208 | #if defined(CONFIG_OF) | 1214 | #if defined(CONFIG_OF) |
1209 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | 1215 | static int atmel_of_init_port(struct atmel_nand_host *host, |
1210 | struct device_node *np) | 1216 | struct device_node *np) |
1211 | { | 1217 | { |
1212 | u32 val, table_offset; | 1218 | u32 val, table_offset; |
@@ -1293,7 +1299,7 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | |||
1293 | return 0; | 1299 | return 0; |
1294 | } | 1300 | } |
1295 | #else | 1301 | #else |
1296 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | 1302 | static int atmel_of_init_port(struct atmel_nand_host *host, |
1297 | struct device_node *np) | 1303 | struct device_node *np) |
1298 | { | 1304 | { |
1299 | return -EINVAL; | 1305 | return -EINVAL; |