diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 79 |
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 | ||
3311 | EXPORT_SYMBOL_GPL(nand_lock); | 3354 | EXPORT_SYMBOL_GPL(nand_lock); |