aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 4a7b86423ee9..16a1714df008 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -42,7 +42,6 @@
42#include <linux/mtd/mtd.h> 42#include <linux/mtd/mtd.h>
43#include <linux/mtd/nand.h> 43#include <linux/mtd/nand.h>
44#include <linux/mtd/nand_ecc.h> 44#include <linux/mtd/nand_ecc.h>
45#include <linux/mtd/compatmac.h>
46#include <linux/interrupt.h> 45#include <linux/interrupt.h>
47#include <linux/bitops.h> 46#include <linux/bitops.h>
48#include <linux/leds.h> 47#include <linux/leds.h>
@@ -347,7 +346,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
347 struct nand_chip *chip = mtd->priv; 346 struct nand_chip *chip = mtd->priv;
348 u16 bad; 347 u16 bad;
349 348
350 if (chip->options & NAND_BB_LAST_PAGE) 349 if (chip->options & NAND_BBT_SCANLASTPAGE)
351 ofs += mtd->erasesize - mtd->writesize; 350 ofs += mtd->erasesize - mtd->writesize;
352 351
353 page = (int)(ofs >> chip->page_shift) & chip->pagemask; 352 page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@@ -397,9 +396,9 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
397{ 396{
398 struct nand_chip *chip = mtd->priv; 397 struct nand_chip *chip = mtd->priv;
399 uint8_t buf[2] = { 0, 0 }; 398 uint8_t buf[2] = { 0, 0 };
400 int block, ret; 399 int block, ret, i = 0;
401 400
402 if (chip->options & NAND_BB_LAST_PAGE) 401 if (chip->options & NAND_BBT_SCANLASTPAGE)
403 ofs += mtd->erasesize - mtd->writesize; 402 ofs += mtd->erasesize - mtd->writesize;
404 403
405 /* Get block number */ 404 /* Get block number */
@@ -411,17 +410,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
411 if (chip->options & NAND_USE_FLASH_BBT) 410 if (chip->options & NAND_USE_FLASH_BBT)
412 ret = nand_update_bbt(mtd, ofs); 411 ret = nand_update_bbt(mtd, ofs);
413 else { 412 else {
414 /* We write two bytes, so we dont have to mess with 16 bit
415 * access
416 */
417 nand_get_device(chip, mtd, FL_WRITING); 413 nand_get_device(chip, mtd, FL_WRITING);
418 ofs += mtd->oobsize;
419 chip->ops.len = chip->ops.ooblen = 2;
420 chip->ops.datbuf = NULL;
421 chip->ops.oobbuf = buf;
422 chip->ops.ooboffs = chip->badblockpos & ~0x01;
423 414
424 ret = nand_do_write_oob(mtd, ofs, &chip->ops); 415 /* Write to first two pages and to byte 1 and 6 if necessary.
416 * If we write to more than one location, the first error
417 * encountered quits the procedure. We write two bytes per
418 * location, so we dont have to mess with 16 bit access.
419 */
420 do {
421 chip->ops.len = chip->ops.ooblen = 2;
422 chip->ops.datbuf = NULL;
423 chip->ops.oobbuf = buf;
424 chip->ops.ooboffs = chip->badblockpos & ~0x01;
425
426 ret = nand_do_write_oob(mtd, ofs, &chip->ops);
427
428 if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) {
429 chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS
430 & ~0x01;
431 ret = nand_do_write_oob(mtd, ofs, &chip->ops);
432 }
433 i++;
434 ofs += mtd->writesize;
435 } while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) &&
436 i < 2);
437
425 nand_release_device(mtd); 438 nand_release_device(mtd);
426 } 439 }
427 if (!ret) 440 if (!ret)
@@ -2920,9 +2933,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2920 chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; 2933 chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
2921 2934
2922 /* Set the bad block position */ 2935 /* Set the bad block position */
2923 chip->badblockpos = mtd->writesize > 512 ? 2936 if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO ||
2924 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; 2937 (*maf_id == NAND_MFR_SAMSUNG &&
2925 chip->badblockbits = 8; 2938 mtd->writesize == 512) ||
2939 *maf_id == NAND_MFR_AMD))
2940 chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
2941 else
2942 chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
2943
2926 2944
2927 /* Get chip options, preserve non chip based options */ 2945 /* Get chip options, preserve non chip based options */
2928 chip->options &= ~NAND_CHIPOPTIONS_MSK; 2946 chip->options &= ~NAND_CHIPOPTIONS_MSK;
@@ -2941,12 +2959,32 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2941 2959
2942 /* 2960 /*
2943 * Bad block marker is stored in the last page of each block 2961 * Bad block marker is stored in the last page of each block
2944 * on Samsung and Hynix MLC devices 2962 * on Samsung and Hynix MLC devices; stored in first two pages
2963 * of each block on Micron devices with 2KiB pages and on
2964 * SLC Samsung, Hynix, and AMD/Spansion. All others scan only
2965 * the first page.
2945 */ 2966 */
2946 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && 2967 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2947 (*maf_id == NAND_MFR_SAMSUNG || 2968 (*maf_id == NAND_MFR_SAMSUNG ||
2948 *maf_id == NAND_MFR_HYNIX)) 2969 *maf_id == NAND_MFR_HYNIX))
2949 chip->options |= NAND_BB_LAST_PAGE; 2970 chip->options |= NAND_BBT_SCANLASTPAGE;
2971 else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2972 (*maf_id == NAND_MFR_SAMSUNG ||
2973 *maf_id == NAND_MFR_HYNIX ||
2974 *maf_id == NAND_MFR_AMD)) ||
2975 (mtd->writesize == 2048 &&
2976 *maf_id == NAND_MFR_MICRON))
2977 chip->options |= NAND_BBT_SCAN2NDPAGE;
2978
2979 /*
2980 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
2981 */
2982 if (!(busw & NAND_BUSWIDTH_16) &&
2983 *maf_id == NAND_MFR_STMICRO &&
2984 mtd->writesize == 2048) {
2985 chip->options |= NAND_BBT_SCANBYTE1AND6;
2986 chip->badblockpos = 0;
2987 }
2950 2988
2951 /* Check for AND chips with 4 page planes */ 2989 /* Check for AND chips with 4 page planes */
2952 if (chip->options & NAND_4PAGE_ARRAY) 2990 if (chip->options & NAND_4PAGE_ARRAY)
@@ -3306,6 +3344,11 @@ void nand_release(struct mtd_info *mtd)
3306 kfree(chip->bbt); 3344 kfree(chip->bbt);
3307 if (!(chip->options & NAND_OWN_BUFFERS)) 3345 if (!(chip->options & NAND_OWN_BUFFERS))
3308 kfree(chip->buffers); 3346 kfree(chip->buffers);
3347
3348 /* Free bad block descriptor memory */
3349 if (chip->badblock_pattern && chip->badblock_pattern->options
3350 & NAND_BBT_DYNAMICSTRUCT)
3351 kfree(chip->badblock_pattern);
3309} 3352}
3310 3353
3311EXPORT_SYMBOL_GPL(nand_lock); 3354EXPORT_SYMBOL_GPL(nand_lock);