diff options
Diffstat (limited to 'drivers/mtd/nand/nand_bbt.c')
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 248 |
1 files changed, 124 insertions, 124 deletions
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 7535ef53685e..ca286999fe08 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -3,10 +3,10 @@ | |||
3 | * | 3 | * |
4 | * Overview: | 4 | * Overview: |
5 | * Bad block table support for the NAND driver | 5 | * Bad block table support for the NAND driver |
6 | * | 6 | * |
7 | * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) | 7 | * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) |
8 | * | 8 | * |
9 | * $Id: nand_bbt.c,v 1.35 2005/07/15 13:53:47 gleixner Exp $ | 9 | * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -14,23 +14,23 @@ | |||
14 | * | 14 | * |
15 | * Description: | 15 | * Description: |
16 | * | 16 | * |
17 | * When nand_scan_bbt is called, then it tries to find the bad block table | 17 | * When nand_scan_bbt is called, then it tries to find the bad block table |
18 | * depending on the options in the bbt descriptor(s). If a bbt is found | 18 | * depending on the options in the bbt descriptor(s). If a bbt is found |
19 | * then the contents are read and the memory based bbt is created. If a | 19 | * then the contents are read and the memory based bbt is created. If a |
20 | * mirrored bbt is selected then the mirror is searched too and the | 20 | * mirrored bbt is selected then the mirror is searched too and the |
21 | * versions are compared. If the mirror has a greater version number | 21 | * versions are compared. If the mirror has a greater version number |
22 | * than the mirror bbt is used to build the memory based bbt. | 22 | * than the mirror bbt is used to build the memory based bbt. |
23 | * If the tables are not versioned, then we "or" the bad block information. | 23 | * If the tables are not versioned, then we "or" the bad block information. |
24 | * If one of the bbt's is out of date or does not exist it is (re)created. | 24 | * If one of the bbt's is out of date or does not exist it is (re)created. |
25 | * If no bbt exists at all then the device is scanned for factory marked | 25 | * If no bbt exists at all then the device is scanned for factory marked |
26 | * good / bad blocks and the bad block tables are created. | 26 | * good / bad blocks and the bad block tables are created. |
27 | * | 27 | * |
28 | * For manufacturer created bbts like the one found on M-SYS DOC devices | 28 | * For manufacturer created bbts like the one found on M-SYS DOC devices |
29 | * the bbt is searched and read but never created | 29 | * the bbt is searched and read but never created |
30 | * | 30 | * |
31 | * The autogenerated bad block table is located in the last good blocks | 31 | * The autogenerated bad block table is located in the last good blocks |
32 | * of the device. The table is mirrored, so it can be updated eventually. | 32 | * of the device. The table is mirrored, so it can be updated eventually. |
33 | * The table is marked in the oob area with an ident pattern and a version | 33 | * The table is marked in the oob area with an ident pattern and a version |
34 | * number which indicates which of both tables is more up to date. | 34 | * number which indicates which of both tables is more up to date. |
35 | * | 35 | * |
36 | * The table uses 2 bits per block | 36 | * The table uses 2 bits per block |
@@ -43,13 +43,13 @@ | |||
43 | * 01b: block is marked bad due to wear | 43 | * 01b: block is marked bad due to wear |
44 | * 10b: block is reserved (to protect the bbt area) | 44 | * 10b: block is reserved (to protect the bbt area) |
45 | * 11b: block is factory marked bad | 45 | * 11b: block is factory marked bad |
46 | * | 46 | * |
47 | * Multichip devices like DOC store the bad block info per floor. | 47 | * Multichip devices like DOC store the bad block info per floor. |
48 | * | 48 | * |
49 | * Following assumptions are made: | 49 | * Following assumptions are made: |
50 | * - bbts start at a page boundary, if autolocated on a block boundary | 50 | * - bbts start at a page boundary, if autolocated on a block boundary |
51 | * - the space neccecary for a bbt in FLASH does not exceed a block boundary | 51 | * - the space neccecary for a bbt in FLASH does not exceed a block boundary |
52 | * | 52 | * |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
@@ -62,7 +62,7 @@ | |||
62 | #include <linux/delay.h> | 62 | #include <linux/delay.h> |
63 | 63 | ||
64 | 64 | ||
65 | /** | 65 | /** |
66 | * check_pattern - [GENERIC] check if a pattern is in the buffer | 66 | * check_pattern - [GENERIC] check if a pattern is in the buffer |
67 | * @buf: the buffer to search | 67 | * @buf: the buffer to search |
68 | * @len: the length of buffer to search | 68 | * @len: the length of buffer to search |
@@ -86,9 +86,9 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des | |||
86 | if (p[i] != 0xff) | 86 | if (p[i] != 0xff) |
87 | return -1; | 87 | return -1; |
88 | } | 88 | } |
89 | } | 89 | } |
90 | p += end; | 90 | p += end; |
91 | 91 | ||
92 | /* Compare the pattern */ | 92 | /* Compare the pattern */ |
93 | for (i = 0; i < td->len; i++) { | 93 | for (i = 0; i < td->len; i++) { |
94 | if (p[i] != td->pattern[i]) | 94 | if (p[i] != td->pattern[i]) |
@@ -106,13 +106,13 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | /** | 109 | /** |
110 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | 110 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer |
111 | * @buf: the buffer to search | 111 | * @buf: the buffer to search |
112 | * @td: search pattern descriptor | 112 | * @td: search pattern descriptor |
113 | * | 113 | * |
114 | * Check for a pattern at the given place. Used to search bad block | 114 | * Check for a pattern at the given place. Used to search bad block |
115 | * tables and good / bad block identifiers. Same as check_pattern, but | 115 | * tables and good / bad block identifiers. Same as check_pattern, but |
116 | * no optional empty check | 116 | * no optional empty check |
117 | * | 117 | * |
118 | */ | 118 | */ |
@@ -142,7 +142,7 @@ static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td) | |||
142 | * Read the bad block table starting from page. | 142 | * Read the bad block table starting from page. |
143 | * | 143 | * |
144 | */ | 144 | */ |
145 | static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | 145 | static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, |
146 | int bits, int offs, int reserved_block_code) | 146 | int bits, int offs, int reserved_block_code) |
147 | { | 147 | { |
148 | int res, i, j, act = 0; | 148 | int res, i, j, act = 0; |
@@ -153,7 +153,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
153 | 153 | ||
154 | totlen = (num * bits) >> 3; | 154 | totlen = (num * bits) >> 3; |
155 | from = ((loff_t)page) << this->page_shift; | 155 | from = ((loff_t)page) << this->page_shift; |
156 | 156 | ||
157 | while (totlen) { | 157 | while (totlen) { |
158 | len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); | 158 | len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); |
159 | res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); | 159 | res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); |
@@ -163,7 +163,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
163 | return res; | 163 | return res; |
164 | } | 164 | } |
165 | printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); | 165 | printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); |
166 | } | 166 | } |
167 | 167 | ||
168 | /* Analyse data */ | 168 | /* Analyse data */ |
169 | for (i = 0; i < len; i++) { | 169 | for (i = 0; i < len; i++) { |
@@ -183,12 +183,12 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
183 | * message to MTD_DEBUG_LEVEL0 */ | 183 | * message to MTD_DEBUG_LEVEL0 */ |
184 | printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", | 184 | printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", |
185 | ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | 185 | ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); |
186 | /* Factory marked bad or worn out ? */ | 186 | /* Factory marked bad or worn out ? */ |
187 | if (tmp == 0) | 187 | if (tmp == 0) |
188 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); | 188 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); |
189 | else | 189 | else |
190 | this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); | 190 | this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); |
191 | } | 191 | } |
192 | } | 192 | } |
193 | totlen -= len; | 193 | totlen -= len; |
194 | from += len; | 194 | from += len; |
@@ -200,7 +200,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
200 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page | 200 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page |
201 | * @mtd: MTD device structure | 201 | * @mtd: MTD device structure |
202 | * @buf: temporary buffer | 202 | * @buf: temporary buffer |
203 | * @td: descriptor for the bad block table | 203 | * @td: descriptor for the bad block table |
204 | * @chip: read the table for a specific chip, -1 read all chips. | 204 | * @chip: read the table for a specific chip, -1 read all chips. |
205 | * Applies only if NAND_BBT_PERCHIP option is set | 205 | * Applies only if NAND_BBT_PERCHIP option is set |
206 | * | 206 | * |
@@ -235,7 +235,7 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
235 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page | 235 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page |
236 | * @mtd: MTD device structure | 236 | * @mtd: MTD device structure |
237 | * @buf: temporary buffer | 237 | * @buf: temporary buffer |
238 | * @td: descriptor for the bad block table | 238 | * @td: descriptor for the bad block table |
239 | * @md: descriptor for the bad block table mirror | 239 | * @md: descriptor for the bad block table mirror |
240 | * | 240 | * |
241 | * Read the bad block table(s) for all chips starting at a given page | 241 | * Read the bad block table(s) for all chips starting at a given page |
@@ -247,16 +247,16 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de | |||
247 | { | 247 | { |
248 | struct nand_chip *this = mtd->priv; | 248 | struct nand_chip *this = mtd->priv; |
249 | 249 | ||
250 | /* Read the primary version, if available */ | 250 | /* Read the primary version, if available */ |
251 | if (td->options & NAND_BBT_VERSION) { | 251 | if (td->options & NAND_BBT_VERSION) { |
252 | nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); | 252 | nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); |
253 | td->version[0] = buf[mtd->oobblock + td->veroffs]; | 253 | td->version[0] = buf[mtd->oobblock + td->veroffs]; |
254 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); | 254 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); |
255 | } | 255 | } |
256 | 256 | ||
257 | /* Read the mirror version, if available */ | 257 | /* Read the mirror version, if available */ |
258 | if (md && (md->options & NAND_BBT_VERSION)) { | 258 | if (md && (md->options & NAND_BBT_VERSION)) { |
259 | nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); | 259 | nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); |
260 | md->version[0] = buf[mtd->oobblock + md->veroffs]; | 260 | md->version[0] = buf[mtd->oobblock + md->veroffs]; |
261 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); | 261 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); |
262 | } | 262 | } |
@@ -290,7 +290,7 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
290 | else { | 290 | else { |
291 | if (bd->options & NAND_BBT_SCAN2NDPAGE) | 291 | if (bd->options & NAND_BBT_SCAN2NDPAGE) |
292 | len = 2; | 292 | len = 2; |
293 | else | 293 | else |
294 | len = 1; | 294 | len = 1; |
295 | } | 295 | } |
296 | 296 | ||
@@ -322,10 +322,10 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
322 | numblocks += startblock; | 322 | numblocks += startblock; |
323 | from = startblock << (this->bbt_erase_shift - 1); | 323 | from = startblock << (this->bbt_erase_shift - 1); |
324 | } | 324 | } |
325 | 325 | ||
326 | for (i = startblock; i < numblocks;) { | 326 | for (i = startblock; i < numblocks;) { |
327 | int ret; | 327 | int ret; |
328 | 328 | ||
329 | if (bd->options & NAND_BBT_SCANEMPTY) | 329 | if (bd->options & NAND_BBT_SCANEMPTY) |
330 | if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen))) | 330 | if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen))) |
331 | return ret; | 331 | return ret; |
@@ -333,8 +333,8 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
333 | for (j = 0; j < len; j++) { | 333 | for (j = 0; j < len; j++) { |
334 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { | 334 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { |
335 | size_t retlen; | 335 | size_t retlen; |
336 | 336 | ||
337 | /* Read the full oob until read_oob is fixed to | 337 | /* Read the full oob until read_oob is fixed to |
338 | * handle single byte reads for 16 bit buswidth */ | 338 | * handle single byte reads for 16 bit buswidth */ |
339 | ret = mtd->read_oob(mtd, from + j * mtd->oobblock, | 339 | ret = mtd->read_oob(mtd, from + j * mtd->oobblock, |
340 | mtd->oobsize, &retlen, buf); | 340 | mtd->oobsize, &retlen, buf); |
@@ -343,14 +343,14 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
343 | 343 | ||
344 | if (check_short_pattern (buf, bd)) { | 344 | if (check_short_pattern (buf, bd)) { |
345 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 345 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); |
346 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | 346 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", |
347 | i >> 1, (unsigned int) from); | 347 | i >> 1, (unsigned int) from); |
348 | break; | 348 | break; |
349 | } | 349 | } |
350 | } else { | 350 | } else { |
351 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { | 351 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { |
352 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 352 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); |
353 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | 353 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", |
354 | i >> 1, (unsigned int) from); | 354 | i >> 1, (unsigned int) from); |
355 | break; | 355 | break; |
356 | } | 356 | } |
@@ -369,15 +369,15 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
369 | * @td: descriptor for the bad block table | 369 | * @td: descriptor for the bad block table |
370 | * | 370 | * |
371 | * Read the bad block table by searching for a given ident pattern. | 371 | * Read the bad block table by searching for a given ident pattern. |
372 | * Search is preformed either from the beginning up or from the end of | 372 | * Search is preformed either from the beginning up or from the end of |
373 | * the device downwards. The search starts always at the start of a | 373 | * the device downwards. The search starts always at the start of a |
374 | * block. | 374 | * block. |
375 | * If the option NAND_BBT_PERCHIP is given, each chip is searched | 375 | * If the option NAND_BBT_PERCHIP is given, each chip is searched |
376 | * for a bbt, which contains the bad block information of this chip. | 376 | * for a bbt, which contains the bad block information of this chip. |
377 | * This is neccecary to provide support for certain DOC devices. | 377 | * This is neccecary to provide support for certain DOC devices. |
378 | * | 378 | * |
379 | * The bbt ident pattern resides in the oob area of the first page | 379 | * The bbt ident pattern resides in the oob area of the first page |
380 | * in a block. | 380 | * in a block. |
381 | */ | 381 | */ |
382 | static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) | 382 | static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) |
383 | { | 383 | { |
@@ -392,10 +392,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
392 | startblock = (mtd->size >> this->bbt_erase_shift) -1; | 392 | startblock = (mtd->size >> this->bbt_erase_shift) -1; |
393 | dir = -1; | 393 | dir = -1; |
394 | } else { | 394 | } else { |
395 | startblock = 0; | 395 | startblock = 0; |
396 | dir = 1; | 396 | dir = 1; |
397 | } | 397 | } |
398 | 398 | ||
399 | /* Do we have a bbt per chip ? */ | 399 | /* Do we have a bbt per chip ? */ |
400 | if (td->options & NAND_BBT_PERCHIP) { | 400 | if (td->options & NAND_BBT_PERCHIP) { |
401 | chips = this->numchips; | 401 | chips = this->numchips; |
@@ -405,19 +405,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
405 | chips = 1; | 405 | chips = 1; |
406 | bbtblocks = mtd->size >> this->bbt_erase_shift; | 406 | bbtblocks = mtd->size >> this->bbt_erase_shift; |
407 | } | 407 | } |
408 | 408 | ||
409 | /* Number of bits for each erase block in the bbt */ | 409 | /* Number of bits for each erase block in the bbt */ |
410 | bits = td->options & NAND_BBT_NRBITS_MSK; | 410 | bits = td->options & NAND_BBT_NRBITS_MSK; |
411 | 411 | ||
412 | for (i = 0; i < chips; i++) { | 412 | for (i = 0; i < chips; i++) { |
413 | /* Reset version information */ | 413 | /* Reset version information */ |
414 | td->version[i] = 0; | 414 | td->version[i] = 0; |
415 | td->pages[i] = -1; | 415 | td->pages[i] = -1; |
416 | /* Scan the maximum number of blocks */ | 416 | /* Scan the maximum number of blocks */ |
417 | for (block = 0; block < td->maxblocks; block++) { | 417 | for (block = 0; block < td->maxblocks; block++) { |
418 | int actblock = startblock + dir * block; | 418 | int actblock = startblock + dir * block; |
419 | /* Read first page */ | 419 | /* Read first page */ |
420 | nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); | 420 | nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); |
421 | if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { | 421 | if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { |
422 | td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); | 422 | td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); |
423 | if (td->options & NAND_BBT_VERSION) { | 423 | if (td->options & NAND_BBT_VERSION) { |
@@ -435,46 +435,46 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
435 | else | 435 | else |
436 | printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); | 436 | printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); |
437 | } | 437 | } |
438 | return 0; | 438 | return 0; |
439 | } | 439 | } |
440 | 440 | ||
441 | /** | 441 | /** |
442 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) | 442 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) |
443 | * @mtd: MTD device structure | 443 | * @mtd: MTD device structure |
444 | * @buf: temporary buffer | 444 | * @buf: temporary buffer |
445 | * @td: descriptor for the bad block table | 445 | * @td: descriptor for the bad block table |
446 | * @md: descriptor for the bad block table mirror | 446 | * @md: descriptor for the bad block table mirror |
447 | * | 447 | * |
448 | * Search and read the bad block table(s) | 448 | * Search and read the bad block table(s) |
449 | */ | 449 | */ |
450 | static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, | 450 | static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, |
451 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) | 451 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) |
452 | { | 452 | { |
453 | /* Search the primary table */ | 453 | /* Search the primary table */ |
454 | search_bbt (mtd, buf, td); | 454 | search_bbt (mtd, buf, td); |
455 | 455 | ||
456 | /* Search the mirror table */ | 456 | /* Search the mirror table */ |
457 | if (md) | 457 | if (md) |
458 | search_bbt (mtd, buf, md); | 458 | search_bbt (mtd, buf, md); |
459 | 459 | ||
460 | /* Force result check */ | 460 | /* Force result check */ |
461 | return 1; | 461 | return 1; |
462 | } | 462 | } |
463 | |||
464 | 463 | ||
465 | /** | 464 | |
465 | /** | ||
466 | * write_bbt - [GENERIC] (Re)write the bad block table | 466 | * write_bbt - [GENERIC] (Re)write the bad block table |
467 | * | 467 | * |
468 | * @mtd: MTD device structure | 468 | * @mtd: MTD device structure |
469 | * @buf: temporary buffer | 469 | * @buf: temporary buffer |
470 | * @td: descriptor for the bad block table | 470 | * @td: descriptor for the bad block table |
471 | * @md: descriptor for the bad block table mirror | 471 | * @md: descriptor for the bad block table mirror |
472 | * @chipsel: selector for a specific chip, -1 for all | 472 | * @chipsel: selector for a specific chip, -1 for all |
473 | * | 473 | * |
474 | * (Re)write the bad block table | 474 | * (Re)write the bad block table |
475 | * | 475 | * |
476 | */ | 476 | */ |
477 | static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | 477 | static int write_bbt (struct mtd_info *mtd, uint8_t *buf, |
478 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) | 478 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) |
479 | { | 479 | { |
480 | struct nand_chip *this = mtd->priv; | 480 | struct nand_chip *this = mtd->priv; |
@@ -493,7 +493,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
493 | /* Write bad block table per chip rather than per device ? */ | 493 | /* Write bad block table per chip rather than per device ? */ |
494 | if (td->options & NAND_BBT_PERCHIP) { | 494 | if (td->options & NAND_BBT_PERCHIP) { |
495 | numblocks = (int) (this->chipsize >> this->bbt_erase_shift); | 495 | numblocks = (int) (this->chipsize >> this->bbt_erase_shift); |
496 | /* Full device write or specific chip ? */ | 496 | /* Full device write or specific chip ? */ |
497 | if (chipsel == -1) { | 497 | if (chipsel == -1) { |
498 | nrchips = this->numchips; | 498 | nrchips = this->numchips; |
499 | } else { | 499 | } else { |
@@ -503,19 +503,19 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
503 | } else { | 503 | } else { |
504 | numblocks = (int) (mtd->size >> this->bbt_erase_shift); | 504 | numblocks = (int) (mtd->size >> this->bbt_erase_shift); |
505 | nrchips = 1; | 505 | nrchips = 1; |
506 | } | 506 | } |
507 | 507 | ||
508 | /* Loop through the chips */ | 508 | /* Loop through the chips */ |
509 | for (; chip < nrchips; chip++) { | 509 | for (; chip < nrchips; chip++) { |
510 | 510 | ||
511 | /* There was already a version of the table, reuse the page | 511 | /* There was already a version of the table, reuse the page |
512 | * This applies for absolute placement too, as we have the | 512 | * This applies for absolute placement too, as we have the |
513 | * page nr. in td->pages. | 513 | * page nr. in td->pages. |
514 | */ | 514 | */ |
515 | if (td->pages[chip] != -1) { | 515 | if (td->pages[chip] != -1) { |
516 | page = td->pages[chip]; | 516 | page = td->pages[chip]; |
517 | goto write; | 517 | goto write; |
518 | } | 518 | } |
519 | 519 | ||
520 | /* Automatic placement of the bad block table */ | 520 | /* Automatic placement of the bad block table */ |
521 | /* Search direction top -> down ? */ | 521 | /* Search direction top -> down ? */ |
@@ -525,7 +525,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
525 | } else { | 525 | } else { |
526 | startblock = chip * numblocks; | 526 | startblock = chip * numblocks; |
527 | dir = 1; | 527 | dir = 1; |
528 | } | 528 | } |
529 | 529 | ||
530 | for (i = 0; i < td->maxblocks; i++) { | 530 | for (i = 0; i < td->maxblocks; i++) { |
531 | int block = startblock + dir * i; | 531 | int block = startblock + dir * i; |
@@ -542,7 +542,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
542 | } | 542 | } |
543 | printk (KERN_ERR "No space left to write bad block table\n"); | 543 | printk (KERN_ERR "No space left to write bad block table\n"); |
544 | return -ENOSPC; | 544 | return -ENOSPC; |
545 | write: | 545 | write: |
546 | 546 | ||
547 | /* Set up shift count and masks for the flash table */ | 547 | /* Set up shift count and masks for the flash table */ |
548 | bits = td->options & NAND_BBT_NRBITS_MSK; | 548 | bits = td->options & NAND_BBT_NRBITS_MSK; |
@@ -553,14 +553,14 @@ write: | |||
553 | case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; | 553 | case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; |
554 | default: return -EINVAL; | 554 | default: return -EINVAL; |
555 | } | 555 | } |
556 | 556 | ||
557 | bbtoffs = chip * (numblocks >> 2); | 557 | bbtoffs = chip * (numblocks >> 2); |
558 | 558 | ||
559 | to = ((loff_t) page) << this->page_shift; | 559 | to = ((loff_t) page) << this->page_shift; |
560 | 560 | ||
561 | memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); | 561 | memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); |
562 | oobinfo.useecc = MTD_NANDECC_PLACEONLY; | 562 | oobinfo.useecc = MTD_NANDECC_PLACEONLY; |
563 | 563 | ||
564 | /* Must we save the block contents ? */ | 564 | /* Must we save the block contents ? */ |
565 | if (td->options & NAND_BBT_SAVECONTENT) { | 565 | if (td->options & NAND_BBT_SAVECONTENT) { |
566 | /* Make it block aligned */ | 566 | /* Make it block aligned */ |
@@ -599,7 +599,7 @@ write: | |||
599 | buf[len + td->veroffs] = td->version[chip]; | 599 | buf[len + td->veroffs] = td->version[chip]; |
600 | } | 600 | } |
601 | } | 601 | } |
602 | 602 | ||
603 | /* walk through the memory table */ | 603 | /* walk through the memory table */ |
604 | for (i = 0; i < numblocks; ) { | 604 | for (i = 0; i < numblocks; ) { |
605 | uint8_t dat; | 605 | uint8_t dat; |
@@ -611,7 +611,7 @@ write: | |||
611 | dat >>= 2; | 611 | dat >>= 2; |
612 | } | 612 | } |
613 | } | 613 | } |
614 | 614 | ||
615 | memset (&einfo, 0, sizeof (einfo)); | 615 | memset (&einfo, 0, sizeof (einfo)); |
616 | einfo.mtd = mtd; | 616 | einfo.mtd = mtd; |
617 | einfo.addr = (unsigned long) to; | 617 | einfo.addr = (unsigned long) to; |
@@ -621,18 +621,18 @@ write: | |||
621 | printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); | 621 | printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); |
622 | return res; | 622 | return res; |
623 | } | 623 | } |
624 | 624 | ||
625 | res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); | 625 | res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); |
626 | if (res < 0) { | 626 | if (res < 0) { |
627 | printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); | 627 | printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); |
628 | return res; | 628 | return res; |
629 | } | 629 | } |
630 | printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", | 630 | printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", |
631 | (unsigned int) to, td->version[chip]); | 631 | (unsigned int) to, td->version[chip]); |
632 | 632 | ||
633 | /* Mark it as used */ | 633 | /* Mark it as used */ |
634 | td->pages[chip] = page; | 634 | td->pages[chip] = page; |
635 | } | 635 | } |
636 | return 0; | 636 | return 0; |
637 | } | 637 | } |
638 | 638 | ||
@@ -641,7 +641,7 @@ write: | |||
641 | * @mtd: MTD device structure | 641 | * @mtd: MTD device structure |
642 | * @bd: descriptor for the good/bad block search pattern | 642 | * @bd: descriptor for the good/bad block search pattern |
643 | * | 643 | * |
644 | * The function creates a memory based bbt by scanning the device | 644 | * The function creates a memory based bbt by scanning the device |
645 | * for manufacturer / software marked good / bad blocks | 645 | * for manufacturer / software marked good / bad blocks |
646 | */ | 646 | */ |
647 | static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) | 647 | static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) |
@@ -673,11 +673,11 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
673 | struct nand_bbt_descr *rd, *rd2; | 673 | struct nand_bbt_descr *rd, *rd2; |
674 | 674 | ||
675 | /* Do we have a bbt per chip ? */ | 675 | /* Do we have a bbt per chip ? */ |
676 | if (td->options & NAND_BBT_PERCHIP) | 676 | if (td->options & NAND_BBT_PERCHIP) |
677 | chips = this->numchips; | 677 | chips = this->numchips; |
678 | else | 678 | else |
679 | chips = 1; | 679 | chips = 1; |
680 | 680 | ||
681 | for (i = 0; i < chips; i++) { | 681 | for (i = 0; i < chips; i++) { |
682 | writeops = 0; | 682 | writeops = 0; |
683 | rd = NULL; | 683 | rd = NULL; |
@@ -692,7 +692,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
692 | } | 692 | } |
693 | 693 | ||
694 | if (td->pages[i] == -1) { | 694 | if (td->pages[i] == -1) { |
695 | rd = md; | 695 | rd = md; |
696 | td->version[i] = md->version[i]; | 696 | td->version[i] = md->version[i]; |
697 | writeops = 1; | 697 | writeops = 1; |
698 | goto writecheck; | 698 | goto writecheck; |
@@ -710,7 +710,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
710 | if (!(td->options & NAND_BBT_VERSION)) | 710 | if (!(td->options & NAND_BBT_VERSION)) |
711 | rd2 = md; | 711 | rd2 = md; |
712 | goto writecheck; | 712 | goto writecheck; |
713 | } | 713 | } |
714 | 714 | ||
715 | if (((int8_t) (td->version[i] - md->version[i])) > 0) { | 715 | if (((int8_t) (td->version[i] - md->version[i])) > 0) { |
716 | rd = td; | 716 | rd = td; |
@@ -735,15 +735,15 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
735 | create: | 735 | create: |
736 | /* Create the bad block table by scanning the device ? */ | 736 | /* Create the bad block table by scanning the device ? */ |
737 | if (!(td->options & NAND_BBT_CREATE)) | 737 | if (!(td->options & NAND_BBT_CREATE)) |
738 | continue; | 738 | continue; |
739 | 739 | ||
740 | /* Create the table in memory by scanning the chip(s) */ | 740 | /* Create the table in memory by scanning the chip(s) */ |
741 | create_bbt (mtd, buf, bd, chipsel); | 741 | create_bbt (mtd, buf, bd, chipsel); |
742 | 742 | ||
743 | td->version[i] = 1; | 743 | td->version[i] = 1; |
744 | if (md) | 744 | if (md) |
745 | md->version[i] = 1; | 745 | md->version[i] = 1; |
746 | writecheck: | 746 | writecheck: |
747 | /* read back first ? */ | 747 | /* read back first ? */ |
748 | if (rd) | 748 | if (rd) |
749 | read_abs_bbt (mtd, buf, rd, chipsel); | 749 | read_abs_bbt (mtd, buf, rd, chipsel); |
@@ -757,7 +757,7 @@ writecheck: | |||
757 | if (res < 0) | 757 | if (res < 0) |
758 | return res; | 758 | return res; |
759 | } | 759 | } |
760 | 760 | ||
761 | /* Write the mirror bad block table to the device ? */ | 761 | /* Write the mirror bad block table to the device ? */ |
762 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { | 762 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { |
763 | res = write_bbt (mtd, buf, md, td, chipsel); | 763 | res = write_bbt (mtd, buf, md, td, chipsel); |
@@ -765,11 +765,11 @@ writecheck: | |||
765 | return res; | 765 | return res; |
766 | } | 766 | } |
767 | } | 767 | } |
768 | return 0; | 768 | return 0; |
769 | } | 769 | } |
770 | 770 | ||
771 | /** | 771 | /** |
772 | * mark_bbt_regions - [GENERIC] mark the bad block table regions | 772 | * mark_bbt_regions - [GENERIC] mark the bad block table regions |
773 | * @mtd: MTD device structure | 773 | * @mtd: MTD device structure |
774 | * @td: bad block table descriptor | 774 | * @td: bad block table descriptor |
775 | * | 775 | * |
@@ -790,14 +790,14 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
790 | } else { | 790 | } else { |
791 | chips = 1; | 791 | chips = 1; |
792 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); | 792 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); |
793 | } | 793 | } |
794 | 794 | ||
795 | for (i = 0; i < chips; i++) { | 795 | for (i = 0; i < chips; i++) { |
796 | if ((td->options & NAND_BBT_ABSPAGE) || | 796 | if ((td->options & NAND_BBT_ABSPAGE) || |
797 | !(td->options & NAND_BBT_WRITE)) { | 797 | !(td->options & NAND_BBT_WRITE)) { |
798 | if (td->pages[i] == -1) continue; | 798 | if (td->pages[i] == -1) continue; |
799 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); | 799 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); |
800 | block <<= 1; | 800 | block <<= 1; |
801 | oldval = this->bbt[(block >> 3)]; | 801 | oldval = this->bbt[(block >> 3)]; |
802 | newval = oldval | (0x2 << (block & 0x06)); | 802 | newval = oldval | (0x2 << (block & 0x06)); |
803 | this->bbt[(block >> 3)] = newval; | 803 | this->bbt[(block >> 3)] = newval; |
@@ -808,16 +808,16 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
808 | update = 0; | 808 | update = 0; |
809 | if (td->options & NAND_BBT_LASTBLOCK) | 809 | if (td->options & NAND_BBT_LASTBLOCK) |
810 | block = ((i + 1) * nrblocks) - td->maxblocks; | 810 | block = ((i + 1) * nrblocks) - td->maxblocks; |
811 | else | 811 | else |
812 | block = i * nrblocks; | 812 | block = i * nrblocks; |
813 | block <<= 1; | 813 | block <<= 1; |
814 | for (j = 0; j < td->maxblocks; j++) { | 814 | for (j = 0; j < td->maxblocks; j++) { |
815 | oldval = this->bbt[(block >> 3)]; | 815 | oldval = this->bbt[(block >> 3)]; |
816 | newval = oldval | (0x2 << (block & 0x06)); | 816 | newval = oldval | (0x2 << (block & 0x06)); |
817 | this->bbt[(block >> 3)] = newval; | 817 | this->bbt[(block >> 3)] = newval; |
818 | if (oldval != newval) update = 1; | 818 | if (oldval != newval) update = 1; |
819 | block += 2; | 819 | block += 2; |
820 | } | 820 | } |
821 | /* If we want reserved blocks to be recorded to flash, and some | 821 | /* If we want reserved blocks to be recorded to flash, and some |
822 | new ones have been marked, then we need to update the stored | 822 | new ones have been marked, then we need to update the stored |
823 | bbts. This should only happen once. */ | 823 | bbts. This should only happen once. */ |
@@ -831,7 +831,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
831 | * @mtd: MTD device structure | 831 | * @mtd: MTD device structure |
832 | * @bd: descriptor for the good/bad block search pattern | 832 | * @bd: descriptor for the good/bad block search pattern |
833 | * | 833 | * |
834 | * The function checks, if a bad block table(s) is/are already | 834 | * The function checks, if a bad block table(s) is/are already |
835 | * available. If not it scans the device for manufacturer | 835 | * available. If not it scans the device for manufacturer |
836 | * marked good / bad blocks and writes the bad block table(s) to | 836 | * marked good / bad blocks and writes the bad block table(s) to |
837 | * the selected place. | 837 | * the selected place. |
@@ -880,30 +880,30 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
880 | this->bbt = NULL; | 880 | this->bbt = NULL; |
881 | return -ENOMEM; | 881 | return -ENOMEM; |
882 | } | 882 | } |
883 | 883 | ||
884 | /* Is the bbt at a given page ? */ | 884 | /* Is the bbt at a given page ? */ |
885 | if (td->options & NAND_BBT_ABSPAGE) { | 885 | if (td->options & NAND_BBT_ABSPAGE) { |
886 | res = read_abs_bbts (mtd, buf, td, md); | 886 | res = read_abs_bbts (mtd, buf, td, md); |
887 | } else { | 887 | } else { |
888 | /* Search the bad block table using a pattern in oob */ | 888 | /* Search the bad block table using a pattern in oob */ |
889 | res = search_read_bbts (mtd, buf, td, md); | 889 | res = search_read_bbts (mtd, buf, td, md); |
890 | } | 890 | } |
891 | 891 | ||
892 | if (res) | 892 | if (res) |
893 | res = check_create (mtd, buf, bd); | 893 | res = check_create (mtd, buf, bd); |
894 | 894 | ||
895 | /* Prevent the bbt regions from erasing / writing */ | 895 | /* Prevent the bbt regions from erasing / writing */ |
896 | mark_bbt_region (mtd, td); | 896 | mark_bbt_region (mtd, td); |
897 | if (md) | 897 | if (md) |
898 | mark_bbt_region (mtd, md); | 898 | mark_bbt_region (mtd, md); |
899 | 899 | ||
900 | kfree (buf); | 900 | kfree (buf); |
901 | return res; | 901 | return res; |
902 | } | 902 | } |
903 | 903 | ||
904 | 904 | ||
905 | /** | 905 | /** |
906 | * nand_update_bbt - [NAND Interface] update bad block table(s) | 906 | * nand_update_bbt - [NAND Interface] update bad block table(s) |
907 | * @mtd: MTD device structure | 907 | * @mtd: MTD device structure |
908 | * @offs: the offset of the newly marked block | 908 | * @offs: the offset of the newly marked block |
909 | * | 909 | * |
@@ -930,7 +930,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | |||
930 | printk (KERN_ERR "nand_update_bbt: Out of memory\n"); | 930 | printk (KERN_ERR "nand_update_bbt: Out of memory\n"); |
931 | return -ENOMEM; | 931 | return -ENOMEM; |
932 | } | 932 | } |
933 | 933 | ||
934 | writeops = md != NULL ? 0x03 : 0x01; | 934 | writeops = md != NULL ? 0x03 : 0x01; |
935 | 935 | ||
936 | /* Do we have a bbt per chip ? */ | 936 | /* Do we have a bbt per chip ? */ |
@@ -944,7 +944,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | |||
944 | 944 | ||
945 | td->version[chip]++; | 945 | td->version[chip]++; |
946 | if (md) | 946 | if (md) |
947 | md->version[chip]++; | 947 | md->version[chip]++; |
948 | 948 | ||
949 | /* Write the bad block table to the device ? */ | 949 | /* Write the bad block table to the device ? */ |
950 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | 950 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { |
@@ -957,12 +957,12 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | |||
957 | res = write_bbt (mtd, buf, md, td, chipsel); | 957 | res = write_bbt (mtd, buf, md, td, chipsel); |
958 | } | 958 | } |
959 | 959 | ||
960 | out: | 960 | out: |
961 | kfree (buf); | 961 | kfree (buf); |
962 | return res; | 962 | return res; |
963 | } | 963 | } |
964 | 964 | ||
965 | /* Define some generic bad / good block scan pattern which are used | 965 | /* Define some generic bad / good block scan pattern which are used |
966 | * while scanning a device for factory marked good / bad blocks. */ | 966 | * while scanning a device for factory marked good / bad blocks. */ |
967 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 967 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
968 | 968 | ||
@@ -1009,7 +1009,7 @@ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | |||
1009 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; | 1009 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; |
1010 | 1010 | ||
1011 | static struct nand_bbt_descr bbt_main_descr = { | 1011 | static struct nand_bbt_descr bbt_main_descr = { |
1012 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 1012 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
1013 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | 1013 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, |
1014 | .offs = 8, | 1014 | .offs = 8, |
1015 | .len = 4, | 1015 | .len = 4, |
@@ -1019,7 +1019,7 @@ static struct nand_bbt_descr bbt_main_descr = { | |||
1019 | }; | 1019 | }; |
1020 | 1020 | ||
1021 | static struct nand_bbt_descr bbt_mirror_descr = { | 1021 | static struct nand_bbt_descr bbt_mirror_descr = { |
1022 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 1022 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
1023 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | 1023 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, |
1024 | .offs = 8, | 1024 | .offs = 8, |
1025 | .len = 4, | 1025 | .len = 4, |
@@ -1029,7 +1029,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1029 | }; | 1029 | }; |
1030 | 1030 | ||
1031 | /** | 1031 | /** |
1032 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device | 1032 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device |
1033 | * @mtd: MTD device structure | 1033 | * @mtd: MTD device structure |
1034 | * | 1034 | * |
1035 | * This function selects the default bad block table | 1035 | * This function selects the default bad block table |
@@ -1039,29 +1039,29 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1039 | int nand_default_bbt (struct mtd_info *mtd) | 1039 | int nand_default_bbt (struct mtd_info *mtd) |
1040 | { | 1040 | { |
1041 | struct nand_chip *this = mtd->priv; | 1041 | struct nand_chip *this = mtd->priv; |
1042 | 1042 | ||
1043 | /* Default for AG-AND. We must use a flash based | 1043 | /* Default for AG-AND. We must use a flash based |
1044 | * bad block table as the devices have factory marked | 1044 | * bad block table as the devices have factory marked |
1045 | * _good_ blocks. Erasing those blocks leads to loss | 1045 | * _good_ blocks. Erasing those blocks leads to loss |
1046 | * of the good / bad information, so we _must_ store | 1046 | * of the good / bad information, so we _must_ store |
1047 | * this information in a good / bad table during | 1047 | * this information in a good / bad table during |
1048 | * startup | 1048 | * startup |
1049 | */ | 1049 | */ |
1050 | if (this->options & NAND_IS_AND) { | 1050 | if (this->options & NAND_IS_AND) { |
1051 | /* Use the default pattern descriptors */ | 1051 | /* Use the default pattern descriptors */ |
1052 | if (!this->bbt_td) { | 1052 | if (!this->bbt_td) { |
1053 | this->bbt_td = &bbt_main_descr; | 1053 | this->bbt_td = &bbt_main_descr; |
1054 | this->bbt_md = &bbt_mirror_descr; | 1054 | this->bbt_md = &bbt_mirror_descr; |
1055 | } | 1055 | } |
1056 | this->options |= NAND_USE_FLASH_BBT; | 1056 | this->options |= NAND_USE_FLASH_BBT; |
1057 | return nand_scan_bbt (mtd, &agand_flashbased); | 1057 | return nand_scan_bbt (mtd, &agand_flashbased); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | 1060 | ||
1061 | /* Is a flash based bad block table requested ? */ | 1061 | /* Is a flash based bad block table requested ? */ |
1062 | if (this->options & NAND_USE_FLASH_BBT) { | 1062 | if (this->options & NAND_USE_FLASH_BBT) { |
1063 | /* Use the default pattern descriptors */ | 1063 | /* Use the default pattern descriptors */ |
1064 | if (!this->bbt_td) { | 1064 | if (!this->bbt_td) { |
1065 | this->bbt_td = &bbt_main_descr; | 1065 | this->bbt_td = &bbt_main_descr; |
1066 | this->bbt_md = &bbt_mirror_descr; | 1066 | this->bbt_md = &bbt_mirror_descr; |
1067 | } | 1067 | } |
@@ -1081,7 +1081,7 @@ int nand_default_bbt (struct mtd_info *mtd) | |||
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | /** | 1083 | /** |
1084 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad | 1084 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad |
1085 | * @mtd: MTD device structure | 1085 | * @mtd: MTD device structure |
1086 | * @offs: offset in the device | 1086 | * @offs: offset in the device |
1087 | * @allowbbt: allow access to bad block table region | 1087 | * @allowbbt: allow access to bad block table region |
@@ -1092,12 +1092,12 @@ int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt) | |||
1092 | struct nand_chip *this = mtd->priv; | 1092 | struct nand_chip *this = mtd->priv; |
1093 | int block; | 1093 | int block; |
1094 | uint8_t res; | 1094 | uint8_t res; |
1095 | 1095 | ||
1096 | /* Get block number * 2 */ | 1096 | /* Get block number * 2 */ |
1097 | block = (int) (offs >> (this->bbt_erase_shift - 1)); | 1097 | block = (int) (offs >> (this->bbt_erase_shift - 1)); |
1098 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; | 1098 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; |
1099 | 1099 | ||
1100 | DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", | 1100 | DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", |
1101 | (unsigned int)offs, block >> 1, res); | 1101 | (unsigned int)offs, block >> 1, res); |
1102 | 1102 | ||
1103 | switch ((int)res) { | 1103 | switch ((int)res) { |