aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/nand_base.c14
-rw-r--r--drivers/mtd/nand/nand_bbt.c127
2 files changed, 86 insertions, 55 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index bd697909db53..c2901bd126f9 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2963,6 +2963,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2963 *maf_id == NAND_MFR_MICRON)) 2963 *maf_id == NAND_MFR_MICRON))
2964 chip->options |= NAND_BBT_SCAN2NDPAGE; 2964 chip->options |= NAND_BBT_SCAN2NDPAGE;
2965 2965
2966 /*
2967 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
2968 */
2969 if (!(busw & NAND_BUSWIDTH_16) &&
2970 *maf_id == NAND_MFR_STMICRO &&
2971 mtd->writesize == 2048) {
2972 chip->options |= NAND_BBT_SCANBYTE1AND6;
2973 chip->badblockpos = 0;
2974 }
2966 2975
2967 /* Check for AND chips with 4 page planes */ 2976 /* Check for AND chips with 4 page planes */
2968 if (chip->options & NAND_4PAGE_ARRAY) 2977 if (chip->options & NAND_4PAGE_ARRAY)
@@ -3322,6 +3331,11 @@ void nand_release(struct mtd_info *mtd)
3322 kfree(chip->bbt); 3331 kfree(chip->bbt);
3323 if (!(chip->options & NAND_OWN_BUFFERS)) 3332 if (!(chip->options & NAND_OWN_BUFFERS))
3324 kfree(chip->buffers); 3333 kfree(chip->buffers);
3334
3335 /* Free bad block descriptor memory */
3336 if (chip->badblock_pattern && chip->badblock_pattern->options
3337 & NAND_BBT_DYNAMICSTRUCT)
3338 kfree(chip->badblock_pattern);
3325} 3339}
3326 3340
3327EXPORT_SYMBOL_GPL(nand_lock); 3341EXPORT_SYMBOL_GPL(nand_lock);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ec1700eaf198..469de17107e5 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -93,6 +93,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
93 return -1; 93 return -1;
94 } 94 }
95 95
96 /* Check both positions 1 and 6 for pattern? */
97 if (td->options & NAND_BBT_SCANBYTE1AND6) {
98 if (td->options & NAND_BBT_SCANEMPTY) {
99 p += td->len;
100 end += NAND_SMALL_BADBLOCK_POS - td->offs;
101 /* Check region between positions 1 and 6 */
102 for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
103 i++) {
104 if (*p++ != 0xff)
105 return -1;
106 }
107 }
108 else {
109 p += NAND_SMALL_BADBLOCK_POS - td->offs;
110 }
111 /* Compare the pattern */
112 for (i = 0; i < td->len; i++) {
113 if (p[i] != td->pattern[i])
114 return -1;
115 }
116 }
117
96 if (td->options & NAND_BBT_SCANEMPTY) { 118 if (td->options & NAND_BBT_SCANEMPTY) {
97 p += td->len; 119 p += td->len;
98 end += td->len; 120 end += td->len;
@@ -124,6 +146,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
124 if (p[td->offs + i] != td->pattern[i]) 146 if (p[td->offs + i] != td->pattern[i])
125 return -1; 147 return -1;
126 } 148 }
149 /* Need to check location 1 AND 6? */
150 if (td->options & NAND_BBT_SCANBYTE1AND6) {
151 for (i = 0; i < td->len; i++) {
152 if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
153 return -1;
154 }
155 }
127 return 0; 156 return 0;
128} 157}
129 158
@@ -397,12 +426,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
397 426
398 if (bd->options & NAND_BBT_SCANALLPAGES) 427 if (bd->options & NAND_BBT_SCANALLPAGES)
399 len = 1 << (this->bbt_erase_shift - this->page_shift); 428 len = 1 << (this->bbt_erase_shift - this->page_shift);
400 else { 429 else if (bd->options & NAND_BBT_SCAN2NDPAGE)
401 if (bd->options & NAND_BBT_SCAN2NDPAGE) 430 len = 2;
402 len = 2; 431 else
403 else 432 len = 1;
404 len = 1;
405 }
406 433
407 if (!(bd->options & NAND_BBT_SCANEMPTY)) { 434 if (!(bd->options & NAND_BBT_SCANEMPTY)) {
408 /* We need only read few bytes from the OOB area */ 435 /* We need only read few bytes from the OOB area */
@@ -1092,41 +1119,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
1092 * while scanning a device for factory marked good / bad blocks. */ 1119 * while scanning a device for factory marked good / bad blocks. */
1093static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 1120static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
1094 1121
1095static struct nand_bbt_descr smallpage_memorybased = {
1096 .options = 0,
1097 .offs = NAND_SMALL_BADBLOCK_POS,
1098 .len = 1,
1099 .pattern = scan_ff_pattern
1100};
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
1109static struct nand_bbt_descr largepage_memorybased = {
1110 .options = 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,
1119 .len = 2,
1120 .pattern = scan_ff_pattern
1121};
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
1130static struct nand_bbt_descr smallpage_flashbased = { 1122static struct nand_bbt_descr smallpage_flashbased = {
1131 .options = NAND_BBT_SCAN2NDPAGE, 1123 .options = NAND_BBT_SCAN2NDPAGE,
1132 .offs = NAND_SMALL_BADBLOCK_POS, 1124 .offs = NAND_SMALL_BADBLOCK_POS,
@@ -1175,6 +1167,43 @@ static struct nand_bbt_descr bbt_mirror_descr = {
1175 .pattern = mirror_pattern 1167 .pattern = mirror_pattern
1176}; 1168};
1177 1169
1170#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
1171 NAND_BBT_SCANBYTE1AND6)
1172/**
1173 * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
1174 * @this: NAND chip to create descriptor for
1175 *
1176 * This function allocates and initializes a nand_bbt_descr for BBM detection
1177 * based on the properties of "this". The new descriptor is stored in
1178 * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
1179 * passed to this function.
1180 *
1181 * TODO: Handle other flags, replace other static structs
1182 * (e.g. handle NAND_BBT_FLASH for flash-based BBT,
1183 * replace smallpage_flashbased)
1184 *
1185 */
1186static int nand_create_default_bbt_descr(struct nand_chip *this)
1187{
1188 struct nand_bbt_descr *bd;
1189 if (this->badblock_pattern) {
1190 printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
1191 return -EINVAL;
1192 }
1193 bd = kzalloc(sizeof(*bd), GFP_KERNEL);
1194 if (!bd) {
1195 printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
1196 return -ENOMEM;
1197 }
1198 bd->options = this->options & BBT_SCAN_OPTIONS;
1199 bd->offs = this->badblockpos;
1200 bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
1201 bd->pattern = scan_ff_pattern;
1202 bd->options |= NAND_BBT_DYNAMICSTRUCT;
1203 this->badblock_pattern = bd;
1204 return 0;
1205}
1206
1178/** 1207/**
1179 * nand_default_bbt - [NAND Interface] Select a default bad block table for the device 1208 * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
1180 * @mtd: MTD device structure 1209 * @mtd: MTD device structure
@@ -1217,20 +1246,8 @@ int nand_default_bbt(struct mtd_info *mtd)
1217 } else { 1246 } else {
1218 this->bbt_td = NULL; 1247 this->bbt_td = NULL;
1219 this->bbt_md = NULL; 1248 this->bbt_md = NULL;
1220 if (!this->badblock_pattern) { 1249 if (!this->badblock_pattern)
1221 if (this->options & NAND_BBT_SCANLASTPAGE) 1250 nand_create_default_bbt_descr(this);
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;
1233 }
1234 } 1251 }
1235 return nand_scan_bbt(mtd, this->badblock_pattern); 1252 return nand_scan_bbt(mtd, this->badblock_pattern);
1236} 1253}