aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/nand_base.c24
-rw-r--r--drivers/mtd/nand/nand_bbt.c45
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)
1093static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 1093static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
1094 1094
1095static struct nand_bbt_descr smallpage_memorybased = { 1095static 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
1102static 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
1102static struct nand_bbt_descr largepage_memorybased = { 1109static 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
1116static 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
1123static struct nand_bbt_descr lastpage_memorybased = {
1124 .options = NAND_BBT_SCANLASTPAGE,
1125 .offs = 0,
1126 .len = 1,
1127 .pattern = scan_ff_pattern
1128};
1129
1109static struct nand_bbt_descr smallpage_flashbased = { 1130static 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
1116static struct nand_bbt_descr largepage_flashbased = { 1137static 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);