diff options
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 24 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 45 |
2 files changed, 58 insertions, 11 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e6cf9aefef13..bd697909db53 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -2920,9 +2920,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; | 2920 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; |
2921 | 2921 | ||
2922 | /* Set the bad block position */ | 2922 | /* Set the bad block position */ |
2923 | chip->badblockpos = mtd->writesize > 512 ? | 2923 | if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO || |
2924 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; | 2924 | (*maf_id == NAND_MFR_SAMSUNG && |
2925 | chip->badblockbits = 8; | 2925 | mtd->writesize == 512) || |
2926 | *maf_id == NAND_MFR_AMD)) | ||
2927 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; | ||
2928 | else | ||
2929 | chip->badblockpos = NAND_LARGE_BADBLOCK_POS; | ||
2930 | |||
2926 | 2931 | ||
2927 | /* Get chip options, preserve non chip based options */ | 2932 | /* Get chip options, preserve non chip based options */ |
2928 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | 2933 | chip->options &= ~NAND_CHIPOPTIONS_MSK; |
@@ -2941,12 +2946,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2941 | 2946 | ||
2942 | /* | 2947 | /* |
2943 | * Bad block marker is stored in the last page of each block | 2948 | * Bad block marker is stored in the last page of each block |
2944 | * on Samsung and Hynix MLC devices | 2949 | * on Samsung and Hynix MLC devices; stored in first two pages |
2950 | * of each block on Micron devices with 2KiB pages and on | ||
2951 | * SLC Samsung, Hynix, and AMD/Spansion. All others scan only | ||
2952 | * the first page. | ||
2945 | */ | 2953 | */ |
2946 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 2954 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2947 | (*maf_id == NAND_MFR_SAMSUNG || | 2955 | (*maf_id == NAND_MFR_SAMSUNG || |
2948 | *maf_id == NAND_MFR_HYNIX)) | 2956 | *maf_id == NAND_MFR_HYNIX)) |
2949 | chip->options |= NAND_BBT_SCANLASTPAGE; | 2957 | chip->options |= NAND_BBT_SCANLASTPAGE; |
2958 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | ||
2959 | (*maf_id == NAND_MFR_SAMSUNG || | ||
2960 | *maf_id == NAND_MFR_HYNIX || | ||
2961 | *maf_id == NAND_MFR_AMD)) || | ||
2962 | (mtd->writesize == 2048 && | ||
2963 | *maf_id == NAND_MFR_MICRON)) | ||
2964 | chip->options |= NAND_BBT_SCAN2NDPAGE; | ||
2965 | |||
2950 | 2966 | ||
2951 | /* Check for AND chips with 4 page planes */ | 2967 | /* Check for AND chips with 4 page planes */ |
2952 | if (chip->options & NAND_4PAGE_ARRAY) | 2968 | if (chip->options & NAND_4PAGE_ARRAY) |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 71d83be24ff6..ec1700eaf198 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -1093,29 +1093,50 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1093 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 1093 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
1094 | 1094 | ||
1095 | static struct nand_bbt_descr smallpage_memorybased = { | 1095 | static struct nand_bbt_descr smallpage_memorybased = { |
1096 | .options = NAND_BBT_SCAN2NDPAGE, | 1096 | .options = 0, |
1097 | .offs = 5, | 1097 | .offs = NAND_SMALL_BADBLOCK_POS, |
1098 | .len = 1, | 1098 | .len = 1, |
1099 | .pattern = scan_ff_pattern | 1099 | .pattern = scan_ff_pattern |
1100 | }; | 1100 | }; |
1101 | 1101 | ||
1102 | static struct nand_bbt_descr smallpage_scan2nd_memorybased = { | ||
1103 | .options = NAND_BBT_SCAN2NDPAGE, | ||
1104 | .offs = NAND_SMALL_BADBLOCK_POS, | ||
1105 | .len = 2, | ||
1106 | .pattern = scan_ff_pattern | ||
1107 | }; | ||
1108 | |||
1102 | static struct nand_bbt_descr largepage_memorybased = { | 1109 | static struct nand_bbt_descr largepage_memorybased = { |
1103 | .options = 0, | 1110 | .options = 0, |
1104 | .offs = 0, | 1111 | .offs = NAND_LARGE_BADBLOCK_POS, |
1112 | .len = 1, | ||
1113 | .pattern = scan_ff_pattern | ||
1114 | }; | ||
1115 | |||
1116 | static struct nand_bbt_descr largepage_scan2nd_memorybased = { | ||
1117 | .options = NAND_BBT_SCAN2NDPAGE, | ||
1118 | .offs = NAND_LARGE_BADBLOCK_POS, | ||
1105 | .len = 2, | 1119 | .len = 2, |
1106 | .pattern = scan_ff_pattern | 1120 | .pattern = scan_ff_pattern |
1107 | }; | 1121 | }; |
1108 | 1122 | ||
1123 | static struct nand_bbt_descr lastpage_memorybased = { | ||
1124 | .options = NAND_BBT_SCANLASTPAGE, | ||
1125 | .offs = 0, | ||
1126 | .len = 1, | ||
1127 | .pattern = scan_ff_pattern | ||
1128 | }; | ||
1129 | |||
1109 | static struct nand_bbt_descr smallpage_flashbased = { | 1130 | static struct nand_bbt_descr smallpage_flashbased = { |
1110 | .options = NAND_BBT_SCAN2NDPAGE, | 1131 | .options = NAND_BBT_SCAN2NDPAGE, |
1111 | .offs = 5, | 1132 | .offs = NAND_SMALL_BADBLOCK_POS, |
1112 | .len = 1, | 1133 | .len = 1, |
1113 | .pattern = scan_ff_pattern | 1134 | .pattern = scan_ff_pattern |
1114 | }; | 1135 | }; |
1115 | 1136 | ||
1116 | static struct nand_bbt_descr largepage_flashbased = { | 1137 | static struct nand_bbt_descr largepage_flashbased = { |
1117 | .options = NAND_BBT_SCAN2NDPAGE, | 1138 | .options = NAND_BBT_SCAN2NDPAGE, |
1118 | .offs = 0, | 1139 | .offs = NAND_LARGE_BADBLOCK_POS, |
1119 | .len = 2, | 1140 | .len = 2, |
1120 | .pattern = scan_ff_pattern | 1141 | .pattern = scan_ff_pattern |
1121 | }; | 1142 | }; |
@@ -1197,8 +1218,18 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1197 | this->bbt_td = NULL; | 1218 | this->bbt_td = NULL; |
1198 | this->bbt_md = NULL; | 1219 | this->bbt_md = NULL; |
1199 | if (!this->badblock_pattern) { | 1220 | if (!this->badblock_pattern) { |
1200 | this->badblock_pattern = (mtd->writesize > 512) ? | 1221 | if (this->options & NAND_BBT_SCANLASTPAGE) |
1201 | &largepage_memorybased : &smallpage_memorybased; | 1222 | this->badblock_pattern = &lastpage_memorybased; |
1223 | else if (this->options & NAND_BBT_SCAN2NDPAGE) | ||
1224 | this->badblock_pattern = this->badblockpos == | ||
1225 | NAND_SMALL_BADBLOCK_POS ? | ||
1226 | &smallpage_scan2nd_memorybased : | ||
1227 | &largepage_scan2nd_memorybased; | ||
1228 | else | ||
1229 | this->badblock_pattern = this->badblockpos == | ||
1230 | NAND_SMALL_BADBLOCK_POS ? | ||
1231 | &smallpage_memorybased : | ||
1232 | &largepage_memorybased; | ||
1202 | } | 1233 | } |
1203 | } | 1234 | } |
1204 | return nand_scan_bbt(mtd, this->badblock_pattern); | 1235 | return nand_scan_bbt(mtd, this->badblock_pattern); |