diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 50c0d5f1c80a..922b890c8fcb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
46 | #include <linux/bitops.h> | 46 | #include <linux/bitops.h> |
47 | #include <linux/leds.h> | 47 | #include <linux/leds.h> |
48 | #include <asm/io.h> | 48 | #include <linux/io.h> |
49 | 49 | ||
50 | #ifdef CONFIG_MTD_PARTITIONS | 50 | #ifdef CONFIG_MTD_PARTITIONS |
51 | #include <linux/mtd/partitions.h> | 51 | #include <linux/mtd/partitions.h> |
@@ -786,7 +786,7 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) | |||
786 | spinlock_t *lock = &chip->controller->lock; | 786 | spinlock_t *lock = &chip->controller->lock; |
787 | wait_queue_head_t *wq = &chip->controller->wq; | 787 | wait_queue_head_t *wq = &chip->controller->wq; |
788 | DECLARE_WAITQUEUE(wait, current); | 788 | DECLARE_WAITQUEUE(wait, current); |
789 | retry: | 789 | retry: |
790 | spin_lock(lock); | 790 | spin_lock(lock); |
791 | 791 | ||
792 | /* Hardware controller shared among independent devices */ | 792 | /* Hardware controller shared among independent devices */ |
@@ -982,6 +982,7 @@ out: | |||
982 | 982 | ||
983 | return ret; | 983 | return ret; |
984 | } | 984 | } |
985 | EXPORT_SYMBOL(nand_unlock); | ||
985 | 986 | ||
986 | /** | 987 | /** |
987 | * nand_lock - [REPLACEABLE] locks all blocks present in the device | 988 | * nand_lock - [REPLACEABLE] locks all blocks present in the device |
@@ -1051,6 +1052,7 @@ out: | |||
1051 | 1052 | ||
1052 | return ret; | 1053 | return ret; |
1053 | } | 1054 | } |
1055 | EXPORT_SYMBOL(nand_lock); | ||
1054 | 1056 | ||
1055 | /** | 1057 | /** |
1056 | * nand_read_page_raw - [Intern] read raw page data without ecc | 1058 | * nand_read_page_raw - [Intern] read raw page data without ecc |
@@ -1078,8 +1080,9 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1078 | * | 1080 | * |
1079 | * We need a special oob layout and handling even when OOB isn't used. | 1081 | * We need a special oob layout and handling even when OOB isn't used. |
1080 | */ | 1082 | */ |
1081 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1083 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, |
1082 | uint8_t *buf, int page) | 1084 | struct nand_chip *chip, |
1085 | uint8_t *buf, int page) | ||
1083 | { | 1086 | { |
1084 | int eccsize = chip->ecc.size; | 1087 | int eccsize = chip->ecc.size; |
1085 | int eccbytes = chip->ecc.bytes; | 1088 | int eccbytes = chip->ecc.bytes; |
@@ -1160,7 +1163,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1160 | * @readlen: data length | 1163 | * @readlen: data length |
1161 | * @bufpoi: buffer to store read data | 1164 | * @bufpoi: buffer to store read data |
1162 | */ | 1165 | */ |
1163 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | 1166 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, |
1167 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | ||
1164 | { | 1168 | { |
1165 | int start_step, end_step, num_steps; | 1169 | int start_step, end_step, num_steps; |
1166 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1170 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
@@ -1168,6 +1172,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 | |||
1168 | int data_col_addr, i, gaps = 0; | 1172 | int data_col_addr, i, gaps = 0; |
1169 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1173 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
1170 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1174 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1175 | int index = 0; | ||
1171 | 1176 | ||
1172 | /* Column address wihin the page aligned to ECC size (256bytes). */ | 1177 | /* Column address wihin the page aligned to ECC size (256bytes). */ |
1173 | start_step = data_offs / chip->ecc.size; | 1178 | start_step = data_offs / chip->ecc.size; |
@@ -1206,25 +1211,29 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 | |||
1206 | } else { | 1211 | } else { |
1207 | /* send the command to read the particular ecc bytes */ | 1212 | /* send the command to read the particular ecc bytes */ |
1208 | /* take care about buswidth alignment in read_buf */ | 1213 | /* take care about buswidth alignment in read_buf */ |
1209 | aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1); | 1214 | index = start_step * chip->ecc.bytes; |
1215 | |||
1216 | aligned_pos = eccpos[index] & ~(busw - 1); | ||
1210 | aligned_len = eccfrag_len; | 1217 | aligned_len = eccfrag_len; |
1211 | if (eccpos[start_step * chip->ecc.bytes] & (busw - 1)) | 1218 | if (eccpos[index] & (busw - 1)) |
1212 | aligned_len++; | 1219 | aligned_len++; |
1213 | if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1)) | 1220 | if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) |
1214 | aligned_len++; | 1221 | aligned_len++; |
1215 | 1222 | ||
1216 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1); | 1223 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
1224 | mtd->writesize + aligned_pos, -1); | ||
1217 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); | 1225 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); |
1218 | } | 1226 | } |
1219 | 1227 | ||
1220 | for (i = 0; i < eccfrag_len; i++) | 1228 | for (i = 0; i < eccfrag_len; i++) |
1221 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]]; | 1229 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; |
1222 | 1230 | ||
1223 | p = bufpoi + data_col_addr; | 1231 | p = bufpoi + data_col_addr; |
1224 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { | 1232 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { |
1225 | int stat; | 1233 | int stat; |
1226 | 1234 | ||
1227 | stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); | 1235 | stat = chip->ecc.correct(mtd, p, |
1236 | &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); | ||
1228 | if (stat < 0) | 1237 | if (stat < 0) |
1229 | mtd->ecc_stats.failed++; | 1238 | mtd->ecc_stats.failed++; |
1230 | else | 1239 | else |
@@ -1486,7 +1495,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1486 | ret = chip->ecc.read_page_raw(mtd, chip, | 1495 | ret = chip->ecc.read_page_raw(mtd, chip, |
1487 | bufpoi, page); | 1496 | bufpoi, page); |
1488 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) | 1497 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) |
1489 | ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); | 1498 | ret = chip->ecc.read_subpage(mtd, chip, |
1499 | col, bytes, bufpoi); | ||
1490 | else | 1500 | else |
1491 | ret = chip->ecc.read_page(mtd, chip, bufpoi, | 1501 | ret = chip->ecc.read_page(mtd, chip, bufpoi, |
1492 | page); | 1502 | page); |
@@ -1878,7 +1888,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1878 | else | 1888 | else |
1879 | ret = nand_do_read_ops(mtd, from, ops); | 1889 | ret = nand_do_read_ops(mtd, from, ops); |
1880 | 1890 | ||
1881 | out: | 1891 | out: |
1882 | nand_release_device(mtd); | 1892 | nand_release_device(mtd); |
1883 | return ret; | 1893 | return ret; |
1884 | } | 1894 | } |
@@ -1907,8 +1917,9 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1907 | * | 1917 | * |
1908 | * We need a special oob layout and handling even when ECC isn't checked. | 1918 | * We need a special oob layout and handling even when ECC isn't checked. |
1909 | */ | 1919 | */ |
1910 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1920 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, |
1911 | const uint8_t *buf) | 1921 | struct nand_chip *chip, |
1922 | const uint8_t *buf) | ||
1912 | { | 1923 | { |
1913 | int eccsize = chip->ecc.size; | 1924 | int eccsize = chip->ecc.size; |
1914 | int eccbytes = chip->ecc.bytes; | 1925 | int eccbytes = chip->ecc.bytes; |
@@ -2448,7 +2459,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2448 | else | 2459 | else |
2449 | ret = nand_do_write_ops(mtd, to, ops); | 2460 | ret = nand_do_write_ops(mtd, to, ops); |
2450 | 2461 | ||
2451 | out: | 2462 | out: |
2452 | nand_release_device(mtd); | 2463 | nand_release_device(mtd); |
2453 | return ret; | 2464 | return ret; |
2454 | } | 2465 | } |
@@ -2634,7 +2645,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2634 | } | 2645 | } |
2635 | instr->state = MTD_ERASE_DONE; | 2646 | instr->state = MTD_ERASE_DONE; |
2636 | 2647 | ||
2637 | erase_exit: | 2648 | erase_exit: |
2638 | 2649 | ||
2639 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; | 2650 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; |
2640 | 2651 | ||
@@ -2892,7 +2903,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2892 | */ | 2903 | */ |
2893 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | 2904 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, |
2894 | struct nand_chip *chip, | 2905 | struct nand_chip *chip, |
2895 | int busw, int *maf_id, int *dev_id, | 2906 | int busw, |
2907 | int *maf_id, int *dev_id, | ||
2896 | struct nand_flash_dev *type) | 2908 | struct nand_flash_dev *type) |
2897 | { | 2909 | { |
2898 | int i, maf_idx; | 2910 | int i, maf_idx; |
@@ -3087,8 +3099,10 @@ ident_done: | |||
3087 | ffs(mtd->erasesize) - 1; | 3099 | ffs(mtd->erasesize) - 1; |
3088 | if (chip->chipsize & 0xffffffff) | 3100 | if (chip->chipsize & 0xffffffff) |
3089 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; | 3101 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; |
3090 | else | 3102 | else { |
3091 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; | 3103 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)); |
3104 | chip->chip_shift += 32 - 1; | ||
3105 | } | ||
3092 | 3106 | ||
3093 | /* Set the bad block position */ | 3107 | /* Set the bad block position */ |
3094 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) | 3108 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) |
@@ -3169,7 +3183,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3169 | nand_set_defaults(chip, busw); | 3183 | nand_set_defaults(chip, busw); |
3170 | 3184 | ||
3171 | /* Read the flash type */ | 3185 | /* Read the flash type */ |
3172 | type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, &nand_dev_id, table); | 3186 | type = nand_get_flash_type(mtd, chip, busw, |
3187 | &nand_maf_id, &nand_dev_id, table); | ||
3173 | 3188 | ||
3174 | if (IS_ERR(type)) { | 3189 | if (IS_ERR(type)) { |
3175 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | 3190 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) |
@@ -3199,6 +3214,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3199 | 3214 | ||
3200 | return 0; | 3215 | return 0; |
3201 | } | 3216 | } |
3217 | EXPORT_SYMBOL(nand_scan_ident); | ||
3202 | 3218 | ||
3203 | 3219 | ||
3204 | /** | 3220 | /** |
@@ -3427,10 +3443,11 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3427 | /* Build bad block table */ | 3443 | /* Build bad block table */ |
3428 | return chip->scan_bbt(mtd); | 3444 | return chip->scan_bbt(mtd); |
3429 | } | 3445 | } |
3446 | EXPORT_SYMBOL(nand_scan_tail); | ||
3430 | 3447 | ||
3431 | /* is_module_text_address() isn't exported, and it's mostly a pointless | 3448 | /* is_module_text_address() isn't exported, and it's mostly a pointless |
3432 | test if this is a module _anyway_ -- they'd have to try _really_ hard | 3449 | * test if this is a module _anyway_ -- they'd have to try _really_ hard |
3433 | to call us from in-kernel code if the core NAND support is modular. */ | 3450 | * to call us from in-kernel code if the core NAND support is modular. */ |
3434 | #ifdef MODULE | 3451 | #ifdef MODULE |
3435 | #define caller_is_module() (1) | 3452 | #define caller_is_module() (1) |
3436 | #else | 3453 | #else |
@@ -3466,6 +3483,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
3466 | ret = nand_scan_tail(mtd); | 3483 | ret = nand_scan_tail(mtd); |
3467 | return ret; | 3484 | return ret; |
3468 | } | 3485 | } |
3486 | EXPORT_SYMBOL(nand_scan); | ||
3469 | 3487 | ||
3470 | /** | 3488 | /** |
3471 | * nand_release - [NAND Interface] Free resources held by the NAND device | 3489 | * nand_release - [NAND Interface] Free resources held by the NAND device |
@@ -3492,12 +3510,6 @@ void nand_release(struct mtd_info *mtd) | |||
3492 | & NAND_BBT_DYNAMICSTRUCT) | 3510 | & NAND_BBT_DYNAMICSTRUCT) |
3493 | kfree(chip->badblock_pattern); | 3511 | kfree(chip->badblock_pattern); |
3494 | } | 3512 | } |
3495 | |||
3496 | EXPORT_SYMBOL_GPL(nand_lock); | ||
3497 | EXPORT_SYMBOL_GPL(nand_unlock); | ||
3498 | EXPORT_SYMBOL_GPL(nand_scan); | ||
3499 | EXPORT_SYMBOL_GPL(nand_scan_ident); | ||
3500 | EXPORT_SYMBOL_GPL(nand_scan_tail); | ||
3501 | EXPORT_SYMBOL_GPL(nand_release); | 3513 | EXPORT_SYMBOL_GPL(nand_release); |
3502 | 3514 | ||
3503 | static int __init nand_base_init(void) | 3515 | static int __init nand_base_init(void) |
@@ -3515,5 +3527,6 @@ module_init(nand_base_init); | |||
3515 | module_exit(nand_base_exit); | 3527 | module_exit(nand_base_exit); |
3516 | 3528 | ||
3517 | MODULE_LICENSE("GPL"); | 3529 | MODULE_LICENSE("GPL"); |
3518 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); | 3530 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); |
3531 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | ||
3519 | MODULE_DESCRIPTION("Generic NAND flash driver code"); | 3532 | MODULE_DESCRIPTION("Generic NAND flash driver code"); |