diff options
107 files changed, 1910 insertions, 1525 deletions
diff --git a/arch/blackfin/include/asm/nand.h b/arch/blackfin/include/asm/nand.h index 3a1e79dfc8d9..256c50d8d465 100644 --- a/arch/blackfin/include/asm/nand.h +++ b/arch/blackfin/include/asm/nand.h | |||
@@ -15,8 +15,6 @@ | |||
15 | * partitions = mtd partition list | 15 | * partitions = mtd partition list |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define NFC_PG_SIZE_256 0 | ||
19 | #define NFC_PG_SIZE_512 1 | ||
20 | #define NFC_PG_SIZE_OFFSET 9 | 18 | #define NFC_PG_SIZE_OFFSET 9 |
21 | 19 | ||
22 | #define NFC_NWIDTH_8 0 | 20 | #define NFC_NWIDTH_8 0 |
@@ -30,7 +28,6 @@ | |||
30 | 28 | ||
31 | struct bf5xx_nand_platform { | 29 | struct bf5xx_nand_platform { |
32 | /* NAND chip information */ | 30 | /* NAND chip information */ |
33 | unsigned short page_size; | ||
34 | unsigned short data_width; | 31 | unsigned short data_width; |
35 | 32 | ||
36 | /* RD/WR strobe delay timing information, all times in SCLK cycles */ | 33 | /* RD/WR strobe delay timing information, all times in SCLK cycles */ |
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index f8210bf2d241..1e2cbf5d9aa1 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -311,15 +311,17 @@ config SM_FTL | |||
311 | select MTD_BLKDEVS | 311 | select MTD_BLKDEVS |
312 | select MTD_NAND_ECC | 312 | select MTD_NAND_ECC |
313 | help | 313 | help |
314 | This enables new and very EXPERMENTAL support for SmartMedia/xD | 314 | This enables EXPERIMENTAL R/W support for SmartMedia/xD |
315 | FTL (Flash translation layer). | 315 | FTL (Flash translation layer). |
316 | Write support isn't yet well tested, therefore this code IS likely to | 316 | Write support is only lightly tested, therefore this driver |
317 | eat your card, so please don't use it together with valuable data. | 317 | isn't recommended to use with valuable data (anyway if you have |
318 | Use readonly driver (CONFIG_SSFDC) instead. | 318 | valuable data, do backups regardless of software/hardware you |
319 | use, because you never know what will eat your data...) | ||
320 | If you only need R/O access, you can use older R/O driver | ||
321 | (CONFIG_SSFDC) | ||
319 | 322 | ||
320 | config MTD_OOPS | 323 | config MTD_OOPS |
321 | tristate "Log panic/oops to an MTD buffer" | 324 | tristate "Log panic/oops to an MTD buffer" |
322 | depends on MTD | ||
323 | help | 325 | help |
324 | This enables panic and oops messages to be logged to a circular | 326 | This enables panic and oops messages to be logged to a circular |
325 | buffer in a flash partition where it can be read back at some | 327 | buffer in a flash partition where it can be read back at some |
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index cec7ab98b2a9..302372c08b56 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | drivers/mtd/afs.c: ARM Flash Layout/Partitioning | 3 | drivers/mtd/afs.c: ARM Flash Layout/Partitioning |
4 | 4 | ||
5 | Copyright (C) 2000 ARM Limited | 5 | Copyright © 2000 ARM Limited |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 62f3ea9de848..9e2b7e9e0ad9 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/mtd/xip.h> | 34 | #include <linux/mtd/xip.h> |
35 | #include <linux/mtd/map.h> | 35 | #include <linux/mtd/map.h> |
36 | #include <linux/mtd/mtd.h> | 36 | #include <linux/mtd/mtd.h> |
37 | #include <linux/mtd/compatmac.h> | ||
38 | #include <linux/mtd/cfi.h> | 37 | #include <linux/mtd/cfi.h> |
39 | 38 | ||
40 | /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ | 39 | /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ |
@@ -63,6 +62,8 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); | |||
63 | static void cfi_intelext_sync (struct mtd_info *); | 62 | static void cfi_intelext_sync (struct mtd_info *); |
64 | static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 63 | static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
65 | static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 64 | static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
65 | static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, | ||
66 | uint64_t len); | ||
66 | #ifdef CONFIG_MTD_OTP | 67 | #ifdef CONFIG_MTD_OTP |
67 | static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 68 | static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
68 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 69 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
@@ -448,6 +449,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) | |||
448 | mtd->sync = cfi_intelext_sync; | 449 | mtd->sync = cfi_intelext_sync; |
449 | mtd->lock = cfi_intelext_lock; | 450 | mtd->lock = cfi_intelext_lock; |
450 | mtd->unlock = cfi_intelext_unlock; | 451 | mtd->unlock = cfi_intelext_unlock; |
452 | mtd->is_locked = cfi_intelext_is_locked; | ||
451 | mtd->suspend = cfi_intelext_suspend; | 453 | mtd->suspend = cfi_intelext_suspend; |
452 | mtd->resume = cfi_intelext_resume; | 454 | mtd->resume = cfi_intelext_resume; |
453 | mtd->flags = MTD_CAP_NORFLASH; | 455 | mtd->flags = MTD_CAP_NORFLASH; |
@@ -717,7 +719,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
717 | chip = &newcfi->chips[0]; | 719 | chip = &newcfi->chips[0]; |
718 | for (i = 0; i < cfi->numchips; i++) { | 720 | for (i = 0; i < cfi->numchips; i++) { |
719 | shared[i].writing = shared[i].erasing = NULL; | 721 | shared[i].writing = shared[i].erasing = NULL; |
720 | spin_lock_init(&shared[i].lock); | 722 | mutex_init(&shared[i].lock); |
721 | for (j = 0; j < numparts; j++) { | 723 | for (j = 0; j < numparts; j++) { |
722 | *chip = cfi->chips[i]; | 724 | *chip = cfi->chips[i]; |
723 | chip->start += j << partshift; | 725 | chip->start += j << partshift; |
@@ -886,7 +888,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
886 | */ | 888 | */ |
887 | struct flchip_shared *shared = chip->priv; | 889 | struct flchip_shared *shared = chip->priv; |
888 | struct flchip *contender; | 890 | struct flchip *contender; |
889 | spin_lock(&shared->lock); | 891 | mutex_lock(&shared->lock); |
890 | contender = shared->writing; | 892 | contender = shared->writing; |
891 | if (contender && contender != chip) { | 893 | if (contender && contender != chip) { |
892 | /* | 894 | /* |
@@ -899,7 +901,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
899 | * get_chip returns success we're clear to go ahead. | 901 | * get_chip returns success we're clear to go ahead. |
900 | */ | 902 | */ |
901 | ret = mutex_trylock(&contender->mutex); | 903 | ret = mutex_trylock(&contender->mutex); |
902 | spin_unlock(&shared->lock); | 904 | mutex_unlock(&shared->lock); |
903 | if (!ret) | 905 | if (!ret) |
904 | goto retry; | 906 | goto retry; |
905 | mutex_unlock(&chip->mutex); | 907 | mutex_unlock(&chip->mutex); |
@@ -914,7 +916,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
914 | mutex_unlock(&contender->mutex); | 916 | mutex_unlock(&contender->mutex); |
915 | return ret; | 917 | return ret; |
916 | } | 918 | } |
917 | spin_lock(&shared->lock); | 919 | mutex_lock(&shared->lock); |
918 | 920 | ||
919 | /* We should not own chip if it is already | 921 | /* We should not own chip if it is already |
920 | * in FL_SYNCING state. Put contender and retry. */ | 922 | * in FL_SYNCING state. Put contender and retry. */ |
@@ -930,7 +932,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
930 | * on this chip. Sleep. */ | 932 | * on this chip. Sleep. */ |
931 | if (mode == FL_ERASING && shared->erasing | 933 | if (mode == FL_ERASING && shared->erasing |
932 | && shared->erasing->oldstate == FL_ERASING) { | 934 | && shared->erasing->oldstate == FL_ERASING) { |
933 | spin_unlock(&shared->lock); | 935 | mutex_unlock(&shared->lock); |
934 | set_current_state(TASK_UNINTERRUPTIBLE); | 936 | set_current_state(TASK_UNINTERRUPTIBLE); |
935 | add_wait_queue(&chip->wq, &wait); | 937 | add_wait_queue(&chip->wq, &wait); |
936 | mutex_unlock(&chip->mutex); | 938 | mutex_unlock(&chip->mutex); |
@@ -944,7 +946,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
944 | shared->writing = chip; | 946 | shared->writing = chip; |
945 | if (mode == FL_ERASING) | 947 | if (mode == FL_ERASING) |
946 | shared->erasing = chip; | 948 | shared->erasing = chip; |
947 | spin_unlock(&shared->lock); | 949 | mutex_unlock(&shared->lock); |
948 | } | 950 | } |
949 | ret = chip_ready(map, chip, adr, mode); | 951 | ret = chip_ready(map, chip, adr, mode); |
950 | if (ret == -EAGAIN) | 952 | if (ret == -EAGAIN) |
@@ -959,7 +961,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
959 | 961 | ||
960 | if (chip->priv) { | 962 | if (chip->priv) { |
961 | struct flchip_shared *shared = chip->priv; | 963 | struct flchip_shared *shared = chip->priv; |
962 | spin_lock(&shared->lock); | 964 | mutex_lock(&shared->lock); |
963 | if (shared->writing == chip && chip->oldstate == FL_READY) { | 965 | if (shared->writing == chip && chip->oldstate == FL_READY) { |
964 | /* We own the ability to write, but we're done */ | 966 | /* We own the ability to write, but we're done */ |
965 | shared->writing = shared->erasing; | 967 | shared->writing = shared->erasing; |
@@ -967,7 +969,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
967 | /* give back ownership to who we loaned it from */ | 969 | /* give back ownership to who we loaned it from */ |
968 | struct flchip *loaner = shared->writing; | 970 | struct flchip *loaner = shared->writing; |
969 | mutex_lock(&loaner->mutex); | 971 | mutex_lock(&loaner->mutex); |
970 | spin_unlock(&shared->lock); | 972 | mutex_unlock(&shared->lock); |
971 | mutex_unlock(&chip->mutex); | 973 | mutex_unlock(&chip->mutex); |
972 | put_chip(map, loaner, loaner->start); | 974 | put_chip(map, loaner, loaner->start); |
973 | mutex_lock(&chip->mutex); | 975 | mutex_lock(&chip->mutex); |
@@ -985,11 +987,11 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
985 | * Don't let the switch below mess things up since | 987 | * Don't let the switch below mess things up since |
986 | * we don't have ownership to resume anything. | 988 | * we don't have ownership to resume anything. |
987 | */ | 989 | */ |
988 | spin_unlock(&shared->lock); | 990 | mutex_unlock(&shared->lock); |
989 | wake_up(&chip->wq); | 991 | wake_up(&chip->wq); |
990 | return; | 992 | return; |
991 | } | 993 | } |
992 | spin_unlock(&shared->lock); | 994 | mutex_unlock(&shared->lock); |
993 | } | 995 | } |
994 | 996 | ||
995 | switch(chip->oldstate) { | 997 | switch(chip->oldstate) { |
@@ -2139,6 +2141,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
2139 | return ret; | 2141 | return ret; |
2140 | } | 2142 | } |
2141 | 2143 | ||
2144 | static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, | ||
2145 | uint64_t len) | ||
2146 | { | ||
2147 | return cfi_varsize_frob(mtd, do_getlockstatus_oneblock, | ||
2148 | ofs, len, NULL) ? 1 : 0; | ||
2149 | } | ||
2150 | |||
2142 | #ifdef CONFIG_MTD_OTP | 2151 | #ifdef CONFIG_MTD_OTP |
2143 | 2152 | ||
2144 | typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, | 2153 | typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index d81079ef91a5..3e6c47bdce53 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/reboot.h> | 35 | #include <linux/reboot.h> |
36 | #include <linux/mtd/compatmac.h> | ||
37 | #include <linux/mtd/map.h> | 36 | #include <linux/mtd/map.h> |
38 | #include <linux/mtd/mtd.h> | 37 | #include <linux/mtd/mtd.h> |
39 | #include <linux/mtd/cfi.h> | 38 | #include <linux/mtd/cfi.h> |
@@ -417,16 +416,26 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
417 | */ | 416 | */ |
418 | cfi_fixup_major_minor(cfi, extp); | 417 | cfi_fixup_major_minor(cfi, extp); |
419 | 418 | ||
419 | /* | ||
420 | * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4 | ||
421 | * see: http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf, page 19 | ||
422 | * http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_100_20011201.pdf | ||
423 | * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf | ||
424 | */ | ||
420 | if (extp->MajorVersion != '1' || | 425 | if (extp->MajorVersion != '1' || |
421 | (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { | 426 | (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) { |
422 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " | 427 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " |
423 | "version %c.%c.\n", extp->MajorVersion, | 428 | "version %c.%c (%#02x/%#02x).\n", |
424 | extp->MinorVersion); | 429 | extp->MajorVersion, extp->MinorVersion, |
430 | extp->MajorVersion, extp->MinorVersion); | ||
425 | kfree(extp); | 431 | kfree(extp); |
426 | kfree(mtd); | 432 | kfree(mtd); |
427 | return NULL; | 433 | return NULL; |
428 | } | 434 | } |
429 | 435 | ||
436 | printk(KERN_INFO " Amd/Fujitsu Extended Query version %c.%c.\n", | ||
437 | extp->MajorVersion, extp->MinorVersion); | ||
438 | |||
430 | /* Install our own private info structure */ | 439 | /* Install our own private info structure */ |
431 | cfi->cmdset_priv = extp; | 440 | cfi->cmdset_priv = extp; |
432 | 441 | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index e54e8c169d76..314af1f5a370 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/mtd/map.h> | 33 | #include <linux/mtd/map.h> |
34 | #include <linux/mtd/cfi.h> | 34 | #include <linux/mtd/cfi.h> |
35 | #include <linux/mtd/mtd.h> | 35 | #include <linux/mtd/mtd.h> |
36 | #include <linux/mtd/compatmac.h> | ||
37 | 36 | ||
38 | 37 | ||
39 | static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 38 | static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index b2acd32f4fbf..8f5b96aa87a0 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
235 | cfi_qry_mode_off(base, map, cfi); | 235 | cfi_qry_mode_off(base, map, cfi); |
236 | xip_allowed(base, map); | 236 | xip_allowed(base, map); |
237 | 237 | ||
238 | printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", | 238 | printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n", |
239 | map->name, cfi->interleave, cfi->device_type*8, base, | 239 | map->name, cfi->interleave, cfi->device_type*8, base, |
240 | map->bankwidth*8); | 240 | map->bankwidth*8, cfi->mfr, cfi->id); |
241 | 241 | ||
242 | return 1; | 242 | return 1; |
243 | } | 243 | } |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index d7c2c672757e..e503b2ca894d 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/mtd.h> |
23 | #include <linux/mtd/map.h> | 23 | #include <linux/mtd/map.h> |
24 | #include <linux/mtd/cfi.h> | 24 | #include <linux/mtd/cfi.h> |
25 | #include <linux/mtd/compatmac.h> | ||
26 | 25 | ||
27 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, | 26 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, |
28 | struct cfi_private *cfi) | 27 | struct cfi_private *cfi) |
diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index c85760968227..da1f96f385c7 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/mtd/map.h> | 11 | #include <linux/mtd/map.h> |
12 | #include <linux/mtd/mtd.h> | 12 | #include <linux/mtd/mtd.h> |
13 | #include <linux/mtd/compatmac.h> | ||
14 | 13 | ||
15 | static DEFINE_SPINLOCK(chip_drvs_lock); | 14 | static DEFINE_SPINLOCK(chip_drvs_lock); |
16 | static LIST_HEAD(chip_drvs_list); | 15 | static LIST_HEAD(chip_drvs_list); |
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c index 494d30d0631a..f2b872946871 100644 --- a/drivers/mtd/chips/map_absent.c +++ b/drivers/mtd/chips/map_absent.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
27 | #include <linux/mtd/map.h> | 27 | #include <linux/mtd/map.h> |
28 | #include <linux/mtd/compatmac.h> | ||
29 | 28 | ||
30 | static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 29 | static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
31 | static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 30 | static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 6bdc50c727e7..67640ccb2d41 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/mtd/mtd.h> | 14 | #include <linux/mtd/mtd.h> |
15 | #include <linux/mtd/map.h> | 15 | #include <linux/mtd/map.h> |
16 | #include <linux/mtd/compatmac.h> | ||
17 | 16 | ||
18 | 17 | ||
19 | static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 18 | static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 076090a67b90..593f73d480d2 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/mtd/mtd.h> | 14 | #include <linux/mtd/mtd.h> |
15 | #include <linux/mtd/map.h> | 15 | #include <linux/mtd/map.h> |
16 | #include <linux/mtd/compatmac.h> | ||
17 | 16 | ||
18 | static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 17 | static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
19 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 18 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 1479da6d3aa6..e790f38893b0 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -1,7 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * Read flash partition table from command line | 2 | * Read flash partition table from command line |
3 | * | 3 | * |
4 | * Copyright 2002 SYSGO Real-Time Solutions GmbH | 4 | * Copyright © 2002 SYSGO Real-Time Solutions GmbH |
5 | * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
5 | * | 20 | * |
6 | * The format for the command line is as follows: | 21 | * The format for the command line is as follows: |
7 | * | 22 | * |
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index a19cda52da5c..a99838bb2dc0 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | 33 | ||
34 | #include <linux/mtd/compatmac.h> /* for min() in older kernels */ | ||
35 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
36 | #include <linux/mtd/doc2000.h> | 35 | #include <linux/mtd/doc2000.h> |
37 | 36 | ||
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 6e62922942b1..d374603493a7 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/mtd/mtd.h> | 49 | #include <linux/mtd/mtd.h> |
50 | #include <linux/mtd/nand.h> | 50 | #include <linux/mtd/nand.h> |
51 | #include <linux/mtd/doc2000.h> | 51 | #include <linux/mtd/doc2000.h> |
52 | #include <linux/mtd/compatmac.h> | ||
53 | 52 | ||
54 | /* Where to look for the devices? */ | 53 | /* Where to look for the devices? */ |
55 | #ifndef CONFIG_MTD_DOCPROBE_ADDRESS | 54 | #ifndef CONFIG_MTD_DOCPROBE_ADDRESS |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 81e49a9b017e..f90941a785e4 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -16,6 +16,8 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/err.h> | ||
20 | #include <linux/errno.h> | ||
19 | #include <linux/module.h> | 21 | #include <linux/module.h> |
20 | #include <linux/device.h> | 22 | #include <linux/device.h> |
21 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
@@ -639,8 +641,18 @@ static const struct spi_device_id m25p_ids[] = { | |||
639 | { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, | 641 | { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, |
640 | { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, | 642 | { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, |
641 | 643 | ||
644 | /* EON -- en25pxx */ | ||
645 | { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, | ||
646 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | ||
647 | |||
648 | /* Intel/Numonyx -- xxxs33b */ | ||
649 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, | ||
650 | { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, | ||
651 | { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, | ||
652 | |||
642 | /* Macronix */ | 653 | /* Macronix */ |
643 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, | 654 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, |
655 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, | ||
644 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, | 656 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, |
645 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, | 657 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, |
646 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, | 658 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, |
@@ -680,6 +692,16 @@ static const struct spi_device_id m25p_ids[] = { | |||
680 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, | 692 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, |
681 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, | 693 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, |
682 | 694 | ||
695 | { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, | ||
696 | { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, | ||
697 | { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, | ||
698 | { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, | ||
699 | { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, | ||
700 | { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, | ||
701 | { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, | ||
702 | { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, | ||
703 | { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, | ||
704 | |||
683 | { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, | 705 | { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, |
684 | { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, | 706 | { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, |
685 | { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, | 707 | { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, |
@@ -694,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
694 | { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, | 716 | { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, |
695 | { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, | 717 | { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, |
696 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, | 718 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, |
719 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, | ||
697 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 720 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
698 | 721 | ||
699 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 722 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
@@ -723,7 +746,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
723 | if (tmp < 0) { | 746 | if (tmp < 0) { |
724 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", | 747 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", |
725 | dev_name(&spi->dev), tmp); | 748 | dev_name(&spi->dev), tmp); |
726 | return NULL; | 749 | return ERR_PTR(tmp); |
727 | } | 750 | } |
728 | jedec = id[0]; | 751 | jedec = id[0]; |
729 | jedec = jedec << 8; | 752 | jedec = jedec << 8; |
@@ -731,14 +754,6 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
731 | jedec = jedec << 8; | 754 | jedec = jedec << 8; |
732 | jedec |= id[2]; | 755 | jedec |= id[2]; |
733 | 756 | ||
734 | /* | ||
735 | * Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants, | ||
736 | * which depend on technology process. Officially RDID command doesn't | ||
737 | * exist for non-JEDEC chips, but for compatibility they return ID 0. | ||
738 | */ | ||
739 | if (jedec == 0) | ||
740 | return NULL; | ||
741 | |||
742 | ext_jedec = id[3] << 8 | id[4]; | 757 | ext_jedec = id[3] << 8 | id[4]; |
743 | 758 | ||
744 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { | 759 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { |
@@ -749,7 +764,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
749 | return &m25p_ids[tmp]; | 764 | return &m25p_ids[tmp]; |
750 | } | 765 | } |
751 | } | 766 | } |
752 | return NULL; | 767 | return ERR_PTR(-ENODEV); |
753 | } | 768 | } |
754 | 769 | ||
755 | 770 | ||
@@ -794,9 +809,8 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
794 | const struct spi_device_id *jid; | 809 | const struct spi_device_id *jid; |
795 | 810 | ||
796 | jid = jedec_probe(spi); | 811 | jid = jedec_probe(spi); |
797 | if (!jid) { | 812 | if (IS_ERR(jid)) { |
798 | dev_info(&spi->dev, "non-JEDEC variant of %s\n", | 813 | return PTR_ERR(jid); |
799 | id->name); | ||
800 | } else if (jid != id) { | 814 | } else if (jid != id) { |
801 | /* | 815 | /* |
802 | * JEDEC knows better, so overwrite platform ID. We | 816 | * JEDEC knows better, so overwrite platform ID. We |
@@ -826,11 +840,12 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
826 | dev_set_drvdata(&spi->dev, flash); | 840 | dev_set_drvdata(&spi->dev, flash); |
827 | 841 | ||
828 | /* | 842 | /* |
829 | * Atmel and SST serial flash tend to power | 843 | * Atmel, SST and Intel/Numonyx serial flash tend to power |
830 | * up with the software protection bits set | 844 | * up with the software protection bits set |
831 | */ | 845 | */ |
832 | 846 | ||
833 | if (info->jedec_id >> 16 == 0x1f || | 847 | if (info->jedec_id >> 16 == 0x1f || |
848 | info->jedec_id >> 16 == 0x89 || | ||
834 | info->jedec_id >> 16 == 0xbf) { | 849 | info->jedec_id >> 16 == 0xbf) { |
835 | write_enable(flash); | 850 | write_enable(flash); |
836 | write_sr(flash, 0); | 851 | write_sr(flash, 0); |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 19817404ce7d..c5015cc721d5 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -141,7 +141,7 @@ static int dataflash_waitready(struct spi_device *spi) | |||
141 | */ | 141 | */ |
142 | static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | 142 | static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) |
143 | { | 143 | { |
144 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 144 | struct dataflash *priv = mtd->priv; |
145 | struct spi_device *spi = priv->spi; | 145 | struct spi_device *spi = priv->spi; |
146 | struct spi_transfer x = { .tx_dma = 0, }; | 146 | struct spi_transfer x = { .tx_dma = 0, }; |
147 | struct spi_message msg; | 147 | struct spi_message msg; |
@@ -231,7 +231,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
231 | static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | 231 | static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, |
232 | size_t *retlen, u_char *buf) | 232 | size_t *retlen, u_char *buf) |
233 | { | 233 | { |
234 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 234 | struct dataflash *priv = mtd->priv; |
235 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | 235 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; |
236 | struct spi_message msg; | 236 | struct spi_message msg; |
237 | unsigned int addr; | 237 | unsigned int addr; |
@@ -304,7 +304,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
304 | static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | 304 | static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, |
305 | size_t * retlen, const u_char * buf) | 305 | size_t * retlen, const u_char * buf) |
306 | { | 306 | { |
307 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 307 | struct dataflash *priv = mtd->priv; |
308 | struct spi_device *spi = priv->spi; | 308 | struct spi_device *spi = priv->spi; |
309 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | 309 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; |
310 | struct spi_message msg; | 310 | struct spi_message msg; |
@@ -515,7 +515,7 @@ static ssize_t otp_read(struct spi_device *spi, unsigned base, | |||
515 | static int dataflash_read_fact_otp(struct mtd_info *mtd, | 515 | static int dataflash_read_fact_otp(struct mtd_info *mtd, |
516 | loff_t from, size_t len, size_t *retlen, u_char *buf) | 516 | loff_t from, size_t len, size_t *retlen, u_char *buf) |
517 | { | 517 | { |
518 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 518 | struct dataflash *priv = mtd->priv; |
519 | int status; | 519 | int status; |
520 | 520 | ||
521 | /* 64 bytes, from 0..63 ... start at 64 on-chip */ | 521 | /* 64 bytes, from 0..63 ... start at 64 on-chip */ |
@@ -532,7 +532,7 @@ static int dataflash_read_fact_otp(struct mtd_info *mtd, | |||
532 | static int dataflash_read_user_otp(struct mtd_info *mtd, | 532 | static int dataflash_read_user_otp(struct mtd_info *mtd, |
533 | loff_t from, size_t len, size_t *retlen, u_char *buf) | 533 | loff_t from, size_t len, size_t *retlen, u_char *buf) |
534 | { | 534 | { |
535 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 535 | struct dataflash *priv = mtd->priv; |
536 | int status; | 536 | int status; |
537 | 537 | ||
538 | /* 64 bytes, from 0..63 ... start at 0 on-chip */ | 538 | /* 64 bytes, from 0..63 ... start at 0 on-chip */ |
@@ -553,7 +553,7 @@ static int dataflash_write_user_otp(struct mtd_info *mtd, | |||
553 | const size_t l = 4 + 64; | 553 | const size_t l = 4 + 64; |
554 | uint8_t *scratch; | 554 | uint8_t *scratch; |
555 | struct spi_transfer t; | 555 | struct spi_transfer t; |
556 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 556 | struct dataflash *priv = mtd->priv; |
557 | int status; | 557 | int status; |
558 | 558 | ||
559 | if (len > 64) | 559 | if (len > 64) |
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index fce5ff7589aa..26a6e809013d 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
15 | #include <linux/vmalloc.h> | 15 | #include <linux/vmalloc.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/mtd/compatmac.h> | ||
18 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/mtdram.h> | 18 | #include <linux/mtd/mtdram.h> |
20 | 19 | ||
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index fc8ea0a57ac2..ef0aba0ce58f 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -98,7 +98,6 @@ | |||
98 | 98 | ||
99 | #include <linux/mtd/mtd.h> | 99 | #include <linux/mtd/mtd.h> |
100 | #include <linux/mtd/pmc551.h> | 100 | #include <linux/mtd/pmc551.h> |
101 | #include <linux/mtd/compatmac.h> | ||
102 | 101 | ||
103 | static struct mtd_info *pmc551list; | 102 | static struct mtd_info *pmc551list; |
104 | 103 | ||
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index ab5d8cd02a15..684247a8a5ed 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -454,7 +454,7 @@ static int __init sst25l_probe(struct spi_device *spi) | |||
454 | parts, nr_parts); | 454 | parts, nr_parts); |
455 | } | 455 | } |
456 | 456 | ||
457 | } else if (data->nr_parts) { | 457 | } else if (data && data->nr_parts) { |
458 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | 458 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", |
459 | data->nr_parts, data->name); | 459 | data->nr_parts, data->name); |
460 | } | 460 | } |
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 62da9eb7032b..4d6a64c387ec 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | The initial developer of the original code is David A. Hinds | 27 | The initial developer of the original code is David A. Hinds |
28 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | 28 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds |
29 | are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 29 | are Copyright © 1999 David A. Hinds. All Rights Reserved. |
30 | 30 | ||
31 | Alternatively, the contents of this file may be used under the | 31 | Alternatively, the contents of this file may be used under the |
32 | terms of the GNU General Public License version 2 (the "GPL"), in | 32 | terms of the GNU General Public License version 2 (the "GPL"), in |
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 015a7fe1b6ee..d7592e67d048 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) | 2 | * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) |
3 | * | 3 | * |
4 | * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) | 4 | * Copyright © 2002, Greg Ungerer (gerg@snapgear.com) |
5 | * | 5 | * |
6 | * Based heavily on the nftlcore.c code which is: | 6 | * Based heavily on the nftlcore.c code which is: |
7 | * (c) 1999 Machine Vision Holdings, Inc. | 7 | * Copyright © 1999 Machine Vision Holdings, Inc. |
8 | * Author: David Woodhouse <dwmw2@infradead.org> | 8 | * Copyright © 1999 David Woodhouse <dwmw2@infradead.org> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 8f988d7d3c5c..104052e774b0 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
@@ -2,11 +2,11 @@ | |||
2 | * inftlmount.c -- INFTL mount code with extensive checks. | 2 | * inftlmount.c -- INFTL mount code with extensive checks. |
3 | * | 3 | * |
4 | * Author: Greg Ungerer (gerg@snapgear.com) | 4 | * Author: Greg Ungerer (gerg@snapgear.com) |
5 | * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com) | 5 | * Copyright © 2002-2003, Greg Ungerer (gerg@snapgear.com) |
6 | * | 6 | * |
7 | * Based heavily on the nftlmount.c code which is: | 7 | * Based heavily on the nftlmount.c code which is: |
8 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 8 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
9 | * Copyright (C) 2000 Netgem S.A. | 9 | * Copyright © 2000 Netgem S.A. |
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 as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/nftl.h> | 35 | #include <linux/mtd/nftl.h> |
36 | #include <linux/mtd/inftl.h> | 36 | #include <linux/mtd/inftl.h> |
37 | #include <linux/mtd/compatmac.h> | ||
38 | 37 | ||
39 | /* | 38 | /* |
40 | * find_boot_record: Find the INFTL Media Header and its Spare copy which | 39 | * find_boot_record: Find the INFTL Media Header and its Spare copy which |
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index fece5be58715..04fdfcca93f7 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c | |||
@@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) | |||
98 | numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; | 98 | numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; |
99 | for (i = 0; i < numchips; i++) { | 99 | for (i = 0; i < numchips; i++) { |
100 | shared[i].writing = shared[i].erasing = NULL; | 100 | shared[i].writing = shared[i].erasing = NULL; |
101 | spin_lock_init(&shared[i].lock); | 101 | mutex_init(&shared[i].lock); |
102 | for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { | 102 | for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { |
103 | *chip = lpddr->chips[i]; | 103 | *chip = lpddr->chips[i]; |
104 | chip->start += j << lpddr->chipshift; | 104 | chip->start += j << lpddr->chipshift; |
@@ -217,7 +217,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
217 | */ | 217 | */ |
218 | struct flchip_shared *shared = chip->priv; | 218 | struct flchip_shared *shared = chip->priv; |
219 | struct flchip *contender; | 219 | struct flchip *contender; |
220 | spin_lock(&shared->lock); | 220 | mutex_lock(&shared->lock); |
221 | contender = shared->writing; | 221 | contender = shared->writing; |
222 | if (contender && contender != chip) { | 222 | if (contender && contender != chip) { |
223 | /* | 223 | /* |
@@ -230,7 +230,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
230 | * get_chip returns success we're clear to go ahead. | 230 | * get_chip returns success we're clear to go ahead. |
231 | */ | 231 | */ |
232 | ret = mutex_trylock(&contender->mutex); | 232 | ret = mutex_trylock(&contender->mutex); |
233 | spin_unlock(&shared->lock); | 233 | mutex_unlock(&shared->lock); |
234 | if (!ret) | 234 | if (!ret) |
235 | goto retry; | 235 | goto retry; |
236 | mutex_unlock(&chip->mutex); | 236 | mutex_unlock(&chip->mutex); |
@@ -245,7 +245,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
245 | mutex_unlock(&contender->mutex); | 245 | mutex_unlock(&contender->mutex); |
246 | return ret; | 246 | return ret; |
247 | } | 247 | } |
248 | spin_lock(&shared->lock); | 248 | mutex_lock(&shared->lock); |
249 | 249 | ||
250 | /* We should not own chip if it is already in FL_SYNCING | 250 | /* We should not own chip if it is already in FL_SYNCING |
251 | * state. Put contender and retry. */ | 251 | * state. Put contender and retry. */ |
@@ -261,7 +261,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
261 | Must sleep in such a case. */ | 261 | Must sleep in such a case. */ |
262 | if (mode == FL_ERASING && shared->erasing | 262 | if (mode == FL_ERASING && shared->erasing |
263 | && shared->erasing->oldstate == FL_ERASING) { | 263 | && shared->erasing->oldstate == FL_ERASING) { |
264 | spin_unlock(&shared->lock); | 264 | mutex_unlock(&shared->lock); |
265 | set_current_state(TASK_UNINTERRUPTIBLE); | 265 | set_current_state(TASK_UNINTERRUPTIBLE); |
266 | add_wait_queue(&chip->wq, &wait); | 266 | add_wait_queue(&chip->wq, &wait); |
267 | mutex_unlock(&chip->mutex); | 267 | mutex_unlock(&chip->mutex); |
@@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
275 | shared->writing = chip; | 275 | shared->writing = chip; |
276 | if (mode == FL_ERASING) | 276 | if (mode == FL_ERASING) |
277 | shared->erasing = chip; | 277 | shared->erasing = chip; |
278 | spin_unlock(&shared->lock); | 278 | mutex_unlock(&shared->lock); |
279 | } | 279 | } |
280 | 280 | ||
281 | ret = chip_ready(map, chip, mode); | 281 | ret = chip_ready(map, chip, mode); |
@@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
348 | { | 348 | { |
349 | if (chip->priv) { | 349 | if (chip->priv) { |
350 | struct flchip_shared *shared = chip->priv; | 350 | struct flchip_shared *shared = chip->priv; |
351 | spin_lock(&shared->lock); | 351 | mutex_lock(&shared->lock); |
352 | if (shared->writing == chip && chip->oldstate == FL_READY) { | 352 | if (shared->writing == chip && chip->oldstate == FL_READY) { |
353 | /* We own the ability to write, but we're done */ | 353 | /* We own the ability to write, but we're done */ |
354 | shared->writing = shared->erasing; | 354 | shared->writing = shared->erasing; |
@@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
356 | /* give back the ownership */ | 356 | /* give back the ownership */ |
357 | struct flchip *loaner = shared->writing; | 357 | struct flchip *loaner = shared->writing; |
358 | mutex_lock(&loaner->mutex); | 358 | mutex_lock(&loaner->mutex); |
359 | spin_unlock(&shared->lock); | 359 | mutex_unlock(&shared->lock); |
360 | mutex_unlock(&chip->mutex); | 360 | mutex_unlock(&chip->mutex); |
361 | put_chip(map, loaner); | 361 | put_chip(map, loaner); |
362 | mutex_lock(&chip->mutex); | 362 | mutex_lock(&chip->mutex); |
@@ -374,11 +374,11 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
374 | * Don't let the switch below mess things up since | 374 | * Don't let the switch below mess things up since |
375 | * we don't have ownership to resume anything. | 375 | * we don't have ownership to resume anything. |
376 | */ | 376 | */ |
377 | spin_unlock(&shared->lock); | 377 | mutex_unlock(&shared->lock); |
378 | wake_up(&chip->wq); | 378 | wake_up(&chip->wq); |
379 | return; | 379 | return; |
380 | } | 380 | } |
381 | spin_unlock(&shared->lock); | 381 | mutex_unlock(&shared->lock); |
382 | } | 382 | } |
383 | 383 | ||
384 | switch (chip->oldstate) { | 384 | switch (chip->oldstate) { |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 6629d09f3b38..701d942c6795 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -319,14 +319,6 @@ config MTD_CFI_FLAGADM | |||
319 | Mapping for the Flaga digital module. If you don't have one, ignore | 319 | Mapping for the Flaga digital module. If you don't have one, ignore |
320 | this setting. | 320 | this setting. |
321 | 321 | ||
322 | config MTD_REDWOOD | ||
323 | tristate "CFI Flash devices mapped on IBM Redwood" | ||
324 | depends on MTD_CFI | ||
325 | help | ||
326 | This enables access routines for the flash chips on the IBM | ||
327 | Redwood board. If you have one of these boards and would like to | ||
328 | use the flash chips on it, say 'Y'. | ||
329 | |||
330 | config MTD_SOLUTIONENGINE | 322 | config MTD_SOLUTIONENGINE |
331 | tristate "CFI Flash device mapped on Hitachi SolutionEngine" | 323 | tristate "CFI Flash device mapped on Hitachi SolutionEngine" |
332 | depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS | 324 | depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index bb035cd54c72..f216bb573713 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -44,7 +44,6 @@ obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o | |||
44 | obj-$(CONFIG_MTD_EDB7312) += edb7312.o | 44 | obj-$(CONFIG_MTD_EDB7312) += edb7312.o |
45 | obj-$(CONFIG_MTD_IMPA7) += impa7.o | 45 | obj-$(CONFIG_MTD_IMPA7) += impa7.o |
46 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o | 46 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o |
47 | obj-$(CONFIG_MTD_REDWOOD) += redwood.o | ||
48 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o | 47 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o |
49 | obj-$(CONFIG_MTD_NETtel) += nettel.o | 48 | obj-$(CONFIG_MTD_NETtel) += nettel.o |
50 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o | 49 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o |
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index e0a5e0426ead..1f9fde0dad35 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
@@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, | |||
118 | *dest++ = BYTE1(data); | 118 | *dest++ = BYTE1(data); |
119 | src += 2; | 119 | src += 2; |
120 | len -= 2; | 120 | len -= 2; |
121 | } | 121 | } |
122 | 122 | ||
123 | if (len > 0) | 123 | if (len > 0) |
124 | *dest++ = BYTE0(flash_read16(src)); | 124 | *dest++ = BYTE0(flash_read16(src)); |
@@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
185 | { | 185 | { |
186 | struct flash_platform_data *plat = dev->dev.platform_data; | 186 | struct flash_platform_data *plat = dev->dev.platform_data; |
187 | struct ixp4xx_flash_info *info; | 187 | struct ixp4xx_flash_info *info; |
188 | const char *part_type = NULL; | ||
189 | int nr_parts = 0; | ||
188 | int err = -1; | 190 | int err = -1; |
189 | 191 | ||
190 | if (!plat) | 192 | if (!plat) |
@@ -218,9 +220,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
218 | */ | 220 | */ |
219 | info->map.bankwidth = 2; | 221 | info->map.bankwidth = 2; |
220 | info->map.name = dev_name(&dev->dev); | 222 | info->map.name = dev_name(&dev->dev); |
221 | info->map.read = ixp4xx_read16, | 223 | info->map.read = ixp4xx_read16; |
222 | info->map.write = ixp4xx_probe_write16, | 224 | info->map.write = ixp4xx_probe_write16; |
223 | info->map.copy_from = ixp4xx_copy_from, | 225 | info->map.copy_from = ixp4xx_copy_from; |
224 | 226 | ||
225 | info->res = request_mem_region(dev->resource->start, | 227 | info->res = request_mem_region(dev->resource->start, |
226 | resource_size(dev->resource), | 228 | resource_size(dev->resource), |
@@ -248,11 +250,28 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
248 | info->mtd->owner = THIS_MODULE; | 250 | info->mtd->owner = THIS_MODULE; |
249 | 251 | ||
250 | /* Use the fast version */ | 252 | /* Use the fast version */ |
251 | info->map.write = ixp4xx_write16, | 253 | info->map.write = ixp4xx_write16; |
254 | |||
255 | #ifdef CONFIG_MTD_PARTITIONS | ||
256 | nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions, | ||
257 | dev->resource->start); | ||
258 | #endif | ||
259 | if (nr_parts > 0) { | ||
260 | part_type = "dynamic"; | ||
261 | } else { | ||
262 | info->partitions = plat->parts; | ||
263 | nr_parts = plat->nr_parts; | ||
264 | part_type = "static"; | ||
265 | } | ||
266 | if (nr_parts == 0) { | ||
267 | printk(KERN_NOTICE "IXP4xx flash: no partition info " | ||
268 | "available, registering whole flash\n"); | ||
269 | err = add_mtd_device(info->mtd); | ||
270 | } else { | ||
271 | printk(KERN_NOTICE "IXP4xx flash: using %s partition " | ||
272 | "definition\n", part_type); | ||
273 | err = add_mtd_partitions(info->mtd, info->partitions, nr_parts); | ||
252 | 274 | ||
253 | err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start); | ||
254 | if (err > 0) { | ||
255 | err = add_mtd_partitions(info->mtd, info->partitions, err); | ||
256 | if(err) | 275 | if(err) |
257 | printk(KERN_ERR "Could not parse partitions\n"); | 276 | printk(KERN_ERR "Could not parse partitions\n"); |
258 | } | 277 | } |
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 426461a5f0d4..4c18b98a3110 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
@@ -106,12 +106,12 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
106 | 106 | ||
107 | for (i = 0; i < dev->num_resources; i++) { | 107 | for (i = 0; i < dev->num_resources; i++) { |
108 | printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", | 108 | printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", |
109 | (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1), | 109 | (unsigned long long)resource_size(&dev->resource[i]), |
110 | (unsigned long long)dev->resource[i].start); | 110 | (unsigned long long)dev->resource[i].start); |
111 | 111 | ||
112 | if (!devm_request_mem_region(&dev->dev, | 112 | if (!devm_request_mem_region(&dev->dev, |
113 | dev->resource[i].start, | 113 | dev->resource[i].start, |
114 | dev->resource[i].end - dev->resource[i].start + 1, | 114 | resource_size(&dev->resource[i]), |
115 | dev_name(&dev->dev))) { | 115 | dev_name(&dev->dev))) { |
116 | dev_err(&dev->dev, "Could not reserve memory region\n"); | 116 | dev_err(&dev->dev, "Could not reserve memory region\n"); |
117 | err = -ENOMEM; | 117 | err = -ENOMEM; |
@@ -120,7 +120,7 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
120 | 120 | ||
121 | info->map[i].name = dev_name(&dev->dev); | 121 | info->map[i].name = dev_name(&dev->dev); |
122 | info->map[i].phys = dev->resource[i].start; | 122 | info->map[i].phys = dev->resource[i].start; |
123 | info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1; | 123 | info->map[i].size = resource_size(&dev->resource[i]); |
124 | info->map[i].bankwidth = physmap_data->width; | 124 | info->map[i].bankwidth = physmap_data->width; |
125 | info->map[i].set_vpp = physmap_data->set_vpp; | 125 | info->map[i].set_vpp = physmap_data->set_vpp; |
126 | info->map[i].pfow_base = physmap_data->pfow_base; | 126 | info->map[i].pfow_base = physmap_data->pfow_base; |
@@ -136,8 +136,12 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
136 | simple_map_init(&info->map[i]); | 136 | simple_map_init(&info->map[i]); |
137 | 137 | ||
138 | probe_type = rom_probe_types; | 138 | probe_type = rom_probe_types; |
139 | for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) | 139 | if (physmap_data->probe_type == NULL) { |
140 | info->mtd[i] = do_map_probe(*probe_type, &info->map[i]); | 140 | for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) |
141 | info->mtd[i] = do_map_probe(*probe_type, &info->map[i]); | ||
142 | } else | ||
143 | info->mtd[i] = do_map_probe(physmap_data->probe_type, &info->map[i]); | ||
144 | |||
141 | if (info->mtd[i] == NULL) { | 145 | if (info->mtd[i] == NULL) { |
142 | dev_err(&dev->dev, "map_probe failed\n"); | 146 | dev_err(&dev->dev, "map_probe failed\n"); |
143 | err = -ENXIO; | 147 | err = -ENXIO; |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ba124baa646d..6ac5f9f28ac3 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -353,7 +353,7 @@ static int __devinit of_flash_probe(struct of_device *dev, | |||
353 | &info->parts, 0); | 353 | &info->parts, 0); |
354 | if (err < 0) { | 354 | if (err < 0) { |
355 | of_free_probes(part_probe_types); | 355 | of_free_probes(part_probe_types); |
356 | return err; | 356 | goto err_out; |
357 | } | 357 | } |
358 | of_free_probes(part_probe_types); | 358 | of_free_probes(part_probe_types); |
359 | 359 | ||
@@ -361,14 +361,14 @@ static int __devinit of_flash_probe(struct of_device *dev, | |||
361 | if (err == 0) { | 361 | if (err == 0) { |
362 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); | 362 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); |
363 | if (err < 0) | 363 | if (err < 0) |
364 | return err; | 364 | goto err_out; |
365 | } | 365 | } |
366 | #endif | 366 | #endif |
367 | 367 | ||
368 | if (err == 0) { | 368 | if (err == 0) { |
369 | err = parse_obsolete_partitions(dev, info, dp); | 369 | err = parse_obsolete_partitions(dev, info, dp); |
370 | if (err < 0) | 370 | if (err < 0) |
371 | return err; | 371 | goto err_out; |
372 | } | 372 | } |
373 | 373 | ||
374 | if (err > 0) | 374 | if (err > 0) |
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c deleted file mode 100644 index d2c9db00db0c..000000000000 --- a/drivers/mtd/maps/redwood.c +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/mtd/maps/redwood.c | ||
3 | * | ||
4 | * FLASH map for the IBM Redwood 4/5/6 boards. | ||
5 | * | ||
6 | * Author: MontaVista Software, Inc. <source@mvista.com> | ||
7 | * | ||
8 | * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <linux/mtd/mtd.h> | ||
20 | #include <linux/mtd/map.h> | ||
21 | #include <linux/mtd/partitions.h> | ||
22 | |||
23 | #include <asm/io.h> | ||
24 | |||
25 | #define WINDOW_ADDR 0xffc00000 | ||
26 | #define WINDOW_SIZE 0x00400000 | ||
27 | |||
28 | #define RW_PART0_OF 0 | ||
29 | #define RW_PART0_SZ 0x10000 | ||
30 | #define RW_PART1_OF RW_PART0_SZ | ||
31 | #define RW_PART1_SZ 0x200000 - 0x10000 | ||
32 | #define RW_PART2_OF 0x200000 | ||
33 | #define RW_PART2_SZ 0x10000 | ||
34 | #define RW_PART3_OF 0x210000 | ||
35 | #define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000) | ||
36 | #define RW_PART4_OF 0x3e0000 | ||
37 | #define RW_PART4_SZ 0x20000 | ||
38 | |||
39 | static struct mtd_partition redwood_flash_partitions[] = { | ||
40 | { | ||
41 | .name = "Redwood OpenBIOS Vital Product Data", | ||
42 | .offset = RW_PART0_OF, | ||
43 | .size = RW_PART0_SZ, | ||
44 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
45 | }, | ||
46 | { | ||
47 | .name = "Redwood kernel", | ||
48 | .offset = RW_PART1_OF, | ||
49 | .size = RW_PART1_SZ | ||
50 | }, | ||
51 | { | ||
52 | .name = "Redwood OpenBIOS non-volatile storage", | ||
53 | .offset = RW_PART2_OF, | ||
54 | .size = RW_PART2_SZ, | ||
55 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
56 | }, | ||
57 | { | ||
58 | .name = "Redwood filesystem", | ||
59 | .offset = RW_PART3_OF, | ||
60 | .size = RW_PART3_SZ | ||
61 | }, | ||
62 | { | ||
63 | .name = "Redwood OpenBIOS", | ||
64 | .offset = RW_PART4_OF, | ||
65 | .size = RW_PART4_SZ, | ||
66 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | struct map_info redwood_flash_map = { | ||
71 | .name = "IBM Redwood", | ||
72 | .size = WINDOW_SIZE, | ||
73 | .bankwidth = 2, | ||
74 | .phys = WINDOW_ADDR, | ||
75 | }; | ||
76 | |||
77 | |||
78 | #define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions) | ||
79 | |||
80 | static struct mtd_info *redwood_mtd; | ||
81 | |||
82 | static int __init init_redwood_flash(void) | ||
83 | { | ||
84 | int err; | ||
85 | |||
86 | printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", | ||
87 | WINDOW_SIZE, WINDOW_ADDR); | ||
88 | |||
89 | redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); | ||
90 | |||
91 | if (!redwood_flash_map.virt) { | ||
92 | printk("init_redwood_flash: failed to ioremap\n"); | ||
93 | return -EIO; | ||
94 | } | ||
95 | simple_map_init(&redwood_flash_map); | ||
96 | |||
97 | redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map); | ||
98 | |||
99 | if (redwood_mtd) { | ||
100 | redwood_mtd->owner = THIS_MODULE; | ||
101 | err = add_mtd_partitions(redwood_mtd, | ||
102 | redwood_flash_partitions, | ||
103 | NUM_REDWOOD_FLASH_PARTITIONS); | ||
104 | if (err) { | ||
105 | printk("init_redwood_flash: add_mtd_partitions failed\n"); | ||
106 | iounmap(redwood_flash_map.virt); | ||
107 | } | ||
108 | return err; | ||
109 | |||
110 | } | ||
111 | |||
112 | iounmap(redwood_flash_map.virt); | ||
113 | return -ENXIO; | ||
114 | } | ||
115 | |||
116 | static void __exit cleanup_redwood_flash(void) | ||
117 | { | ||
118 | if (redwood_mtd) { | ||
119 | del_mtd_partitions(redwood_mtd); | ||
120 | /* moved iounmap after map_destroy - armin */ | ||
121 | map_destroy(redwood_mtd); | ||
122 | iounmap((void *)redwood_flash_map.virt); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | module_init(init_redwood_flash); | ||
127 | module_exit(cleanup_redwood_flash); | ||
128 | |||
129 | MODULE_LICENSE("GPL"); | ||
130 | MODULE_AUTHOR("MontaVista Software <source@mvista.com>"); | ||
131 | MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards"); | ||
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 03e19c1965cc..1d2144d77470 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -1,7 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> | 2 | * Interface to Linux block layer for MTD 'translation layers'. |
3 | * | 3 | * |
4 | * Interface to Linux 2.5 block layer for MTD 'translation layers'. | 4 | * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
5 | * | 19 | * |
6 | */ | 20 | */ |
7 | 21 | ||
@@ -245,6 +259,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, | |||
245 | switch (cmd) { | 259 | switch (cmd) { |
246 | case BLKFLSBUF: | 260 | case BLKFLSBUF: |
247 | ret = dev->tr->flush ? dev->tr->flush(dev) : 0; | 261 | ret = dev->tr->flush ? dev->tr->flush(dev) : 0; |
262 | break; | ||
248 | default: | 263 | default: |
249 | ret = -ENOTTY; | 264 | ret = -ENOTTY; |
250 | } | 265 | } |
@@ -409,13 +424,14 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | |||
409 | BUG(); | 424 | BUG(); |
410 | } | 425 | } |
411 | 426 | ||
412 | /* Stop new requests to arrive */ | ||
413 | del_gendisk(old->disk); | ||
414 | |||
415 | if (old->disk_attributes) | 427 | if (old->disk_attributes) |
416 | sysfs_remove_group(&disk_to_dev(old->disk)->kobj, | 428 | sysfs_remove_group(&disk_to_dev(old->disk)->kobj, |
417 | old->disk_attributes); | 429 | old->disk_attributes); |
418 | 430 | ||
431 | /* Stop new requests to arrive */ | ||
432 | del_gendisk(old->disk); | ||
433 | |||
434 | |||
419 | /* Stop the thread */ | 435 | /* Stop the thread */ |
420 | kthread_stop(old->thread); | 436 | kthread_stop(old->thread); |
421 | 437 | ||
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index e6edbec609fd..1e74ad961040 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
@@ -1,8 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * Direct MTD block device access | 2 | * Direct MTD block device access |
3 | * | 3 | * |
4 | * (C) 2000-2003 Nicolas Pitre <nico@fluxnic.net> | 4 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> | 5 | * Copyright © 2000-2003 Nicolas Pitre <nico@fluxnic.net> |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
6 | */ | 21 | */ |
7 | 22 | ||
8 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index d0d3f79f9d03..795a8c0a05b8 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c | |||
@@ -1,7 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> | ||
3 | * | ||
4 | * Simple read-only (writable only for RAM) mtdblock driver | 2 | * Simple read-only (writable only for RAM) mtdblock driver |
3 | * | ||
4 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | * | ||
5 | */ | 20 | */ |
6 | 21 | ||
7 | #include <linux/init.h> | 22 | #include <linux/init.h> |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 91c8013cf0d9..a825002123c8 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -1,5 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Character-device access to raw MTD devices. | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
3 | * | 17 | * |
4 | */ | 18 | */ |
5 | 19 | ||
@@ -18,7 +32,7 @@ | |||
18 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
19 | 33 | ||
20 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
21 | #include <linux/mtd/compatmac.h> | 35 | #include <linux/mtd/map.h> |
22 | 36 | ||
23 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
24 | 38 | ||
@@ -675,6 +689,20 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
675 | break; | 689 | break; |
676 | } | 690 | } |
677 | 691 | ||
692 | case MEMISLOCKED: | ||
693 | { | ||
694 | struct erase_info_user einfo; | ||
695 | |||
696 | if (copy_from_user(&einfo, argp, sizeof(einfo))) | ||
697 | return -EFAULT; | ||
698 | |||
699 | if (!mtd->is_locked) | ||
700 | ret = -EOPNOTSUPP; | ||
701 | else | ||
702 | ret = mtd->is_locked(mtd, einfo.start, einfo.length); | ||
703 | break; | ||
704 | } | ||
705 | |||
678 | /* Legacy interface */ | 706 | /* Legacy interface */ |
679 | case MEMGETOOBSEL: | 707 | case MEMGETOOBSEL: |
680 | { | 708 | { |
@@ -950,9 +978,34 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma) | |||
950 | #ifdef CONFIG_MMU | 978 | #ifdef CONFIG_MMU |
951 | struct mtd_file_info *mfi = file->private_data; | 979 | struct mtd_file_info *mfi = file->private_data; |
952 | struct mtd_info *mtd = mfi->mtd; | 980 | struct mtd_info *mtd = mfi->mtd; |
981 | struct map_info *map = mtd->priv; | ||
982 | unsigned long start; | ||
983 | unsigned long off; | ||
984 | u32 len; | ||
985 | |||
986 | if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) { | ||
987 | off = vma->vm_pgoff << PAGE_SHIFT; | ||
988 | start = map->phys; | ||
989 | len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size); | ||
990 | start &= PAGE_MASK; | ||
991 | if ((vma->vm_end - vma->vm_start + off) > len) | ||
992 | return -EINVAL; | ||
993 | |||
994 | off += start; | ||
995 | vma->vm_pgoff = off >> PAGE_SHIFT; | ||
996 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
997 | |||
998 | #ifdef pgprot_noncached | ||
999 | if (file->f_flags & O_DSYNC || off >= __pa(high_memory)) | ||
1000 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
1001 | #endif | ||
1002 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | ||
1003 | vma->vm_end - vma->vm_start, | ||
1004 | vma->vm_page_prot)) | ||
1005 | return -EAGAIN; | ||
953 | 1006 | ||
954 | if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) | ||
955 | return 0; | 1007 | return 0; |
1008 | } | ||
956 | return -ENOSYS; | 1009 | return -ENOSYS; |
957 | #else | 1010 | #else |
958 | return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; | 1011 | return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; |
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 7e075621bbf4..bf8de0943103 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -1,11 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * MTD device concatenation layer | 2 | * MTD device concatenation layer |
3 | * | 3 | * |
4 | * (C) 2002 Robert Kaiser <rkaiser@sysgo.de> | 4 | * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de> |
5 | * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * NAND support by Christian Gan <cgan@iders.ca> | 7 | * NAND support by Christian Gan <cgan@iders.ca> |
7 | * | 8 | * |
8 | * This code is GPL | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | * | ||
9 | */ | 23 | */ |
10 | 24 | ||
11 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
@@ -540,10 +554,12 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
540 | else | 554 | else |
541 | size = len; | 555 | size = len; |
542 | 556 | ||
543 | err = subdev->lock(subdev, ofs, size); | 557 | if (subdev->lock) { |
544 | 558 | err = subdev->lock(subdev, ofs, size); | |
545 | if (err) | 559 | if (err) |
546 | break; | 560 | break; |
561 | } else | ||
562 | err = -EOPNOTSUPP; | ||
547 | 563 | ||
548 | len -= size; | 564 | len -= size; |
549 | if (len == 0) | 565 | if (len == 0) |
@@ -578,10 +594,12 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
578 | else | 594 | else |
579 | size = len; | 595 | size = len; |
580 | 596 | ||
581 | err = subdev->unlock(subdev, ofs, size); | 597 | if (subdev->unlock) { |
582 | 598 | err = subdev->unlock(subdev, ofs, size); | |
583 | if (err) | 599 | if (err) |
584 | break; | 600 | break; |
601 | } else | ||
602 | err = -EOPNOTSUPP; | ||
585 | 603 | ||
586 | len -= size; | 604 | len -= size; |
587 | if (len == 0) | 605 | if (len == 0) |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index a1b8b70d2d0a..527cebf58da4 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -2,9 +2,23 @@ | |||
2 | * Core registration and callback routines for MTD | 2 | * Core registration and callback routines for MTD |
3 | * drivers and users. | 3 | * drivers and users. |
4 | * | 4 | * |
5 | * bdi bits are: | 5 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
6 | * Copyright © 2006 Red Hat, Inc. All Rights Reserved. | 6 | * Copyright © 2006 Red Hat UK Limited |
7 | * Written by David Howells (dhowells@redhat.com) | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | * | ||
8 | */ | 22 | */ |
9 | 23 | ||
10 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -17,7 +31,6 @@ | |||
17 | #include <linux/err.h> | 31 | #include <linux/err.h> |
18 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
19 | #include <linux/init.h> | 33 | #include <linux/init.h> |
20 | #include <linux/mtd/compatmac.h> | ||
21 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
22 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
23 | #include <linux/backing-dev.h> | 36 | #include <linux/backing-dev.h> |
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 328313c3dccb..1ee72f3f0512 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MTD Oops/Panic logger | 2 | * MTD Oops/Panic logger |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Nokia Corporation. All rights reserved. | 4 | * Copyright © 2007 Nokia Corporation. All rights reserved. |
5 | * | 5 | * |
6 | * Author: Richard Purdie <rpurdie@openedhand.com> | 6 | * Author: Richard Purdie <rpurdie@openedhand.com> |
7 | * | 7 | * |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b8043a9ba32d..dc6558568876 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -1,12 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Simple MTD partitioning layer | 2 | * Simple MTD partitioning layer |
3 | * | 3 | * |
4 | * (C) 2000 Nicolas Pitre <nico@fluxnic.net> | 4 | * Copyright © 2000 Nicolas Pitre <nico@fluxnic.net> |
5 | * Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de> | ||
6 | * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 7 | * |
6 | * This code is GPL | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
7 | * | 21 | * |
8 | * 02-21-2002 Thomas Gleixner <gleixner@autronix.de> | ||
9 | * added support for read_oob, write_oob | ||
10 | */ | 22 | */ |
11 | 23 | ||
12 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -17,7 +29,6 @@ | |||
17 | #include <linux/kmod.h> | 29 | #include <linux/kmod.h> |
18 | #include <linux/mtd/mtd.h> | 30 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
20 | #include <linux/mtd/compatmac.h> | ||
21 | 32 | ||
22 | /* Our partition linked list */ | 33 | /* Our partition linked list */ |
23 | static LIST_HEAD(mtd_partitions); | 34 | static LIST_HEAD(mtd_partitions); |
@@ -264,6 +275,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
264 | return part->master->unlock(part->master, ofs + part->offset, len); | 275 | return part->master->unlock(part->master, ofs + part->offset, len); |
265 | } | 276 | } |
266 | 277 | ||
278 | static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
279 | { | ||
280 | struct mtd_part *part = PART(mtd); | ||
281 | if ((len + ofs) > mtd->size) | ||
282 | return -EINVAL; | ||
283 | return part->master->is_locked(part->master, ofs + part->offset, len); | ||
284 | } | ||
285 | |||
267 | static void part_sync(struct mtd_info *mtd) | 286 | static void part_sync(struct mtd_info *mtd) |
268 | { | 287 | { |
269 | struct mtd_part *part = PART(mtd); | 288 | struct mtd_part *part = PART(mtd); |
@@ -402,6 +421,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
402 | slave->mtd.lock = part_lock; | 421 | slave->mtd.lock = part_lock; |
403 | if (master->unlock) | 422 | if (master->unlock) |
404 | slave->mtd.unlock = part_unlock; | 423 | slave->mtd.unlock = part_unlock; |
424 | if (master->is_locked) | ||
425 | slave->mtd.is_locked = part_is_locked; | ||
405 | if (master->block_isbad) | 426 | if (master->block_isbad) |
406 | slave->mtd.block_isbad = part_block_isbad; | 427 | slave->mtd.block_isbad = part_block_isbad; |
407 | if (master->block_markbad) | 428 | if (master->block_markbad) |
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index bd9a443ccf69..38e2ab07e7a3 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* MTD-based superblock management | 1 | /* MTD-based superblock management |
2 | * | 2 | * |
3 | * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved. |
4 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | ||
4 | * Written by: David Howells <dhowells@redhat.com> | 6 | * Written by: David Howells <dhowells@redhat.com> |
5 | * David Woodhouse <dwmw2@infradead.org> | 7 | * David Woodhouse <dwmw2@infradead.org> |
6 | * | 8 | * |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 362d177efe1b..8b4b67c8a391 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -37,7 +37,6 @@ config MTD_SM_COMMON | |||
37 | 37 | ||
38 | config MTD_NAND_MUSEUM_IDS | 38 | config MTD_NAND_MUSEUM_IDS |
39 | bool "Enable chip ids for obsolete ancient NAND devices" | 39 | bool "Enable chip ids for obsolete ancient NAND devices" |
40 | depends on MTD_NAND | ||
41 | default n | 40 | default n |
42 | help | 41 | help |
43 | Enable this option only when your board has first generation | 42 | Enable this option only when your board has first generation |
@@ -61,6 +60,7 @@ config MTD_NAND_DENALI | |||
61 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR | 60 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR |
62 | hex "Denali NAND size scratch register address" | 61 | hex "Denali NAND size scratch register address" |
63 | default "0xFF108018" | 62 | default "0xFF108018" |
63 | depends on MTD_NAND_DENALI | ||
64 | help | 64 | help |
65 | Some platforms place the NAND chip size in a scratch register | 65 | Some platforms place the NAND chip size in a scratch register |
66 | because (some versions of) the driver aren't able to automatically | 66 | because (some versions of) the driver aren't able to automatically |
@@ -101,13 +101,13 @@ config MTD_NAND_AMS_DELTA | |||
101 | 101 | ||
102 | config MTD_NAND_OMAP2 | 102 | config MTD_NAND_OMAP2 |
103 | tristate "NAND Flash device on OMAP2 and OMAP3" | 103 | tristate "NAND Flash device on OMAP2 and OMAP3" |
104 | depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3) | 104 | depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3) |
105 | help | 105 | help |
106 | Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. | 106 | Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. |
107 | 107 | ||
108 | config MTD_NAND_OMAP_PREFETCH | 108 | config MTD_NAND_OMAP_PREFETCH |
109 | bool "GPMC prefetch support for NAND Flash device" | 109 | bool "GPMC prefetch support for NAND Flash device" |
110 | depends on MTD_NAND && MTD_NAND_OMAP2 | 110 | depends on MTD_NAND_OMAP2 |
111 | default y | 111 | default y |
112 | help | 112 | help |
113 | The NAND device can be accessed for Read/Write using GPMC PREFETCH engine | 113 | The NAND device can be accessed for Read/Write using GPMC PREFETCH engine |
@@ -146,7 +146,7 @@ config MTD_NAND_AU1550 | |||
146 | 146 | ||
147 | config MTD_NAND_BF5XX | 147 | config MTD_NAND_BF5XX |
148 | tristate "Blackfin on-chip NAND Flash Controller driver" | 148 | tristate "Blackfin on-chip NAND Flash Controller driver" |
149 | depends on (BF54x || BF52x) && MTD_NAND | 149 | depends on BF54x || BF52x |
150 | help | 150 | help |
151 | This enables the Blackfin on-chip NAND flash controller | 151 | This enables the Blackfin on-chip NAND flash controller |
152 | 152 | ||
@@ -236,7 +236,7 @@ config MTD_NAND_S3C2410_CLKSTOP | |||
236 | 236 | ||
237 | config MTD_NAND_BCM_UMI | 237 | config MTD_NAND_BCM_UMI |
238 | tristate "NAND Flash support for BCM Reference Boards" | 238 | tristate "NAND Flash support for BCM Reference Boards" |
239 | depends on ARCH_BCMRING && MTD_NAND | 239 | depends on ARCH_BCMRING |
240 | help | 240 | help |
241 | This enables the NAND flash controller on the BCM UMI block. | 241 | This enables the NAND flash controller on the BCM UMI block. |
242 | 242 | ||
@@ -395,7 +395,7 @@ endchoice | |||
395 | 395 | ||
396 | config MTD_NAND_PXA3xx | 396 | config MTD_NAND_PXA3xx |
397 | tristate "Support for NAND flash devices on PXA3xx" | 397 | tristate "Support for NAND flash devices on PXA3xx" |
398 | depends on MTD_NAND && (PXA3xx || ARCH_MMP) | 398 | depends on PXA3xx || ARCH_MMP |
399 | help | 399 | help |
400 | This enables the driver for the NAND flash device found on | 400 | This enables the driver for the NAND flash device found on |
401 | PXA3xx processors | 401 | PXA3xx processors |
@@ -409,18 +409,18 @@ config MTD_NAND_PXA3xx_BUILTIN | |||
409 | 409 | ||
410 | config MTD_NAND_CM_X270 | 410 | config MTD_NAND_CM_X270 |
411 | tristate "Support for NAND Flash on CM-X270 modules" | 411 | tristate "Support for NAND Flash on CM-X270 modules" |
412 | depends on MTD_NAND && MACH_ARMCORE | 412 | depends on MACH_ARMCORE |
413 | 413 | ||
414 | config MTD_NAND_PASEMI | 414 | config MTD_NAND_PASEMI |
415 | tristate "NAND support for PA Semi PWRficient" | 415 | tristate "NAND support for PA Semi PWRficient" |
416 | depends on MTD_NAND && PPC_PASEMI | 416 | depends on PPC_PASEMI |
417 | help | 417 | help |
418 | Enables support for NAND Flash interface on PA Semi PWRficient | 418 | Enables support for NAND Flash interface on PA Semi PWRficient |
419 | based boards | 419 | based boards |
420 | 420 | ||
421 | config MTD_NAND_TMIO | 421 | config MTD_NAND_TMIO |
422 | tristate "NAND Flash device on Toshiba Mobile IO Controller" | 422 | tristate "NAND Flash device on Toshiba Mobile IO Controller" |
423 | depends on MTD_NAND && MFD_TMIO | 423 | depends on MFD_TMIO |
424 | help | 424 | help |
425 | Support for NAND flash connected to a Toshiba Mobile IO | 425 | Support for NAND flash connected to a Toshiba Mobile IO |
426 | Controller in some PDAs, including the Sharp SL6000x. | 426 | Controller in some PDAs, including the Sharp SL6000x. |
@@ -434,7 +434,6 @@ config MTD_NAND_NANDSIM | |||
434 | 434 | ||
435 | config MTD_NAND_PLATFORM | 435 | config MTD_NAND_PLATFORM |
436 | tristate "Support for generic platform NAND driver" | 436 | tristate "Support for generic platform NAND driver" |
437 | depends on MTD_NAND | ||
438 | help | 437 | help |
439 | This implements a generic NAND driver for on-SOC platform | 438 | This implements a generic NAND driver for on-SOC platform |
440 | devices. You will need to provide platform-specific functions | 439 | devices. You will need to provide platform-specific functions |
@@ -442,14 +441,14 @@ config MTD_NAND_PLATFORM | |||
442 | 441 | ||
443 | config MTD_ALAUDA | 442 | config MTD_ALAUDA |
444 | tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1" | 443 | tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1" |
445 | depends on MTD_NAND && USB | 444 | depends on USB |
446 | help | 445 | help |
447 | These two (and possibly other) Alauda-based cardreaders for | 446 | These two (and possibly other) Alauda-based cardreaders for |
448 | SmartMedia and xD allow raw flash access. | 447 | SmartMedia and xD allow raw flash access. |
449 | 448 | ||
450 | config MTD_NAND_ORION | 449 | config MTD_NAND_ORION |
451 | tristate "NAND Flash support for Marvell Orion SoC" | 450 | tristate "NAND Flash support for Marvell Orion SoC" |
452 | depends on PLAT_ORION && MTD_NAND | 451 | depends on PLAT_ORION |
453 | help | 452 | help |
454 | This enables the NAND flash controller on Orion machines. | 453 | This enables the NAND flash controller on Orion machines. |
455 | 454 | ||
@@ -458,7 +457,7 @@ config MTD_NAND_ORION | |||
458 | 457 | ||
459 | config MTD_NAND_FSL_ELBC | 458 | config MTD_NAND_FSL_ELBC |
460 | tristate "NAND support for Freescale eLBC controllers" | 459 | tristate "NAND support for Freescale eLBC controllers" |
461 | depends on MTD_NAND && PPC_OF | 460 | depends on PPC_OF |
462 | help | 461 | help |
463 | Various Freescale chips, including the 8313, include a NAND Flash | 462 | Various Freescale chips, including the 8313, include a NAND Flash |
464 | Controller Module with built-in hardware ECC capabilities. | 463 | Controller Module with built-in hardware ECC capabilities. |
@@ -467,7 +466,7 @@ config MTD_NAND_FSL_ELBC | |||
467 | 466 | ||
468 | config MTD_NAND_FSL_UPM | 467 | config MTD_NAND_FSL_UPM |
469 | tristate "Support for NAND on Freescale UPM" | 468 | tristate "Support for NAND on Freescale UPM" |
470 | depends on MTD_NAND && (PPC_83xx || PPC_85xx) | 469 | depends on PPC_83xx || PPC_85xx |
471 | select FSL_LBC | 470 | select FSL_LBC |
472 | help | 471 | help |
473 | Enables support for NAND Flash chips wired onto Freescale PowerPC | 472 | Enables support for NAND Flash chips wired onto Freescale PowerPC |
@@ -482,7 +481,7 @@ config MTD_NAND_MPC5121_NFC | |||
482 | 481 | ||
483 | config MTD_NAND_MXC | 482 | config MTD_NAND_MXC |
484 | tristate "MXC NAND support" | 483 | tristate "MXC NAND support" |
485 | depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 | 484 | depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51 |
486 | help | 485 | help |
487 | This enables the driver for the NAND flash controller on the | 486 | This enables the driver for the NAND flash controller on the |
488 | MXC processors. | 487 | MXC processors. |
@@ -495,7 +494,7 @@ config MTD_NAND_NOMADIK | |||
495 | 494 | ||
496 | config MTD_NAND_SH_FLCTL | 495 | config MTD_NAND_SH_FLCTL |
497 | tristate "Support for NAND on Renesas SuperH FLCTL" | 496 | tristate "Support for NAND on Renesas SuperH FLCTL" |
498 | depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE) | 497 | depends on SUPERH || ARCH_SHMOBILE |
499 | help | 498 | help |
500 | Several Renesas SuperH CPU has FLCTL. This option enables support | 499 | Several Renesas SuperH CPU has FLCTL. This option enables support |
501 | for NAND Flash using FLCTL. | 500 | for NAND Flash using FLCTL. |
@@ -515,7 +514,7 @@ config MTD_NAND_TXX9NDFMC | |||
515 | 514 | ||
516 | config MTD_NAND_SOCRATES | 515 | config MTD_NAND_SOCRATES |
517 | tristate "Support for NAND on Socrates board" | 516 | tristate "Support for NAND on Socrates board" |
518 | depends on MTD_NAND && SOCRATES | 517 | depends on SOCRATES |
519 | help | 518 | help |
520 | Enables support for NAND Flash chips wired onto Socrates board. | 519 | Enables support for NAND Flash chips wired onto Socrates board. |
521 | 520 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 04d30887ca7f..ccce0f03b5dc 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -364,7 +364,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
364 | } | 364 | } |
365 | } | 365 | } |
366 | 366 | ||
367 | #ifdef CONFIG_MTD_PARTITIONS | 367 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
368 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 368 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
369 | #endif | 369 | #endif |
370 | 370 | ||
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 2974995e194d..a382e3dd0a5d 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -20,9 +20,6 @@ | |||
20 | * - DMA supported in ECC_HW | 20 | * - DMA supported in ECC_HW |
21 | * - YAFFS tested as rootfs in both ECC_HW and ECC_SW | 21 | * - YAFFS tested as rootfs in both ECC_HW and ECC_SW |
22 | * | 22 | * |
23 | * TODO: | ||
24 | * Enable JFFS2 over NAND as rootfs | ||
25 | * | ||
26 | * This program is free software; you can redistribute it and/or modify | 23 | * This program is free software; you can redistribute it and/or modify |
27 | * it under the terms of the GNU General Public License as published by | 24 | * it under the terms of the GNU General Public License as published by |
28 | * the Free Software Foundation; either version 2 of the License, or | 25 | * the Free Software Foundation; either version 2 of the License, or |
@@ -206,7 +203,7 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd, | |||
206 | 203 | ||
207 | if (ctrl & NAND_CLE) | 204 | if (ctrl & NAND_CLE) |
208 | bfin_write_NFC_CMD(cmd); | 205 | bfin_write_NFC_CMD(cmd); |
209 | else | 206 | else if (ctrl & NAND_ALE) |
210 | bfin_write_NFC_ADDR(cmd); | 207 | bfin_write_NFC_ADDR(cmd); |
211 | SSYNC(); | 208 | SSYNC(); |
212 | } | 209 | } |
@@ -218,9 +215,9 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd, | |||
218 | */ | 215 | */ |
219 | static int bf5xx_nand_devready(struct mtd_info *mtd) | 216 | static int bf5xx_nand_devready(struct mtd_info *mtd) |
220 | { | 217 | { |
221 | unsigned short val = bfin_read_NFC_IRQSTAT(); | 218 | unsigned short val = bfin_read_NFC_STAT(); |
222 | 219 | ||
223 | if ((val & NBUSYIRQ) == NBUSYIRQ) | 220 | if ((val & NBUSY) == NBUSY) |
224 | return 1; | 221 | return 1; |
225 | else | 222 | else |
226 | return 0; | 223 | return 0; |
@@ -317,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, | |||
317 | static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, | 314 | static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, |
318 | u_char *read_ecc, u_char *calc_ecc) | 315 | u_char *read_ecc, u_char *calc_ecc) |
319 | { | 316 | { |
320 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 317 | struct nand_chip *chip = mtd->priv; |
321 | struct bf5xx_nand_platform *plat = info->platform; | ||
322 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
323 | int ret; | 318 | int ret; |
324 | 319 | ||
325 | ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); | 320 | ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); |
326 | 321 | ||
327 | /* If page size is 512, correct second 256 bytes */ | 322 | /* If ecc size is 512, correct second 256 bytes */ |
328 | if (page_size == 512) { | 323 | if (chip->ecc.size == 512) { |
329 | dat += 256; | 324 | dat += 256; |
330 | read_ecc += 8; | 325 | read_ecc += 3; |
331 | calc_ecc += 8; | 326 | calc_ecc += 3; |
332 | ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); | 327 | ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); |
333 | } | 328 | } |
334 | 329 | ||
@@ -344,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, | |||
344 | const u_char *dat, u_char *ecc_code) | 339 | const u_char *dat, u_char *ecc_code) |
345 | { | 340 | { |
346 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 341 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
347 | struct bf5xx_nand_platform *plat = info->platform; | 342 | struct nand_chip *chip = mtd->priv; |
348 | u16 page_size = (plat->page_size ? 512 : 256); | ||
349 | u16 ecc0, ecc1; | 343 | u16 ecc0, ecc1; |
350 | u32 code[2]; | 344 | u32 code[2]; |
351 | u8 *p; | 345 | u8 *p; |
352 | 346 | ||
353 | /* first 4 bytes ECC code for 256 page size */ | 347 | /* first 3 bytes ECC code for 256 page size */ |
354 | ecc0 = bfin_read_NFC_ECC0(); | 348 | ecc0 = bfin_read_NFC_ECC0(); |
355 | ecc1 = bfin_read_NFC_ECC1(); | 349 | ecc1 = bfin_read_NFC_ECC1(); |
356 | 350 | ||
@@ -358,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, | |||
358 | 352 | ||
359 | dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); | 353 | dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); |
360 | 354 | ||
361 | /* first 3 bytes in ecc_code for 256 page size */ | ||
362 | p = (u8 *) code; | 355 | p = (u8 *) code; |
363 | memcpy(ecc_code, p, 3); | 356 | memcpy(ecc_code, p, 3); |
364 | 357 | ||
365 | /* second 4 bytes ECC code for 512 page size */ | 358 | /* second 3 bytes ECC code for 512 ecc size */ |
366 | if (page_size == 512) { | 359 | if (chip->ecc.size == 512) { |
367 | ecc0 = bfin_read_NFC_ECC2(); | 360 | ecc0 = bfin_read_NFC_ECC2(); |
368 | ecc1 = bfin_read_NFC_ECC3(); | 361 | ecc1 = bfin_read_NFC_ECC3(); |
369 | code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); | 362 | code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); |
@@ -483,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
483 | uint8_t *buf, int is_read) | 476 | uint8_t *buf, int is_read) |
484 | { | 477 | { |
485 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 478 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
486 | struct bf5xx_nand_platform *plat = info->platform; | 479 | struct nand_chip *chip = mtd->priv; |
487 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
488 | unsigned short val; | 480 | unsigned short val; |
489 | 481 | ||
490 | dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", | 482 | dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", |
@@ -498,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
498 | */ | 490 | */ |
499 | if (is_read) | 491 | if (is_read) |
500 | invalidate_dcache_range((unsigned int)buf, | 492 | invalidate_dcache_range((unsigned int)buf, |
501 | (unsigned int)(buf + page_size)); | 493 | (unsigned int)(buf + chip->ecc.size)); |
502 | else | 494 | else |
503 | flush_dcache_range((unsigned int)buf, | 495 | flush_dcache_range((unsigned int)buf, |
504 | (unsigned int)(buf + page_size)); | 496 | (unsigned int)(buf + chip->ecc.size)); |
505 | 497 | ||
506 | /* | 498 | /* |
507 | * This register must be written before each page is | 499 | * This register must be written before each page is |
@@ -510,6 +502,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
510 | */ | 502 | */ |
511 | bfin_write_NFC_RST(ECC_RST); | 503 | bfin_write_NFC_RST(ECC_RST); |
512 | SSYNC(); | 504 | SSYNC(); |
505 | while (bfin_read_NFC_RST() & ECC_RST) | ||
506 | cpu_relax(); | ||
513 | 507 | ||
514 | disable_dma(CH_NFC); | 508 | disable_dma(CH_NFC); |
515 | clear_dma_irqstat(CH_NFC); | 509 | clear_dma_irqstat(CH_NFC); |
@@ -520,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
520 | 514 | ||
521 | /* The DMAs have different size on BF52x and BF54x */ | 515 | /* The DMAs have different size on BF52x and BF54x */ |
522 | #ifdef CONFIG_BF52x | 516 | #ifdef CONFIG_BF52x |
523 | set_dma_x_count(CH_NFC, (page_size >> 1)); | 517 | set_dma_x_count(CH_NFC, (chip->ecc.size >> 1)); |
524 | set_dma_x_modify(CH_NFC, 2); | 518 | set_dma_x_modify(CH_NFC, 2); |
525 | val = DI_EN | WDSIZE_16; | 519 | val = DI_EN | WDSIZE_16; |
526 | #endif | 520 | #endif |
527 | 521 | ||
528 | #ifdef CONFIG_BF54x | 522 | #ifdef CONFIG_BF54x |
529 | set_dma_x_count(CH_NFC, (page_size >> 2)); | 523 | set_dma_x_count(CH_NFC, (chip->ecc.size >> 2)); |
530 | set_dma_x_modify(CH_NFC, 4); | 524 | set_dma_x_modify(CH_NFC, 4); |
531 | val = DI_EN | WDSIZE_32; | 525 | val = DI_EN | WDSIZE_32; |
532 | #endif | 526 | #endif |
@@ -548,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd, | |||
548 | uint8_t *buf, int len) | 542 | uint8_t *buf, int len) |
549 | { | 543 | { |
550 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 544 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
551 | struct bf5xx_nand_platform *plat = info->platform; | 545 | struct nand_chip *chip = mtd->priv; |
552 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
553 | 546 | ||
554 | dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); | 547 | dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); |
555 | 548 | ||
556 | if (len == page_size) | 549 | if (len == chip->ecc.size) |
557 | bf5xx_nand_dma_rw(mtd, buf, 1); | 550 | bf5xx_nand_dma_rw(mtd, buf, 1); |
558 | else | 551 | else |
559 | bf5xx_nand_read_buf(mtd, buf, len); | 552 | bf5xx_nand_read_buf(mtd, buf, len); |
@@ -563,17 +556,32 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, | |||
563 | const uint8_t *buf, int len) | 556 | const uint8_t *buf, int len) |
564 | { | 557 | { |
565 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 558 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
566 | struct bf5xx_nand_platform *plat = info->platform; | 559 | struct nand_chip *chip = mtd->priv; |
567 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
568 | 560 | ||
569 | dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); | 561 | dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); |
570 | 562 | ||
571 | if (len == page_size) | 563 | if (len == chip->ecc.size) |
572 | bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); | 564 | bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); |
573 | else | 565 | else |
574 | bf5xx_nand_write_buf(mtd, buf, len); | 566 | bf5xx_nand_write_buf(mtd, buf, len); |
575 | } | 567 | } |
576 | 568 | ||
569 | static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
570 | uint8_t *buf, int page) | ||
571 | { | ||
572 | bf5xx_nand_read_buf(mtd, buf, mtd->writesize); | ||
573 | bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
579 | const uint8_t *buf) | ||
580 | { | ||
581 | bf5xx_nand_write_buf(mtd, buf, mtd->writesize); | ||
582 | bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
583 | } | ||
584 | |||
577 | /* | 585 | /* |
578 | * System initialization functions | 586 | * System initialization functions |
579 | */ | 587 | */ |
@@ -627,15 +635,14 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) | |||
627 | 635 | ||
628 | /* setup NFC_CTL register */ | 636 | /* setup NFC_CTL register */ |
629 | dev_info(info->device, | 637 | dev_info(info->device, |
630 | "page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n", | 638 | "data_width=%d, wr_dly=%d, rd_dly=%d\n", |
631 | (plat->page_size ? 512 : 256), | ||
632 | (plat->data_width ? 16 : 8), | 639 | (plat->data_width ? 16 : 8), |
633 | plat->wr_dly, plat->rd_dly); | 640 | plat->wr_dly, plat->rd_dly); |
634 | 641 | ||
635 | val = (plat->page_size << NFC_PG_SIZE_OFFSET) | | 642 | val = (1 << NFC_PG_SIZE_OFFSET) | |
636 | (plat->data_width << NFC_NWIDTH_OFFSET) | | 643 | (plat->data_width << NFC_NWIDTH_OFFSET) | |
637 | (plat->rd_dly << NFC_RDDLY_OFFSET) | | 644 | (plat->rd_dly << NFC_RDDLY_OFFSET) | |
638 | (plat->rd_dly << NFC_WRDLY_OFFSET); | 645 | (plat->wr_dly << NFC_WRDLY_OFFSET); |
639 | dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val); | 646 | dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val); |
640 | 647 | ||
641 | bfin_write_NFC_CTL(val); | 648 | bfin_write_NFC_CTL(val); |
@@ -698,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | |||
698 | return 0; | 705 | return 0; |
699 | } | 706 | } |
700 | 707 | ||
708 | static int bf5xx_nand_scan(struct mtd_info *mtd) | ||
709 | { | ||
710 | struct nand_chip *chip = mtd->priv; | ||
711 | int ret; | ||
712 | |||
713 | ret = nand_scan_ident(mtd, 1); | ||
714 | if (ret) | ||
715 | return ret; | ||
716 | |||
717 | if (hardware_ecc) { | ||
718 | /* | ||
719 | * for nand with page size > 512B, think it as several sections with 512B | ||
720 | */ | ||
721 | if (likely(mtd->writesize >= 512)) { | ||
722 | chip->ecc.size = 512; | ||
723 | chip->ecc.bytes = 6; | ||
724 | } else { | ||
725 | chip->ecc.size = 256; | ||
726 | chip->ecc.bytes = 3; | ||
727 | bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET)); | ||
728 | SSYNC(); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | return nand_scan_tail(mtd); | ||
733 | } | ||
734 | |||
701 | /* | 735 | /* |
702 | * bf5xx_nand_probe | 736 | * bf5xx_nand_probe |
703 | * | 737 | * |
@@ -783,27 +817,20 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | |||
783 | chip->badblock_pattern = &bootrom_bbt; | 817 | chip->badblock_pattern = &bootrom_bbt; |
784 | chip->ecc.layout = &bootrom_ecclayout; | 818 | chip->ecc.layout = &bootrom_ecclayout; |
785 | #endif | 819 | #endif |
786 | |||
787 | if (plat->page_size == NFC_PG_SIZE_256) { | ||
788 | chip->ecc.bytes = 3; | ||
789 | chip->ecc.size = 256; | ||
790 | } else if (plat->page_size == NFC_PG_SIZE_512) { | ||
791 | chip->ecc.bytes = 6; | ||
792 | chip->ecc.size = 512; | ||
793 | } | ||
794 | |||
795 | chip->read_buf = bf5xx_nand_dma_read_buf; | 820 | chip->read_buf = bf5xx_nand_dma_read_buf; |
796 | chip->write_buf = bf5xx_nand_dma_write_buf; | 821 | chip->write_buf = bf5xx_nand_dma_write_buf; |
797 | chip->ecc.calculate = bf5xx_nand_calculate_ecc; | 822 | chip->ecc.calculate = bf5xx_nand_calculate_ecc; |
798 | chip->ecc.correct = bf5xx_nand_correct_data; | 823 | chip->ecc.correct = bf5xx_nand_correct_data; |
799 | chip->ecc.mode = NAND_ECC_HW; | 824 | chip->ecc.mode = NAND_ECC_HW; |
800 | chip->ecc.hwctl = bf5xx_nand_enable_hwecc; | 825 | chip->ecc.hwctl = bf5xx_nand_enable_hwecc; |
826 | chip->ecc.read_page_raw = bf5xx_nand_read_page_raw; | ||
827 | chip->ecc.write_page_raw = bf5xx_nand_write_page_raw; | ||
801 | } else { | 828 | } else { |
802 | chip->ecc.mode = NAND_ECC_SOFT; | 829 | chip->ecc.mode = NAND_ECC_SOFT; |
803 | } | 830 | } |
804 | 831 | ||
805 | /* scan hardware nand chip and setup mtd info data struct */ | 832 | /* scan hardware nand chip and setup mtd info data struct */ |
806 | if (nand_scan(mtd, 1)) { | 833 | if (bf5xx_nand_scan(mtd)) { |
807 | err = -ENXIO; | 834 | err = -ENXIO; |
808 | goto out_err_nand_scan; | 835 | goto out_err_nand_scan; |
809 | } | 836 | } |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 9c9d893affeb..2ac7367afe77 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -311,7 +311,9 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, | |||
311 | unsigned short ecc10[8]; | 311 | unsigned short ecc10[8]; |
312 | unsigned short *ecc16; | 312 | unsigned short *ecc16; |
313 | u32 syndrome[4]; | 313 | u32 syndrome[4]; |
314 | u32 ecc_state; | ||
314 | unsigned num_errors, corrected; | 315 | unsigned num_errors, corrected; |
316 | unsigned long timeo = jiffies + msecs_to_jiffies(100); | ||
315 | 317 | ||
316 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ | 318 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ |
317 | for (i = 0; i < 10; i++) { | 319 | for (i = 0; i < 10; i++) { |
@@ -361,6 +363,21 @@ compare: | |||
361 | */ | 363 | */ |
362 | davinci_nand_writel(info, NANDFCR_OFFSET, | 364 | davinci_nand_writel(info, NANDFCR_OFFSET, |
363 | davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); | 365 | davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); |
366 | |||
367 | /* | ||
368 | * ECC_STATE field reads 0x3 (Error correction complete) immediately | ||
369 | * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately | ||
370 | * begin trying to poll for the state, you may fall right out of your | ||
371 | * loop without any of the correction calculations having taken place. | ||
372 | * The recommendation from the hardware team is to wait till ECC_STATE | ||
373 | * reads less than 4, which means ECC HW has entered correction state. | ||
374 | */ | ||
375 | do { | ||
376 | ecc_state = (davinci_nand_readl(info, | ||
377 | NANDFSR_OFFSET) >> 8) & 0x0f; | ||
378 | cpu_relax(); | ||
379 | } while ((ecc_state < 4) && time_before(jiffies, timeo)); | ||
380 | |||
364 | for (;;) { | 381 | for (;;) { |
365 | u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); | 382 | u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); |
366 | 383 | ||
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 3dfda9cc677d..618fb42b86b0 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
25 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
@@ -29,15 +30,15 @@ | |||
29 | 30 | ||
30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
31 | 32 | ||
32 | /* We define a module parameter that allows the user to override | 33 | /* We define a module parameter that allows the user to override |
33 | * the hardware and decide what timing mode should be used. | 34 | * the hardware and decide what timing mode should be used. |
34 | */ | 35 | */ |
35 | #define NAND_DEFAULT_TIMINGS -1 | 36 | #define NAND_DEFAULT_TIMINGS -1 |
36 | 37 | ||
37 | static int onfi_timing_mode = NAND_DEFAULT_TIMINGS; | 38 | static int onfi_timing_mode = NAND_DEFAULT_TIMINGS; |
38 | module_param(onfi_timing_mode, int, S_IRUGO); | 39 | module_param(onfi_timing_mode, int, S_IRUGO); |
39 | MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates" | 40 | MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." |
40 | " use default timings"); | 41 | " -1 indicates use default timings"); |
41 | 42 | ||
42 | #define DENALI_NAND_NAME "denali-nand" | 43 | #define DENALI_NAND_NAME "denali-nand" |
43 | 44 | ||
@@ -54,13 +55,13 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates | |||
54 | INTR_STATUS0__RST_COMP | \ | 55 | INTR_STATUS0__RST_COMP | \ |
55 | INTR_STATUS0__ERASE_COMP) | 56 | INTR_STATUS0__ERASE_COMP) |
56 | 57 | ||
57 | /* indicates whether or not the internal value for the flash bank is | 58 | /* indicates whether or not the internal value for the flash bank is |
58 | valid or not */ | 59 | valid or not */ |
59 | #define CHIP_SELECT_INVALID -1 | 60 | #define CHIP_SELECT_INVALID -1 |
60 | 61 | ||
61 | #define SUPPORT_8BITECC 1 | 62 | #define SUPPORT_8BITECC 1 |
62 | 63 | ||
63 | /* This macro divides two integers and rounds fractional values up | 64 | /* This macro divides two integers and rounds fractional values up |
64 | * to the nearest integer value. */ | 65 | * to the nearest integer value. */ |
65 | #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) | 66 | #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) |
66 | 67 | ||
@@ -83,7 +84,7 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates | |||
83 | #define ADDR_CYCLE 1 | 84 | #define ADDR_CYCLE 1 |
84 | #define STATUS_CYCLE 2 | 85 | #define STATUS_CYCLE 2 |
85 | 86 | ||
86 | /* this is a helper macro that allows us to | 87 | /* this is a helper macro that allows us to |
87 | * format the bank into the proper bits for the controller */ | 88 | * format the bank into the proper bits for the controller */ |
88 | #define BANK(x) ((x) << 24) | 89 | #define BANK(x) ((x) << 24) |
89 | 90 | ||
@@ -95,59 +96,64 @@ static const struct pci_device_id denali_pci_ids[] = { | |||
95 | }; | 96 | }; |
96 | 97 | ||
97 | 98 | ||
98 | /* these are static lookup tables that give us easy access to | 99 | /* these are static lookup tables that give us easy access to |
99 | registers in the NAND controller. | 100 | registers in the NAND controller. |
100 | */ | 101 | */ |
101 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, | 102 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, |
102 | INTR_STATUS1, | 103 | INTR_STATUS1, |
103 | INTR_STATUS2, | 104 | INTR_STATUS2, |
104 | INTR_STATUS3}; | 105 | INTR_STATUS3}; |
105 | 106 | ||
106 | static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0, | 107 | static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0, |
107 | DEVICE_RESET__BANK1, | 108 | DEVICE_RESET__BANK1, |
108 | DEVICE_RESET__BANK2, | 109 | DEVICE_RESET__BANK2, |
109 | DEVICE_RESET__BANK3}; | 110 | DEVICE_RESET__BANK3}; |
110 | 111 | ||
111 | static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT, | 112 | static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT, |
112 | INTR_STATUS1__TIME_OUT, | 113 | INTR_STATUS1__TIME_OUT, |
113 | INTR_STATUS2__TIME_OUT, | 114 | INTR_STATUS2__TIME_OUT, |
114 | INTR_STATUS3__TIME_OUT}; | 115 | INTR_STATUS3__TIME_OUT}; |
115 | 116 | ||
116 | static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP, | 117 | static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP, |
117 | INTR_STATUS1__RST_COMP, | 118 | INTR_STATUS1__RST_COMP, |
118 | INTR_STATUS2__RST_COMP, | 119 | INTR_STATUS2__RST_COMP, |
119 | INTR_STATUS3__RST_COMP}; | 120 | INTR_STATUS3__RST_COMP}; |
120 | 121 | ||
121 | /* specifies the debug level of the driver */ | 122 | /* specifies the debug level of the driver */ |
122 | static int nand_debug_level = 0; | 123 | static int nand_debug_level; |
123 | 124 | ||
124 | /* forward declarations */ | 125 | /* forward declarations */ |
125 | static void clear_interrupts(struct denali_nand_info *denali); | 126 | static void clear_interrupts(struct denali_nand_info *denali); |
126 | static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask); | 127 | static uint32_t wait_for_irq(struct denali_nand_info *denali, |
127 | static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask); | 128 | uint32_t irq_mask); |
129 | static void denali_irq_enable(struct denali_nand_info *denali, | ||
130 | uint32_t int_mask); | ||
128 | static uint32_t read_interrupt_status(struct denali_nand_info *denali); | 131 | static uint32_t read_interrupt_status(struct denali_nand_info *denali); |
129 | 132 | ||
130 | #define DEBUG_DENALI 0 | 133 | #define DEBUG_DENALI 0 |
131 | 134 | ||
132 | /* This is a wrapper for writing to the denali registers. | 135 | /* This is a wrapper for writing to the denali registers. |
133 | * this allows us to create debug information so we can | 136 | * this allows us to create debug information so we can |
134 | * observe how the driver is programming the device. | 137 | * observe how the driver is programming the device. |
135 | * it uses standard linux convention for (val, addr) */ | 138 | * it uses standard linux convention for (val, addr) */ |
136 | static void denali_write32(uint32_t value, void *addr) | 139 | static void denali_write32(uint32_t value, void *addr) |
137 | { | 140 | { |
138 | iowrite32(value, addr); | 141 | iowrite32(value, addr); |
139 | 142 | ||
140 | #if DEBUG_DENALI | 143 | #if DEBUG_DENALI |
141 | printk(KERN_ERR "wrote: 0x%x -> 0x%x\n", value, (uint32_t)((uint32_t)addr & 0x1fff)); | 144 | printk(KERN_INFO "wrote: 0x%x -> 0x%x\n", value, |
145 | (uint32_t)((uint32_t)addr & 0x1fff)); | ||
142 | #endif | 146 | #endif |
143 | } | 147 | } |
144 | 148 | ||
145 | /* Certain operations for the denali NAND controller use an indexed mode to read/write | 149 | /* Certain operations for the denali NAND controller use |
146 | data. The operation is performed by writing the address value of the command to | 150 | * an indexed mode to read/write data. The operation is |
147 | the device memory followed by the data. This function abstracts this common | 151 | * performed by writing the address value of the command |
148 | operation. | 152 | * to the device memory followed by the data. This function |
153 | * abstracts this common operation. | ||
149 | */ | 154 | */ |
150 | static void index_addr(struct denali_nand_info *denali, uint32_t address, uint32_t data) | 155 | static void index_addr(struct denali_nand_info *denali, |
156 | uint32_t address, uint32_t data) | ||
151 | { | 157 | { |
152 | denali_write32(address, denali->flash_mem); | 158 | denali_write32(address, denali->flash_mem); |
153 | denali_write32(data, denali->flash_mem + 0x10); | 159 | denali_write32(data, denali->flash_mem + 0x10); |
@@ -161,7 +167,7 @@ static void index_addr_read_data(struct denali_nand_info *denali, | |||
161 | *pdata = ioread32(denali->flash_mem + 0x10); | 167 | *pdata = ioread32(denali->flash_mem + 0x10); |
162 | } | 168 | } |
163 | 169 | ||
164 | /* We need to buffer some data for some of the NAND core routines. | 170 | /* We need to buffer some data for some of the NAND core routines. |
165 | * The operations manage buffering that data. */ | 171 | * The operations manage buffering that data. */ |
166 | static void reset_buf(struct denali_nand_info *denali) | 172 | static void reset_buf(struct denali_nand_info *denali) |
167 | { | 173 | { |
@@ -183,7 +189,7 @@ static void read_status(struct denali_nand_info *denali) | |||
183 | reset_buf(denali); | 189 | reset_buf(denali); |
184 | 190 | ||
185 | /* initiate a device status read */ | 191 | /* initiate a device status read */ |
186 | cmd = MODE_11 | BANK(denali->flash_bank); | 192 | cmd = MODE_11 | BANK(denali->flash_bank); |
187 | index_addr(denali, cmd | COMMAND_CYCLE, 0x70); | 193 | index_addr(denali, cmd | COMMAND_CYCLE, 0x70); |
188 | denali_write32(cmd | STATUS_CYCLE, denali->flash_mem); | 194 | denali_write32(cmd | STATUS_CYCLE, denali->flash_mem); |
189 | 195 | ||
@@ -191,7 +197,8 @@ static void read_status(struct denali_nand_info *denali) | |||
191 | write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10)); | 197 | write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10)); |
192 | 198 | ||
193 | #if DEBUG_DENALI | 199 | #if DEBUG_DENALI |
194 | printk("device reporting status value of 0x%2x\n", denali->buf.buf[0]); | 200 | printk(KERN_INFO "device reporting status value of 0x%2x\n", |
201 | denali->buf.buf[0]); | ||
195 | #endif | 202 | #endif |
196 | } | 203 | } |
197 | 204 | ||
@@ -199,7 +206,7 @@ static void read_status(struct denali_nand_info *denali) | |||
199 | static void reset_bank(struct denali_nand_info *denali) | 206 | static void reset_bank(struct denali_nand_info *denali) |
200 | { | 207 | { |
201 | uint32_t irq_status = 0; | 208 | uint32_t irq_status = 0; |
202 | uint32_t irq_mask = reset_complete[denali->flash_bank] | | 209 | uint32_t irq_mask = reset_complete[denali->flash_bank] | |
203 | operation_timeout[denali->flash_bank]; | 210 | operation_timeout[denali->flash_bank]; |
204 | int bank = 0; | 211 | int bank = 0; |
205 | 212 | ||
@@ -209,15 +216,13 @@ static void reset_bank(struct denali_nand_info *denali) | |||
209 | denali_write32(bank, denali->flash_reg + DEVICE_RESET); | 216 | denali_write32(bank, denali->flash_reg + DEVICE_RESET); |
210 | 217 | ||
211 | irq_status = wait_for_irq(denali, irq_mask); | 218 | irq_status = wait_for_irq(denali, irq_mask); |
212 | 219 | ||
213 | if (irq_status & operation_timeout[denali->flash_bank]) | 220 | if (irq_status & operation_timeout[denali->flash_bank]) |
214 | { | ||
215 | printk(KERN_ERR "reset bank failed.\n"); | 221 | printk(KERN_ERR "reset bank failed.\n"); |
216 | } | ||
217 | } | 222 | } |
218 | 223 | ||
219 | /* Reset the flash controller */ | 224 | /* Reset the flash controller */ |
220 | static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali) | 225 | static uint16_t denali_nand_reset(struct denali_nand_info *denali) |
221 | { | 226 | { |
222 | uint32_t i; | 227 | uint32_t i; |
223 | 228 | ||
@@ -229,8 +234,10 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali) | |||
229 | denali->flash_reg + intr_status_addresses[i]); | 234 | denali->flash_reg + intr_status_addresses[i]); |
230 | 235 | ||
231 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { | 236 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { |
232 | denali_write32(device_reset_banks[i], denali->flash_reg + DEVICE_RESET); | 237 | denali_write32(device_reset_banks[i], |
233 | while (!(ioread32(denali->flash_reg + intr_status_addresses[i]) & | 238 | denali->flash_reg + DEVICE_RESET); |
239 | while (!(ioread32(denali->flash_reg + | ||
240 | intr_status_addresses[i]) & | ||
234 | (reset_complete[i] | operation_timeout[i]))) | 241 | (reset_complete[i] | operation_timeout[i]))) |
235 | ; | 242 | ; |
236 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & | 243 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & |
@@ -246,11 +253,12 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali) | |||
246 | return PASS; | 253 | return PASS; |
247 | } | 254 | } |
248 | 255 | ||
249 | /* this routine calculates the ONFI timing values for a given mode and programs | 256 | /* this routine calculates the ONFI timing values for a given mode and |
250 | * the clocking register accordingly. The mode is determined by the get_onfi_nand_para | 257 | * programs the clocking register accordingly. The mode is determined by |
251 | routine. | 258 | * the get_onfi_nand_para routine. |
252 | */ | 259 | */ |
253 | static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_t mode) | 260 | static void nand_onfi_timing_set(struct denali_nand_info *denali, |
261 | uint16_t mode) | ||
254 | { | 262 | { |
255 | uint16_t Trea[6] = {40, 30, 25, 20, 20, 16}; | 263 | uint16_t Trea[6] = {40, 30, 25, 20, 20, 16}; |
256 | uint16_t Trp[6] = {50, 25, 17, 15, 12, 10}; | 264 | uint16_t Trp[6] = {50, 25, 17, 15, 12, 10}; |
@@ -347,136 +355,24 @@ static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_t mode | |||
347 | denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); | 355 | denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); |
348 | } | 356 | } |
349 | 357 | ||
350 | /* configures the initial ECC settings for the controller */ | ||
351 | static void set_ecc_config(struct denali_nand_info *denali) | ||
352 | { | ||
353 | #if SUPPORT_8BITECC | ||
354 | if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) < 4096) || | ||
355 | (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) <= 128)) | ||
356 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | ||
357 | #endif | ||
358 | |||
359 | if ((ioread32(denali->flash_reg + ECC_CORRECTION) & ECC_CORRECTION__VALUE) | ||
360 | == 1) { | ||
361 | denali->dev_info.wECCBytesPerSector = 4; | ||
362 | denali->dev_info.wECCBytesPerSector *= denali->dev_info.wDevicesConnected; | ||
363 | denali->dev_info.wNumPageSpareFlag = | ||
364 | denali->dev_info.wPageSpareSize - | ||
365 | denali->dev_info.wPageDataSize / | ||
366 | (ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) * | ||
367 | denali->dev_info.wECCBytesPerSector | ||
368 | - denali->dev_info.wSpareSkipBytes; | ||
369 | } else { | ||
370 | denali->dev_info.wECCBytesPerSector = | ||
371 | (ioread32(denali->flash_reg + ECC_CORRECTION) & | ||
372 | ECC_CORRECTION__VALUE) * 13 / 8; | ||
373 | if ((denali->dev_info.wECCBytesPerSector) % 2 == 0) | ||
374 | denali->dev_info.wECCBytesPerSector += 2; | ||
375 | else | ||
376 | denali->dev_info.wECCBytesPerSector += 1; | ||
377 | |||
378 | denali->dev_info.wECCBytesPerSector *= denali->dev_info.wDevicesConnected; | ||
379 | denali->dev_info.wNumPageSpareFlag = denali->dev_info.wPageSpareSize - | ||
380 | denali->dev_info.wPageDataSize / | ||
381 | (ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) * | ||
382 | denali->dev_info.wECCBytesPerSector | ||
383 | - denali->dev_info.wSpareSkipBytes; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* queries the NAND device to see what ONFI modes it supports. */ | 358 | /* queries the NAND device to see what ONFI modes it supports. */ |
388 | static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) | 359 | static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) |
389 | { | 360 | { |
390 | int i; | 361 | int i; |
391 | uint16_t blks_lun_l, blks_lun_h, n_of_luns; | 362 | /* we needn't to do a reset here because driver has already |
392 | uint32_t blockperlun, id; | 363 | * reset all the banks before |
393 | 364 | * */ | |
394 | denali_write32(DEVICE_RESET__BANK0, denali->flash_reg + DEVICE_RESET); | ||
395 | |||
396 | while (!((ioread32(denali->flash_reg + INTR_STATUS0) & | ||
397 | INTR_STATUS0__RST_COMP) | | ||
398 | (ioread32(denali->flash_reg + INTR_STATUS0) & | ||
399 | INTR_STATUS0__TIME_OUT))) | ||
400 | ; | ||
401 | |||
402 | if (ioread32(denali->flash_reg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) { | ||
403 | denali_write32(DEVICE_RESET__BANK1, denali->flash_reg + DEVICE_RESET); | ||
404 | while (!((ioread32(denali->flash_reg + INTR_STATUS1) & | ||
405 | INTR_STATUS1__RST_COMP) | | ||
406 | (ioread32(denali->flash_reg + INTR_STATUS1) & | ||
407 | INTR_STATUS1__TIME_OUT))) | ||
408 | ; | ||
409 | |||
410 | if (ioread32(denali->flash_reg + INTR_STATUS1) & | ||
411 | INTR_STATUS1__RST_COMP) { | ||
412 | denali_write32(DEVICE_RESET__BANK2, | ||
413 | denali->flash_reg + DEVICE_RESET); | ||
414 | while (!((ioread32(denali->flash_reg + INTR_STATUS2) & | ||
415 | INTR_STATUS2__RST_COMP) | | ||
416 | (ioread32(denali->flash_reg + INTR_STATUS2) & | ||
417 | INTR_STATUS2__TIME_OUT))) | ||
418 | ; | ||
419 | |||
420 | if (ioread32(denali->flash_reg + INTR_STATUS2) & | ||
421 | INTR_STATUS2__RST_COMP) { | ||
422 | denali_write32(DEVICE_RESET__BANK3, | ||
423 | denali->flash_reg + DEVICE_RESET); | ||
424 | while (!((ioread32(denali->flash_reg + INTR_STATUS3) & | ||
425 | INTR_STATUS3__RST_COMP) | | ||
426 | (ioread32(denali->flash_reg + INTR_STATUS3) & | ||
427 | INTR_STATUS3__TIME_OUT))) | ||
428 | ; | ||
429 | } else { | ||
430 | printk(KERN_ERR "Getting a time out for bank 2!\n"); | ||
431 | } | ||
432 | } else { | ||
433 | printk(KERN_ERR "Getting a time out for bank 1!\n"); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | denali_write32(INTR_STATUS0__TIME_OUT, denali->flash_reg + INTR_STATUS0); | ||
438 | denali_write32(INTR_STATUS1__TIME_OUT, denali->flash_reg + INTR_STATUS1); | ||
439 | denali_write32(INTR_STATUS2__TIME_OUT, denali->flash_reg + INTR_STATUS2); | ||
440 | denali_write32(INTR_STATUS3__TIME_OUT, denali->flash_reg + INTR_STATUS3); | ||
441 | |||
442 | denali->dev_info.wONFIDevFeatures = | ||
443 | ioread32(denali->flash_reg + ONFI_DEVICE_FEATURES); | ||
444 | denali->dev_info.wONFIOptCommands = | ||
445 | ioread32(denali->flash_reg + ONFI_OPTIONAL_COMMANDS); | ||
446 | denali->dev_info.wONFITimingMode = | ||
447 | ioread32(denali->flash_reg + ONFI_TIMING_MODE); | ||
448 | denali->dev_info.wONFIPgmCacheTimingMode = | ||
449 | ioread32(denali->flash_reg + ONFI_PGM_CACHE_TIMING_MODE); | ||
450 | |||
451 | n_of_luns = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & | ||
452 | ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS; | ||
453 | blks_lun_l = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L); | ||
454 | blks_lun_h = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U); | ||
455 | |||
456 | blockperlun = (blks_lun_h << 16) | blks_lun_l; | ||
457 | |||
458 | denali->dev_info.wTotalBlocks = n_of_luns * blockperlun; | ||
459 | |||
460 | if (!(ioread32(denali->flash_reg + ONFI_TIMING_MODE) & | 365 | if (!(ioread32(denali->flash_reg + ONFI_TIMING_MODE) & |
461 | ONFI_TIMING_MODE__VALUE)) | 366 | ONFI_TIMING_MODE__VALUE)) |
462 | return FAIL; | 367 | return FAIL; |
463 | 368 | ||
464 | for (i = 5; i > 0; i--) { | 369 | for (i = 5; i > 0; i--) { |
465 | if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) & (0x01 << i)) | 370 | if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) & |
371 | (0x01 << i)) | ||
466 | break; | 372 | break; |
467 | } | 373 | } |
468 | 374 | ||
469 | NAND_ONFi_Timing_Mode(denali, i); | 375 | nand_onfi_timing_set(denali, i); |
470 | |||
471 | index_addr(denali, MODE_11 | 0, 0x90); | ||
472 | index_addr(denali, MODE_11 | 1, 0); | ||
473 | |||
474 | for (i = 0; i < 3; i++) | ||
475 | index_addr_read_data(denali, MODE_11 | 2, &id); | ||
476 | |||
477 | nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id); | ||
478 | |||
479 | denali->dev_info.MLCDevice = id & 0x0C; | ||
480 | 376 | ||
481 | /* By now, all the ONFI devices we know support the page cache */ | 377 | /* By now, all the ONFI devices we know support the page cache */ |
482 | /* rw feature. So here we enable the pipeline_rw_ahead feature */ | 378 | /* rw feature. So here we enable the pipeline_rw_ahead feature */ |
@@ -486,25 +382,10 @@ static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) | |||
486 | return PASS; | 382 | return PASS; |
487 | } | 383 | } |
488 | 384 | ||
489 | static void get_samsung_nand_para(struct denali_nand_info *denali) | 385 | static void get_samsung_nand_para(struct denali_nand_info *denali, |
386 | uint8_t device_id) | ||
490 | { | 387 | { |
491 | uint8_t no_of_planes; | 388 | if (device_id == 0xd3) { /* Samsung K9WAG08U1A */ |
492 | uint32_t blk_size; | ||
493 | uint64_t plane_size, capacity; | ||
494 | uint32_t id_bytes[5]; | ||
495 | int i; | ||
496 | |||
497 | index_addr(denali, (uint32_t)(MODE_11 | 0), 0x90); | ||
498 | index_addr(denali, (uint32_t)(MODE_11 | 1), 0); | ||
499 | for (i = 0; i < 5; i++) | ||
500 | index_addr_read_data(denali, (uint32_t)(MODE_11 | 2), &id_bytes[i]); | ||
501 | |||
502 | nand_dbg_print(NAND_DBG_DEBUG, | ||
503 | "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", | ||
504 | id_bytes[0], id_bytes[1], id_bytes[2], | ||
505 | id_bytes[3], id_bytes[4]); | ||
506 | |||
507 | if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */ | ||
508 | /* Set timing register values according to datasheet */ | 389 | /* Set timing register values according to datasheet */ |
509 | denali_write32(5, denali->flash_reg + ACC_CLKS); | 390 | denali_write32(5, denali->flash_reg + ACC_CLKS); |
510 | denali_write32(20, denali->flash_reg + RE_2_WE); | 391 | denali_write32(20, denali->flash_reg + RE_2_WE); |
@@ -514,19 +395,10 @@ static void get_samsung_nand_para(struct denali_nand_info *denali) | |||
514 | denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT); | 395 | denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT); |
515 | denali_write32(2, denali->flash_reg + CS_SETUP_CNT); | 396 | denali_write32(2, denali->flash_reg + CS_SETUP_CNT); |
516 | } | 397 | } |
517 | |||
518 | no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2); | ||
519 | plane_size = (uint64_t)64 << ((id_bytes[4] & 0x70) >> 4); | ||
520 | blk_size = 64 << ((ioread32(denali->flash_reg + DEVICE_PARAM_1) & 0x30) >> 4); | ||
521 | capacity = (uint64_t)128 * plane_size * no_of_planes; | ||
522 | |||
523 | do_div(capacity, blk_size); | ||
524 | denali->dev_info.wTotalBlocks = capacity; | ||
525 | } | 398 | } |
526 | 399 | ||
527 | static void get_toshiba_nand_para(struct denali_nand_info *denali) | 400 | static void get_toshiba_nand_para(struct denali_nand_info *denali) |
528 | { | 401 | { |
529 | void __iomem *scratch_reg; | ||
530 | uint32_t tmp; | 402 | uint32_t tmp; |
531 | 403 | ||
532 | /* Workaround to fix a controller bug which reports a wrong */ | 404 | /* Workaround to fix a controller bug which reports a wrong */ |
@@ -536,81 +408,52 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali) | |||
536 | denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 408 | denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
537 | tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) * | 409 | tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) * |
538 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 410 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
539 | denali_write32(tmp, denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | 411 | denali_write32(tmp, |
412 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | ||
540 | #if SUPPORT_15BITECC | 413 | #if SUPPORT_15BITECC |
541 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 414 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); |
542 | #elif SUPPORT_8BITECC | 415 | #elif SUPPORT_8BITECC |
543 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 416 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); |
544 | #endif | 417 | #endif |
545 | } | 418 | } |
546 | |||
547 | /* As Toshiba NAND can not provide it's block number, */ | ||
548 | /* so here we need user to provide the correct block */ | ||
549 | /* number in a scratch register before the Linux NAND */ | ||
550 | /* driver is loaded. If no valid value found in the scratch */ | ||
551 | /* register, then we use default block number value */ | ||
552 | scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); | ||
553 | if (!scratch_reg) { | ||
554 | printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", | ||
555 | __FILE__, __LINE__); | ||
556 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
557 | } else { | ||
558 | nand_dbg_print(NAND_DBG_WARN, | ||
559 | "Spectra: ioremap reg address: 0x%p\n", scratch_reg); | ||
560 | denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg); | ||
561 | if (denali->dev_info.wTotalBlocks < 512) | ||
562 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
563 | iounmap(scratch_reg); | ||
564 | } | ||
565 | } | 419 | } |
566 | 420 | ||
567 | static void get_hynix_nand_para(struct denali_nand_info *denali) | 421 | static void get_hynix_nand_para(struct denali_nand_info *denali, |
422 | uint8_t device_id) | ||
568 | { | 423 | { |
569 | void __iomem *scratch_reg; | ||
570 | uint32_t main_size, spare_size; | 424 | uint32_t main_size, spare_size; |
571 | 425 | ||
572 | switch (denali->dev_info.wDeviceID) { | 426 | switch (device_id) { |
573 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ | 427 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ |
574 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ | 428 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ |
575 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); | 429 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); |
576 | denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE); | 430 | denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE); |
577 | denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 431 | denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
578 | main_size = 4096 * ioread32(denali->flash_reg + DEVICES_CONNECTED); | 432 | main_size = 4096 * |
579 | spare_size = 224 * ioread32(denali->flash_reg + DEVICES_CONNECTED); | 433 | ioread32(denali->flash_reg + DEVICES_CONNECTED); |
580 | denali_write32(main_size, denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | 434 | spare_size = 224 * |
581 | denali_write32(spare_size, denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | 435 | ioread32(denali->flash_reg + DEVICES_CONNECTED); |
436 | denali_write32(main_size, | ||
437 | denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | ||
438 | denali_write32(spare_size, | ||
439 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | ||
582 | denali_write32(0, denali->flash_reg + DEVICE_WIDTH); | 440 | denali_write32(0, denali->flash_reg + DEVICE_WIDTH); |
583 | #if SUPPORT_15BITECC | 441 | #if SUPPORT_15BITECC |
584 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 442 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); |
585 | #elif SUPPORT_8BITECC | 443 | #elif SUPPORT_8BITECC |
586 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 444 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); |
587 | #endif | 445 | #endif |
588 | denali->dev_info.MLCDevice = 1; | ||
589 | break; | 446 | break; |
590 | default: | 447 | default: |
591 | nand_dbg_print(NAND_DBG_WARN, | 448 | nand_dbg_print(NAND_DBG_WARN, |
592 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." | 449 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." |
593 | "Will use default parameter values instead.\n", | 450 | "Will use default parameter values instead.\n", |
594 | denali->dev_info.wDeviceID); | 451 | device_id); |
595 | } | ||
596 | |||
597 | scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); | ||
598 | if (!scratch_reg) { | ||
599 | printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", | ||
600 | __FILE__, __LINE__); | ||
601 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
602 | } else { | ||
603 | nand_dbg_print(NAND_DBG_WARN, | ||
604 | "Spectra: ioremap reg address: 0x%p\n", scratch_reg); | ||
605 | denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg); | ||
606 | if (denali->dev_info.wTotalBlocks < 512) | ||
607 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
608 | iounmap(scratch_reg); | ||
609 | } | 452 | } |
610 | } | 453 | } |
611 | 454 | ||
612 | /* determines how many NAND chips are connected to the controller. Note for | 455 | /* determines how many NAND chips are connected to the controller. Note for |
613 | Intel CE4100 devices we don't support more than one device. | 456 | Intel CE4100 devices we don't support more than one device. |
614 | */ | 457 | */ |
615 | static void find_valid_banks(struct denali_nand_info *denali) | 458 | static void find_valid_banks(struct denali_nand_info *denali) |
616 | { | 459 | { |
@@ -621,7 +464,8 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
621 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { | 464 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { |
622 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90); | 465 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90); |
623 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0); | 466 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0); |
624 | index_addr_read_data(denali, (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); | 467 | index_addr_read_data(denali, |
468 | (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); | ||
625 | 469 | ||
626 | nand_dbg_print(NAND_DBG_DEBUG, | 470 | nand_dbg_print(NAND_DBG_DEBUG, |
627 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); | 471 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); |
@@ -637,14 +481,12 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
637 | } | 481 | } |
638 | } | 482 | } |
639 | 483 | ||
640 | if (denali->platform == INTEL_CE4100) | 484 | if (denali->platform == INTEL_CE4100) { |
641 | { | ||
642 | /* Platform limitations of the CE4100 device limit | 485 | /* Platform limitations of the CE4100 device limit |
643 | * users to a single chip solution for NAND. | 486 | * users to a single chip solution for NAND. |
644 | * Multichip support is not enabled. | 487 | * Multichip support is not enabled. |
645 | */ | 488 | */ |
646 | if (denali->total_used_banks != 1) | 489 | if (denali->total_used_banks != 1) { |
647 | { | ||
648 | printk(KERN_ERR "Sorry, Intel CE4100 only supports " | 490 | printk(KERN_ERR "Sorry, Intel CE4100 only supports " |
649 | "a single NAND device.\n"); | 491 | "a single NAND device.\n"); |
650 | BUG(); | 492 | BUG(); |
@@ -656,150 +498,60 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
656 | 498 | ||
657 | static void detect_partition_feature(struct denali_nand_info *denali) | 499 | static void detect_partition_feature(struct denali_nand_info *denali) |
658 | { | 500 | { |
501 | /* For MRST platform, denali->fwblks represent the | ||
502 | * number of blocks firmware is taken, | ||
503 | * FW is in protect partition and MTD driver has no | ||
504 | * permission to access it. So let driver know how many | ||
505 | * blocks it can't touch. | ||
506 | * */ | ||
659 | if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) { | 507 | if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) { |
660 | if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) & | 508 | if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) & |
661 | PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { | 509 | PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { |
662 | denali->dev_info.wSpectraStartBlock = | 510 | denali->fwblks = |
663 | ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & | 511 | ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & |
664 | MIN_MAX_BANK_1__MIN_VALUE) * | 512 | MIN_MAX_BANK_1__MIN_VALUE) * |
665 | denali->dev_info.wTotalBlocks) | 513 | denali->blksperchip) |
666 | + | 514 | + |
667 | (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) & | 515 | (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) & |
668 | MIN_BLK_ADDR_1__VALUE); | 516 | MIN_BLK_ADDR_1__VALUE); |
669 | 517 | } else | |
670 | denali->dev_info.wSpectraEndBlock = | 518 | denali->fwblks = SPECTRA_START_BLOCK; |
671 | (((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & | 519 | } else |
672 | MIN_MAX_BANK_1__MAX_VALUE) >> 2) * | 520 | denali->fwblks = SPECTRA_START_BLOCK; |
673 | denali->dev_info.wTotalBlocks) | ||
674 | + | ||
675 | (ioread32(denali->flash_reg + MAX_BLK_ADDR_1) & | ||
676 | MAX_BLK_ADDR_1__VALUE); | ||
677 | |||
678 | denali->dev_info.wTotalBlocks *= denali->total_used_banks; | ||
679 | |||
680 | if (denali->dev_info.wSpectraEndBlock >= | ||
681 | denali->dev_info.wTotalBlocks) { | ||
682 | denali->dev_info.wSpectraEndBlock = | ||
683 | denali->dev_info.wTotalBlocks - 1; | ||
684 | } | ||
685 | |||
686 | denali->dev_info.wDataBlockNum = | ||
687 | denali->dev_info.wSpectraEndBlock - | ||
688 | denali->dev_info.wSpectraStartBlock + 1; | ||
689 | } else { | ||
690 | denali->dev_info.wTotalBlocks *= denali->total_used_banks; | ||
691 | denali->dev_info.wSpectraStartBlock = SPECTRA_START_BLOCK; | ||
692 | denali->dev_info.wSpectraEndBlock = | ||
693 | denali->dev_info.wTotalBlocks - 1; | ||
694 | denali->dev_info.wDataBlockNum = | ||
695 | denali->dev_info.wSpectraEndBlock - | ||
696 | denali->dev_info.wSpectraStartBlock + 1; | ||
697 | } | ||
698 | } else { | ||
699 | denali->dev_info.wTotalBlocks *= denali->total_used_banks; | ||
700 | denali->dev_info.wSpectraStartBlock = SPECTRA_START_BLOCK; | ||
701 | denali->dev_info.wSpectraEndBlock = denali->dev_info.wTotalBlocks - 1; | ||
702 | denali->dev_info.wDataBlockNum = | ||
703 | denali->dev_info.wSpectraEndBlock - | ||
704 | denali->dev_info.wSpectraStartBlock + 1; | ||
705 | } | ||
706 | } | 521 | } |
707 | 522 | ||
708 | static void dump_device_info(struct denali_nand_info *denali) | 523 | static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) |
709 | { | ||
710 | nand_dbg_print(NAND_DBG_DEBUG, "denali->dev_info:\n"); | ||
711 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n", | ||
712 | denali->dev_info.wDeviceMaker); | ||
713 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n", | ||
714 | denali->dev_info.wDeviceID); | ||
715 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n", | ||
716 | denali->dev_info.wDeviceType); | ||
717 | nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n", | ||
718 | denali->dev_info.wSpectraStartBlock); | ||
719 | nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n", | ||
720 | denali->dev_info.wSpectraEndBlock); | ||
721 | nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n", | ||
722 | denali->dev_info.wTotalBlocks); | ||
723 | nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n", | ||
724 | denali->dev_info.wPagesPerBlock); | ||
725 | nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n", | ||
726 | denali->dev_info.wPageSize); | ||
727 | nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n", | ||
728 | denali->dev_info.wPageDataSize); | ||
729 | nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n", | ||
730 | denali->dev_info.wPageSpareSize); | ||
731 | nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n", | ||
732 | denali->dev_info.wNumPageSpareFlag); | ||
733 | nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n", | ||
734 | denali->dev_info.wECCBytesPerSector); | ||
735 | nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n", | ||
736 | denali->dev_info.wBlockSize); | ||
737 | nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n", | ||
738 | denali->dev_info.wBlockDataSize); | ||
739 | nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n", | ||
740 | denali->dev_info.wDataBlockNum); | ||
741 | nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n", | ||
742 | denali->dev_info.bPlaneNum); | ||
743 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n", | ||
744 | denali->dev_info.wDeviceMainAreaSize); | ||
745 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n", | ||
746 | denali->dev_info.wDeviceSpareAreaSize); | ||
747 | nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n", | ||
748 | denali->dev_info.wDevicesConnected); | ||
749 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n", | ||
750 | denali->dev_info.wDeviceWidth); | ||
751 | nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n", | ||
752 | denali->dev_info.wHWRevision); | ||
753 | nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n", | ||
754 | denali->dev_info.wHWFeatures); | ||
755 | nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n", | ||
756 | denali->dev_info.wONFIDevFeatures); | ||
757 | nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n", | ||
758 | denali->dev_info.wONFIOptCommands); | ||
759 | nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n", | ||
760 | denali->dev_info.wONFITimingMode); | ||
761 | nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n", | ||
762 | denali->dev_info.wONFIPgmCacheTimingMode); | ||
763 | nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n", | ||
764 | denali->dev_info.MLCDevice ? "Yes" : "No"); | ||
765 | nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n", | ||
766 | denali->dev_info.wSpareSkipBytes); | ||
767 | nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n", | ||
768 | denali->dev_info.nBitsInPageNumber); | ||
769 | nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n", | ||
770 | denali->dev_info.nBitsInPageDataSize); | ||
771 | nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n", | ||
772 | denali->dev_info.nBitsInBlockDataSize); | ||
773 | } | ||
774 | |||
775 | static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali) | ||
776 | { | 524 | { |
777 | uint16_t status = PASS; | 525 | uint16_t status = PASS; |
778 | uint8_t no_of_planes; | 526 | uint32_t id_bytes[5], addr; |
527 | uint8_t i, maf_id, device_id; | ||
779 | 528 | ||
780 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 529 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", |
781 | __FILE__, __LINE__, __func__); | 530 | __FILE__, __LINE__, __func__); |
782 | 531 | ||
783 | denali->dev_info.wDeviceMaker = ioread32(denali->flash_reg + MANUFACTURER_ID); | 532 | /* Use read id method to get device ID and other |
784 | denali->dev_info.wDeviceID = ioread32(denali->flash_reg + DEVICE_ID); | 533 | * params. For some NAND chips, controller can't |
785 | denali->dev_info.bDeviceParam0 = ioread32(denali->flash_reg + DEVICE_PARAM_0); | 534 | * report the correct device ID by reading from |
786 | denali->dev_info.bDeviceParam1 = ioread32(denali->flash_reg + DEVICE_PARAM_1); | 535 | * DEVICE_ID register |
787 | denali->dev_info.bDeviceParam2 = ioread32(denali->flash_reg + DEVICE_PARAM_2); | 536 | * */ |
788 | 537 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); | |
789 | denali->dev_info.MLCDevice = ioread32(denali->flash_reg + DEVICE_PARAM_0) & 0x0c; | 538 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
539 | index_addr(denali, (uint32_t)addr | 1, 0); | ||
540 | for (i = 0; i < 5; i++) | ||
541 | index_addr_read_data(denali, addr | 2, &id_bytes[i]); | ||
542 | maf_id = id_bytes[0]; | ||
543 | device_id = id_bytes[1]; | ||
790 | 544 | ||
791 | if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & | 545 | if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & |
792 | ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ | 546 | ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ |
793 | if (FAIL == get_onfi_nand_para(denali)) | 547 | if (FAIL == get_onfi_nand_para(denali)) |
794 | return FAIL; | 548 | return FAIL; |
795 | } else if (denali->dev_info.wDeviceMaker == 0xEC) { /* Samsung NAND */ | 549 | } else if (maf_id == 0xEC) { /* Samsung NAND */ |
796 | get_samsung_nand_para(denali); | 550 | get_samsung_nand_para(denali, device_id); |
797 | } else if (denali->dev_info.wDeviceMaker == 0x98) { /* Toshiba NAND */ | 551 | } else if (maf_id == 0x98) { /* Toshiba NAND */ |
798 | get_toshiba_nand_para(denali); | 552 | get_toshiba_nand_para(denali); |
799 | } else if (denali->dev_info.wDeviceMaker == 0xAD) { /* Hynix NAND */ | 553 | } else if (maf_id == 0xAD) { /* Hynix NAND */ |
800 | get_hynix_nand_para(denali); | 554 | get_hynix_nand_para(denali, device_id); |
801 | } else { | ||
802 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
803 | } | 555 | } |
804 | 556 | ||
805 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" | 557 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" |
@@ -814,88 +566,20 @@ static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali) | |||
814 | ioread32(denali->flash_reg + RDWR_EN_HI_CNT), | 566 | ioread32(denali->flash_reg + RDWR_EN_HI_CNT), |
815 | ioread32(denali->flash_reg + CS_SETUP_CNT)); | 567 | ioread32(denali->flash_reg + CS_SETUP_CNT)); |
816 | 568 | ||
817 | denali->dev_info.wHWRevision = ioread32(denali->flash_reg + REVISION); | ||
818 | denali->dev_info.wHWFeatures = ioread32(denali->flash_reg + FEATURES); | ||
819 | |||
820 | denali->dev_info.wDeviceMainAreaSize = | ||
821 | ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE); | ||
822 | denali->dev_info.wDeviceSpareAreaSize = | ||
823 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | ||
824 | |||
825 | denali->dev_info.wPageDataSize = | ||
826 | ioread32(denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | ||
827 | |||
828 | /* Note: When using the Micon 4K NAND device, the controller will report | ||
829 | * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes. | ||
830 | * And if force set it to 218 bytes, the controller can not work | ||
831 | * correctly. So just let it be. But keep in mind that this bug may | ||
832 | * cause | ||
833 | * other problems in future. - Yunpeng 2008-10-10 | ||
834 | */ | ||
835 | denali->dev_info.wPageSpareSize = | ||
836 | ioread32(denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | ||
837 | |||
838 | denali->dev_info.wPagesPerBlock = ioread32(denali->flash_reg + PAGES_PER_BLOCK); | ||
839 | |||
840 | denali->dev_info.wPageSize = | ||
841 | denali->dev_info.wPageDataSize + denali->dev_info.wPageSpareSize; | ||
842 | denali->dev_info.wBlockSize = | ||
843 | denali->dev_info.wPageSize * denali->dev_info.wPagesPerBlock; | ||
844 | denali->dev_info.wBlockDataSize = | ||
845 | denali->dev_info.wPagesPerBlock * denali->dev_info.wPageDataSize; | ||
846 | |||
847 | denali->dev_info.wDeviceWidth = ioread32(denali->flash_reg + DEVICE_WIDTH); | ||
848 | denali->dev_info.wDeviceType = | ||
849 | ((ioread32(denali->flash_reg + DEVICE_WIDTH) > 0) ? 16 : 8); | ||
850 | |||
851 | denali->dev_info.wDevicesConnected = ioread32(denali->flash_reg + DEVICES_CONNECTED); | ||
852 | |||
853 | denali->dev_info.wSpareSkipBytes = | ||
854 | ioread32(denali->flash_reg + SPARE_AREA_SKIP_BYTES) * | ||
855 | denali->dev_info.wDevicesConnected; | ||
856 | |||
857 | denali->dev_info.nBitsInPageNumber = | ||
858 | ilog2(denali->dev_info.wPagesPerBlock); | ||
859 | denali->dev_info.nBitsInPageDataSize = | ||
860 | ilog2(denali->dev_info.wPageDataSize); | ||
861 | denali->dev_info.nBitsInBlockDataSize = | ||
862 | ilog2(denali->dev_info.wBlockDataSize); | ||
863 | |||
864 | set_ecc_config(denali); | ||
865 | |||
866 | no_of_planes = ioread32(denali->flash_reg + NUMBER_OF_PLANES) & | ||
867 | NUMBER_OF_PLANES__VALUE; | ||
868 | |||
869 | switch (no_of_planes) { | ||
870 | case 0: | ||
871 | case 1: | ||
872 | case 3: | ||
873 | case 7: | ||
874 | denali->dev_info.bPlaneNum = no_of_planes + 1; | ||
875 | break; | ||
876 | default: | ||
877 | status = FAIL; | ||
878 | break; | ||
879 | } | ||
880 | |||
881 | find_valid_banks(denali); | 569 | find_valid_banks(denali); |
882 | 570 | ||
883 | detect_partition_feature(denali); | 571 | detect_partition_feature(denali); |
884 | 572 | ||
885 | dump_device_info(denali); | ||
886 | |||
887 | /* If the user specified to override the default timings | 573 | /* If the user specified to override the default timings |
888 | * with a specific ONFI mode, we apply those changes here. | 574 | * with a specific ONFI mode, we apply those changes here. |
889 | */ | 575 | */ |
890 | if (onfi_timing_mode != NAND_DEFAULT_TIMINGS) | 576 | if (onfi_timing_mode != NAND_DEFAULT_TIMINGS) |
891 | { | 577 | nand_onfi_timing_set(denali, onfi_timing_mode); |
892 | NAND_ONFi_Timing_Mode(denali, onfi_timing_mode); | ||
893 | } | ||
894 | 578 | ||
895 | return status; | 579 | return status; |
896 | } | 580 | } |
897 | 581 | ||
898 | static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, | 582 | static void denali_set_intr_modes(struct denali_nand_info *denali, |
899 | uint16_t INT_ENABLE) | 583 | uint16_t INT_ENABLE) |
900 | { | 584 | { |
901 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 585 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", |
@@ -912,7 +596,7 @@ static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, | |||
912 | */ | 596 | */ |
913 | static inline bool is_flash_bank_valid(int flash_bank) | 597 | static inline bool is_flash_bank_valid(int flash_bank) |
914 | { | 598 | { |
915 | return (flash_bank >= 0 && flash_bank < 4); | 599 | return (flash_bank >= 0 && flash_bank < 4); |
916 | } | 600 | } |
917 | 601 | ||
918 | static void denali_irq_init(struct denali_nand_info *denali) | 602 | static void denali_irq_init(struct denali_nand_info *denali) |
@@ -920,7 +604,7 @@ static void denali_irq_init(struct denali_nand_info *denali) | |||
920 | uint32_t int_mask = 0; | 604 | uint32_t int_mask = 0; |
921 | 605 | ||
922 | /* Disable global interrupts */ | 606 | /* Disable global interrupts */ |
923 | NAND_LLD_Enable_Disable_Interrupts(denali, false); | 607 | denali_set_intr_modes(denali, false); |
924 | 608 | ||
925 | int_mask = DENALI_IRQ_ALL; | 609 | int_mask = DENALI_IRQ_ALL; |
926 | 610 | ||
@@ -935,11 +619,12 @@ static void denali_irq_init(struct denali_nand_info *denali) | |||
935 | 619 | ||
936 | static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) | 620 | static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) |
937 | { | 621 | { |
938 | NAND_LLD_Enable_Disable_Interrupts(denali, false); | 622 | denali_set_intr_modes(denali, false); |
939 | free_irq(irqnum, denali); | 623 | free_irq(irqnum, denali); |
940 | } | 624 | } |
941 | 625 | ||
942 | static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask) | 626 | static void denali_irq_enable(struct denali_nand_info *denali, |
627 | uint32_t int_mask) | ||
943 | { | 628 | { |
944 | denali_write32(int_mask, denali->flash_reg + INTR_EN0); | 629 | denali_write32(int_mask, denali->flash_reg + INTR_EN0); |
945 | denali_write32(int_mask, denali->flash_reg + INTR_EN1); | 630 | denali_write32(int_mask, denali->flash_reg + INTR_EN1); |
@@ -948,15 +633,16 @@ static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask | |||
948 | } | 633 | } |
949 | 634 | ||
950 | /* This function only returns when an interrupt that this driver cares about | 635 | /* This function only returns when an interrupt that this driver cares about |
951 | * occurs. This is to reduce the overhead of servicing interrupts | 636 | * occurs. This is to reduce the overhead of servicing interrupts |
952 | */ | 637 | */ |
953 | static inline uint32_t denali_irq_detected(struct denali_nand_info *denali) | 638 | static inline uint32_t denali_irq_detected(struct denali_nand_info *denali) |
954 | { | 639 | { |
955 | return (read_interrupt_status(denali) & DENALI_IRQ_ALL); | 640 | return read_interrupt_status(denali) & DENALI_IRQ_ALL; |
956 | } | 641 | } |
957 | 642 | ||
958 | /* Interrupts are cleared by writing a 1 to the appropriate status bit */ | 643 | /* Interrupts are cleared by writing a 1 to the appropriate status bit */ |
959 | static inline void clear_interrupt(struct denali_nand_info *denali, uint32_t irq_mask) | 644 | static inline void clear_interrupt(struct denali_nand_info *denali, |
645 | uint32_t irq_mask) | ||
960 | { | 646 | { |
961 | uint32_t intr_status_reg = 0; | 647 | uint32_t intr_status_reg = 0; |
962 | 648 | ||
@@ -995,17 +681,15 @@ static void print_irq_log(struct denali_nand_info *denali) | |||
995 | { | 681 | { |
996 | int i = 0; | 682 | int i = 0; |
997 | 683 | ||
998 | printk("ISR debug log index = %X\n", denali->idx); | 684 | printk(KERN_INFO "ISR debug log index = %X\n", denali->idx); |
999 | for (i = 0; i < 32; i++) | 685 | for (i = 0; i < 32; i++) |
1000 | { | 686 | printk(KERN_INFO "%08X: %08X\n", i, denali->irq_debug_array[i]); |
1001 | printk("%08X: %08X\n", i, denali->irq_debug_array[i]); | ||
1002 | } | ||
1003 | } | 687 | } |
1004 | #endif | 688 | #endif |
1005 | 689 | ||
1006 | /* This is the interrupt service routine. It handles all interrupts | 690 | /* This is the interrupt service routine. It handles all interrupts |
1007 | * sent to this device. Note that on CE4100, this is a shared | 691 | * sent to this device. Note that on CE4100, this is a shared |
1008 | * interrupt. | 692 | * interrupt. |
1009 | */ | 693 | */ |
1010 | static irqreturn_t denali_isr(int irq, void *dev_id) | 694 | static irqreturn_t denali_isr(int irq, void *dev_id) |
1011 | { | 695 | { |
@@ -1015,20 +699,20 @@ static irqreturn_t denali_isr(int irq, void *dev_id) | |||
1015 | 699 | ||
1016 | spin_lock(&denali->irq_lock); | 700 | spin_lock(&denali->irq_lock); |
1017 | 701 | ||
1018 | /* check to see if a valid NAND chip has | 702 | /* check to see if a valid NAND chip has |
1019 | * been selected. | 703 | * been selected. |
1020 | */ | 704 | */ |
1021 | if (is_flash_bank_valid(denali->flash_bank)) | 705 | if (is_flash_bank_valid(denali->flash_bank)) { |
1022 | { | 706 | /* check to see if controller generated |
1023 | /* check to see if controller generated | ||
1024 | * the interrupt, since this is a shared interrupt */ | 707 | * the interrupt, since this is a shared interrupt */ |
1025 | if ((irq_status = denali_irq_detected(denali)) != 0) | 708 | irq_status = denali_irq_detected(denali); |
1026 | { | 709 | if (irq_status != 0) { |
1027 | #if DEBUG_DENALI | 710 | #if DEBUG_DENALI |
1028 | denali->irq_debug_array[denali->idx++] = 0x10000000 | irq_status; | 711 | denali->irq_debug_array[denali->idx++] = |
712 | 0x10000000 | irq_status; | ||
1029 | denali->idx %= 32; | 713 | denali->idx %= 32; |
1030 | 714 | ||
1031 | printk("IRQ status = 0x%04x\n", irq_status); | 715 | printk(KERN_INFO "IRQ status = 0x%04x\n", irq_status); |
1032 | #endif | 716 | #endif |
1033 | /* handle interrupt */ | 717 | /* handle interrupt */ |
1034 | /* first acknowledge it */ | 718 | /* first acknowledge it */ |
@@ -1054,61 +738,62 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) | |||
1054 | bool retry = false; | 738 | bool retry = false; |
1055 | unsigned long timeout = msecs_to_jiffies(1000); | 739 | unsigned long timeout = msecs_to_jiffies(1000); |
1056 | 740 | ||
1057 | do | 741 | do { |
1058 | { | ||
1059 | #if DEBUG_DENALI | 742 | #if DEBUG_DENALI |
1060 | printk("waiting for 0x%x\n", irq_mask); | 743 | printk(KERN_INFO "waiting for 0x%x\n", irq_mask); |
1061 | #endif | 744 | #endif |
1062 | comp_res = wait_for_completion_timeout(&denali->complete, timeout); | 745 | comp_res = |
746 | wait_for_completion_timeout(&denali->complete, timeout); | ||
1063 | spin_lock_irq(&denali->irq_lock); | 747 | spin_lock_irq(&denali->irq_lock); |
1064 | intr_status = denali->irq_status; | 748 | intr_status = denali->irq_status; |
1065 | 749 | ||
1066 | #if DEBUG_DENALI | 750 | #if DEBUG_DENALI |
1067 | denali->irq_debug_array[denali->idx++] = 0x20000000 | (irq_mask << 16) | intr_status; | 751 | denali->irq_debug_array[denali->idx++] = |
752 | 0x20000000 | (irq_mask << 16) | intr_status; | ||
1068 | denali->idx %= 32; | 753 | denali->idx %= 32; |
1069 | #endif | 754 | #endif |
1070 | 755 | ||
1071 | if (intr_status & irq_mask) | 756 | if (intr_status & irq_mask) { |
1072 | { | ||
1073 | denali->irq_status &= ~irq_mask; | 757 | denali->irq_status &= ~irq_mask; |
1074 | spin_unlock_irq(&denali->irq_lock); | 758 | spin_unlock_irq(&denali->irq_lock); |
1075 | #if DEBUG_DENALI | 759 | #if DEBUG_DENALI |
1076 | if (retry) printk("status on retry = 0x%x\n", intr_status); | 760 | if (retry) |
761 | printk(KERN_INFO "status on retry = 0x%x\n", | ||
762 | intr_status); | ||
1077 | #endif | 763 | #endif |
1078 | /* our interrupt was detected */ | 764 | /* our interrupt was detected */ |
1079 | break; | 765 | break; |
1080 | } | 766 | } else { |
1081 | else | 767 | /* these are not the interrupts you are looking for - |
1082 | { | 768 | * need to wait again */ |
1083 | /* these are not the interrupts you are looking for - | ||
1084 | need to wait again */ | ||
1085 | spin_unlock_irq(&denali->irq_lock); | 769 | spin_unlock_irq(&denali->irq_lock); |
1086 | #if DEBUG_DENALI | 770 | #if DEBUG_DENALI |
1087 | print_irq_log(denali); | 771 | print_irq_log(denali); |
1088 | printk("received irq nobody cared: irq_status = 0x%x," | 772 | printk(KERN_INFO "received irq nobody cared:" |
1089 | " irq_mask = 0x%x, timeout = %ld\n", intr_status, irq_mask, comp_res); | 773 | " irq_status = 0x%x, irq_mask = 0x%x," |
774 | " timeout = %ld\n", intr_status, | ||
775 | irq_mask, comp_res); | ||
1090 | #endif | 776 | #endif |
1091 | retry = true; | 777 | retry = true; |
1092 | } | 778 | } |
1093 | } while (comp_res != 0); | 779 | } while (comp_res != 0); |
1094 | 780 | ||
1095 | if (comp_res == 0) | 781 | if (comp_res == 0) { |
1096 | { | ||
1097 | /* timeout */ | 782 | /* timeout */ |
1098 | printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", | 783 | printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", |
1099 | intr_status, irq_mask); | 784 | intr_status, irq_mask); |
1100 | 785 | ||
1101 | intr_status = 0; | 786 | intr_status = 0; |
1102 | } | 787 | } |
1103 | return intr_status; | 788 | return intr_status; |
1104 | } | 789 | } |
1105 | 790 | ||
1106 | /* This helper function setups the registers for ECC and whether or not | 791 | /* This helper function setups the registers for ECC and whether or not |
1107 | the spare area will be transfered. */ | 792 | the spare area will be transfered. */ |
1108 | static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, | 793 | static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, |
1109 | bool transfer_spare) | 794 | bool transfer_spare) |
1110 | { | 795 | { |
1111 | int ecc_en_flag = 0, transfer_spare_flag = 0; | 796 | int ecc_en_flag = 0, transfer_spare_flag = 0; |
1112 | 797 | ||
1113 | /* set ECC, transfer spare bits if needed */ | 798 | /* set ECC, transfer spare bits if needed */ |
1114 | ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0; | 799 | ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0; |
@@ -1116,85 +801,85 @@ static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, | |||
1116 | 801 | ||
1117 | /* Enable spare area/ECC per user's request. */ | 802 | /* Enable spare area/ECC per user's request. */ |
1118 | denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE); | 803 | denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE); |
1119 | denali_write32(transfer_spare_flag, denali->flash_reg + TRANSFER_SPARE_REG); | 804 | denali_write32(transfer_spare_flag, |
805 | denali->flash_reg + TRANSFER_SPARE_REG); | ||
1120 | } | 806 | } |
1121 | 807 | ||
1122 | /* sends a pipeline command operation to the controller. See the Denali NAND | 808 | /* sends a pipeline command operation to the controller. See the Denali NAND |
1123 | controller's user guide for more information (section 4.2.3.6). | 809 | controller's user guide for more information (section 4.2.3.6). |
1124 | */ | 810 | */ |
1125 | static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en, | 811 | static int denali_send_pipeline_cmd(struct denali_nand_info *denali, |
1126 | bool transfer_spare, int access_type, | 812 | bool ecc_en, |
1127 | int op) | 813 | bool transfer_spare, |
814 | int access_type, | ||
815 | int op) | ||
1128 | { | 816 | { |
1129 | int status = PASS; | 817 | int status = PASS; |
1130 | uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, | 818 | uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, |
1131 | irq_mask = 0; | 819 | irq_mask = 0; |
1132 | 820 | ||
1133 | if (op == DENALI_READ) irq_mask = INTR_STATUS0__LOAD_COMP; | 821 | if (op == DENALI_READ) |
1134 | else if (op == DENALI_WRITE) irq_mask = 0; | 822 | irq_mask = INTR_STATUS0__LOAD_COMP; |
1135 | else BUG(); | 823 | else if (op == DENALI_WRITE) |
824 | irq_mask = 0; | ||
825 | else | ||
826 | BUG(); | ||
1136 | 827 | ||
1137 | setup_ecc_for_xfer(denali, ecc_en, transfer_spare); | 828 | setup_ecc_for_xfer(denali, ecc_en, transfer_spare); |
1138 | 829 | ||
1139 | #if DEBUG_DENALI | 830 | #if DEBUG_DENALI |
1140 | spin_lock_irq(&denali->irq_lock); | 831 | spin_lock_irq(&denali->irq_lock); |
1141 | denali->irq_debug_array[denali->idx++] = 0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) | (access_type << 4); | 832 | denali->irq_debug_array[denali->idx++] = |
833 | 0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) | | ||
834 | (access_type << 4); | ||
1142 | denali->idx %= 32; | 835 | denali->idx %= 32; |
1143 | spin_unlock_irq(&denali->irq_lock); | 836 | spin_unlock_irq(&denali->irq_lock); |
1144 | #endif | 837 | #endif |
1145 | 838 | ||
1146 | 839 | ||
1147 | /* clear interrupts */ | 840 | /* clear interrupts */ |
1148 | clear_interrupts(denali); | 841 | clear_interrupts(denali); |
1149 | 842 | ||
1150 | addr = BANK(denali->flash_bank) | denali->page; | 843 | addr = BANK(denali->flash_bank) | denali->page; |
1151 | 844 | ||
1152 | if (op == DENALI_WRITE && access_type != SPARE_ACCESS) | 845 | if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { |
1153 | { | 846 | cmd = MODE_01 | addr; |
1154 | cmd = MODE_01 | addr; | ||
1155 | denali_write32(cmd, denali->flash_mem); | 847 | denali_write32(cmd, denali->flash_mem); |
1156 | } | 848 | } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { |
1157 | else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) | ||
1158 | { | ||
1159 | /* read spare area */ | 849 | /* read spare area */ |
1160 | cmd = MODE_10 | addr; | 850 | cmd = MODE_10 | addr; |
1161 | index_addr(denali, (uint32_t)cmd, access_type); | 851 | index_addr(denali, (uint32_t)cmd, access_type); |
1162 | 852 | ||
1163 | cmd = MODE_01 | addr; | 853 | cmd = MODE_01 | addr; |
1164 | denali_write32(cmd, denali->flash_mem); | 854 | denali_write32(cmd, denali->flash_mem); |
1165 | } | 855 | } else if (op == DENALI_READ) { |
1166 | else if (op == DENALI_READ) | ||
1167 | { | ||
1168 | /* setup page read request for access type */ | 856 | /* setup page read request for access type */ |
1169 | cmd = MODE_10 | addr; | 857 | cmd = MODE_10 | addr; |
1170 | index_addr(denali, (uint32_t)cmd, access_type); | 858 | index_addr(denali, (uint32_t)cmd, access_type); |
1171 | 859 | ||
1172 | /* page 33 of the NAND controller spec indicates we should not | 860 | /* page 33 of the NAND controller spec indicates we should not |
1173 | use the pipeline commands in Spare area only mode. So we | 861 | use the pipeline commands in Spare area only mode. So we |
1174 | don't. | 862 | don't. |
1175 | */ | 863 | */ |
1176 | if (access_type == SPARE_ACCESS) | 864 | if (access_type == SPARE_ACCESS) { |
1177 | { | ||
1178 | cmd = MODE_01 | addr; | 865 | cmd = MODE_01 | addr; |
1179 | denali_write32(cmd, denali->flash_mem); | 866 | denali_write32(cmd, denali->flash_mem); |
1180 | } | 867 | } else { |
1181 | else | 868 | index_addr(denali, (uint32_t)cmd, |
1182 | { | 869 | 0x2000 | op | page_count); |
1183 | index_addr(denali, (uint32_t)cmd, 0x2000 | op | page_count); | 870 | |
1184 | 871 | /* wait for command to be accepted | |
1185 | /* wait for command to be accepted | 872 | * can always use status0 bit as the |
1186 | * can always use status0 bit as the mask is identical for each | 873 | * mask is identical for each |
1187 | * bank. */ | 874 | * bank. */ |
1188 | irq_status = wait_for_irq(denali, irq_mask); | 875 | irq_status = wait_for_irq(denali, irq_mask); |
1189 | 876 | ||
1190 | if (irq_status == 0) | 877 | if (irq_status == 0) { |
1191 | { | ||
1192 | printk(KERN_ERR "cmd, page, addr on timeout " | 878 | printk(KERN_ERR "cmd, page, addr on timeout " |
1193 | "(0x%x, 0x%x, 0x%x)\n", cmd, denali->page, addr); | 879 | "(0x%x, 0x%x, 0x%x)\n", cmd, |
880 | denali->page, addr); | ||
1194 | status = FAIL; | 881 | status = FAIL; |
1195 | } | 882 | } else { |
1196 | else | ||
1197 | { | ||
1198 | cmd = MODE_01 | addr; | 883 | cmd = MODE_01 | addr; |
1199 | denali_write32(cmd, denali->flash_mem); | 884 | denali_write32(cmd, denali->flash_mem); |
1200 | } | 885 | } |
@@ -1204,36 +889,35 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en | |||
1204 | } | 889 | } |
1205 | 890 | ||
1206 | /* helper function that simply writes a buffer to the flash */ | 891 | /* helper function that simply writes a buffer to the flash */ |
1207 | static int write_data_to_flash_mem(struct denali_nand_info *denali, const uint8_t *buf, | 892 | static int write_data_to_flash_mem(struct denali_nand_info *denali, |
1208 | int len) | 893 | const uint8_t *buf, |
894 | int len) | ||
1209 | { | 895 | { |
1210 | uint32_t i = 0, *buf32; | 896 | uint32_t i = 0, *buf32; |
1211 | 897 | ||
1212 | /* verify that the len is a multiple of 4. see comment in | 898 | /* verify that the len is a multiple of 4. see comment in |
1213 | * read_data_from_flash_mem() */ | 899 | * read_data_from_flash_mem() */ |
1214 | BUG_ON((len % 4) != 0); | 900 | BUG_ON((len % 4) != 0); |
1215 | 901 | ||
1216 | /* write the data to the flash memory */ | 902 | /* write the data to the flash memory */ |
1217 | buf32 = (uint32_t *)buf; | 903 | buf32 = (uint32_t *)buf; |
1218 | for (i = 0; i < len / 4; i++) | 904 | for (i = 0; i < len / 4; i++) |
1219 | { | ||
1220 | denali_write32(*buf32++, denali->flash_mem + 0x10); | 905 | denali_write32(*buf32++, denali->flash_mem + 0x10); |
1221 | } | 906 | return i*4; /* intent is to return the number of bytes read */ |
1222 | return i*4; /* intent is to return the number of bytes read */ | ||
1223 | } | 907 | } |
1224 | 908 | ||
1225 | /* helper function that simply reads a buffer from the flash */ | 909 | /* helper function that simply reads a buffer from the flash */ |
1226 | static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8_t *buf, | 910 | static int read_data_from_flash_mem(struct denali_nand_info *denali, |
1227 | int len) | 911 | uint8_t *buf, |
912 | int len) | ||
1228 | { | 913 | { |
1229 | uint32_t i = 0, *buf32; | 914 | uint32_t i = 0, *buf32; |
1230 | 915 | ||
1231 | /* we assume that len will be a multiple of 4, if not | 916 | /* we assume that len will be a multiple of 4, if not |
1232 | * it would be nice to know about it ASAP rather than | 917 | * it would be nice to know about it ASAP rather than |
1233 | * have random failures... | 918 | * have random failures... |
1234 | * | 919 | * This assumption is based on the fact that this |
1235 | * This assumption is based on the fact that this | 920 | * function is designed to be used to read flash pages, |
1236 | * function is designed to be used to read flash pages, | ||
1237 | * which are typically multiples of 4... | 921 | * which are typically multiples of 4... |
1238 | */ | 922 | */ |
1239 | 923 | ||
@@ -1242,10 +926,8 @@ static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8_t *bu | |||
1242 | /* transfer the data from the flash */ | 926 | /* transfer the data from the flash */ |
1243 | buf32 = (uint32_t *)buf; | 927 | buf32 = (uint32_t *)buf; |
1244 | for (i = 0; i < len / 4; i++) | 928 | for (i = 0; i < len / 4; i++) |
1245 | { | ||
1246 | *buf32++ = ioread32(denali->flash_mem + 0x10); | 929 | *buf32++ = ioread32(denali->flash_mem + 0x10); |
1247 | } | 930 | return i*4; /* intent is to return the number of bytes read */ |
1248 | return i*4; /* intent is to return the number of bytes read */ | ||
1249 | } | 931 | } |
1250 | 932 | ||
1251 | /* writes OOB data to the device */ | 933 | /* writes OOB data to the device */ |
@@ -1253,38 +935,35 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
1253 | { | 935 | { |
1254 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 936 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1255 | uint32_t irq_status = 0; | 937 | uint32_t irq_status = 0; |
1256 | uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP | | 938 | uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP | |
1257 | INTR_STATUS0__PROGRAM_FAIL; | 939 | INTR_STATUS0__PROGRAM_FAIL; |
1258 | int status = 0; | 940 | int status = 0; |
1259 | 941 | ||
1260 | denali->page = page; | 942 | denali->page = page; |
1261 | 943 | ||
1262 | if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS, | 944 | if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS, |
1263 | DENALI_WRITE) == PASS) | 945 | DENALI_WRITE) == PASS) { |
1264 | { | ||
1265 | write_data_to_flash_mem(denali, buf, mtd->oobsize); | 946 | write_data_to_flash_mem(denali, buf, mtd->oobsize); |
1266 | 947 | ||
1267 | #if DEBUG_DENALI | 948 | #if DEBUG_DENALI |
1268 | spin_lock_irq(&denali->irq_lock); | 949 | spin_lock_irq(&denali->irq_lock); |
1269 | denali->irq_debug_array[denali->idx++] = 0x80000000 | mtd->oobsize; | 950 | denali->irq_debug_array[denali->idx++] = |
951 | 0x80000000 | mtd->oobsize; | ||
1270 | denali->idx %= 32; | 952 | denali->idx %= 32; |
1271 | spin_unlock_irq(&denali->irq_lock); | 953 | spin_unlock_irq(&denali->irq_lock); |
1272 | #endif | 954 | #endif |
1273 | 955 | ||
1274 | 956 | ||
1275 | /* wait for operation to complete */ | 957 | /* wait for operation to complete */ |
1276 | irq_status = wait_for_irq(denali, irq_mask); | 958 | irq_status = wait_for_irq(denali, irq_mask); |
1277 | 959 | ||
1278 | if (irq_status == 0) | 960 | if (irq_status == 0) { |
1279 | { | ||
1280 | printk(KERN_ERR "OOB write failed\n"); | 961 | printk(KERN_ERR "OOB write failed\n"); |
1281 | status = -EIO; | 962 | status = -EIO; |
1282 | } | 963 | } |
1283 | } | 964 | } else { |
1284 | else | ||
1285 | { | ||
1286 | printk(KERN_ERR "unable to send pipeline command\n"); | 965 | printk(KERN_ERR "unable to send pipeline command\n"); |
1287 | status = -EIO; | 966 | status = -EIO; |
1288 | } | 967 | } |
1289 | return status; | 968 | return status; |
1290 | } | 969 | } |
@@ -1293,60 +972,56 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
1293 | static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | 972 | static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) |
1294 | { | 973 | { |
1295 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 974 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1296 | uint32_t irq_mask = INTR_STATUS0__LOAD_COMP, irq_status = 0, addr = 0x0, cmd = 0x0; | 975 | uint32_t irq_mask = INTR_STATUS0__LOAD_COMP, |
976 | irq_status = 0, addr = 0x0, cmd = 0x0; | ||
1297 | 977 | ||
1298 | denali->page = page; | 978 | denali->page = page; |
1299 | 979 | ||
1300 | #if DEBUG_DENALI | 980 | #if DEBUG_DENALI |
1301 | printk("read_oob %d\n", page); | 981 | printk(KERN_INFO "read_oob %d\n", page); |
1302 | #endif | 982 | #endif |
1303 | if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, | 983 | if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, |
1304 | DENALI_READ) == PASS) | 984 | DENALI_READ) == PASS) { |
1305 | { | 985 | read_data_from_flash_mem(denali, buf, mtd->oobsize); |
1306 | read_data_from_flash_mem(denali, buf, mtd->oobsize); | ||
1307 | 986 | ||
1308 | /* wait for command to be accepted | 987 | /* wait for command to be accepted |
1309 | * can always use status0 bit as the mask is identical for each | 988 | * can always use status0 bit as the mask is identical for each |
1310 | * bank. */ | 989 | * bank. */ |
1311 | irq_status = wait_for_irq(denali, irq_mask); | 990 | irq_status = wait_for_irq(denali, irq_mask); |
1312 | 991 | ||
1313 | if (irq_status == 0) | 992 | if (irq_status == 0) |
1314 | { | 993 | printk(KERN_ERR "page on OOB timeout %d\n", |
1315 | printk(KERN_ERR "page on OOB timeout %d\n", denali->page); | 994 | denali->page); |
1316 | } | ||
1317 | 995 | ||
1318 | /* We set the device back to MAIN_ACCESS here as I observed | 996 | /* We set the device back to MAIN_ACCESS here as I observed |
1319 | * instability with the controller if you do a block erase | 997 | * instability with the controller if you do a block erase |
1320 | * and the last transaction was a SPARE_ACCESS. Block erase | 998 | * and the last transaction was a SPARE_ACCESS. Block erase |
1321 | * is reliable (according to the MTD test infrastructure) | 999 | * is reliable (according to the MTD test infrastructure) |
1322 | * if you are in MAIN_ACCESS. | 1000 | * if you are in MAIN_ACCESS. |
1323 | */ | 1001 | */ |
1324 | addr = BANK(denali->flash_bank) | denali->page; | 1002 | addr = BANK(denali->flash_bank) | denali->page; |
1325 | cmd = MODE_10 | addr; | 1003 | cmd = MODE_10 | addr; |
1326 | index_addr(denali, (uint32_t)cmd, MAIN_ACCESS); | 1004 | index_addr(denali, (uint32_t)cmd, MAIN_ACCESS); |
1327 | 1005 | ||
1328 | #if DEBUG_DENALI | 1006 | #if DEBUG_DENALI |
1329 | spin_lock_irq(&denali->irq_lock); | 1007 | spin_lock_irq(&denali->irq_lock); |
1330 | denali->irq_debug_array[denali->idx++] = 0x60000000 | mtd->oobsize; | 1008 | denali->irq_debug_array[denali->idx++] = |
1009 | 0x60000000 | mtd->oobsize; | ||
1331 | denali->idx %= 32; | 1010 | denali->idx %= 32; |
1332 | spin_unlock_irq(&denali->irq_lock); | 1011 | spin_unlock_irq(&denali->irq_lock); |
1333 | #endif | 1012 | #endif |
1334 | } | 1013 | } |
1335 | } | 1014 | } |
1336 | 1015 | ||
1337 | /* this function examines buffers to see if they contain data that | 1016 | /* this function examines buffers to see if they contain data that |
1338 | * indicate that the buffer is part of an erased region of flash. | 1017 | * indicate that the buffer is part of an erased region of flash. |
1339 | */ | 1018 | */ |
1340 | bool is_erased(uint8_t *buf, int len) | 1019 | bool is_erased(uint8_t *buf, int len) |
1341 | { | 1020 | { |
1342 | int i = 0; | 1021 | int i = 0; |
1343 | for (i = 0; i < len; i++) | 1022 | for (i = 0; i < len; i++) |
1344 | { | ||
1345 | if (buf[i] != 0xFF) | 1023 | if (buf[i] != 0xFF) |
1346 | { | ||
1347 | return false; | 1024 | return false; |
1348 | } | ||
1349 | } | ||
1350 | return true; | 1025 | return true; |
1351 | } | 1026 | } |
1352 | #define ECC_SECTOR_SIZE 512 | 1027 | #define ECC_SECTOR_SIZE 512 |
@@ -1358,65 +1033,59 @@ bool is_erased(uint8_t *buf, int len) | |||
1358 | #define ECC_ERR_DEVICE(x) ((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8) | 1033 | #define ECC_ERR_DEVICE(x) ((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8) |
1359 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) | 1034 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) |
1360 | 1035 | ||
1361 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | 1036 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, |
1362 | uint8_t *oobbuf, uint32_t irq_status) | 1037 | uint8_t *oobbuf, uint32_t irq_status) |
1363 | { | 1038 | { |
1364 | bool check_erased_page = false; | 1039 | bool check_erased_page = false; |
1365 | 1040 | ||
1366 | if (irq_status & INTR_STATUS0__ECC_ERR) | 1041 | if (irq_status & INTR_STATUS0__ECC_ERR) { |
1367 | { | ||
1368 | /* read the ECC errors. we'll ignore them for now */ | 1042 | /* read the ECC errors. we'll ignore them for now */ |
1369 | uint32_t err_address = 0, err_correction_info = 0; | 1043 | uint32_t err_address = 0, err_correction_info = 0; |
1370 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; | 1044 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; |
1371 | uint32_t err_correction_value = 0; | 1045 | uint32_t err_correction_value = 0; |
1372 | 1046 | ||
1373 | do | 1047 | do { |
1374 | { | 1048 | err_address = ioread32(denali->flash_reg + |
1375 | err_address = ioread32(denali->flash_reg + | ||
1376 | ECC_ERROR_ADDRESS); | 1049 | ECC_ERROR_ADDRESS); |
1377 | err_sector = ECC_SECTOR(err_address); | 1050 | err_sector = ECC_SECTOR(err_address); |
1378 | err_byte = ECC_BYTE(err_address); | 1051 | err_byte = ECC_BYTE(err_address); |
1379 | 1052 | ||
1380 | 1053 | ||
1381 | err_correction_info = ioread32(denali->flash_reg + | 1054 | err_correction_info = ioread32(denali->flash_reg + |
1382 | ERR_CORRECTION_INFO); | 1055 | ERR_CORRECTION_INFO); |
1383 | err_correction_value = | 1056 | err_correction_value = |
1384 | ECC_CORRECTION_VALUE(err_correction_info); | 1057 | ECC_CORRECTION_VALUE(err_correction_info); |
1385 | err_device = ECC_ERR_DEVICE(err_correction_info); | 1058 | err_device = ECC_ERR_DEVICE(err_correction_info); |
1386 | 1059 | ||
1387 | if (ECC_ERROR_CORRECTABLE(err_correction_info)) | 1060 | if (ECC_ERROR_CORRECTABLE(err_correction_info)) { |
1388 | { | ||
1389 | /* offset in our buffer is computed as: | 1061 | /* offset in our buffer is computed as: |
1390 | sector number * sector size + offset in | 1062 | sector number * sector size + offset in |
1391 | sector | 1063 | sector |
1392 | */ | 1064 | */ |
1393 | int offset = err_sector * ECC_SECTOR_SIZE + | 1065 | int offset = err_sector * ECC_SECTOR_SIZE + |
1394 | err_byte; | 1066 | err_byte; |
1395 | if (offset < denali->mtd.writesize) | 1067 | if (offset < denali->mtd.writesize) { |
1396 | { | ||
1397 | /* correct the ECC error */ | 1068 | /* correct the ECC error */ |
1398 | buf[offset] ^= err_correction_value; | 1069 | buf[offset] ^= err_correction_value; |
1399 | denali->mtd.ecc_stats.corrected++; | 1070 | denali->mtd.ecc_stats.corrected++; |
1400 | } | 1071 | } else { |
1401 | else | ||
1402 | { | ||
1403 | /* bummer, couldn't correct the error */ | 1072 | /* bummer, couldn't correct the error */ |
1404 | printk(KERN_ERR "ECC offset invalid\n"); | 1073 | printk(KERN_ERR "ECC offset invalid\n"); |
1405 | denali->mtd.ecc_stats.failed++; | 1074 | denali->mtd.ecc_stats.failed++; |
1406 | } | 1075 | } |
1407 | } | 1076 | } else { |
1408 | else | 1077 | /* if the error is not correctable, need to |
1409 | { | 1078 | * look at the page to see if it is an erased |
1410 | /* if the error is not correctable, need to | 1079 | * page. if so, then it's not a real ECC error |
1411 | * look at the page to see if it is an erased page. | 1080 | * */ |
1412 | * if so, then it's not a real ECC error */ | ||
1413 | check_erased_page = true; | 1081 | check_erased_page = true; |
1414 | } | 1082 | } |
1415 | 1083 | ||
1416 | #if DEBUG_DENALI | 1084 | #if DEBUG_DENALI |
1417 | printk("Detected ECC error in page %d: err_addr = 0x%08x," | 1085 | printk(KERN_INFO "Detected ECC error in page %d:" |
1418 | " info to fix is 0x%08x\n", denali->page, err_address, | 1086 | " err_addr = 0x%08x, info to fix is" |
1419 | err_correction_info); | 1087 | " 0x%08x\n", denali->page, err_address, |
1088 | err_correction_info); | ||
1420 | #endif | 1089 | #endif |
1421 | } while (!ECC_LAST_ERR(err_correction_info)); | 1090 | } while (!ECC_LAST_ERR(err_correction_info)); |
1422 | } | 1091 | } |
@@ -1428,7 +1097,8 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en) | |||
1428 | { | 1097 | { |
1429 | uint32_t reg_val = 0x0; | 1098 | uint32_t reg_val = 0x0; |
1430 | 1099 | ||
1431 | if (en) reg_val = DMA_ENABLE__FLAG; | 1100 | if (en) |
1101 | reg_val = DMA_ENABLE__FLAG; | ||
1432 | 1102 | ||
1433 | denali_write32(reg_val, denali->flash_reg + DMA_ENABLE); | 1103 | denali_write32(reg_val, denali->flash_reg + DMA_ENABLE); |
1434 | ioread32(denali->flash_reg + DMA_ENABLE); | 1104 | ioread32(denali->flash_reg + DMA_ENABLE); |
@@ -1458,9 +1128,9 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) | |||
1458 | index_addr(denali, mode | 0x14000, 0x2400); | 1128 | index_addr(denali, mode | 0x14000, 0x2400); |
1459 | } | 1129 | } |
1460 | 1130 | ||
1461 | /* writes a page. user specifies type, and this function handles the | 1131 | /* writes a page. user specifies type, and this function handles the |
1462 | configuration details. */ | 1132 | configuration details. */ |
1463 | static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1133 | static void write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1464 | const uint8_t *buf, bool raw_xfer) | 1134 | const uint8_t *buf, bool raw_xfer) |
1465 | { | 1135 | { |
1466 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1136 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
@@ -1470,7 +1140,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1470 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1140 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1471 | 1141 | ||
1472 | uint32_t irq_status = 0; | 1142 | uint32_t irq_status = 0; |
1473 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP | | 1143 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP | |
1474 | INTR_STATUS0__PROGRAM_FAIL; | 1144 | INTR_STATUS0__PROGRAM_FAIL; |
1475 | 1145 | ||
1476 | /* if it is a raw xfer, we want to disable ecc, and send | 1146 | /* if it is a raw xfer, we want to disable ecc, and send |
@@ -1483,74 +1153,73 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1483 | /* copy buffer into DMA buffer */ | 1153 | /* copy buffer into DMA buffer */ |
1484 | memcpy(denali->buf.buf, buf, mtd->writesize); | 1154 | memcpy(denali->buf.buf, buf, mtd->writesize); |
1485 | 1155 | ||
1486 | if (raw_xfer) | 1156 | if (raw_xfer) { |
1487 | { | ||
1488 | /* transfer the data to the spare area */ | 1157 | /* transfer the data to the spare area */ |
1489 | memcpy(denali->buf.buf + mtd->writesize, | 1158 | memcpy(denali->buf.buf + mtd->writesize, |
1490 | chip->oob_poi, | 1159 | chip->oob_poi, |
1491 | mtd->oobsize); | 1160 | mtd->oobsize); |
1492 | } | 1161 | } |
1493 | 1162 | ||
1494 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE); | 1163 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE); |
1495 | 1164 | ||
1496 | clear_interrupts(denali); | 1165 | clear_interrupts(denali); |
1497 | denali_enable_dma(denali, true); | 1166 | denali_enable_dma(denali, true); |
1498 | 1167 | ||
1499 | denali_setup_dma(denali, DENALI_WRITE); | 1168 | denali_setup_dma(denali, DENALI_WRITE); |
1500 | 1169 | ||
1501 | /* wait for operation to complete */ | 1170 | /* wait for operation to complete */ |
1502 | irq_status = wait_for_irq(denali, irq_mask); | 1171 | irq_status = wait_for_irq(denali, irq_mask); |
1503 | 1172 | ||
1504 | if (irq_status == 0) | 1173 | if (irq_status == 0) { |
1505 | { | 1174 | printk(KERN_ERR "timeout on write_page" |
1506 | printk(KERN_ERR "timeout on write_page (type = %d)\n", raw_xfer); | 1175 | " (type = %d)\n", raw_xfer); |
1507 | denali->status = | 1176 | denali->status = |
1508 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? NAND_STATUS_FAIL : | 1177 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? |
1509 | PASS; | 1178 | NAND_STATUS_FAIL : PASS; |
1510 | } | 1179 | } |
1511 | 1180 | ||
1512 | denali_enable_dma(denali, false); | 1181 | denali_enable_dma(denali, false); |
1513 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE); | 1182 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE); |
1514 | } | 1183 | } |
1515 | 1184 | ||
1516 | /* NAND core entry points */ | 1185 | /* NAND core entry points */ |
1517 | 1186 | ||
1518 | /* this is the callback that the NAND core calls to write a page. Since | 1187 | /* this is the callback that the NAND core calls to write a page. Since |
1519 | writing a page with ECC or without is similar, all the work is done | 1188 | writing a page with ECC or without is similar, all the work is done |
1520 | by write_page above. */ | 1189 | by write_page above. */ |
1521 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1190 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1522 | const uint8_t *buf) | 1191 | const uint8_t *buf) |
1523 | { | 1192 | { |
1524 | /* for regular page writes, we let HW handle all the ECC | 1193 | /* for regular page writes, we let HW handle all the ECC |
1525 | * data written to the device. */ | 1194 | * data written to the device. */ |
1526 | write_page(mtd, chip, buf, false); | 1195 | write_page(mtd, chip, buf, false); |
1527 | } | 1196 | } |
1528 | 1197 | ||
1529 | /* This is the callback that the NAND core calls to write a page without ECC. | 1198 | /* This is the callback that the NAND core calls to write a page without ECC. |
1530 | raw access is similiar to ECC page writes, so all the work is done in the | 1199 | raw access is similiar to ECC page writes, so all the work is done in the |
1531 | write_page() function above. | 1200 | write_page() function above. |
1532 | */ | 1201 | */ |
1533 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1202 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1534 | const uint8_t *buf) | 1203 | const uint8_t *buf) |
1535 | { | 1204 | { |
1536 | /* for raw page writes, we want to disable ECC and simply write | 1205 | /* for raw page writes, we want to disable ECC and simply write |
1537 | whatever data is in the buffer. */ | 1206 | whatever data is in the buffer. */ |
1538 | write_page(mtd, chip, buf, true); | 1207 | write_page(mtd, chip, buf, true); |
1539 | } | 1208 | } |
1540 | 1209 | ||
1541 | static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1210 | static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, |
1542 | int page) | 1211 | int page) |
1543 | { | 1212 | { |
1544 | return write_oob_data(mtd, chip->oob_poi, page); | 1213 | return write_oob_data(mtd, chip->oob_poi, page); |
1545 | } | 1214 | } |
1546 | 1215 | ||
1547 | static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1216 | static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
1548 | int page, int sndcmd) | 1217 | int page, int sndcmd) |
1549 | { | 1218 | { |
1550 | read_oob_data(mtd, chip->oob_poi, page); | 1219 | read_oob_data(mtd, chip->oob_poi, page); |
1551 | 1220 | ||
1552 | return 0; /* notify NAND core to send command to | 1221 | return 0; /* notify NAND core to send command to |
1553 | * NAND device. */ | 1222 | NAND device. */ |
1554 | } | 1223 | } |
1555 | 1224 | ||
1556 | static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | 1225 | static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
@@ -1563,7 +1232,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1563 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1232 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1564 | 1233 | ||
1565 | uint32_t irq_status = 0; | 1234 | uint32_t irq_status = 0; |
1566 | uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE | | 1235 | uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE | |
1567 | INTR_STATUS0__ECC_ERR; | 1236 | INTR_STATUS0__ECC_ERR; |
1568 | bool check_erased_page = false; | 1237 | bool check_erased_page = false; |
1569 | 1238 | ||
@@ -1581,26 +1250,20 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1581 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE); | 1250 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE); |
1582 | 1251 | ||
1583 | memcpy(buf, denali->buf.buf, mtd->writesize); | 1252 | memcpy(buf, denali->buf.buf, mtd->writesize); |
1584 | 1253 | ||
1585 | check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status); | 1254 | check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status); |
1586 | denali_enable_dma(denali, false); | 1255 | denali_enable_dma(denali, false); |
1587 | 1256 | ||
1588 | if (check_erased_page) | 1257 | if (check_erased_page) { |
1589 | { | ||
1590 | read_oob_data(&denali->mtd, chip->oob_poi, denali->page); | 1258 | read_oob_data(&denali->mtd, chip->oob_poi, denali->page); |
1591 | 1259 | ||
1592 | /* check ECC failures that may have occurred on erased pages */ | 1260 | /* check ECC failures that may have occurred on erased pages */ |
1593 | if (check_erased_page) | 1261 | if (check_erased_page) { |
1594 | { | ||
1595 | if (!is_erased(buf, denali->mtd.writesize)) | 1262 | if (!is_erased(buf, denali->mtd.writesize)) |
1596 | { | ||
1597 | denali->mtd.ecc_stats.failed++; | 1263 | denali->mtd.ecc_stats.failed++; |
1598 | } | ||
1599 | if (!is_erased(buf, denali->mtd.oobsize)) | 1264 | if (!is_erased(buf, denali->mtd.oobsize)) |
1600 | { | ||
1601 | denali->mtd.ecc_stats.failed++; | 1265 | denali->mtd.ecc_stats.failed++; |
1602 | } | 1266 | } |
1603 | } | ||
1604 | } | 1267 | } |
1605 | return 0; | 1268 | return 0; |
1606 | } | 1269 | } |
@@ -1616,7 +1279,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1616 | 1279 | ||
1617 | uint32_t irq_status = 0; | 1280 | uint32_t irq_status = 0; |
1618 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; | 1281 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; |
1619 | 1282 | ||
1620 | setup_ecc_for_xfer(denali, false, true); | 1283 | setup_ecc_for_xfer(denali, false, true); |
1621 | denali_enable_dma(denali, true); | 1284 | denali_enable_dma(denali, true); |
1622 | 1285 | ||
@@ -1644,12 +1307,10 @@ static uint8_t denali_read_byte(struct mtd_info *mtd) | |||
1644 | uint8_t result = 0xff; | 1307 | uint8_t result = 0xff; |
1645 | 1308 | ||
1646 | if (denali->buf.head < denali->buf.tail) | 1309 | if (denali->buf.head < denali->buf.tail) |
1647 | { | ||
1648 | result = denali->buf.buf[denali->buf.head++]; | 1310 | result = denali->buf.buf[denali->buf.head++]; |
1649 | } | ||
1650 | 1311 | ||
1651 | #if DEBUG_DENALI | 1312 | #if DEBUG_DENALI |
1652 | printk("read byte -> 0x%02x\n", result); | 1313 | printk(KERN_INFO "read byte -> 0x%02x\n", result); |
1653 | #endif | 1314 | #endif |
1654 | return result; | 1315 | return result; |
1655 | } | 1316 | } |
@@ -1658,7 +1319,7 @@ static void denali_select_chip(struct mtd_info *mtd, int chip) | |||
1658 | { | 1319 | { |
1659 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1320 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1660 | #if DEBUG_DENALI | 1321 | #if DEBUG_DENALI |
1661 | printk("denali select chip %d\n", chip); | 1322 | printk(KERN_INFO "denali select chip %d\n", chip); |
1662 | #endif | 1323 | #endif |
1663 | spin_lock_irq(&denali->irq_lock); | 1324 | spin_lock_irq(&denali->irq_lock); |
1664 | denali->flash_bank = chip; | 1325 | denali->flash_bank = chip; |
@@ -1672,7 +1333,7 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) | |||
1672 | denali->status = 0; | 1333 | denali->status = 0; |
1673 | 1334 | ||
1674 | #if DEBUG_DENALI | 1335 | #if DEBUG_DENALI |
1675 | printk("waitfunc %d\n", status); | 1336 | printk(KERN_INFO "waitfunc %d\n", status); |
1676 | #endif | 1337 | #endif |
1677 | return status; | 1338 | return status; |
1678 | } | 1339 | } |
@@ -1684,76 +1345,74 @@ static void denali_erase(struct mtd_info *mtd, int page) | |||
1684 | uint32_t cmd = 0x0, irq_status = 0; | 1345 | uint32_t cmd = 0x0, irq_status = 0; |
1685 | 1346 | ||
1686 | #if DEBUG_DENALI | 1347 | #if DEBUG_DENALI |
1687 | printk("erase page: %d\n", page); | 1348 | printk(KERN_INFO "erase page: %d\n", page); |
1688 | #endif | 1349 | #endif |
1689 | /* clear interrupts */ | 1350 | /* clear interrupts */ |
1690 | clear_interrupts(denali); | 1351 | clear_interrupts(denali); |
1691 | 1352 | ||
1692 | /* setup page read request for access type */ | 1353 | /* setup page read request for access type */ |
1693 | cmd = MODE_10 | BANK(denali->flash_bank) | page; | 1354 | cmd = MODE_10 | BANK(denali->flash_bank) | page; |
1694 | index_addr(denali, (uint32_t)cmd, 0x1); | 1355 | index_addr(denali, (uint32_t)cmd, 0x1); |
1695 | 1356 | ||
1696 | /* wait for erase to complete or failure to occur */ | 1357 | /* wait for erase to complete or failure to occur */ |
1697 | irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP | | 1358 | irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP | |
1698 | INTR_STATUS0__ERASE_FAIL); | 1359 | INTR_STATUS0__ERASE_FAIL); |
1699 | 1360 | ||
1700 | denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ? NAND_STATUS_FAIL : | 1361 | denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ? |
1701 | PASS; | 1362 | NAND_STATUS_FAIL : PASS; |
1702 | } | 1363 | } |
1703 | 1364 | ||
1704 | static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | 1365 | static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, |
1705 | int page) | 1366 | int page) |
1706 | { | 1367 | { |
1707 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1368 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1369 | uint32_t addr, id; | ||
1370 | int i; | ||
1708 | 1371 | ||
1709 | #if DEBUG_DENALI | 1372 | #if DEBUG_DENALI |
1710 | printk("cmdfunc: 0x%x %d %d\n", cmd, col, page); | 1373 | printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page); |
1711 | #endif | 1374 | #endif |
1712 | switch (cmd) | 1375 | switch (cmd) { |
1713 | { | 1376 | case NAND_CMD_PAGEPROG: |
1714 | case NAND_CMD_PAGEPROG: | 1377 | break; |
1715 | break; | 1378 | case NAND_CMD_STATUS: |
1716 | case NAND_CMD_STATUS: | 1379 | read_status(denali); |
1717 | read_status(denali); | 1380 | break; |
1718 | break; | 1381 | case NAND_CMD_READID: |
1719 | case NAND_CMD_READID: | 1382 | reset_buf(denali); |
1720 | reset_buf(denali); | 1383 | /*sometimes ManufactureId read from register is not right |
1721 | if (denali->flash_bank < denali->total_used_banks) | 1384 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips |
1722 | { | 1385 | * So here we send READID cmd to NAND insteand |
1723 | /* write manufacturer information into nand | 1386 | * */ |
1724 | buffer for NAND subsystem to fetch. | 1387 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); |
1725 | */ | 1388 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
1726 | write_byte_to_buf(denali, denali->dev_info.wDeviceMaker); | 1389 | index_addr(denali, (uint32_t)addr | 1, 0); |
1727 | write_byte_to_buf(denali, denali->dev_info.wDeviceID); | 1390 | for (i = 0; i < 5; i++) { |
1728 | write_byte_to_buf(denali, denali->dev_info.bDeviceParam0); | 1391 | index_addr_read_data(denali, |
1729 | write_byte_to_buf(denali, denali->dev_info.bDeviceParam1); | 1392 | (uint32_t)addr | 2, |
1730 | write_byte_to_buf(denali, denali->dev_info.bDeviceParam2); | 1393 | &id); |
1731 | } | 1394 | write_byte_to_buf(denali, id); |
1732 | else | 1395 | } |
1733 | { | 1396 | break; |
1734 | int i; | 1397 | case NAND_CMD_READ0: |
1735 | for (i = 0; i < 5; i++) | 1398 | case NAND_CMD_SEQIN: |
1736 | write_byte_to_buf(denali, 0xff); | 1399 | denali->page = page; |
1737 | } | 1400 | break; |
1738 | break; | 1401 | case NAND_CMD_RESET: |
1739 | case NAND_CMD_READ0: | 1402 | reset_bank(denali); |
1740 | case NAND_CMD_SEQIN: | 1403 | break; |
1741 | denali->page = page; | 1404 | case NAND_CMD_READOOB: |
1742 | break; | 1405 | /* TODO: Read OOB data */ |
1743 | case NAND_CMD_RESET: | 1406 | break; |
1744 | reset_bank(denali); | 1407 | default: |
1745 | break; | 1408 | printk(KERN_ERR ": unsupported command" |
1746 | case NAND_CMD_READOOB: | 1409 | " received 0x%x\n", cmd); |
1747 | /* TODO: Read OOB data */ | 1410 | break; |
1748 | break; | ||
1749 | default: | ||
1750 | printk(KERN_ERR ": unsupported command received 0x%x\n", cmd); | ||
1751 | break; | ||
1752 | } | 1411 | } |
1753 | } | 1412 | } |
1754 | 1413 | ||
1755 | /* stubs for ECC functions not used by the NAND core */ | 1414 | /* stubs for ECC functions not used by the NAND core */ |
1756 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | 1415 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, |
1757 | uint8_t *ecc_code) | 1416 | uint8_t *ecc_code) |
1758 | { | 1417 | { |
1759 | printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n"); | 1418 | printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n"); |
@@ -1761,7 +1420,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | |||
1761 | return -EIO; | 1420 | return -EIO; |
1762 | } | 1421 | } |
1763 | 1422 | ||
1764 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | 1423 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, |
1765 | uint8_t *read_ecc, uint8_t *calc_ecc) | 1424 | uint8_t *read_ecc, uint8_t *calc_ecc) |
1766 | { | 1425 | { |
1767 | printk(KERN_ERR "denali_ecc_correct called unexpectedly\n"); | 1426 | printk(KERN_ERR "denali_ecc_correct called unexpectedly\n"); |
@@ -1779,10 +1438,18 @@ static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) | |||
1779 | /* Initialization code to bring the device up to a known good state */ | 1438 | /* Initialization code to bring the device up to a known good state */ |
1780 | static void denali_hw_init(struct denali_nand_info *denali) | 1439 | static void denali_hw_init(struct denali_nand_info *denali) |
1781 | { | 1440 | { |
1441 | /* tell driver how many bit controller will skip before | ||
1442 | * writing ECC code in OOB, this register may be already | ||
1443 | * set by firmware. So we read this value out. | ||
1444 | * if this value is 0, just let it be. | ||
1445 | * */ | ||
1446 | denali->bbtskipbytes = ioread32(denali->flash_reg + | ||
1447 | SPARE_AREA_SKIP_BYTES); | ||
1782 | denali_irq_init(denali); | 1448 | denali_irq_init(denali); |
1783 | NAND_Flash_Reset(denali); | 1449 | denali_nand_reset(denali); |
1784 | denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED); | 1450 | denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED); |
1785 | denali_write32(CHIP_EN_DONT_CARE__FLAG, denali->flash_reg + CHIP_ENABLE_DONT_CARE); | 1451 | denali_write32(CHIP_EN_DONT_CARE__FLAG, |
1452 | denali->flash_reg + CHIP_ENABLE_DONT_CARE); | ||
1786 | 1453 | ||
1787 | denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES); | 1454 | denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES); |
1788 | denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER); | 1455 | denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER); |
@@ -1792,25 +1459,18 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
1792 | denali_write32(1, denali->flash_reg + ECC_ENABLE); | 1459 | denali_write32(1, denali->flash_reg + ECC_ENABLE); |
1793 | } | 1460 | } |
1794 | 1461 | ||
1795 | /* ECC layout for SLC devices. Denali spec indicates SLC fixed at 4 bytes */ | 1462 | /* Althogh controller spec said SLC ECC is forceb to be 4bit, |
1796 | #define ECC_BYTES_SLC 4 * (2048 / ECC_SECTOR_SIZE) | 1463 | * but denali controller in MRST only support 15bit and 8bit ECC |
1797 | static struct nand_ecclayout nand_oob_slc = { | 1464 | * correction |
1798 | .eccbytes = 4, | 1465 | * */ |
1799 | .eccpos = { 0, 1, 2, 3 }, /* not used */ | 1466 | #define ECC_8BITS 14 |
1800 | .oobfree = {{ | 1467 | static struct nand_ecclayout nand_8bit_oob = { |
1801 | .offset = ECC_BYTES_SLC, | 1468 | .eccbytes = 14, |
1802 | .length = 64 - ECC_BYTES_SLC | ||
1803 | }} | ||
1804 | }; | 1469 | }; |
1805 | 1470 | ||
1806 | #define ECC_BYTES_MLC 14 * (2048 / ECC_SECTOR_SIZE) | 1471 | #define ECC_15BITS 26 |
1807 | static struct nand_ecclayout nand_oob_mlc_14bit = { | 1472 | static struct nand_ecclayout nand_15bit_oob = { |
1808 | .eccbytes = 14, | 1473 | .eccbytes = 26, |
1809 | .eccpos = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, /* not used */ | ||
1810 | .oobfree = {{ | ||
1811 | .offset = ECC_BYTES_MLC, | ||
1812 | .length = 64 - ECC_BYTES_MLC | ||
1813 | }} | ||
1814 | }; | 1474 | }; |
1815 | 1475 | ||
1816 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | 1476 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; |
@@ -1842,12 +1502,12 @@ void denali_drv_init(struct denali_nand_info *denali) | |||
1842 | denali->idx = 0; | 1502 | denali->idx = 0; |
1843 | 1503 | ||
1844 | /* setup interrupt handler */ | 1504 | /* setup interrupt handler */ |
1845 | /* the completion object will be used to notify | 1505 | /* the completion object will be used to notify |
1846 | * the callee that the interrupt is done */ | 1506 | * the callee that the interrupt is done */ |
1847 | init_completion(&denali->complete); | 1507 | init_completion(&denali->complete); |
1848 | 1508 | ||
1849 | /* the spinlock will be used to synchronize the ISR | 1509 | /* the spinlock will be used to synchronize the ISR |
1850 | * with any element that might be access shared | 1510 | * with any element that might be access shared |
1851 | * data (interrupt status) */ | 1511 | * data (interrupt status) */ |
1852 | spin_lock_init(&denali->irq_lock); | 1512 | spin_lock_init(&denali->irq_lock); |
1853 | 1513 | ||
@@ -1880,13 +1540,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1880 | } | 1540 | } |
1881 | 1541 | ||
1882 | if (id->driver_data == INTEL_CE4100) { | 1542 | if (id->driver_data == INTEL_CE4100) { |
1883 | /* Due to a silicon limitation, we can only support | 1543 | /* Due to a silicon limitation, we can only support |
1884 | * ONFI timing mode 1 and below. | 1544 | * ONFI timing mode 1 and below. |
1885 | */ | 1545 | */ |
1886 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) | 1546 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { |
1887 | { | 1547 | printk(KERN_ERR "Intel CE4100 only supports" |
1888 | printk("Intel CE4100 only supports ONFI timing mode 1 " | 1548 | " ONFI timing mode 1 or below\n"); |
1889 | "or below\n"); | ||
1890 | ret = -EINVAL; | 1549 | ret = -EINVAL; |
1891 | goto failed_enable; | 1550 | goto failed_enable; |
1892 | } | 1551 | } |
@@ -1905,7 +1564,9 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1905 | mem_base = csr_base + csr_len; | 1564 | mem_base = csr_base + csr_len; |
1906 | mem_len = csr_len; | 1565 | mem_len = csr_len; |
1907 | nand_dbg_print(NAND_DBG_WARN, | 1566 | nand_dbg_print(NAND_DBG_WARN, |
1908 | "Spectra: No second BAR for PCI device; assuming %08Lx\n", | 1567 | "Spectra: No second" |
1568 | " BAR for PCI device;" | ||
1569 | " assuming %08Lx\n", | ||
1909 | (uint64_t)csr_base); | 1570 | (uint64_t)csr_base); |
1910 | } | 1571 | } |
1911 | } | 1572 | } |
@@ -1913,16 +1574,16 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1913 | /* Is 32-bit DMA supported? */ | 1574 | /* Is 32-bit DMA supported? */ |
1914 | ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); | 1575 | ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); |
1915 | 1576 | ||
1916 | if (ret) | 1577 | if (ret) { |
1917 | { | ||
1918 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); | 1578 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); |
1919 | goto failed_enable; | 1579 | goto failed_enable; |
1920 | } | 1580 | } |
1921 | denali->buf.dma_buf = pci_map_single(dev, denali->buf.buf, DENALI_BUF_SIZE, | 1581 | denali->buf.dma_buf = |
1922 | PCI_DMA_BIDIRECTIONAL); | 1582 | pci_map_single(dev, denali->buf.buf, |
1583 | DENALI_BUF_SIZE, | ||
1584 | PCI_DMA_BIDIRECTIONAL); | ||
1923 | 1585 | ||
1924 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) | 1586 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) { |
1925 | { | ||
1926 | printk(KERN_ERR "Spectra: failed to map DMA buffer\n"); | 1587 | printk(KERN_ERR "Spectra: failed to map DMA buffer\n"); |
1927 | goto failed_enable; | 1588 | goto failed_enable; |
1928 | } | 1589 | } |
@@ -1970,22 +1631,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1970 | } | 1631 | } |
1971 | 1632 | ||
1972 | /* now that our ISR is registered, we can enable interrupts */ | 1633 | /* now that our ISR is registered, we can enable interrupts */ |
1973 | NAND_LLD_Enable_Disable_Interrupts(denali, true); | 1634 | denali_set_intr_modes(denali, true); |
1974 | 1635 | ||
1975 | pci_set_drvdata(dev, denali); | 1636 | pci_set_drvdata(dev, denali); |
1976 | 1637 | ||
1977 | NAND_Read_Device_ID(denali); | 1638 | denali_nand_timing_set(denali); |
1978 | |||
1979 | /* MTD supported page sizes vary by kernel. We validate our | ||
1980 | kernel supports the device here. | ||
1981 | */ | ||
1982 | if (denali->dev_info.wPageSize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) | ||
1983 | { | ||
1984 | ret = -ENODEV; | ||
1985 | printk(KERN_ERR "Spectra: device size not supported by this " | ||
1986 | "version of MTD."); | ||
1987 | goto failed_nand; | ||
1988 | } | ||
1989 | 1639 | ||
1990 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" | 1640 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" |
1991 | "acc_clks: %d, re_2_we: %d, we_2_re: %d," | 1641 | "acc_clks: %d, re_2_we: %d, we_2_re: %d," |
@@ -2009,18 +1659,46 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2009 | denali->nand.read_byte = denali_read_byte; | 1659 | denali->nand.read_byte = denali_read_byte; |
2010 | denali->nand.waitfunc = denali_waitfunc; | 1660 | denali->nand.waitfunc = denali_waitfunc; |
2011 | 1661 | ||
2012 | /* scan for NAND devices attached to the controller | 1662 | /* scan for NAND devices attached to the controller |
2013 | * this is the first stage in a two step process to register | 1663 | * this is the first stage in a two step process to register |
2014 | * with the nand subsystem */ | 1664 | * with the nand subsystem */ |
2015 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) | 1665 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) { |
2016 | { | ||
2017 | ret = -ENXIO; | 1666 | ret = -ENXIO; |
2018 | goto failed_nand; | 1667 | goto failed_nand; |
2019 | } | 1668 | } |
2020 | 1669 | ||
2021 | /* second stage of the NAND scan | 1670 | /* MTD supported page sizes vary by kernel. We validate our |
2022 | * this stage requires information regarding ECC and | 1671 | * kernel supports the device here. |
2023 | * bad block management. */ | 1672 | */ |
1673 | if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { | ||
1674 | ret = -ENODEV; | ||
1675 | printk(KERN_ERR "Spectra: device size not supported by this " | ||
1676 | "version of MTD."); | ||
1677 | goto failed_nand; | ||
1678 | } | ||
1679 | |||
1680 | /* support for multi nand | ||
1681 | * MTD known nothing about multi nand, | ||
1682 | * so we should tell it the real pagesize | ||
1683 | * and anything necessery | ||
1684 | */ | ||
1685 | denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED); | ||
1686 | denali->nand.chipsize <<= (denali->devnum - 1); | ||
1687 | denali->nand.page_shift += (denali->devnum - 1); | ||
1688 | denali->nand.pagemask = (denali->nand.chipsize >> | ||
1689 | denali->nand.page_shift) - 1; | ||
1690 | denali->nand.bbt_erase_shift += (denali->devnum - 1); | ||
1691 | denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift; | ||
1692 | denali->nand.chip_shift += (denali->devnum - 1); | ||
1693 | denali->mtd.writesize <<= (denali->devnum - 1); | ||
1694 | denali->mtd.oobsize <<= (denali->devnum - 1); | ||
1695 | denali->mtd.erasesize <<= (denali->devnum - 1); | ||
1696 | denali->mtd.size = denali->nand.numchips * denali->nand.chipsize; | ||
1697 | denali->bbtskipbytes *= denali->devnum; | ||
1698 | |||
1699 | /* second stage of the NAND scan | ||
1700 | * this stage requires information regarding ECC and | ||
1701 | * bad block management. */ | ||
2024 | 1702 | ||
2025 | /* Bad block management */ | 1703 | /* Bad block management */ |
2026 | denali->nand.bbt_td = &bbt_main_descr; | 1704 | denali->nand.bbt_td = &bbt_main_descr; |
@@ -2030,26 +1708,57 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2030 | denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; | 1708 | denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; |
2031 | denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | 1709 | denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; |
2032 | 1710 | ||
2033 | if (denali->dev_info.MLCDevice) | 1711 | /* Denali Controller only support 15bit and 8bit ECC in MRST, |
2034 | { | 1712 | * so just let controller do 15bit ECC for MLC and 8bit ECC for |
2035 | denali->nand.ecc.layout = &nand_oob_mlc_14bit; | 1713 | * SLC if possible. |
2036 | denali->nand.ecc.bytes = ECC_BYTES_MLC; | 1714 | * */ |
2037 | } | 1715 | if (denali->nand.cellinfo & 0xc && |
2038 | else /* SLC */ | 1716 | (denali->mtd.oobsize > (denali->bbtskipbytes + |
2039 | { | 1717 | ECC_15BITS * (denali->mtd.writesize / |
2040 | denali->nand.ecc.layout = &nand_oob_slc; | 1718 | ECC_SECTOR_SIZE)))) { |
2041 | denali->nand.ecc.bytes = ECC_BYTES_SLC; | 1719 | /* if MLC OOB size is large enough, use 15bit ECC*/ |
1720 | denali->nand.ecc.layout = &nand_15bit_oob; | ||
1721 | denali->nand.ecc.bytes = ECC_15BITS; | ||
1722 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | ||
1723 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + | ||
1724 | ECC_8BITS * (denali->mtd.writesize / | ||
1725 | ECC_SECTOR_SIZE))) { | ||
1726 | printk(KERN_ERR "Your NAND chip OOB is not large enough to" | ||
1727 | " contain 8bit ECC correction codes"); | ||
1728 | goto failed_nand; | ||
1729 | } else { | ||
1730 | denali->nand.ecc.layout = &nand_8bit_oob; | ||
1731 | denali->nand.ecc.bytes = ECC_8BITS; | ||
1732 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | ||
2042 | } | 1733 | } |
2043 | 1734 | ||
2044 | /* These functions are required by the NAND core framework, otherwise, | 1735 | denali->nand.ecc.bytes *= denali->devnum; |
2045 | the NAND core will assert. However, we don't need them, so we'll stub | 1736 | denali->nand.ecc.layout->eccbytes *= |
2046 | them out. */ | 1737 | denali->mtd.writesize / ECC_SECTOR_SIZE; |
1738 | denali->nand.ecc.layout->oobfree[0].offset = | ||
1739 | denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes; | ||
1740 | denali->nand.ecc.layout->oobfree[0].length = | ||
1741 | denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes - | ||
1742 | denali->bbtskipbytes; | ||
1743 | |||
1744 | /* Let driver know the total blocks number and | ||
1745 | * how many blocks contained by each nand chip. | ||
1746 | * blksperchip will help driver to know how many | ||
1747 | * blocks is taken by FW. | ||
1748 | * */ | ||
1749 | denali->totalblks = denali->mtd.size >> | ||
1750 | denali->nand.phys_erase_shift; | ||
1751 | denali->blksperchip = denali->totalblks / denali->nand.numchips; | ||
1752 | |||
1753 | /* These functions are required by the NAND core framework, otherwise, | ||
1754 | * the NAND core will assert. However, we don't need them, so we'll stub | ||
1755 | * them out. */ | ||
2047 | denali->nand.ecc.calculate = denali_ecc_calculate; | 1756 | denali->nand.ecc.calculate = denali_ecc_calculate; |
2048 | denali->nand.ecc.correct = denali_ecc_correct; | 1757 | denali->nand.ecc.correct = denali_ecc_correct; |
2049 | denali->nand.ecc.hwctl = denali_ecc_hwctl; | 1758 | denali->nand.ecc.hwctl = denali_ecc_hwctl; |
2050 | 1759 | ||
2051 | /* override the default read operations */ | 1760 | /* override the default read operations */ |
2052 | denali->nand.ecc.size = denali->mtd.writesize; | 1761 | denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum; |
2053 | denali->nand.ecc.read_page = denali_read_page; | 1762 | denali->nand.ecc.read_page = denali_read_page; |
2054 | denali->nand.ecc.read_page_raw = denali_read_page_raw; | 1763 | denali->nand.ecc.read_page_raw = denali_read_page_raw; |
2055 | denali->nand.ecc.write_page = denali_write_page; | 1764 | denali->nand.ecc.write_page = denali_write_page; |
@@ -2058,15 +1767,15 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2058 | denali->nand.ecc.write_oob = denali_write_oob; | 1767 | denali->nand.ecc.write_oob = denali_write_oob; |
2059 | denali->nand.erase_cmd = denali_erase; | 1768 | denali->nand.erase_cmd = denali_erase; |
2060 | 1769 | ||
2061 | if (nand_scan_tail(&denali->mtd)) | 1770 | if (nand_scan_tail(&denali->mtd)) { |
2062 | { | ||
2063 | ret = -ENXIO; | 1771 | ret = -ENXIO; |
2064 | goto failed_nand; | 1772 | goto failed_nand; |
2065 | } | 1773 | } |
2066 | 1774 | ||
2067 | ret = add_mtd_device(&denali->mtd); | 1775 | ret = add_mtd_device(&denali->mtd); |
2068 | if (ret) { | 1776 | if (ret) { |
2069 | printk(KERN_ERR "Spectra: Failed to register MTD device: %d\n", ret); | 1777 | printk(KERN_ERR "Spectra: Failed to register" |
1778 | " MTD device: %d\n", ret); | ||
2070 | goto failed_nand; | 1779 | goto failed_nand; |
2071 | } | 1780 | } |
2072 | return 0; | 1781 | return 0; |
@@ -2079,7 +1788,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2079 | failed_remap_csr: | 1788 | failed_remap_csr: |
2080 | pci_release_regions(dev); | 1789 | pci_release_regions(dev); |
2081 | failed_req_csr: | 1790 | failed_req_csr: |
2082 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1791 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
2083 | PCI_DMA_BIDIRECTIONAL); | 1792 | PCI_DMA_BIDIRECTIONAL); |
2084 | failed_enable: | 1793 | failed_enable: |
2085 | kfree(denali); | 1794 | kfree(denali); |
@@ -2103,7 +1812,7 @@ static void denali_pci_remove(struct pci_dev *dev) | |||
2103 | iounmap(denali->flash_mem); | 1812 | iounmap(denali->flash_mem); |
2104 | pci_release_regions(dev); | 1813 | pci_release_regions(dev); |
2105 | pci_disable_device(dev); | 1814 | pci_disable_device(dev); |
2106 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1815 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
2107 | PCI_DMA_BIDIRECTIONAL); | 1816 | PCI_DMA_BIDIRECTIONAL); |
2108 | pci_set_drvdata(dev, NULL); | 1817 | pci_set_drvdata(dev, NULL); |
2109 | kfree(denali); | 1818 | kfree(denali); |
@@ -2120,7 +1829,8 @@ static struct pci_driver denali_pci_driver = { | |||
2120 | 1829 | ||
2121 | static int __devinit denali_init(void) | 1830 | static int __devinit denali_init(void) |
2122 | { | 1831 | { |
2123 | printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__); | 1832 | printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", |
1833 | __DATE__, __TIME__); | ||
2124 | return pci_register_driver(&denali_pci_driver); | 1834 | return pci_register_driver(&denali_pci_driver); |
2125 | } | 1835 | } |
2126 | 1836 | ||
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 422a29ab2f60..b680474e6333 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h | |||
@@ -17,7 +17,7 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/mtd/nand.h> | 20 | #include <linux/mtd/nand.h> |
21 | 21 | ||
22 | #define DEVICE_RESET 0x0 | 22 | #define DEVICE_RESET 0x0 |
23 | #define DEVICE_RESET__BANK0 0x0001 | 23 | #define DEVICE_RESET__BANK0 0x0001 |
@@ -29,7 +29,7 @@ | |||
29 | #define TRANSFER_SPARE_REG__FLAG 0x0001 | 29 | #define TRANSFER_SPARE_REG__FLAG 0x0001 |
30 | 30 | ||
31 | #define LOAD_WAIT_CNT 0x20 | 31 | #define LOAD_WAIT_CNT 0x20 |
32 | #define LOAD_WAIT_CNT__VALUE 0xffff | 32 | #define LOAD_WAIT_CNT__VALUE 0xffff |
33 | 33 | ||
34 | #define PROGRAM_WAIT_CNT 0x30 | 34 | #define PROGRAM_WAIT_CNT 0x30 |
35 | #define PROGRAM_WAIT_CNT__VALUE 0xffff | 35 | #define PROGRAM_WAIT_CNT__VALUE 0xffff |
@@ -83,7 +83,7 @@ | |||
83 | #define RE_2_WE 0x120 | 83 | #define RE_2_WE 0x120 |
84 | #define RE_2_WE__VALUE 0x003f | 84 | #define RE_2_WE__VALUE 0x003f |
85 | 85 | ||
86 | #define ACC_CLKS 0x130 | 86 | #define ACC_CLKS 0x130 |
87 | #define ACC_CLKS__VALUE 0x000f | 87 | #define ACC_CLKS__VALUE 0x000f |
88 | 88 | ||
89 | #define NUMBER_OF_PLANES 0x140 | 89 | #define NUMBER_OF_PLANES 0x140 |
@@ -140,7 +140,7 @@ | |||
140 | #define DEVICES_CONNECTED 0x250 | 140 | #define DEVICES_CONNECTED 0x250 |
141 | #define DEVICES_CONNECTED__VALUE 0x0007 | 141 | #define DEVICES_CONNECTED__VALUE 0x0007 |
142 | 142 | ||
143 | #define DIE_MASK 0x260 | 143 | #define DIE_MASK 0x260 |
144 | #define DIE_MASK__VALUE 0x00ff | 144 | #define DIE_MASK__VALUE 0x00ff |
145 | 145 | ||
146 | #define FIRST_BLOCK_OF_NEXT_PLANE 0x270 | 146 | #define FIRST_BLOCK_OF_NEXT_PLANE 0x270 |
@@ -152,7 +152,7 @@ | |||
152 | #define RE_2_RE 0x290 | 152 | #define RE_2_RE 0x290 |
153 | #define RE_2_RE__VALUE 0x003f | 153 | #define RE_2_RE__VALUE 0x003f |
154 | 154 | ||
155 | #define MANUFACTURER_ID 0x300 | 155 | #define MANUFACTURER_ID 0x300 |
156 | #define MANUFACTURER_ID__VALUE 0x00ff | 156 | #define MANUFACTURER_ID__VALUE 0x00ff |
157 | 157 | ||
158 | #define DEVICE_ID 0x310 | 158 | #define DEVICE_ID 0x310 |
@@ -173,13 +173,13 @@ | |||
173 | #define LOGICAL_PAGE_SPARE_SIZE 0x360 | 173 | #define LOGICAL_PAGE_SPARE_SIZE 0x360 |
174 | #define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff | 174 | #define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff |
175 | 175 | ||
176 | #define REVISION 0x370 | 176 | #define REVISION 0x370 |
177 | #define REVISION__VALUE 0xffff | 177 | #define REVISION__VALUE 0xffff |
178 | 178 | ||
179 | #define ONFI_DEVICE_FEATURES 0x380 | 179 | #define ONFI_DEVICE_FEATURES 0x380 |
180 | #define ONFI_DEVICE_FEATURES__VALUE 0x003f | 180 | #define ONFI_DEVICE_FEATURES__VALUE 0x003f |
181 | 181 | ||
182 | #define ONFI_OPTIONAL_COMMANDS 0x390 | 182 | #define ONFI_OPTIONAL_COMMANDS 0x390 |
183 | #define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f | 183 | #define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f |
184 | 184 | ||
185 | #define ONFI_TIMING_MODE 0x3a0 | 185 | #define ONFI_TIMING_MODE 0x3a0 |
@@ -201,12 +201,12 @@ | |||
201 | #define FEATURES 0x3f0 | 201 | #define FEATURES 0x3f0 |
202 | #define FEATURES__N_BANKS 0x0003 | 202 | #define FEATURES__N_BANKS 0x0003 |
203 | #define FEATURES__ECC_MAX_ERR 0x003c | 203 | #define FEATURES__ECC_MAX_ERR 0x003c |
204 | #define FEATURES__DMA 0x0040 | 204 | #define FEATURES__DMA 0x0040 |
205 | #define FEATURES__CMD_DMA 0x0080 | 205 | #define FEATURES__CMD_DMA 0x0080 |
206 | #define FEATURES__PARTITION 0x0100 | 206 | #define FEATURES__PARTITION 0x0100 |
207 | #define FEATURES__XDMA_SIDEBAND 0x0200 | 207 | #define FEATURES__XDMA_SIDEBAND 0x0200 |
208 | #define FEATURES__GPREG 0x0400 | 208 | #define FEATURES__GPREG 0x0400 |
209 | #define FEATURES__INDEX_ADDR 0x0800 | 209 | #define FEATURES__INDEX_ADDR 0x0800 |
210 | 210 | ||
211 | #define TRANSFER_MODE 0x400 | 211 | #define TRANSFER_MODE 0x400 |
212 | #define TRANSFER_MODE__VALUE 0x0003 | 212 | #define TRANSFER_MODE__VALUE 0x0003 |
@@ -235,12 +235,12 @@ | |||
235 | #define INTR_EN0__DMA_CMD_COMP 0x0004 | 235 | #define INTR_EN0__DMA_CMD_COMP 0x0004 |
236 | #define INTR_EN0__TIME_OUT 0x0008 | 236 | #define INTR_EN0__TIME_OUT 0x0008 |
237 | #define INTR_EN0__PROGRAM_FAIL 0x0010 | 237 | #define INTR_EN0__PROGRAM_FAIL 0x0010 |
238 | #define INTR_EN0__ERASE_FAIL 0x0020 | 238 | #define INTR_EN0__ERASE_FAIL 0x0020 |
239 | #define INTR_EN0__LOAD_COMP 0x0040 | 239 | #define INTR_EN0__LOAD_COMP 0x0040 |
240 | #define INTR_EN0__PROGRAM_COMP 0x0080 | 240 | #define INTR_EN0__PROGRAM_COMP 0x0080 |
241 | #define INTR_EN0__ERASE_COMP 0x0100 | 241 | #define INTR_EN0__ERASE_COMP 0x0100 |
242 | #define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 | 242 | #define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 |
243 | #define INTR_EN0__LOCKED_BLK 0x0400 | 243 | #define INTR_EN0__LOCKED_BLK 0x0400 |
244 | #define INTR_EN0__UNSUP_CMD 0x0800 | 244 | #define INTR_EN0__UNSUP_CMD 0x0800 |
245 | #define INTR_EN0__INT_ACT 0x1000 | 245 | #define INTR_EN0__INT_ACT 0x1000 |
246 | #define INTR_EN0__RST_COMP 0x2000 | 246 | #define INTR_EN0__RST_COMP 0x2000 |
@@ -253,7 +253,7 @@ | |||
253 | #define ERR_PAGE_ADDR0 0x440 | 253 | #define ERR_PAGE_ADDR0 0x440 |
254 | #define ERR_PAGE_ADDR0__VALUE 0xffff | 254 | #define ERR_PAGE_ADDR0__VALUE 0xffff |
255 | 255 | ||
256 | #define ERR_BLOCK_ADDR0 0x450 | 256 | #define ERR_BLOCK_ADDR0 0x450 |
257 | #define ERR_BLOCK_ADDR0__VALUE 0xffff | 257 | #define ERR_BLOCK_ADDR0__VALUE 0xffff |
258 | 258 | ||
259 | #define INTR_STATUS1 0x460 | 259 | #define INTR_STATUS1 0x460 |
@@ -280,12 +280,12 @@ | |||
280 | #define INTR_EN1__DMA_CMD_COMP 0x0004 | 280 | #define INTR_EN1__DMA_CMD_COMP 0x0004 |
281 | #define INTR_EN1__TIME_OUT 0x0008 | 281 | #define INTR_EN1__TIME_OUT 0x0008 |
282 | #define INTR_EN1__PROGRAM_FAIL 0x0010 | 282 | #define INTR_EN1__PROGRAM_FAIL 0x0010 |
283 | #define INTR_EN1__ERASE_FAIL 0x0020 | 283 | #define INTR_EN1__ERASE_FAIL 0x0020 |
284 | #define INTR_EN1__LOAD_COMP 0x0040 | 284 | #define INTR_EN1__LOAD_COMP 0x0040 |
285 | #define INTR_EN1__PROGRAM_COMP 0x0080 | 285 | #define INTR_EN1__PROGRAM_COMP 0x0080 |
286 | #define INTR_EN1__ERASE_COMP 0x0100 | 286 | #define INTR_EN1__ERASE_COMP 0x0100 |
287 | #define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 | 287 | #define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 |
288 | #define INTR_EN1__LOCKED_BLK 0x0400 | 288 | #define INTR_EN1__LOCKED_BLK 0x0400 |
289 | #define INTR_EN1__UNSUP_CMD 0x0800 | 289 | #define INTR_EN1__UNSUP_CMD 0x0800 |
290 | #define INTR_EN1__INT_ACT 0x1000 | 290 | #define INTR_EN1__INT_ACT 0x1000 |
291 | #define INTR_EN1__RST_COMP 0x2000 | 291 | #define INTR_EN1__RST_COMP 0x2000 |
@@ -298,7 +298,7 @@ | |||
298 | #define ERR_PAGE_ADDR1 0x490 | 298 | #define ERR_PAGE_ADDR1 0x490 |
299 | #define ERR_PAGE_ADDR1__VALUE 0xffff | 299 | #define ERR_PAGE_ADDR1__VALUE 0xffff |
300 | 300 | ||
301 | #define ERR_BLOCK_ADDR1 0x4a0 | 301 | #define ERR_BLOCK_ADDR1 0x4a0 |
302 | #define ERR_BLOCK_ADDR1__VALUE 0xffff | 302 | #define ERR_BLOCK_ADDR1__VALUE 0xffff |
303 | 303 | ||
304 | #define INTR_STATUS2 0x4b0 | 304 | #define INTR_STATUS2 0x4b0 |
@@ -325,12 +325,12 @@ | |||
325 | #define INTR_EN2__DMA_CMD_COMP 0x0004 | 325 | #define INTR_EN2__DMA_CMD_COMP 0x0004 |
326 | #define INTR_EN2__TIME_OUT 0x0008 | 326 | #define INTR_EN2__TIME_OUT 0x0008 |
327 | #define INTR_EN2__PROGRAM_FAIL 0x0010 | 327 | #define INTR_EN2__PROGRAM_FAIL 0x0010 |
328 | #define INTR_EN2__ERASE_FAIL 0x0020 | 328 | #define INTR_EN2__ERASE_FAIL 0x0020 |
329 | #define INTR_EN2__LOAD_COMP 0x0040 | 329 | #define INTR_EN2__LOAD_COMP 0x0040 |
330 | #define INTR_EN2__PROGRAM_COMP 0x0080 | 330 | #define INTR_EN2__PROGRAM_COMP 0x0080 |
331 | #define INTR_EN2__ERASE_COMP 0x0100 | 331 | #define INTR_EN2__ERASE_COMP 0x0100 |
332 | #define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 | 332 | #define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 |
333 | #define INTR_EN2__LOCKED_BLK 0x0400 | 333 | #define INTR_EN2__LOCKED_BLK 0x0400 |
334 | #define INTR_EN2__UNSUP_CMD 0x0800 | 334 | #define INTR_EN2__UNSUP_CMD 0x0800 |
335 | #define INTR_EN2__INT_ACT 0x1000 | 335 | #define INTR_EN2__INT_ACT 0x1000 |
336 | #define INTR_EN2__RST_COMP 0x2000 | 336 | #define INTR_EN2__RST_COMP 0x2000 |
@@ -343,7 +343,7 @@ | |||
343 | #define ERR_PAGE_ADDR2 0x4e0 | 343 | #define ERR_PAGE_ADDR2 0x4e0 |
344 | #define ERR_PAGE_ADDR2__VALUE 0xffff | 344 | #define ERR_PAGE_ADDR2__VALUE 0xffff |
345 | 345 | ||
346 | #define ERR_BLOCK_ADDR2 0x4f0 | 346 | #define ERR_BLOCK_ADDR2 0x4f0 |
347 | #define ERR_BLOCK_ADDR2__VALUE 0xffff | 347 | #define ERR_BLOCK_ADDR2__VALUE 0xffff |
348 | 348 | ||
349 | #define INTR_STATUS3 0x500 | 349 | #define INTR_STATUS3 0x500 |
@@ -370,12 +370,12 @@ | |||
370 | #define INTR_EN3__DMA_CMD_COMP 0x0004 | 370 | #define INTR_EN3__DMA_CMD_COMP 0x0004 |
371 | #define INTR_EN3__TIME_OUT 0x0008 | 371 | #define INTR_EN3__TIME_OUT 0x0008 |
372 | #define INTR_EN3__PROGRAM_FAIL 0x0010 | 372 | #define INTR_EN3__PROGRAM_FAIL 0x0010 |
373 | #define INTR_EN3__ERASE_FAIL 0x0020 | 373 | #define INTR_EN3__ERASE_FAIL 0x0020 |
374 | #define INTR_EN3__LOAD_COMP 0x0040 | 374 | #define INTR_EN3__LOAD_COMP 0x0040 |
375 | #define INTR_EN3__PROGRAM_COMP 0x0080 | 375 | #define INTR_EN3__PROGRAM_COMP 0x0080 |
376 | #define INTR_EN3__ERASE_COMP 0x0100 | 376 | #define INTR_EN3__ERASE_COMP 0x0100 |
377 | #define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 | 377 | #define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 |
378 | #define INTR_EN3__LOCKED_BLK 0x0400 | 378 | #define INTR_EN3__LOCKED_BLK 0x0400 |
379 | #define INTR_EN3__UNSUP_CMD 0x0800 | 379 | #define INTR_EN3__UNSUP_CMD 0x0800 |
380 | #define INTR_EN3__INT_ACT 0x1000 | 380 | #define INTR_EN3__INT_ACT 0x1000 |
381 | #define INTR_EN3__RST_COMP 0x2000 | 381 | #define INTR_EN3__RST_COMP 0x2000 |
@@ -388,7 +388,7 @@ | |||
388 | #define ERR_PAGE_ADDR3 0x530 | 388 | #define ERR_PAGE_ADDR3 0x530 |
389 | #define ERR_PAGE_ADDR3__VALUE 0xffff | 389 | #define ERR_PAGE_ADDR3__VALUE 0xffff |
390 | 390 | ||
391 | #define ERR_BLOCK_ADDR3 0x540 | 391 | #define ERR_BLOCK_ADDR3 0x540 |
392 | #define ERR_BLOCK_ADDR3__VALUE 0xffff | 392 | #define ERR_BLOCK_ADDR3__VALUE 0xffff |
393 | 393 | ||
394 | #define DATA_INTR 0x550 | 394 | #define DATA_INTR 0x550 |
@@ -412,9 +412,9 @@ | |||
412 | #define GPREG_3__VALUE 0xffff | 412 | #define GPREG_3__VALUE 0xffff |
413 | 413 | ||
414 | #define ECC_THRESHOLD 0x600 | 414 | #define ECC_THRESHOLD 0x600 |
415 | #define ECC_THRESHOLD__VALUE 0x03ff | 415 | #define ECC_THRESHOLD__VALUE 0x03ff |
416 | 416 | ||
417 | #define ECC_ERROR_BLOCK_ADDRESS 0x610 | 417 | #define ECC_ERROR_BLOCK_ADDRESS 0x610 |
418 | #define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff | 418 | #define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff |
419 | 419 | ||
420 | #define ECC_ERROR_PAGE_ADDRESS 0x620 | 420 | #define ECC_ERROR_PAGE_ADDRESS 0x620 |
@@ -466,7 +466,7 @@ | |||
466 | #define CHNL_ACTIVE__CHANNEL3 0x0008 | 466 | #define CHNL_ACTIVE__CHANNEL3 0x0008 |
467 | 467 | ||
468 | #define ACTIVE_SRC_ID 0x800 | 468 | #define ACTIVE_SRC_ID 0x800 |
469 | #define ACTIVE_SRC_ID__VALUE 0x00ff | 469 | #define ACTIVE_SRC_ID__VALUE 0x00ff |
470 | 470 | ||
471 | #define PTN_INTR 0x810 | 471 | #define PTN_INTR 0x810 |
472 | #define PTN_INTR__CONFIG_ERROR 0x0001 | 472 | #define PTN_INTR__CONFIG_ERROR 0x0001 |
@@ -485,7 +485,7 @@ | |||
485 | #define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 | 485 | #define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 |
486 | 486 | ||
487 | #define PERM_SRC_ID_0 0x830 | 487 | #define PERM_SRC_ID_0 0x830 |
488 | #define PERM_SRC_ID_0__SRCID 0x00ff | 488 | #define PERM_SRC_ID_0__SRCID 0x00ff |
489 | #define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 | 489 | #define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 |
490 | #define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 | 490 | #define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 |
491 | #define PERM_SRC_ID_0__READ_ACTIVE 0x4000 | 491 | #define PERM_SRC_ID_0__READ_ACTIVE 0x4000 |
@@ -502,7 +502,7 @@ | |||
502 | #define MIN_MAX_BANK_0__MAX_VALUE 0x000c | 502 | #define MIN_MAX_BANK_0__MAX_VALUE 0x000c |
503 | 503 | ||
504 | #define PERM_SRC_ID_1 0x870 | 504 | #define PERM_SRC_ID_1 0x870 |
505 | #define PERM_SRC_ID_1__SRCID 0x00ff | 505 | #define PERM_SRC_ID_1__SRCID 0x00ff |
506 | #define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 | 506 | #define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 |
507 | #define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 | 507 | #define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 |
508 | #define PERM_SRC_ID_1__READ_ACTIVE 0x4000 | 508 | #define PERM_SRC_ID_1__READ_ACTIVE 0x4000 |
@@ -519,7 +519,7 @@ | |||
519 | #define MIN_MAX_BANK_1__MAX_VALUE 0x000c | 519 | #define MIN_MAX_BANK_1__MAX_VALUE 0x000c |
520 | 520 | ||
521 | #define PERM_SRC_ID_2 0x8b0 | 521 | #define PERM_SRC_ID_2 0x8b0 |
522 | #define PERM_SRC_ID_2__SRCID 0x00ff | 522 | #define PERM_SRC_ID_2__SRCID 0x00ff |
523 | #define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 | 523 | #define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 |
524 | #define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 | 524 | #define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 |
525 | #define PERM_SRC_ID_2__READ_ACTIVE 0x4000 | 525 | #define PERM_SRC_ID_2__READ_ACTIVE 0x4000 |
@@ -536,7 +536,7 @@ | |||
536 | #define MIN_MAX_BANK_2__MAX_VALUE 0x000c | 536 | #define MIN_MAX_BANK_2__MAX_VALUE 0x000c |
537 | 537 | ||
538 | #define PERM_SRC_ID_3 0x8f0 | 538 | #define PERM_SRC_ID_3 0x8f0 |
539 | #define PERM_SRC_ID_3__SRCID 0x00ff | 539 | #define PERM_SRC_ID_3__SRCID 0x00ff |
540 | #define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 | 540 | #define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 |
541 | #define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 | 541 | #define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 |
542 | #define PERM_SRC_ID_3__READ_ACTIVE 0x4000 | 542 | #define PERM_SRC_ID_3__READ_ACTIVE 0x4000 |
@@ -553,7 +553,7 @@ | |||
553 | #define MIN_MAX_BANK_3__MAX_VALUE 0x000c | 553 | #define MIN_MAX_BANK_3__MAX_VALUE 0x000c |
554 | 554 | ||
555 | #define PERM_SRC_ID_4 0x930 | 555 | #define PERM_SRC_ID_4 0x930 |
556 | #define PERM_SRC_ID_4__SRCID 0x00ff | 556 | #define PERM_SRC_ID_4__SRCID 0x00ff |
557 | #define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 | 557 | #define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 |
558 | #define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 | 558 | #define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 |
559 | #define PERM_SRC_ID_4__READ_ACTIVE 0x4000 | 559 | #define PERM_SRC_ID_4__READ_ACTIVE 0x4000 |
@@ -570,7 +570,7 @@ | |||
570 | #define MIN_MAX_BANK_4__MAX_VALUE 0x000c | 570 | #define MIN_MAX_BANK_4__MAX_VALUE 0x000c |
571 | 571 | ||
572 | #define PERM_SRC_ID_5 0x970 | 572 | #define PERM_SRC_ID_5 0x970 |
573 | #define PERM_SRC_ID_5__SRCID 0x00ff | 573 | #define PERM_SRC_ID_5__SRCID 0x00ff |
574 | #define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 | 574 | #define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 |
575 | #define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 | 575 | #define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 |
576 | #define PERM_SRC_ID_5__READ_ACTIVE 0x4000 | 576 | #define PERM_SRC_ID_5__READ_ACTIVE 0x4000 |
@@ -587,7 +587,7 @@ | |||
587 | #define MIN_MAX_BANK_5__MAX_VALUE 0x000c | 587 | #define MIN_MAX_BANK_5__MAX_VALUE 0x000c |
588 | 588 | ||
589 | #define PERM_SRC_ID_6 0x9b0 | 589 | #define PERM_SRC_ID_6 0x9b0 |
590 | #define PERM_SRC_ID_6__SRCID 0x00ff | 590 | #define PERM_SRC_ID_6__SRCID 0x00ff |
591 | #define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 | 591 | #define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 |
592 | #define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 | 592 | #define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 |
593 | #define PERM_SRC_ID_6__READ_ACTIVE 0x4000 | 593 | #define PERM_SRC_ID_6__READ_ACTIVE 0x4000 |
@@ -604,7 +604,7 @@ | |||
604 | #define MIN_MAX_BANK_6__MAX_VALUE 0x000c | 604 | #define MIN_MAX_BANK_6__MAX_VALUE 0x000c |
605 | 605 | ||
606 | #define PERM_SRC_ID_7 0x9f0 | 606 | #define PERM_SRC_ID_7 0x9f0 |
607 | #define PERM_SRC_ID_7__SRCID 0x00ff | 607 | #define PERM_SRC_ID_7__SRCID 0x00ff |
608 | #define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 | 608 | #define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 |
609 | #define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 | 609 | #define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 |
610 | #define PERM_SRC_ID_7__READ_ACTIVE 0x4000 | 610 | #define PERM_SRC_ID_7__READ_ACTIVE 0x4000 |
@@ -620,47 +620,6 @@ | |||
620 | #define MIN_MAX_BANK_7__MIN_VALUE 0x0003 | 620 | #define MIN_MAX_BANK_7__MIN_VALUE 0x0003 |
621 | #define MIN_MAX_BANK_7__MAX_VALUE 0x000c | 621 | #define MIN_MAX_BANK_7__MAX_VALUE 0x000c |
622 | 622 | ||
623 | /* flash.h */ | ||
624 | struct device_info_tag { | ||
625 | uint16_t wDeviceMaker; | ||
626 | uint16_t wDeviceID; | ||
627 | uint8_t bDeviceParam0; | ||
628 | uint8_t bDeviceParam1; | ||
629 | uint8_t bDeviceParam2; | ||
630 | uint32_t wDeviceType; | ||
631 | uint32_t wSpectraStartBlock; | ||
632 | uint32_t wSpectraEndBlock; | ||
633 | uint32_t wTotalBlocks; | ||
634 | uint16_t wPagesPerBlock; | ||
635 | uint16_t wPageSize; | ||
636 | uint16_t wPageDataSize; | ||
637 | uint16_t wPageSpareSize; | ||
638 | uint16_t wNumPageSpareFlag; | ||
639 | uint16_t wECCBytesPerSector; | ||
640 | uint32_t wBlockSize; | ||
641 | uint32_t wBlockDataSize; | ||
642 | uint32_t wDataBlockNum; | ||
643 | uint8_t bPlaneNum; | ||
644 | uint16_t wDeviceMainAreaSize; | ||
645 | uint16_t wDeviceSpareAreaSize; | ||
646 | uint16_t wDevicesConnected; | ||
647 | uint16_t wDeviceWidth; | ||
648 | uint16_t wHWRevision; | ||
649 | uint16_t wHWFeatures; | ||
650 | |||
651 | uint16_t wONFIDevFeatures; | ||
652 | uint16_t wONFIOptCommands; | ||
653 | uint16_t wONFITimingMode; | ||
654 | uint16_t wONFIPgmCacheTimingMode; | ||
655 | |||
656 | uint16_t MLCDevice; | ||
657 | uint16_t wSpareSkipBytes; | ||
658 | |||
659 | uint8_t nBitsInPageNumber; | ||
660 | uint8_t nBitsInPageDataSize; | ||
661 | uint8_t nBitsInBlockDataSize; | ||
662 | }; | ||
663 | |||
664 | /* ffsdefs.h */ | 623 | /* ffsdefs.h */ |
665 | #define CLEAR 0 /*use this to clear a field instead of "fail"*/ | 624 | #define CLEAR 0 /*use this to clear a field instead of "fail"*/ |
666 | #define SET 1 /*use this to set a field instead of "pass"*/ | 625 | #define SET 1 /*use this to set a field instead of "pass"*/ |
@@ -684,11 +643,11 @@ struct device_info_tag { | |||
684 | #define NAND_DBG_TRACE 3 | 643 | #define NAND_DBG_TRACE 3 |
685 | 644 | ||
686 | #ifdef VERBOSE | 645 | #ifdef VERBOSE |
687 | #define nand_dbg_print(level, args...) \ | 646 | #define nand_dbg_print(level, args...) \ |
688 | do { \ | 647 | do { \ |
689 | if (level <= nand_debug_level) \ | 648 | if (level <= nand_debug_level) \ |
690 | printk(KERN_ALERT args); \ | 649 | printk(KERN_ALERT args); \ |
691 | } while (0) | 650 | } while (0) |
692 | #else | 651 | #else |
693 | #define nand_dbg_print(level, args...) | 652 | #define nand_dbg_print(level, args...) |
694 | #endif | 653 | #endif |
@@ -772,10 +731,9 @@ struct device_info_tag { | |||
772 | #define ECC_SECTOR_SIZE 512 | 731 | #define ECC_SECTOR_SIZE 512 |
773 | #define LLD_MAX_FLASH_BANKS 4 | 732 | #define LLD_MAX_FLASH_BANKS 4 |
774 | 733 | ||
775 | #define DENALI_BUF_SIZE NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE | 734 | #define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) |
776 | 735 | ||
777 | struct nand_buf | 736 | struct nand_buf { |
778 | { | ||
779 | int head; | 737 | int head; |
780 | int tail; | 738 | int tail; |
781 | uint8_t buf[DENALI_BUF_SIZE]; | 739 | uint8_t buf[DENALI_BUF_SIZE]; |
@@ -788,7 +746,6 @@ struct nand_buf | |||
788 | struct denali_nand_info { | 746 | struct denali_nand_info { |
789 | struct mtd_info mtd; | 747 | struct mtd_info mtd; |
790 | struct nand_chip nand; | 748 | struct nand_chip nand; |
791 | struct device_info_tag dev_info; | ||
792 | int flash_bank; /* currently selected chip */ | 749 | int flash_bank; /* currently selected chip */ |
793 | int status; | 750 | int status; |
794 | int platform; | 751 | int platform; |
@@ -806,11 +763,12 @@ struct denali_nand_info { | |||
806 | uint32_t irq_status; | 763 | uint32_t irq_status; |
807 | int irq_debug_array[32]; | 764 | int irq_debug_array[32]; |
808 | int idx; | 765 | int idx; |
809 | }; | ||
810 | 766 | ||
811 | static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali); | 767 | uint32_t devnum; /* represent how many nands connected */ |
812 | static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali); | 768 | uint32_t fwblks; /* represent how many blocks FW used */ |
813 | static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, uint16_t INT_ENABLE); | 769 | uint32_t totalblks; |
770 | uint32_t blksperchip; | ||
771 | uint32_t bbtskipbytes; | ||
772 | }; | ||
814 | 773 | ||
815 | #endif /*_LLD_NAND_*/ | 774 | #endif /*_LLD_NAND_*/ |
816 | |||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 47067bc98248..b7f8de7b2780 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/mtd/mtd.h> | 29 | #include <linux/mtd/mtd.h> |
30 | #include <linux/mtd/nand.h> | 30 | #include <linux/mtd/nand.h> |
31 | #include <linux/mtd/doc2000.h> | 31 | #include <linux/mtd/doc2000.h> |
32 | #include <linux/mtd/compatmac.h> | ||
33 | #include <linux/mtd/partitions.h> | 32 | #include <linux/mtd/partitions.h> |
34 | #include <linux/mtd/inftl.h> | 33 | #include <linux/mtd/inftl.h> |
35 | 34 | ||
@@ -146,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
146 | uint8_t parity; | 145 | uint8_t parity; |
147 | uint16_t ds[4], s[5], tmp, errval[8], syn[4]; | 146 | uint16_t ds[4], s[5], tmp, errval[8], syn[4]; |
148 | 147 | ||
148 | memset(syn, 0, sizeof(syn)); | ||
149 | /* Convert the ecc bytes into words */ | 149 | /* Convert the ecc bytes into words */ |
150 | ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); | 150 | ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); |
151 | ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); | 151 | ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); |
@@ -169,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
169 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; | 169 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; |
170 | } | 170 | } |
171 | 171 | ||
172 | /* Calc s[i] = s[i] / alpha^(v + i) */ | 172 | /* Calc syn[i] = s[i] / alpha^(v + i) */ |
173 | for (i = 0; i < NROOTS; i++) { | 173 | for (i = 0; i < NROOTS; i++) { |
174 | if (syn[i]) | 174 | if (s[i]) |
175 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); | 175 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); |
176 | } | 176 | } |
177 | /* Call the decoder library */ | 177 | /* Call the decoder library */ |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 0d76b169482f..fcf8ceb277d4 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -39,60 +39,96 @@ | |||
39 | 39 | ||
40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) | 40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) |
41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) | 41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) |
42 | #define nfc_is_v3_2() cpu_is_mx51() | ||
43 | #define nfc_is_v3() nfc_is_v3_2() | ||
42 | 44 | ||
43 | /* Addresses for NFC registers */ | 45 | /* Addresses for NFC registers */ |
44 | #define NFC_BUF_SIZE 0xE00 | 46 | #define NFC_V1_V2_BUF_SIZE (host->regs + 0x00) |
45 | #define NFC_BUF_ADDR 0xE04 | 47 | #define NFC_V1_V2_BUF_ADDR (host->regs + 0x04) |
46 | #define NFC_FLASH_ADDR 0xE06 | 48 | #define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06) |
47 | #define NFC_FLASH_CMD 0xE08 | 49 | #define NFC_V1_V2_FLASH_CMD (host->regs + 0x08) |
48 | #define NFC_CONFIG 0xE0A | 50 | #define NFC_V1_V2_CONFIG (host->regs + 0x0a) |
49 | #define NFC_ECC_STATUS_RESULT 0xE0C | 51 | #define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c) |
50 | #define NFC_RSLTMAIN_AREA 0xE0E | 52 | #define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e) |
51 | #define NFC_RSLTSPARE_AREA 0xE10 | 53 | #define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10) |
52 | #define NFC_WRPROT 0xE12 | 54 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) |
53 | #define NFC_V1_UNLOCKSTART_BLKADDR 0xe14 | 55 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) |
54 | #define NFC_V1_UNLOCKEND_BLKADDR 0xe16 | 56 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) |
55 | #define NFC_V21_UNLOCKSTART_BLKADDR 0xe20 | 57 | #define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20) |
56 | #define NFC_V21_UNLOCKEND_BLKADDR 0xe22 | 58 | #define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22) |
57 | #define NFC_NF_WRPRST 0xE18 | 59 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) |
58 | #define NFC_CONFIG1 0xE1A | 60 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) |
59 | #define NFC_CONFIG2 0xE1C | 61 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) |
60 | 62 | ||
61 | /* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register | 63 | #define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) |
62 | * for Command operation */ | 64 | #define NFC_V1_V2_CONFIG1_SP_EN (1 << 2) |
63 | #define NFC_CMD 0x1 | 65 | #define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) |
64 | 66 | #define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) | |
65 | /* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register | 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) |
66 | * for Address operation */ | 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) |
67 | #define NFC_ADDR 0x2 | 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) |
68 | 70 | #define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) | |
69 | /* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register | 71 | |
70 | * for Input operation */ | 72 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) |
71 | #define NFC_INPUT 0x4 | 73 | |
72 | 74 | /* | |
73 | /* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register | 75 | * Operation modes for the NFC. Valid for v1, v2 and v3 |
74 | * for Data Output operation */ | 76 | * type controllers. |
75 | #define NFC_OUTPUT 0x8 | 77 | */ |
76 | 78 | #define NFC_CMD (1 << 0) | |
77 | /* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register | 79 | #define NFC_ADDR (1 << 1) |
78 | * for Read ID operation */ | 80 | #define NFC_INPUT (1 << 2) |
79 | #define NFC_ID 0x10 | 81 | #define NFC_OUTPUT (1 << 3) |
80 | 82 | #define NFC_ID (1 << 4) | |
81 | /* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register | 83 | #define NFC_STATUS (1 << 5) |
82 | * for Read Status operation */ | 84 | |
83 | #define NFC_STATUS 0x20 | 85 | #define NFC_V3_FLASH_CMD (host->regs_axi + 0x00) |
84 | 86 | #define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04) | |
85 | /* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read | 87 | |
86 | * Status operation */ | 88 | #define NFC_V3_CONFIG1 (host->regs_axi + 0x34) |
87 | #define NFC_INT 0x8000 | 89 | #define NFC_V3_CONFIG1_SP_EN (1 << 0) |
88 | 90 | #define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4) | |
89 | #define NFC_SP_EN (1 << 2) | 91 | |
90 | #define NFC_ECC_EN (1 << 3) | 92 | #define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38) |
91 | #define NFC_INT_MSK (1 << 4) | 93 | |
92 | #define NFC_BIG (1 << 5) | 94 | #define NFC_V3_LAUNCH (host->regs_axi + 0x40) |
93 | #define NFC_RST (1 << 6) | 95 | |
94 | #define NFC_CE (1 << 7) | 96 | #define NFC_V3_WRPROT (host->regs_ip + 0x0) |
95 | #define NFC_ONE_CYCLE (1 << 8) | 97 | #define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0) |
98 | #define NFC_V3_WRPROT_LOCK (1 << 1) | ||
99 | #define NFC_V3_WRPROT_UNLOCK (1 << 2) | ||
100 | #define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) | ||
101 | |||
102 | #define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04) | ||
103 | |||
104 | #define NFC_V3_CONFIG2 (host->regs_ip + 0x24) | ||
105 | #define NFC_V3_CONFIG2_PS_512 (0 << 0) | ||
106 | #define NFC_V3_CONFIG2_PS_2048 (1 << 0) | ||
107 | #define NFC_V3_CONFIG2_PS_4096 (2 << 0) | ||
108 | #define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) | ||
109 | #define NFC_V3_CONFIG2_ECC_EN (1 << 3) | ||
110 | #define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) | ||
111 | #define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5) | ||
112 | #define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) | ||
113 | #define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) | ||
114 | #define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12) | ||
115 | #define NFC_V3_CONFIG2_INT_MSK (1 << 15) | ||
116 | #define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) | ||
117 | #define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) | ||
118 | |||
119 | #define NFC_V3_CONFIG3 (host->regs_ip + 0x28) | ||
120 | #define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) | ||
121 | #define NFC_V3_CONFIG3_FW8 (1 << 3) | ||
122 | #define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) | ||
123 | #define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12) | ||
124 | #define NFC_V3_CONFIG3_RBB_MODE (1 << 15) | ||
125 | #define NFC_V3_CONFIG3_NO_SDMA (1 << 20) | ||
126 | |||
127 | #define NFC_V3_IPC (host->regs_ip + 0x2C) | ||
128 | #define NFC_V3_IPC_CREQ (1 << 0) | ||
129 | #define NFC_V3_IPC_INT (1 << 31) | ||
130 | |||
131 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) | ||
96 | 132 | ||
97 | struct mxc_nand_host { | 133 | struct mxc_nand_host { |
98 | struct mtd_info mtd; | 134 | struct mtd_info mtd; |
@@ -102,20 +138,30 @@ struct mxc_nand_host { | |||
102 | 138 | ||
103 | void *spare0; | 139 | void *spare0; |
104 | void *main_area0; | 140 | void *main_area0; |
105 | void *main_area1; | ||
106 | 141 | ||
107 | void __iomem *base; | 142 | void __iomem *base; |
108 | void __iomem *regs; | 143 | void __iomem *regs; |
144 | void __iomem *regs_axi; | ||
145 | void __iomem *regs_ip; | ||
109 | int status_request; | 146 | int status_request; |
110 | struct clk *clk; | 147 | struct clk *clk; |
111 | int clk_act; | 148 | int clk_act; |
112 | int irq; | 149 | int irq; |
150 | int eccsize; | ||
113 | 151 | ||
114 | wait_queue_head_t irq_waitq; | 152 | wait_queue_head_t irq_waitq; |
115 | 153 | ||
116 | uint8_t *data_buf; | 154 | uint8_t *data_buf; |
117 | unsigned int buf_start; | 155 | unsigned int buf_start; |
118 | int spare_len; | 156 | int spare_len; |
157 | |||
158 | void (*preset)(struct mtd_info *); | ||
159 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
160 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
161 | void (*send_page)(struct mtd_info *, unsigned int); | ||
162 | void (*send_read_id)(struct mxc_nand_host *); | ||
163 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
164 | int (*check_int)(struct mxc_nand_host *); | ||
119 | }; | 165 | }; |
120 | 166 | ||
121 | /* OOB placement block for use with hardware ecc generation */ | 167 | /* OOB placement block for use with hardware ecc generation */ |
@@ -175,34 +221,52 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
175 | return IRQ_HANDLED; | 221 | return IRQ_HANDLED; |
176 | } | 222 | } |
177 | 223 | ||
224 | static int check_int_v3(struct mxc_nand_host *host) | ||
225 | { | ||
226 | uint32_t tmp; | ||
227 | |||
228 | tmp = readl(NFC_V3_IPC); | ||
229 | if (!(tmp & NFC_V3_IPC_INT)) | ||
230 | return 0; | ||
231 | |||
232 | tmp &= ~NFC_V3_IPC_INT; | ||
233 | writel(tmp, NFC_V3_IPC); | ||
234 | |||
235 | return 1; | ||
236 | } | ||
237 | |||
238 | static int check_int_v1_v2(struct mxc_nand_host *host) | ||
239 | { | ||
240 | uint32_t tmp; | ||
241 | |||
242 | tmp = readw(NFC_V1_V2_CONFIG2); | ||
243 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | ||
244 | return 0; | ||
245 | |||
246 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
178 | /* This function polls the NANDFC to wait for the basic operation to | 251 | /* This function polls the NANDFC to wait for the basic operation to |
179 | * complete by checking the INT bit of config2 register. | 252 | * complete by checking the INT bit of config2 register. |
180 | */ | 253 | */ |
181 | static void wait_op_done(struct mxc_nand_host *host, int useirq) | 254 | static void wait_op_done(struct mxc_nand_host *host, int useirq) |
182 | { | 255 | { |
183 | uint16_t tmp; | ||
184 | int max_retries = 8000; | 256 | int max_retries = 8000; |
185 | 257 | ||
186 | if (useirq) { | 258 | if (useirq) { |
187 | if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { | 259 | if (!host->check_int(host)) { |
188 | 260 | ||
189 | enable_irq(host->irq); | 261 | enable_irq(host->irq); |
190 | 262 | ||
191 | wait_event(host->irq_waitq, | 263 | wait_event(host->irq_waitq, host->check_int(host)); |
192 | readw(host->regs + NFC_CONFIG2) & NFC_INT); | ||
193 | |||
194 | tmp = readw(host->regs + NFC_CONFIG2); | ||
195 | tmp &= ~NFC_INT; | ||
196 | writew(tmp, host->regs + NFC_CONFIG2); | ||
197 | } | 264 | } |
198 | } else { | 265 | } else { |
199 | while (max_retries-- > 0) { | 266 | while (max_retries-- > 0) { |
200 | if (readw(host->regs + NFC_CONFIG2) & NFC_INT) { | 267 | if (host->check_int(host)) |
201 | tmp = readw(host->regs + NFC_CONFIG2); | ||
202 | tmp &= ~NFC_INT; | ||
203 | writew(tmp, host->regs + NFC_CONFIG2); | ||
204 | break; | 268 | break; |
205 | } | 269 | |
206 | udelay(1); | 270 | udelay(1); |
207 | } | 271 | } |
208 | if (max_retries < 0) | 272 | if (max_retries < 0) |
@@ -211,21 +275,33 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
211 | } | 275 | } |
212 | } | 276 | } |
213 | 277 | ||
278 | static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) | ||
279 | { | ||
280 | /* fill command */ | ||
281 | writel(cmd, NFC_V3_FLASH_CMD); | ||
282 | |||
283 | /* send out command */ | ||
284 | writel(NFC_CMD, NFC_V3_LAUNCH); | ||
285 | |||
286 | /* Wait for operation to complete */ | ||
287 | wait_op_done(host, useirq); | ||
288 | } | ||
289 | |||
214 | /* This function issues the specified command to the NAND device and | 290 | /* This function issues the specified command to the NAND device and |
215 | * waits for completion. */ | 291 | * waits for completion. */ |
216 | static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | 292 | static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) |
217 | { | 293 | { |
218 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); | 294 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); |
219 | 295 | ||
220 | writew(cmd, host->regs + NFC_FLASH_CMD); | 296 | writew(cmd, NFC_V1_V2_FLASH_CMD); |
221 | writew(NFC_CMD, host->regs + NFC_CONFIG2); | 297 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); |
222 | 298 | ||
223 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { | 299 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { |
224 | int max_retries = 100; | 300 | int max_retries = 100; |
225 | /* Reset completion is indicated by NFC_CONFIG2 */ | 301 | /* Reset completion is indicated by NFC_CONFIG2 */ |
226 | /* being set to 0 */ | 302 | /* being set to 0 */ |
227 | while (max_retries-- > 0) { | 303 | while (max_retries-- > 0) { |
228 | if (readw(host->regs + NFC_CONFIG2) == 0) { | 304 | if (readw(NFC_V1_V2_CONFIG2) == 0) { |
229 | break; | 305 | break; |
230 | } | 306 | } |
231 | udelay(1); | 307 | udelay(1); |
@@ -239,21 +315,48 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
239 | } | 315 | } |
240 | } | 316 | } |
241 | 317 | ||
318 | static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast) | ||
319 | { | ||
320 | /* fill address */ | ||
321 | writel(addr, NFC_V3_FLASH_ADDR0); | ||
322 | |||
323 | /* send out address */ | ||
324 | writel(NFC_ADDR, NFC_V3_LAUNCH); | ||
325 | |||
326 | wait_op_done(host, 0); | ||
327 | } | ||
328 | |||
242 | /* This function sends an address (or partial address) to the | 329 | /* This function sends an address (or partial address) to the |
243 | * NAND device. The address is used to select the source/destination for | 330 | * NAND device. The address is used to select the source/destination for |
244 | * a NAND command. */ | 331 | * a NAND command. */ |
245 | static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast) | 332 | static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast) |
246 | { | 333 | { |
247 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); | 334 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); |
248 | 335 | ||
249 | writew(addr, host->regs + NFC_FLASH_ADDR); | 336 | writew(addr, NFC_V1_V2_FLASH_ADDR); |
250 | writew(NFC_ADDR, host->regs + NFC_CONFIG2); | 337 | writew(NFC_ADDR, NFC_V1_V2_CONFIG2); |
251 | 338 | ||
252 | /* Wait for operation to complete */ | 339 | /* Wait for operation to complete */ |
253 | wait_op_done(host, islast); | 340 | wait_op_done(host, islast); |
254 | } | 341 | } |
255 | 342 | ||
256 | static void send_page(struct mtd_info *mtd, unsigned int ops) | 343 | static void send_page_v3(struct mtd_info *mtd, unsigned int ops) |
344 | { | ||
345 | struct nand_chip *nand_chip = mtd->priv; | ||
346 | struct mxc_nand_host *host = nand_chip->priv; | ||
347 | uint32_t tmp; | ||
348 | |||
349 | tmp = readl(NFC_V3_CONFIG1); | ||
350 | tmp &= ~(7 << 4); | ||
351 | writel(tmp, NFC_V3_CONFIG1); | ||
352 | |||
353 | /* transfer data from NFC ram to nand */ | ||
354 | writel(ops, NFC_V3_LAUNCH); | ||
355 | |||
356 | wait_op_done(host, false); | ||
357 | } | ||
358 | |||
359 | static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | ||
257 | { | 360 | { |
258 | struct nand_chip *nand_chip = mtd->priv; | 361 | struct nand_chip *nand_chip = mtd->priv; |
259 | struct mxc_nand_host *host = nand_chip->priv; | 362 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -267,24 +370,34 @@ static void send_page(struct mtd_info *mtd, unsigned int ops) | |||
267 | for (i = 0; i < bufs; i++) { | 370 | for (i = 0; i < bufs; i++) { |
268 | 371 | ||
269 | /* NANDFC buffer 0 is used for page read/write */ | 372 | /* NANDFC buffer 0 is used for page read/write */ |
270 | writew(i, host->regs + NFC_BUF_ADDR); | 373 | writew(i, NFC_V1_V2_BUF_ADDR); |
271 | 374 | ||
272 | writew(ops, host->regs + NFC_CONFIG2); | 375 | writew(ops, NFC_V1_V2_CONFIG2); |
273 | 376 | ||
274 | /* Wait for operation to complete */ | 377 | /* Wait for operation to complete */ |
275 | wait_op_done(host, true); | 378 | wait_op_done(host, true); |
276 | } | 379 | } |
277 | } | 380 | } |
278 | 381 | ||
382 | static void send_read_id_v3(struct mxc_nand_host *host) | ||
383 | { | ||
384 | /* Read ID into main buffer */ | ||
385 | writel(NFC_ID, NFC_V3_LAUNCH); | ||
386 | |||
387 | wait_op_done(host, true); | ||
388 | |||
389 | memcpy(host->data_buf, host->main_area0, 16); | ||
390 | } | ||
391 | |||
279 | /* Request the NANDFC to perform a read of the NAND device ID. */ | 392 | /* Request the NANDFC to perform a read of the NAND device ID. */ |
280 | static void send_read_id(struct mxc_nand_host *host) | 393 | static void send_read_id_v1_v2(struct mxc_nand_host *host) |
281 | { | 394 | { |
282 | struct nand_chip *this = &host->nand; | 395 | struct nand_chip *this = &host->nand; |
283 | 396 | ||
284 | /* NANDFC buffer 0 is used for device ID output */ | 397 | /* NANDFC buffer 0 is used for device ID output */ |
285 | writew(0x0, host->regs + NFC_BUF_ADDR); | 398 | writew(0x0, NFC_V1_V2_BUF_ADDR); |
286 | 399 | ||
287 | writew(NFC_ID, host->regs + NFC_CONFIG2); | 400 | writew(NFC_ID, NFC_V1_V2_CONFIG2); |
288 | 401 | ||
289 | /* Wait for operation to complete */ | 402 | /* Wait for operation to complete */ |
290 | wait_op_done(host, true); | 403 | wait_op_done(host, true); |
@@ -301,29 +414,36 @@ static void send_read_id(struct mxc_nand_host *host) | |||
301 | memcpy(host->data_buf, host->main_area0, 16); | 414 | memcpy(host->data_buf, host->main_area0, 16); |
302 | } | 415 | } |
303 | 416 | ||
417 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | ||
418 | { | ||
419 | writew(NFC_STATUS, NFC_V3_LAUNCH); | ||
420 | wait_op_done(host, true); | ||
421 | |||
422 | return readl(NFC_V3_CONFIG1) >> 16; | ||
423 | } | ||
424 | |||
304 | /* This function requests the NANDFC to perform a read of the | 425 | /* This function requests the NANDFC to perform a read of the |
305 | * NAND device status and returns the current status. */ | 426 | * NAND device status and returns the current status. */ |
306 | static uint16_t get_dev_status(struct mxc_nand_host *host) | 427 | static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host) |
307 | { | 428 | { |
308 | void __iomem *main_buf = host->main_area1; | 429 | void __iomem *main_buf = host->main_area0; |
309 | uint32_t store; | 430 | uint32_t store; |
310 | uint16_t ret; | 431 | uint16_t ret; |
311 | /* Issue status request to NAND device */ | ||
312 | 432 | ||
313 | /* store the main area1 first word, later do recovery */ | 433 | writew(0x0, NFC_V1_V2_BUF_ADDR); |
314 | store = readl(main_buf); | ||
315 | /* NANDFC buffer 1 is used for device status to prevent | ||
316 | * corruption of read/write buffer on status requests. */ | ||
317 | writew(1, host->regs + NFC_BUF_ADDR); | ||
318 | 434 | ||
319 | writew(NFC_STATUS, host->regs + NFC_CONFIG2); | 435 | /* |
436 | * The device status is stored in main_area0. To | ||
437 | * prevent corruption of the buffer save the value | ||
438 | * and restore it afterwards. | ||
439 | */ | ||
440 | store = readl(main_buf); | ||
320 | 441 | ||
321 | /* Wait for operation to complete */ | 442 | writew(NFC_STATUS, NFC_V1_V2_CONFIG2); |
322 | wait_op_done(host, true); | 443 | wait_op_done(host, true); |
323 | 444 | ||
324 | /* Status is placed in first word of main buffer */ | ||
325 | /* get status, then recovery area 1 data */ | ||
326 | ret = readw(main_buf); | 445 | ret = readw(main_buf); |
446 | |||
327 | writel(store, main_buf); | 447 | writel(store, main_buf); |
328 | 448 | ||
329 | return ret; | 449 | return ret; |
@@ -347,7 +467,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) | |||
347 | */ | 467 | */ |
348 | } | 468 | } |
349 | 469 | ||
350 | static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | 470 | static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, |
351 | u_char *read_ecc, u_char *calc_ecc) | 471 | u_char *read_ecc, u_char *calc_ecc) |
352 | { | 472 | { |
353 | struct nand_chip *nand_chip = mtd->priv; | 473 | struct nand_chip *nand_chip = mtd->priv; |
@@ -358,7 +478,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
358 | * additional correction. 2-Bit errors cannot be corrected by | 478 | * additional correction. 2-Bit errors cannot be corrected by |
359 | * HW ECC, so we need to return failure | 479 | * HW ECC, so we need to return failure |
360 | */ | 480 | */ |
361 | uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT); | 481 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); |
362 | 482 | ||
363 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | 483 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { |
364 | DEBUG(MTD_DEBUG_LEVEL0, | 484 | DEBUG(MTD_DEBUG_LEVEL0, |
@@ -369,6 +489,43 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
369 | return 0; | 489 | return 0; |
370 | } | 490 | } |
371 | 491 | ||
492 | static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, | ||
493 | u_char *read_ecc, u_char *calc_ecc) | ||
494 | { | ||
495 | struct nand_chip *nand_chip = mtd->priv; | ||
496 | struct mxc_nand_host *host = nand_chip->priv; | ||
497 | u32 ecc_stat, err; | ||
498 | int no_subpages = 1; | ||
499 | int ret = 0; | ||
500 | u8 ecc_bit_mask, err_limit; | ||
501 | |||
502 | ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf; | ||
503 | err_limit = (host->eccsize == 4) ? 0x4 : 0x8; | ||
504 | |||
505 | no_subpages = mtd->writesize >> 9; | ||
506 | |||
507 | if (nfc_is_v21()) | ||
508 | ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
509 | else | ||
510 | ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); | ||
511 | |||
512 | do { | ||
513 | err = ecc_stat & ecc_bit_mask; | ||
514 | if (err > err_limit) { | ||
515 | printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); | ||
516 | return -1; | ||
517 | } else { | ||
518 | ret += err; | ||
519 | } | ||
520 | ecc_stat >>= 4; | ||
521 | } while (--no_subpages); | ||
522 | |||
523 | mtd->ecc_stats.corrected += ret; | ||
524 | pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); | ||
525 | |||
526 | return ret; | ||
527 | } | ||
528 | |||
372 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | 529 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
373 | u_char *ecc_code) | 530 | u_char *ecc_code) |
374 | { | 531 | { |
@@ -383,7 +540,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |||
383 | 540 | ||
384 | /* Check for status request */ | 541 | /* Check for status request */ |
385 | if (host->status_request) | 542 | if (host->status_request) |
386 | return get_dev_status(host) & 0xFF; | 543 | return host->get_dev_status(host) & 0xFF; |
387 | 544 | ||
388 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | 545 | ret = *(uint8_t *)(host->data_buf + host->buf_start); |
389 | host->buf_start++; | 546 | host->buf_start++; |
@@ -519,71 +676,163 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
519 | * we will used the saved column address to index into | 676 | * we will used the saved column address to index into |
520 | * the full page. | 677 | * the full page. |
521 | */ | 678 | */ |
522 | send_addr(host, 0, page_addr == -1); | 679 | host->send_addr(host, 0, page_addr == -1); |
523 | if (mtd->writesize > 512) | 680 | if (mtd->writesize > 512) |
524 | /* another col addr cycle for 2k page */ | 681 | /* another col addr cycle for 2k page */ |
525 | send_addr(host, 0, false); | 682 | host->send_addr(host, 0, false); |
526 | } | 683 | } |
527 | 684 | ||
528 | /* Write out page address, if necessary */ | 685 | /* Write out page address, if necessary */ |
529 | if (page_addr != -1) { | 686 | if (page_addr != -1) { |
530 | /* paddr_0 - p_addr_7 */ | 687 | /* paddr_0 - p_addr_7 */ |
531 | send_addr(host, (page_addr & 0xff), false); | 688 | host->send_addr(host, (page_addr & 0xff), false); |
532 | 689 | ||
533 | if (mtd->writesize > 512) { | 690 | if (mtd->writesize > 512) { |
534 | if (mtd->size >= 0x10000000) { | 691 | if (mtd->size >= 0x10000000) { |
535 | /* paddr_8 - paddr_15 */ | 692 | /* paddr_8 - paddr_15 */ |
536 | send_addr(host, (page_addr >> 8) & 0xff, false); | 693 | host->send_addr(host, (page_addr >> 8) & 0xff, false); |
537 | send_addr(host, (page_addr >> 16) & 0xff, true); | 694 | host->send_addr(host, (page_addr >> 16) & 0xff, true); |
538 | } else | 695 | } else |
539 | /* paddr_8 - paddr_15 */ | 696 | /* paddr_8 - paddr_15 */ |
540 | send_addr(host, (page_addr >> 8) & 0xff, true); | 697 | host->send_addr(host, (page_addr >> 8) & 0xff, true); |
541 | } else { | 698 | } else { |
542 | /* One more address cycle for higher density devices */ | 699 | /* One more address cycle for higher density devices */ |
543 | if (mtd->size >= 0x4000000) { | 700 | if (mtd->size >= 0x4000000) { |
544 | /* paddr_8 - paddr_15 */ | 701 | /* paddr_8 - paddr_15 */ |
545 | send_addr(host, (page_addr >> 8) & 0xff, false); | 702 | host->send_addr(host, (page_addr >> 8) & 0xff, false); |
546 | send_addr(host, (page_addr >> 16) & 0xff, true); | 703 | host->send_addr(host, (page_addr >> 16) & 0xff, true); |
547 | } else | 704 | } else |
548 | /* paddr_8 - paddr_15 */ | 705 | /* paddr_8 - paddr_15 */ |
549 | send_addr(host, (page_addr >> 8) & 0xff, true); | 706 | host->send_addr(host, (page_addr >> 8) & 0xff, true); |
550 | } | 707 | } |
551 | } | 708 | } |
552 | } | 709 | } |
553 | 710 | ||
554 | static void preset(struct mtd_info *mtd) | 711 | /* |
712 | * v2 and v3 type controllers can do 4bit or 8bit ecc depending | ||
713 | * on how much oob the nand chip has. For 8bit ecc we need at least | ||
714 | * 26 bytes of oob data per 512 byte block. | ||
715 | */ | ||
716 | static int get_eccsize(struct mtd_info *mtd) | ||
717 | { | ||
718 | int oobbytes_per_512 = 0; | ||
719 | |||
720 | oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize; | ||
721 | |||
722 | if (oobbytes_per_512 < 26) | ||
723 | return 4; | ||
724 | else | ||
725 | return 8; | ||
726 | } | ||
727 | |||
728 | static void preset_v1_v2(struct mtd_info *mtd) | ||
555 | { | 729 | { |
556 | struct nand_chip *nand_chip = mtd->priv; | 730 | struct nand_chip *nand_chip = mtd->priv; |
557 | struct mxc_nand_host *host = nand_chip->priv; | 731 | struct mxc_nand_host *host = nand_chip->priv; |
558 | uint16_t tmp; | 732 | uint16_t tmp; |
559 | 733 | ||
560 | /* enable interrupt, disable spare enable */ | 734 | /* enable interrupt, disable spare enable */ |
561 | tmp = readw(host->regs + NFC_CONFIG1); | 735 | tmp = readw(NFC_V1_V2_CONFIG1); |
562 | tmp &= ~NFC_INT_MSK; | 736 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; |
563 | tmp &= ~NFC_SP_EN; | 737 | tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; |
564 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 738 | if (nand_chip->ecc.mode == NAND_ECC_HW) { |
565 | tmp |= NFC_ECC_EN; | 739 | tmp |= NFC_V1_V2_CONFIG1_ECC_EN; |
740 | } else { | ||
741 | tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; | ||
742 | } | ||
743 | |||
744 | if (nfc_is_v21() && mtd->writesize) { | ||
745 | host->eccsize = get_eccsize(mtd); | ||
746 | if (host->eccsize == 4) | ||
747 | tmp |= NFC_V2_CONFIG1_ECC_MODE_4; | ||
566 | } else { | 748 | } else { |
567 | tmp &= ~NFC_ECC_EN; | 749 | host->eccsize = 1; |
568 | } | 750 | } |
569 | writew(tmp, host->regs + NFC_CONFIG1); | 751 | |
752 | writew(tmp, NFC_V1_V2_CONFIG1); | ||
570 | /* preset operation */ | 753 | /* preset operation */ |
571 | 754 | ||
572 | /* Unlock the internal RAM Buffer */ | 755 | /* Unlock the internal RAM Buffer */ |
573 | writew(0x2, host->regs + NFC_CONFIG); | 756 | writew(0x2, NFC_V1_V2_CONFIG); |
574 | 757 | ||
575 | /* Blocks to be unlocked */ | 758 | /* Blocks to be unlocked */ |
576 | if (nfc_is_v21()) { | 759 | if (nfc_is_v21()) { |
577 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | 760 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR); |
578 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | 761 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR); |
579 | } else if (nfc_is_v1()) { | 762 | } else if (nfc_is_v1()) { |
580 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | 763 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); |
581 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | 764 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); |
582 | } else | 765 | } else |
583 | BUG(); | 766 | BUG(); |
584 | 767 | ||
585 | /* Unlock Block Command for given address range */ | 768 | /* Unlock Block Command for given address range */ |
586 | writew(0x4, host->regs + NFC_WRPROT); | 769 | writew(0x4, NFC_V1_V2_WRPROT); |
770 | } | ||
771 | |||
772 | static void preset_v3(struct mtd_info *mtd) | ||
773 | { | ||
774 | struct nand_chip *chip = mtd->priv; | ||
775 | struct mxc_nand_host *host = chip->priv; | ||
776 | uint32_t config2, config3; | ||
777 | int i, addr_phases; | ||
778 | |||
779 | writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1); | ||
780 | writel(NFC_V3_IPC_CREQ, NFC_V3_IPC); | ||
781 | |||
782 | /* Unlock the internal RAM Buffer */ | ||
783 | writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, | ||
784 | NFC_V3_WRPROT); | ||
785 | |||
786 | /* Blocks to be unlocked */ | ||
787 | for (i = 0; i < NAND_MAX_CHIPS; i++) | ||
788 | writel(0x0 | (0xffff << 16), | ||
789 | NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2)); | ||
790 | |||
791 | writel(0, NFC_V3_IPC); | ||
792 | |||
793 | config2 = NFC_V3_CONFIG2_ONE_CYCLE | | ||
794 | NFC_V3_CONFIG2_2CMD_PHASES | | ||
795 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | | ||
796 | NFC_V3_CONFIG2_ST_CMD(0x70) | | ||
797 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; | ||
798 | |||
799 | if (chip->ecc.mode == NAND_ECC_HW) | ||
800 | config2 |= NFC_V3_CONFIG2_ECC_EN; | ||
801 | |||
802 | addr_phases = fls(chip->pagemask) >> 3; | ||
803 | |||
804 | if (mtd->writesize == 2048) { | ||
805 | config2 |= NFC_V3_CONFIG2_PS_2048; | ||
806 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases); | ||
807 | } else if (mtd->writesize == 4096) { | ||
808 | config2 |= NFC_V3_CONFIG2_PS_4096; | ||
809 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases); | ||
810 | } else { | ||
811 | config2 |= NFC_V3_CONFIG2_PS_512; | ||
812 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1); | ||
813 | } | ||
814 | |||
815 | if (mtd->writesize) { | ||
816 | config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6); | ||
817 | host->eccsize = get_eccsize(mtd); | ||
818 | if (host->eccsize == 8) | ||
819 | config2 |= NFC_V3_CONFIG2_ECC_MODE_8; | ||
820 | } | ||
821 | |||
822 | writel(config2, NFC_V3_CONFIG2); | ||
823 | |||
824 | config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) | | ||
825 | NFC_V3_CONFIG3_NO_SDMA | | ||
826 | NFC_V3_CONFIG3_RBB_MODE | | ||
827 | NFC_V3_CONFIG3_SBB(6) | /* Reset default */ | ||
828 | NFC_V3_CONFIG3_ADD_OP(0); | ||
829 | |||
830 | if (!(chip->options & NAND_BUSWIDTH_16)) | ||
831 | config3 |= NFC_V3_CONFIG3_FW8; | ||
832 | |||
833 | writel(config3, NFC_V3_CONFIG3); | ||
834 | |||
835 | writel(0, NFC_V3_DELAY_LINE); | ||
587 | } | 836 | } |
588 | 837 | ||
589 | /* Used by the upper layer to write command to NAND Flash for | 838 | /* Used by the upper layer to write command to NAND Flash for |
@@ -604,15 +853,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
604 | /* Command pre-processing step */ | 853 | /* Command pre-processing step */ |
605 | switch (command) { | 854 | switch (command) { |
606 | case NAND_CMD_RESET: | 855 | case NAND_CMD_RESET: |
607 | send_cmd(host, command, false); | 856 | host->preset(mtd); |
608 | preset(mtd); | 857 | host->send_cmd(host, command, false); |
609 | break; | 858 | break; |
610 | 859 | ||
611 | case NAND_CMD_STATUS: | 860 | case NAND_CMD_STATUS: |
612 | host->buf_start = 0; | 861 | host->buf_start = 0; |
613 | host->status_request = true; | 862 | host->status_request = true; |
614 | 863 | ||
615 | send_cmd(host, command, true); | 864 | host->send_cmd(host, command, true); |
616 | mxc_do_addr_cycle(mtd, column, page_addr); | 865 | mxc_do_addr_cycle(mtd, column, page_addr); |
617 | break; | 866 | break; |
618 | 867 | ||
@@ -625,13 +874,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
625 | 874 | ||
626 | command = NAND_CMD_READ0; /* only READ0 is valid */ | 875 | command = NAND_CMD_READ0; /* only READ0 is valid */ |
627 | 876 | ||
628 | send_cmd(host, command, false); | 877 | host->send_cmd(host, command, false); |
629 | mxc_do_addr_cycle(mtd, column, page_addr); | 878 | mxc_do_addr_cycle(mtd, column, page_addr); |
630 | 879 | ||
631 | if (mtd->writesize > 512) | 880 | if (mtd->writesize > 512) |
632 | send_cmd(host, NAND_CMD_READSTART, true); | 881 | host->send_cmd(host, NAND_CMD_READSTART, true); |
633 | 882 | ||
634 | send_page(mtd, NFC_OUTPUT); | 883 | host->send_page(mtd, NFC_OUTPUT); |
635 | 884 | ||
636 | memcpy(host->data_buf, host->main_area0, mtd->writesize); | 885 | memcpy(host->data_buf, host->main_area0, mtd->writesize); |
637 | copy_spare(mtd, true); | 886 | copy_spare(mtd, true); |
@@ -644,28 +893,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
644 | 893 | ||
645 | host->buf_start = column; | 894 | host->buf_start = column; |
646 | 895 | ||
647 | send_cmd(host, command, false); | 896 | host->send_cmd(host, command, false); |
648 | mxc_do_addr_cycle(mtd, column, page_addr); | 897 | mxc_do_addr_cycle(mtd, column, page_addr); |
649 | break; | 898 | break; |
650 | 899 | ||
651 | case NAND_CMD_PAGEPROG: | 900 | case NAND_CMD_PAGEPROG: |
652 | memcpy(host->main_area0, host->data_buf, mtd->writesize); | 901 | memcpy(host->main_area0, host->data_buf, mtd->writesize); |
653 | copy_spare(mtd, false); | 902 | copy_spare(mtd, false); |
654 | send_page(mtd, NFC_INPUT); | 903 | host->send_page(mtd, NFC_INPUT); |
655 | send_cmd(host, command, true); | 904 | host->send_cmd(host, command, true); |
656 | mxc_do_addr_cycle(mtd, column, page_addr); | 905 | mxc_do_addr_cycle(mtd, column, page_addr); |
657 | break; | 906 | break; |
658 | 907 | ||
659 | case NAND_CMD_READID: | 908 | case NAND_CMD_READID: |
660 | send_cmd(host, command, true); | 909 | host->send_cmd(host, command, true); |
661 | mxc_do_addr_cycle(mtd, column, page_addr); | 910 | mxc_do_addr_cycle(mtd, column, page_addr); |
662 | send_read_id(host); | 911 | host->send_read_id(host); |
663 | host->buf_start = column; | 912 | host->buf_start = column; |
664 | break; | 913 | break; |
665 | 914 | ||
666 | case NAND_CMD_ERASE1: | 915 | case NAND_CMD_ERASE1: |
667 | case NAND_CMD_ERASE2: | 916 | case NAND_CMD_ERASE2: |
668 | send_cmd(host, command, false); | 917 | host->send_cmd(host, command, false); |
669 | mxc_do_addr_cycle(mtd, column, page_addr); | 918 | mxc_do_addr_cycle(mtd, column, page_addr); |
670 | 919 | ||
671 | break; | 920 | break; |
@@ -761,22 +1010,55 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
761 | } | 1010 | } |
762 | 1011 | ||
763 | host->main_area0 = host->base; | 1012 | host->main_area0 = host->base; |
764 | host->main_area1 = host->base + 0x200; | 1013 | |
1014 | if (nfc_is_v1() || nfc_is_v21()) { | ||
1015 | host->preset = preset_v1_v2; | ||
1016 | host->send_cmd = send_cmd_v1_v2; | ||
1017 | host->send_addr = send_addr_v1_v2; | ||
1018 | host->send_page = send_page_v1_v2; | ||
1019 | host->send_read_id = send_read_id_v1_v2; | ||
1020 | host->get_dev_status = get_dev_status_v1_v2; | ||
1021 | host->check_int = check_int_v1_v2; | ||
1022 | } | ||
765 | 1023 | ||
766 | if (nfc_is_v21()) { | 1024 | if (nfc_is_v21()) { |
767 | host->regs = host->base + 0x1000; | 1025 | host->regs = host->base + 0x1e00; |
768 | host->spare0 = host->base + 0x1000; | 1026 | host->spare0 = host->base + 0x1000; |
769 | host->spare_len = 64; | 1027 | host->spare_len = 64; |
770 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1028 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
771 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1029 | oob_largepage = &nandv2_hw_eccoob_largepage; |
772 | this->ecc.bytes = 9; | 1030 | this->ecc.bytes = 9; |
773 | } else if (nfc_is_v1()) { | 1031 | } else if (nfc_is_v1()) { |
774 | host->regs = host->base; | 1032 | host->regs = host->base + 0xe00; |
775 | host->spare0 = host->base + 0x800; | 1033 | host->spare0 = host->base + 0x800; |
776 | host->spare_len = 16; | 1034 | host->spare_len = 16; |
777 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 1035 | oob_smallpage = &nandv1_hw_eccoob_smallpage; |
778 | oob_largepage = &nandv1_hw_eccoob_largepage; | 1036 | oob_largepage = &nandv1_hw_eccoob_largepage; |
779 | this->ecc.bytes = 3; | 1037 | this->ecc.bytes = 3; |
1038 | host->eccsize = 1; | ||
1039 | } else if (nfc_is_v3_2()) { | ||
1040 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1041 | if (!res) { | ||
1042 | err = -ENODEV; | ||
1043 | goto eirq; | ||
1044 | } | ||
1045 | host->regs_ip = ioremap(res->start, resource_size(res)); | ||
1046 | if (!host->regs_ip) { | ||
1047 | err = -ENOMEM; | ||
1048 | goto eirq; | ||
1049 | } | ||
1050 | host->regs_axi = host->base + 0x1e00; | ||
1051 | host->spare0 = host->base + 0x1000; | ||
1052 | host->spare_len = 64; | ||
1053 | host->preset = preset_v3; | ||
1054 | host->send_cmd = send_cmd_v3; | ||
1055 | host->send_addr = send_addr_v3; | ||
1056 | host->send_page = send_page_v3; | ||
1057 | host->send_read_id = send_read_id_v3; | ||
1058 | host->check_int = check_int_v3; | ||
1059 | host->get_dev_status = get_dev_status_v3; | ||
1060 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | ||
1061 | oob_largepage = &nandv2_hw_eccoob_largepage; | ||
780 | } else | 1062 | } else |
781 | BUG(); | 1063 | BUG(); |
782 | 1064 | ||
@@ -786,7 +1068,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
786 | if (pdata->hw_ecc) { | 1068 | if (pdata->hw_ecc) { |
787 | this->ecc.calculate = mxc_nand_calculate_ecc; | 1069 | this->ecc.calculate = mxc_nand_calculate_ecc; |
788 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 1070 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
789 | this->ecc.correct = mxc_nand_correct_data; | 1071 | if (nfc_is_v1()) |
1072 | this->ecc.correct = mxc_nand_correct_data_v1; | ||
1073 | else | ||
1074 | this->ecc.correct = mxc_nand_correct_data_v2_v3; | ||
790 | this->ecc.mode = NAND_ECC_HW; | 1075 | this->ecc.mode = NAND_ECC_HW; |
791 | } else { | 1076 | } else { |
792 | this->ecc.mode = NAND_ECC_SOFT; | 1077 | this->ecc.mode = NAND_ECC_SOFT; |
@@ -817,6 +1102,9 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
817 | goto escan; | 1102 | goto escan; |
818 | } | 1103 | } |
819 | 1104 | ||
1105 | /* Call preset again, with correct writesize this time */ | ||
1106 | host->preset(mtd); | ||
1107 | |||
820 | if (mtd->writesize == 2048) | 1108 | if (mtd->writesize == 2048) |
821 | this->ecc.layout = oob_largepage; | 1109 | this->ecc.layout = oob_largepage; |
822 | 1110 | ||
@@ -848,6 +1136,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
848 | escan: | 1136 | escan: |
849 | free_irq(host->irq, host); | 1137 | free_irq(host->irq, host); |
850 | eirq: | 1138 | eirq: |
1139 | if (host->regs_ip) | ||
1140 | iounmap(host->regs_ip); | ||
851 | iounmap(host->base); | 1141 | iounmap(host->base); |
852 | eres: | 1142 | eres: |
853 | clk_put(host->clk); | 1143 | clk_put(host->clk); |
@@ -867,59 +1157,19 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
867 | 1157 | ||
868 | nand_release(&host->mtd); | 1158 | nand_release(&host->mtd); |
869 | free_irq(host->irq, host); | 1159 | free_irq(host->irq, host); |
1160 | if (host->regs_ip) | ||
1161 | iounmap(host->regs_ip); | ||
870 | iounmap(host->base); | 1162 | iounmap(host->base); |
871 | kfree(host); | 1163 | kfree(host); |
872 | 1164 | ||
873 | return 0; | 1165 | return 0; |
874 | } | 1166 | } |
875 | 1167 | ||
876 | #ifdef CONFIG_PM | ||
877 | static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) | ||
878 | { | ||
879 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
880 | struct nand_chip *nand_chip = mtd->priv; | ||
881 | struct mxc_nand_host *host = nand_chip->priv; | ||
882 | int ret = 0; | ||
883 | |||
884 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); | ||
885 | |||
886 | ret = mtd->suspend(mtd); | ||
887 | |||
888 | /* | ||
889 | * nand_suspend locks the device for exclusive access, so | ||
890 | * the clock must already be off. | ||
891 | */ | ||
892 | BUG_ON(!ret && host->clk_act); | ||
893 | |||
894 | return ret; | ||
895 | } | ||
896 | |||
897 | static int mxcnd_resume(struct platform_device *pdev) | ||
898 | { | ||
899 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
900 | struct nand_chip *nand_chip = mtd->priv; | ||
901 | struct mxc_nand_host *host = nand_chip->priv; | ||
902 | int ret = 0; | ||
903 | |||
904 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); | ||
905 | |||
906 | mtd->resume(mtd); | ||
907 | |||
908 | return ret; | ||
909 | } | ||
910 | |||
911 | #else | ||
912 | # define mxcnd_suspend NULL | ||
913 | # define mxcnd_resume NULL | ||
914 | #endif /* CONFIG_PM */ | ||
915 | |||
916 | static struct platform_driver mxcnd_driver = { | 1168 | static struct platform_driver mxcnd_driver = { |
917 | .driver = { | 1169 | .driver = { |
918 | .name = DRIVER_NAME, | 1170 | .name = DRIVER_NAME, |
919 | }, | 1171 | }, |
920 | .remove = __devexit_p(mxcnd_remove), | 1172 | .remove = __devexit_p(mxcnd_remove), |
921 | .suspend = mxcnd_suspend, | ||
922 | .resume = mxcnd_resume, | ||
923 | }; | 1173 | }; |
924 | 1174 | ||
925 | static int __init mxc_nd_init(void) | 1175 | static int __init mxc_nd_init(void) |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4a7b86423ee9..16a1714df008 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/mtd/mtd.h> | 42 | #include <linux/mtd/mtd.h> |
43 | #include <linux/mtd/nand.h> | 43 | #include <linux/mtd/nand.h> |
44 | #include <linux/mtd/nand_ecc.h> | 44 | #include <linux/mtd/nand_ecc.h> |
45 | #include <linux/mtd/compatmac.h> | ||
46 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
47 | #include <linux/bitops.h> | 46 | #include <linux/bitops.h> |
48 | #include <linux/leds.h> | 47 | #include <linux/leds.h> |
@@ -347,7 +346,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
347 | struct nand_chip *chip = mtd->priv; | 346 | struct nand_chip *chip = mtd->priv; |
348 | u16 bad; | 347 | u16 bad; |
349 | 348 | ||
350 | if (chip->options & NAND_BB_LAST_PAGE) | 349 | if (chip->options & NAND_BBT_SCANLASTPAGE) |
351 | ofs += mtd->erasesize - mtd->writesize; | 350 | ofs += mtd->erasesize - mtd->writesize; |
352 | 351 | ||
353 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | 352 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; |
@@ -397,9 +396,9 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
397 | { | 396 | { |
398 | struct nand_chip *chip = mtd->priv; | 397 | struct nand_chip *chip = mtd->priv; |
399 | uint8_t buf[2] = { 0, 0 }; | 398 | uint8_t buf[2] = { 0, 0 }; |
400 | int block, ret; | 399 | int block, ret, i = 0; |
401 | 400 | ||
402 | if (chip->options & NAND_BB_LAST_PAGE) | 401 | if (chip->options & NAND_BBT_SCANLASTPAGE) |
403 | ofs += mtd->erasesize - mtd->writesize; | 402 | ofs += mtd->erasesize - mtd->writesize; |
404 | 403 | ||
405 | /* Get block number */ | 404 | /* Get block number */ |
@@ -411,17 +410,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
411 | if (chip->options & NAND_USE_FLASH_BBT) | 410 | if (chip->options & NAND_USE_FLASH_BBT) |
412 | ret = nand_update_bbt(mtd, ofs); | 411 | ret = nand_update_bbt(mtd, ofs); |
413 | else { | 412 | else { |
414 | /* We write two bytes, so we dont have to mess with 16 bit | ||
415 | * access | ||
416 | */ | ||
417 | nand_get_device(chip, mtd, FL_WRITING); | 413 | nand_get_device(chip, mtd, FL_WRITING); |
418 | ofs += mtd->oobsize; | ||
419 | chip->ops.len = chip->ops.ooblen = 2; | ||
420 | chip->ops.datbuf = NULL; | ||
421 | chip->ops.oobbuf = buf; | ||
422 | chip->ops.ooboffs = chip->badblockpos & ~0x01; | ||
423 | 414 | ||
424 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | 415 | /* Write to first two pages and to byte 1 and 6 if necessary. |
416 | * If we write to more than one location, the first error | ||
417 | * encountered quits the procedure. We write two bytes per | ||
418 | * location, so we dont have to mess with 16 bit access. | ||
419 | */ | ||
420 | do { | ||
421 | chip->ops.len = chip->ops.ooblen = 2; | ||
422 | chip->ops.datbuf = NULL; | ||
423 | chip->ops.oobbuf = buf; | ||
424 | chip->ops.ooboffs = chip->badblockpos & ~0x01; | ||
425 | |||
426 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | ||
427 | |||
428 | if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) { | ||
429 | chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS | ||
430 | & ~0x01; | ||
431 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | ||
432 | } | ||
433 | i++; | ||
434 | ofs += mtd->writesize; | ||
435 | } while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) && | ||
436 | i < 2); | ||
437 | |||
425 | nand_release_device(mtd); | 438 | nand_release_device(mtd); |
426 | } | 439 | } |
427 | if (!ret) | 440 | if (!ret) |
@@ -2920,9 +2933,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; | 2933 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; |
2921 | 2934 | ||
2922 | /* Set the bad block position */ | 2935 | /* Set the bad block position */ |
2923 | chip->badblockpos = mtd->writesize > 512 ? | 2936 | if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO || |
2924 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; | 2937 | (*maf_id == NAND_MFR_SAMSUNG && |
2925 | chip->badblockbits = 8; | 2938 | mtd->writesize == 512) || |
2939 | *maf_id == NAND_MFR_AMD)) | ||
2940 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; | ||
2941 | else | ||
2942 | chip->badblockpos = NAND_LARGE_BADBLOCK_POS; | ||
2943 | |||
2926 | 2944 | ||
2927 | /* Get chip options, preserve non chip based options */ | 2945 | /* Get chip options, preserve non chip based options */ |
2928 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | 2946 | chip->options &= ~NAND_CHIPOPTIONS_MSK; |
@@ -2941,12 +2959,32 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2941 | 2959 | ||
2942 | /* | 2960 | /* |
2943 | * Bad block marker is stored in the last page of each block | 2961 | * Bad block marker is stored in the last page of each block |
2944 | * on Samsung and Hynix MLC devices | 2962 | * on Samsung and Hynix MLC devices; stored in first two pages |
2963 | * of each block on Micron devices with 2KiB pages and on | ||
2964 | * SLC Samsung, Hynix, and AMD/Spansion. All others scan only | ||
2965 | * the first page. | ||
2945 | */ | 2966 | */ |
2946 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 2967 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2947 | (*maf_id == NAND_MFR_SAMSUNG || | 2968 | (*maf_id == NAND_MFR_SAMSUNG || |
2948 | *maf_id == NAND_MFR_HYNIX)) | 2969 | *maf_id == NAND_MFR_HYNIX)) |
2949 | chip->options |= NAND_BB_LAST_PAGE; | 2970 | chip->options |= NAND_BBT_SCANLASTPAGE; |
2971 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | ||
2972 | (*maf_id == NAND_MFR_SAMSUNG || | ||
2973 | *maf_id == NAND_MFR_HYNIX || | ||
2974 | *maf_id == NAND_MFR_AMD)) || | ||
2975 | (mtd->writesize == 2048 && | ||
2976 | *maf_id == NAND_MFR_MICRON)) | ||
2977 | chip->options |= NAND_BBT_SCAN2NDPAGE; | ||
2978 | |||
2979 | /* | ||
2980 | * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6 | ||
2981 | */ | ||
2982 | if (!(busw & NAND_BUSWIDTH_16) && | ||
2983 | *maf_id == NAND_MFR_STMICRO && | ||
2984 | mtd->writesize == 2048) { | ||
2985 | chip->options |= NAND_BBT_SCANBYTE1AND6; | ||
2986 | chip->badblockpos = 0; | ||
2987 | } | ||
2950 | 2988 | ||
2951 | /* Check for AND chips with 4 page planes */ | 2989 | /* Check for AND chips with 4 page planes */ |
2952 | if (chip->options & NAND_4PAGE_ARRAY) | 2990 | if (chip->options & NAND_4PAGE_ARRAY) |
@@ -3306,6 +3344,11 @@ void nand_release(struct mtd_info *mtd) | |||
3306 | kfree(chip->bbt); | 3344 | kfree(chip->bbt); |
3307 | if (!(chip->options & NAND_OWN_BUFFERS)) | 3345 | if (!(chip->options & NAND_OWN_BUFFERS)) |
3308 | kfree(chip->buffers); | 3346 | kfree(chip->buffers); |
3347 | |||
3348 | /* Free bad block descriptor memory */ | ||
3349 | if (chip->badblock_pattern && chip->badblock_pattern->options | ||
3350 | & NAND_BBT_DYNAMICSTRUCT) | ||
3351 | kfree(chip->badblock_pattern); | ||
3309 | } | 3352 | } |
3310 | 3353 | ||
3311 | EXPORT_SYMBOL_GPL(nand_lock); | 3354 | EXPORT_SYMBOL_GPL(nand_lock); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index ad97c0ce73b2..5fedf4a74f16 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <linux/mtd/mtd.h> | 55 | #include <linux/mtd/mtd.h> |
56 | #include <linux/mtd/nand.h> | 56 | #include <linux/mtd/nand.h> |
57 | #include <linux/mtd/nand_ecc.h> | 57 | #include <linux/mtd/nand_ecc.h> |
58 | #include <linux/mtd/compatmac.h> | ||
59 | #include <linux/bitops.h> | 58 | #include <linux/bitops.h> |
60 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
61 | #include <linux/vmalloc.h> | 60 | #include <linux/vmalloc.h> |
@@ -93,6 +92,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc | |||
93 | return -1; | 92 | return -1; |
94 | } | 93 | } |
95 | 94 | ||
95 | /* Check both positions 1 and 6 for pattern? */ | ||
96 | if (td->options & NAND_BBT_SCANBYTE1AND6) { | ||
97 | if (td->options & NAND_BBT_SCANEMPTY) { | ||
98 | p += td->len; | ||
99 | end += NAND_SMALL_BADBLOCK_POS - td->offs; | ||
100 | /* Check region between positions 1 and 6 */ | ||
101 | for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len; | ||
102 | i++) { | ||
103 | if (*p++ != 0xff) | ||
104 | return -1; | ||
105 | } | ||
106 | } | ||
107 | else { | ||
108 | p += NAND_SMALL_BADBLOCK_POS - td->offs; | ||
109 | } | ||
110 | /* Compare the pattern */ | ||
111 | for (i = 0; i < td->len; i++) { | ||
112 | if (p[i] != td->pattern[i]) | ||
113 | return -1; | ||
114 | } | ||
115 | } | ||
116 | |||
96 | if (td->options & NAND_BBT_SCANEMPTY) { | 117 | if (td->options & NAND_BBT_SCANEMPTY) { |
97 | p += td->len; | 118 | p += td->len; |
98 | end += td->len; | 119 | end += td->len; |
@@ -124,6 +145,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) | |||
124 | if (p[td->offs + i] != td->pattern[i]) | 145 | if (p[td->offs + i] != td->pattern[i]) |
125 | return -1; | 146 | return -1; |
126 | } | 147 | } |
148 | /* Need to check location 1 AND 6? */ | ||
149 | if (td->options & NAND_BBT_SCANBYTE1AND6) { | ||
150 | for (i = 0; i < td->len; i++) { | ||
151 | if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i]) | ||
152 | return -1; | ||
153 | } | ||
154 | } | ||
127 | return 0; | 155 | return 0; |
128 | } | 156 | } |
129 | 157 | ||
@@ -397,12 +425,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
397 | 425 | ||
398 | if (bd->options & NAND_BBT_SCANALLPAGES) | 426 | if (bd->options & NAND_BBT_SCANALLPAGES) |
399 | len = 1 << (this->bbt_erase_shift - this->page_shift); | 427 | len = 1 << (this->bbt_erase_shift - this->page_shift); |
400 | else { | 428 | else if (bd->options & NAND_BBT_SCAN2NDPAGE) |
401 | if (bd->options & NAND_BBT_SCAN2NDPAGE) | 429 | len = 2; |
402 | len = 2; | 430 | else |
403 | else | 431 | len = 1; |
404 | len = 1; | ||
405 | } | ||
406 | 432 | ||
407 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { | 433 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { |
408 | /* We need only read few bytes from the OOB area */ | 434 | /* We need only read few bytes from the OOB area */ |
@@ -432,7 +458,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
432 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); | 458 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); |
433 | } | 459 | } |
434 | 460 | ||
435 | if (this->options & NAND_BB_LAST_PAGE) | 461 | if (this->options & NAND_BBT_SCANLASTPAGE) |
436 | from += mtd->erasesize - (mtd->writesize * len); | 462 | from += mtd->erasesize - (mtd->writesize * len); |
437 | 463 | ||
438 | for (i = startblock; i < numblocks;) { | 464 | for (i = startblock; i < numblocks;) { |
@@ -1092,30 +1118,16 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1092 | * while scanning a device for factory marked good / bad blocks. */ | 1118 | * while scanning a device for factory marked good / bad blocks. */ |
1093 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 1119 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
1094 | 1120 | ||
1095 | static struct nand_bbt_descr smallpage_memorybased = { | ||
1096 | .options = NAND_BBT_SCAN2NDPAGE, | ||
1097 | .offs = 5, | ||
1098 | .len = 1, | ||
1099 | .pattern = scan_ff_pattern | ||
1100 | }; | ||
1101 | |||
1102 | static struct nand_bbt_descr largepage_memorybased = { | ||
1103 | .options = 0, | ||
1104 | .offs = 0, | ||
1105 | .len = 2, | ||
1106 | .pattern = scan_ff_pattern | ||
1107 | }; | ||
1108 | |||
1109 | static struct nand_bbt_descr smallpage_flashbased = { | 1121 | static struct nand_bbt_descr smallpage_flashbased = { |
1110 | .options = NAND_BBT_SCAN2NDPAGE, | 1122 | .options = NAND_BBT_SCAN2NDPAGE, |
1111 | .offs = 5, | 1123 | .offs = NAND_SMALL_BADBLOCK_POS, |
1112 | .len = 1, | 1124 | .len = 1, |
1113 | .pattern = scan_ff_pattern | 1125 | .pattern = scan_ff_pattern |
1114 | }; | 1126 | }; |
1115 | 1127 | ||
1116 | static struct nand_bbt_descr largepage_flashbased = { | 1128 | static struct nand_bbt_descr largepage_flashbased = { |
1117 | .options = NAND_BBT_SCAN2NDPAGE, | 1129 | .options = NAND_BBT_SCAN2NDPAGE, |
1118 | .offs = 0, | 1130 | .offs = NAND_LARGE_BADBLOCK_POS, |
1119 | .len = 2, | 1131 | .len = 2, |
1120 | .pattern = scan_ff_pattern | 1132 | .pattern = scan_ff_pattern |
1121 | }; | 1133 | }; |
@@ -1154,6 +1166,43 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1154 | .pattern = mirror_pattern | 1166 | .pattern = mirror_pattern |
1155 | }; | 1167 | }; |
1156 | 1168 | ||
1169 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ | ||
1170 | NAND_BBT_SCANBYTE1AND6) | ||
1171 | /** | ||
1172 | * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure | ||
1173 | * @this: NAND chip to create descriptor for | ||
1174 | * | ||
1175 | * This function allocates and initializes a nand_bbt_descr for BBM detection | ||
1176 | * based on the properties of "this". The new descriptor is stored in | ||
1177 | * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when | ||
1178 | * passed to this function. | ||
1179 | * | ||
1180 | * TODO: Handle other flags, replace other static structs | ||
1181 | * (e.g. handle NAND_BBT_FLASH for flash-based BBT, | ||
1182 | * replace smallpage_flashbased) | ||
1183 | * | ||
1184 | */ | ||
1185 | static int nand_create_default_bbt_descr(struct nand_chip *this) | ||
1186 | { | ||
1187 | struct nand_bbt_descr *bd; | ||
1188 | if (this->badblock_pattern) { | ||
1189 | printk(KERN_WARNING "BBT descr already allocated; not replacing.\n"); | ||
1190 | return -EINVAL; | ||
1191 | } | ||
1192 | bd = kzalloc(sizeof(*bd), GFP_KERNEL); | ||
1193 | if (!bd) { | ||
1194 | printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n"); | ||
1195 | return -ENOMEM; | ||
1196 | } | ||
1197 | bd->options = this->options & BBT_SCAN_OPTIONS; | ||
1198 | bd->offs = this->badblockpos; | ||
1199 | bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1; | ||
1200 | bd->pattern = scan_ff_pattern; | ||
1201 | bd->options |= NAND_BBT_DYNAMICSTRUCT; | ||
1202 | this->badblock_pattern = bd; | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1157 | /** | 1206 | /** |
1158 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device | 1207 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device |
1159 | * @mtd: MTD device structure | 1208 | * @mtd: MTD device structure |
@@ -1196,10 +1245,8 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1196 | } else { | 1245 | } else { |
1197 | this->bbt_td = NULL; | 1246 | this->bbt_td = NULL; |
1198 | this->bbt_md = NULL; | 1247 | this->bbt_md = NULL; |
1199 | if (!this->badblock_pattern) { | 1248 | if (!this->badblock_pattern) |
1200 | this->badblock_pattern = (mtd->writesize > 512) ? | 1249 | nand_create_default_bbt_descr(this); |
1201 | &largepage_memorybased : &smallpage_memorybased; | ||
1202 | } | ||
1203 | } | 1250 | } |
1204 | return nand_scan_bbt(mtd, this->badblock_pattern); | 1251 | return nand_scan_bbt(mtd, this->badblock_pattern); |
1205 | } | 1252 | } |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 89907ed99009..a04b89105b65 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -85,6 +85,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
85 | {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, | 85 | {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, |
86 | {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, | 86 | {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, |
87 | {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, | 87 | {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, |
88 | {"NAND 128MiB 1,8V 16-bit", 0xAD, 0, 128, 0, LP_OPTIONS16}, | ||
88 | 89 | ||
89 | /* 2 Gigabit */ | 90 | /* 2 Gigabit */ |
90 | {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS}, | 91 | {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS}, |
@@ -110,6 +111,9 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
110 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, | 111 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, |
111 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, | 112 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, |
112 | 113 | ||
114 | /* 32 Gigabit */ | ||
115 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS16}, | ||
116 | |||
113 | /* | 117 | /* |
114 | * Renesas AND 1 Gigabit. Those chips do not support extended id and | 118 | * Renesas AND 1 Gigabit. Those chips do not support extended id and |
115 | * have a strange page/block layout ! The chosen minimum erasesize is | 119 | * have a strange page/block layout ! The chosen minimum erasesize is |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 261337efe0ee..c25648bb5793 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -553,8 +553,8 @@ static uint64_t divide(uint64_t n, uint32_t d) | |||
553 | */ | 553 | */ |
554 | static int init_nandsim(struct mtd_info *mtd) | 554 | static int init_nandsim(struct mtd_info *mtd) |
555 | { | 555 | { |
556 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 556 | struct nand_chip *chip = mtd->priv; |
557 | struct nandsim *ns = (struct nandsim *)(chip->priv); | 557 | struct nandsim *ns = chip->priv; |
558 | int i, ret = 0; | 558 | int i, ret = 0; |
559 | uint64_t remains; | 559 | uint64_t remains; |
560 | uint64_t next_offset; | 560 | uint64_t next_offset; |
@@ -1877,7 +1877,7 @@ static void switch_state(struct nandsim *ns) | |||
1877 | 1877 | ||
1878 | static u_char ns_nand_read_byte(struct mtd_info *mtd) | 1878 | static u_char ns_nand_read_byte(struct mtd_info *mtd) |
1879 | { | 1879 | { |
1880 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1880 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
1881 | u_char outb = 0x00; | 1881 | u_char outb = 0x00; |
1882 | 1882 | ||
1883 | /* Sanity and correctness checks */ | 1883 | /* Sanity and correctness checks */ |
@@ -1950,7 +1950,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) | |||
1950 | 1950 | ||
1951 | static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | 1951 | static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) |
1952 | { | 1952 | { |
1953 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1953 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
1954 | 1954 | ||
1955 | /* Sanity and correctness checks */ | 1955 | /* Sanity and correctness checks */ |
1956 | if (!ns->lines.ce) { | 1956 | if (!ns->lines.ce) { |
@@ -2132,7 +2132,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd) | |||
2132 | 2132 | ||
2133 | static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 2133 | static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
2134 | { | 2134 | { |
2135 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 2135 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
2136 | 2136 | ||
2137 | /* Check that chip is expecting data input */ | 2137 | /* Check that chip is expecting data input */ |
2138 | if (!(ns->state & STATE_DATAIN_MASK)) { | 2138 | if (!(ns->state & STATE_DATAIN_MASK)) { |
@@ -2159,7 +2159,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
2159 | 2159 | ||
2160 | static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 2160 | static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
2161 | { | 2161 | { |
2162 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 2162 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
2163 | 2163 | ||
2164 | /* Sanity and correctness checks */ | 2164 | /* Sanity and correctness checks */ |
2165 | if (!ns->lines.ce) { | 2165 | if (!ns->lines.ce) { |
@@ -2352,7 +2352,7 @@ module_init(ns_init_module); | |||
2352 | */ | 2352 | */ |
2353 | static void __exit ns_cleanup_module(void) | 2353 | static void __exit ns_cleanup_module(void) |
2354 | { | 2354 | { |
2355 | struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); | 2355 | struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv; |
2356 | int i; | 2356 | int i; |
2357 | 2357 | ||
2358 | free_nandsim(ns); /* Free nandsim private resources */ | 2358 | free_nandsim(ns); /* Free nandsim private resources */ |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 8d467315f02b..90e143e5ad3e 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -91,7 +91,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
91 | } | 91 | } |
92 | 92 | ||
93 | /* Scan to find existance of the device */ | 93 | /* Scan to find existance of the device */ |
94 | if (nand_scan(&data->mtd, 1)) { | 94 | if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { |
95 | err = -ENXIO; | 95 | err = -ENXIO; |
96 | goto out; | 96 | goto out; |
97 | } | 97 | } |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index bcfc851fe550..5169ca6a66bc 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -64,8 +64,8 @@ static inline void r852_write_reg_dword(struct r852_device *dev, | |||
64 | /* returns pointer to our private structure */ | 64 | /* returns pointer to our private structure */ |
65 | static inline struct r852_device *r852_get_dev(struct mtd_info *mtd) | 65 | static inline struct r852_device *r852_get_dev(struct mtd_info *mtd) |
66 | { | 66 | { |
67 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 67 | struct nand_chip *chip = mtd->priv; |
68 | return (struct r852_device *)chip->priv; | 68 | return chip->priv; |
69 | } | 69 | } |
70 | 70 | ||
71 | 71 | ||
@@ -380,7 +380,7 @@ void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) | |||
380 | */ | 380 | */ |
381 | int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) | 381 | int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) |
382 | { | 382 | { |
383 | struct r852_device *dev = (struct r852_device *)chip->priv; | 383 | struct r852_device *dev = chip->priv; |
384 | 384 | ||
385 | unsigned long timeout; | 385 | unsigned long timeout; |
386 | int status; | 386 | int status; |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index a033c4cd8e16..67440b5beef8 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/rslib.h> | 24 | #include <linux/rslib.h> |
25 | #include <linux/bitrev.h> | 25 | #include <linux/bitrev.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/mtd/compatmac.h> | ||
28 | #include <linux/mtd/mtd.h> | 27 | #include <linux/mtd/mtd.h> |
29 | #include <linux/mtd/nand.h> | 28 | #include <linux/mtd/nand.h> |
30 | #include <linux/mtd/partitions.h> | 29 | #include <linux/mtd/partitions.h> |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 239aadfd01b0..33d832dddfdd 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -727,15 +727,12 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
727 | if (set == NULL) | 727 | if (set == NULL) |
728 | return add_mtd_device(&mtd->mtd); | 728 | return add_mtd_device(&mtd->mtd); |
729 | 729 | ||
730 | if (set->nr_partitions == 0) { | 730 | mtd->mtd.name = set->name; |
731 | mtd->mtd.name = set->name; | 731 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0); |
732 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, | 732 | |
733 | &part_info, 0); | 733 | if (nr_part <= 0 && set->nr_partitions > 0) { |
734 | } else { | 734 | nr_part = set->nr_partitions; |
735 | if (set->nr_partitions > 0 && set->partitions != NULL) { | 735 | part_info = set->partitions; |
736 | nr_part = set->nr_partitions; | ||
737 | part_info = set->partitions; | ||
738 | } | ||
739 | } | 736 | } |
740 | 737 | ||
741 | if (nr_part > 0 && part_info) | 738 | if (nr_part > 0 && part_info) |
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index ac80fb362e63..4a8f367c295c 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
@@ -109,7 +109,7 @@ static struct nand_flash_dev nand_xd_flash_ids[] = { | |||
109 | 109 | ||
110 | int sm_register_device(struct mtd_info *mtd, int smartmedia) | 110 | int sm_register_device(struct mtd_info *mtd, int smartmedia) |
111 | { | 111 | { |
112 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 112 | struct nand_chip *chip = mtd->priv; |
113 | int ret; | 113 | int ret; |
114 | 114 | ||
115 | chip->options |= NAND_SKIP_BBTSCAN; | 115 | chip->options |= NAND_SKIP_BBTSCAN; |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index a4578bf903aa..b155666acfbe 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -1,11 +1,22 @@ | |||
1 | /* Linux driver for NAND Flash Translation Layer */ | ||
2 | /* (c) 1999 Machine Vision Holdings, Inc. */ | ||
3 | /* Author: David Woodhouse <dwmw2@infradead.org> */ | ||
4 | |||
5 | /* | 1 | /* |
6 | The contents of this file are distributed under the GNU General | 2 | * Linux driver for NAND Flash Translation Layer |
7 | Public License version 2. The author places no additional | 3 | * |
8 | restrictions of any kind on it. | 4 | * Copyright © 1999 Machine Vision Holdings, Inc. |
5 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
9 | */ | 20 | */ |
10 | 21 | ||
11 | #define PRERELEASE | 22 | #define PRERELEASE |
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 8b22b1836e9f..e3cd1ffad2f6 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * NFTL mount code with extensive checks | 2 | * NFTL mount code with extensive checks |
3 | * | 3 | * |
4 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 4 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
5 | * Copyright (C) 2000 Netgem S.A. | 5 | * Copyright © 2000 Netgem S.A. |
6 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 4f0d635674f3..8bf7dc6d1ce6 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Flash partitions described by the OF (or flattened) device tree | 2 | * Flash partitions described by the OF (or flattened) device tree |
3 | * | 3 | * |
4 | * Copyright (C) 2006 MontaVista Software Inc. | 4 | * Copyright © 2006 MontaVista Software Inc. |
5 | * Author: Vitaly Wool <vwool@ru.mvista.com> | 5 | * Author: Vitaly Wool <vwool@ru.mvista.com> |
6 | * | 6 | * |
7 | * Revised to handle newer style flash binding by: | 7 | * Revised to handle newer style flash binding by: |
8 | * Copyright (C) 2007 David Gibson, IBM Corporation. | 8 | * Copyright © 2007 David Gibson, IBM Corporation. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 9a49d68ba5f9..3f32289fdbb5 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -25,14 +25,14 @@ config MTD_ONENAND_GENERIC | |||
25 | 25 | ||
26 | config MTD_ONENAND_OMAP2 | 26 | config MTD_ONENAND_OMAP2 |
27 | tristate "OneNAND on OMAP2/OMAP3 support" | 27 | tristate "OneNAND on OMAP2/OMAP3 support" |
28 | depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3) | 28 | depends on ARCH_OMAP2 || ARCH_OMAP3 |
29 | help | 29 | help |
30 | Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU | 30 | Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU |
31 | via the GPMC memory controller. | 31 | via the GPMC memory controller. |
32 | 32 | ||
33 | config MTD_ONENAND_SAMSUNG | 33 | config MTD_ONENAND_SAMSUNG |
34 | tristate "OneNAND on Samsung SOC controller support" | 34 | tristate "OneNAND on Samsung SOC controller support" |
35 | depends on MTD_ONENAND && (ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210) | 35 | depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 |
36 | help | 36 | help |
37 | Support for a OneNAND flash device connected to an Samsung SOC | 37 | Support for a OneNAND flash device connected to an Samsung SOC |
38 | S3C64XX/S5PC1XX controller. | 38 | S3C64XX/S5PC1XX controller. |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 26caf2590dae..a2bb520286f8 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -377,8 +377,11 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
377 | 377 | ||
378 | default: | 378 | default: |
379 | block = onenand_block(this, addr); | 379 | block = onenand_block(this, addr); |
380 | page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; | 380 | if (FLEXONENAND(this)) |
381 | 381 | page = (int) (addr - onenand_addr(this, block))>>\ | |
382 | this->page_shift; | ||
383 | else | ||
384 | page = (int) (addr >> this->page_shift); | ||
382 | if (ONENAND_IS_2PLANE(this)) { | 385 | if (ONENAND_IS_2PLANE(this)) { |
383 | /* Make the even block number */ | 386 | /* Make the even block number */ |
384 | block &= ~1; | 387 | block &= ~1; |
@@ -3730,17 +3733,16 @@ out: | |||
3730 | } | 3733 | } |
3731 | 3734 | ||
3732 | /** | 3735 | /** |
3733 | * onenand_probe - [OneNAND Interface] Probe the OneNAND device | 3736 | * onenand_chip_probe - [OneNAND Interface] The generic chip probe |
3734 | * @param mtd MTD device structure | 3737 | * @param mtd MTD device structure |
3735 | * | 3738 | * |
3736 | * OneNAND detection method: | 3739 | * OneNAND detection method: |
3737 | * Compare the values from command with ones from register | 3740 | * Compare the values from command with ones from register |
3738 | */ | 3741 | */ |
3739 | static int onenand_probe(struct mtd_info *mtd) | 3742 | static int onenand_chip_probe(struct mtd_info *mtd) |
3740 | { | 3743 | { |
3741 | struct onenand_chip *this = mtd->priv; | 3744 | struct onenand_chip *this = mtd->priv; |
3742 | int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id; | 3745 | int bram_maf_id, bram_dev_id, maf_id, dev_id; |
3743 | int density; | ||
3744 | int syscfg; | 3746 | int syscfg; |
3745 | 3747 | ||
3746 | /* Save system configuration 1 */ | 3748 | /* Save system configuration 1 */ |
@@ -3763,12 +3765,6 @@ static int onenand_probe(struct mtd_info *mtd) | |||
3763 | /* Restore system configuration 1 */ | 3765 | /* Restore system configuration 1 */ |
3764 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); | 3766 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); |
3765 | 3767 | ||
3766 | /* Workaround */ | ||
3767 | if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) { | ||
3768 | bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | ||
3769 | bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | ||
3770 | } | ||
3771 | |||
3772 | /* Check manufacturer ID */ | 3768 | /* Check manufacturer ID */ |
3773 | if (onenand_check_maf(bram_maf_id)) | 3769 | if (onenand_check_maf(bram_maf_id)) |
3774 | return -ENXIO; | 3770 | return -ENXIO; |
@@ -3776,13 +3772,35 @@ static int onenand_probe(struct mtd_info *mtd) | |||
3776 | /* Read manufacturer and device IDs from Register */ | 3772 | /* Read manufacturer and device IDs from Register */ |
3777 | maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | 3773 | maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); |
3778 | dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | 3774 | dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); |
3779 | ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); | ||
3780 | this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); | ||
3781 | 3775 | ||
3782 | /* Check OneNAND device */ | 3776 | /* Check OneNAND device */ |
3783 | if (maf_id != bram_maf_id || dev_id != bram_dev_id) | 3777 | if (maf_id != bram_maf_id || dev_id != bram_dev_id) |
3784 | return -ENXIO; | 3778 | return -ENXIO; |
3785 | 3779 | ||
3780 | return 0; | ||
3781 | } | ||
3782 | |||
3783 | /** | ||
3784 | * onenand_probe - [OneNAND Interface] Probe the OneNAND device | ||
3785 | * @param mtd MTD device structure | ||
3786 | */ | ||
3787 | static int onenand_probe(struct mtd_info *mtd) | ||
3788 | { | ||
3789 | struct onenand_chip *this = mtd->priv; | ||
3790 | int maf_id, dev_id, ver_id; | ||
3791 | int density; | ||
3792 | int ret; | ||
3793 | |||
3794 | ret = this->chip_probe(mtd); | ||
3795 | if (ret) | ||
3796 | return ret; | ||
3797 | |||
3798 | /* Read manufacturer and device IDs from Register */ | ||
3799 | maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | ||
3800 | dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | ||
3801 | ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); | ||
3802 | this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); | ||
3803 | |||
3786 | /* Flash device information */ | 3804 | /* Flash device information */ |
3787 | onenand_print_device_info(dev_id, ver_id); | 3805 | onenand_print_device_info(dev_id, ver_id); |
3788 | this->device_id = dev_id; | 3806 | this->device_id = dev_id; |
@@ -3909,6 +3927,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
3909 | if (!this->unlock_all) | 3927 | if (!this->unlock_all) |
3910 | this->unlock_all = onenand_unlock_all; | 3928 | this->unlock_all = onenand_unlock_all; |
3911 | 3929 | ||
3930 | if (!this->chip_probe) | ||
3931 | this->chip_probe = onenand_chip_probe; | ||
3932 | |||
3912 | if (!this->read_bufferram) | 3933 | if (!this->read_bufferram) |
3913 | this->read_bufferram = onenand_read_bufferram; | 3934 | this->read_bufferram = onenand_read_bufferram; |
3914 | if (!this->write_bufferram) | 3935 | if (!this->write_bufferram) |
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index a91fcac1af01..01ab5b3c453b 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
17 | #include <linux/mtd/onenand.h> | 17 | #include <linux/mtd/onenand.h> |
18 | #include <linux/mtd/compatmac.h> | ||
19 | 18 | ||
20 | /** | 19 | /** |
21 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | 20 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 2750317cb58f..cb443af3d45f 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -630,6 +630,12 @@ normal: | |||
630 | return 0; | 630 | return 0; |
631 | } | 631 | } |
632 | 632 | ||
633 | static int s5pc110_chip_probe(struct mtd_info *mtd) | ||
634 | { | ||
635 | /* Now just return 0 */ | ||
636 | return 0; | ||
637 | } | ||
638 | |||
633 | static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state) | 639 | static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state) |
634 | { | 640 | { |
635 | unsigned int flags = INT_ACT | LOAD_CMP; | 641 | unsigned int flags = INT_ACT | LOAD_CMP; |
@@ -757,6 +763,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd) | |||
757 | /* Use generic onenand functions */ | 763 | /* Use generic onenand functions */ |
758 | onenand->cmd_map = s5pc1xx_cmd_map; | 764 | onenand->cmd_map = s5pc1xx_cmd_map; |
759 | this->read_bufferram = s5pc110_read_bufferram; | 765 | this->read_bufferram = s5pc110_read_bufferram; |
766 | this->chip_probe = s5pc110_chip_probe; | ||
760 | return; | 767 | return; |
761 | } else { | 768 | } else { |
762 | BUG(); | 769 | BUG(); |
@@ -781,7 +788,6 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
781 | struct mtd_info *mtd; | 788 | struct mtd_info *mtd; |
782 | struct resource *r; | 789 | struct resource *r; |
783 | int size, err; | 790 | int size, err; |
784 | unsigned long onenand_ctrl_cfg = 0; | ||
785 | 791 | ||
786 | pdata = pdev->dev.platform_data; | 792 | pdata = pdev->dev.platform_data; |
787 | /* No need to check pdata. the platform data is optional */ | 793 | /* No need to check pdata. the platform data is optional */ |
@@ -900,14 +906,6 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
900 | } | 906 | } |
901 | 907 | ||
902 | onenand->phys_base = onenand->base_res->start; | 908 | onenand->phys_base = onenand->base_res->start; |
903 | |||
904 | onenand_ctrl_cfg = readl(onenand->dma_addr + 0x100); | ||
905 | if ((onenand_ctrl_cfg & ONENAND_SYS_CFG1_SYNC_WRITE) && | ||
906 | onenand->dma_addr) | ||
907 | writel(onenand_ctrl_cfg & ~ONENAND_SYS_CFG1_SYNC_WRITE, | ||
908 | onenand->dma_addr + 0x100); | ||
909 | else | ||
910 | onenand_ctrl_cfg = 0; | ||
911 | } | 909 | } |
912 | 910 | ||
913 | if (onenand_scan(mtd, 1)) { | 911 | if (onenand_scan(mtd, 1)) { |
@@ -915,10 +913,7 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
915 | goto scan_failed; | 913 | goto scan_failed; |
916 | } | 914 | } |
917 | 915 | ||
918 | if (onenand->type == TYPE_S5PC110) { | 916 | if (onenand->type != TYPE_S5PC110) { |
919 | if (onenand_ctrl_cfg && onenand->dma_addr) | ||
920 | writel(onenand_ctrl_cfg, onenand->dma_addr + 0x100); | ||
921 | } else { | ||
922 | /* S3C doesn't handle subpage write */ | 917 | /* S3C doesn't handle subpage write */ |
923 | mtd->subpage_sft = 0; | 918 | mtd->subpage_sft = 0; |
924 | this->subpagesize = mtd->writesize; | 919 | this->subpagesize = mtd->writesize; |
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 2d600a1bf2aa..7a87d07cd79f 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c | |||
@@ -1,6 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Parse RedBoot-style Flash Image System (FIS) tables and | 2 | * Parse RedBoot-style Flash Image System (FIS) tables and |
3 | * produce a Linux partition array to match. | 3 | * produce a Linux partition array to match. |
4 | * | ||
5 | * Copyright © 2001 Red Hat UK Limited | ||
6 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | * | ||
4 | */ | 22 | */ |
5 | 23 | ||
6 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 63b83c0d9a13..cc4d1805b864 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * rfd_ftl.c -- resident flash disk (flash translation layer) | 2 | * rfd_ftl.c -- resident flash disk (flash translation layer) |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Sean Young <sean@mess.org> | 4 | * Copyright © 2005 Sean Young <sean@mess.org> |
5 | * | 5 | * |
6 | * This type of flash translation layer (FTL) is used by the Embedded BIOS | 6 | * This type of flash translation layer (FTL) is used by the Embedded BIOS |
7 | * by General Software. It is known as the Resident Flash Disk (RFD), see: | 7 | * by General Software. It is known as the Resident Flash Disk (RFD), see: |
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index 81c4ecdc11f5..5cd189793332 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Linux driver for SSFDC Flash Translation Layer (Read only) | 2 | * Linux driver for SSFDC Flash Translation Layer (Read only) |
3 | * (c) 2005 Eptar srl | 3 | * © 2005 Eptar srl |
4 | * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com> | 4 | * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com> |
5 | * | 5 | * |
6 | * Based on NTFL and MTDBLOCK_RO drivers | 6 | * Based on NTFL and MTDBLOCK_RO drivers |
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c index 6bc1b8276c62..00b937e38c1d 100644 --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/mtd_pagetest.c | |||
@@ -310,7 +310,7 @@ static int crosstest(void) | |||
310 | static int erasecrosstest(void) | 310 | static int erasecrosstest(void) |
311 | { | 311 | { |
312 | size_t read = 0, written = 0; | 312 | size_t read = 0, written = 0; |
313 | int err = 0, i, ebnum, ok = 1, ebnum2; | 313 | int err = 0, i, ebnum, ebnum2; |
314 | loff_t addr0; | 314 | loff_t addr0; |
315 | char *readbuf = twopages; | 315 | char *readbuf = twopages; |
316 | 316 | ||
@@ -357,8 +357,7 @@ static int erasecrosstest(void) | |||
357 | if (memcmp(writebuf, readbuf, pgsize)) { | 357 | if (memcmp(writebuf, readbuf, pgsize)) { |
358 | printk(PRINT_PREF "verify failed!\n"); | 358 | printk(PRINT_PREF "verify failed!\n"); |
359 | errcnt += 1; | 359 | errcnt += 1; |
360 | ok = 0; | 360 | return -1; |
361 | return err; | ||
362 | } | 361 | } |
363 | 362 | ||
364 | printk(PRINT_PREF "erasing block %d\n", ebnum); | 363 | printk(PRINT_PREF "erasing block %d\n", ebnum); |
@@ -396,10 +395,10 @@ static int erasecrosstest(void) | |||
396 | if (memcmp(writebuf, readbuf, pgsize)) { | 395 | if (memcmp(writebuf, readbuf, pgsize)) { |
397 | printk(PRINT_PREF "verify failed!\n"); | 396 | printk(PRINT_PREF "verify failed!\n"); |
398 | errcnt += 1; | 397 | errcnt += 1; |
399 | ok = 0; | 398 | return -1; |
400 | } | 399 | } |
401 | 400 | ||
402 | if (ok && !err) | 401 | if (!err) |
403 | printk(PRINT_PREF "erasecrosstest ok\n"); | 402 | printk(PRINT_PREF "erasecrosstest ok\n"); |
404 | return err; | 403 | return err; |
405 | } | 404 | } |
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 55f1dde2fa8b..404111b016c9 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index c5e1450d79f9..a906f538d11c 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index f0294410868d..617a1e5694c1 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c | |||
@@ -2,11 +2,12 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Created by Arjan van de Ven <arjanv@redhat.com> | 5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> |
6 | * | ||
7 | * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, | 6 | * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, |
8 | * University of Szeged, Hungary | 7 | * University of Szeged, Hungary |
9 | * | 8 | * |
9 | * Created by Arjan van de Ven <arjan@infradead.org> | ||
10 | * | ||
10 | * For licensing information, see the file 'LICENCE' in this directory. | 11 | * For licensing information, see the file 'LICENCE' in this directory. |
11 | * | 12 | * |
12 | */ | 13 | */ |
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 7d1d72faa774..e471a9106fd9 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, | 4 | * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, |
5 | * University of Szeged, Hungary | 5 | * University of Szeged, Hungary |
6 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
6 | * | 7 | * |
7 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
8 | * | 9 | * |
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c index cd02acafde8a..ed25ae7c98eb 100644 --- a/fs/jffs2/compr_lzo.c +++ b/fs/jffs2/compr_lzo.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2007 Nokia Corporation. All rights reserved. | 4 | * Copyright © 2007 Nokia Corporation. All rights reserved. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by Richard Purdie <rpurdie@openedhand.com> | 7 | * Created by Richard Purdie <rpurdie@openedhand.com> |
7 | * | 8 | * |
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 546d1538d076..9696ad9ef5f7 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by Arjan van de Ven <arjanv@redhat.com> | 7 | * Created by Arjan van de Ven <arjanv@redhat.com> |
7 | * | 8 | * |
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 170d289ac785..a12b4f763373 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by Arjan van de Ven <arjanv@redhat.com> | 7 | * Created by Arjan van de Ven <arjanv@redhat.com> |
7 | * | 8 | * |
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index b46661a42758..97fc45de6f81 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index ec3538413926..e0b76c87a91a 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index a113ecc3bafe..c4f8eef5ca68 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 5fd3b5cecda5..ed78a3cf3cb0 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 6286ad9b00f7..abac961f617b 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 813497024437..1c0a08d711aa 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index ac0638f04969..6b2964a19850 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index f5e96bd656e8..846a79452497 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c index 9d41f43e47bb..859a598af020 100644 --- a/fs/jffs2/ioctl.c +++ b/fs/jffs2/ioctl.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index c6923da98263..2e4a86763c07 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 85ef6dbb1be7..6784bc89add1 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright © 2001-2007 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index a881a42f19e3..523a91691052 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -24,7 +24,6 @@ | |||
24 | #ifdef __ECOS | 24 | #ifdef __ECOS |
25 | #include "os-ecos.h" | 25 | #include "os-ecos.h" |
26 | #else | 26 | #else |
27 | #include <linux/mtd/compatmac.h> /* For compatibility with older kernels */ | ||
28 | #include "os-linux.h" | 27 | #include "os-linux.h" |
29 | #endif | 28 | #endif |
30 | 29 | ||
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index edb9231f1898..a18b719f49d4 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
3 | * | 3 | * |
4 | * Copyright (C) 2001-2003 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
5 | * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * Created by David Woodhouse <dwmw2@infradead.org> | 7 | * Created by David Woodhouse <dwmw2@infradead.org> |
7 | * | 8 | * |
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 9c3757c5759d..7fa20beb2ab9 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h | |||
@@ -4,12 +4,26 @@ | |||
4 | * NAND family Bad Block Management (BBM) header file | 4 | * NAND family Bad Block Management (BBM) header file |
5 | * - Bad Block Table (BBT) implementation | 5 | * - Bad Block Table (BBT) implementation |
6 | * | 6 | * |
7 | * Copyright (c) 2005 Samsung Electronics | 7 | * Copyright © 2005 Samsung Electronics |
8 | * Kyungmin Park <kyungmin.park@samsung.com> | 8 | * Kyungmin Park <kyungmin.park@samsung.com> |
9 | * | 9 | * |
10 | * Copyright (c) 2000-2005 | 10 | * Copyright © 2000-2005 |
11 | * Thomas Gleixner <tglx@linuxtronix.de> | 11 | * Thomas Gleixner <tglx@linuxtronix.de> |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
26 | * | ||
13 | */ | 27 | */ |
14 | #ifndef __LINUX_MTD_BBM_H | 28 | #ifndef __LINUX_MTD_BBM_H |
15 | #define __LINUX_MTD_BBM_H | 29 | #define __LINUX_MTD_BBM_H |
@@ -82,6 +96,12 @@ struct nand_bbt_descr { | |||
82 | #define NAND_BBT_SAVECONTENT 0x00002000 | 96 | #define NAND_BBT_SAVECONTENT 0x00002000 |
83 | /* Search good / bad pattern on the first and the second page */ | 97 | /* Search good / bad pattern on the first and the second page */ |
84 | #define NAND_BBT_SCAN2NDPAGE 0x00004000 | 98 | #define NAND_BBT_SCAN2NDPAGE 0x00004000 |
99 | /* Search good / bad pattern on the last page of the eraseblock */ | ||
100 | #define NAND_BBT_SCANLASTPAGE 0x00008000 | ||
101 | /* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */ | ||
102 | #define NAND_BBT_SCANBYTE1AND6 0x00100000 | ||
103 | /* The nand_bbt_descr was created dynamicaly and must be freed */ | ||
104 | #define NAND_BBT_DYNAMICSTRUCT 0x00200000 | ||
85 | 105 | ||
86 | /* The maximum number of blocks to scan for a bbt */ | 106 | /* The maximum number of blocks to scan for a bbt */ |
87 | #define NAND_BBT_SCAN_MAXBLOCKS 4 | 107 | #define NAND_BBT_SCAN_MAXBLOCKS 4 |
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index b481ccd7ff3c..26529ebd59cc 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h | |||
@@ -1,7 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> | 2 | * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org> |
3 | * | 3 | * |
4 | * Interface to Linux block layer for MTD 'translation layers'. | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
5 | * | 17 | * |
6 | */ | 18 | */ |
7 | 19 | ||
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 574d9ee066f1..d2118b0eac9a 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h | |||
@@ -1,6 +1,20 @@ | |||
1 | 1 | /* | |
2 | /* Common Flash Interface structures | 2 | * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al. |
3 | * See http://support.intel.com/design/flash/technote/index.htm | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | * | ||
4 | */ | 18 | */ |
5 | 19 | ||
6 | #ifndef __MTD_CFI_H__ | 20 | #ifndef __MTD_CFI_H__ |
diff --git a/include/linux/mtd/cfi_endian.h b/include/linux/mtd/cfi_endian.h index d802f7736be3..51cc3f5917a8 100644 --- a/include/linux/mtd/cfi_endian.h +++ b/include/linux/mtd/cfi_endian.h | |||
@@ -1,3 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | * | ||
18 | */ | ||
19 | |||
1 | #include <asm/byteorder.h> | 20 | #include <asm/byteorder.h> |
2 | 21 | ||
3 | #ifndef CONFIG_MTD_CFI_ADV_OPTIONS | 22 | #ifndef CONFIG_MTD_CFI_ADV_OPTIONS |
diff --git a/include/linux/mtd/compatmac.h b/include/linux/mtd/compatmac.h deleted file mode 100644 index 7d1300d9bd51..000000000000 --- a/include/linux/mtd/compatmac.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | |||
2 | #ifndef __LINUX_MTD_COMPATMAC_H__ | ||
3 | #define __LINUX_MTD_COMPATMAC_H__ | ||
4 | |||
5 | /* Nothing to see here. We write 2.5-compatible code and this | ||
6 | file makes it all OK in older kernels, but it's empty in _current_ | ||
7 | kernels. Include guard just to make GCC ignore it in future inclusions | ||
8 | anyway... */ | ||
9 | |||
10 | #endif /* __LINUX_MTD_COMPATMAC_H__ */ | ||
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h index e80c674daeb3..ccdbe93a909c 100644 --- a/include/linux/mtd/concat.h +++ b/include/linux/mtd/concat.h | |||
@@ -1,9 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * MTD device concatenation layer definitions | 2 | * MTD device concatenation layer definitions |
3 | * | 3 | * |
4 | * (C) 2002 Robert Kaiser <rkaiser@sysgo.de> | 4 | * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
5 | * | 19 | * |
6 | * This code is GPL | ||
7 | */ | 20 | */ |
8 | 21 | ||
9 | #ifndef MTD_CONCAT_H | 22 | #ifndef MTD_CONCAT_H |
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 0a6d516ab71d..0f6fea73a1f6 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h | |||
@@ -1,12 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * Linux driver for Disk-On-Chip devices | 2 | * Linux driver for Disk-On-Chip devices |
3 | * | 3 | * |
4 | * Copyright (C) 1999 Machine Vision Holdings, Inc. | 4 | * Copyright © 1999 Machine Vision Holdings, Inc. |
5 | * Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org> | 5 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
6 | * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com> | 6 | * Copyright © 2002-2003 Greg Ungerer <gerg@snapgear.com> |
7 | * Copyright (C) 2002-2003 SnapGear Inc | 7 | * Copyright © 2002-2003 SnapGear Inc |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
8 | * | 22 | * |
9 | * Released under GPL | ||
10 | */ | 23 | */ |
11 | 24 | ||
12 | #ifndef __MTD_DOC2000_H__ | 25 | #ifndef __MTD_DOC2000_H__ |
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index f43e9b49b751..b63fa457febd 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h | |||
@@ -1,10 +1,21 @@ | |||
1 | |||
2 | /* | 1 | /* |
3 | * struct flchip definition | 2 | * Copyright © 2000 Red Hat UK Limited |
3 | * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
4 | * | 14 | * |
5 | * Contains information about the location and state of a given flash device | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
6 | * | 18 | * |
7 | * (C) 2000 Red Hat. GPLd. | ||
8 | */ | 19 | */ |
9 | 20 | ||
10 | #ifndef __MTD_FLASHCHIP_H__ | 21 | #ifndef __MTD_FLASHCHIP_H__ |
@@ -92,7 +103,7 @@ struct flchip { | |||
92 | /* This is used to handle contention on write/erase operations | 103 | /* This is used to handle contention on write/erase operations |
93 | between partitions of the same physical chip. */ | 104 | between partitions of the same physical chip. */ |
94 | struct flchip_shared { | 105 | struct flchip_shared { |
95 | spinlock_t lock; | 106 | struct mutex lock; |
96 | struct flchip *writing; | 107 | struct flchip *writing; |
97 | struct flchip *erasing; | 108 | struct flchip *erasing; |
98 | }; | 109 | }; |
diff --git a/include/linux/mtd/gen_probe.h b/include/linux/mtd/gen_probe.h index df362ddf2949..2c456054fded 100644 --- a/include/linux/mtd/gen_probe.h +++ b/include/linux/mtd/gen_probe.h | |||
@@ -1,6 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 2001, 2001 Red Hat, Inc. | 2 | * Copyright © 2001 Red Hat UK Limited |
3 | * GPL'd | 3 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> |
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | * | ||
4 | */ | 19 | */ |
5 | 20 | ||
6 | #ifndef __LINUX_MTD_GEN_PROBE_H__ | 21 | #ifndef __LINUX_MTD_GEN_PROBE_H__ |
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index de89eca864ce..a9e6ba46865e 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h | |||
@@ -1,3 +1,21 @@ | |||
1 | /* | ||
2 | * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | * | ||
18 | */ | ||
1 | 19 | ||
2 | /* Overhauled routines for dealing with different mmap regions of flash */ | 20 | /* Overhauled routines for dealing with different mmap regions of flash */ |
3 | 21 | ||
@@ -9,7 +27,6 @@ | |||
9 | #include <linux/string.h> | 27 | #include <linux/string.h> |
10 | #include <linux/bug.h> | 28 | #include <linux/bug.h> |
11 | 29 | ||
12 | #include <linux/mtd/compatmac.h> | ||
13 | 30 | ||
14 | #include <asm/unaligned.h> | 31 | #include <asm/unaligned.h> |
15 | #include <asm/system.h> | 32 | #include <asm/system.h> |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 5326435a7571..8485e42a9b09 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -1,7 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al. | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al. |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
3 | * | 17 | * |
4 | * Released under GPL | ||
5 | */ | 18 | */ |
6 | 19 | ||
7 | #ifndef __MTD_MTD_H__ | 20 | #ifndef __MTD_MTD_H__ |
@@ -13,7 +26,6 @@ | |||
13 | #include <linux/notifier.h> | 26 | #include <linux/notifier.h> |
14 | #include <linux/device.h> | 27 | #include <linux/device.h> |
15 | 28 | ||
16 | #include <linux/mtd/compatmac.h> | ||
17 | #include <mtd/mtd-abi.h> | 29 | #include <mtd/mtd-abi.h> |
18 | 30 | ||
19 | #include <asm/div64.h> | 31 | #include <asm/div64.h> |
@@ -216,6 +228,7 @@ struct mtd_info { | |||
216 | /* Chip-supported device locking */ | 228 | /* Chip-supported device locking */ |
217 | int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 229 | int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
218 | int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 230 | int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
231 | int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | ||
219 | 232 | ||
220 | /* Power Management functions */ | 233 | /* Power Management functions */ |
221 | int (*suspend) (struct mtd_info *mtd); | 234 | int (*suspend) (struct mtd_info *mtd); |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index a81b185e23a7..102e12c58cb3 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * linux/include/linux/mtd/nand.h | 2 | * linux/include/linux/mtd/nand.h |
3 | * | 3 | * |
4 | * Copyright (c) 2000 David Woodhouse <dwmw2@infradead.org> | 4 | * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * Steven J. Hill <sjhill@realitydiluted.com> | 5 | * Steven J. Hill <sjhill@realitydiluted.com> |
6 | * Thomas Gleixner <tglx@linutronix.de> | 6 | * Thomas Gleixner <tglx@linutronix.de> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -181,8 +181,6 @@ typedef enum { | |||
181 | #define NAND_NO_READRDY 0x00000100 | 181 | #define NAND_NO_READRDY 0x00000100 |
182 | /* Chip does not allow subpage writes */ | 182 | /* Chip does not allow subpage writes */ |
183 | #define NAND_NO_SUBPAGE_WRITE 0x00000200 | 183 | #define NAND_NO_SUBPAGE_WRITE 0x00000200 |
184 | /* Chip stores bad block marker on the last page of the eraseblock */ | ||
185 | #define NAND_BB_LAST_PAGE 0x00000400 | ||
186 | 184 | ||
187 | /* Device is one of 'new' xD cards that expose fake nand command set */ | 185 | /* Device is one of 'new' xD cards that expose fake nand command set */ |
188 | #define NAND_BROKEN_XD 0x00000400 | 186 | #define NAND_BROKEN_XD 0x00000400 |
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h index 41bc013571d0..4d8406c81652 100644 --- a/include/linux/mtd/nand_ecc.h +++ b/include/linux/mtd/nand_ecc.h | |||
@@ -1,7 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/mtd/nand_ecc.h | 2 | * drivers/mtd/nand_ecc.h |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | 4 | * Copyright (C) 2000-2010 Steven J. Hill <sjhill@realitydiluted.com> |
5 | * David Woodhouse <dwmw2@infradead.org> | ||
6 | * Thomas Gleixner <tglx@linutronix.de> | ||
5 | * | 7 | * |
6 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h index dcaf611ed748..b059629e22bc 100644 --- a/include/linux/mtd/nftl.h +++ b/include/linux/mtd/nftl.h | |||
@@ -1,5 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | * | ||
3 | */ | 18 | */ |
4 | 19 | ||
5 | #ifndef __MTD_NFTL_H__ | 20 | #ifndef __MTD_NFTL_H__ |
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index c26ff86ad08a..0c8815bfae1c 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h | |||
@@ -68,6 +68,7 @@ struct onenand_bufferram { | |||
68 | * @write_word: [REPLACEABLE] hardware specific function for write | 68 | * @write_word: [REPLACEABLE] hardware specific function for write |
69 | * register of OneNAND | 69 | * register of OneNAND |
70 | * @mmcontrol: sync burst read function | 70 | * @mmcontrol: sync burst read function |
71 | * @chip_probe: [REPLACEABLE] hardware specific function for chip probe | ||
71 | * @block_markbad: function to mark a block as bad | 72 | * @block_markbad: function to mark a block as bad |
72 | * @scan_bbt: [REPLACEALBE] hardware specific function for scanning | 73 | * @scan_bbt: [REPLACEALBE] hardware specific function for scanning |
73 | * Bad block Table | 74 | * Bad block Table |
@@ -114,6 +115,7 @@ struct onenand_chip { | |||
114 | unsigned short (*read_word)(void __iomem *addr); | 115 | unsigned short (*read_word)(void __iomem *addr); |
115 | void (*write_word)(unsigned short value, void __iomem *addr); | 116 | void (*write_word)(unsigned short value, void __iomem *addr); |
116 | void (*mmcontrol)(struct mtd_info *mtd, int sync_read); | 117 | void (*mmcontrol)(struct mtd_info *mtd, int sync_read); |
118 | int (*chip_probe)(struct mtd_info *mtd); | ||
117 | int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); | 119 | int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); |
118 | int (*scan_bbt)(struct mtd_info *mtd); | 120 | int (*scan_bbt)(struct mtd_info *mtd); |
119 | 121 | ||
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h index 76f7cabf07d3..bcfd9f777454 100644 --- a/include/linux/mtd/physmap.h +++ b/include/linux/mtd/physmap.h | |||
@@ -25,6 +25,7 @@ struct physmap_flash_data { | |||
25 | void (*set_vpp)(struct map_info *, int); | 25 | void (*set_vpp)(struct map_info *, int); |
26 | unsigned int nr_parts; | 26 | unsigned int nr_parts; |
27 | unsigned int pfow_base; | 27 | unsigned int pfow_base; |
28 | char *probe_type; | ||
28 | struct mtd_partition *parts; | 29 | struct mtd_partition *parts; |
29 | }; | 30 | }; |
30 | 31 | ||
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index be51ae2bd0ff..4debb4514634 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h | |||
@@ -1,5 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * Portions of MTD ABI definition which are shared by kernel and user space | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al. |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | * | ||
3 | */ | 18 | */ |
4 | 19 | ||
5 | #ifndef __MTD_ABI_H__ | 20 | #ifndef __MTD_ABI_H__ |
@@ -110,6 +125,7 @@ struct otp_info { | |||
110 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) | 125 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) |
111 | #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) | 126 | #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) |
112 | #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) | 127 | #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) |
128 | #define MEMISLOCKED _IOR('M', 23, struct erase_info_user) | ||
113 | 129 | ||
114 | /* | 130 | /* |
115 | * Obsolete legacy interface. Keep it in order not to break userspace | 131 | * Obsolete legacy interface. Keep it in order not to break userspace |
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h index 170ceca3b2d0..aa3c2f86a913 100644 --- a/include/mtd/mtd-user.h +++ b/include/mtd/mtd-user.h | |||
@@ -1,5 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * MTD ABI header for use by user space only. | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | * | ||
3 | */ | 18 | */ |
4 | 19 | ||
5 | #ifndef __MTD_USER_H__ | 20 | #ifndef __MTD_USER_H__ |
diff --git a/include/mtd/nftl-user.h b/include/mtd/nftl-user.h index 98e9e57f22de..bdeabd86ad99 100644 --- a/include/mtd/nftl-user.h +++ b/include/mtd/nftl-user.h | |||
@@ -1,5 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Parts of NFTL headers shared with userspace | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
3 | * | 17 | * |
4 | */ | 18 | */ |
5 | 19 | ||
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index 466a8320f1e6..c0d47ad4b103 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) International Business Machines Corp., 2006 | 2 | * Copyright © International Business Machines Corp., 2006 |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |