diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-07 12:11:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-07 12:11:16 -0500 |
commit | e0d65113a70f1dc514e625cc4e7a7485a4bf72df (patch) | |
tree | 7320a130dc304623f5cf4b5dd8f67fb1776225ca /drivers/mtd | |
parent | cf5e15fbd72c13977720aa15b7b7e00e1d8fd8f2 (diff) | |
parent | 48e546b7f281f251893baa40769581fd15f085fb (diff) |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (226 commits)
mtd: tests: annotate as DANGEROUS in Kconfig
mtd: tests: don't use mtd0 as a default
mtd: clean up usage of MTD_DOCPROBE_ADDRESS
jffs2: add compr=lzo and compr=zlib options
jffs2: implement mount option parsing and compression overriding
mtd: nand: initialize ops.mode
mtd: provide an alias for the redboot module name
mtd: m25p80: don't probe device which has status of 'disabled'
mtd: nand_h1900 never worked
mtd: Add DiskOnChip G3 support
mtd: m25p80: add EON flash EN25Q32B into spi flash id table
mtd: mark block device queue as non-rotational
mtd: r852: make r852_pm_ops static
mtd: m25p80: add support for at25df321a spi data flash
mtd: mxc_nand: preset_v1_v2: unlock all NAND flash blocks
mtd: nand: switch `check_pattern()' to standard `memcmp()'
mtd: nand: invalidate cache on unaligned reads
mtd: nand: do not scan bad blocks with NAND_BBT_NO_OOB set
mtd: nand: wait to set BBT version
mtd: nand: scrub BBT on ECC errors
...
Fix up trivial conflicts:
- arch/arm/mach-at91/board-usb-a9260.c
Merged into board-usb-a926x.c
- drivers/mtd/maps/lantiq-flash.c
add_mtd_partitions -> mtd_device_register vs changed to use
mtd_device_parse_register.
Diffstat (limited to 'drivers/mtd')
129 files changed, 7007 insertions, 3621 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 66b616ebe536..318a869286ab 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -12,27 +12,17 @@ menuconfig MTD | |||
12 | 12 | ||
13 | if MTD | 13 | if MTD |
14 | 14 | ||
15 | config MTD_DEBUG | ||
16 | bool "Debugging" | ||
17 | help | ||
18 | This turns on low-level debugging for the entire MTD sub-system. | ||
19 | Normally, you should say 'N'. | ||
20 | |||
21 | config MTD_DEBUG_VERBOSE | ||
22 | int "Debugging verbosity (0 = quiet, 3 = noisy)" | ||
23 | depends on MTD_DEBUG | ||
24 | default "0" | ||
25 | help | ||
26 | Determines the verbosity level of the MTD debugging messages. | ||
27 | |||
28 | config MTD_TESTS | 15 | config MTD_TESTS |
29 | tristate "MTD tests support" | 16 | tristate "MTD tests support (DANGEROUS)" |
30 | depends on m | 17 | depends on m |
31 | help | 18 | help |
32 | This option includes various MTD tests into compilation. The tests | 19 | This option includes various MTD tests into compilation. The tests |
33 | should normally be compiled as kernel modules. The modules perform | 20 | should normally be compiled as kernel modules. The modules perform |
34 | various checks and verifications when loaded. | 21 | various checks and verifications when loaded. |
35 | 22 | ||
23 | WARNING: some of the tests will ERASE entire MTD device which they | ||
24 | test. Do not use these tests unless you really know what you do. | ||
25 | |||
36 | config MTD_REDBOOT_PARTS | 26 | config MTD_REDBOOT_PARTS |
37 | tristate "RedBoot partition table parsing" | 27 | tristate "RedBoot partition table parsing" |
38 | ---help--- | 28 | ---help--- |
@@ -137,7 +127,8 @@ config MTD_AFS_PARTS | |||
137 | 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. | 127 | 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. |
138 | 128 | ||
139 | config MTD_OF_PARTS | 129 | config MTD_OF_PARTS |
140 | def_bool y | 130 | tristate "OpenFirmware partitioning information support" |
131 | default Y | ||
141 | depends on OF | 132 | depends on OF |
142 | help | 133 | help |
143 | This provides a partition parsing function which derives | 134 | This provides a partition parsing function which derives |
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 39664c4229ff..9aaac3ac89f3 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile | |||
@@ -5,8 +5,8 @@ | |||
5 | # Core functionality. | 5 | # Core functionality. |
6 | obj-$(CONFIG_MTD) += mtd.o | 6 | obj-$(CONFIG_MTD) += mtd.o |
7 | mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o | 7 | mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o |
8 | mtd-$(CONFIG_MTD_OF_PARTS) += ofpart.o | ||
9 | 8 | ||
9 | obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o | ||
10 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o | 10 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o |
11 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o | 11 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o |
12 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o | 12 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o |
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index 302372c08b56..89a02f6f65dc 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c | |||
@@ -162,8 +162,8 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) | |||
162 | } | 162 | } |
163 | 163 | ||
164 | static int parse_afs_partitions(struct mtd_info *mtd, | 164 | static int parse_afs_partitions(struct mtd_info *mtd, |
165 | struct mtd_partition **pparts, | 165 | struct mtd_partition **pparts, |
166 | unsigned long origin) | 166 | struct mtd_part_parser_data *data) |
167 | { | 167 | { |
168 | struct mtd_partition *parts; | 168 | struct mtd_partition *parts; |
169 | u_int mask, off, idx, sz; | 169 | u_int mask, off, idx, sz; |
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c index 95949b97de6a..f40ea4547554 100644 --- a/drivers/mtd/ar7part.c +++ b/drivers/mtd/ar7part.c | |||
@@ -47,7 +47,7 @@ struct ar7_bin_rec { | |||
47 | 47 | ||
48 | static int create_mtd_partitions(struct mtd_info *master, | 48 | static int create_mtd_partitions(struct mtd_info *master, |
49 | struct mtd_partition **pparts, | 49 | struct mtd_partition **pparts, |
50 | unsigned long origin) | 50 | struct mtd_part_parser_data *data) |
51 | { | 51 | { |
52 | struct ar7_bin_rec header; | 52 | struct ar7_bin_rec header; |
53 | unsigned int offset; | 53 | unsigned int offset; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 23175edd5634..8d70895a58d6 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -145,8 +145,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) | |||
145 | if (((major << 8) | minor) < 0x3131) { | 145 | if (((major << 8) | minor) < 0x3131) { |
146 | /* CFI version 1.0 => don't trust bootloc */ | 146 | /* CFI version 1.0 => don't trust bootloc */ |
147 | 147 | ||
148 | DEBUG(MTD_DEBUG_LEVEL1, | 148 | pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", |
149 | "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", | ||
150 | map->name, cfi->mfr, cfi->id); | 149 | map->name, cfi->mfr, cfi->id); |
151 | 150 | ||
152 | /* AFAICS all 29LV400 with a bottom boot block have a device ID | 151 | /* AFAICS all 29LV400 with a bottom boot block have a device ID |
@@ -166,8 +165,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) | |||
166 | * the 8-bit device ID. | 165 | * the 8-bit device ID. |
167 | */ | 166 | */ |
168 | (cfi->mfr == CFI_MFR_MACRONIX)) { | 167 | (cfi->mfr == CFI_MFR_MACRONIX)) { |
169 | DEBUG(MTD_DEBUG_LEVEL1, | 168 | pr_debug("%s: Macronix MX29LV400C with bottom boot block" |
170 | "%s: Macronix MX29LV400C with bottom boot block" | ||
171 | " detected\n", map->name); | 169 | " detected\n", map->name); |
172 | extp->TopBottom = 2; /* bottom boot */ | 170 | extp->TopBottom = 2; /* bottom boot */ |
173 | } else | 171 | } else |
@@ -178,8 +176,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) | |||
178 | extp->TopBottom = 2; /* bottom boot */ | 176 | extp->TopBottom = 2; /* bottom boot */ |
179 | } | 177 | } |
180 | 178 | ||
181 | DEBUG(MTD_DEBUG_LEVEL1, | 179 | pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;" |
182 | "%s: AMD CFI PRI V%c.%c has no boot block field;" | ||
183 | " deduced %s from Device ID\n", map->name, major, minor, | 180 | " deduced %s from Device ID\n", map->name, major, minor, |
184 | extp->TopBottom == 2 ? "bottom" : "top"); | 181 | extp->TopBottom == 2 ? "bottom" : "top"); |
185 | } | 182 | } |
@@ -191,7 +188,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd) | |||
191 | struct map_info *map = mtd->priv; | 188 | struct map_info *map = mtd->priv; |
192 | struct cfi_private *cfi = map->fldrv_priv; | 189 | struct cfi_private *cfi = map->fldrv_priv; |
193 | if (cfi->cfiq->BufWriteTimeoutTyp) { | 190 | if (cfi->cfiq->BufWriteTimeoutTyp) { |
194 | DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); | 191 | pr_debug("Using buffer write method\n" ); |
195 | mtd->write = cfi_amdstd_write_buffers; | 192 | mtd->write = cfi_amdstd_write_buffers; |
196 | } | 193 | } |
197 | } | 194 | } |
@@ -443,8 +440,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
443 | mtd->writesize = 1; | 440 | mtd->writesize = 1; |
444 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | 441 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; |
445 | 442 | ||
446 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n", | 443 | pr_debug("MTD %s(): write buffer size %d\n", __func__, |
447 | __func__, mtd->writebufsize); | 444 | mtd->writebufsize); |
448 | 445 | ||
449 | mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; | 446 | mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; |
450 | 447 | ||
@@ -1163,7 +1160,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1163 | return ret; | 1160 | return ret; |
1164 | } | 1161 | } |
1165 | 1162 | ||
1166 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", | 1163 | pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", |
1167 | __func__, adr, datum.x[0] ); | 1164 | __func__, adr, datum.x[0] ); |
1168 | 1165 | ||
1169 | /* | 1166 | /* |
@@ -1174,7 +1171,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1174 | */ | 1171 | */ |
1175 | oldd = map_read(map, adr); | 1172 | oldd = map_read(map, adr); |
1176 | if (map_word_equal(map, oldd, datum)) { | 1173 | if (map_word_equal(map, oldd, datum)) { |
1177 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n", | 1174 | pr_debug("MTD %s(): NOP\n", |
1178 | __func__); | 1175 | __func__); |
1179 | goto op_done; | 1176 | goto op_done; |
1180 | } | 1177 | } |
@@ -1400,7 +1397,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1400 | 1397 | ||
1401 | datum = map_word_load(map, buf); | 1398 | datum = map_word_load(map, buf); |
1402 | 1399 | ||
1403 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", | 1400 | pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", |
1404 | __func__, adr, datum.x[0] ); | 1401 | __func__, adr, datum.x[0] ); |
1405 | 1402 | ||
1406 | XIP_INVAL_CACHED_RANGE(map, adr, len); | 1403 | XIP_INVAL_CACHED_RANGE(map, adr, len); |
@@ -1587,7 +1584,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) | |||
1587 | return ret; | 1584 | return ret; |
1588 | } | 1585 | } |
1589 | 1586 | ||
1590 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", | 1587 | pr_debug("MTD %s(): ERASE 0x%.8lx\n", |
1591 | __func__, chip->start ); | 1588 | __func__, chip->start ); |
1592 | 1589 | ||
1593 | XIP_INVAL_CACHED_RANGE(map, adr, map->size); | 1590 | XIP_INVAL_CACHED_RANGE(map, adr, map->size); |
@@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1675 | return ret; | 1672 | return ret; |
1676 | } | 1673 | } |
1677 | 1674 | ||
1678 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", | 1675 | pr_debug("MTD %s(): ERASE 0x%.8lx\n", |
1679 | __func__, adr ); | 1676 | __func__, adr ); |
1680 | 1677 | ||
1681 | XIP_INVAL_CACHED_RANGE(map, adr, len); | 1678 | XIP_INVAL_CACHED_RANGE(map, adr, len); |
@@ -1801,8 +1798,7 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip, | |||
1801 | goto out_unlock; | 1798 | goto out_unlock; |
1802 | chip->state = FL_LOCKING; | 1799 | chip->state = FL_LOCKING; |
1803 | 1800 | ||
1804 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", | 1801 | pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); |
1805 | __func__, adr, len); | ||
1806 | 1802 | ||
1807 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | 1803 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, |
1808 | cfi->device_type, NULL); | 1804 | cfi->device_type, NULL); |
@@ -1837,8 +1833,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip, | |||
1837 | goto out_unlock; | 1833 | goto out_unlock; |
1838 | chip->state = FL_UNLOCKING; | 1834 | chip->state = FL_UNLOCKING; |
1839 | 1835 | ||
1840 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", | 1836 | pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); |
1841 | __func__, adr, len); | ||
1842 | 1837 | ||
1843 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | 1838 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, |
1844 | cfi->device_type, NULL); | 1839 | cfi->device_type, NULL); |
diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h index 5e3cc80128aa..89c6595454a5 100644 --- a/drivers/mtd/chips/fwh_lock.h +++ b/drivers/mtd/chips/fwh_lock.h | |||
@@ -34,8 +34,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, | |||
34 | 34 | ||
35 | /* Refuse the operation if the we cannot look behind the chip */ | 35 | /* Refuse the operation if the we cannot look behind the chip */ |
36 | if (chip->start < 0x400000) { | 36 | if (chip->start < 0x400000) { |
37 | DEBUG( MTD_DEBUG_LEVEL3, | 37 | pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n", |
38 | "MTD %s(): chip->start: %lx wanted >= 0x400000\n", | ||
39 | __func__, chip->start ); | 38 | __func__, chip->start ); |
40 | return -EIO; | 39 | return -EIO; |
41 | } | 40 | } |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index ea832ea0e4aa..c443f527a53a 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -1914,11 +1914,10 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) | |||
1914 | * (oh and incidentaly the jedec spec - 3.5.3.3) the reset | 1914 | * (oh and incidentaly the jedec spec - 3.5.3.3) the reset |
1915 | * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at | 1915 | * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at |
1916 | * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips | 1916 | * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips |
1917 | * as they will ignore the writes and dont care what address | 1917 | * as they will ignore the writes and don't care what address |
1918 | * the F0 is written to */ | 1918 | * the F0 is written to */ |
1919 | if (cfi->addr_unlock1) { | 1919 | if (cfi->addr_unlock1) { |
1920 | DEBUG( MTD_DEBUG_LEVEL3, | 1920 | pr_debug( "reset unlock called %x %x \n", |
1921 | "reset unlock called %x %x \n", | ||
1922 | cfi->addr_unlock1,cfi->addr_unlock2); | 1921 | cfi->addr_unlock1,cfi->addr_unlock2); |
1923 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); | 1922 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); |
1924 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); | 1923 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); |
@@ -1941,7 +1940,7 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in | |||
1941 | uint8_t uaddr; | 1940 | uint8_t uaddr; |
1942 | 1941 | ||
1943 | if (!(jedec_table[index].devtypes & cfi->device_type)) { | 1942 | if (!(jedec_table[index].devtypes & cfi->device_type)) { |
1944 | DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", | 1943 | pr_debug("Rejecting potential %s with incompatible %d-bit device type\n", |
1945 | jedec_table[index].name, 4 * (1<<cfi->device_type)); | 1944 | jedec_table[index].name, 4 * (1<<cfi->device_type)); |
1946 | return 0; | 1945 | return 0; |
1947 | } | 1946 | } |
@@ -2021,7 +2020,7 @@ static inline int jedec_match( uint32_t base, | |||
2021 | * there aren't. | 2020 | * there aren't. |
2022 | */ | 2021 | */ |
2023 | if (finfo->dev_id > 0xff) { | 2022 | if (finfo->dev_id > 0xff) { |
2024 | DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n", | 2023 | pr_debug("%s(): ID is not 8bit\n", |
2025 | __func__); | 2024 | __func__); |
2026 | goto match_done; | 2025 | goto match_done; |
2027 | } | 2026 | } |
@@ -2045,12 +2044,10 @@ static inline int jedec_match( uint32_t base, | |||
2045 | } | 2044 | } |
2046 | 2045 | ||
2047 | /* the part size must fit in the memory window */ | 2046 | /* the part size must fit in the memory window */ |
2048 | DEBUG( MTD_DEBUG_LEVEL3, | 2047 | pr_debug("MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", |
2049 | "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", | ||
2050 | __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) ); | 2048 | __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) ); |
2051 | if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) { | 2049 | if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) { |
2052 | DEBUG( MTD_DEBUG_LEVEL3, | 2050 | pr_debug("MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", |
2053 | "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", | ||
2054 | __func__, finfo->mfr_id, finfo->dev_id, | 2051 | __func__, finfo->mfr_id, finfo->dev_id, |
2055 | 1 << finfo->dev_size ); | 2052 | 1 << finfo->dev_size ); |
2056 | goto match_done; | 2053 | goto match_done; |
@@ -2061,13 +2058,12 @@ static inline int jedec_match( uint32_t base, | |||
2061 | 2058 | ||
2062 | uaddr = finfo->uaddr; | 2059 | uaddr = finfo->uaddr; |
2063 | 2060 | ||
2064 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", | 2061 | pr_debug("MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", |
2065 | __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); | 2062 | __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); |
2066 | if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr | 2063 | if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr |
2067 | && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 || | 2064 | && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 || |
2068 | unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) { | 2065 | unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) { |
2069 | DEBUG( MTD_DEBUG_LEVEL3, | 2066 | pr_debug("MTD %s(): 0x%.4x 0x%.4x did not match\n", |
2070 | "MTD %s(): 0x%.4x 0x%.4x did not match\n", | ||
2071 | __func__, | 2067 | __func__, |
2072 | unlock_addrs[uaddr].addr1, | 2068 | unlock_addrs[uaddr].addr1, |
2073 | unlock_addrs[uaddr].addr2); | 2069 | unlock_addrs[uaddr].addr2); |
@@ -2083,15 +2079,13 @@ static inline int jedec_match( uint32_t base, | |||
2083 | * FIXME - write a driver that takes all of the chip info as | 2079 | * FIXME - write a driver that takes all of the chip info as |
2084 | * module parameters, doesn't probe but forces a load. | 2080 | * module parameters, doesn't probe but forces a load. |
2085 | */ | 2081 | */ |
2086 | DEBUG( MTD_DEBUG_LEVEL3, | 2082 | pr_debug("MTD %s(): check ID's disappear when not in ID mode\n", |
2087 | "MTD %s(): check ID's disappear when not in ID mode\n", | ||
2088 | __func__ ); | 2083 | __func__ ); |
2089 | jedec_reset( base, map, cfi ); | 2084 | jedec_reset( base, map, cfi ); |
2090 | mfr = jedec_read_mfr( map, base, cfi ); | 2085 | mfr = jedec_read_mfr( map, base, cfi ); |
2091 | id = jedec_read_id( map, base, cfi ); | 2086 | id = jedec_read_id( map, base, cfi ); |
2092 | if ( mfr == cfi->mfr && id == cfi->id ) { | 2087 | if ( mfr == cfi->mfr && id == cfi->id ) { |
2093 | DEBUG( MTD_DEBUG_LEVEL3, | 2088 | pr_debug("MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n" |
2094 | "MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n" | ||
2095 | "You might need to manually specify JEDEC parameters.\n", | 2089 | "You might need to manually specify JEDEC parameters.\n", |
2096 | __func__, cfi->mfr, cfi->id ); | 2090 | __func__, cfi->mfr, cfi->id ); |
2097 | goto match_done; | 2091 | goto match_done; |
@@ -2104,7 +2098,7 @@ static inline int jedec_match( uint32_t base, | |||
2104 | * Put the device back in ID mode - only need to do this if we | 2098 | * Put the device back in ID mode - only need to do this if we |
2105 | * were truly frobbing a real device. | 2099 | * were truly frobbing a real device. |
2106 | */ | 2100 | */ |
2107 | DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ ); | 2101 | pr_debug("MTD %s(): return to ID mode\n", __func__ ); |
2108 | if (cfi->addr_unlock1) { | 2102 | if (cfi->addr_unlock1) { |
2109 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); | 2103 | cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); |
2110 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); | 2104 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); |
@@ -2167,13 +2161,11 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, | |||
2167 | 2161 | ||
2168 | cfi->mfr = jedec_read_mfr(map, base, cfi); | 2162 | cfi->mfr = jedec_read_mfr(map, base, cfi); |
2169 | cfi->id = jedec_read_id(map, base, cfi); | 2163 | cfi->id = jedec_read_id(map, base, cfi); |
2170 | DEBUG(MTD_DEBUG_LEVEL3, | 2164 | pr_debug("Search for id:(%02x %02x) interleave(%d) type(%d)\n", |
2171 | "Search for id:(%02x %02x) interleave(%d) type(%d)\n", | ||
2172 | cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); | 2165 | cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); |
2173 | for (i = 0; i < ARRAY_SIZE(jedec_table); i++) { | 2166 | for (i = 0; i < ARRAY_SIZE(jedec_table); i++) { |
2174 | if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { | 2167 | if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) { |
2175 | DEBUG( MTD_DEBUG_LEVEL3, | 2168 | pr_debug("MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", |
2176 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", | ||
2177 | __func__, cfi->mfr, cfi->id, | 2169 | __func__, cfi->mfr, cfi->id, |
2178 | cfi->addr_unlock1, cfi->addr_unlock2 ); | 2170 | cfi->addr_unlock1, cfi->addr_unlock2 ); |
2179 | if (!cfi_jedec_setup(map, cfi, i)) | 2171 | if (!cfi_jedec_setup(map, cfi, i)) |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 8cf667da2408..ddf9ec6d9168 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -189,10 +189,7 @@ static struct mtd_partition * newpart(char *s, | |||
189 | extra_mem_size; | 189 | extra_mem_size; |
190 | parts = kzalloc(alloc_size, GFP_KERNEL); | 190 | parts = kzalloc(alloc_size, GFP_KERNEL); |
191 | if (!parts) | 191 | if (!parts) |
192 | { | ||
193 | printk(KERN_ERR ERRP "out of memory\n"); | ||
194 | return NULL; | 192 | return NULL; |
195 | } | ||
196 | extra_mem = (unsigned char *)(parts + *num_parts); | 193 | extra_mem = (unsigned char *)(parts + *num_parts); |
197 | } | 194 | } |
198 | /* enter this partition (offset will be calculated later if it is zero at this point) */ | 195 | /* enter this partition (offset will be calculated later if it is zero at this point) */ |
@@ -317,8 +314,8 @@ static int mtdpart_setup_real(char *s) | |||
317 | * the first one in the chain if a NULL mtd_id is passed in. | 314 | * the first one in the chain if a NULL mtd_id is passed in. |
318 | */ | 315 | */ |
319 | static int parse_cmdline_partitions(struct mtd_info *master, | 316 | static int parse_cmdline_partitions(struct mtd_info *master, |
320 | struct mtd_partition **pparts, | 317 | struct mtd_partition **pparts, |
321 | unsigned long origin) | 318 | struct mtd_part_parser_data *data) |
322 | { | 319 | { |
323 | unsigned long offset; | 320 | unsigned long offset; |
324 | int i; | 321 | int i; |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 35081ce77fbd..283d887f7825 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -249,6 +249,16 @@ config MTD_DOC2001PLUS | |||
249 | under "NAND Flash Device Drivers" (currently that driver does not | 249 | under "NAND Flash Device Drivers" (currently that driver does not |
250 | support all Millennium Plus devices). | 250 | support all Millennium Plus devices). |
251 | 251 | ||
252 | config MTD_DOCG3 | ||
253 | tristate "M-Systems Disk-On-Chip G3" | ||
254 | ---help--- | ||
255 | This provides an MTD device driver for the M-Systems DiskOnChip | ||
256 | G3 devices. | ||
257 | |||
258 | The driver provides access to G3 DiskOnChip, distributed by | ||
259 | M-Systems and now Sandisk. The support is very experimental, | ||
260 | and doesn't give access to any write operations. | ||
261 | |||
252 | config MTD_DOCPROBE | 262 | config MTD_DOCPROBE |
253 | tristate | 263 | tristate |
254 | select MTD_DOCECC | 264 | select MTD_DOCECC |
@@ -268,8 +278,7 @@ config MTD_DOCPROBE_ADVANCED | |||
268 | config MTD_DOCPROBE_ADDRESS | 278 | config MTD_DOCPROBE_ADDRESS |
269 | hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED | 279 | hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED |
270 | depends on MTD_DOCPROBE | 280 | depends on MTD_DOCPROBE |
271 | default "0x0000" if MTD_DOCPROBE_ADVANCED | 281 | default "0x0" |
272 | default "0" if !MTD_DOCPROBE_ADVANCED | ||
273 | ---help--- | 282 | ---help--- |
274 | By default, the probe for DiskOnChip devices will look for a | 283 | By default, the probe for DiskOnChip devices will look for a |
275 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | 284 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index f3226b1d38fc..56c7cd462f11 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | obj-$(CONFIG_MTD_DOC2000) += doc2000.o | 5 | obj-$(CONFIG_MTD_DOC2000) += doc2000.o |
6 | obj-$(CONFIG_MTD_DOC2001) += doc2001.o | 6 | obj-$(CONFIG_MTD_DOC2001) += doc2001.o |
7 | obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o | 7 | obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o |
8 | obj-$(CONFIG_MTD_DOCG3) += docg3.o | ||
8 | obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o | 9 | obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o |
9 | obj-$(CONFIG_MTD_DOCECC) += docecc.o | 10 | obj-$(CONFIG_MTD_DOCECC) += docecc.o |
10 | obj-$(CONFIG_MTD_SLRAM) += slram.o | 11 | obj-$(CONFIG_MTD_SLRAM) += slram.o |
@@ -17,3 +18,5 @@ obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o | |||
17 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o | 18 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o |
18 | obj-$(CONFIG_MTD_M25P80) += m25p80.o | 19 | obj-$(CONFIG_MTD_M25P80) += m25p80.o |
19 | obj-$(CONFIG_MTD_SST25L) += sst25l.o | 20 | obj-$(CONFIG_MTD_SST25L) += sst25l.o |
21 | |||
22 | CFLAGS_docg3.o += -I$(src) \ No newline at end of file | ||
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index f7fbf6025ef2..e9fad9151219 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -82,8 +82,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc) | |||
82 | void __iomem *docptr = doc->virtadr; | 82 | void __iomem *docptr = doc->virtadr; |
83 | unsigned long timeo = jiffies + (HZ * 10); | 83 | unsigned long timeo = jiffies + (HZ * 10); |
84 | 84 | ||
85 | DEBUG(MTD_DEBUG_LEVEL3, | 85 | pr_debug("_DoC_WaitReady called for out-of-line wait\n"); |
86 | "_DoC_WaitReady called for out-of-line wait\n"); | ||
87 | 86 | ||
88 | /* Out-of-line routine to wait for chip response */ | 87 | /* Out-of-line routine to wait for chip response */ |
89 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { | 88 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { |
@@ -92,7 +91,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc) | |||
92 | DoC_Delay(doc, 2); | 91 | DoC_Delay(doc, 2); |
93 | 92 | ||
94 | if (time_after(jiffies, timeo)) { | 93 | if (time_after(jiffies, timeo)) { |
95 | DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); | 94 | pr_debug("_DoC_WaitReady timed out.\n"); |
96 | return -EIO; | 95 | return -EIO; |
97 | } | 96 | } |
98 | udelay(1); | 97 | udelay(1); |
@@ -323,8 +322,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) | |||
323 | 322 | ||
324 | /* Reset the chip */ | 323 | /* Reset the chip */ |
325 | if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { | 324 | if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { |
326 | DEBUG(MTD_DEBUG_LEVEL2, | 325 | pr_debug("DoC_Command (reset) for %d,%d returned true\n", |
327 | "DoC_Command (reset) for %d,%d returned true\n", | ||
328 | floor, chip); | 326 | floor, chip); |
329 | return 0; | 327 | return 0; |
330 | } | 328 | } |
@@ -332,8 +330,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) | |||
332 | 330 | ||
333 | /* Read the NAND chip ID: 1. Send ReadID command */ | 331 | /* Read the NAND chip ID: 1. Send ReadID command */ |
334 | if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { | 332 | if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { |
335 | DEBUG(MTD_DEBUG_LEVEL2, | 333 | pr_debug("DoC_Command (ReadID) for %d,%d returned true\n", |
336 | "DoC_Command (ReadID) for %d,%d returned true\n", | ||
337 | floor, chip); | 334 | floor, chip); |
338 | return 0; | 335 | return 0; |
339 | } | 336 | } |
@@ -699,7 +696,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
699 | #ifdef ECC_DEBUG | 696 | #ifdef ECC_DEBUG |
700 | printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); | 697 | printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); |
701 | #endif | 698 | #endif |
702 | /* Read the ECC syndrom through the DiskOnChip ECC | 699 | /* Read the ECC syndrome through the DiskOnChip ECC |
703 | logic. These syndrome will be all ZERO when there | 700 | logic. These syndrome will be all ZERO when there |
704 | is no error */ | 701 | is no error */ |
705 | for (i = 0; i < 6; i++) { | 702 | for (i = 0; i < 6; i++) { |
@@ -930,7 +927,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | |||
930 | uint8_t *buf = ops->oobbuf; | 927 | uint8_t *buf = ops->oobbuf; |
931 | size_t len = ops->len; | 928 | size_t len = ops->len; |
932 | 929 | ||
933 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 930 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
934 | 931 | ||
935 | ofs += ops->ooboffs; | 932 | ofs += ops->ooboffs; |
936 | 933 | ||
@@ -1094,7 +1091,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1094 | struct DiskOnChip *this = mtd->priv; | 1091 | struct DiskOnChip *this = mtd->priv; |
1095 | int ret; | 1092 | int ret; |
1096 | 1093 | ||
1097 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 1094 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
1098 | 1095 | ||
1099 | mutex_lock(&this->lock); | 1096 | mutex_lock(&this->lock); |
1100 | ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len, | 1097 | ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len, |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 241192f05bc8..a3f7a27499be 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
@@ -55,15 +55,14 @@ static int _DoC_WaitReady(void __iomem * docptr) | |||
55 | { | 55 | { |
56 | unsigned short c = 0xffff; | 56 | unsigned short c = 0xffff; |
57 | 57 | ||
58 | DEBUG(MTD_DEBUG_LEVEL3, | 58 | pr_debug("_DoC_WaitReady called for out-of-line wait\n"); |
59 | "_DoC_WaitReady called for out-of-line wait\n"); | ||
60 | 59 | ||
61 | /* Out-of-line routine to wait for chip response */ | 60 | /* Out-of-line routine to wait for chip response */ |
62 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) | 61 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) |
63 | ; | 62 | ; |
64 | 63 | ||
65 | if (c == 0) | 64 | if (c == 0) |
66 | DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); | 65 | pr_debug("_DoC_WaitReady timed out.\n"); |
67 | 66 | ||
68 | return (c == 0); | 67 | return (c == 0); |
69 | } | 68 | } |
@@ -464,7 +463,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, | |||
464 | #ifdef ECC_DEBUG | 463 | #ifdef ECC_DEBUG |
465 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); | 464 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); |
466 | #endif | 465 | #endif |
467 | /* Read the ECC syndrom through the DiskOnChip ECC logic. | 466 | /* Read the ECC syndrome through the DiskOnChip ECC logic. |
468 | These syndrome will be all ZERO when there is no error */ | 467 | These syndrome will be all ZERO when there is no error */ |
469 | for (i = 0; i < 6; i++) { | 468 | for (i = 0; i < 6; i++) { |
470 | syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); | 469 | syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); |
@@ -632,7 +631,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | |||
632 | uint8_t *buf = ops->oobbuf; | 631 | uint8_t *buf = ops->oobbuf; |
633 | size_t len = ops->len; | 632 | size_t len = ops->len; |
634 | 633 | ||
635 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 634 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
636 | 635 | ||
637 | ofs += ops->ooboffs; | 636 | ofs += ops->ooboffs; |
638 | 637 | ||
@@ -690,7 +689,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
690 | uint8_t *buf = ops->oobbuf; | 689 | uint8_t *buf = ops->oobbuf; |
691 | size_t len = ops->len; | 690 | size_t len = ops->len; |
692 | 691 | ||
693 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 692 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
694 | 693 | ||
695 | ofs += ops->ooboffs; | 694 | ofs += ops->ooboffs; |
696 | 695 | ||
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 09ae0adc3ad0..99351bc3e0ed 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c | |||
@@ -61,15 +61,14 @@ static int _DoC_WaitReady(void __iomem * docptr) | |||
61 | { | 61 | { |
62 | unsigned int c = 0xffff; | 62 | unsigned int c = 0xffff; |
63 | 63 | ||
64 | DEBUG(MTD_DEBUG_LEVEL3, | 64 | pr_debug("_DoC_WaitReady called for out-of-line wait\n"); |
65 | "_DoC_WaitReady called for out-of-line wait\n"); | ||
66 | 65 | ||
67 | /* Out-of-line routine to wait for chip response */ | 66 | /* Out-of-line routine to wait for chip response */ |
68 | while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c) | 67 | while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c) |
69 | ; | 68 | ; |
70 | 69 | ||
71 | if (c == 0) | 70 | if (c == 0) |
72 | DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); | 71 | pr_debug("_DoC_WaitReady timed out.\n"); |
73 | 72 | ||
74 | return (c == 0); | 73 | return (c == 0); |
75 | } | 74 | } |
@@ -655,7 +654,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
655 | #ifdef ECC_DEBUG | 654 | #ifdef ECC_DEBUG |
656 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); | 655 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); |
657 | #endif | 656 | #endif |
658 | /* Read the ECC syndrom through the DiskOnChip ECC logic. | 657 | /* Read the ECC syndrome through the DiskOnChip ECC logic. |
659 | These syndrome will be all ZERO when there is no error */ | 658 | These syndrome will be all ZERO when there is no error */ |
660 | for (i = 0; i < 6; i++) | 659 | for (i = 0; i < 6; i++) |
661 | syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); | 660 | syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); |
@@ -835,7 +834,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | |||
835 | uint8_t *buf = ops->oobbuf; | 834 | uint8_t *buf = ops->oobbuf; |
836 | size_t len = ops->len; | 835 | size_t len = ops->len; |
837 | 836 | ||
838 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 837 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
839 | 838 | ||
840 | ofs += ops->ooboffs; | 839 | ofs += ops->ooboffs; |
841 | 840 | ||
@@ -920,7 +919,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
920 | uint8_t *buf = ops->oobbuf; | 919 | uint8_t *buf = ops->oobbuf; |
921 | size_t len = ops->len; | 920 | size_t len = ops->len; |
922 | 921 | ||
923 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 922 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
924 | 923 | ||
925 | ofs += ops->ooboffs; | 924 | ofs += ops->ooboffs; |
926 | 925 | ||
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index 37ef29a73ee4..4a1c39b6f37d 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ECC algorithm for M-systems disk on chip. We use the excellent Reed | 2 | * ECC algorithm for M-systems disk on chip. We use the excellent Reed |
3 | * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the | 3 | * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the |
4 | * GNU GPL License. The rest is simply to convert the disk on chip | 4 | * GNU GPL License. The rest is simply to convert the disk on chip |
5 | * syndrom into a standard syndom. | 5 | * syndrome into a standard syndome. |
6 | * | 6 | * |
7 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 7 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
8 | * Copyright (C) 2000 Netgem S.A. | 8 | * Copyright (C) 2000 Netgem S.A. |
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c new file mode 100644 index 000000000000..bdcf5df982e8 --- /dev/null +++ b/drivers/mtd/devices/docg3.c | |||
@@ -0,0 +1,1114 @@ | |||
1 | /* | ||
2 | * Handles the M-Systems DiskOnChip G3 chip | ||
3 | * | ||
4 | * Copyright (C) 2011 Robert Jarzmik | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/mtd/mtd.h> | ||
31 | #include <linux/mtd/partitions.h> | ||
32 | |||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | |||
36 | #define CREATE_TRACE_POINTS | ||
37 | #include "docg3.h" | ||
38 | |||
39 | /* | ||
40 | * This driver handles the DiskOnChip G3 flash memory. | ||
41 | * | ||
42 | * As no specification is available from M-Systems/Sandisk, this drivers lacks | ||
43 | * several functions available on the chip, as : | ||
44 | * - block erase | ||
45 | * - page write | ||
46 | * - IPL write | ||
47 | * - ECC fixing (lack of BCH algorith understanding) | ||
48 | * - powerdown / powerup | ||
49 | * | ||
50 | * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and | ||
51 | * the driver assumes a 16bits data bus. | ||
52 | * | ||
53 | * DocG3 relies on 2 ECC algorithms, which are handled in hardware : | ||
54 | * - a 1 byte Hamming code stored in the OOB for each page | ||
55 | * - a 7 bytes BCH code stored in the OOB for each page | ||
56 | * The BCH part is only used for check purpose, no correction is available as | ||
57 | * some information is missing. What is known is that : | ||
58 | * - BCH is in GF(2^14) | ||
59 | * - BCH is over data of 520 bytes (512 page + 7 page_info bytes | ||
60 | * + 1 hamming byte) | ||
61 | * - BCH can correct up to 4 bits (t = 4) | ||
62 | * - BCH syndroms are calculated in hardware, and checked in hardware as well | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | ||
67 | { | ||
68 | u8 val = readb(docg3->base + reg); | ||
69 | |||
70 | trace_docg3_io(0, 8, reg, (int)val); | ||
71 | return val; | ||
72 | } | ||
73 | |||
74 | static inline u16 doc_readw(struct docg3 *docg3, u16 reg) | ||
75 | { | ||
76 | u16 val = readw(docg3->base + reg); | ||
77 | |||
78 | trace_docg3_io(0, 16, reg, (int)val); | ||
79 | return val; | ||
80 | } | ||
81 | |||
82 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) | ||
83 | { | ||
84 | writeb(val, docg3->base + reg); | ||
85 | trace_docg3_io(1, 16, reg, val); | ||
86 | } | ||
87 | |||
88 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) | ||
89 | { | ||
90 | writew(val, docg3->base + reg); | ||
91 | trace_docg3_io(1, 16, reg, val); | ||
92 | } | ||
93 | |||
94 | static inline void doc_flash_command(struct docg3 *docg3, u8 cmd) | ||
95 | { | ||
96 | doc_writeb(docg3, cmd, DOC_FLASHCOMMAND); | ||
97 | } | ||
98 | |||
99 | static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq) | ||
100 | { | ||
101 | doc_writeb(docg3, seq, DOC_FLASHSEQUENCE); | ||
102 | } | ||
103 | |||
104 | static inline void doc_flash_address(struct docg3 *docg3, u8 addr) | ||
105 | { | ||
106 | doc_writeb(docg3, addr, DOC_FLASHADDRESS); | ||
107 | } | ||
108 | |||
109 | static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL }; | ||
110 | |||
111 | static int doc_register_readb(struct docg3 *docg3, int reg) | ||
112 | { | ||
113 | u8 val; | ||
114 | |||
115 | doc_writew(docg3, reg, DOC_READADDRESS); | ||
116 | val = doc_readb(docg3, reg); | ||
117 | doc_vdbg("Read register %04x : %02x\n", reg, val); | ||
118 | return val; | ||
119 | } | ||
120 | |||
121 | static int doc_register_readw(struct docg3 *docg3, int reg) | ||
122 | { | ||
123 | u16 val; | ||
124 | |||
125 | doc_writew(docg3, reg, DOC_READADDRESS); | ||
126 | val = doc_readw(docg3, reg); | ||
127 | doc_vdbg("Read register %04x : %04x\n", reg, val); | ||
128 | return val; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * doc_delay - delay docg3 operations | ||
133 | * @docg3: the device | ||
134 | * @nbNOPs: the number of NOPs to issue | ||
135 | * | ||
136 | * As no specification is available, the right timings between chip commands are | ||
137 | * unknown. The only available piece of information are the observed nops on a | ||
138 | * working docg3 chip. | ||
139 | * Therefore, doc_delay relies on a busy loop of NOPs, instead of scheduler | ||
140 | * friendlier msleep() functions or blocking mdelay(). | ||
141 | */ | ||
142 | static void doc_delay(struct docg3 *docg3, int nbNOPs) | ||
143 | { | ||
144 | int i; | ||
145 | |||
146 | doc_dbg("NOP x %d\n", nbNOPs); | ||
147 | for (i = 0; i < nbNOPs; i++) | ||
148 | doc_writeb(docg3, 0, DOC_NOP); | ||
149 | } | ||
150 | |||
151 | static int is_prot_seq_error(struct docg3 *docg3) | ||
152 | { | ||
153 | int ctrl; | ||
154 | |||
155 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
156 | return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR); | ||
157 | } | ||
158 | |||
159 | static int doc_is_ready(struct docg3 *docg3) | ||
160 | { | ||
161 | int ctrl; | ||
162 | |||
163 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
164 | return ctrl & DOC_CTRL_FLASHREADY; | ||
165 | } | ||
166 | |||
167 | static int doc_wait_ready(struct docg3 *docg3) | ||
168 | { | ||
169 | int maxWaitCycles = 100; | ||
170 | |||
171 | do { | ||
172 | doc_delay(docg3, 4); | ||
173 | cpu_relax(); | ||
174 | } while (!doc_is_ready(docg3) && maxWaitCycles--); | ||
175 | doc_delay(docg3, 2); | ||
176 | if (maxWaitCycles > 0) | ||
177 | return 0; | ||
178 | else | ||
179 | return -EIO; | ||
180 | } | ||
181 | |||
182 | static int doc_reset_seq(struct docg3 *docg3) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | doc_writeb(docg3, 0x10, DOC_FLASHCONTROL); | ||
187 | doc_flash_sequence(docg3, DOC_SEQ_RESET); | ||
188 | doc_flash_command(docg3, DOC_CMD_RESET); | ||
189 | doc_delay(docg3, 2); | ||
190 | ret = doc_wait_ready(docg3); | ||
191 | |||
192 | doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true"); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * doc_read_data_area - Read data from data area | ||
198 | * @docg3: the device | ||
199 | * @buf: the buffer to fill in | ||
200 | * @len: the lenght to read | ||
201 | * @first: first time read, DOC_READADDRESS should be set | ||
202 | * | ||
203 | * Reads bytes from flash data. Handles the single byte / even bytes reads. | ||
204 | */ | ||
205 | static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, | ||
206 | int first) | ||
207 | { | ||
208 | int i, cdr, len4; | ||
209 | u16 data16, *dst16; | ||
210 | u8 data8, *dst8; | ||
211 | |||
212 | doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); | ||
213 | cdr = len & 0x3; | ||
214 | len4 = len - cdr; | ||
215 | |||
216 | if (first) | ||
217 | doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS); | ||
218 | dst16 = buf; | ||
219 | for (i = 0; i < len4; i += 2) { | ||
220 | data16 = doc_readw(docg3, DOC_IOSPACE_DATA); | ||
221 | *dst16 = data16; | ||
222 | dst16++; | ||
223 | } | ||
224 | |||
225 | if (cdr) { | ||
226 | doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE, | ||
227 | DOC_READADDRESS); | ||
228 | doc_delay(docg3, 1); | ||
229 | dst8 = (u8 *)dst16; | ||
230 | for (i = 0; i < cdr; i++) { | ||
231 | data8 = doc_readb(docg3, DOC_IOSPACE_DATA); | ||
232 | *dst8 = data8; | ||
233 | dst8++; | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * doc_set_data_mode - Sets the flash to reliable data mode | ||
240 | * @docg3: the device | ||
241 | * | ||
242 | * The reliable data mode is a bit slower than the fast mode, but less errors | ||
243 | * occur. Entering the reliable mode cannot be done without entering the fast | ||
244 | * mode first. | ||
245 | */ | ||
246 | static void doc_set_reliable_mode(struct docg3 *docg3) | ||
247 | { | ||
248 | doc_dbg("doc_set_reliable_mode()\n"); | ||
249 | doc_flash_sequence(docg3, DOC_SEQ_SET_MODE); | ||
250 | doc_flash_command(docg3, DOC_CMD_FAST_MODE); | ||
251 | doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE); | ||
252 | doc_delay(docg3, 2); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * doc_set_asic_mode - Set the ASIC mode | ||
257 | * @docg3: the device | ||
258 | * @mode: the mode | ||
259 | * | ||
260 | * The ASIC can work in 3 modes : | ||
261 | * - RESET: all registers are zeroed | ||
262 | * - NORMAL: receives and handles commands | ||
263 | * - POWERDOWN: minimal poweruse, flash parts shut off | ||
264 | */ | ||
265 | static void doc_set_asic_mode(struct docg3 *docg3, u8 mode) | ||
266 | { | ||
267 | int i; | ||
268 | |||
269 | for (i = 0; i < 12; i++) | ||
270 | doc_readb(docg3, DOC_IOSPACE_IPL); | ||
271 | |||
272 | mode |= DOC_ASICMODE_MDWREN; | ||
273 | doc_dbg("doc_set_asic_mode(%02x)\n", mode); | ||
274 | doc_writeb(docg3, mode, DOC_ASICMODE); | ||
275 | doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM); | ||
276 | doc_delay(docg3, 1); | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * doc_set_device_id - Sets the devices id for cascaded G3 chips | ||
281 | * @docg3: the device | ||
282 | * @id: the chip to select (amongst 0, 1, 2, 3) | ||
283 | * | ||
284 | * There can be 4 cascaded G3 chips. This function selects the one which will | ||
285 | * should be the active one. | ||
286 | */ | ||
287 | static void doc_set_device_id(struct docg3 *docg3, int id) | ||
288 | { | ||
289 | u8 ctrl; | ||
290 | |||
291 | doc_dbg("doc_set_device_id(%d)\n", id); | ||
292 | doc_writeb(docg3, id, DOC_DEVICESELECT); | ||
293 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
294 | |||
295 | ctrl &= ~DOC_CTRL_VIOLATION; | ||
296 | ctrl |= DOC_CTRL_CE; | ||
297 | doc_writeb(docg3, ctrl, DOC_FLASHCONTROL); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * doc_set_extra_page_mode - Change flash page layout | ||
302 | * @docg3: the device | ||
303 | * | ||
304 | * Normally, the flash page is split into the data (512 bytes) and the out of | ||
305 | * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear | ||
306 | * leveling counters are stored. To access this last area of 4 bytes, a special | ||
307 | * mode must be input to the flash ASIC. | ||
308 | * | ||
309 | * Returns 0 if no error occured, -EIO else. | ||
310 | */ | ||
311 | static int doc_set_extra_page_mode(struct docg3 *docg3) | ||
312 | { | ||
313 | int fctrl; | ||
314 | |||
315 | doc_dbg("doc_set_extra_page_mode()\n"); | ||
316 | doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532); | ||
317 | doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532); | ||
318 | doc_delay(docg3, 2); | ||
319 | |||
320 | fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
321 | if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR)) | ||
322 | return -EIO; | ||
323 | else | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * doc_seek - Set both flash planes to the specified block, page for reading | ||
329 | * @docg3: the device | ||
330 | * @block0: the first plane block index | ||
331 | * @block1: the second plane block index | ||
332 | * @page: the page index within the block | ||
333 | * @wear: if true, read will occur on the 4 extra bytes of the wear area | ||
334 | * @ofs: offset in page to read | ||
335 | * | ||
336 | * Programs the flash even and odd planes to the specific block and page. | ||
337 | * Alternatively, programs the flash to the wear area of the specified page. | ||
338 | */ | ||
339 | static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page, | ||
340 | int wear, int ofs) | ||
341 | { | ||
342 | int sector, ret = 0; | ||
343 | |||
344 | doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n", | ||
345 | block0, block1, page, ofs, wear); | ||
346 | |||
347 | if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) { | ||
348 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1); | ||
349 | doc_flash_command(docg3, DOC_CMD_READ_PLANE1); | ||
350 | doc_delay(docg3, 2); | ||
351 | } else { | ||
352 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2); | ||
353 | doc_flash_command(docg3, DOC_CMD_READ_PLANE2); | ||
354 | doc_delay(docg3, 2); | ||
355 | } | ||
356 | |||
357 | doc_set_reliable_mode(docg3); | ||
358 | if (wear) | ||
359 | ret = doc_set_extra_page_mode(docg3); | ||
360 | if (ret) | ||
361 | goto out; | ||
362 | |||
363 | sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
364 | doc_flash_sequence(docg3, DOC_SEQ_READ); | ||
365 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
366 | doc_delay(docg3, 1); | ||
367 | doc_flash_address(docg3, sector & 0xff); | ||
368 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
369 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
370 | doc_delay(docg3, 1); | ||
371 | |||
372 | sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
373 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
374 | doc_delay(docg3, 1); | ||
375 | doc_flash_address(docg3, sector & 0xff); | ||
376 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
377 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
378 | doc_delay(docg3, 2); | ||
379 | |||
380 | out: | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * doc_read_page_ecc_init - Initialize hardware ECC engine | ||
386 | * @docg3: the device | ||
387 | * @len: the number of bytes covered by the ECC (BCH covered) | ||
388 | * | ||
389 | * The function does initialize the hardware ECC engine to compute the Hamming | ||
390 | * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes). | ||
391 | * | ||
392 | * Return 0 if succeeded, -EIO on error | ||
393 | */ | ||
394 | static int doc_read_page_ecc_init(struct docg3 *docg3, int len) | ||
395 | { | ||
396 | doc_writew(docg3, DOC_ECCCONF0_READ_MODE | ||
397 | | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE | ||
398 | | (len & DOC_ECCCONF0_DATA_BYTES_MASK), | ||
399 | DOC_ECCCONF0); | ||
400 | doc_delay(docg3, 4); | ||
401 | doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
402 | return doc_wait_ready(docg3); | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * doc_read_page_prepare - Prepares reading data from a flash page | ||
407 | * @docg3: the device | ||
408 | * @block0: the first plane block index on flash memory | ||
409 | * @block1: the second plane block index on flash memory | ||
410 | * @page: the page index in the block | ||
411 | * @offset: the offset in the page (must be a multiple of 4) | ||
412 | * | ||
413 | * Prepares the page to be read in the flash memory : | ||
414 | * - tell ASIC to map the flash pages | ||
415 | * - tell ASIC to be in read mode | ||
416 | * | ||
417 | * After a call to this method, a call to doc_read_page_finish is mandatory, | ||
418 | * to end the read cycle of the flash. | ||
419 | * | ||
420 | * Read data from a flash page. The length to be read must be between 0 and | ||
421 | * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because | ||
422 | * the extra bytes reading is not implemented). | ||
423 | * | ||
424 | * As pages are grouped by 2 (in 2 planes), reading from a page must be done | ||
425 | * in two steps: | ||
426 | * - one read of 512 bytes at offset 0 | ||
427 | * - one read of 512 bytes at offset 512 + 16 | ||
428 | * | ||
429 | * Returns 0 if successful, -EIO if a read error occured. | ||
430 | */ | ||
431 | static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1, | ||
432 | int page, int offset) | ||
433 | { | ||
434 | int wear_area = 0, ret = 0; | ||
435 | |||
436 | doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n", | ||
437 | block0, block1, page, offset); | ||
438 | if (offset >= DOC_LAYOUT_WEAR_OFFSET) | ||
439 | wear_area = 1; | ||
440 | if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2)) | ||
441 | return -EINVAL; | ||
442 | |||
443 | doc_set_device_id(docg3, docg3->device_id); | ||
444 | ret = doc_reset_seq(docg3); | ||
445 | if (ret) | ||
446 | goto err; | ||
447 | |||
448 | /* Program the flash address block and page */ | ||
449 | ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset); | ||
450 | if (ret) | ||
451 | goto err; | ||
452 | |||
453 | doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES); | ||
454 | doc_delay(docg3, 2); | ||
455 | doc_wait_ready(docg3); | ||
456 | |||
457 | doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ); | ||
458 | doc_delay(docg3, 1); | ||
459 | if (offset >= DOC_LAYOUT_PAGE_SIZE * 2) | ||
460 | offset -= 2 * DOC_LAYOUT_PAGE_SIZE; | ||
461 | doc_flash_address(docg3, offset >> 2); | ||
462 | doc_delay(docg3, 1); | ||
463 | doc_wait_ready(docg3); | ||
464 | |||
465 | doc_flash_command(docg3, DOC_CMD_READ_FLASH); | ||
466 | |||
467 | return 0; | ||
468 | err: | ||
469 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
470 | doc_delay(docg3, 2); | ||
471 | return -EIO; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * doc_read_page_getbytes - Reads bytes from a prepared page | ||
476 | * @docg3: the device | ||
477 | * @len: the number of bytes to be read (must be a multiple of 4) | ||
478 | * @buf: the buffer to be filled in | ||
479 | * @first: 1 if first time read, DOC_READADDRESS should be set | ||
480 | * | ||
481 | */ | ||
482 | static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, | ||
483 | int first) | ||
484 | { | ||
485 | doc_read_data_area(docg3, buf, len, first); | ||
486 | doc_delay(docg3, 2); | ||
487 | return len; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms | ||
492 | * @docg3: the device | ||
493 | * @syns: the array of 7 integers where the syndroms will be stored | ||
494 | */ | ||
495 | static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns) | ||
496 | { | ||
497 | int i; | ||
498 | |||
499 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) | ||
500 | syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i)); | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * doc_read_page_finish - Ends reading of a flash page | ||
505 | * @docg3: the device | ||
506 | * | ||
507 | * As a side effect, resets the chip selector to 0. This ensures that after each | ||
508 | * read operation, the floor 0 is selected. Therefore, if the systems halts, the | ||
509 | * reboot will boot on floor 0, where the IPL is. | ||
510 | */ | ||
511 | static void doc_read_page_finish(struct docg3 *docg3) | ||
512 | { | ||
513 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
514 | doc_delay(docg3, 2); | ||
515 | doc_set_device_id(docg3, 0); | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * calc_block_sector - Calculate blocks, pages and ofs. | ||
520 | |||
521 | * @from: offset in flash | ||
522 | * @block0: first plane block index calculated | ||
523 | * @block1: second plane block index calculated | ||
524 | * @page: page calculated | ||
525 | * @ofs: offset in page | ||
526 | */ | ||
527 | static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, | ||
528 | int *ofs) | ||
529 | { | ||
530 | uint sector; | ||
531 | |||
532 | sector = from / DOC_LAYOUT_PAGE_SIZE; | ||
533 | *block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES) | ||
534 | * DOC_LAYOUT_NBPLANES; | ||
535 | *block1 = *block0 + 1; | ||
536 | *page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES); | ||
537 | *page /= DOC_LAYOUT_NBPLANES; | ||
538 | if (sector % 2) | ||
539 | *ofs = DOC_LAYOUT_PAGE_OOB_SIZE; | ||
540 | else | ||
541 | *ofs = 0; | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * doc_read - Read bytes from flash | ||
546 | * @mtd: the device | ||
547 | * @from: the offset from first block and first page, in bytes, aligned on page | ||
548 | * size | ||
549 | * @len: the number of bytes to read (must be a multiple of 4) | ||
550 | * @retlen: the number of bytes actually read | ||
551 | * @buf: the filled in buffer | ||
552 | * | ||
553 | * Reads flash memory pages. This function does not read the OOB chunk, but only | ||
554 | * the page data. | ||
555 | * | ||
556 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | ||
557 | */ | ||
558 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
559 | size_t *retlen, u_char *buf) | ||
560 | { | ||
561 | struct docg3 *docg3 = mtd->priv; | ||
562 | int block0, block1, page, readlen, ret, ofs = 0; | ||
563 | int syn[DOC_ECC_BCH_SIZE], eccconf1; | ||
564 | u8 oob[DOC_LAYOUT_OOB_SIZE]; | ||
565 | |||
566 | ret = -EINVAL; | ||
567 | doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf); | ||
568 | if (from % DOC_LAYOUT_PAGE_SIZE) | ||
569 | goto err; | ||
570 | if (len % 4) | ||
571 | goto err; | ||
572 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
573 | if (block1 > docg3->max_block) | ||
574 | goto err; | ||
575 | |||
576 | *retlen = 0; | ||
577 | ret = 0; | ||
578 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
579 | while (!ret && len > 0) { | ||
580 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
581 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); | ||
582 | if (ret < 0) | ||
583 | goto err; | ||
584 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES); | ||
585 | if (ret < 0) | ||
586 | goto err_in_read; | ||
587 | ret = doc_read_page_getbytes(docg3, readlen, buf, 1); | ||
588 | if (ret < readlen) | ||
589 | goto err_in_read; | ||
590 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | ||
591 | oob, 0); | ||
592 | if (ret < DOC_LAYOUT_OOB_SIZE) | ||
593 | goto err_in_read; | ||
594 | |||
595 | *retlen += readlen; | ||
596 | buf += readlen; | ||
597 | len -= readlen; | ||
598 | |||
599 | ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE; | ||
600 | if (ofs == 0) | ||
601 | page += 2; | ||
602 | if (page > DOC_ADDR_PAGE_MASK) { | ||
603 | page = 0; | ||
604 | block0 += 2; | ||
605 | block1 += 2; | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * There should be a BCH bitstream fixing algorithm here ... | ||
610 | * By now, a page read failure is triggered by BCH error | ||
611 | */ | ||
612 | doc_get_hw_bch_syndroms(docg3, syn); | ||
613 | eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); | ||
614 | |||
615 | doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
616 | oob[0], oob[1], oob[2], oob[3], oob[4], | ||
617 | oob[5], oob[6]); | ||
618 | doc_dbg("OOB - HAMMING: %02x\n", oob[7]); | ||
619 | doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
620 | oob[8], oob[9], oob[10], oob[11], oob[12], | ||
621 | oob[13], oob[14]); | ||
622 | doc_dbg("OOB - UNUSED: %02x\n", oob[15]); | ||
623 | doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1); | ||
624 | doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
625 | syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]); | ||
626 | |||
627 | ret = -EBADMSG; | ||
628 | if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) { | ||
629 | if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) | ||
630 | goto err_in_read; | ||
631 | if (is_prot_seq_error(docg3)) | ||
632 | goto err_in_read; | ||
633 | } | ||
634 | doc_read_page_finish(docg3); | ||
635 | } | ||
636 | |||
637 | return 0; | ||
638 | err_in_read: | ||
639 | doc_read_page_finish(docg3); | ||
640 | err: | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | /** | ||
645 | * doc_read_oob - Read out of band bytes from flash | ||
646 | * @mtd: the device | ||
647 | * @from: the offset from first block and first page, in bytes, aligned on page | ||
648 | * size | ||
649 | * @ops: the mtd oob structure | ||
650 | * | ||
651 | * Reads flash memory OOB area of pages. | ||
652 | * | ||
653 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | ||
654 | */ | ||
655 | static int doc_read_oob(struct mtd_info *mtd, loff_t from, | ||
656 | struct mtd_oob_ops *ops) | ||
657 | { | ||
658 | struct docg3 *docg3 = mtd->priv; | ||
659 | int block0, block1, page, ofs, ret; | ||
660 | u8 *buf = ops->oobbuf; | ||
661 | size_t len = ops->ooblen; | ||
662 | |||
663 | doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len); | ||
664 | if (len != DOC_LAYOUT_OOB_SIZE) | ||
665 | return -EINVAL; | ||
666 | |||
667 | switch (ops->mode) { | ||
668 | case MTD_OPS_PLACE_OOB: | ||
669 | buf += ops->ooboffs; | ||
670 | break; | ||
671 | default: | ||
672 | break; | ||
673 | } | ||
674 | |||
675 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
676 | if (block1 > docg3->max_block) | ||
677 | return -EINVAL; | ||
678 | |||
679 | ret = doc_read_page_prepare(docg3, block0, block1, page, | ||
680 | ofs + DOC_LAYOUT_PAGE_SIZE); | ||
681 | if (!ret) | ||
682 | ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE); | ||
683 | if (!ret) | ||
684 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | ||
685 | buf, 1); | ||
686 | doc_read_page_finish(docg3); | ||
687 | |||
688 | if (ret > 0) | ||
689 | ops->oobretlen = ret; | ||
690 | else | ||
691 | ops->oobretlen = 0; | ||
692 | return (ret > 0) ? 0 : ret; | ||
693 | } | ||
694 | |||
695 | static int doc_reload_bbt(struct docg3 *docg3) | ||
696 | { | ||
697 | int block = DOC_LAYOUT_BLOCK_BBT; | ||
698 | int ret = 0, nbpages, page; | ||
699 | u_char *buf = docg3->bbt; | ||
700 | |||
701 | nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE); | ||
702 | for (page = 0; !ret && (page < nbpages); page++) { | ||
703 | ret = doc_read_page_prepare(docg3, block, block + 1, | ||
704 | page + DOC_LAYOUT_PAGE_BBT, 0); | ||
705 | if (!ret) | ||
706 | ret = doc_read_page_ecc_init(docg3, | ||
707 | DOC_LAYOUT_PAGE_SIZE); | ||
708 | if (!ret) | ||
709 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, | ||
710 | buf, 1); | ||
711 | buf += DOC_LAYOUT_PAGE_SIZE; | ||
712 | } | ||
713 | doc_read_page_finish(docg3); | ||
714 | return ret; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * doc_block_isbad - Checks whether a block is good or not | ||
719 | * @mtd: the device | ||
720 | * @from: the offset to find the correct block | ||
721 | * | ||
722 | * Returns 1 if block is bad, 0 if block is good | ||
723 | */ | ||
724 | static int doc_block_isbad(struct mtd_info *mtd, loff_t from) | ||
725 | { | ||
726 | struct docg3 *docg3 = mtd->priv; | ||
727 | int block0, block1, page, ofs, is_good; | ||
728 | |||
729 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
730 | doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n", | ||
731 | from, block0, block1, page, ofs); | ||
732 | |||
733 | if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA) | ||
734 | return 0; | ||
735 | if (block1 > docg3->max_block) | ||
736 | return -EINVAL; | ||
737 | |||
738 | is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7)); | ||
739 | return !is_good; | ||
740 | } | ||
741 | |||
742 | /** | ||
743 | * doc_get_erase_count - Get block erase count | ||
744 | * @docg3: the device | ||
745 | * @from: the offset in which the block is. | ||
746 | * | ||
747 | * Get the number of times a block was erased. The number is the maximum of | ||
748 | * erase times between first and second plane (which should be equal normally). | ||
749 | * | ||
750 | * Returns The number of erases, or -EINVAL or -EIO on error. | ||
751 | */ | ||
752 | static int doc_get_erase_count(struct docg3 *docg3, loff_t from) | ||
753 | { | ||
754 | u8 buf[DOC_LAYOUT_WEAR_SIZE]; | ||
755 | int ret, plane1_erase_count, plane2_erase_count; | ||
756 | int block0, block1, page, ofs; | ||
757 | |||
758 | doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf); | ||
759 | if (from % DOC_LAYOUT_PAGE_SIZE) | ||
760 | return -EINVAL; | ||
761 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
762 | if (block1 > docg3->max_block) | ||
763 | return -EINVAL; | ||
764 | |||
765 | ret = doc_reset_seq(docg3); | ||
766 | if (!ret) | ||
767 | ret = doc_read_page_prepare(docg3, block0, block1, page, | ||
768 | ofs + DOC_LAYOUT_WEAR_OFFSET); | ||
769 | if (!ret) | ||
770 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, | ||
771 | buf, 1); | ||
772 | doc_read_page_finish(docg3); | ||
773 | |||
774 | if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) | ||
775 | return -EIO; | ||
776 | plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8) | ||
777 | | ((u8)(~buf[5]) << 16); | ||
778 | plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8) | ||
779 | | ((u8)(~buf[7]) << 16); | ||
780 | |||
781 | return max(plane1_erase_count, plane2_erase_count); | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * Debug sysfs entries | ||
786 | */ | ||
787 | static int dbg_flashctrl_show(struct seq_file *s, void *p) | ||
788 | { | ||
789 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
790 | |||
791 | int pos = 0; | ||
792 | u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
793 | |||
794 | pos += seq_printf(s, | ||
795 | "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", | ||
796 | fctrl, | ||
797 | fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-", | ||
798 | fctrl & DOC_CTRL_CE ? "active" : "inactive", | ||
799 | fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-", | ||
800 | fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-", | ||
801 | fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready"); | ||
802 | return pos; | ||
803 | } | ||
804 | DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show); | ||
805 | |||
806 | static int dbg_asicmode_show(struct seq_file *s, void *p) | ||
807 | { | ||
808 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
809 | |||
810 | int pos = 0; | ||
811 | int pctrl = doc_register_readb(docg3, DOC_ASICMODE); | ||
812 | int mode = pctrl & 0x03; | ||
813 | |||
814 | pos += seq_printf(s, | ||
815 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", | ||
816 | pctrl, | ||
817 | pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0, | ||
818 | pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0, | ||
819 | pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0, | ||
820 | pctrl & DOC_ASICMODE_MDWREN ? 1 : 0, | ||
821 | pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0, | ||
822 | mode >> 1, mode & 0x1); | ||
823 | |||
824 | switch (mode) { | ||
825 | case DOC_ASICMODE_RESET: | ||
826 | pos += seq_printf(s, "reset"); | ||
827 | break; | ||
828 | case DOC_ASICMODE_NORMAL: | ||
829 | pos += seq_printf(s, "normal"); | ||
830 | break; | ||
831 | case DOC_ASICMODE_POWERDOWN: | ||
832 | pos += seq_printf(s, "powerdown"); | ||
833 | break; | ||
834 | } | ||
835 | pos += seq_printf(s, ")\n"); | ||
836 | return pos; | ||
837 | } | ||
838 | DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show); | ||
839 | |||
840 | static int dbg_device_id_show(struct seq_file *s, void *p) | ||
841 | { | ||
842 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
843 | int pos = 0; | ||
844 | int id = doc_register_readb(docg3, DOC_DEVICESELECT); | ||
845 | |||
846 | pos += seq_printf(s, "DeviceId = %d\n", id); | ||
847 | return pos; | ||
848 | } | ||
849 | DEBUGFS_RO_ATTR(device_id, dbg_device_id_show); | ||
850 | |||
851 | static int dbg_protection_show(struct seq_file *s, void *p) | ||
852 | { | ||
853 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
854 | int pos = 0; | ||
855 | int protect = doc_register_readb(docg3, DOC_PROTECTION); | ||
856 | int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | ||
857 | int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW); | ||
858 | int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH); | ||
859 | int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | ||
860 | int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW); | ||
861 | int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH); | ||
862 | |||
863 | pos += seq_printf(s, "Protection = 0x%02x (", | ||
864 | protect); | ||
865 | if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK) | ||
866 | pos += seq_printf(s, "FOUNDRY_OTP_LOCK,"); | ||
867 | if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK) | ||
868 | pos += seq_printf(s, "CUSTOMER_OTP_LOCK,"); | ||
869 | if (protect & DOC_PROTECT_LOCK_INPUT) | ||
870 | pos += seq_printf(s, "LOCK_INPUT,"); | ||
871 | if (protect & DOC_PROTECT_STICKY_LOCK) | ||
872 | pos += seq_printf(s, "STICKY_LOCK,"); | ||
873 | if (protect & DOC_PROTECT_PROTECTION_ENABLED) | ||
874 | pos += seq_printf(s, "PROTECTION ON,"); | ||
875 | if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK) | ||
876 | pos += seq_printf(s, "IPL_DOWNLOAD_LOCK,"); | ||
877 | if (protect & DOC_PROTECT_PROTECTION_ERROR) | ||
878 | pos += seq_printf(s, "PROTECT_ERR,"); | ||
879 | else | ||
880 | pos += seq_printf(s, "NO_PROTECT_ERR"); | ||
881 | pos += seq_printf(s, ")\n"); | ||
882 | |||
883 | pos += seq_printf(s, "DPS0 = 0x%02x : " | ||
884 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | ||
885 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | ||
886 | dps0, dps0_low, dps0_high, | ||
887 | !!(dps0 & DOC_DPS_OTP_PROTECTED), | ||
888 | !!(dps0 & DOC_DPS_READ_PROTECTED), | ||
889 | !!(dps0 & DOC_DPS_WRITE_PROTECTED), | ||
890 | !!(dps0 & DOC_DPS_HW_LOCK_ENABLED), | ||
891 | !!(dps0 & DOC_DPS_KEY_OK)); | ||
892 | pos += seq_printf(s, "DPS1 = 0x%02x : " | ||
893 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | ||
894 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | ||
895 | dps1, dps1_low, dps1_high, | ||
896 | !!(dps1 & DOC_DPS_OTP_PROTECTED), | ||
897 | !!(dps1 & DOC_DPS_READ_PROTECTED), | ||
898 | !!(dps1 & DOC_DPS_WRITE_PROTECTED), | ||
899 | !!(dps1 & DOC_DPS_HW_LOCK_ENABLED), | ||
900 | !!(dps1 & DOC_DPS_KEY_OK)); | ||
901 | return pos; | ||
902 | } | ||
903 | DEBUGFS_RO_ATTR(protection, dbg_protection_show); | ||
904 | |||
905 | static int __init doc_dbg_register(struct docg3 *docg3) | ||
906 | { | ||
907 | struct dentry *root, *entry; | ||
908 | |||
909 | root = debugfs_create_dir("docg3", NULL); | ||
910 | if (!root) | ||
911 | return -ENOMEM; | ||
912 | |||
913 | entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3, | ||
914 | &flashcontrol_fops); | ||
915 | if (entry) | ||
916 | entry = debugfs_create_file("asic_mode", S_IRUSR, root, | ||
917 | docg3, &asic_mode_fops); | ||
918 | if (entry) | ||
919 | entry = debugfs_create_file("device_id", S_IRUSR, root, | ||
920 | docg3, &device_id_fops); | ||
921 | if (entry) | ||
922 | entry = debugfs_create_file("protection", S_IRUSR, root, | ||
923 | docg3, &protection_fops); | ||
924 | if (entry) { | ||
925 | docg3->debugfs_root = root; | ||
926 | return 0; | ||
927 | } else { | ||
928 | debugfs_remove_recursive(root); | ||
929 | return -ENOMEM; | ||
930 | } | ||
931 | } | ||
932 | |||
933 | static void __exit doc_dbg_unregister(struct docg3 *docg3) | ||
934 | { | ||
935 | debugfs_remove_recursive(docg3->debugfs_root); | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * doc_set_driver_info - Fill the mtd_info structure and docg3 structure | ||
940 | * @chip_id: The chip ID of the supported chip | ||
941 | * @mtd: The structure to fill | ||
942 | */ | ||
943 | static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | ||
944 | { | ||
945 | struct docg3 *docg3 = mtd->priv; | ||
946 | int cfg; | ||
947 | |||
948 | cfg = doc_register_readb(docg3, DOC_CONFIGURATION); | ||
949 | docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0); | ||
950 | |||
951 | switch (chip_id) { | ||
952 | case DOC_CHIPID_G3: | ||
953 | mtd->name = "DiskOnChip G3"; | ||
954 | docg3->max_block = 2047; | ||
955 | break; | ||
956 | } | ||
957 | mtd->type = MTD_NANDFLASH; | ||
958 | /* | ||
959 | * Once write methods are added, the correct flags will be set. | ||
960 | * mtd->flags = MTD_CAP_NANDFLASH; | ||
961 | */ | ||
962 | mtd->flags = MTD_CAP_ROM; | ||
963 | mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE; | ||
964 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; | ||
965 | mtd->writesize = DOC_LAYOUT_PAGE_SIZE; | ||
966 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; | ||
967 | mtd->owner = THIS_MODULE; | ||
968 | mtd->erase = NULL; | ||
969 | mtd->point = NULL; | ||
970 | mtd->unpoint = NULL; | ||
971 | mtd->read = doc_read; | ||
972 | mtd->write = NULL; | ||
973 | mtd->read_oob = doc_read_oob; | ||
974 | mtd->write_oob = NULL; | ||
975 | mtd->sync = NULL; | ||
976 | mtd->block_isbad = doc_block_isbad; | ||
977 | } | ||
978 | |||
979 | /** | ||
980 | * doc_probe - Probe the IO space for a DiskOnChip G3 chip | ||
981 | * @pdev: platform device | ||
982 | * | ||
983 | * Probes for a G3 chip at the specified IO space in the platform data | ||
984 | * ressources. | ||
985 | * | ||
986 | * Returns 0 on success, -ENOMEM, -ENXIO on error | ||
987 | */ | ||
988 | static int __init docg3_probe(struct platform_device *pdev) | ||
989 | { | ||
990 | struct device *dev = &pdev->dev; | ||
991 | struct docg3 *docg3; | ||
992 | struct mtd_info *mtd; | ||
993 | struct resource *ress; | ||
994 | int ret, bbt_nbpages; | ||
995 | u16 chip_id, chip_id_inv; | ||
996 | |||
997 | ret = -ENOMEM; | ||
998 | docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL); | ||
999 | if (!docg3) | ||
1000 | goto nomem1; | ||
1001 | mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); | ||
1002 | if (!mtd) | ||
1003 | goto nomem2; | ||
1004 | mtd->priv = docg3; | ||
1005 | |||
1006 | ret = -ENXIO; | ||
1007 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1008 | if (!ress) { | ||
1009 | dev_err(dev, "No I/O memory resource defined\n"); | ||
1010 | goto noress; | ||
1011 | } | ||
1012 | docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE); | ||
1013 | |||
1014 | docg3->dev = &pdev->dev; | ||
1015 | docg3->device_id = 0; | ||
1016 | doc_set_device_id(docg3, docg3->device_id); | ||
1017 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | ||
1018 | doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL); | ||
1019 | |||
1020 | chip_id = doc_register_readw(docg3, DOC_CHIPID); | ||
1021 | chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV); | ||
1022 | |||
1023 | ret = -ENODEV; | ||
1024 | if (chip_id != (u16)(~chip_id_inv)) { | ||
1025 | doc_info("No device found at IO addr %p\n", | ||
1026 | (void *)ress->start); | ||
1027 | goto nochipfound; | ||
1028 | } | ||
1029 | |||
1030 | switch (chip_id) { | ||
1031 | case DOC_CHIPID_G3: | ||
1032 | doc_info("Found a G3 DiskOnChip at addr %p\n", | ||
1033 | (void *)ress->start); | ||
1034 | break; | ||
1035 | default: | ||
1036 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | ||
1037 | goto nochipfound; | ||
1038 | } | ||
1039 | |||
1040 | doc_set_driver_info(chip_id, mtd); | ||
1041 | platform_set_drvdata(pdev, mtd); | ||
1042 | |||
1043 | ret = -ENOMEM; | ||
1044 | bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1, | ||
1045 | 8 * DOC_LAYOUT_PAGE_SIZE); | ||
1046 | docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL); | ||
1047 | if (!docg3->bbt) | ||
1048 | goto nochipfound; | ||
1049 | doc_reload_bbt(docg3); | ||
1050 | |||
1051 | ret = mtd_device_parse_register(mtd, part_probes, | ||
1052 | NULL, NULL, 0); | ||
1053 | if (ret) | ||
1054 | goto register_error; | ||
1055 | |||
1056 | doc_dbg_register(docg3); | ||
1057 | return 0; | ||
1058 | |||
1059 | register_error: | ||
1060 | kfree(docg3->bbt); | ||
1061 | nochipfound: | ||
1062 | iounmap(docg3->base); | ||
1063 | noress: | ||
1064 | kfree(mtd); | ||
1065 | nomem2: | ||
1066 | kfree(docg3); | ||
1067 | nomem1: | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | /** | ||
1072 | * docg3_release - Release the driver | ||
1073 | * @pdev: the platform device | ||
1074 | * | ||
1075 | * Returns 0 | ||
1076 | */ | ||
1077 | static int __exit docg3_release(struct platform_device *pdev) | ||
1078 | { | ||
1079 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
1080 | struct docg3 *docg3 = mtd->priv; | ||
1081 | |||
1082 | doc_dbg_unregister(docg3); | ||
1083 | mtd_device_unregister(mtd); | ||
1084 | iounmap(docg3->base); | ||
1085 | kfree(docg3->bbt); | ||
1086 | kfree(docg3); | ||
1087 | kfree(mtd); | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static struct platform_driver g3_driver = { | ||
1092 | .driver = { | ||
1093 | .name = "docg3", | ||
1094 | .owner = THIS_MODULE, | ||
1095 | }, | ||
1096 | .remove = __exit_p(docg3_release), | ||
1097 | }; | ||
1098 | |||
1099 | static int __init docg3_init(void) | ||
1100 | { | ||
1101 | return platform_driver_probe(&g3_driver, docg3_probe); | ||
1102 | } | ||
1103 | module_init(docg3_init); | ||
1104 | |||
1105 | |||
1106 | static void __exit docg3_exit(void) | ||
1107 | { | ||
1108 | platform_driver_unregister(&g3_driver); | ||
1109 | } | ||
1110 | module_exit(docg3_exit); | ||
1111 | |||
1112 | MODULE_LICENSE("GPL"); | ||
1113 | MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); | ||
1114 | MODULE_DESCRIPTION("MTD driver for DiskOnChip G3"); | ||
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h new file mode 100644 index 000000000000..0d407be24594 --- /dev/null +++ b/drivers/mtd/devices/docg3.h | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Handles the M-Systems DiskOnChip G3 chip | ||
3 | * | ||
4 | * Copyright (C) 2011 Robert Jarzmik | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef _MTD_DOCG3_H | ||
23 | #define _MTD_DOCG3_H | ||
24 | |||
25 | /* | ||
26 | * Flash memory areas : | ||
27 | * - 0x0000 .. 0x07ff : IPL | ||
28 | * - 0x0800 .. 0x0fff : Data area | ||
29 | * - 0x1000 .. 0x17ff : Registers | ||
30 | * - 0x1800 .. 0x1fff : Unknown | ||
31 | */ | ||
32 | #define DOC_IOSPACE_IPL 0x0000 | ||
33 | #define DOC_IOSPACE_DATA 0x0800 | ||
34 | #define DOC_IOSPACE_SIZE 0x2000 | ||
35 | |||
36 | /* | ||
37 | * DOC G3 layout and adressing scheme | ||
38 | * A page address for the block "b", plane "P" and page "p": | ||
39 | * address = [bbbb bPpp pppp] | ||
40 | */ | ||
41 | |||
42 | #define DOC_ADDR_PAGE_MASK 0x3f | ||
43 | #define DOC_ADDR_BLOCK_SHIFT 6 | ||
44 | #define DOC_LAYOUT_NBPLANES 2 | ||
45 | #define DOC_LAYOUT_PAGES_PER_BLOCK 64 | ||
46 | #define DOC_LAYOUT_PAGE_SIZE 512 | ||
47 | #define DOC_LAYOUT_OOB_SIZE 16 | ||
48 | #define DOC_LAYOUT_WEAR_SIZE 8 | ||
49 | #define DOC_LAYOUT_PAGE_OOB_SIZE \ | ||
50 | (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE) | ||
51 | #define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2) | ||
52 | #define DOC_LAYOUT_BLOCK_SIZE \ | ||
53 | (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE) | ||
54 | #define DOC_ECC_BCH_SIZE 7 | ||
55 | #define DOC_ECC_BCH_COVERED_BYTES \ | ||
56 | (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \ | ||
57 | DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ) | ||
58 | |||
59 | /* | ||
60 | * Blocks distribution | ||
61 | */ | ||
62 | #define DOC_LAYOUT_BLOCK_BBT 0 | ||
63 | #define DOC_LAYOUT_BLOCK_OTP 0 | ||
64 | #define DOC_LAYOUT_BLOCK_FIRST_DATA 6 | ||
65 | |||
66 | #define DOC_LAYOUT_PAGE_BBT 4 | ||
67 | |||
68 | /* | ||
69 | * Extra page OOB (16 bytes wide) layout | ||
70 | */ | ||
71 | #define DOC_LAYOUT_OOB_PAGEINFO_OFS 0 | ||
72 | #define DOC_LAYOUT_OOB_HAMMING_OFS 7 | ||
73 | #define DOC_LAYOUT_OOB_BCH_OFS 8 | ||
74 | #define DOC_LAYOUT_OOB_UNUSED_OFS 15 | ||
75 | #define DOC_LAYOUT_OOB_PAGEINFO_SZ 7 | ||
76 | #define DOC_LAYOUT_OOB_HAMMING_SZ 1 | ||
77 | #define DOC_LAYOUT_OOB_BCH_SZ 7 | ||
78 | #define DOC_LAYOUT_OOB_UNUSED_SZ 1 | ||
79 | |||
80 | |||
81 | #define DOC_CHIPID_G3 0x200 | ||
82 | #define DOC_ERASE_MARK 0xaa | ||
83 | /* | ||
84 | * Flash registers | ||
85 | */ | ||
86 | #define DOC_CHIPID 0x1000 | ||
87 | #define DOC_TEST 0x1004 | ||
88 | #define DOC_BUSLOCK 0x1006 | ||
89 | #define DOC_ENDIANCONTROL 0x1008 | ||
90 | #define DOC_DEVICESELECT 0x100a | ||
91 | #define DOC_ASICMODE 0x100c | ||
92 | #define DOC_CONFIGURATION 0x100e | ||
93 | #define DOC_INTERRUPTCONTROL 0x1010 | ||
94 | #define DOC_READADDRESS 0x101a | ||
95 | #define DOC_DATAEND 0x101e | ||
96 | #define DOC_INTERRUPTSTATUS 0x1020 | ||
97 | |||
98 | #define DOC_FLASHSEQUENCE 0x1032 | ||
99 | #define DOC_FLASHCOMMAND 0x1034 | ||
100 | #define DOC_FLASHADDRESS 0x1036 | ||
101 | #define DOC_FLASHCONTROL 0x1038 | ||
102 | #define DOC_NOP 0x103e | ||
103 | |||
104 | #define DOC_ECCCONF0 0x1040 | ||
105 | #define DOC_ECCCONF1 0x1042 | ||
106 | #define DOC_ECCPRESET 0x1044 | ||
107 | #define DOC_HAMMINGPARITY 0x1046 | ||
108 | #define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 1)) | ||
109 | |||
110 | #define DOC_PROTECTION 0x1056 | ||
111 | #define DOC_DPS0_ADDRLOW 0x1060 | ||
112 | #define DOC_DPS0_ADDRHIGH 0x1062 | ||
113 | #define DOC_DPS1_ADDRLOW 0x1064 | ||
114 | #define DOC_DPS1_ADDRHIGH 0x1066 | ||
115 | #define DOC_DPS0_STATUS 0x106c | ||
116 | #define DOC_DPS1_STATUS 0x106e | ||
117 | |||
118 | #define DOC_ASICMODECONFIRM 0x1072 | ||
119 | #define DOC_CHIPID_INV 0x1074 | ||
120 | |||
121 | /* | ||
122 | * Flash sequences | ||
123 | * A sequence is preset before one or more commands are input to the chip. | ||
124 | */ | ||
125 | #define DOC_SEQ_RESET 0x00 | ||
126 | #define DOC_SEQ_PAGE_SIZE_532 0x03 | ||
127 | #define DOC_SEQ_SET_MODE 0x09 | ||
128 | #define DOC_SEQ_READ 0x12 | ||
129 | #define DOC_SEQ_SET_PLANE1 0x0e | ||
130 | #define DOC_SEQ_SET_PLANE2 0x10 | ||
131 | #define DOC_SEQ_PAGE_SETUP 0x1d | ||
132 | |||
133 | /* | ||
134 | * Flash commands | ||
135 | */ | ||
136 | #define DOC_CMD_READ_PLANE1 0x00 | ||
137 | #define DOC_CMD_SET_ADDR_READ 0x05 | ||
138 | #define DOC_CMD_READ_ALL_PLANES 0x30 | ||
139 | #define DOC_CMD_READ_PLANE2 0x50 | ||
140 | #define DOC_CMD_READ_FLASH 0xe0 | ||
141 | #define DOC_CMD_PAGE_SIZE_532 0x3c | ||
142 | |||
143 | #define DOC_CMD_PROG_BLOCK_ADDR 0x60 | ||
144 | #define DOC_CMD_PROG_CYCLE1 0x80 | ||
145 | #define DOC_CMD_PROG_CYCLE2 0x10 | ||
146 | #define DOC_CMD_ERASECYCLE2 0xd0 | ||
147 | |||
148 | #define DOC_CMD_RELIABLE_MODE 0x22 | ||
149 | #define DOC_CMD_FAST_MODE 0xa2 | ||
150 | |||
151 | #define DOC_CMD_RESET 0xff | ||
152 | |||
153 | /* | ||
154 | * Flash register : DOC_FLASHCONTROL | ||
155 | */ | ||
156 | #define DOC_CTRL_VIOLATION 0x20 | ||
157 | #define DOC_CTRL_CE 0x10 | ||
158 | #define DOC_CTRL_UNKNOWN_BITS 0x08 | ||
159 | #define DOC_CTRL_PROTECTION_ERROR 0x04 | ||
160 | #define DOC_CTRL_SEQUENCE_ERROR 0x02 | ||
161 | #define DOC_CTRL_FLASHREADY 0x01 | ||
162 | |||
163 | /* | ||
164 | * Flash register : DOC_ASICMODE | ||
165 | */ | ||
166 | #define DOC_ASICMODE_RESET 0x00 | ||
167 | #define DOC_ASICMODE_NORMAL 0x01 | ||
168 | #define DOC_ASICMODE_POWERDOWN 0x02 | ||
169 | #define DOC_ASICMODE_MDWREN 0x04 | ||
170 | #define DOC_ASICMODE_BDETCT_RESET 0x08 | ||
171 | #define DOC_ASICMODE_RSTIN_RESET 0x10 | ||
172 | #define DOC_ASICMODE_RAM_WE 0x20 | ||
173 | |||
174 | /* | ||
175 | * Flash register : DOC_ECCCONF0 | ||
176 | */ | ||
177 | #define DOC_ECCCONF0_READ_MODE 0x8000 | ||
178 | #define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000 | ||
179 | #define DOC_ECCCONF0_HAMMING_ENABLE 0x1000 | ||
180 | #define DOC_ECCCONF0_BCH_ENABLE 0x0800 | ||
181 | #define DOC_ECCCONF0_DATA_BYTES_MASK 0x07ff | ||
182 | |||
183 | /* | ||
184 | * Flash register : DOC_ECCCONF1 | ||
185 | */ | ||
186 | #define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80 | ||
187 | #define DOC_ECCCONF1_UNKOWN1 0x40 | ||
188 | #define DOC_ECCCONF1_UNKOWN2 0x20 | ||
189 | #define DOC_ECCCONF1_UNKOWN3 0x10 | ||
190 | #define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f | ||
191 | |||
192 | /* | ||
193 | * Flash register : DOC_PROTECTION | ||
194 | */ | ||
195 | #define DOC_PROTECT_FOUNDRY_OTP_LOCK 0x01 | ||
196 | #define DOC_PROTECT_CUSTOMER_OTP_LOCK 0x02 | ||
197 | #define DOC_PROTECT_LOCK_INPUT 0x04 | ||
198 | #define DOC_PROTECT_STICKY_LOCK 0x08 | ||
199 | #define DOC_PROTECT_PROTECTION_ENABLED 0x10 | ||
200 | #define DOC_PROTECT_IPL_DOWNLOAD_LOCK 0x20 | ||
201 | #define DOC_PROTECT_PROTECTION_ERROR 0x80 | ||
202 | |||
203 | /* | ||
204 | * Flash register : DOC_DPS0_STATUS and DOC_DPS1_STATUS | ||
205 | */ | ||
206 | #define DOC_DPS_OTP_PROTECTED 0x01 | ||
207 | #define DOC_DPS_READ_PROTECTED 0x02 | ||
208 | #define DOC_DPS_WRITE_PROTECTED 0x04 | ||
209 | #define DOC_DPS_HW_LOCK_ENABLED 0x08 | ||
210 | #define DOC_DPS_KEY_OK 0x80 | ||
211 | |||
212 | /* | ||
213 | * Flash register : DOC_CONFIGURATION | ||
214 | */ | ||
215 | #define DOC_CONF_IF_CFG 0x80 | ||
216 | #define DOC_CONF_MAX_ID_MASK 0x30 | ||
217 | #define DOC_CONF_VCCQ_3V 0x01 | ||
218 | |||
219 | /* | ||
220 | * Flash register : DOC_READADDRESS | ||
221 | */ | ||
222 | #define DOC_READADDR_INC 0x8000 | ||
223 | #define DOC_READADDR_ONE_BYTE 0x4000 | ||
224 | #define DOC_READADDR_ADDR_MASK 0x1fff | ||
225 | |||
226 | /** | ||
227 | * struct docg3 - DiskOnChip driver private data | ||
228 | * @dev: the device currently under control | ||
229 | * @base: mapped IO space | ||
230 | * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3) | ||
231 | * @if_cfg: if true, reads are on 16bits, else reads are on 8bits | ||
232 | * @bbt: bad block table cache | ||
233 | * @debugfs_root: debugfs root node | ||
234 | */ | ||
235 | struct docg3 { | ||
236 | struct device *dev; | ||
237 | void __iomem *base; | ||
238 | unsigned int device_id:4; | ||
239 | unsigned int if_cfg:1; | ||
240 | int max_block; | ||
241 | u8 *bbt; | ||
242 | struct dentry *debugfs_root; | ||
243 | }; | ||
244 | |||
245 | #define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg) | ||
246 | #define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg) | ||
247 | #define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg) | ||
248 | #define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg) | ||
249 | |||
250 | #define DEBUGFS_RO_ATTR(name, show_fct) \ | ||
251 | static int name##_open(struct inode *inode, struct file *file) \ | ||
252 | { return single_open(file, show_fct, inode->i_private); } \ | ||
253 | static const struct file_operations name##_fops = { \ | ||
254 | .owner = THIS_MODULE, \ | ||
255 | .open = name##_open, \ | ||
256 | .llseek = seq_lseek, \ | ||
257 | .read = seq_read, \ | ||
258 | .release = single_release \ | ||
259 | }; | ||
260 | #endif | ||
261 | |||
262 | /* | ||
263 | * Trace events part | ||
264 | */ | ||
265 | #undef TRACE_SYSTEM | ||
266 | #define TRACE_SYSTEM docg3 | ||
267 | |||
268 | #if !defined(_MTD_DOCG3_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
269 | #define _MTD_DOCG3_TRACE | ||
270 | |||
271 | #include <linux/tracepoint.h> | ||
272 | |||
273 | TRACE_EVENT(docg3_io, | ||
274 | TP_PROTO(int op, int width, u16 reg, int val), | ||
275 | TP_ARGS(op, width, reg, val), | ||
276 | TP_STRUCT__entry( | ||
277 | __field(int, op) | ||
278 | __field(unsigned char, width) | ||
279 | __field(u16, reg) | ||
280 | __field(int, val)), | ||
281 | TP_fast_assign( | ||
282 | __entry->op = op; | ||
283 | __entry->width = width; | ||
284 | __entry->reg = reg; | ||
285 | __entry->val = val;), | ||
286 | TP_printk("docg3: %s%02d reg=%04x, val=%04x", | ||
287 | __entry->op ? "write" : "read", __entry->width, | ||
288 | __entry->reg, __entry->val) | ||
289 | ); | ||
290 | #endif | ||
291 | |||
292 | /* This part must be outside protection */ | ||
293 | #undef TRACE_INCLUDE_PATH | ||
294 | #undef TRACE_INCLUDE_FILE | ||
295 | #define TRACE_INCLUDE_PATH . | ||
296 | #define TRACE_INCLUDE_FILE docg3 | ||
297 | #include <trace/define_trace.h> | ||
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index d374603493a7..45116bb30297 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c | |||
@@ -50,11 +50,6 @@ | |||
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 | 52 | ||
53 | /* Where to look for the devices? */ | ||
54 | #ifndef CONFIG_MTD_DOCPROBE_ADDRESS | ||
55 | #define CONFIG_MTD_DOCPROBE_ADDRESS 0 | ||
56 | #endif | ||
57 | |||
58 | 53 | ||
59 | static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; | 54 | static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; |
60 | module_param(doc_config_location, ulong, 0); | 55 | module_param(doc_config_location, ulong, 0); |
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 772a0ff89e0f..3a11ea628e58 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c | |||
@@ -34,9 +34,6 @@ | |||
34 | /* debugging */ | 34 | /* debugging */ |
35 | //#define LART_DEBUG | 35 | //#define LART_DEBUG |
36 | 36 | ||
37 | /* partition support */ | ||
38 | #define HAVE_PARTITIONS | ||
39 | |||
40 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
41 | #include <linux/module.h> | 38 | #include <linux/module.h> |
42 | #include <linux/types.h> | 39 | #include <linux/types.h> |
@@ -44,9 +41,7 @@ | |||
44 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
45 | #include <linux/string.h> | 42 | #include <linux/string.h> |
46 | #include <linux/mtd/mtd.h> | 43 | #include <linux/mtd/mtd.h> |
47 | #ifdef HAVE_PARTITIONS | ||
48 | #include <linux/mtd/partitions.h> | 44 | #include <linux/mtd/partitions.h> |
49 | #endif | ||
50 | 45 | ||
51 | #ifndef CONFIG_SA1100_LART | 46 | #ifndef CONFIG_SA1100_LART |
52 | #error This is for LART architecture only | 47 | #error This is for LART architecture only |
@@ -598,7 +593,6 @@ static struct mtd_erase_region_info erase_regions[] = { | |||
598 | } | 593 | } |
599 | }; | 594 | }; |
600 | 595 | ||
601 | #ifdef HAVE_PARTITIONS | ||
602 | static struct mtd_partition lart_partitions[] = { | 596 | static struct mtd_partition lart_partitions[] = { |
603 | /* blob */ | 597 | /* blob */ |
604 | { | 598 | { |
@@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = { | |||
619 | .size = INITRD_LEN, /* MTDPART_SIZ_FULL */ | 613 | .size = INITRD_LEN, /* MTDPART_SIZ_FULL */ |
620 | } | 614 | } |
621 | }; | 615 | }; |
622 | #endif | 616 | #define NUM_PARTITIONS ARRAY_SIZE(lart_partitions) |
623 | 617 | ||
624 | static int __init lart_flash_init (void) | 618 | static int __init lart_flash_init (void) |
625 | { | 619 | { |
@@ -668,7 +662,6 @@ static int __init lart_flash_init (void) | |||
668 | result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024, | 662 | result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024, |
669 | result,mtd.eraseregions[result].numblocks); | 663 | result,mtd.eraseregions[result].numblocks); |
670 | 664 | ||
671 | #ifdef HAVE_PARTITIONS | ||
672 | printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions)); | 665 | printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions)); |
673 | 666 | ||
674 | for (result = 0; result < ARRAY_SIZE(lart_partitions); result++) | 667 | for (result = 0; result < ARRAY_SIZE(lart_partitions); result++) |
@@ -681,25 +674,16 @@ static int __init lart_flash_init (void) | |||
681 | result,lart_partitions[result].offset, | 674 | result,lart_partitions[result].offset, |
682 | result,lart_partitions[result].size,lart_partitions[result].size / 1024); | 675 | result,lart_partitions[result].size,lart_partitions[result].size / 1024); |
683 | #endif | 676 | #endif |
684 | #endif | ||
685 | 677 | ||
686 | #ifndef HAVE_PARTITIONS | ||
687 | result = mtd_device_register(&mtd, NULL, 0); | ||
688 | #else | ||
689 | result = mtd_device_register(&mtd, lart_partitions, | 678 | result = mtd_device_register(&mtd, lart_partitions, |
690 | ARRAY_SIZE(lart_partitions)); | 679 | ARRAY_SIZE(lart_partitions)); |
691 | #endif | ||
692 | 680 | ||
693 | return (result); | 681 | return (result); |
694 | } | 682 | } |
695 | 683 | ||
696 | static void __exit lart_flash_exit (void) | 684 | static void __exit lart_flash_exit (void) |
697 | { | 685 | { |
698 | #ifndef HAVE_PARTITIONS | ||
699 | mtd_device_unregister(&mtd); | ||
700 | #else | ||
701 | mtd_device_unregister(&mtd); | 686 | mtd_device_unregister(&mtd); |
702 | #endif | ||
703 | } | 687 | } |
704 | 688 | ||
705 | module_init (lart_flash_init); | 689 | module_init (lart_flash_init); |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 35180e475c4c..884904d3f9d2 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/mtd/cfi.h> | 30 | #include <linux/mtd/cfi.h> |
31 | #include <linux/mtd/mtd.h> | 31 | #include <linux/mtd/mtd.h> |
32 | #include <linux/mtd/partitions.h> | 32 | #include <linux/mtd/partitions.h> |
33 | #include <linux/of_platform.h> | ||
33 | 34 | ||
34 | #include <linux/spi/spi.h> | 35 | #include <linux/spi/spi.h> |
35 | #include <linux/spi/flash.h> | 36 | #include <linux/spi/flash.h> |
@@ -88,7 +89,6 @@ struct m25p { | |||
88 | struct spi_device *spi; | 89 | struct spi_device *spi; |
89 | struct mutex lock; | 90 | struct mutex lock; |
90 | struct mtd_info mtd; | 91 | struct mtd_info mtd; |
91 | unsigned partitioned:1; | ||
92 | u16 page_size; | 92 | u16 page_size; |
93 | u16 addr_width; | 93 | u16 addr_width; |
94 | u8 erase_opcode; | 94 | u8 erase_opcode; |
@@ -209,9 +209,8 @@ static int wait_till_ready(struct m25p *flash) | |||
209 | */ | 209 | */ |
210 | static int erase_chip(struct m25p *flash) | 210 | static int erase_chip(struct m25p *flash) |
211 | { | 211 | { |
212 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n", | 212 | pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__, |
213 | dev_name(&flash->spi->dev), __func__, | 213 | (long long)(flash->mtd.size >> 10)); |
214 | (long long)(flash->mtd.size >> 10)); | ||
215 | 214 | ||
216 | /* Wait until finished previous write command. */ | 215 | /* Wait until finished previous write command. */ |
217 | if (wait_till_ready(flash)) | 216 | if (wait_till_ready(flash)) |
@@ -250,9 +249,8 @@ static int m25p_cmdsz(struct m25p *flash) | |||
250 | */ | 249 | */ |
251 | static int erase_sector(struct m25p *flash, u32 offset) | 250 | static int erase_sector(struct m25p *flash, u32 offset) |
252 | { | 251 | { |
253 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", | 252 | pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev), |
254 | dev_name(&flash->spi->dev), __func__, | 253 | __func__, flash->mtd.erasesize / 1024, offset); |
255 | flash->mtd.erasesize / 1024, offset); | ||
256 | 254 | ||
257 | /* Wait until finished previous write command. */ | 255 | /* Wait until finished previous write command. */ |
258 | if (wait_till_ready(flash)) | 256 | if (wait_till_ready(flash)) |
@@ -286,9 +284,9 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
286 | u32 addr,len; | 284 | u32 addr,len; |
287 | uint32_t rem; | 285 | uint32_t rem; |
288 | 286 | ||
289 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n", | 287 | pr_debug("%s: %s at 0x%llx, len %lld\n", dev_name(&flash->spi->dev), |
290 | dev_name(&flash->spi->dev), __func__, "at", | 288 | __func__, (long long)instr->addr, |
291 | (long long)instr->addr, (long long)instr->len); | 289 | (long long)instr->len); |
292 | 290 | ||
293 | /* sanity checks */ | 291 | /* sanity checks */ |
294 | if (instr->addr + instr->len > flash->mtd.size) | 292 | if (instr->addr + instr->len > flash->mtd.size) |
@@ -348,9 +346,8 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
348 | struct spi_transfer t[2]; | 346 | struct spi_transfer t[2]; |
349 | struct spi_message m; | 347 | struct spi_message m; |
350 | 348 | ||
351 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 349 | pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
352 | dev_name(&flash->spi->dev), __func__, "from", | 350 | __func__, (u32)from, len); |
353 | (u32)from, len); | ||
354 | 351 | ||
355 | /* sanity checks */ | 352 | /* sanity checks */ |
356 | if (!len) | 353 | if (!len) |
@@ -417,9 +414,8 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
417 | struct spi_transfer t[2]; | 414 | struct spi_transfer t[2]; |
418 | struct spi_message m; | 415 | struct spi_message m; |
419 | 416 | ||
420 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 417 | pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
421 | dev_name(&flash->spi->dev), __func__, "to", | 418 | __func__, (u32)to, len); |
422 | (u32)to, len); | ||
423 | 419 | ||
424 | *retlen = 0; | 420 | *retlen = 0; |
425 | 421 | ||
@@ -510,9 +506,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
510 | size_t actual; | 506 | size_t actual; |
511 | int cmd_sz, ret; | 507 | int cmd_sz, ret; |
512 | 508 | ||
513 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 509 | pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
514 | dev_name(&flash->spi->dev), __func__, "to", | 510 | __func__, (u32)to, len); |
515 | (u32)to, len); | ||
516 | 511 | ||
517 | *retlen = 0; | 512 | *retlen = 0; |
518 | 513 | ||
@@ -661,6 +656,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
661 | { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, | 656 | { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, |
662 | 657 | ||
663 | { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, | 658 | { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, |
659 | { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, | ||
664 | { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, | 660 | { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, |
665 | 661 | ||
666 | { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, | 662 | { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, |
@@ -671,6 +667,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
671 | /* EON -- en25xxx */ | 667 | /* EON -- en25xxx */ |
672 | { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, | 668 | { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, |
673 | { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, | 669 | { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, |
670 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, | ||
674 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | 671 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, |
675 | 672 | ||
676 | /* Intel/Numonyx -- xxxs33b */ | 673 | /* Intel/Numonyx -- xxxs33b */ |
@@ -788,8 +785,8 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
788 | */ | 785 | */ |
789 | tmp = spi_write_then_read(spi, &code, 1, id, 5); | 786 | tmp = spi_write_then_read(spi, &code, 1, id, 5); |
790 | if (tmp < 0) { | 787 | if (tmp < 0) { |
791 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", | 788 | pr_debug("%s: error %d reading JEDEC ID\n", |
792 | dev_name(&spi->dev), tmp); | 789 | dev_name(&spi->dev), tmp); |
793 | return ERR_PTR(tmp); | 790 | return ERR_PTR(tmp); |
794 | } | 791 | } |
795 | jedec = id[0]; | 792 | jedec = id[0]; |
@@ -825,8 +822,12 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
825 | struct m25p *flash; | 822 | struct m25p *flash; |
826 | struct flash_info *info; | 823 | struct flash_info *info; |
827 | unsigned i; | 824 | unsigned i; |
828 | struct mtd_partition *parts = NULL; | 825 | struct mtd_part_parser_data ppdata; |
829 | int nr_parts = 0; | 826 | |
827 | #ifdef CONFIG_MTD_OF_PARTS | ||
828 | if (!of_device_is_available(spi->dev.of_node)) | ||
829 | return -ENODEV; | ||
830 | #endif | ||
830 | 831 | ||
831 | /* Platform data helps sort out which chip type we have, as | 832 | /* Platform data helps sort out which chip type we have, as |
832 | * well as how this board partitions it. If we don't have | 833 | * well as how this board partitions it. If we don't have |
@@ -928,6 +929,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
928 | if (info->flags & M25P_NO_ERASE) | 929 | if (info->flags & M25P_NO_ERASE) |
929 | flash->mtd.flags |= MTD_NO_ERASE; | 930 | flash->mtd.flags |= MTD_NO_ERASE; |
930 | 931 | ||
932 | ppdata.of_node = spi->dev.of_node; | ||
931 | flash->mtd.dev.parent = &spi->dev; | 933 | flash->mtd.dev.parent = &spi->dev; |
932 | flash->page_size = info->page_size; | 934 | flash->page_size = info->page_size; |
933 | 935 | ||
@@ -945,8 +947,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
945 | dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, | 947 | dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, |
946 | (long long)flash->mtd.size >> 10); | 948 | (long long)flash->mtd.size >> 10); |
947 | 949 | ||
948 | DEBUG(MTD_DEBUG_LEVEL2, | 950 | pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) " |
949 | "mtd .name = %s, .size = 0x%llx (%lldMiB) " | ||
950 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", | 951 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", |
951 | flash->mtd.name, | 952 | flash->mtd.name, |
952 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), | 953 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), |
@@ -955,8 +956,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
955 | 956 | ||
956 | if (flash->mtd.numeraseregions) | 957 | if (flash->mtd.numeraseregions) |
957 | for (i = 0; i < flash->mtd.numeraseregions; i++) | 958 | for (i = 0; i < flash->mtd.numeraseregions; i++) |
958 | DEBUG(MTD_DEBUG_LEVEL2, | 959 | pr_debug("mtd.eraseregions[%d] = { .offset = 0x%llx, " |
959 | "mtd.eraseregions[%d] = { .offset = 0x%llx, " | ||
960 | ".erasesize = 0x%.8x (%uKiB), " | 960 | ".erasesize = 0x%.8x (%uKiB), " |
961 | ".numblocks = %d }\n", | 961 | ".numblocks = %d }\n", |
962 | i, (long long)flash->mtd.eraseregions[i].offset, | 962 | i, (long long)flash->mtd.eraseregions[i].offset, |
@@ -968,41 +968,9 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
968 | /* partitions should match sector boundaries; and it may be good to | 968 | /* partitions should match sector boundaries; and it may be good to |
969 | * use readonly partitions for writeprotected sectors (BP2..BP0). | 969 | * use readonly partitions for writeprotected sectors (BP2..BP0). |
970 | */ | 970 | */ |
971 | if (mtd_has_cmdlinepart()) { | 971 | return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, |
972 | static const char *part_probes[] | 972 | data ? data->parts : NULL, |
973 | = { "cmdlinepart", NULL, }; | 973 | data ? data->nr_parts : 0); |
974 | |||
975 | nr_parts = parse_mtd_partitions(&flash->mtd, | ||
976 | part_probes, &parts, 0); | ||
977 | } | ||
978 | |||
979 | if (nr_parts <= 0 && data && data->parts) { | ||
980 | parts = data->parts; | ||
981 | nr_parts = data->nr_parts; | ||
982 | } | ||
983 | |||
984 | #ifdef CONFIG_MTD_OF_PARTS | ||
985 | if (nr_parts <= 0 && spi->dev.of_node) { | ||
986 | nr_parts = of_mtd_parse_partitions(&spi->dev, | ||
987 | spi->dev.of_node, &parts); | ||
988 | } | ||
989 | #endif | ||
990 | |||
991 | if (nr_parts > 0) { | ||
992 | for (i = 0; i < nr_parts; i++) { | ||
993 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | ||
994 | "{.name = %s, .offset = 0x%llx, " | ||
995 | ".size = 0x%llx (%lldKiB) }\n", | ||
996 | i, parts[i].name, | ||
997 | (long long)parts[i].offset, | ||
998 | (long long)parts[i].size, | ||
999 | (long long)(parts[i].size >> 10)); | ||
1000 | } | ||
1001 | flash->partitioned = 1; | ||
1002 | } | ||
1003 | |||
1004 | return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ? | ||
1005 | -ENODEV : 0; | ||
1006 | } | 974 | } |
1007 | 975 | ||
1008 | 976 | ||
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 13749d458a31..d75c7af18a63 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/math64.h> | 19 | #include <linux/math64.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_device.h> | ||
20 | 22 | ||
21 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
22 | #include <linux/spi/flash.h> | 24 | #include <linux/spi/flash.h> |
@@ -24,7 +26,6 @@ | |||
24 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
25 | #include <linux/mtd/partitions.h> | 27 | #include <linux/mtd/partitions.h> |
26 | 28 | ||
27 | |||
28 | /* | 29 | /* |
29 | * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in | 30 | * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in |
30 | * each chip, which may be used for double buffered I/O; but this driver | 31 | * each chip, which may be used for double buffered I/O; but this driver |
@@ -98,6 +99,16 @@ struct dataflash { | |||
98 | struct mtd_info mtd; | 99 | struct mtd_info mtd; |
99 | }; | 100 | }; |
100 | 101 | ||
102 | #ifdef CONFIG_OF | ||
103 | static const struct of_device_id dataflash_dt_ids[] = { | ||
104 | { .compatible = "atmel,at45", }, | ||
105 | { .compatible = "atmel,dataflash", }, | ||
106 | { /* sentinel */ } | ||
107 | }; | ||
108 | #else | ||
109 | #define dataflash_dt_ids NULL | ||
110 | #endif | ||
111 | |||
101 | /* ......................................................................... */ | 112 | /* ......................................................................... */ |
102 | 113 | ||
103 | /* | 114 | /* |
@@ -122,7 +133,7 @@ static int dataflash_waitready(struct spi_device *spi) | |||
122 | for (;;) { | 133 | for (;;) { |
123 | status = dataflash_status(spi); | 134 | status = dataflash_status(spi); |
124 | if (status < 0) { | 135 | if (status < 0) { |
125 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", | 136 | pr_debug("%s: status %d?\n", |
126 | dev_name(&spi->dev), status); | 137 | dev_name(&spi->dev), status); |
127 | status = 0; | 138 | status = 0; |
128 | } | 139 | } |
@@ -149,7 +160,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
149 | uint8_t *command; | 160 | uint8_t *command; |
150 | uint32_t rem; | 161 | uint32_t rem; |
151 | 162 | ||
152 | DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n", | 163 | pr_debug("%s: erase addr=0x%llx len 0x%llx\n", |
153 | dev_name(&spi->dev), (long long)instr->addr, | 164 | dev_name(&spi->dev), (long long)instr->addr, |
154 | (long long)instr->len); | 165 | (long long)instr->len); |
155 | 166 | ||
@@ -187,7 +198,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
187 | command[2] = (uint8_t)(pageaddr >> 8); | 198 | command[2] = (uint8_t)(pageaddr >> 8); |
188 | command[3] = 0; | 199 | command[3] = 0; |
189 | 200 | ||
190 | DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", | 201 | pr_debug("ERASE %s: (%x) %x %x %x [%i]\n", |
191 | do_block ? "block" : "page", | 202 | do_block ? "block" : "page", |
192 | command[0], command[1], command[2], command[3], | 203 | command[0], command[1], command[2], command[3], |
193 | pageaddr); | 204 | pageaddr); |
@@ -238,8 +249,8 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
238 | uint8_t *command; | 249 | uint8_t *command; |
239 | int status; | 250 | int status; |
240 | 251 | ||
241 | DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", | 252 | pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev), |
242 | dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len)); | 253 | (unsigned)from, (unsigned)(from + len)); |
243 | 254 | ||
244 | *retlen = 0; | 255 | *retlen = 0; |
245 | 256 | ||
@@ -255,7 +266,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
255 | 266 | ||
256 | command = priv->command; | 267 | command = priv->command; |
257 | 268 | ||
258 | DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", | 269 | pr_debug("READ: (%x) %x %x %x\n", |
259 | command[0], command[1], command[2], command[3]); | 270 | command[0], command[1], command[2], command[3]); |
260 | 271 | ||
261 | spi_message_init(&msg); | 272 | spi_message_init(&msg); |
@@ -287,7 +298,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
287 | *retlen = msg.actual_length - 8; | 298 | *retlen = msg.actual_length - 8; |
288 | status = 0; | 299 | status = 0; |
289 | } else | 300 | } else |
290 | DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", | 301 | pr_debug("%s: read %x..%x --> %d\n", |
291 | dev_name(&priv->spi->dev), | 302 | dev_name(&priv->spi->dev), |
292 | (unsigned)from, (unsigned)(from + len), | 303 | (unsigned)from, (unsigned)(from + len), |
293 | status); | 304 | status); |
@@ -314,7 +325,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
314 | int status = -EINVAL; | 325 | int status = -EINVAL; |
315 | uint8_t *command; | 326 | uint8_t *command; |
316 | 327 | ||
317 | DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", | 328 | pr_debug("%s: write 0x%x..0x%x\n", |
318 | dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len)); | 329 | dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len)); |
319 | 330 | ||
320 | *retlen = 0; | 331 | *retlen = 0; |
@@ -340,7 +351,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
340 | 351 | ||
341 | mutex_lock(&priv->lock); | 352 | mutex_lock(&priv->lock); |
342 | while (remaining > 0) { | 353 | while (remaining > 0) { |
343 | DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", | 354 | pr_debug("write @ %i:%i len=%i\n", |
344 | pageaddr, offset, writelen); | 355 | pageaddr, offset, writelen); |
345 | 356 | ||
346 | /* REVISIT: | 357 | /* REVISIT: |
@@ -368,12 +379,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
368 | command[2] = (addr & 0x0000FF00) >> 8; | 379 | command[2] = (addr & 0x0000FF00) >> 8; |
369 | command[3] = 0; | 380 | command[3] = 0; |
370 | 381 | ||
371 | DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", | 382 | pr_debug("TRANSFER: (%x) %x %x %x\n", |
372 | command[0], command[1], command[2], command[3]); | 383 | command[0], command[1], command[2], command[3]); |
373 | 384 | ||
374 | status = spi_sync(spi, &msg); | 385 | status = spi_sync(spi, &msg); |
375 | if (status < 0) | 386 | if (status < 0) |
376 | DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", | 387 | pr_debug("%s: xfer %u -> %d\n", |
377 | dev_name(&spi->dev), addr, status); | 388 | dev_name(&spi->dev), addr, status); |
378 | 389 | ||
379 | (void) dataflash_waitready(priv->spi); | 390 | (void) dataflash_waitready(priv->spi); |
@@ -386,7 +397,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
386 | command[2] = (addr & 0x0000FF00) >> 8; | 397 | command[2] = (addr & 0x0000FF00) >> 8; |
387 | command[3] = (addr & 0x000000FF); | 398 | command[3] = (addr & 0x000000FF); |
388 | 399 | ||
389 | DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", | 400 | pr_debug("PROGRAM: (%x) %x %x %x\n", |
390 | command[0], command[1], command[2], command[3]); | 401 | command[0], command[1], command[2], command[3]); |
391 | 402 | ||
392 | x[1].tx_buf = writebuf; | 403 | x[1].tx_buf = writebuf; |
@@ -395,7 +406,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
395 | status = spi_sync(spi, &msg); | 406 | status = spi_sync(spi, &msg); |
396 | spi_transfer_del(x + 1); | 407 | spi_transfer_del(x + 1); |
397 | if (status < 0) | 408 | if (status < 0) |
398 | DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", | 409 | pr_debug("%s: pgm %u/%u -> %d\n", |
399 | dev_name(&spi->dev), addr, writelen, status); | 410 | dev_name(&spi->dev), addr, writelen, status); |
400 | 411 | ||
401 | (void) dataflash_waitready(priv->spi); | 412 | (void) dataflash_waitready(priv->spi); |
@@ -410,12 +421,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
410 | command[2] = (addr & 0x0000FF00) >> 8; | 421 | command[2] = (addr & 0x0000FF00) >> 8; |
411 | command[3] = 0; | 422 | command[3] = 0; |
412 | 423 | ||
413 | DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", | 424 | pr_debug("COMPARE: (%x) %x %x %x\n", |
414 | command[0], command[1], command[2], command[3]); | 425 | command[0], command[1], command[2], command[3]); |
415 | 426 | ||
416 | status = spi_sync(spi, &msg); | 427 | status = spi_sync(spi, &msg); |
417 | if (status < 0) | 428 | if (status < 0) |
418 | DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", | 429 | pr_debug("%s: compare %u -> %d\n", |
419 | dev_name(&spi->dev), addr, status); | 430 | dev_name(&spi->dev), addr, status); |
420 | 431 | ||
421 | status = dataflash_waitready(priv->spi); | 432 | status = dataflash_waitready(priv->spi); |
@@ -634,11 +645,10 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
634 | { | 645 | { |
635 | struct dataflash *priv; | 646 | struct dataflash *priv; |
636 | struct mtd_info *device; | 647 | struct mtd_info *device; |
648 | struct mtd_part_parser_data ppdata; | ||
637 | struct flash_platform_data *pdata = spi->dev.platform_data; | 649 | struct flash_platform_data *pdata = spi->dev.platform_data; |
638 | char *otp_tag = ""; | 650 | char *otp_tag = ""; |
639 | int err = 0; | 651 | int err = 0; |
640 | struct mtd_partition *parts; | ||
641 | int nr_parts = 0; | ||
642 | 652 | ||
643 | priv = kzalloc(sizeof *priv, GFP_KERNEL); | 653 | priv = kzalloc(sizeof *priv, GFP_KERNEL); |
644 | if (!priv) | 654 | if (!priv) |
@@ -677,28 +687,11 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
677 | pagesize, otp_tag); | 687 | pagesize, otp_tag); |
678 | dev_set_drvdata(&spi->dev, priv); | 688 | dev_set_drvdata(&spi->dev, priv); |
679 | 689 | ||
680 | if (mtd_has_cmdlinepart()) { | 690 | ppdata.of_node = spi->dev.of_node; |
681 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | 691 | err = mtd_device_parse_register(device, NULL, &ppdata, |
682 | 692 | pdata ? pdata->parts : NULL, | |
683 | nr_parts = parse_mtd_partitions(device, part_probes, &parts, | 693 | pdata ? pdata->nr_parts : 0); |
684 | 0); | ||
685 | } | ||
686 | 694 | ||
687 | if (nr_parts <= 0 && pdata && pdata->parts) { | ||
688 | parts = pdata->parts; | ||
689 | nr_parts = pdata->nr_parts; | ||
690 | } | ||
691 | |||
692 | if (nr_parts > 0) { | ||
693 | priv->partitioned = 1; | ||
694 | err = mtd_device_register(device, parts, nr_parts); | ||
695 | goto out; | ||
696 | } | ||
697 | |||
698 | if (mtd_device_register(device, NULL, 0) == 1) | ||
699 | err = -ENODEV; | ||
700 | |||
701 | out: | ||
702 | if (!err) | 695 | if (!err) |
703 | return 0; | 696 | return 0; |
704 | 697 | ||
@@ -787,7 +780,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
787 | */ | 780 | */ |
788 | tmp = spi_write_then_read(spi, &code, 1, id, 3); | 781 | tmp = spi_write_then_read(spi, &code, 1, id, 3); |
789 | if (tmp < 0) { | 782 | if (tmp < 0) { |
790 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", | 783 | pr_debug("%s: error %d reading JEDEC ID\n", |
791 | dev_name(&spi->dev), tmp); | 784 | dev_name(&spi->dev), tmp); |
792 | return ERR_PTR(tmp); | 785 | return ERR_PTR(tmp); |
793 | } | 786 | } |
@@ -804,7 +797,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
804 | tmp < ARRAY_SIZE(dataflash_data); | 797 | tmp < ARRAY_SIZE(dataflash_data); |
805 | tmp++, info++) { | 798 | tmp++, info++) { |
806 | if (info->jedec_id == jedec) { | 799 | if (info->jedec_id == jedec) { |
807 | DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n", | 800 | pr_debug("%s: OTP, sector protect%s\n", |
808 | dev_name(&spi->dev), | 801 | dev_name(&spi->dev), |
809 | (info->flags & SUP_POW2PS) | 802 | (info->flags & SUP_POW2PS) |
810 | ? ", binary pagesize" : "" | 803 | ? ", binary pagesize" : "" |
@@ -812,8 +805,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
812 | if (info->flags & SUP_POW2PS) { | 805 | if (info->flags & SUP_POW2PS) { |
813 | status = dataflash_status(spi); | 806 | status = dataflash_status(spi); |
814 | if (status < 0) { | 807 | if (status < 0) { |
815 | DEBUG(MTD_DEBUG_LEVEL1, | 808 | pr_debug("%s: status error %d\n", |
816 | "%s: status error %d\n", | ||
817 | dev_name(&spi->dev), status); | 809 | dev_name(&spi->dev), status); |
818 | return ERR_PTR(status); | 810 | return ERR_PTR(status); |
819 | } | 811 | } |
@@ -878,7 +870,7 @@ static int __devinit dataflash_probe(struct spi_device *spi) | |||
878 | */ | 870 | */ |
879 | status = dataflash_status(spi); | 871 | status = dataflash_status(spi); |
880 | if (status <= 0 || status == 0xff) { | 872 | if (status <= 0 || status == 0xff) { |
881 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", | 873 | pr_debug("%s: status error %d\n", |
882 | dev_name(&spi->dev), status); | 874 | dev_name(&spi->dev), status); |
883 | if (status == 0 || status == 0xff) | 875 | if (status == 0 || status == 0xff) |
884 | status = -ENODEV; | 876 | status = -ENODEV; |
@@ -914,14 +906,14 @@ static int __devinit dataflash_probe(struct spi_device *spi) | |||
914 | break; | 906 | break; |
915 | /* obsolete AT45DB1282 not (yet?) supported */ | 907 | /* obsolete AT45DB1282 not (yet?) supported */ |
916 | default: | 908 | default: |
917 | DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", | 909 | pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev), |
918 | dev_name(&spi->dev), status & 0x3c); | 910 | status & 0x3c); |
919 | status = -ENODEV; | 911 | status = -ENODEV; |
920 | } | 912 | } |
921 | 913 | ||
922 | if (status < 0) | 914 | if (status < 0) |
923 | DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", | 915 | pr_debug("%s: add_dataflash --> %d\n", dev_name(&spi->dev), |
924 | dev_name(&spi->dev), status); | 916 | status); |
925 | 917 | ||
926 | return status; | 918 | return status; |
927 | } | 919 | } |
@@ -931,7 +923,7 @@ static int __devexit dataflash_remove(struct spi_device *spi) | |||
931 | struct dataflash *flash = dev_get_drvdata(&spi->dev); | 923 | struct dataflash *flash = dev_get_drvdata(&spi->dev); |
932 | int status; | 924 | int status; |
933 | 925 | ||
934 | DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev)); | 926 | pr_debug("%s: remove\n", dev_name(&spi->dev)); |
935 | 927 | ||
936 | status = mtd_device_unregister(&flash->mtd); | 928 | status = mtd_device_unregister(&flash->mtd); |
937 | if (status == 0) { | 929 | if (status == 0) { |
@@ -946,6 +938,7 @@ static struct spi_driver dataflash_driver = { | |||
946 | .name = "mtd_dataflash", | 938 | .name = "mtd_dataflash", |
947 | .bus = &spi_bus_type, | 939 | .bus = &spi_bus_type, |
948 | .owner = THIS_MODULE, | 940 | .owner = THIS_MODULE, |
941 | .of_match_table = dataflash_dt_ids, | ||
949 | }, | 942 | }, |
950 | 943 | ||
951 | .probe = dataflash_probe, | 944 | .probe = dataflash_probe, |
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index 83e80c65d6e7..d38ef3bffe8d 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -52,8 +52,6 @@ struct sst25l_flash { | |||
52 | struct spi_device *spi; | 52 | struct spi_device *spi; |
53 | struct mutex lock; | 53 | struct mutex lock; |
54 | struct mtd_info mtd; | 54 | struct mtd_info mtd; |
55 | |||
56 | int partitioned; | ||
57 | }; | 55 | }; |
58 | 56 | ||
59 | struct flash_info { | 57 | struct flash_info { |
@@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
381 | struct sst25l_flash *flash; | 379 | struct sst25l_flash *flash; |
382 | struct flash_platform_data *data; | 380 | struct flash_platform_data *data; |
383 | int ret, i; | 381 | int ret, i; |
384 | struct mtd_partition *parts = NULL; | ||
385 | int nr_parts = 0; | ||
386 | 382 | ||
387 | flash_info = sst25l_match_device(spi); | 383 | flash_info = sst25l_match_device(spi); |
388 | if (!flash_info) | 384 | if (!flash_info) |
@@ -414,8 +410,7 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
414 | dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name, | 410 | dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name, |
415 | (long long)flash->mtd.size >> 10); | 411 | (long long)flash->mtd.size >> 10); |
416 | 412 | ||
417 | DEBUG(MTD_DEBUG_LEVEL2, | 413 | pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) " |
418 | "mtd .name = %s, .size = 0x%llx (%lldMiB) " | ||
419 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", | 414 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", |
420 | flash->mtd.name, | 415 | flash->mtd.name, |
421 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), | 416 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), |
@@ -423,37 +418,10 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
423 | flash->mtd.numeraseregions); | 418 | flash->mtd.numeraseregions); |
424 | 419 | ||
425 | 420 | ||
426 | if (mtd_has_cmdlinepart()) { | 421 | ret = mtd_device_parse_register(&flash->mtd, NULL, 0, |
427 | static const char *part_probes[] = {"cmdlinepart", NULL}; | 422 | data ? data->parts : NULL, |
428 | 423 | data ? data->nr_parts : 0); | |
429 | nr_parts = parse_mtd_partitions(&flash->mtd, | 424 | if (ret) { |
430 | part_probes, | ||
431 | &parts, 0); | ||
432 | } | ||
433 | |||
434 | if (nr_parts <= 0 && data && data->parts) { | ||
435 | parts = data->parts; | ||
436 | nr_parts = data->nr_parts; | ||
437 | } | ||
438 | |||
439 | if (nr_parts > 0) { | ||
440 | for (i = 0; i < nr_parts; i++) { | ||
441 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | ||
442 | "{.name = %s, .offset = 0x%llx, " | ||
443 | ".size = 0x%llx (%lldKiB) }\n", | ||
444 | i, parts[i].name, | ||
445 | (long long)parts[i].offset, | ||
446 | (long long)parts[i].size, | ||
447 | (long long)(parts[i].size >> 10)); | ||
448 | } | ||
449 | |||
450 | flash->partitioned = 1; | ||
451 | return mtd_device_register(&flash->mtd, parts, | ||
452 | nr_parts); | ||
453 | } | ||
454 | |||
455 | ret = mtd_device_register(&flash->mtd, NULL, 0); | ||
456 | if (ret == 1) { | ||
457 | kfree(flash); | 425 | kfree(flash); |
458 | dev_set_drvdata(&spi->dev, NULL); | 426 | dev_set_drvdata(&spi->dev, NULL); |
459 | return -ENODEV; | 427 | return -ENODEV; |
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 037b399df3f1..c7382bb686c6 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c | |||
@@ -339,7 +339,7 @@ static int erase_xfer(partition_t *part, | |||
339 | struct erase_info *erase; | 339 | struct erase_info *erase; |
340 | 340 | ||
341 | xfer = &part->XferInfo[xfernum]; | 341 | xfer = &part->XferInfo[xfernum]; |
342 | DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset); | 342 | pr_debug("ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset); |
343 | xfer->state = XFER_ERASING; | 343 | xfer->state = XFER_ERASING; |
344 | 344 | ||
345 | /* Is there a free erase slot? Always in MTD. */ | 345 | /* Is there a free erase slot? Always in MTD. */ |
@@ -415,7 +415,7 @@ static int prepare_xfer(partition_t *part, int i) | |||
415 | xfer = &part->XferInfo[i]; | 415 | xfer = &part->XferInfo[i]; |
416 | xfer->state = XFER_FAILED; | 416 | xfer->state = XFER_FAILED; |
417 | 417 | ||
418 | DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset); | 418 | pr_debug("ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset); |
419 | 419 | ||
420 | /* Write the transfer unit header */ | 420 | /* Write the transfer unit header */ |
421 | header = part->header; | 421 | header = part->header; |
@@ -476,7 +476,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit, | |||
476 | 476 | ||
477 | eun = &part->EUNInfo[srcunit]; | 477 | eun = &part->EUNInfo[srcunit]; |
478 | xfer = &part->XferInfo[xferunit]; | 478 | xfer = &part->XferInfo[xferunit]; |
479 | DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n", | 479 | pr_debug("ftl_cs: copying block 0x%x to 0x%x\n", |
480 | eun->Offset, xfer->Offset); | 480 | eun->Offset, xfer->Offset); |
481 | 481 | ||
482 | 482 | ||
@@ -598,7 +598,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit, | |||
598 | unit with the fewest erases, and usually pick the data unit with | 598 | unit with the fewest erases, and usually pick the data unit with |
599 | the most deleted blocks. But with a small probability, pick the | 599 | the most deleted blocks. But with a small probability, pick the |
600 | oldest data unit instead. This means that we generally postpone | 600 | oldest data unit instead. This means that we generally postpone |
601 | the next reclaimation as long as possible, but shuffle static | 601 | the next reclamation as long as possible, but shuffle static |
602 | stuff around a bit for wear leveling. | 602 | stuff around a bit for wear leveling. |
603 | 603 | ||
604 | ======================================================================*/ | 604 | ======================================================================*/ |
@@ -609,8 +609,8 @@ static int reclaim_block(partition_t *part) | |||
609 | uint32_t best; | 609 | uint32_t best; |
610 | int queued, ret; | 610 | int queued, ret; |
611 | 611 | ||
612 | DEBUG(0, "ftl_cs: reclaiming space...\n"); | 612 | pr_debug("ftl_cs: reclaiming space...\n"); |
613 | DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits); | 613 | pr_debug("NumTransferUnits == %x\n", part->header.NumTransferUnits); |
614 | /* Pick the least erased transfer unit */ | 614 | /* Pick the least erased transfer unit */ |
615 | best = 0xffffffff; xfer = 0xffff; | 615 | best = 0xffffffff; xfer = 0xffff; |
616 | do { | 616 | do { |
@@ -618,22 +618,22 @@ static int reclaim_block(partition_t *part) | |||
618 | for (i = 0; i < part->header.NumTransferUnits; i++) { | 618 | for (i = 0; i < part->header.NumTransferUnits; i++) { |
619 | int n=0; | 619 | int n=0; |
620 | if (part->XferInfo[i].state == XFER_UNKNOWN) { | 620 | if (part->XferInfo[i].state == XFER_UNKNOWN) { |
621 | DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i); | 621 | pr_debug("XferInfo[%d].state == XFER_UNKNOWN\n",i); |
622 | n=1; | 622 | n=1; |
623 | erase_xfer(part, i); | 623 | erase_xfer(part, i); |
624 | } | 624 | } |
625 | if (part->XferInfo[i].state == XFER_ERASING) { | 625 | if (part->XferInfo[i].state == XFER_ERASING) { |
626 | DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i); | 626 | pr_debug("XferInfo[%d].state == XFER_ERASING\n",i); |
627 | n=1; | 627 | n=1; |
628 | queued = 1; | 628 | queued = 1; |
629 | } | 629 | } |
630 | else if (part->XferInfo[i].state == XFER_ERASED) { | 630 | else if (part->XferInfo[i].state == XFER_ERASED) { |
631 | DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i); | 631 | pr_debug("XferInfo[%d].state == XFER_ERASED\n",i); |
632 | n=1; | 632 | n=1; |
633 | prepare_xfer(part, i); | 633 | prepare_xfer(part, i); |
634 | } | 634 | } |
635 | if (part->XferInfo[i].state == XFER_PREPARED) { | 635 | if (part->XferInfo[i].state == XFER_PREPARED) { |
636 | DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i); | 636 | pr_debug("XferInfo[%d].state == XFER_PREPARED\n",i); |
637 | n=1; | 637 | n=1; |
638 | if (part->XferInfo[i].EraseCount <= best) { | 638 | if (part->XferInfo[i].EraseCount <= best) { |
639 | best = part->XferInfo[i].EraseCount; | 639 | best = part->XferInfo[i].EraseCount; |
@@ -641,12 +641,12 @@ static int reclaim_block(partition_t *part) | |||
641 | } | 641 | } |
642 | } | 642 | } |
643 | if (!n) | 643 | if (!n) |
644 | DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state); | 644 | pr_debug("XferInfo[%d].state == %x\n",i, part->XferInfo[i].state); |
645 | 645 | ||
646 | } | 646 | } |
647 | if (xfer == 0xffff) { | 647 | if (xfer == 0xffff) { |
648 | if (queued) { | 648 | if (queued) { |
649 | DEBUG(1, "ftl_cs: waiting for transfer " | 649 | pr_debug("ftl_cs: waiting for transfer " |
650 | "unit to be prepared...\n"); | 650 | "unit to be prepared...\n"); |
651 | if (part->mbd.mtd->sync) | 651 | if (part->mbd.mtd->sync) |
652 | part->mbd.mtd->sync(part->mbd.mtd); | 652 | part->mbd.mtd->sync(part->mbd.mtd); |
@@ -656,7 +656,7 @@ static int reclaim_block(partition_t *part) | |||
656 | printk(KERN_NOTICE "ftl_cs: reclaim failed: no " | 656 | printk(KERN_NOTICE "ftl_cs: reclaim failed: no " |
657 | "suitable transfer units!\n"); | 657 | "suitable transfer units!\n"); |
658 | else | 658 | else |
659 | DEBUG(1, "ftl_cs: reclaim failed: no " | 659 | pr_debug("ftl_cs: reclaim failed: no " |
660 | "suitable transfer units!\n"); | 660 | "suitable transfer units!\n"); |
661 | 661 | ||
662 | return -EIO; | 662 | return -EIO; |
@@ -666,7 +666,7 @@ static int reclaim_block(partition_t *part) | |||
666 | 666 | ||
667 | eun = 0; | 667 | eun = 0; |
668 | if ((jiffies % shuffle_freq) == 0) { | 668 | if ((jiffies % shuffle_freq) == 0) { |
669 | DEBUG(1, "ftl_cs: recycling freshest block...\n"); | 669 | pr_debug("ftl_cs: recycling freshest block...\n"); |
670 | best = 0xffffffff; | 670 | best = 0xffffffff; |
671 | for (i = 0; i < part->DataUnits; i++) | 671 | for (i = 0; i < part->DataUnits; i++) |
672 | if (part->EUNInfo[i].EraseCount <= best) { | 672 | if (part->EUNInfo[i].EraseCount <= best) { |
@@ -686,7 +686,7 @@ static int reclaim_block(partition_t *part) | |||
686 | printk(KERN_NOTICE "ftl_cs: reclaim failed: " | 686 | printk(KERN_NOTICE "ftl_cs: reclaim failed: " |
687 | "no free blocks!\n"); | 687 | "no free blocks!\n"); |
688 | else | 688 | else |
689 | DEBUG(1,"ftl_cs: reclaim failed: " | 689 | pr_debug("ftl_cs: reclaim failed: " |
690 | "no free blocks!\n"); | 690 | "no free blocks!\n"); |
691 | 691 | ||
692 | return -EIO; | 692 | return -EIO; |
@@ -771,7 +771,7 @@ static uint32_t find_free(partition_t *part) | |||
771 | printk(KERN_NOTICE "ftl_cs: bad free list!\n"); | 771 | printk(KERN_NOTICE "ftl_cs: bad free list!\n"); |
772 | return 0; | 772 | return 0; |
773 | } | 773 | } |
774 | DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun); | 774 | pr_debug("ftl_cs: found free block at %d in %d\n", blk, eun); |
775 | return blk; | 775 | return blk; |
776 | 776 | ||
777 | } /* find_free */ | 777 | } /* find_free */ |
@@ -791,7 +791,7 @@ static int ftl_read(partition_t *part, caddr_t buffer, | |||
791 | int ret; | 791 | int ret; |
792 | size_t offset, retlen; | 792 | size_t offset, retlen; |
793 | 793 | ||
794 | DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n", | 794 | pr_debug("ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n", |
795 | part, sector, nblocks); | 795 | part, sector, nblocks); |
796 | if (!(part->state & FTL_FORMATTED)) { | 796 | if (!(part->state & FTL_FORMATTED)) { |
797 | printk(KERN_NOTICE "ftl_cs: bad partition\n"); | 797 | printk(KERN_NOTICE "ftl_cs: bad partition\n"); |
@@ -840,7 +840,7 @@ static int set_bam_entry(partition_t *part, uint32_t log_addr, | |||
840 | int ret; | 840 | int ret; |
841 | size_t retlen, offset; | 841 | size_t retlen, offset; |
842 | 842 | ||
843 | DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n", | 843 | pr_debug("ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n", |
844 | part, log_addr, virt_addr); | 844 | part, log_addr, virt_addr); |
845 | bsize = 1 << part->header.EraseUnitSize; | 845 | bsize = 1 << part->header.EraseUnitSize; |
846 | eun = log_addr / bsize; | 846 | eun = log_addr / bsize; |
@@ -905,7 +905,7 @@ static int ftl_write(partition_t *part, caddr_t buffer, | |||
905 | int ret; | 905 | int ret; |
906 | size_t retlen, offset; | 906 | size_t retlen, offset; |
907 | 907 | ||
908 | DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n", | 908 | pr_debug("ftl_cs: ftl_write(0x%p, %ld, %ld)\n", |
909 | part, sector, nblocks); | 909 | part, sector, nblocks); |
910 | if (!(part->state & FTL_FORMATTED)) { | 910 | if (!(part->state & FTL_FORMATTED)) { |
911 | printk(KERN_NOTICE "ftl_cs: bad partition\n"); | 911 | printk(KERN_NOTICE "ftl_cs: bad partition\n"); |
@@ -1011,7 +1011,7 @@ static int ftl_discardsect(struct mtd_blktrans_dev *dev, | |||
1011 | partition_t *part = (void *)dev; | 1011 | partition_t *part = (void *)dev; |
1012 | uint32_t bsize = 1 << part->header.EraseUnitSize; | 1012 | uint32_t bsize = 1 << part->header.EraseUnitSize; |
1013 | 1013 | ||
1014 | DEBUG(1, "FTL erase sector %ld for %d sectors\n", | 1014 | pr_debug("FTL erase sector %ld for %d sectors\n", |
1015 | sector, nr_sects); | 1015 | sector, nr_sects); |
1016 | 1016 | ||
1017 | while (nr_sects) { | 1017 | while (nr_sects) { |
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index d7592e67d048..dd034efd1875 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -63,14 +63,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
63 | return; | 63 | return; |
64 | } | 64 | } |
65 | 65 | ||
66 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name); | 66 | pr_debug("INFTL: add_mtd for %s\n", mtd->name); |
67 | 67 | ||
68 | inftl = kzalloc(sizeof(*inftl), GFP_KERNEL); | 68 | inftl = kzalloc(sizeof(*inftl), GFP_KERNEL); |
69 | 69 | ||
70 | if (!inftl) { | 70 | if (!inftl) |
71 | printk(KERN_WARNING "INFTL: Out of memory for data structures\n"); | ||
72 | return; | 71 | return; |
73 | } | ||
74 | 72 | ||
75 | inftl->mbd.mtd = mtd; | 73 | inftl->mbd.mtd = mtd; |
76 | inftl->mbd.devnum = -1; | 74 | inftl->mbd.devnum = -1; |
@@ -133,7 +131,7 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev) | |||
133 | { | 131 | { |
134 | struct INFTLrecord *inftl = (void *)dev; | 132 | struct INFTLrecord *inftl = (void *)dev; |
135 | 133 | ||
136 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum); | 134 | pr_debug("INFTL: remove_dev (i=%d)\n", dev->devnum); |
137 | 135 | ||
138 | del_mtd_blktrans_dev(dev); | 136 | del_mtd_blktrans_dev(dev); |
139 | 137 | ||
@@ -154,7 +152,7 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | |||
154 | struct mtd_oob_ops ops; | 152 | struct mtd_oob_ops ops; |
155 | int res; | 153 | int res; |
156 | 154 | ||
157 | ops.mode = MTD_OOB_PLACE; | 155 | ops.mode = MTD_OPS_PLACE_OOB; |
158 | ops.ooboffs = offs & (mtd->writesize - 1); | 156 | ops.ooboffs = offs & (mtd->writesize - 1); |
159 | ops.ooblen = len; | 157 | ops.ooblen = len; |
160 | ops.oobbuf = buf; | 158 | ops.oobbuf = buf; |
@@ -174,7 +172,7 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | |||
174 | struct mtd_oob_ops ops; | 172 | struct mtd_oob_ops ops; |
175 | int res; | 173 | int res; |
176 | 174 | ||
177 | ops.mode = MTD_OOB_PLACE; | 175 | ops.mode = MTD_OPS_PLACE_OOB; |
178 | ops.ooboffs = offs & (mtd->writesize - 1); | 176 | ops.ooboffs = offs & (mtd->writesize - 1); |
179 | ops.ooblen = len; | 177 | ops.ooblen = len; |
180 | ops.oobbuf = buf; | 178 | ops.oobbuf = buf; |
@@ -194,7 +192,7 @@ static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len, | |||
194 | struct mtd_oob_ops ops; | 192 | struct mtd_oob_ops ops; |
195 | int res; | 193 | int res; |
196 | 194 | ||
197 | ops.mode = MTD_OOB_PLACE; | 195 | ops.mode = MTD_OPS_PLACE_OOB; |
198 | ops.ooboffs = offs; | 196 | ops.ooboffs = offs; |
199 | ops.ooblen = mtd->oobsize; | 197 | ops.ooblen = mtd->oobsize; |
200 | ops.oobbuf = oob; | 198 | ops.oobbuf = oob; |
@@ -215,16 +213,16 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) | |||
215 | u16 pot = inftl->LastFreeEUN; | 213 | u16 pot = inftl->LastFreeEUN; |
216 | int silly = inftl->nb_blocks; | 214 | int silly = inftl->nb_blocks; |
217 | 215 | ||
218 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p," | 216 | pr_debug("INFTL: INFTL_findfreeblock(inftl=%p,desperate=%d)\n", |
219 | "desperate=%d)\n", inftl, desperate); | 217 | inftl, desperate); |
220 | 218 | ||
221 | /* | 219 | /* |
222 | * Normally, we force a fold to happen before we run out of free | 220 | * Normally, we force a fold to happen before we run out of free |
223 | * blocks completely. | 221 | * blocks completely. |
224 | */ | 222 | */ |
225 | if (!desperate && inftl->numfreeEUNs < 2) { | 223 | if (!desperate && inftl->numfreeEUNs < 2) { |
226 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " | 224 | pr_debug("INFTL: there are too few free EUNs (%d)\n", |
227 | "EUNs (%d)\n", inftl->numfreeEUNs); | 225 | inftl->numfreeEUNs); |
228 | return BLOCK_NIL; | 226 | return BLOCK_NIL; |
229 | } | 227 | } |
230 | 228 | ||
@@ -259,8 +257,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
259 | struct inftl_oob oob; | 257 | struct inftl_oob oob; |
260 | size_t retlen; | 258 | size_t retlen; |
261 | 259 | ||
262 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d," | 260 | pr_debug("INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,pending=%d)\n", |
263 | "pending=%d)\n", inftl, thisVUC, pendingblock); | 261 | inftl, thisVUC, pendingblock); |
264 | 262 | ||
265 | memset(BlockMap, 0xff, sizeof(BlockMap)); | 263 | memset(BlockMap, 0xff, sizeof(BlockMap)); |
266 | memset(BlockDeleted, 0, sizeof(BlockDeleted)); | 264 | memset(BlockDeleted, 0, sizeof(BlockDeleted)); |
@@ -323,8 +321,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
323 | * Chain, and the Erase Unit into which we are supposed to be copying. | 321 | * Chain, and the Erase Unit into which we are supposed to be copying. |
324 | * Go for it. | 322 | * Go for it. |
325 | */ | 323 | */ |
326 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n", | 324 | pr_debug("INFTL: folding chain %d into unit %d\n", thisVUC, targetEUN); |
327 | thisVUC, targetEUN); | ||
328 | 325 | ||
329 | for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) { | 326 | for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) { |
330 | unsigned char movebuf[SECTORSIZE]; | 327 | unsigned char movebuf[SECTORSIZE]; |
@@ -349,14 +346,13 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
349 | ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) + | 346 | ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) + |
350 | (block * SECTORSIZE), SECTORSIZE, &retlen, | 347 | (block * SECTORSIZE), SECTORSIZE, &retlen, |
351 | movebuf); | 348 | movebuf); |
352 | if (ret < 0 && ret != -EUCLEAN) { | 349 | if (ret < 0 && !mtd_is_bitflip(ret)) { |
353 | ret = mtd->read(mtd, | 350 | ret = mtd->read(mtd, |
354 | (inftl->EraseSize * BlockMap[block]) + | 351 | (inftl->EraseSize * BlockMap[block]) + |
355 | (block * SECTORSIZE), SECTORSIZE, | 352 | (block * SECTORSIZE), SECTORSIZE, |
356 | &retlen, movebuf); | 353 | &retlen, movebuf); |
357 | if (ret != -EIO) | 354 | if (ret != -EIO) |
358 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " | 355 | pr_debug("INFTL: error went away on retry?\n"); |
359 | "away on retry?\n"); | ||
360 | } | 356 | } |
361 | memset(&oob, 0xff, sizeof(struct inftl_oob)); | 357 | memset(&oob, 0xff, sizeof(struct inftl_oob)); |
362 | oob.b.Status = oob.b.Status1 = SECTOR_USED; | 358 | oob.b.Status = oob.b.Status1 = SECTOR_USED; |
@@ -372,8 +368,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
372 | * is important, by doing oldest first if we crash/reboot then it | 368 | * is important, by doing oldest first if we crash/reboot then it |
373 | * it is relatively simple to clean up the mess). | 369 | * it is relatively simple to clean up the mess). |
374 | */ | 370 | */ |
375 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n", | 371 | pr_debug("INFTL: want to erase virtual chain %d\n", thisVUC); |
376 | thisVUC); | ||
377 | 372 | ||
378 | for (;;) { | 373 | for (;;) { |
379 | /* Find oldest unit in chain. */ | 374 | /* Find oldest unit in chain. */ |
@@ -421,7 +416,7 @@ static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) | |||
421 | u16 ChainLength = 0, thislen; | 416 | u16 ChainLength = 0, thislen; |
422 | u16 chain, EUN; | 417 | u16 chain, EUN; |
423 | 418 | ||
424 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p," | 419 | pr_debug("INFTL: INFTL_makefreeblock(inftl=%p," |
425 | "pending=%d)\n", inftl, pendingblock); | 420 | "pending=%d)\n", inftl, pendingblock); |
426 | 421 | ||
427 | for (chain = 0; chain < inftl->nb_blocks; chain++) { | 422 | for (chain = 0; chain < inftl->nb_blocks; chain++) { |
@@ -484,8 +479,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) | |||
484 | size_t retlen; | 479 | size_t retlen; |
485 | int silly, silly2 = 3; | 480 | int silly, silly2 = 3; |
486 | 481 | ||
487 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p," | 482 | pr_debug("INFTL: INFTL_findwriteunit(inftl=%p,block=%d)\n", |
488 | "block=%d)\n", inftl, block); | 483 | inftl, block); |
489 | 484 | ||
490 | do { | 485 | do { |
491 | /* | 486 | /* |
@@ -501,8 +496,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) | |||
501 | blockofs, 8, &retlen, (char *)&bci); | 496 | blockofs, 8, &retlen, (char *)&bci); |
502 | 497 | ||
503 | status = bci.Status | bci.Status1; | 498 | status = bci.Status | bci.Status1; |
504 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in " | 499 | pr_debug("INFTL: status of block %d in EUN %d is %x\n", |
505 | "EUN %d is %x\n", block , writeEUN, status); | 500 | block , writeEUN, status); |
506 | 501 | ||
507 | switch(status) { | 502 | switch(status) { |
508 | case SECTOR_FREE: | 503 | case SECTOR_FREE: |
@@ -555,9 +550,9 @@ hitused: | |||
555 | * Hopefully we free something, lets try again. | 550 | * Hopefully we free something, lets try again. |
556 | * This time we are desperate... | 551 | * This time we are desperate... |
557 | */ | 552 | */ |
558 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 " | 553 | pr_debug("INFTL: using desperate==1 to find free EUN " |
559 | "to find free EUN to accommodate write to " | 554 | "to accommodate write to VUC %d\n", |
560 | "VUC %d\n", thisVUC); | 555 | thisVUC); |
561 | writeEUN = INFTL_findfreeblock(inftl, 1); | 556 | writeEUN = INFTL_findfreeblock(inftl, 1); |
562 | if (writeEUN == BLOCK_NIL) { | 557 | if (writeEUN == BLOCK_NIL) { |
563 | /* | 558 | /* |
@@ -647,7 +642,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) | |||
647 | struct inftl_bci bci; | 642 | struct inftl_bci bci; |
648 | size_t retlen; | 643 | size_t retlen; |
649 | 644 | ||
650 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p," | 645 | pr_debug("INFTL: INFTL_trydeletechain(inftl=%p," |
651 | "thisVUC=%d)\n", inftl, thisVUC); | 646 | "thisVUC=%d)\n", inftl, thisVUC); |
652 | 647 | ||
653 | memset(BlockUsed, 0, sizeof(BlockUsed)); | 648 | memset(BlockUsed, 0, sizeof(BlockUsed)); |
@@ -711,7 +706,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) | |||
711 | * For each block in the chain free it and make it available | 706 | * For each block in the chain free it and make it available |
712 | * for future use. Erase from the oldest unit first. | 707 | * for future use. Erase from the oldest unit first. |
713 | */ | 708 | */ |
714 | DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC); | 709 | pr_debug("INFTL: deleting empty VUC %d\n", thisVUC); |
715 | 710 | ||
716 | for (;;) { | 711 | for (;;) { |
717 | u16 *prevEUN = &inftl->VUtable[thisVUC]; | 712 | u16 *prevEUN = &inftl->VUtable[thisVUC]; |
@@ -719,7 +714,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) | |||
719 | 714 | ||
720 | /* If the chain is all gone already, we're done */ | 715 | /* If the chain is all gone already, we're done */ |
721 | if (thisEUN == BLOCK_NIL) { | 716 | if (thisEUN == BLOCK_NIL) { |
722 | DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN); | 717 | pr_debug("INFTL: Empty VUC %d for deletion was already absent\n", thisEUN); |
723 | return; | 718 | return; |
724 | } | 719 | } |
725 | 720 | ||
@@ -731,7 +726,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) | |||
731 | thisEUN = *prevEUN; | 726 | thisEUN = *prevEUN; |
732 | } | 727 | } |
733 | 728 | ||
734 | DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n", | 729 | pr_debug("Deleting EUN %d from VUC %d\n", |
735 | thisEUN, thisVUC); | 730 | thisEUN, thisVUC); |
736 | 731 | ||
737 | if (INFTL_formatblock(inftl, thisEUN) < 0) { | 732 | if (INFTL_formatblock(inftl, thisEUN) < 0) { |
@@ -767,7 +762,7 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block) | |||
767 | size_t retlen; | 762 | size_t retlen; |
768 | struct inftl_bci bci; | 763 | struct inftl_bci bci; |
769 | 764 | ||
770 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p," | 765 | pr_debug("INFTL: INFTL_deleteblock(inftl=%p," |
771 | "block=%d)\n", inftl, block); | 766 | "block=%d)\n", inftl, block); |
772 | 767 | ||
773 | while (thisEUN < inftl->nb_blocks) { | 768 | while (thisEUN < inftl->nb_blocks) { |
@@ -826,7 +821,7 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, | |||
826 | struct inftl_oob oob; | 821 | struct inftl_oob oob; |
827 | char *p, *pend; | 822 | char *p, *pend; |
828 | 823 | ||
829 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld," | 824 | pr_debug("INFTL: inftl_writeblock(inftl=%p,block=%ld," |
830 | "buffer=%p)\n", inftl, block, buffer); | 825 | "buffer=%p)\n", inftl, block, buffer); |
831 | 826 | ||
832 | /* Is block all zero? */ | 827 | /* Is block all zero? */ |
@@ -876,7 +871,7 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, | |||
876 | struct inftl_bci bci; | 871 | struct inftl_bci bci; |
877 | size_t retlen; | 872 | size_t retlen; |
878 | 873 | ||
879 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld," | 874 | pr_debug("INFTL: inftl_readblock(inftl=%p,block=%ld," |
880 | "buffer=%p)\n", inftl, block, buffer); | 875 | "buffer=%p)\n", inftl, block, buffer); |
881 | 876 | ||
882 | while (thisEUN < inftl->nb_blocks) { | 877 | while (thisEUN < inftl->nb_blocks) { |
@@ -922,7 +917,7 @@ foundit: | |||
922 | int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer); | 917 | int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer); |
923 | 918 | ||
924 | /* Handle corrected bit flips gracefully */ | 919 | /* Handle corrected bit flips gracefully */ |
925 | if (ret < 0 && ret != -EUCLEAN) | 920 | if (ret < 0 && !mtd_is_bitflip(ret)) |
926 | return -EIO; | 921 | return -EIO; |
927 | } | 922 | } |
928 | return 0; | 923 | return 0; |
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 104052e774b0..2ff601f816ce 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
@@ -53,7 +53,7 @@ static int find_boot_record(struct INFTLrecord *inftl) | |||
53 | struct INFTLPartition *ip; | 53 | struct INFTLPartition *ip; |
54 | size_t retlen; | 54 | size_t retlen; |
55 | 55 | ||
56 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl); | 56 | pr_debug("INFTL: find_boot_record(inftl=%p)\n", inftl); |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Assume logical EraseSize == physical erasesize for starting the | 59 | * Assume logical EraseSize == physical erasesize for starting the |
@@ -139,24 +139,20 @@ static int find_boot_record(struct INFTLrecord *inftl) | |||
139 | mh->FormatFlags = le32_to_cpu(mh->FormatFlags); | 139 | mh->FormatFlags = le32_to_cpu(mh->FormatFlags); |
140 | mh->PercentUsed = le32_to_cpu(mh->PercentUsed); | 140 | mh->PercentUsed = le32_to_cpu(mh->PercentUsed); |
141 | 141 | ||
142 | #ifdef CONFIG_MTD_DEBUG_VERBOSE | 142 | pr_debug("INFTL: Media Header ->\n" |
143 | if (CONFIG_MTD_DEBUG_VERBOSE >= 2) { | 143 | " bootRecordID = %s\n" |
144 | printk("INFTL: Media Header ->\n" | 144 | " NoOfBootImageBlocks = %d\n" |
145 | " bootRecordID = %s\n" | 145 | " NoOfBinaryPartitions = %d\n" |
146 | " NoOfBootImageBlocks = %d\n" | 146 | " NoOfBDTLPartitions = %d\n" |
147 | " NoOfBinaryPartitions = %d\n" | 147 | " BlockMultiplerBits = %d\n" |
148 | " NoOfBDTLPartitions = %d\n" | 148 | " FormatFlgs = %d\n" |
149 | " BlockMultiplerBits = %d\n" | 149 | " OsakVersion = 0x%x\n" |
150 | " FormatFlgs = %d\n" | 150 | " PercentUsed = %d\n", |
151 | " OsakVersion = 0x%x\n" | 151 | mh->bootRecordID, mh->NoOfBootImageBlocks, |
152 | " PercentUsed = %d\n", | 152 | mh->NoOfBinaryPartitions, |
153 | mh->bootRecordID, mh->NoOfBootImageBlocks, | 153 | mh->NoOfBDTLPartitions, |
154 | mh->NoOfBinaryPartitions, | 154 | mh->BlockMultiplierBits, mh->FormatFlags, |
155 | mh->NoOfBDTLPartitions, | 155 | mh->OsakVersion, mh->PercentUsed); |
156 | mh->BlockMultiplierBits, mh->FormatFlags, | ||
157 | mh->OsakVersion, mh->PercentUsed); | ||
158 | } | ||
159 | #endif | ||
160 | 156 | ||
161 | if (mh->NoOfBDTLPartitions == 0) { | 157 | if (mh->NoOfBDTLPartitions == 0) { |
162 | printk(KERN_WARNING "INFTL: Media Header sanity check " | 158 | printk(KERN_WARNING "INFTL: Media Header sanity check " |
@@ -200,19 +196,15 @@ static int find_boot_record(struct INFTLrecord *inftl) | |||
200 | ip->spareUnits = le32_to_cpu(ip->spareUnits); | 196 | ip->spareUnits = le32_to_cpu(ip->spareUnits); |
201 | ip->Reserved0 = le32_to_cpu(ip->Reserved0); | 197 | ip->Reserved0 = le32_to_cpu(ip->Reserved0); |
202 | 198 | ||
203 | #ifdef CONFIG_MTD_DEBUG_VERBOSE | 199 | pr_debug(" PARTITION[%d] ->\n" |
204 | if (CONFIG_MTD_DEBUG_VERBOSE >= 2) { | 200 | " virtualUnits = %d\n" |
205 | printk(" PARTITION[%d] ->\n" | 201 | " firstUnit = %d\n" |
206 | " virtualUnits = %d\n" | 202 | " lastUnit = %d\n" |
207 | " firstUnit = %d\n" | 203 | " flags = 0x%x\n" |
208 | " lastUnit = %d\n" | 204 | " spareUnits = %d\n", |
209 | " flags = 0x%x\n" | 205 | i, ip->virtualUnits, ip->firstUnit, |
210 | " spareUnits = %d\n", | 206 | ip->lastUnit, ip->flags, |
211 | i, ip->virtualUnits, ip->firstUnit, | 207 | ip->spareUnits); |
212 | ip->lastUnit, ip->flags, | ||
213 | ip->spareUnits); | ||
214 | } | ||
215 | #endif | ||
216 | 208 | ||
217 | if (ip->Reserved0 != ip->firstUnit) { | 209 | if (ip->Reserved0 != ip->firstUnit) { |
218 | struct erase_info *instr = &inftl->instr; | 210 | struct erase_info *instr = &inftl->instr; |
@@ -375,7 +367,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, | |||
375 | * | 367 | * |
376 | * Return: 0 when succeed, -1 on error. | 368 | * Return: 0 when succeed, -1 on error. |
377 | * | 369 | * |
378 | * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? | 370 | * ToDo: 1. Is it necessary to check_free_sector after erasing ?? |
379 | */ | 371 | */ |
380 | int INFTL_formatblock(struct INFTLrecord *inftl, int block) | 372 | int INFTL_formatblock(struct INFTLrecord *inftl, int block) |
381 | { | 373 | { |
@@ -385,8 +377,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block) | |||
385 | struct mtd_info *mtd = inftl->mbd.mtd; | 377 | struct mtd_info *mtd = inftl->mbd.mtd; |
386 | int physblock; | 378 | int physblock; |
387 | 379 | ||
388 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p," | 380 | pr_debug("INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block); |
389 | "block=%d)\n", inftl, block); | ||
390 | 381 | ||
391 | memset(instr, 0, sizeof(struct erase_info)); | 382 | memset(instr, 0, sizeof(struct erase_info)); |
392 | 383 | ||
@@ -476,30 +467,30 @@ void INFTL_dumptables(struct INFTLrecord *s) | |||
476 | { | 467 | { |
477 | int i; | 468 | int i; |
478 | 469 | ||
479 | printk("-------------------------------------------" | 470 | pr_debug("-------------------------------------------" |
480 | "----------------------------------\n"); | 471 | "----------------------------------\n"); |
481 | 472 | ||
482 | printk("VUtable[%d] ->", s->nb_blocks); | 473 | pr_debug("VUtable[%d] ->", s->nb_blocks); |
483 | for (i = 0; i < s->nb_blocks; i++) { | 474 | for (i = 0; i < s->nb_blocks; i++) { |
484 | if ((i % 8) == 0) | 475 | if ((i % 8) == 0) |
485 | printk("\n%04x: ", i); | 476 | pr_debug("\n%04x: ", i); |
486 | printk("%04x ", s->VUtable[i]); | 477 | pr_debug("%04x ", s->VUtable[i]); |
487 | } | 478 | } |
488 | 479 | ||
489 | printk("\n-------------------------------------------" | 480 | pr_debug("\n-------------------------------------------" |
490 | "----------------------------------\n"); | 481 | "----------------------------------\n"); |
491 | 482 | ||
492 | printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks); | 483 | pr_debug("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks); |
493 | for (i = 0; i <= s->lastEUN; i++) { | 484 | for (i = 0; i <= s->lastEUN; i++) { |
494 | if ((i % 8) == 0) | 485 | if ((i % 8) == 0) |
495 | printk("\n%04x: ", i); | 486 | pr_debug("\n%04x: ", i); |
496 | printk("%04x ", s->PUtable[i]); | 487 | pr_debug("%04x ", s->PUtable[i]); |
497 | } | 488 | } |
498 | 489 | ||
499 | printk("\n-------------------------------------------" | 490 | pr_debug("\n-------------------------------------------" |
500 | "----------------------------------\n"); | 491 | "----------------------------------\n"); |
501 | 492 | ||
502 | printk("INFTL ->\n" | 493 | pr_debug("INFTL ->\n" |
503 | " EraseSize = %d\n" | 494 | " EraseSize = %d\n" |
504 | " h/s/c = %d/%d/%d\n" | 495 | " h/s/c = %d/%d/%d\n" |
505 | " numvunits = %d\n" | 496 | " numvunits = %d\n" |
@@ -513,7 +504,7 @@ void INFTL_dumptables(struct INFTLrecord *s) | |||
513 | s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs, | 504 | s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs, |
514 | s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks); | 505 | s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks); |
515 | 506 | ||
516 | printk("\n-------------------------------------------" | 507 | pr_debug("\n-------------------------------------------" |
517 | "----------------------------------\n"); | 508 | "----------------------------------\n"); |
518 | } | 509 | } |
519 | 510 | ||
@@ -521,25 +512,25 @@ void INFTL_dumpVUchains(struct INFTLrecord *s) | |||
521 | { | 512 | { |
522 | int logical, block, i; | 513 | int logical, block, i; |
523 | 514 | ||
524 | printk("-------------------------------------------" | 515 | pr_debug("-------------------------------------------" |
525 | "----------------------------------\n"); | 516 | "----------------------------------\n"); |
526 | 517 | ||
527 | printk("INFTL Virtual Unit Chains:\n"); | 518 | pr_debug("INFTL Virtual Unit Chains:\n"); |
528 | for (logical = 0; logical < s->nb_blocks; logical++) { | 519 | for (logical = 0; logical < s->nb_blocks; logical++) { |
529 | block = s->VUtable[logical]; | 520 | block = s->VUtable[logical]; |
530 | if (block > s->nb_blocks) | 521 | if (block > s->nb_blocks) |
531 | continue; | 522 | continue; |
532 | printk(" LOGICAL %d --> %d ", logical, block); | 523 | pr_debug(" LOGICAL %d --> %d ", logical, block); |
533 | for (i = 0; i < s->nb_blocks; i++) { | 524 | for (i = 0; i < s->nb_blocks; i++) { |
534 | if (s->PUtable[block] == BLOCK_NIL) | 525 | if (s->PUtable[block] == BLOCK_NIL) |
535 | break; | 526 | break; |
536 | block = s->PUtable[block]; | 527 | block = s->PUtable[block]; |
537 | printk("%d ", block); | 528 | pr_debug("%d ", block); |
538 | } | 529 | } |
539 | printk("\n"); | 530 | pr_debug("\n"); |
540 | } | 531 | } |
541 | 532 | ||
542 | printk("-------------------------------------------" | 533 | pr_debug("-------------------------------------------" |
543 | "----------------------------------\n"); | 534 | "----------------------------------\n"); |
544 | } | 535 | } |
545 | 536 | ||
@@ -555,7 +546,7 @@ int INFTL_mount(struct INFTLrecord *s) | |||
555 | int i; | 546 | int i; |
556 | u8 *ANACtable, ANAC; | 547 | u8 *ANACtable, ANAC; |
557 | 548 | ||
558 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s); | 549 | pr_debug("INFTL: INFTL_mount(inftl=%p)\n", s); |
559 | 550 | ||
560 | /* Search for INFTL MediaHeader and Spare INFTL Media Header */ | 551 | /* Search for INFTL MediaHeader and Spare INFTL Media Header */ |
561 | if (find_boot_record(s) < 0) { | 552 | if (find_boot_record(s) < 0) { |
@@ -585,7 +576,7 @@ int INFTL_mount(struct INFTLrecord *s) | |||
585 | * NOTEXPLORED state. Then at the end we will try to format it and | 576 | * NOTEXPLORED state. Then at the end we will try to format it and |
586 | * mark it as free. | 577 | * mark it as free. |
587 | */ | 578 | */ |
588 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n"); | 579 | pr_debug("INFTL: pass 1, explore each unit\n"); |
589 | for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) { | 580 | for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) { |
590 | if (s->PUtable[first_block] != BLOCK_NOTEXPLORED) | 581 | if (s->PUtable[first_block] != BLOCK_NOTEXPLORED) |
591 | continue; | 582 | continue; |
@@ -717,17 +708,14 @@ int INFTL_mount(struct INFTLrecord *s) | |||
717 | logical_block = BLOCK_NIL; | 708 | logical_block = BLOCK_NIL; |
718 | } | 709 | } |
719 | 710 | ||
720 | #ifdef CONFIG_MTD_DEBUG_VERBOSE | 711 | INFTL_dumptables(s); |
721 | if (CONFIG_MTD_DEBUG_VERBOSE >= 2) | ||
722 | INFTL_dumptables(s); | ||
723 | #endif | ||
724 | 712 | ||
725 | /* | 713 | /* |
726 | * Second pass, check for infinite loops in chains. These are | 714 | * Second pass, check for infinite loops in chains. These are |
727 | * possible because we don't update the previous pointers when | 715 | * possible because we don't update the previous pointers when |
728 | * we fold chains. No big deal, just fix them up in PUtable. | 716 | * we fold chains. No big deal, just fix them up in PUtable. |
729 | */ | 717 | */ |
730 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n"); | 718 | pr_debug("INFTL: pass 2, validate virtual chains\n"); |
731 | for (logical_block = 0; logical_block < s->numvunits; logical_block++) { | 719 | for (logical_block = 0; logical_block < s->numvunits; logical_block++) { |
732 | block = s->VUtable[logical_block]; | 720 | block = s->VUtable[logical_block]; |
733 | last_block = BLOCK_NIL; | 721 | last_block = BLOCK_NIL; |
@@ -772,12 +760,8 @@ int INFTL_mount(struct INFTLrecord *s) | |||
772 | } | 760 | } |
773 | } | 761 | } |
774 | 762 | ||
775 | #ifdef CONFIG_MTD_DEBUG_VERBOSE | 763 | INFTL_dumptables(s); |
776 | if (CONFIG_MTD_DEBUG_VERBOSE >= 2) | 764 | INFTL_dumpVUchains(s); |
777 | INFTL_dumptables(s); | ||
778 | if (CONFIG_MTD_DEBUG_VERBOSE >= 2) | ||
779 | INFTL_dumpVUchains(s); | ||
780 | #endif | ||
781 | 765 | ||
782 | /* | 766 | /* |
783 | * Third pass, format unreferenced blocks and init free block count. | 767 | * Third pass, format unreferenced blocks and init free block count. |
@@ -785,7 +769,7 @@ int INFTL_mount(struct INFTLrecord *s) | |||
785 | s->numfreeEUNs = 0; | 769 | s->numfreeEUNs = 0; |
786 | s->LastFreeEUN = BLOCK_NIL; | 770 | s->LastFreeEUN = BLOCK_NIL; |
787 | 771 | ||
788 | DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n"); | 772 | pr_debug("INFTL: pass 3, format unused blocks\n"); |
789 | for (block = s->firstEUN; block <= s->lastEUN; block++) { | 773 | for (block = s->firstEUN; block <= s->lastEUN; block++) { |
790 | if (s->PUtable[block] == BLOCK_NOTEXPLORED) { | 774 | if (s->PUtable[block] == BLOCK_NOTEXPLORED) { |
791 | printk("INFTL: unreferenced block %d, formatting it\n", | 775 | printk("INFTL: unreferenced block %d, formatting it\n", |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index c0c328c5b133..8e0c4bf9f7fb 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -41,8 +41,6 @@ config MTD_PHYSMAP_START | |||
41 | are mapped on your particular target board. Refer to the | 41 | are mapped on your particular target board. Refer to the |
42 | memory map which should hopefully be in the documentation for | 42 | memory map which should hopefully be in the documentation for |
43 | your board. | 43 | your board. |
44 | Ignore this option if you use run-time physmap configuration | ||
45 | (i.e., run-time calling physmap_configure()). | ||
46 | 44 | ||
47 | config MTD_PHYSMAP_LEN | 45 | config MTD_PHYSMAP_LEN |
48 | hex "Physical length of flash mapping" | 46 | hex "Physical length of flash mapping" |
@@ -55,8 +53,6 @@ config MTD_PHYSMAP_LEN | |||
55 | than the total amount of flash present. Refer to the memory | 53 | than the total amount of flash present. Refer to the memory |
56 | map which should hopefully be in the documentation for your | 54 | map which should hopefully be in the documentation for your |
57 | board. | 55 | board. |
58 | Ignore this option if you use run-time physmap configuration | ||
59 | (i.e., run-time calling physmap_configure()). | ||
60 | 56 | ||
61 | config MTD_PHYSMAP_BANKWIDTH | 57 | config MTD_PHYSMAP_BANKWIDTH |
62 | int "Bank width in octets" | 58 | int "Bank width in octets" |
@@ -67,8 +63,6 @@ config MTD_PHYSMAP_BANKWIDTH | |||
67 | in octets. For example, if you have a data bus width of 32 | 63 | in octets. For example, if you have a data bus width of 32 |
68 | bits, you would set the bus width octet value to 4. This is | 64 | bits, you would set the bus width octet value to 4. This is |
69 | used internally by the CFI drivers. | 65 | used internally by the CFI drivers. |
70 | Ignore this option if you use run-time physmap configuration | ||
71 | (i.e., run-time calling physmap_configure()). | ||
72 | 66 | ||
73 | config MTD_PHYSMAP_OF | 67 | config MTD_PHYSMAP_OF |
74 | tristate "Flash device in physical memory map based on OF description" | 68 | tristate "Flash device in physical memory map based on OF description" |
@@ -260,7 +254,6 @@ config MTD_BCM963XX | |||
260 | config MTD_LANTIQ | 254 | config MTD_LANTIQ |
261 | tristate "Lantiq SoC NOR support" | 255 | tristate "Lantiq SoC NOR support" |
262 | depends on LANTIQ | 256 | depends on LANTIQ |
263 | select MTD_PARTITIONS | ||
264 | help | 257 | help |
265 | Support for NOR flash attached to the Lantiq SoC's External Bus Unit. | 258 | Support for NOR flash attached to the Lantiq SoC's External Bus Unit. |
266 | 259 | ||
@@ -339,10 +332,6 @@ config MTD_SOLUTIONENGINE | |||
339 | This enables access to the flash chips on the Hitachi SolutionEngine and | 332 | This enables access to the flash chips on the Hitachi SolutionEngine and |
340 | similar boards. Say 'Y' if you are building a kernel for such a board. | 333 | similar boards. Say 'Y' if you are building a kernel for such a board. |
341 | 334 | ||
342 | config MTD_ARM_INTEGRATOR | ||
343 | tristate "CFI Flash device mapped on ARM Integrator/P720T" | ||
344 | depends on ARM && MTD_CFI | ||
345 | |||
346 | config MTD_CDB89712 | 335 | config MTD_CDB89712 |
347 | tristate "Cirrus CDB89712 evaluation board mappings" | 336 | tristate "Cirrus CDB89712 evaluation board mappings" |
348 | depends on MTD_CFI && ARCH_CDB89712 | 337 | depends on MTD_CFI && ARCH_CDB89712 |
@@ -398,13 +387,6 @@ config MTD_AUTCPU12 | |||
398 | This enables access to the NV-RAM on autronix autcpu12 board. | 387 | This enables access to the NV-RAM on autronix autcpu12 board. |
399 | If you have such a board, say 'Y'. | 388 | If you have such a board, say 'Y'. |
400 | 389 | ||
401 | config MTD_EDB7312 | ||
402 | tristate "CFI Flash device mapped on EDB7312" | ||
403 | depends on ARCH_EDB7312 && MTD_CFI | ||
404 | help | ||
405 | This enables access to the CFI Flash on the Cogent EDB7312 board. | ||
406 | If you have such a board, say 'Y' here. | ||
407 | |||
408 | config MTD_IMPA7 | 390 | config MTD_IMPA7 |
409 | tristate "JEDEC Flash device mapped on impA7" | 391 | tristate "JEDEC Flash device mapped on impA7" |
410 | depends on ARM && MTD_JEDECPROBE | 392 | depends on ARM && MTD_JEDECPROBE |
@@ -412,14 +394,6 @@ config MTD_IMPA7 | |||
412 | This enables access to the NOR Flash on the impA7 board of | 394 | This enables access to the NOR Flash on the impA7 board of |
413 | implementa GmbH. If you have such a board, say 'Y' here. | 395 | implementa GmbH. If you have such a board, say 'Y' here. |
414 | 396 | ||
415 | config MTD_CEIVA | ||
416 | tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame" | ||
417 | depends on MTD_JEDECPROBE && ARCH_CEIVA | ||
418 | help | ||
419 | This enables access to the flash chips on the Ceiva/Polaroid | ||
420 | PhotoMax Digital Picture Frame. | ||
421 | If you have such a device, say 'Y'. | ||
422 | |||
423 | config MTD_H720X | 397 | config MTD_H720X |
424 | tristate "Hynix evaluation board mappings" | 398 | tristate "Hynix evaluation board mappings" |
425 | depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 ) | 399 | depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 ) |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index cb48b11affff..45dcb8b14f22 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -19,7 +19,6 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o | |||
19 | obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o | 19 | obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o |
20 | obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o | 20 | obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o |
21 | obj-$(CONFIG_MTD_MBX860) += mbx860.o | 21 | obj-$(CONFIG_MTD_MBX860) += mbx860.o |
22 | obj-$(CONFIG_MTD_CEIVA) += ceiva.o | ||
23 | obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o | 22 | obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o |
24 | obj-$(CONFIG_MTD_PHYSMAP) += physmap.o | 23 | obj-$(CONFIG_MTD_PHYSMAP) += physmap.o |
25 | obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o | 24 | obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o |
@@ -40,7 +39,6 @@ obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o | |||
40 | obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o | 39 | obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o |
41 | obj-$(CONFIG_MTD_PCI) += pci.o | 40 | obj-$(CONFIG_MTD_PCI) += pci.o |
42 | obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o | 41 | obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o |
43 | obj-$(CONFIG_MTD_EDB7312) += edb7312.o | ||
44 | obj-$(CONFIG_MTD_IMPA7) += impa7.o | 42 | obj-$(CONFIG_MTD_IMPA7) += impa7.o |
45 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o | 43 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o |
46 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o | 44 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o |
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 67815eed2f00..6d6b2b5674ee 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
@@ -41,7 +41,6 @@ struct async_state { | |||
41 | uint32_t flash_ambctl0, flash_ambctl1; | 41 | uint32_t flash_ambctl0, flash_ambctl1; |
42 | uint32_t save_ambctl0, save_ambctl1; | 42 | uint32_t save_ambctl0, save_ambctl1; |
43 | unsigned long irq_flags; | 43 | unsigned long irq_flags; |
44 | struct mtd_partition *parts; | ||
45 | }; | 44 | }; |
46 | 45 | ||
47 | static void switch_to_flash(struct async_state *state) | 46 | static void switch_to_flash(struct async_state *state) |
@@ -165,18 +164,8 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) | |||
165 | return -ENXIO; | 164 | return -ENXIO; |
166 | } | 165 | } |
167 | 166 | ||
168 | ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); | 167 | mtd_device_parse_register(state->mtd, part_probe_types, 0, |
169 | if (ret > 0) { | 168 | pdata->parts, pdata->nr_parts); |
170 | pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n"); | ||
171 | mtd_device_register(state->mtd, pdata->parts, ret); | ||
172 | state->parts = pdata->parts; | ||
173 | } else if (pdata->nr_parts) { | ||
174 | pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n"); | ||
175 | mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts); | ||
176 | } else { | ||
177 | pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n"); | ||
178 | mtd_device_register(state->mtd, NULL, 0); | ||
179 | } | ||
180 | 169 | ||
181 | platform_set_drvdata(pdev, state); | 170 | platform_set_drvdata(pdev, state); |
182 | 171 | ||
@@ -188,7 +177,6 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev) | |||
188 | struct async_state *state = platform_get_drvdata(pdev); | 177 | struct async_state *state = platform_get_drvdata(pdev); |
189 | gpio_free(state->enet_flash_pin); | 178 | gpio_free(state->enet_flash_pin); |
190 | mtd_device_unregister(state->mtd); | 179 | mtd_device_unregister(state->mtd); |
191 | kfree(state->parts); | ||
192 | map_destroy(state->mtd); | 180 | map_destroy(state->mtd); |
193 | kfree(state); | 181 | kfree(state); |
194 | return 0; | 182 | return 0; |
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c deleted file mode 100644 index 06f9c9815720..000000000000 --- a/drivers/mtd/maps/ceiva.c +++ /dev/null | |||
@@ -1,341 +0,0 @@ | |||
1 | /* | ||
2 | * Ceiva flash memory driver. | ||
3 | * Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net> | ||
4 | * | ||
5 | * Note: this driver supports jedec compatible devices. Modification | ||
6 | * for CFI compatible devices should be straight forward: change | ||
7 | * jedec_probe to cfi_probe. | ||
8 | * | ||
9 | * Based on: sa1100-flash.c, which has the following copyright: | ||
10 | * Flash memory access on SA11x0 based devices | ||
11 | * | ||
12 | * (C) 2000 Nicolas Pitre <nico@fluxnic.net> | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <linux/mtd/mtd.h> | ||
24 | #include <linux/mtd/map.h> | ||
25 | #include <linux/mtd/partitions.h> | ||
26 | #include <linux/mtd/concat.h> | ||
27 | |||
28 | #include <mach/hardware.h> | ||
29 | #include <asm/mach-types.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/sizes.h> | ||
32 | |||
33 | /* | ||
34 | * This isn't complete yet, so... | ||
35 | */ | ||
36 | #define CONFIG_MTD_CEIVA_STATICMAP | ||
37 | |||
38 | #ifdef CONFIG_MTD_CEIVA_STATICMAP | ||
39 | /* | ||
40 | * See include/linux/mtd/partitions.h for definition of the mtd_partition | ||
41 | * structure. | ||
42 | * | ||
43 | * Please note: | ||
44 | * 1. The flash size given should be the largest flash size that can | ||
45 | * be accommodated. | ||
46 | * | ||
47 | * 2. The bus width must defined in clps_setup_flash. | ||
48 | * | ||
49 | * The MTD layer will detect flash chip aliasing and reduce the size of | ||
50 | * the map accordingly. | ||
51 | * | ||
52 | */ | ||
53 | |||
54 | #ifdef CONFIG_ARCH_CEIVA | ||
55 | /* Flash / Partition sizing */ | ||
56 | /* For the 28F8003, we use the block mapping to calcuate the sizes */ | ||
57 | #define MAX_SIZE_KiB (16 + 8 + 8 + 96 + (7*128)) | ||
58 | #define BOOT_PARTITION_SIZE_KiB (16) | ||
59 | #define PARAMS_PARTITION_SIZE_KiB (8) | ||
60 | #define KERNEL_PARTITION_SIZE_KiB (4*128) | ||
61 | /* Use both remaining portion of first flash, and all of second flash */ | ||
62 | #define ROOT_PARTITION_SIZE_KiB (3*128) + (8*128) | ||
63 | |||
64 | static struct mtd_partition ceiva_partitions[] = { | ||
65 | { | ||
66 | .name = "Ceiva BOOT partition", | ||
67 | .size = BOOT_PARTITION_SIZE_KiB*1024, | ||
68 | .offset = 0, | ||
69 | |||
70 | },{ | ||
71 | .name = "Ceiva parameters partition", | ||
72 | .size = PARAMS_PARTITION_SIZE_KiB*1024, | ||
73 | .offset = (16 + 8) * 1024, | ||
74 | },{ | ||
75 | .name = "Ceiva kernel partition", | ||
76 | .size = (KERNEL_PARTITION_SIZE_KiB)*1024, | ||
77 | .offset = 0x20000, | ||
78 | |||
79 | },{ | ||
80 | .name = "Ceiva root filesystem partition", | ||
81 | .offset = MTDPART_OFS_APPEND, | ||
82 | .size = (ROOT_PARTITION_SIZE_KiB)*1024, | ||
83 | } | ||
84 | }; | ||
85 | #endif | ||
86 | |||
87 | static int __init clps_static_partitions(struct mtd_partition **parts) | ||
88 | { | ||
89 | int nb_parts = 0; | ||
90 | |||
91 | #ifdef CONFIG_ARCH_CEIVA | ||
92 | if (machine_is_ceiva()) { | ||
93 | *parts = ceiva_partitions; | ||
94 | nb_parts = ARRAY_SIZE(ceiva_partitions); | ||
95 | } | ||
96 | #endif | ||
97 | return nb_parts; | ||
98 | } | ||
99 | #endif | ||
100 | |||
101 | struct clps_info { | ||
102 | unsigned long base; | ||
103 | unsigned long size; | ||
104 | int width; | ||
105 | void *vbase; | ||
106 | struct map_info *map; | ||
107 | struct mtd_info *mtd; | ||
108 | struct resource *res; | ||
109 | }; | ||
110 | |||
111 | #define NR_SUBMTD 4 | ||
112 | |||
113 | static struct clps_info info[NR_SUBMTD]; | ||
114 | |||
115 | static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd) | ||
116 | { | ||
117 | struct mtd_info *subdev[nr]; | ||
118 | struct map_info *maps; | ||
119 | int i, found = 0, ret = 0; | ||
120 | |||
121 | /* | ||
122 | * Allocate the map_info structs in one go. | ||
123 | */ | ||
124 | maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL); | ||
125 | if (!maps) | ||
126 | return -ENOMEM; | ||
127 | /* | ||
128 | * Claim and then map the memory regions. | ||
129 | */ | ||
130 | for (i = 0; i < nr; i++) { | ||
131 | if (clps[i].base == (unsigned long)-1) | ||
132 | break; | ||
133 | |||
134 | clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash"); | ||
135 | if (!clps[i].res) { | ||
136 | ret = -EBUSY; | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | clps[i].map = maps + i; | ||
141 | |||
142 | clps[i].map->name = "clps flash"; | ||
143 | clps[i].map->phys = clps[i].base; | ||
144 | |||
145 | clps[i].vbase = ioremap(clps[i].base, clps[i].size); | ||
146 | if (!clps[i].vbase) { | ||
147 | ret = -ENOMEM; | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | clps[i].map->virt = (void __iomem *)clps[i].vbase; | ||
152 | clps[i].map->bankwidth = clps[i].width; | ||
153 | clps[i].map->size = clps[i].size; | ||
154 | |||
155 | simple_map_init(&clps[i].map); | ||
156 | |||
157 | clps[i].mtd = do_map_probe("jedec_probe", clps[i].map); | ||
158 | if (clps[i].mtd == NULL) { | ||
159 | ret = -ENXIO; | ||
160 | break; | ||
161 | } | ||
162 | clps[i].mtd->owner = THIS_MODULE; | ||
163 | subdev[i] = clps[i].mtd; | ||
164 | |||
165 | printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, " | ||
166 | "%d-bit\n", clps[i].base, clps[i].mtd->size >> 20, | ||
167 | clps[i].width * 8); | ||
168 | found += 1; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * ENXIO is special. It means we didn't find a chip when | ||
173 | * we probed. We need to tear down the mapping, free the | ||
174 | * resource and mark it as such. | ||
175 | */ | ||
176 | if (ret == -ENXIO) { | ||
177 | iounmap(clps[i].vbase); | ||
178 | clps[i].vbase = NULL; | ||
179 | release_resource(clps[i].res); | ||
180 | clps[i].res = NULL; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * If we found one device, don't bother with concat support. | ||
185 | * If we found multiple devices, use concat if we have it | ||
186 | * available, otherwise fail. | ||
187 | */ | ||
188 | if (ret == 0 || ret == -ENXIO) { | ||
189 | if (found == 1) { | ||
190 | *rmtd = subdev[0]; | ||
191 | ret = 0; | ||
192 | } else if (found > 1) { | ||
193 | /* | ||
194 | * We detected multiple devices. Concatenate | ||
195 | * them together. | ||
196 | */ | ||
197 | *rmtd = mtd_concat_create(subdev, found, | ||
198 | "clps flash"); | ||
199 | if (*rmtd == NULL) | ||
200 | ret = -ENXIO; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * If we failed, clean up. | ||
206 | */ | ||
207 | if (ret) { | ||
208 | do { | ||
209 | if (clps[i].mtd) | ||
210 | map_destroy(clps[i].mtd); | ||
211 | if (clps[i].vbase) | ||
212 | iounmap(clps[i].vbase); | ||
213 | if (clps[i].res) | ||
214 | release_resource(clps[i].res); | ||
215 | } while (i--); | ||
216 | |||
217 | kfree(maps); | ||
218 | } | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd) | ||
224 | { | ||
225 | int i; | ||
226 | |||
227 | mtd_device_unregister(mtd); | ||
228 | |||
229 | if (mtd != clps[0].mtd) | ||
230 | mtd_concat_destroy(mtd); | ||
231 | |||
232 | for (i = NR_SUBMTD; i >= 0; i--) { | ||
233 | if (clps[i].mtd) | ||
234 | map_destroy(clps[i].mtd); | ||
235 | if (clps[i].vbase) | ||
236 | iounmap(clps[i].vbase); | ||
237 | if (clps[i].res) | ||
238 | release_resource(clps[i].res); | ||
239 | } | ||
240 | kfree(clps[0].map); | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | * We define the memory space, size, and width for the flash memory | ||
245 | * space here. | ||
246 | */ | ||
247 | |||
248 | static int __init clps_setup_flash(void) | ||
249 | { | ||
250 | int nr = 0; | ||
251 | |||
252 | #ifdef CONFIG_ARCH_CEIVA | ||
253 | if (machine_is_ceiva()) { | ||
254 | info[0].base = CS0_PHYS_BASE; | ||
255 | info[0].size = SZ_32M; | ||
256 | info[0].width = CEIVA_FLASH_WIDTH; | ||
257 | info[1].base = CS1_PHYS_BASE; | ||
258 | info[1].size = SZ_32M; | ||
259 | info[1].width = CEIVA_FLASH_WIDTH; | ||
260 | nr = 2; | ||
261 | } | ||
262 | #endif | ||
263 | return nr; | ||
264 | } | ||
265 | |||
266 | static struct mtd_partition *parsed_parts; | ||
267 | static const char *probes[] = { "cmdlinepart", "RedBoot", NULL }; | ||
268 | |||
269 | static void __init clps_locate_partitions(struct mtd_info *mtd) | ||
270 | { | ||
271 | const char *part_type = NULL; | ||
272 | int nr_parts = 0; | ||
273 | do { | ||
274 | /* | ||
275 | * Partition selection stuff. | ||
276 | */ | ||
277 | nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0); | ||
278 | if (nr_parts > 0) { | ||
279 | part_type = "command line"; | ||
280 | break; | ||
281 | } | ||
282 | #ifdef CONFIG_MTD_CEIVA_STATICMAP | ||
283 | nr_parts = clps_static_partitions(&parsed_parts); | ||
284 | if (nr_parts > 0) { | ||
285 | part_type = "static"; | ||
286 | break; | ||
287 | } | ||
288 | printk("found: %d partitions\n", nr_parts); | ||
289 | #endif | ||
290 | } while (0); | ||
291 | |||
292 | if (nr_parts == 0) { | ||
293 | printk(KERN_NOTICE "clps flash: no partition info " | ||
294 | "available, registering whole flash\n"); | ||
295 | mtd_device_register(mtd, NULL, 0); | ||
296 | } else { | ||
297 | printk(KERN_NOTICE "clps flash: using %s partition " | ||
298 | "definition\n", part_type); | ||
299 | mtd_device_register(mtd, parsed_parts, nr_parts); | ||
300 | } | ||
301 | |||
302 | /* Always succeeds. */ | ||
303 | } | ||
304 | |||
305 | static void __exit clps_destroy_partitions(void) | ||
306 | { | ||
307 | kfree(parsed_parts); | ||
308 | } | ||
309 | |||
310 | static struct mtd_info *mymtd; | ||
311 | |||
312 | static int __init clps_mtd_init(void) | ||
313 | { | ||
314 | int ret; | ||
315 | int nr; | ||
316 | |||
317 | nr = clps_setup_flash(); | ||
318 | if (nr < 0) | ||
319 | return nr; | ||
320 | |||
321 | ret = clps_setup_mtd(info, nr, &mymtd); | ||
322 | if (ret) | ||
323 | return ret; | ||
324 | |||
325 | clps_locate_partitions(mymtd); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static void __exit clps_mtd_cleanup(void) | ||
331 | { | ||
332 | clps_destroy_mtd(info, mymtd); | ||
333 | clps_destroy_partitions(); | ||
334 | } | ||
335 | |||
336 | module_init(clps_mtd_init); | ||
337 | module_exit(clps_mtd_cleanup); | ||
338 | |||
339 | MODULE_AUTHOR("Rob Scott"); | ||
340 | MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver"); | ||
341 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index 7a9e1989c977..f43b365b848c 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c | |||
@@ -145,14 +145,10 @@ static struct map_info dc21285_map = { | |||
145 | 145 | ||
146 | 146 | ||
147 | /* Partition stuff */ | 147 | /* Partition stuff */ |
148 | static struct mtd_partition *dc21285_parts; | ||
149 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; | 148 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; |
150 | 149 | ||
151 | static int __init init_dc21285(void) | 150 | static int __init init_dc21285(void) |
152 | { | 151 | { |
153 | |||
154 | int nrparts; | ||
155 | |||
156 | /* Determine bankwidth */ | 152 | /* Determine bankwidth */ |
157 | switch (*CSR_SA110_CNTL & (3<<14)) { | 153 | switch (*CSR_SA110_CNTL & (3<<14)) { |
158 | case SA110_CNTL_ROMWIDTH_8: | 154 | case SA110_CNTL_ROMWIDTH_8: |
@@ -200,8 +196,7 @@ static int __init init_dc21285(void) | |||
200 | 196 | ||
201 | dc21285_mtd->owner = THIS_MODULE; | 197 | dc21285_mtd->owner = THIS_MODULE; |
202 | 198 | ||
203 | nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0); | 199 | mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0); |
204 | mtd_device_register(dc21285_mtd, dc21285_parts, nrparts); | ||
205 | 200 | ||
206 | if(machine_is_ebsa285()) { | 201 | if(machine_is_ebsa285()) { |
207 | /* | 202 | /* |
@@ -224,8 +219,6 @@ static int __init init_dc21285(void) | |||
224 | static void __exit cleanup_dc21285(void) | 219 | static void __exit cleanup_dc21285(void) |
225 | { | 220 | { |
226 | mtd_device_unregister(dc21285_mtd); | 221 | mtd_device_unregister(dc21285_mtd); |
227 | if (dc21285_parts) | ||
228 | kfree(dc21285_parts); | ||
229 | map_destroy(dc21285_mtd); | 222 | map_destroy(dc21285_mtd); |
230 | iounmap(dc21285_map.virt); | 223 | iounmap(dc21285_map.virt); |
231 | } | 224 | } |
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c deleted file mode 100644 index fe42a212bb3e..000000000000 --- a/drivers/mtd/maps/edb7312.c +++ /dev/null | |||
@@ -1,134 +0,0 @@ | |||
1 | /* | ||
2 | * Handle mapping of the NOR flash on Cogent EDB7312 boards | ||
3 | * | ||
4 | * Copyright 2002 SYSGO Real-Time Solutions GmbH | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <linux/mtd/mtd.h> | ||
17 | #include <linux/mtd/map.h> | ||
18 | #include <linux/mtd/partitions.h> | ||
19 | |||
20 | #define WINDOW_ADDR 0x00000000 /* physical properties of flash */ | ||
21 | #define WINDOW_SIZE 0x01000000 | ||
22 | #define BUSWIDTH 2 | ||
23 | #define FLASH_BLOCKSIZE_MAIN 0x20000 | ||
24 | #define FLASH_NUMBLOCKS_MAIN 128 | ||
25 | /* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */ | ||
26 | #define PROBETYPES { "cfi_probe", NULL } | ||
27 | |||
28 | #define MSG_PREFIX "EDB7312-NOR:" /* prefix for our printk()'s */ | ||
29 | #define MTDID "edb7312-nor" /* for mtdparts= partitioning */ | ||
30 | |||
31 | static struct mtd_info *mymtd; | ||
32 | |||
33 | struct map_info edb7312nor_map = { | ||
34 | .name = "NOR flash on EDB7312", | ||
35 | .size = WINDOW_SIZE, | ||
36 | .bankwidth = BUSWIDTH, | ||
37 | .phys = WINDOW_ADDR, | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * MTD partitioning stuff | ||
42 | */ | ||
43 | static struct mtd_partition static_partitions[3] = | ||
44 | { | ||
45 | { | ||
46 | .name = "ARMboot", | ||
47 | .size = 0x40000, | ||
48 | .offset = 0 | ||
49 | }, | ||
50 | { | ||
51 | .name = "Kernel", | ||
52 | .size = 0x200000, | ||
53 | .offset = 0x40000 | ||
54 | }, | ||
55 | { | ||
56 | .name = "RootFS", | ||
57 | .size = 0xDC0000, | ||
58 | .offset = 0x240000 | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; | ||
63 | |||
64 | static int mtd_parts_nb = 0; | ||
65 | static struct mtd_partition *mtd_parts = 0; | ||
66 | |||
67 | static int __init init_edb7312nor(void) | ||
68 | { | ||
69 | static const char *rom_probe_types[] = PROBETYPES; | ||
70 | const char **type; | ||
71 | const char *part_type = 0; | ||
72 | |||
73 | printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", | ||
74 | WINDOW_SIZE, WINDOW_ADDR); | ||
75 | edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); | ||
76 | |||
77 | if (!edb7312nor_map.virt) { | ||
78 | printk(MSG_PREFIX "failed to ioremap\n"); | ||
79 | return -EIO; | ||
80 | } | ||
81 | |||
82 | simple_map_init(&edb7312nor_map); | ||
83 | |||
84 | mymtd = 0; | ||
85 | type = rom_probe_types; | ||
86 | for(; !mymtd && *type; type++) { | ||
87 | mymtd = do_map_probe(*type, &edb7312nor_map); | ||
88 | } | ||
89 | if (mymtd) { | ||
90 | mymtd->owner = THIS_MODULE; | ||
91 | |||
92 | mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID); | ||
93 | if (mtd_parts_nb > 0) | ||
94 | part_type = "detected"; | ||
95 | |||
96 | if (mtd_parts_nb == 0) { | ||
97 | mtd_parts = static_partitions; | ||
98 | mtd_parts_nb = ARRAY_SIZE(static_partitions); | ||
99 | part_type = "static"; | ||
100 | } | ||
101 | |||
102 | if (mtd_parts_nb == 0) | ||
103 | printk(KERN_NOTICE MSG_PREFIX "no partition info available\n"); | ||
104 | else | ||
105 | printk(KERN_NOTICE MSG_PREFIX | ||
106 | "using %s partition definition\n", part_type); | ||
107 | /* Register the whole device first. */ | ||
108 | mtd_device_register(mymtd, NULL, 0); | ||
109 | mtd_device_register(mymtd, mtd_parts, mtd_parts_nb); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | iounmap((void *)edb7312nor_map.virt); | ||
114 | return -ENXIO; | ||
115 | } | ||
116 | |||
117 | static void __exit cleanup_edb7312nor(void) | ||
118 | { | ||
119 | if (mymtd) { | ||
120 | mtd_device_unregister(mymtd); | ||
121 | map_destroy(mymtd); | ||
122 | } | ||
123 | if (edb7312nor_map.virt) { | ||
124 | iounmap((void *)edb7312nor_map.virt); | ||
125 | edb7312nor_map.virt = 0; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | module_init(init_edb7312nor); | ||
130 | module_exit(cleanup_edb7312nor); | ||
131 | |||
132 | MODULE_LICENSE("GPL"); | ||
133 | MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>"); | ||
134 | MODULE_DESCRIPTION("Generic configurable MTD map driver"); | ||
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index 7568c5f8b8ae..1ec66f031c51 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -187,7 +187,6 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; | |||
187 | */ | 187 | */ |
188 | static int __devinit gpio_flash_probe(struct platform_device *pdev) | 188 | static int __devinit gpio_flash_probe(struct platform_device *pdev) |
189 | { | 189 | { |
190 | int nr_parts; | ||
191 | size_t i, arr_size; | 190 | size_t i, arr_size; |
192 | struct physmap_flash_data *pdata; | 191 | struct physmap_flash_data *pdata; |
193 | struct resource *memory; | 192 | struct resource *memory; |
@@ -252,20 +251,9 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
252 | return -ENXIO; | 251 | return -ENXIO; |
253 | } | 252 | } |
254 | 253 | ||
255 | nr_parts = parse_mtd_partitions(state->mtd, part_probe_types, | ||
256 | &pdata->parts, 0); | ||
257 | if (nr_parts > 0) { | ||
258 | pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n"); | ||
259 | kfree(pdata->parts); | ||
260 | } else if (pdata->nr_parts) { | ||
261 | pr_devinit(KERN_NOTICE PFX "Using board partition definition\n"); | ||
262 | nr_parts = pdata->nr_parts; | ||
263 | } else { | ||
264 | pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n"); | ||
265 | nr_parts = 0; | ||
266 | } | ||
267 | 254 | ||
268 | mtd_device_register(state->mtd, pdata->parts, nr_parts); | 255 | mtd_device_parse_register(state->mtd, part_probe_types, 0, |
256 | pdata->parts, pdata->nr_parts); | ||
269 | 257 | ||
270 | return 0; | 258 | return 0; |
271 | } | 259 | } |
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index 7f035860a36b..49c14187fc66 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c | |||
@@ -58,18 +58,11 @@ static struct mtd_partition h720x_partitions[] = { | |||
58 | 58 | ||
59 | #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions) | 59 | #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions) |
60 | 60 | ||
61 | static int nr_mtd_parts; | ||
62 | static struct mtd_partition *mtd_parts; | ||
63 | static const char *probes[] = { "cmdlinepart", NULL }; | ||
64 | |||
65 | /* | 61 | /* |
66 | * Initialize FLASH support | 62 | * Initialize FLASH support |
67 | */ | 63 | */ |
68 | static int __init h720x_mtd_init(void) | 64 | static int __init h720x_mtd_init(void) |
69 | { | 65 | { |
70 | |||
71 | char *part_type = NULL; | ||
72 | |||
73 | h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size); | 66 | h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size); |
74 | 67 | ||
75 | if (!h720x_map.virt) { | 68 | if (!h720x_map.virt) { |
@@ -92,16 +85,8 @@ static int __init h720x_mtd_init(void) | |||
92 | if (mymtd) { | 85 | if (mymtd) { |
93 | mymtd->owner = THIS_MODULE; | 86 | mymtd->owner = THIS_MODULE; |
94 | 87 | ||
95 | nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0); | 88 | mtd_device_parse_register(mymtd, NULL, 0, |
96 | if (nr_mtd_parts > 0) | 89 | h720x_partitions, NUM_PARTITIONS); |
97 | part_type = "command line"; | ||
98 | if (nr_mtd_parts <= 0) { | ||
99 | mtd_parts = h720x_partitions; | ||
100 | nr_mtd_parts = NUM_PARTITIONS; | ||
101 | part_type = "builtin"; | ||
102 | } | ||
103 | printk(KERN_INFO "Using %s partition table\n", part_type); | ||
104 | mtd_device_register(mymtd, mtd_parts, nr_mtd_parts); | ||
105 | return 0; | 90 | return 0; |
106 | } | 91 | } |
107 | 92 | ||
@@ -120,10 +105,6 @@ static void __exit h720x_mtd_cleanup(void) | |||
120 | map_destroy(mymtd); | 105 | map_destroy(mymtd); |
121 | } | 106 | } |
122 | 107 | ||
123 | /* Free partition info, if commandline partition was used */ | ||
124 | if (mtd_parts && (mtd_parts != h720x_partitions)) | ||
125 | kfree (mtd_parts); | ||
126 | |||
127 | if (h720x_map.virt) { | 108 | if (h720x_map.virt) { |
128 | iounmap((void *)h720x_map.virt); | 109 | iounmap((void *)h720x_map.virt); |
129 | h720x_map.virt = 0; | 110 | h720x_map.virt = 0; |
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index 404a50cbafa0..f47aedb24366 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c | |||
@@ -49,7 +49,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = { | |||
49 | /* | 49 | /* |
50 | * MTD partitioning stuff | 50 | * MTD partitioning stuff |
51 | */ | 51 | */ |
52 | static struct mtd_partition static_partitions[] = | 52 | static struct mtd_partition partitions[] = |
53 | { | 53 | { |
54 | { | 54 | { |
55 | .name = "FileSystem", | 55 | .name = "FileSystem", |
@@ -58,16 +58,10 @@ static struct mtd_partition static_partitions[] = | |||
58 | }, | 58 | }, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static int mtd_parts_nb[NUM_FLASHBANKS]; | ||
62 | static struct mtd_partition *mtd_parts[NUM_FLASHBANKS]; | ||
63 | |||
64 | static const char *probes[] = { "cmdlinepart", NULL }; | ||
65 | |||
66 | static int __init init_impa7(void) | 61 | static int __init init_impa7(void) |
67 | { | 62 | { |
68 | static const char *rom_probe_types[] = PROBETYPES; | 63 | static const char *rom_probe_types[] = PROBETYPES; |
69 | const char **type; | 64 | const char **type; |
70 | const char *part_type = 0; | ||
71 | int i; | 65 | int i; |
72 | static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = { | 66 | static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = { |
73 | { WINDOW_ADDR0, WINDOW_SIZE0 }, | 67 | { WINDOW_ADDR0, WINDOW_SIZE0 }, |
@@ -97,23 +91,9 @@ static int __init init_impa7(void) | |||
97 | if (impa7_mtd[i]) { | 91 | if (impa7_mtd[i]) { |
98 | impa7_mtd[i]->owner = THIS_MODULE; | 92 | impa7_mtd[i]->owner = THIS_MODULE; |
99 | devicesfound++; | 93 | devicesfound++; |
100 | mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], | 94 | mtd_device_parse_register(impa7_mtd[i], NULL, 0, |
101 | probes, | 95 | partitions, |
102 | &mtd_parts[i], | 96 | ARRAY_SIZE(partitions)); |
103 | 0); | ||
104 | if (mtd_parts_nb[i] > 0) { | ||
105 | part_type = "command line"; | ||
106 | } else { | ||
107 | mtd_parts[i] = static_partitions; | ||
108 | mtd_parts_nb[i] = ARRAY_SIZE(static_partitions); | ||
109 | part_type = "static"; | ||
110 | } | ||
111 | |||
112 | printk(KERN_NOTICE MSG_PREFIX | ||
113 | "using %s partition definition\n", | ||
114 | part_type); | ||
115 | mtd_device_register(impa7_mtd[i], | ||
116 | mtd_parts[i], mtd_parts_nb[i]); | ||
117 | } | 97 | } |
118 | else | 98 | else |
119 | iounmap((void *)impa7_map[i].virt); | 99 | iounmap((void *)impa7_map[i].virt); |
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index d2f47be8754b..08c239604ee4 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c | |||
@@ -44,7 +44,6 @@ struct vr_nor_mtd { | |||
44 | void __iomem *csr_base; | 44 | void __iomem *csr_base; |
45 | struct map_info map; | 45 | struct map_info map; |
46 | struct mtd_info *info; | 46 | struct mtd_info *info; |
47 | int nr_parts; | ||
48 | struct pci_dev *dev; | 47 | struct pci_dev *dev; |
49 | }; | 48 | }; |
50 | 49 | ||
@@ -71,13 +70,9 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p) | |||
71 | 70 | ||
72 | static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) | 71 | static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) |
73 | { | 72 | { |
74 | struct mtd_partition *parts; | ||
75 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
76 | |||
77 | /* register the flash bank */ | 73 | /* register the flash bank */ |
78 | /* partition the flash bank */ | 74 | /* partition the flash bank */ |
79 | p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0); | 75 | return mtd_device_parse_register(p->info, NULL, 0, NULL, 0); |
80 | return mtd_device_register(p->info, parts, p->nr_parts); | ||
81 | } | 76 | } |
82 | 77 | ||
83 | static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) | 78 | static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) |
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 1594a802631d..437fcd2f352f 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c | |||
@@ -38,7 +38,6 @@ | |||
38 | struct ixp2000_flash_info { | 38 | struct ixp2000_flash_info { |
39 | struct mtd_info *mtd; | 39 | struct mtd_info *mtd; |
40 | struct map_info map; | 40 | struct map_info map; |
41 | struct mtd_partition *partitions; | ||
42 | struct resource *res; | 41 | struct resource *res; |
43 | }; | 42 | }; |
44 | 43 | ||
@@ -125,8 +124,6 @@ static int ixp2000_flash_remove(struct platform_device *dev) | |||
125 | if (info->map.map_priv_1) | 124 | if (info->map.map_priv_1) |
126 | iounmap((void *) info->map.map_priv_1); | 125 | iounmap((void *) info->map.map_priv_1); |
127 | 126 | ||
128 | kfree(info->partitions); | ||
129 | |||
130 | if (info->res) { | 127 | if (info->res) { |
131 | release_resource(info->res); | 128 | release_resource(info->res); |
132 | kfree(info->res); | 129 | kfree(info->res); |
@@ -229,13 +226,7 @@ static int ixp2000_flash_probe(struct platform_device *dev) | |||
229 | } | 226 | } |
230 | info->mtd->owner = THIS_MODULE; | 227 | info->mtd->owner = THIS_MODULE; |
231 | 228 | ||
232 | err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); | 229 | err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0); |
233 | if (err > 0) { | ||
234 | err = mtd_device_register(info->mtd, info->partitions, err); | ||
235 | if(err) | ||
236 | dev_err(&dev->dev, "Could not parse partitions\n"); | ||
237 | } | ||
238 | |||
239 | if (err) | 230 | if (err) |
240 | goto Error; | 231 | goto Error; |
241 | 232 | ||
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 155b21942f47..30409015a3de 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
@@ -145,7 +145,6 @@ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) | |||
145 | struct ixp4xx_flash_info { | 145 | struct ixp4xx_flash_info { |
146 | struct mtd_info *mtd; | 146 | struct mtd_info *mtd; |
147 | struct map_info map; | 147 | struct map_info map; |
148 | struct mtd_partition *partitions; | ||
149 | struct resource *res; | 148 | struct resource *res; |
150 | }; | 149 | }; |
151 | 150 | ||
@@ -168,8 +167,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev) | |||
168 | if (info->map.virt) | 167 | if (info->map.virt) |
169 | iounmap(info->map.virt); | 168 | iounmap(info->map.virt); |
170 | 169 | ||
171 | kfree(info->partitions); | ||
172 | |||
173 | if (info->res) { | 170 | if (info->res) { |
174 | release_resource(info->res); | 171 | release_resource(info->res); |
175 | kfree(info->res); | 172 | kfree(info->res); |
@@ -185,8 +182,6 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
185 | { | 182 | { |
186 | struct flash_platform_data *plat = dev->dev.platform_data; | 183 | struct flash_platform_data *plat = dev->dev.platform_data; |
187 | struct ixp4xx_flash_info *info; | 184 | struct ixp4xx_flash_info *info; |
188 | const char *part_type = NULL; | ||
189 | int nr_parts = 0; | ||
190 | int err = -1; | 185 | int err = -1; |
191 | 186 | ||
192 | if (!plat) | 187 | if (!plat) |
@@ -252,28 +247,12 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
252 | /* Use the fast version */ | 247 | /* Use the fast version */ |
253 | info->map.write = ixp4xx_write16; | 248 | info->map.write = ixp4xx_write16; |
254 | 249 | ||
255 | nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions, | 250 | err = mtd_device_parse_register(info->mtd, probes, dev->resource->start, |
256 | dev->resource->start); | 251 | plat->parts, plat->nr_parts); |
257 | if (nr_parts > 0) { | 252 | if (err) { |
258 | part_type = "dynamic"; | ||
259 | } else { | ||
260 | info->partitions = plat->parts; | ||
261 | nr_parts = plat->nr_parts; | ||
262 | part_type = "static"; | ||
263 | } | ||
264 | if (nr_parts == 0) | ||
265 | printk(KERN_NOTICE "IXP4xx flash: no partition info " | ||
266 | "available, registering whole flash\n"); | ||
267 | else | ||
268 | printk(KERN_NOTICE "IXP4xx flash: using %s partition " | ||
269 | "definition\n", part_type); | ||
270 | |||
271 | err = mtd_device_register(info->mtd, info->partitions, nr_parts); | ||
272 | if (err) | ||
273 | printk(KERN_ERR "Could not parse partitions\n"); | 253 | printk(KERN_ERR "Could not parse partitions\n"); |
274 | |||
275 | if (err) | ||
276 | goto Error; | 254 | goto Error; |
255 | } | ||
277 | 256 | ||
278 | return 0; | 257 | return 0; |
279 | 258 | ||
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index 7e508969239e..4f10e27ada55 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c | |||
@@ -107,16 +107,12 @@ ltq_copy_to(struct map_info *map, unsigned long to, | |||
107 | spin_unlock_irqrestore(&ebu_lock, flags); | 107 | spin_unlock_irqrestore(&ebu_lock, flags); |
108 | } | 108 | } |
109 | 109 | ||
110 | static const char const *part_probe_types[] = { "cmdlinepart", NULL }; | ||
111 | |||
112 | static int __init | 110 | static int __init |
113 | ltq_mtd_probe(struct platform_device *pdev) | 111 | ltq_mtd_probe(struct platform_device *pdev) |
114 | { | 112 | { |
115 | struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev); | 113 | struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev); |
116 | struct ltq_mtd *ltq_mtd; | 114 | struct ltq_mtd *ltq_mtd; |
117 | struct mtd_partition *parts; | ||
118 | struct resource *res; | 115 | struct resource *res; |
119 | int nr_parts = 0; | ||
120 | struct cfi_private *cfi; | 116 | struct cfi_private *cfi; |
121 | int err; | 117 | int err; |
122 | 118 | ||
@@ -172,17 +168,8 @@ ltq_mtd_probe(struct platform_device *pdev) | |||
172 | cfi->addr_unlock1 ^= 1; | 168 | cfi->addr_unlock1 ^= 1; |
173 | cfi->addr_unlock2 ^= 1; | 169 | cfi->addr_unlock2 ^= 1; |
174 | 170 | ||
175 | nr_parts = parse_mtd_partitions(ltq_mtd->mtd, | 171 | err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0, |
176 | part_probe_types, &parts, 0); | 172 | ltq_mtd_data->parts, ltq_mtd_data->nr_parts); |
177 | if (nr_parts > 0) { | ||
178 | dev_info(&pdev->dev, | ||
179 | "using %d partitions from cmdline", nr_parts); | ||
180 | } else { | ||
181 | nr_parts = ltq_mtd_data->nr_parts; | ||
182 | parts = ltq_mtd_data->parts; | ||
183 | } | ||
184 | |||
185 | err = mtd_device_register(ltq_mtd->mtd, parts, nr_parts); | ||
186 | if (err) { | 173 | if (err) { |
187 | dev_err(&pdev->dev, "failed to add partitions\n"); | 174 | dev_err(&pdev->dev, "failed to add partitions\n"); |
188 | goto err_destroy; | 175 | goto err_destroy; |
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c index 5936c466e901..119baa7d7477 100644 --- a/drivers/mtd/maps/latch-addr-flash.c +++ b/drivers/mtd/maps/latch-addr-flash.c | |||
@@ -33,9 +33,6 @@ struct latch_addr_flash_info { | |||
33 | /* cache; could be found out of res */ | 33 | /* cache; could be found out of res */ |
34 | unsigned long win_mask; | 34 | unsigned long win_mask; |
35 | 35 | ||
36 | int nr_parts; | ||
37 | struct mtd_partition *parts; | ||
38 | |||
39 | spinlock_t lock; | 36 | spinlock_t lock; |
40 | }; | 37 | }; |
41 | 38 | ||
@@ -97,8 +94,6 @@ static void lf_copy_from(struct map_info *map, void *to, | |||
97 | 94 | ||
98 | static char *rom_probe_types[] = { "cfi_probe", NULL }; | 95 | static char *rom_probe_types[] = { "cfi_probe", NULL }; |
99 | 96 | ||
100 | static char *part_probe_types[] = { "cmdlinepart", NULL }; | ||
101 | |||
102 | static int latch_addr_flash_remove(struct platform_device *dev) | 97 | static int latch_addr_flash_remove(struct platform_device *dev) |
103 | { | 98 | { |
104 | struct latch_addr_flash_info *info; | 99 | struct latch_addr_flash_info *info; |
@@ -112,8 +107,6 @@ static int latch_addr_flash_remove(struct platform_device *dev) | |||
112 | latch_addr_data = dev->dev.platform_data; | 107 | latch_addr_data = dev->dev.platform_data; |
113 | 108 | ||
114 | if (info->mtd != NULL) { | 109 | if (info->mtd != NULL) { |
115 | if (info->nr_parts) | ||
116 | kfree(info->parts); | ||
117 | mtd_device_unregister(info->mtd); | 110 | mtd_device_unregister(info->mtd); |
118 | map_destroy(info->mtd); | 111 | map_destroy(info->mtd); |
119 | } | 112 | } |
@@ -206,21 +199,8 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev) | |||
206 | } | 199 | } |
207 | info->mtd->owner = THIS_MODULE; | 200 | info->mtd->owner = THIS_MODULE; |
208 | 201 | ||
209 | err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types, | 202 | mtd_device_parse_register(info->mtd, NULL, 0, |
210 | &info->parts, 0); | 203 | latch_addr_data->parts, latch_addr_data->nr_parts); |
211 | if (err > 0) { | ||
212 | mtd_device_register(info->mtd, info->parts, err); | ||
213 | return 0; | ||
214 | } | ||
215 | if (latch_addr_data->nr_parts) { | ||
216 | pr_notice("Using latch-addr-flash partition information\n"); | ||
217 | mtd_device_register(info->mtd, | ||
218 | latch_addr_data->parts, | ||
219 | latch_addr_data->nr_parts); | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | mtd_device_register(info->mtd, NULL, 0); | ||
224 | return 0; | 204 | return 0; |
225 | 205 | ||
226 | iounmap: | 206 | iounmap: |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index bbe168b65c26..e8e9fec23553 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -22,22 +22,6 @@ | |||
22 | #include <linux/mtd/map.h> | 22 | #include <linux/mtd/map.h> |
23 | #include <linux/mtd/mtd.h> | 23 | #include <linux/mtd/mtd.h> |
24 | 24 | ||
25 | #ifdef CONFIG_MTD_DEBUG | ||
26 | static int debug = CONFIG_MTD_DEBUG_VERBOSE; | ||
27 | module_param(debug, int, 0); | ||
28 | MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); | ||
29 | #undef DEBUG | ||
30 | #define DEBUG(n, format, arg...) \ | ||
31 | if (n <= debug) { \ | ||
32 | printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ | ||
33 | } | ||
34 | |||
35 | #else | ||
36 | #undef DEBUG | ||
37 | #define DEBUG(n, arg...) | ||
38 | static const int debug = 0; | ||
39 | #endif | ||
40 | |||
41 | #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) | 25 | #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) |
42 | 26 | ||
43 | #define DRIVER_DESC "PCMCIA Flash memory card driver" | 27 | #define DRIVER_DESC "PCMCIA Flash memory card driver" |
@@ -105,13 +89,13 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) | |||
105 | int ret; | 89 | int ret; |
106 | 90 | ||
107 | if (!pcmcia_dev_present(dev->p_dev)) { | 91 | if (!pcmcia_dev_present(dev->p_dev)) { |
108 | DEBUG(1, "device removed"); | 92 | pr_debug("device removed\n"); |
109 | return 0; | 93 | return 0; |
110 | } | 94 | } |
111 | 95 | ||
112 | offset = to & ~(dev->win_size-1); | 96 | offset = to & ~(dev->win_size-1); |
113 | if (offset != dev->offset) { | 97 | if (offset != dev->offset) { |
114 | DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", | 98 | pr_debug("Remapping window from 0x%8.8x to 0x%8.8x\n", |
115 | dev->offset, offset); | 99 | dev->offset, offset); |
116 | ret = pcmcia_map_mem_page(dev->p_dev, win, offset); | 100 | ret = pcmcia_map_mem_page(dev->p_dev, win, offset); |
117 | if (ret != 0) | 101 | if (ret != 0) |
@@ -132,7 +116,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) | |||
132 | return d; | 116 | return d; |
133 | 117 | ||
134 | d.x[0] = readb(addr); | 118 | d.x[0] = readb(addr); |
135 | DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]); | 119 | pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", ofs, addr, d.x[0]); |
136 | return d; | 120 | return d; |
137 | } | 121 | } |
138 | 122 | ||
@@ -147,7 +131,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs) | |||
147 | return d; | 131 | return d; |
148 | 132 | ||
149 | d.x[0] = readw(addr); | 133 | d.x[0] = readw(addr); |
150 | DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]); | 134 | pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", ofs, addr, d.x[0]); |
151 | return d; | 135 | return d; |
152 | } | 136 | } |
153 | 137 | ||
@@ -157,7 +141,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long | |||
157 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 141 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
158 | unsigned long win_size = dev->win_size; | 142 | unsigned long win_size = dev->win_size; |
159 | 143 | ||
160 | DEBUG(3, "to = %p from = %lu len = %zd", to, from, len); | 144 | pr_debug("to = %p from = %lu len = %zd\n", to, from, len); |
161 | while(len) { | 145 | while(len) { |
162 | int toread = win_size - (from & (win_size-1)); | 146 | int toread = win_size - (from & (win_size-1)); |
163 | caddr_t addr; | 147 | caddr_t addr; |
@@ -169,7 +153,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long | |||
169 | if(!addr) | 153 | if(!addr) |
170 | return; | 154 | return; |
171 | 155 | ||
172 | DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread); | 156 | pr_debug("memcpy from %p to %p len = %d\n", addr, to, toread); |
173 | memcpy_fromio(to, addr, toread); | 157 | memcpy_fromio(to, addr, toread); |
174 | len -= toread; | 158 | len -= toread; |
175 | to += toread; | 159 | to += toread; |
@@ -185,7 +169,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long | |||
185 | if(!addr) | 169 | if(!addr) |
186 | return; | 170 | return; |
187 | 171 | ||
188 | DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", adr, addr, d.x[0]); | 172 | pr_debug("adr = 0x%08lx (%p) data = 0x%02lx\n", adr, addr, d.x[0]); |
189 | writeb(d.x[0], addr); | 173 | writeb(d.x[0], addr); |
190 | } | 174 | } |
191 | 175 | ||
@@ -196,7 +180,7 @@ static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long | |||
196 | if(!addr) | 180 | if(!addr) |
197 | return; | 181 | return; |
198 | 182 | ||
199 | DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", adr, addr, d.x[0]); | 183 | pr_debug("adr = 0x%08lx (%p) data = 0x%04lx\n", adr, addr, d.x[0]); |
200 | writew(d.x[0], addr); | 184 | writew(d.x[0], addr); |
201 | } | 185 | } |
202 | 186 | ||
@@ -206,7 +190,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v | |||
206 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 190 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
207 | unsigned long win_size = dev->win_size; | 191 | unsigned long win_size = dev->win_size; |
208 | 192 | ||
209 | DEBUG(3, "to = %lu from = %p len = %zd", to, from, len); | 193 | pr_debug("to = %lu from = %p len = %zd\n", to, from, len); |
210 | while(len) { | 194 | while(len) { |
211 | int towrite = win_size - (to & (win_size-1)); | 195 | int towrite = win_size - (to & (win_size-1)); |
212 | caddr_t addr; | 196 | caddr_t addr; |
@@ -218,7 +202,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v | |||
218 | if(!addr) | 202 | if(!addr) |
219 | return; | 203 | return; |
220 | 204 | ||
221 | DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite); | 205 | pr_debug("memcpy from %p to %p len = %d\n", from, addr, towrite); |
222 | memcpy_toio(addr, from, towrite); | 206 | memcpy_toio(addr, from, towrite); |
223 | len -= towrite; | 207 | len -= towrite; |
224 | to += towrite; | 208 | to += towrite; |
@@ -240,7 +224,7 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) | |||
240 | return d; | 224 | return d; |
241 | 225 | ||
242 | d.x[0] = readb(win_base + ofs); | 226 | d.x[0] = readb(win_base + ofs); |
243 | DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", | 227 | pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", |
244 | ofs, win_base + ofs, d.x[0]); | 228 | ofs, win_base + ofs, d.x[0]); |
245 | return d; | 229 | return d; |
246 | } | 230 | } |
@@ -255,7 +239,7 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs) | |||
255 | return d; | 239 | return d; |
256 | 240 | ||
257 | d.x[0] = readw(win_base + ofs); | 241 | d.x[0] = readw(win_base + ofs); |
258 | DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", | 242 | pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", |
259 | ofs, win_base + ofs, d.x[0]); | 243 | ofs, win_base + ofs, d.x[0]); |
260 | return d; | 244 | return d; |
261 | } | 245 | } |
@@ -268,7 +252,7 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, | |||
268 | if(DEV_REMOVED(map)) | 252 | if(DEV_REMOVED(map)) |
269 | return; | 253 | return; |
270 | 254 | ||
271 | DEBUG(3, "to = %p from = %lu len = %zd", to, from, len); | 255 | pr_debug("to = %p from = %lu len = %zd\n", to, from, len); |
272 | memcpy_fromio(to, win_base + from, len); | 256 | memcpy_fromio(to, win_base + from, len); |
273 | } | 257 | } |
274 | 258 | ||
@@ -280,7 +264,7 @@ static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr) | |||
280 | if(DEV_REMOVED(map)) | 264 | if(DEV_REMOVED(map)) |
281 | return; | 265 | return; |
282 | 266 | ||
283 | DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", | 267 | pr_debug("adr = 0x%08lx (%p) data = 0x%02lx\n", |
284 | adr, win_base + adr, d.x[0]); | 268 | adr, win_base + adr, d.x[0]); |
285 | writeb(d.x[0], win_base + adr); | 269 | writeb(d.x[0], win_base + adr); |
286 | } | 270 | } |
@@ -293,7 +277,7 @@ static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr) | |||
293 | if(DEV_REMOVED(map)) | 277 | if(DEV_REMOVED(map)) |
294 | return; | 278 | return; |
295 | 279 | ||
296 | DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", | 280 | pr_debug("adr = 0x%08lx (%p) data = 0x%04lx\n", |
297 | adr, win_base + adr, d.x[0]); | 281 | adr, win_base + adr, d.x[0]); |
298 | writew(d.x[0], win_base + adr); | 282 | writew(d.x[0], win_base + adr); |
299 | } | 283 | } |
@@ -306,7 +290,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f | |||
306 | if(DEV_REMOVED(map)) | 290 | if(DEV_REMOVED(map)) |
307 | return; | 291 | return; |
308 | 292 | ||
309 | DEBUG(3, "to = %lu from = %p len = %zd", to, from, len); | 293 | pr_debug("to = %lu from = %p len = %zd\n", to, from, len); |
310 | memcpy_toio(win_base + to, from, len); | 294 | memcpy_toio(win_base + to, from, len); |
311 | } | 295 | } |
312 | 296 | ||
@@ -316,7 +300,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
316 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 300 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
317 | struct pcmcia_device *link = dev->p_dev; | 301 | struct pcmcia_device *link = dev->p_dev; |
318 | 302 | ||
319 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); | 303 | pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp); |
320 | pcmcia_fixup_vpp(link, on ? dev->vpp : 0); | 304 | pcmcia_fixup_vpp(link, on ? dev->vpp : 0); |
321 | } | 305 | } |
322 | 306 | ||
@@ -325,7 +309,7 @@ static void pcmciamtd_release(struct pcmcia_device *link) | |||
325 | { | 309 | { |
326 | struct pcmciamtd_dev *dev = link->priv; | 310 | struct pcmciamtd_dev *dev = link->priv; |
327 | 311 | ||
328 | DEBUG(3, "link = 0x%p", link); | 312 | pr_debug("link = 0x%p\n", link); |
329 | 313 | ||
330 | if (link->resource[2]->end) { | 314 | if (link->resource[2]->end) { |
331 | if(dev->win_base) { | 315 | if(dev->win_base) { |
@@ -337,7 +321,6 @@ static void pcmciamtd_release(struct pcmcia_device *link) | |||
337 | } | 321 | } |
338 | 322 | ||
339 | 323 | ||
340 | #ifdef CONFIG_MTD_DEBUG | ||
341 | static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev, | 324 | static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev, |
342 | tuple_t *tuple, | 325 | tuple_t *tuple, |
343 | void *priv_data) | 326 | void *priv_data) |
@@ -347,7 +330,7 @@ static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev, | |||
347 | if (!pcmcia_parse_tuple(tuple, &parse)) { | 330 | if (!pcmcia_parse_tuple(tuple, &parse)) { |
348 | cistpl_format_t *t = &parse.format; | 331 | cistpl_format_t *t = &parse.format; |
349 | (void)t; /* Shut up, gcc */ | 332 | (void)t; /* Shut up, gcc */ |
350 | DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", | 333 | pr_debug("Format type: %u, Error Detection: %u, offset = %u, length =%u\n", |
351 | t->type, t->edc, t->offset, t->length); | 334 | t->type, t->edc, t->offset, t->length); |
352 | } | 335 | } |
353 | return -ENOSPC; | 336 | return -ENOSPC; |
@@ -363,12 +346,11 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev, | |||
363 | if (!pcmcia_parse_tuple(tuple, &parse)) { | 346 | if (!pcmcia_parse_tuple(tuple, &parse)) { |
364 | cistpl_jedec_t *t = &parse.jedec; | 347 | cistpl_jedec_t *t = &parse.jedec; |
365 | for (i = 0; i < t->nid; i++) | 348 | for (i = 0; i < t->nid; i++) |
366 | DEBUG(2, "JEDEC: 0x%02x 0x%02x", | 349 | pr_debug("JEDEC: 0x%02x 0x%02x\n", |
367 | t->id[i].mfr, t->id[i].info); | 350 | t->id[i].mfr, t->id[i].info); |
368 | } | 351 | } |
369 | return -ENOSPC; | 352 | return -ENOSPC; |
370 | } | 353 | } |
371 | #endif | ||
372 | 354 | ||
373 | static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev, | 355 | static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev, |
374 | tuple_t *tuple, | 356 | tuple_t *tuple, |
@@ -382,14 +364,14 @@ static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev, | |||
382 | if (pcmcia_parse_tuple(tuple, &parse)) | 364 | if (pcmcia_parse_tuple(tuple, &parse)) |
383 | return -EINVAL; | 365 | return -EINVAL; |
384 | 366 | ||
385 | DEBUG(2, "Common memory:"); | 367 | pr_debug("Common memory:\n"); |
386 | dev->pcmcia_map.size = t->dev[0].size; | 368 | dev->pcmcia_map.size = t->dev[0].size; |
387 | /* from here on: DEBUG only */ | 369 | /* from here on: DEBUG only */ |
388 | for (i = 0; i < t->ndev; i++) { | 370 | for (i = 0; i < t->ndev; i++) { |
389 | DEBUG(2, "Region %d, type = %u", i, t->dev[i].type); | 371 | pr_debug("Region %d, type = %u\n", i, t->dev[i].type); |
390 | DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp); | 372 | pr_debug("Region %d, wp = %u\n", i, t->dev[i].wp); |
391 | DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed); | 373 | pr_debug("Region %d, speed = %u ns\n", i, t->dev[i].speed); |
392 | DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size); | 374 | pr_debug("Region %d, size = %u bytes\n", i, t->dev[i].size); |
393 | } | 375 | } |
394 | return 0; | 376 | return 0; |
395 | } | 377 | } |
@@ -409,12 +391,12 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev, | |||
409 | dev->pcmcia_map.bankwidth = t->geo[0].buswidth; | 391 | dev->pcmcia_map.bankwidth = t->geo[0].buswidth; |
410 | /* from here on: DEBUG only */ | 392 | /* from here on: DEBUG only */ |
411 | for (i = 0; i < t->ngeo; i++) { | 393 | for (i = 0; i < t->ngeo; i++) { |
412 | DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth); | 394 | pr_debug("region: %d bankwidth = %u\n", i, t->geo[i].buswidth); |
413 | DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block); | 395 | pr_debug("region: %d erase_block = %u\n", i, t->geo[i].erase_block); |
414 | DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block); | 396 | pr_debug("region: %d read_block = %u\n", i, t->geo[i].read_block); |
415 | DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block); | 397 | pr_debug("region: %d write_block = %u\n", i, t->geo[i].write_block); |
416 | DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition); | 398 | pr_debug("region: %d partition = %u\n", i, t->geo[i].partition); |
417 | DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave); | 399 | pr_debug("region: %d interleave = %u\n", i, t->geo[i].interleave); |
418 | } | 400 | } |
419 | return 0; | 401 | return 0; |
420 | } | 402 | } |
@@ -432,13 +414,11 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev | |||
432 | if (p_dev->prod_id[i]) | 414 | if (p_dev->prod_id[i]) |
433 | strcat(dev->mtd_name, p_dev->prod_id[i]); | 415 | strcat(dev->mtd_name, p_dev->prod_id[i]); |
434 | } | 416 | } |
435 | DEBUG(2, "Found name: %s", dev->mtd_name); | 417 | pr_debug("Found name: %s\n", dev->mtd_name); |
436 | } | 418 | } |
437 | 419 | ||
438 | #ifdef CONFIG_MTD_DEBUG | ||
439 | pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL); | 420 | pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL); |
440 | pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL); | 421 | pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL); |
441 | #endif | ||
442 | pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev); | 422 | pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev); |
443 | pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev); | 423 | pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev); |
444 | 424 | ||
@@ -450,12 +430,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev | |||
450 | 430 | ||
451 | if(force_size) { | 431 | if(force_size) { |
452 | dev->pcmcia_map.size = force_size << 20; | 432 | dev->pcmcia_map.size = force_size << 20; |
453 | DEBUG(2, "size forced to %dM", force_size); | 433 | pr_debug("size forced to %dM\n", force_size); |
454 | } | 434 | } |
455 | 435 | ||
456 | if(bankwidth) { | 436 | if(bankwidth) { |
457 | dev->pcmcia_map.bankwidth = bankwidth; | 437 | dev->pcmcia_map.bankwidth = bankwidth; |
458 | DEBUG(2, "bankwidth forced to %d", bankwidth); | 438 | pr_debug("bankwidth forced to %d\n", bankwidth); |
459 | } | 439 | } |
460 | 440 | ||
461 | dev->pcmcia_map.name = dev->mtd_name; | 441 | dev->pcmcia_map.name = dev->mtd_name; |
@@ -464,7 +444,7 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev | |||
464 | *new_name = 1; | 444 | *new_name = 1; |
465 | } | 445 | } |
466 | 446 | ||
467 | DEBUG(1, "Device: Size: %lu Width:%d Name: %s", | 447 | pr_debug("Device: Size: %lu Width:%d Name: %s\n", |
468 | dev->pcmcia_map.size, | 448 | dev->pcmcia_map.size, |
469 | dev->pcmcia_map.bankwidth << 3, dev->mtd_name); | 449 | dev->pcmcia_map.bankwidth << 3, dev->mtd_name); |
470 | } | 450 | } |
@@ -479,7 +459,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
479 | static char *probes[] = { "jedec_probe", "cfi_probe" }; | 459 | static char *probes[] = { "jedec_probe", "cfi_probe" }; |
480 | int new_name = 0; | 460 | int new_name = 0; |
481 | 461 | ||
482 | DEBUG(3, "link=0x%p", link); | 462 | pr_debug("link=0x%p\n", link); |
483 | 463 | ||
484 | card_settings(dev, link, &new_name); | 464 | card_settings(dev, link, &new_name); |
485 | 465 | ||
@@ -512,11 +492,11 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
512 | 492 | ||
513 | do { | 493 | do { |
514 | int ret; | 494 | int ret; |
515 | DEBUG(2, "requesting window with size = %luKiB memspeed = %d", | 495 | pr_debug("requesting window with size = %luKiB memspeed = %d\n", |
516 | (unsigned long) resource_size(link->resource[2]) >> 10, | 496 | (unsigned long) resource_size(link->resource[2]) >> 10, |
517 | mem_speed); | 497 | mem_speed); |
518 | ret = pcmcia_request_window(link, link->resource[2], mem_speed); | 498 | ret = pcmcia_request_window(link, link->resource[2], mem_speed); |
519 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); | 499 | pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size); |
520 | if(ret) { | 500 | if(ret) { |
521 | j++; | 501 | j++; |
522 | link->resource[2]->start = 0; | 502 | link->resource[2]->start = 0; |
@@ -524,21 +504,21 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
524 | force_size << 20 : MAX_PCMCIA_ADDR; | 504 | force_size << 20 : MAX_PCMCIA_ADDR; |
525 | link->resource[2]->end >>= j; | 505 | link->resource[2]->end >>= j; |
526 | } else { | 506 | } else { |
527 | DEBUG(2, "Got window of size %luKiB", (unsigned long) | 507 | pr_debug("Got window of size %luKiB\n", (unsigned long) |
528 | resource_size(link->resource[2]) >> 10); | 508 | resource_size(link->resource[2]) >> 10); |
529 | dev->win_size = resource_size(link->resource[2]); | 509 | dev->win_size = resource_size(link->resource[2]); |
530 | break; | 510 | break; |
531 | } | 511 | } |
532 | } while (link->resource[2]->end >= 0x1000); | 512 | } while (link->resource[2]->end >= 0x1000); |
533 | 513 | ||
534 | DEBUG(2, "dev->win_size = %d", dev->win_size); | 514 | pr_debug("dev->win_size = %d\n", dev->win_size); |
535 | 515 | ||
536 | if(!dev->win_size) { | 516 | if(!dev->win_size) { |
537 | dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n"); | 517 | dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n"); |
538 | pcmciamtd_release(link); | 518 | pcmciamtd_release(link); |
539 | return -ENODEV; | 519 | return -ENODEV; |
540 | } | 520 | } |
541 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); | 521 | pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10); |
542 | 522 | ||
543 | /* Get write protect status */ | 523 | /* Get write protect status */ |
544 | dev->win_base = ioremap(link->resource[2]->start, | 524 | dev->win_base = ioremap(link->resource[2]->start, |
@@ -549,7 +529,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
549 | pcmciamtd_release(link); | 529 | pcmciamtd_release(link); |
550 | return -ENODEV; | 530 | return -ENODEV; |
551 | } | 531 | } |
552 | DEBUG(1, "mapped window dev = %p @ %pR, base = %p", | 532 | pr_debug("mapped window dev = %p @ %pR, base = %p\n", |
553 | dev, link->resource[2], dev->win_base); | 533 | dev, link->resource[2], dev->win_base); |
554 | 534 | ||
555 | dev->offset = 0; | 535 | dev->offset = 0; |
@@ -564,7 +544,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
564 | } | 544 | } |
565 | 545 | ||
566 | link->config_index = 0; | 546 | link->config_index = 0; |
567 | DEBUG(2, "Setting Configuration"); | 547 | pr_debug("Setting Configuration\n"); |
568 | ret = pcmcia_enable_device(link); | 548 | ret = pcmcia_enable_device(link); |
569 | if (ret != 0) { | 549 | if (ret != 0) { |
570 | if (dev->win_base) { | 550 | if (dev->win_base) { |
@@ -580,17 +560,17 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
580 | mtd = do_map_probe("map_rom", &dev->pcmcia_map); | 560 | mtd = do_map_probe("map_rom", &dev->pcmcia_map); |
581 | } else { | 561 | } else { |
582 | for(i = 0; i < ARRAY_SIZE(probes); i++) { | 562 | for(i = 0; i < ARRAY_SIZE(probes); i++) { |
583 | DEBUG(1, "Trying %s", probes[i]); | 563 | pr_debug("Trying %s\n", probes[i]); |
584 | mtd = do_map_probe(probes[i], &dev->pcmcia_map); | 564 | mtd = do_map_probe(probes[i], &dev->pcmcia_map); |
585 | if(mtd) | 565 | if(mtd) |
586 | break; | 566 | break; |
587 | 567 | ||
588 | DEBUG(1, "FAILED: %s", probes[i]); | 568 | pr_debug("FAILED: %s\n", probes[i]); |
589 | } | 569 | } |
590 | } | 570 | } |
591 | 571 | ||
592 | if(!mtd) { | 572 | if(!mtd) { |
593 | DEBUG(1, "Can not find an MTD"); | 573 | pr_debug("Can not find an MTD\n"); |
594 | pcmciamtd_release(link); | 574 | pcmciamtd_release(link); |
595 | return -ENODEV; | 575 | return -ENODEV; |
596 | } | 576 | } |
@@ -617,7 +597,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
617 | /* If the memory found is fits completely into the mapped PCMCIA window, | 597 | /* If the memory found is fits completely into the mapped PCMCIA window, |
618 | use the faster non-remapping read/write functions */ | 598 | use the faster non-remapping read/write functions */ |
619 | if(mtd->size <= dev->win_size) { | 599 | if(mtd->size <= dev->win_size) { |
620 | DEBUG(1, "Using non remapping memory functions"); | 600 | pr_debug("Using non remapping memory functions\n"); |
621 | dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; | 601 | dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; |
622 | if (dev->pcmcia_map.bankwidth == 1) { | 602 | if (dev->pcmcia_map.bankwidth == 1) { |
623 | dev->pcmcia_map.read = pcmcia_read8; | 603 | dev->pcmcia_map.read = pcmcia_read8; |
@@ -645,7 +625,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
645 | 625 | ||
646 | static int pcmciamtd_suspend(struct pcmcia_device *dev) | 626 | static int pcmciamtd_suspend(struct pcmcia_device *dev) |
647 | { | 627 | { |
648 | DEBUG(2, "EVENT_PM_RESUME"); | 628 | pr_debug("EVENT_PM_RESUME\n"); |
649 | 629 | ||
650 | /* get_lock(link); */ | 630 | /* get_lock(link); */ |
651 | 631 | ||
@@ -654,7 +634,7 @@ static int pcmciamtd_suspend(struct pcmcia_device *dev) | |||
654 | 634 | ||
655 | static int pcmciamtd_resume(struct pcmcia_device *dev) | 635 | static int pcmciamtd_resume(struct pcmcia_device *dev) |
656 | { | 636 | { |
657 | DEBUG(2, "EVENT_PM_SUSPEND"); | 637 | pr_debug("EVENT_PM_SUSPEND\n"); |
658 | 638 | ||
659 | /* free_lock(link); */ | 639 | /* free_lock(link); */ |
660 | 640 | ||
@@ -666,7 +646,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link) | |||
666 | { | 646 | { |
667 | struct pcmciamtd_dev *dev = link->priv; | 647 | struct pcmciamtd_dev *dev = link->priv; |
668 | 648 | ||
669 | DEBUG(3, "link=0x%p", link); | 649 | pr_debug("link=0x%p\n", link); |
670 | 650 | ||
671 | if(dev->mtd_info) { | 651 | if(dev->mtd_info) { |
672 | mtd_device_unregister(dev->mtd_info); | 652 | mtd_device_unregister(dev->mtd_info); |
@@ -686,7 +666,7 @@ static int pcmciamtd_probe(struct pcmcia_device *link) | |||
686 | /* Create new memory card device */ | 666 | /* Create new memory card device */ |
687 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 667 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
688 | if (!dev) return -ENOMEM; | 668 | if (!dev) return -ENOMEM; |
689 | DEBUG(1, "dev=0x%p", dev); | 669 | pr_debug("dev=0x%p\n", dev); |
690 | 670 | ||
691 | dev->p_dev = link; | 671 | dev->p_dev = link; |
692 | link->priv = dev; | 672 | link->priv = dev; |
@@ -755,7 +735,7 @@ static int __init init_pcmciamtd(void) | |||
755 | 735 | ||
756 | static void __exit exit_pcmciamtd(void) | 736 | static void __exit exit_pcmciamtd(void) |
757 | { | 737 | { |
758 | DEBUG(1, DRIVER_DESC " unloading"); | 738 | pr_debug(DRIVER_DESC " unloading"); |
759 | pcmcia_unregister_driver(&pcmciamtd_driver); | 739 | pcmcia_unregister_driver(&pcmciamtd_driver); |
760 | } | 740 | } |
761 | 741 | ||
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index f64cee4a3bfb..66e8200079c2 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
@@ -27,8 +27,6 @@ struct physmap_flash_info { | |||
27 | struct mtd_info *mtd[MAX_RESOURCES]; | 27 | struct mtd_info *mtd[MAX_RESOURCES]; |
28 | struct mtd_info *cmtd; | 28 | struct mtd_info *cmtd; |
29 | struct map_info map[MAX_RESOURCES]; | 29 | struct map_info map[MAX_RESOURCES]; |
30 | int nr_parts; | ||
31 | struct mtd_partition *parts; | ||
32 | }; | 30 | }; |
33 | 31 | ||
34 | static int physmap_flash_remove(struct platform_device *dev) | 32 | static int physmap_flash_remove(struct platform_device *dev) |
@@ -46,8 +44,6 @@ static int physmap_flash_remove(struct platform_device *dev) | |||
46 | 44 | ||
47 | if (info->cmtd) { | 45 | if (info->cmtd) { |
48 | mtd_device_unregister(info->cmtd); | 46 | mtd_device_unregister(info->cmtd); |
49 | if (info->nr_parts) | ||
50 | kfree(info->parts); | ||
51 | if (info->cmtd != info->mtd[0]) | 47 | if (info->cmtd != info->mtd[0]) |
52 | mtd_concat_destroy(info->cmtd); | 48 | mtd_concat_destroy(info->cmtd); |
53 | } | 49 | } |
@@ -175,23 +171,8 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
175 | if (err) | 171 | if (err) |
176 | goto err_out; | 172 | goto err_out; |
177 | 173 | ||
178 | err = parse_mtd_partitions(info->cmtd, part_probe_types, | 174 | mtd_device_parse_register(info->cmtd, part_probe_types, 0, |
179 | &info->parts, 0); | 175 | physmap_data->parts, physmap_data->nr_parts); |
180 | if (err > 0) { | ||
181 | mtd_device_register(info->cmtd, info->parts, err); | ||
182 | info->nr_parts = err; | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | if (physmap_data->nr_parts) { | ||
187 | printk(KERN_NOTICE "Using physmap partition information\n"); | ||
188 | mtd_device_register(info->cmtd, physmap_data->parts, | ||
189 | physmap_data->nr_parts); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | mtd_device_register(info->cmtd, NULL, 0); | ||
194 | |||
195 | return 0; | 176 | return 0; |
196 | 177 | ||
197 | err_out: | 178 | err_out: |
@@ -245,21 +226,6 @@ static struct platform_device physmap_flash = { | |||
245 | .num_resources = 1, | 226 | .num_resources = 1, |
246 | .resource = &physmap_flash_resource, | 227 | .resource = &physmap_flash_resource, |
247 | }; | 228 | }; |
248 | |||
249 | void physmap_configure(unsigned long addr, unsigned long size, | ||
250 | int bankwidth, void (*set_vpp)(struct map_info *, int)) | ||
251 | { | ||
252 | physmap_flash_resource.start = addr; | ||
253 | physmap_flash_resource.end = addr + size - 1; | ||
254 | physmap_flash_data.width = bankwidth; | ||
255 | physmap_flash_data.set_vpp = set_vpp; | ||
256 | } | ||
257 | |||
258 | void physmap_set_partitions(struct mtd_partition *parts, int num_parts) | ||
259 | { | ||
260 | physmap_flash_data.nr_parts = num_parts; | ||
261 | physmap_flash_data.parts = parts; | ||
262 | } | ||
263 | #endif | 229 | #endif |
264 | 230 | ||
265 | static int __init physmap_init(void) | 231 | static int __init physmap_init(void) |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index d251d1db129b..7d65f9d3e690 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -34,58 +34,10 @@ struct of_flash_list { | |||
34 | 34 | ||
35 | struct of_flash { | 35 | struct of_flash { |
36 | struct mtd_info *cmtd; | 36 | struct mtd_info *cmtd; |
37 | struct mtd_partition *parts; | ||
38 | int list_size; /* number of elements in of_flash_list */ | 37 | int list_size; /* number of elements in of_flash_list */ |
39 | struct of_flash_list list[0]; | 38 | struct of_flash_list list[0]; |
40 | }; | 39 | }; |
41 | 40 | ||
42 | #define OF_FLASH_PARTS(info) ((info)->parts) | ||
43 | static int parse_obsolete_partitions(struct platform_device *dev, | ||
44 | struct of_flash *info, | ||
45 | struct device_node *dp) | ||
46 | { | ||
47 | int i, plen, nr_parts; | ||
48 | const struct { | ||
49 | __be32 offset, len; | ||
50 | } *part; | ||
51 | const char *names; | ||
52 | |||
53 | part = of_get_property(dp, "partitions", &plen); | ||
54 | if (!part) | ||
55 | return 0; /* No partitions found */ | ||
56 | |||
57 | dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n"); | ||
58 | |||
59 | nr_parts = plen / sizeof(part[0]); | ||
60 | |||
61 | info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL); | ||
62 | if (!info->parts) | ||
63 | return -ENOMEM; | ||
64 | |||
65 | names = of_get_property(dp, "partition-names", &plen); | ||
66 | |||
67 | for (i = 0; i < nr_parts; i++) { | ||
68 | info->parts[i].offset = be32_to_cpu(part->offset); | ||
69 | info->parts[i].size = be32_to_cpu(part->len) & ~1; | ||
70 | if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */ | ||
71 | info->parts[i].mask_flags = MTD_WRITEABLE; | ||
72 | |||
73 | if (names && (plen > 0)) { | ||
74 | int len = strlen(names) + 1; | ||
75 | |||
76 | info->parts[i].name = (char *)names; | ||
77 | plen -= len; | ||
78 | names += len; | ||
79 | } else { | ||
80 | info->parts[i].name = "unnamed"; | ||
81 | } | ||
82 | |||
83 | part++; | ||
84 | } | ||
85 | |||
86 | return nr_parts; | ||
87 | } | ||
88 | |||
89 | static int of_flash_remove(struct platform_device *dev) | 41 | static int of_flash_remove(struct platform_device *dev) |
90 | { | 42 | { |
91 | struct of_flash *info; | 43 | struct of_flash *info; |
@@ -101,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev) | |||
101 | mtd_concat_destroy(info->cmtd); | 53 | mtd_concat_destroy(info->cmtd); |
102 | } | 54 | } |
103 | 55 | ||
104 | if (info->cmtd) { | 56 | if (info->cmtd) |
105 | if (OF_FLASH_PARTS(info)) | ||
106 | kfree(OF_FLASH_PARTS(info)); | ||
107 | mtd_device_unregister(info->cmtd); | 57 | mtd_device_unregister(info->cmtd); |
108 | } | ||
109 | 58 | ||
110 | for (i = 0; i < info->list_size; i++) { | 59 | for (i = 0; i < info->list_size; i++) { |
111 | if (info->list[i].mtd) | 60 | if (info->list[i].mtd) |
@@ -165,7 +114,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, | |||
165 | specifies the list of partition probers to use. If none is given then the | 114 | specifies the list of partition probers to use. If none is given then the |
166 | default is use. These take precedence over other device tree | 115 | default is use. These take precedence over other device tree |
167 | information. */ | 116 | information. */ |
168 | static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL }; | 117 | static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", |
118 | "ofpart", "ofoldpart", NULL }; | ||
169 | static const char ** __devinit of_get_probes(struct device_node *dp) | 119 | static const char ** __devinit of_get_probes(struct device_node *dp) |
170 | { | 120 | { |
171 | const char *cp; | 121 | const char *cp; |
@@ -218,6 +168,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
218 | int reg_tuple_size; | 168 | int reg_tuple_size; |
219 | struct mtd_info **mtd_list = NULL; | 169 | struct mtd_info **mtd_list = NULL; |
220 | resource_size_t res_size; | 170 | resource_size_t res_size; |
171 | struct mtd_part_parser_data ppdata; | ||
221 | 172 | ||
222 | match = of_match_device(of_flash_match, &dev->dev); | 173 | match = of_match_device(of_flash_match, &dev->dev); |
223 | if (!match) | 174 | if (!match) |
@@ -331,29 +282,12 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
331 | if (err) | 282 | if (err) |
332 | goto err_out; | 283 | goto err_out; |
333 | 284 | ||
285 | ppdata.of_node = dp; | ||
334 | part_probe_types = of_get_probes(dp); | 286 | part_probe_types = of_get_probes(dp); |
335 | err = parse_mtd_partitions(info->cmtd, part_probe_types, | 287 | mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata, |
336 | &info->parts, 0); | 288 | NULL, 0); |
337 | if (err < 0) { | ||
338 | of_free_probes(part_probe_types); | ||
339 | goto err_out; | ||
340 | } | ||
341 | of_free_probes(part_probe_types); | 289 | of_free_probes(part_probe_types); |
342 | 290 | ||
343 | if (err == 0) { | ||
344 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); | ||
345 | if (err < 0) | ||
346 | goto err_out; | ||
347 | } | ||
348 | |||
349 | if (err == 0) { | ||
350 | err = parse_obsolete_partitions(dev, info, dp); | ||
351 | if (err < 0) | ||
352 | goto err_out; | ||
353 | } | ||
354 | |||
355 | mtd_device_register(info->cmtd, info->parts, err); | ||
356 | |||
357 | kfree(mtd_list); | 291 | kfree(mtd_list); |
358 | 292 | ||
359 | return 0; | 293 | return 0; |
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 9ca1eccba4bc..94f553489725 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c | |||
@@ -44,8 +44,6 @@ struct platram_info { | |||
44 | struct device *dev; | 44 | struct device *dev; |
45 | struct mtd_info *mtd; | 45 | struct mtd_info *mtd; |
46 | struct map_info map; | 46 | struct map_info map; |
47 | struct mtd_partition *partitions; | ||
48 | bool free_partitions; | ||
49 | struct resource *area; | 47 | struct resource *area; |
50 | struct platdata_mtd_ram *pdata; | 48 | struct platdata_mtd_ram *pdata; |
51 | }; | 49 | }; |
@@ -95,10 +93,6 @@ static int platram_remove(struct platform_device *pdev) | |||
95 | 93 | ||
96 | if (info->mtd) { | 94 | if (info->mtd) { |
97 | mtd_device_unregister(info->mtd); | 95 | mtd_device_unregister(info->mtd); |
98 | if (info->partitions) { | ||
99 | if (info->free_partitions) | ||
100 | kfree(info->partitions); | ||
101 | } | ||
102 | map_destroy(info->mtd); | 96 | map_destroy(info->mtd); |
103 | } | 97 | } |
104 | 98 | ||
@@ -228,21 +222,8 @@ static int platram_probe(struct platform_device *pdev) | |||
228 | /* check to see if there are any available partitions, or wether | 222 | /* check to see if there are any available partitions, or wether |
229 | * to add this device whole */ | 223 | * to add this device whole */ |
230 | 224 | ||
231 | if (!pdata->nr_partitions) { | 225 | err = mtd_device_parse_register(info->mtd, pdata->probes, 0, |
232 | /* try to probe using the supplied probe type */ | 226 | pdata->partitions, pdata->nr_partitions); |
233 | if (pdata->probes) { | ||
234 | err = parse_mtd_partitions(info->mtd, pdata->probes, | ||
235 | &info->partitions, 0); | ||
236 | info->free_partitions = 1; | ||
237 | if (err > 0) | ||
238 | err = mtd_device_register(info->mtd, | ||
239 | info->partitions, err); | ||
240 | } | ||
241 | } | ||
242 | /* use the static mapping */ | ||
243 | else | ||
244 | err = mtd_device_register(info->mtd, pdata->partitions, | ||
245 | pdata->nr_partitions); | ||
246 | if (!err) | 227 | if (!err) |
247 | dev_info(&pdev->dev, "registered mtd device\n"); | 228 | dev_info(&pdev->dev, "registered mtd device\n"); |
248 | 229 | ||
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 7ae137d4b998..411a17df9fc1 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
@@ -41,8 +41,6 @@ static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, | |||
41 | } | 41 | } |
42 | 42 | ||
43 | struct pxa2xx_flash_info { | 43 | struct pxa2xx_flash_info { |
44 | struct mtd_partition *parts; | ||
45 | int nr_parts; | ||
46 | struct mtd_info *mtd; | 44 | struct mtd_info *mtd; |
47 | struct map_info map; | 45 | struct map_info map; |
48 | }; | 46 | }; |
@@ -55,9 +53,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) | |||
55 | { | 53 | { |
56 | struct flash_platform_data *flash = pdev->dev.platform_data; | 54 | struct flash_platform_data *flash = pdev->dev.platform_data; |
57 | struct pxa2xx_flash_info *info; | 55 | struct pxa2xx_flash_info *info; |
58 | struct mtd_partition *parts; | ||
59 | struct resource *res; | 56 | struct resource *res; |
60 | int ret = 0; | ||
61 | 57 | ||
62 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 58 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
63 | if (!res) | 59 | if (!res) |
@@ -71,8 +67,6 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) | |||
71 | info->map.bankwidth = flash->width; | 67 | info->map.bankwidth = flash->width; |
72 | info->map.phys = res->start; | 68 | info->map.phys = res->start; |
73 | info->map.size = resource_size(res); | 69 | info->map.size = resource_size(res); |
74 | info->parts = flash->parts; | ||
75 | info->nr_parts = flash->nr_parts; | ||
76 | 70 | ||
77 | info->map.virt = ioremap(info->map.phys, info->map.size); | 71 | info->map.virt = ioremap(info->map.phys, info->map.size); |
78 | if (!info->map.virt) { | 72 | if (!info->map.virt) { |
@@ -104,18 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) | |||
104 | } | 98 | } |
105 | info->mtd->owner = THIS_MODULE; | 99 | info->mtd->owner = THIS_MODULE; |
106 | 100 | ||
107 | ret = parse_mtd_partitions(info->mtd, probes, &parts, 0); | 101 | mtd_device_parse_register(info->mtd, probes, 0, NULL, 0); |
108 | |||
109 | if (ret > 0) { | ||
110 | info->nr_parts = ret; | ||
111 | info->parts = parts; | ||
112 | } | ||
113 | |||
114 | if (!info->nr_parts) | ||
115 | printk("Registering %s as whole device\n", | ||
116 | info->map.name); | ||
117 | |||
118 | mtd_device_register(info->mtd, info->parts, info->nr_parts); | ||
119 | 102 | ||
120 | platform_set_drvdata(pdev, info); | 103 | platform_set_drvdata(pdev, info); |
121 | return 0; | 104 | return 0; |
@@ -133,7 +116,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev) | |||
133 | iounmap(info->map.virt); | 116 | iounmap(info->map.virt); |
134 | if (info->map.cached) | 117 | if (info->map.cached) |
135 | iounmap(info->map.cached); | 118 | iounmap(info->map.cached); |
136 | kfree(info->parts); | ||
137 | kfree(info); | 119 | kfree(info); |
138 | return 0; | 120 | return 0; |
139 | } | 121 | } |
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c index 761fb459d2c7..0237f197fd12 100644 --- a/drivers/mtd/maps/rbtx4939-flash.c +++ b/drivers/mtd/maps/rbtx4939-flash.c | |||
@@ -25,8 +25,6 @@ | |||
25 | struct rbtx4939_flash_info { | 25 | struct rbtx4939_flash_info { |
26 | struct mtd_info *mtd; | 26 | struct mtd_info *mtd; |
27 | struct map_info map; | 27 | struct map_info map; |
28 | int nr_parts; | ||
29 | struct mtd_partition *parts; | ||
30 | }; | 28 | }; |
31 | 29 | ||
32 | static int rbtx4939_flash_remove(struct platform_device *dev) | 30 | static int rbtx4939_flash_remove(struct platform_device *dev) |
@@ -41,8 +39,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev) | |||
41 | if (info->mtd) { | 39 | if (info->mtd) { |
42 | struct rbtx4939_flash_data *pdata = dev->dev.platform_data; | 40 | struct rbtx4939_flash_data *pdata = dev->dev.platform_data; |
43 | 41 | ||
44 | if (info->nr_parts) | ||
45 | kfree(info->parts); | ||
46 | mtd_device_unregister(info->mtd); | 42 | mtd_device_unregister(info->mtd); |
47 | map_destroy(info->mtd); | 43 | map_destroy(info->mtd); |
48 | } | 44 | } |
@@ -50,7 +46,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev) | |||
50 | } | 46 | } |
51 | 47 | ||
52 | static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 48 | static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
53 | static const char *part_probe_types[] = { "cmdlinepart", NULL }; | ||
54 | 49 | ||
55 | static int rbtx4939_flash_probe(struct platform_device *dev) | 50 | static int rbtx4939_flash_probe(struct platform_device *dev) |
56 | { | 51 | { |
@@ -107,22 +102,11 @@ static int rbtx4939_flash_probe(struct platform_device *dev) | |||
107 | info->mtd->owner = THIS_MODULE; | 102 | info->mtd->owner = THIS_MODULE; |
108 | if (err) | 103 | if (err) |
109 | goto err_out; | 104 | goto err_out; |
105 | err = mtd_device_parse_register(info->mtd, NULL, 0, | ||
106 | pdata->parts, pdata->nr_parts); | ||
110 | 107 | ||
111 | err = parse_mtd_partitions(info->mtd, part_probe_types, | 108 | if (err) |
112 | &info->parts, 0); | 109 | goto err_out; |
113 | if (err > 0) { | ||
114 | mtd_device_register(info->mtd, info->parts, err); | ||
115 | info->nr_parts = err; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | if (pdata->nr_parts) { | ||
120 | pr_notice("Using rbtx4939 partition information\n"); | ||
121 | mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts); | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | mtd_device_register(info->mtd, NULL, 0); | ||
126 | return 0; | 110 | return 0; |
127 | 111 | ||
128 | err_out: | 112 | err_out: |
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index a9b5e0e5c4c5..fa9c0a9670cd 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c | |||
@@ -131,10 +131,8 @@ struct sa_subdev_info { | |||
131 | }; | 131 | }; |
132 | 132 | ||
133 | struct sa_info { | 133 | struct sa_info { |
134 | struct mtd_partition *parts; | ||
135 | struct mtd_info *mtd; | 134 | struct mtd_info *mtd; |
136 | int num_subdev; | 135 | int num_subdev; |
137 | unsigned int nr_parts; | ||
138 | struct sa_subdev_info subdev[0]; | 136 | struct sa_subdev_info subdev[0]; |
139 | }; | 137 | }; |
140 | 138 | ||
@@ -231,8 +229,6 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla | |||
231 | mtd_concat_destroy(info->mtd); | 229 | mtd_concat_destroy(info->mtd); |
232 | } | 230 | } |
233 | 231 | ||
234 | kfree(info->parts); | ||
235 | |||
236 | for (i = info->num_subdev - 1; i >= 0; i--) | 232 | for (i = info->num_subdev - 1; i >= 0; i--) |
237 | sa1100_destroy_subdev(&info->subdev[i]); | 233 | sa1100_destroy_subdev(&info->subdev[i]); |
238 | kfree(info); | 234 | kfree(info); |
@@ -341,10 +337,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; | |||
341 | static int __devinit sa1100_mtd_probe(struct platform_device *pdev) | 337 | static int __devinit sa1100_mtd_probe(struct platform_device *pdev) |
342 | { | 338 | { |
343 | struct flash_platform_data *plat = pdev->dev.platform_data; | 339 | struct flash_platform_data *plat = pdev->dev.platform_data; |
344 | struct mtd_partition *parts; | ||
345 | const char *part_type = NULL; | ||
346 | struct sa_info *info; | 340 | struct sa_info *info; |
347 | int err, nr_parts = 0; | 341 | int err; |
348 | 342 | ||
349 | if (!plat) | 343 | if (!plat) |
350 | return -ENODEV; | 344 | return -ENODEV; |
@@ -358,26 +352,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev) | |||
358 | /* | 352 | /* |
359 | * Partition selection stuff. | 353 | * Partition selection stuff. |
360 | */ | 354 | */ |
361 | nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0); | 355 | mtd_device_parse_register(info->mtd, part_probes, 0, |
362 | if (nr_parts > 0) { | 356 | plat->parts, plat->nr_parts); |
363 | info->parts = parts; | ||
364 | part_type = "dynamic"; | ||
365 | } else { | ||
366 | parts = plat->parts; | ||
367 | nr_parts = plat->nr_parts; | ||
368 | part_type = "static"; | ||
369 | } | ||
370 | |||
371 | if (nr_parts == 0) | ||
372 | printk(KERN_NOTICE "SA1100 flash: no partition info " | ||
373 | "available, registering whole flash\n"); | ||
374 | else | ||
375 | printk(KERN_NOTICE "SA1100 flash: using %s partition " | ||
376 | "definition\n", part_type); | ||
377 | |||
378 | mtd_device_register(info->mtd, parts, nr_parts); | ||
379 | |||
380 | info->nr_parts = nr_parts; | ||
381 | 357 | ||
382 | platform_set_drvdata(pdev, info); | 358 | platform_set_drvdata(pdev, info); |
383 | err = 0; | 359 | err = 0; |
diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c index cbf6bade9354..496c40704aff 100644 --- a/drivers/mtd/maps/solutionengine.c +++ b/drivers/mtd/maps/solutionengine.c | |||
@@ -19,8 +19,6 @@ | |||
19 | static struct mtd_info *flash_mtd; | 19 | static struct mtd_info *flash_mtd; |
20 | static struct mtd_info *eprom_mtd; | 20 | static struct mtd_info *eprom_mtd; |
21 | 21 | ||
22 | static struct mtd_partition *parsed_parts; | ||
23 | |||
24 | struct map_info soleng_eprom_map = { | 22 | struct map_info soleng_eprom_map = { |
25 | .name = "Solution Engine EPROM", | 23 | .name = "Solution Engine EPROM", |
26 | .size = 0x400000, | 24 | .size = 0x400000, |
@@ -51,12 +49,14 @@ static struct mtd_partition superh_se_partitions[] = { | |||
51 | .size = MTDPART_SIZ_FULL, | 49 | .size = MTDPART_SIZ_FULL, |
52 | } | 50 | } |
53 | }; | 51 | }; |
52 | #define NUM_PARTITIONS ARRAY_SIZE(superh_se_partitions) | ||
53 | #else | ||
54 | #define superh_se_partitions NULL | ||
55 | #define NUM_PARTITIONS 0 | ||
54 | #endif /* CONFIG_MTD_SUPERH_RESERVE */ | 56 | #endif /* CONFIG_MTD_SUPERH_RESERVE */ |
55 | 57 | ||
56 | static int __init init_soleng_maps(void) | 58 | static int __init init_soleng_maps(void) |
57 | { | 59 | { |
58 | int nr_parts = 0; | ||
59 | |||
60 | /* First probe at offset 0 */ | 60 | /* First probe at offset 0 */ |
61 | soleng_flash_map.phys = 0; | 61 | soleng_flash_map.phys = 0; |
62 | soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0); | 62 | soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0); |
@@ -92,21 +92,8 @@ static int __init init_soleng_maps(void) | |||
92 | mtd_device_register(eprom_mtd, NULL, 0); | 92 | mtd_device_register(eprom_mtd, NULL, 0); |
93 | } | 93 | } |
94 | 94 | ||
95 | nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); | 95 | mtd_device_parse_register(flash_mtd, probes, 0, |
96 | 96 | superh_se_partitions, NUM_PARTITIONS); | |
97 | #ifdef CONFIG_MTD_SUPERH_RESERVE | ||
98 | if (nr_parts <= 0) { | ||
99 | printk(KERN_NOTICE "Using configured partition at 0x%08x.\n", | ||
100 | CONFIG_MTD_SUPERH_RESERVE); | ||
101 | parsed_parts = superh_se_partitions; | ||
102 | nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts); | ||
103 | } | ||
104 | #endif /* CONFIG_MTD_SUPERH_RESERVE */ | ||
105 | |||
106 | if (nr_parts > 0) | ||
107 | mtd_device_register(flash_mtd, parsed_parts, nr_parts); | ||
108 | else | ||
109 | mtd_device_register(flash_mtd, NULL, 0); | ||
110 | 97 | ||
111 | return 0; | 98 | return 0; |
112 | } | 99 | } |
@@ -118,10 +105,7 @@ static void __exit cleanup_soleng_maps(void) | |||
118 | map_destroy(eprom_mtd); | 105 | map_destroy(eprom_mtd); |
119 | } | 106 | } |
120 | 107 | ||
121 | if (parsed_parts) | 108 | mtd_device_unregister(flash_mtd); |
122 | mtd_device_unregister(flash_mtd); | ||
123 | else | ||
124 | mtd_device_unregister(flash_mtd); | ||
125 | map_destroy(flash_mtd); | 109 | map_destroy(flash_mtd); |
126 | } | 110 | } |
127 | 111 | ||
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c index 901ce968efae..aa7e0cb2893c 100644 --- a/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/drivers/mtd/maps/wr_sbc82xx_flash.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <asm/immap_cpm2.h> | 20 | #include <asm/immap_cpm2.h> |
21 | 21 | ||
22 | static struct mtd_info *sbcmtd[3]; | 22 | static struct mtd_info *sbcmtd[3]; |
23 | static struct mtd_partition *sbcmtd_parts[3]; | ||
24 | 23 | ||
25 | struct map_info sbc82xx_flash_map[3] = { | 24 | struct map_info sbc82xx_flash_map[3] = { |
26 | {.name = "Boot flash"}, | 25 | {.name = "Boot flash"}, |
@@ -101,6 +100,7 @@ static int __init init_sbc82xx_flash(void) | |||
101 | for (i=0; i<3; i++) { | 100 | for (i=0; i<3; i++) { |
102 | int8_t flashcs[3] = { 0, 6, 1 }; | 101 | int8_t flashcs[3] = { 0, 6, 1 }; |
103 | int nr_parts; | 102 | int nr_parts; |
103 | struct mtd_partition *defparts; | ||
104 | 104 | ||
105 | printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d", | 105 | printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d", |
106 | sbc82xx_flash_map[i].name, | 106 | sbc82xx_flash_map[i].name, |
@@ -113,7 +113,8 @@ static int __init init_sbc82xx_flash(void) | |||
113 | } | 113 | } |
114 | printk(" at %08lx)\n", sbc82xx_flash_map[i].phys); | 114 | printk(" at %08lx)\n", sbc82xx_flash_map[i].phys); |
115 | 115 | ||
116 | sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size); | 116 | sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, |
117 | sbc82xx_flash_map[i].size); | ||
117 | 118 | ||
118 | if (!sbc82xx_flash_map[i].virt) { | 119 | if (!sbc82xx_flash_map[i].virt) { |
119 | printk("Failed to ioremap\n"); | 120 | printk("Failed to ioremap\n"); |
@@ -129,24 +130,20 @@ static int __init init_sbc82xx_flash(void) | |||
129 | 130 | ||
130 | sbcmtd[i]->owner = THIS_MODULE; | 131 | sbcmtd[i]->owner = THIS_MODULE; |
131 | 132 | ||
132 | nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes, | ||
133 | &sbcmtd_parts[i], 0); | ||
134 | if (nr_parts > 0) { | ||
135 | mtd_device_register(sbcmtd[i], sbcmtd_parts[i], | ||
136 | nr_parts); | ||
137 | continue; | ||
138 | } | ||
139 | |||
140 | /* No partitioning detected. Use default */ | 133 | /* No partitioning detected. Use default */ |
141 | if (i == 2) { | 134 | if (i == 2) { |
142 | mtd_device_register(sbcmtd[i], NULL, 0); | 135 | defparts = NULL; |
136 | nr_parts = 0; | ||
143 | } else if (i == bigflash) { | 137 | } else if (i == bigflash) { |
144 | mtd_device_register(sbcmtd[i], bigflash_parts, | 138 | defparts = bigflash_parts; |
145 | ARRAY_SIZE(bigflash_parts)); | 139 | nr_parts = ARRAY_SIZE(bigflash_parts); |
146 | } else { | 140 | } else { |
147 | mtd_device_register(sbcmtd[i], smallflash_parts, | 141 | defparts = smallflash_parts; |
148 | ARRAY_SIZE(smallflash_parts)); | 142 | nr_parts = ARRAY_SIZE(smallflash_parts); |
149 | } | 143 | } |
144 | |||
145 | mtd_device_parse_register(sbcmtd[i], part_probes, 0, | ||
146 | defparts, nr_parts); | ||
150 | } | 147 | } |
151 | return 0; | 148 | return 0; |
152 | } | 149 | } |
@@ -159,12 +156,8 @@ static void __exit cleanup_sbc82xx_flash(void) | |||
159 | if (!sbcmtd[i]) | 156 | if (!sbcmtd[i]) |
160 | continue; | 157 | continue; |
161 | 158 | ||
162 | if (i<2 || sbcmtd_parts[i]) | 159 | mtd_device_unregister(sbcmtd[i]); |
163 | mtd_device_unregister(sbcmtd[i]); | ||
164 | else | ||
165 | mtd_device_unregister(sbcmtd[i]); | ||
166 | 160 | ||
167 | kfree(sbcmtd_parts[i]); | ||
168 | map_destroy(sbcmtd[i]); | 161 | map_destroy(sbcmtd[i]); |
169 | 162 | ||
170 | iounmap((void *)sbc82xx_flash_map[i].virt); | 163 | iounmap((void *)sbc82xx_flash_map[i].virt); |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index ca385697446e..ed8b5e744b12 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -426,6 +426,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
426 | new->rq->queuedata = new; | 426 | new->rq->queuedata = new; |
427 | blk_queue_logical_block_size(new->rq, tr->blksize); | 427 | blk_queue_logical_block_size(new->rq, tr->blksize); |
428 | 428 | ||
429 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, new->rq); | ||
430 | |||
429 | if (tr->discard) { | 431 | if (tr->discard) { |
430 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq); | 432 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq); |
431 | new->rq->limits.max_discard_sectors = UINT_MAX; | 433 | new->rq->limits.max_discard_sectors = UINT_MAX; |
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 3326615ad66b..7c1dc908a174 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
@@ -44,7 +44,7 @@ struct mtdblk_dev { | |||
44 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; | 44 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | static struct mutex mtdblks_lock; | 47 | static DEFINE_MUTEX(mtdblks_lock); |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * Cache stuff... | 50 | * Cache stuff... |
@@ -119,7 +119,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) | |||
119 | if (mtdblk->cache_state != STATE_DIRTY) | 119 | if (mtdblk->cache_state != STATE_DIRTY) |
120 | return 0; | 120 | return 0; |
121 | 121 | ||
122 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" " | 122 | pr_debug("mtdblock: writing cached data for \"%s\" " |
123 | "at 0x%lx, size 0x%x\n", mtd->name, | 123 | "at 0x%lx, size 0x%x\n", mtd->name, |
124 | mtdblk->cache_offset, mtdblk->cache_size); | 124 | mtdblk->cache_offset, mtdblk->cache_size); |
125 | 125 | ||
@@ -148,7 +148,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
148 | size_t retlen; | 148 | size_t retlen; |
149 | int ret; | 149 | int ret; |
150 | 150 | ||
151 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", | 151 | pr_debug("mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", |
152 | mtd->name, pos, len); | 152 | mtd->name, pos, len); |
153 | 153 | ||
154 | if (!sect_size) | 154 | if (!sect_size) |
@@ -218,7 +218,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
218 | size_t retlen; | 218 | size_t retlen; |
219 | int ret; | 219 | int ret; |
220 | 220 | ||
221 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", | 221 | pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", |
222 | mtd->name, pos, len); | 222 | mtd->name, pos, len); |
223 | 223 | ||
224 | if (!sect_size) | 224 | if (!sect_size) |
@@ -283,7 +283,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
283 | { | 283 | { |
284 | struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd); | 284 | struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd); |
285 | 285 | ||
286 | DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); | 286 | pr_debug("mtdblock_open\n"); |
287 | 287 | ||
288 | mutex_lock(&mtdblks_lock); | 288 | mutex_lock(&mtdblks_lock); |
289 | if (mtdblk->count) { | 289 | if (mtdblk->count) { |
@@ -303,7 +303,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
303 | 303 | ||
304 | mutex_unlock(&mtdblks_lock); | 304 | mutex_unlock(&mtdblks_lock); |
305 | 305 | ||
306 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); | 306 | pr_debug("ok\n"); |
307 | 307 | ||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
@@ -312,7 +312,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
312 | { | 312 | { |
313 | struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd); | 313 | struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd); |
314 | 314 | ||
315 | DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); | 315 | pr_debug("mtdblock_release\n"); |
316 | 316 | ||
317 | mutex_lock(&mtdblks_lock); | 317 | mutex_lock(&mtdblks_lock); |
318 | 318 | ||
@@ -329,7 +329,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
329 | 329 | ||
330 | mutex_unlock(&mtdblks_lock); | 330 | mutex_unlock(&mtdblks_lock); |
331 | 331 | ||
332 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); | 332 | pr_debug("ok\n"); |
333 | 333 | ||
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
@@ -389,8 +389,6 @@ static struct mtd_blktrans_ops mtdblock_tr = { | |||
389 | 389 | ||
390 | static int __init init_mtdblock(void) | 390 | static int __init init_mtdblock(void) |
391 | { | 391 | { |
392 | mutex_init(&mtdblks_lock); | ||
393 | |||
394 | return register_mtd_blktrans(&mtdblock_tr); | 392 | return register_mtd_blktrans(&mtdblock_tr); |
395 | } | 393 | } |
396 | 394 | ||
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 61086ea3cc6b..e7dc732ddabc 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -43,7 +43,7 @@ static struct vfsmount *mtd_inode_mnt __read_mostly; | |||
43 | 43 | ||
44 | /* | 44 | /* |
45 | * Data structure to hold the pointer to the mtd device as well | 45 | * Data structure to hold the pointer to the mtd device as well |
46 | * as mode information ofr various use cases. | 46 | * as mode information of various use cases. |
47 | */ | 47 | */ |
48 | struct mtd_file_info { | 48 | struct mtd_file_info { |
49 | struct mtd_info *mtd; | 49 | struct mtd_info *mtd; |
@@ -86,7 +86,7 @@ static int mtd_open(struct inode *inode, struct file *file) | |||
86 | struct mtd_file_info *mfi; | 86 | struct mtd_file_info *mfi; |
87 | struct inode *mtd_ino; | 87 | struct inode *mtd_ino; |
88 | 88 | ||
89 | DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n"); | 89 | pr_debug("MTD_open\n"); |
90 | 90 | ||
91 | /* You can't open the RO devices RW */ | 91 | /* You can't open the RO devices RW */ |
92 | if ((file->f_mode & FMODE_WRITE) && (minor & 1)) | 92 | if ((file->f_mode & FMODE_WRITE) && (minor & 1)) |
@@ -151,7 +151,7 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
151 | struct mtd_file_info *mfi = file->private_data; | 151 | struct mtd_file_info *mfi = file->private_data; |
152 | struct mtd_info *mtd = mfi->mtd; | 152 | struct mtd_info *mtd = mfi->mtd; |
153 | 153 | ||
154 | DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); | 154 | pr_debug("MTD_close\n"); |
155 | 155 | ||
156 | /* Only sync if opened RW */ | 156 | /* Only sync if opened RW */ |
157 | if ((file->f_mode & FMODE_WRITE) && mtd->sync) | 157 | if ((file->f_mode & FMODE_WRITE) && mtd->sync) |
@@ -195,7 +195,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
195 | size_t size = count; | 195 | size_t size = count; |
196 | char *kbuf; | 196 | char *kbuf; |
197 | 197 | ||
198 | DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); | 198 | pr_debug("MTD_read\n"); |
199 | 199 | ||
200 | if (*ppos + count > mtd->size) | 200 | if (*ppos + count > mtd->size) |
201 | count = mtd->size - *ppos; | 201 | count = mtd->size - *ppos; |
@@ -211,17 +211,17 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
211 | len = min_t(size_t, count, size); | 211 | len = min_t(size_t, count, size); |
212 | 212 | ||
213 | switch (mfi->mode) { | 213 | switch (mfi->mode) { |
214 | case MTD_MODE_OTP_FACTORY: | 214 | case MTD_FILE_MODE_OTP_FACTORY: |
215 | ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); | 215 | ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); |
216 | break; | 216 | break; |
217 | case MTD_MODE_OTP_USER: | 217 | case MTD_FILE_MODE_OTP_USER: |
218 | ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); | 218 | ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); |
219 | break; | 219 | break; |
220 | case MTD_MODE_RAW: | 220 | case MTD_FILE_MODE_RAW: |
221 | { | 221 | { |
222 | struct mtd_oob_ops ops; | 222 | struct mtd_oob_ops ops; |
223 | 223 | ||
224 | ops.mode = MTD_OOB_RAW; | 224 | ops.mode = MTD_OPS_RAW; |
225 | ops.datbuf = kbuf; | 225 | ops.datbuf = kbuf; |
226 | ops.oobbuf = NULL; | 226 | ops.oobbuf = NULL; |
227 | ops.len = len; | 227 | ops.len = len; |
@@ -233,16 +233,16 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
233 | default: | 233 | default: |
234 | ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); | 234 | ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); |
235 | } | 235 | } |
236 | /* Nand returns -EBADMSG on ecc errors, but it returns | 236 | /* Nand returns -EBADMSG on ECC errors, but it returns |
237 | * the data. For our userspace tools it is important | 237 | * the data. For our userspace tools it is important |
238 | * to dump areas with ecc errors ! | 238 | * to dump areas with ECC errors! |
239 | * For kernel internal usage it also might return -EUCLEAN | 239 | * For kernel internal usage it also might return -EUCLEAN |
240 | * to signal the caller that a bitflip has occurred and has | 240 | * to signal the caller that a bitflip has occurred and has |
241 | * been corrected by the ECC algorithm. | 241 | * been corrected by the ECC algorithm. |
242 | * Userspace software which accesses NAND this way | 242 | * Userspace software which accesses NAND this way |
243 | * must be aware of the fact that it deals with NAND | 243 | * must be aware of the fact that it deals with NAND |
244 | */ | 244 | */ |
245 | if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) { | 245 | if (!ret || mtd_is_bitflip_or_eccerr(ret)) { |
246 | *ppos += retlen; | 246 | *ppos += retlen; |
247 | if (copy_to_user(buf, kbuf, retlen)) { | 247 | if (copy_to_user(buf, kbuf, retlen)) { |
248 | kfree(kbuf); | 248 | kfree(kbuf); |
@@ -278,7 +278,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
278 | int ret=0; | 278 | int ret=0; |
279 | int len; | 279 | int len; |
280 | 280 | ||
281 | DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); | 281 | pr_debug("MTD_write\n"); |
282 | 282 | ||
283 | if (*ppos == mtd->size) | 283 | if (*ppos == mtd->size) |
284 | return -ENOSPC; | 284 | return -ENOSPC; |
@@ -302,10 +302,10 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
302 | } | 302 | } |
303 | 303 | ||
304 | switch (mfi->mode) { | 304 | switch (mfi->mode) { |
305 | case MTD_MODE_OTP_FACTORY: | 305 | case MTD_FILE_MODE_OTP_FACTORY: |
306 | ret = -EROFS; | 306 | ret = -EROFS; |
307 | break; | 307 | break; |
308 | case MTD_MODE_OTP_USER: | 308 | case MTD_FILE_MODE_OTP_USER: |
309 | if (!mtd->write_user_prot_reg) { | 309 | if (!mtd->write_user_prot_reg) { |
310 | ret = -EOPNOTSUPP; | 310 | ret = -EOPNOTSUPP; |
311 | break; | 311 | break; |
@@ -313,13 +313,14 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
313 | ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); | 313 | ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); |
314 | break; | 314 | break; |
315 | 315 | ||
316 | case MTD_MODE_RAW: | 316 | case MTD_FILE_MODE_RAW: |
317 | { | 317 | { |
318 | struct mtd_oob_ops ops; | 318 | struct mtd_oob_ops ops; |
319 | 319 | ||
320 | ops.mode = MTD_OOB_RAW; | 320 | ops.mode = MTD_OPS_RAW; |
321 | ops.datbuf = kbuf; | 321 | ops.datbuf = kbuf; |
322 | ops.oobbuf = NULL; | 322 | ops.oobbuf = NULL; |
323 | ops.ooboffs = 0; | ||
323 | ops.len = len; | 324 | ops.len = len; |
324 | 325 | ||
325 | ret = mtd->write_oob(mtd, *ppos, &ops); | 326 | ret = mtd->write_oob(mtd, *ppos, &ops); |
@@ -367,13 +368,13 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode) | |||
367 | if (!mtd->read_fact_prot_reg) | 368 | if (!mtd->read_fact_prot_reg) |
368 | ret = -EOPNOTSUPP; | 369 | ret = -EOPNOTSUPP; |
369 | else | 370 | else |
370 | mfi->mode = MTD_MODE_OTP_FACTORY; | 371 | mfi->mode = MTD_FILE_MODE_OTP_FACTORY; |
371 | break; | 372 | break; |
372 | case MTD_OTP_USER: | 373 | case MTD_OTP_USER: |
373 | if (!mtd->read_fact_prot_reg) | 374 | if (!mtd->read_fact_prot_reg) |
374 | ret = -EOPNOTSUPP; | 375 | ret = -EOPNOTSUPP; |
375 | else | 376 | else |
376 | mfi->mode = MTD_MODE_OTP_USER; | 377 | mfi->mode = MTD_FILE_MODE_OTP_USER; |
377 | break; | 378 | break; |
378 | default: | 379 | default: |
379 | ret = -EINVAL; | 380 | ret = -EINVAL; |
@@ -390,6 +391,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | |||
390 | uint64_t start, uint32_t length, void __user *ptr, | 391 | uint64_t start, uint32_t length, void __user *ptr, |
391 | uint32_t __user *retp) | 392 | uint32_t __user *retp) |
392 | { | 393 | { |
394 | struct mtd_file_info *mfi = file->private_data; | ||
393 | struct mtd_oob_ops ops; | 395 | struct mtd_oob_ops ops; |
394 | uint32_t retlen; | 396 | uint32_t retlen; |
395 | int ret = 0; | 397 | int ret = 0; |
@@ -409,9 +411,10 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | |||
409 | return ret; | 411 | return ret; |
410 | 412 | ||
411 | ops.ooblen = length; | 413 | ops.ooblen = length; |
412 | ops.ooboffs = start & (mtd->oobsize - 1); | 414 | ops.ooboffs = start & (mtd->writesize - 1); |
413 | ops.datbuf = NULL; | 415 | ops.datbuf = NULL; |
414 | ops.mode = MTD_OOB_PLACE; | 416 | ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW : |
417 | MTD_OPS_PLACE_OOB; | ||
415 | 418 | ||
416 | if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) | 419 | if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) |
417 | return -EINVAL; | 420 | return -EINVAL; |
@@ -420,7 +423,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | |||
420 | if (IS_ERR(ops.oobbuf)) | 423 | if (IS_ERR(ops.oobbuf)) |
421 | return PTR_ERR(ops.oobbuf); | 424 | return PTR_ERR(ops.oobbuf); |
422 | 425 | ||
423 | start &= ~((uint64_t)mtd->oobsize - 1); | 426 | start &= ~((uint64_t)mtd->writesize - 1); |
424 | ret = mtd->write_oob(mtd, start, &ops); | 427 | ret = mtd->write_oob(mtd, start, &ops); |
425 | 428 | ||
426 | if (ops.oobretlen > 0xFFFFFFFFU) | 429 | if (ops.oobretlen > 0xFFFFFFFFU) |
@@ -433,9 +436,11 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | |||
433 | return ret; | 436 | return ret; |
434 | } | 437 | } |
435 | 438 | ||
436 | static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, | 439 | static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, |
437 | uint32_t length, void __user *ptr, uint32_t __user *retp) | 440 | uint64_t start, uint32_t length, void __user *ptr, |
441 | uint32_t __user *retp) | ||
438 | { | 442 | { |
443 | struct mtd_file_info *mfi = file->private_data; | ||
439 | struct mtd_oob_ops ops; | 444 | struct mtd_oob_ops ops; |
440 | int ret = 0; | 445 | int ret = 0; |
441 | 446 | ||
@@ -451,9 +456,10 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, | |||
451 | return ret; | 456 | return ret; |
452 | 457 | ||
453 | ops.ooblen = length; | 458 | ops.ooblen = length; |
454 | ops.ooboffs = start & (mtd->oobsize - 1); | 459 | ops.ooboffs = start & (mtd->writesize - 1); |
455 | ops.datbuf = NULL; | 460 | ops.datbuf = NULL; |
456 | ops.mode = MTD_OOB_PLACE; | 461 | ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW : |
462 | MTD_OPS_PLACE_OOB; | ||
457 | 463 | ||
458 | if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) | 464 | if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) |
459 | return -EINVAL; | 465 | return -EINVAL; |
@@ -462,7 +468,7 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, | |||
462 | if (!ops.oobbuf) | 468 | if (!ops.oobbuf) |
463 | return -ENOMEM; | 469 | return -ENOMEM; |
464 | 470 | ||
465 | start &= ~((uint64_t)mtd->oobsize - 1); | 471 | start &= ~((uint64_t)mtd->writesize - 1); |
466 | ret = mtd->read_oob(mtd, start, &ops); | 472 | ret = mtd->read_oob(mtd, start, &ops); |
467 | 473 | ||
468 | if (put_user(ops.oobretlen, retp)) | 474 | if (put_user(ops.oobretlen, retp)) |
@@ -472,13 +478,29 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, | |||
472 | ret = -EFAULT; | 478 | ret = -EFAULT; |
473 | 479 | ||
474 | kfree(ops.oobbuf); | 480 | kfree(ops.oobbuf); |
481 | |||
482 | /* | ||
483 | * NAND returns -EBADMSG on ECC errors, but it returns the OOB | ||
484 | * data. For our userspace tools it is important to dump areas | ||
485 | * with ECC errors! | ||
486 | * For kernel internal usage it also might return -EUCLEAN | ||
487 | * to signal the caller that a bitflip has occured and has | ||
488 | * been corrected by the ECC algorithm. | ||
489 | * | ||
490 | * Note: currently the standard NAND function, nand_read_oob_std, | ||
491 | * does not calculate ECC for the OOB area, so do not rely on | ||
492 | * this behavior unless you have replaced it with your own. | ||
493 | */ | ||
494 | if (mtd_is_bitflip_or_eccerr(ret)) | ||
495 | return 0; | ||
496 | |||
475 | return ret; | 497 | return ret; |
476 | } | 498 | } |
477 | 499 | ||
478 | /* | 500 | /* |
479 | * Copies (and truncates, if necessary) data from the larger struct, | 501 | * Copies (and truncates, if necessary) data from the larger struct, |
480 | * nand_ecclayout, to the smaller, deprecated layout struct, | 502 | * nand_ecclayout, to the smaller, deprecated layout struct, |
481 | * nand_ecclayout_user. This is necessary only to suppport the deprecated | 503 | * nand_ecclayout_user. This is necessary only to support the deprecated |
482 | * API ioctl ECCGETLAYOUT while allowing all new functionality to use | 504 | * API ioctl ECCGETLAYOUT while allowing all new functionality to use |
483 | * nand_ecclayout flexibly (i.e. the struct may change size in new | 505 | * nand_ecclayout flexibly (i.e. the struct may change size in new |
484 | * releases without requiring major rewrites). | 506 | * releases without requiring major rewrites). |
@@ -544,6 +566,55 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd, | |||
544 | } | 566 | } |
545 | } | 567 | } |
546 | 568 | ||
569 | static int mtd_write_ioctl(struct mtd_info *mtd, | ||
570 | struct mtd_write_req __user *argp) | ||
571 | { | ||
572 | struct mtd_write_req req; | ||
573 | struct mtd_oob_ops ops; | ||
574 | void __user *usr_data, *usr_oob; | ||
575 | int ret; | ||
576 | |||
577 | if (copy_from_user(&req, argp, sizeof(req)) || | ||
578 | !access_ok(VERIFY_READ, req.usr_data, req.len) || | ||
579 | !access_ok(VERIFY_READ, req.usr_oob, req.ooblen)) | ||
580 | return -EFAULT; | ||
581 | if (!mtd->write_oob) | ||
582 | return -EOPNOTSUPP; | ||
583 | |||
584 | ops.mode = req.mode; | ||
585 | ops.len = (size_t)req.len; | ||
586 | ops.ooblen = (size_t)req.ooblen; | ||
587 | ops.ooboffs = 0; | ||
588 | |||
589 | usr_data = (void __user *)(uintptr_t)req.usr_data; | ||
590 | usr_oob = (void __user *)(uintptr_t)req.usr_oob; | ||
591 | |||
592 | if (req.usr_data) { | ||
593 | ops.datbuf = memdup_user(usr_data, ops.len); | ||
594 | if (IS_ERR(ops.datbuf)) | ||
595 | return PTR_ERR(ops.datbuf); | ||
596 | } else { | ||
597 | ops.datbuf = NULL; | ||
598 | } | ||
599 | |||
600 | if (req.usr_oob) { | ||
601 | ops.oobbuf = memdup_user(usr_oob, ops.ooblen); | ||
602 | if (IS_ERR(ops.oobbuf)) { | ||
603 | kfree(ops.datbuf); | ||
604 | return PTR_ERR(ops.oobbuf); | ||
605 | } | ||
606 | } else { | ||
607 | ops.oobbuf = NULL; | ||
608 | } | ||
609 | |||
610 | ret = mtd->write_oob(mtd, (loff_t)req.start, &ops); | ||
611 | |||
612 | kfree(ops.datbuf); | ||
613 | kfree(ops.oobbuf); | ||
614 | |||
615 | return ret; | ||
616 | } | ||
617 | |||
547 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | 618 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) |
548 | { | 619 | { |
549 | struct mtd_file_info *mfi = file->private_data; | 620 | struct mtd_file_info *mfi = file->private_data; |
@@ -553,7 +624,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
553 | u_long size; | 624 | u_long size; |
554 | struct mtd_info_user info; | 625 | struct mtd_info_user info; |
555 | 626 | ||
556 | DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n"); | 627 | pr_debug("MTD_ioctl\n"); |
557 | 628 | ||
558 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; | 629 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; |
559 | if (cmd & IOC_IN) { | 630 | if (cmd & IOC_IN) { |
@@ -601,8 +672,8 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
601 | info.erasesize = mtd->erasesize; | 672 | info.erasesize = mtd->erasesize; |
602 | info.writesize = mtd->writesize; | 673 | info.writesize = mtd->writesize; |
603 | info.oobsize = mtd->oobsize; | 674 | info.oobsize = mtd->oobsize; |
604 | /* The below fields are obsolete */ | 675 | /* The below field is obsolete */ |
605 | info.ecctype = -1; | 676 | info.padding = 0; |
606 | if (copy_to_user(argp, &info, sizeof(struct mtd_info_user))) | 677 | if (copy_to_user(argp, &info, sizeof(struct mtd_info_user))) |
607 | return -EFAULT; | 678 | return -EFAULT; |
608 | break; | 679 | break; |
@@ -698,7 +769,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
698 | if (copy_from_user(&buf, argp, sizeof(buf))) | 769 | if (copy_from_user(&buf, argp, sizeof(buf))) |
699 | ret = -EFAULT; | 770 | ret = -EFAULT; |
700 | else | 771 | else |
701 | ret = mtd_do_readoob(mtd, buf.start, buf.length, | 772 | ret = mtd_do_readoob(file, mtd, buf.start, buf.length, |
702 | buf.ptr, &buf_user->start); | 773 | buf.ptr, &buf_user->start); |
703 | break; | 774 | break; |
704 | } | 775 | } |
@@ -725,12 +796,19 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
725 | if (copy_from_user(&buf, argp, sizeof(buf))) | 796 | if (copy_from_user(&buf, argp, sizeof(buf))) |
726 | ret = -EFAULT; | 797 | ret = -EFAULT; |
727 | else | 798 | else |
728 | ret = mtd_do_readoob(mtd, buf.start, buf.length, | 799 | ret = mtd_do_readoob(file, mtd, buf.start, buf.length, |
729 | (void __user *)(uintptr_t)buf.usr_ptr, | 800 | (void __user *)(uintptr_t)buf.usr_ptr, |
730 | &buf_user->length); | 801 | &buf_user->length); |
731 | break; | 802 | break; |
732 | } | 803 | } |
733 | 804 | ||
805 | case MEMWRITE: | ||
806 | { | ||
807 | ret = mtd_write_ioctl(mtd, | ||
808 | (struct mtd_write_req __user *)arg); | ||
809 | break; | ||
810 | } | ||
811 | |||
734 | case MEMLOCK: | 812 | case MEMLOCK: |
735 | { | 813 | { |
736 | struct erase_info_user einfo; | 814 | struct erase_info_user einfo; |
@@ -827,7 +905,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
827 | if (copy_from_user(&mode, argp, sizeof(int))) | 905 | if (copy_from_user(&mode, argp, sizeof(int))) |
828 | return -EFAULT; | 906 | return -EFAULT; |
829 | 907 | ||
830 | mfi->mode = MTD_MODE_NORMAL; | 908 | mfi->mode = MTD_FILE_MODE_NORMAL; |
831 | 909 | ||
832 | ret = otp_select_filemode(mfi, mode); | 910 | ret = otp_select_filemode(mfi, mode); |
833 | 911 | ||
@@ -843,11 +921,11 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
843 | return -ENOMEM; | 921 | return -ENOMEM; |
844 | ret = -EOPNOTSUPP; | 922 | ret = -EOPNOTSUPP; |
845 | switch (mfi->mode) { | 923 | switch (mfi->mode) { |
846 | case MTD_MODE_OTP_FACTORY: | 924 | case MTD_FILE_MODE_OTP_FACTORY: |
847 | if (mtd->get_fact_prot_info) | 925 | if (mtd->get_fact_prot_info) |
848 | ret = mtd->get_fact_prot_info(mtd, buf, 4096); | 926 | ret = mtd->get_fact_prot_info(mtd, buf, 4096); |
849 | break; | 927 | break; |
850 | case MTD_MODE_OTP_USER: | 928 | case MTD_FILE_MODE_OTP_USER: |
851 | if (mtd->get_user_prot_info) | 929 | if (mtd->get_user_prot_info) |
852 | ret = mtd->get_user_prot_info(mtd, buf, 4096); | 930 | ret = mtd->get_user_prot_info(mtd, buf, 4096); |
853 | break; | 931 | break; |
@@ -871,7 +949,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
871 | { | 949 | { |
872 | struct otp_info oinfo; | 950 | struct otp_info oinfo; |
873 | 951 | ||
874 | if (mfi->mode != MTD_MODE_OTP_USER) | 952 | if (mfi->mode != MTD_FILE_MODE_OTP_USER) |
875 | return -EINVAL; | 953 | return -EINVAL; |
876 | if (copy_from_user(&oinfo, argp, sizeof(oinfo))) | 954 | if (copy_from_user(&oinfo, argp, sizeof(oinfo))) |
877 | return -EFAULT; | 955 | return -EFAULT; |
@@ -882,7 +960,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
882 | } | 960 | } |
883 | #endif | 961 | #endif |
884 | 962 | ||
885 | /* This ioctl is being deprecated - it truncates the ecc layout */ | 963 | /* This ioctl is being deprecated - it truncates the ECC layout */ |
886 | case ECCGETLAYOUT: | 964 | case ECCGETLAYOUT: |
887 | { | 965 | { |
888 | struct nand_ecclayout_user *usrlay; | 966 | struct nand_ecclayout_user *usrlay; |
@@ -915,17 +993,17 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
915 | mfi->mode = 0; | 993 | mfi->mode = 0; |
916 | 994 | ||
917 | switch(arg) { | 995 | switch(arg) { |
918 | case MTD_MODE_OTP_FACTORY: | 996 | case MTD_FILE_MODE_OTP_FACTORY: |
919 | case MTD_MODE_OTP_USER: | 997 | case MTD_FILE_MODE_OTP_USER: |
920 | ret = otp_select_filemode(mfi, arg); | 998 | ret = otp_select_filemode(mfi, arg); |
921 | break; | 999 | break; |
922 | 1000 | ||
923 | case MTD_MODE_RAW: | 1001 | case MTD_FILE_MODE_RAW: |
924 | if (!mtd->read_oob || !mtd->write_oob) | 1002 | if (!mtd->read_oob || !mtd->write_oob) |
925 | return -EOPNOTSUPP; | 1003 | return -EOPNOTSUPP; |
926 | mfi->mode = arg; | 1004 | mfi->mode = arg; |
927 | 1005 | ||
928 | case MTD_MODE_NORMAL: | 1006 | case MTD_FILE_MODE_NORMAL: |
929 | break; | 1007 | break; |
930 | default: | 1008 | default: |
931 | ret = -EINVAL; | 1009 | ret = -EINVAL; |
@@ -1011,7 +1089,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, | |||
1011 | if (copy_from_user(&buf, argp, sizeof(buf))) | 1089 | if (copy_from_user(&buf, argp, sizeof(buf))) |
1012 | ret = -EFAULT; | 1090 | ret = -EFAULT; |
1013 | else | 1091 | else |
1014 | ret = mtd_do_readoob(mtd, buf.start, | 1092 | ret = mtd_do_readoob(file, mtd, buf.start, |
1015 | buf.length, compat_ptr(buf.ptr), | 1093 | buf.length, compat_ptr(buf.ptr), |
1016 | &buf_user->start); | 1094 | &buf_user->start); |
1017 | break; | 1095 | break; |
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index e601672a5305..6df4d4d4eb92 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -95,10 +95,10 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
95 | 95 | ||
96 | /* Save information about bitflips! */ | 96 | /* Save information about bitflips! */ |
97 | if (unlikely(err)) { | 97 | if (unlikely(err)) { |
98 | if (err == -EBADMSG) { | 98 | if (mtd_is_eccerr(err)) { |
99 | mtd->ecc_stats.failed++; | 99 | mtd->ecc_stats.failed++; |
100 | ret = err; | 100 | ret = err; |
101 | } else if (err == -EUCLEAN) { | 101 | } else if (mtd_is_bitflip(err)) { |
102 | mtd->ecc_stats.corrected++; | 102 | mtd->ecc_stats.corrected++; |
103 | /* Do not overwrite -EBADMSG !! */ | 103 | /* Do not overwrite -EBADMSG !! */ |
104 | if (!ret) | 104 | if (!ret) |
@@ -279,10 +279,10 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) | |||
279 | 279 | ||
280 | /* Save information about bitflips! */ | 280 | /* Save information about bitflips! */ |
281 | if (unlikely(err)) { | 281 | if (unlikely(err)) { |
282 | if (err == -EBADMSG) { | 282 | if (mtd_is_eccerr(err)) { |
283 | mtd->ecc_stats.failed++; | 283 | mtd->ecc_stats.failed++; |
284 | ret = err; | 284 | ret = err; |
285 | } else if (err == -EUCLEAN) { | 285 | } else if (mtd_is_bitflip(err)) { |
286 | mtd->ecc_stats.corrected++; | 286 | mtd->ecc_stats.corrected++; |
287 | /* Do not overwrite -EBADMSG !! */ | 287 | /* Do not overwrite -EBADMSG !! */ |
288 | if (!ret) | 288 | if (!ret) |
@@ -770,7 +770,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
770 | 770 | ||
771 | /* | 771 | /* |
772 | * Set up the new "super" device's MTD object structure, check for | 772 | * Set up the new "super" device's MTD object structure, check for |
773 | * incompatibilites between the subdevices. | 773 | * incompatibilities between the subdevices. |
774 | */ | 774 | */ |
775 | concat->mtd.type = subdev[0]->type; | 775 | concat->mtd.type = subdev[0]->type; |
776 | concat->mtd.flags = subdev[0]->flags; | 776 | concat->mtd.flags = subdev[0]->flags; |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index c510aff289a8..b01993ea260e 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -362,7 +362,7 @@ int add_mtd_device(struct mtd_info *mtd) | |||
362 | MTD_DEVT(i) + 1, | 362 | MTD_DEVT(i) + 1, |
363 | NULL, "mtd%dro", i); | 363 | NULL, "mtd%dro", i); |
364 | 364 | ||
365 | DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name); | 365 | pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name); |
366 | /* No need to get a refcount on the module containing | 366 | /* No need to get a refcount on the module containing |
367 | the notifier, since we hold the mtd_table_mutex */ | 367 | the notifier, since we hold the mtd_table_mutex */ |
368 | list_for_each_entry(not, &mtd_notifiers, list) | 368 | list_for_each_entry(not, &mtd_notifiers, list) |
@@ -429,27 +429,63 @@ out_error: | |||
429 | } | 429 | } |
430 | 430 | ||
431 | /** | 431 | /** |
432 | * mtd_device_register - register an MTD device. | 432 | * mtd_device_parse_register - parse partitions and register an MTD device. |
433 | * | 433 | * |
434 | * @master: the MTD device to register | 434 | * @mtd: the MTD device to register |
435 | * @parts: the partitions to register - only valid if nr_parts > 0 | 435 | * @types: the list of MTD partition probes to try, see |
436 | * @nr_parts: the number of partitions in parts. If zero then the full MTD | 436 | * 'parse_mtd_partitions()' for more information |
437 | * device is registered | 437 | * @parser_data: MTD partition parser-specific data |
438 | * @parts: fallback partition information to register, if parsing fails; | ||
439 | * only valid if %nr_parts > %0 | ||
440 | * @nr_parts: the number of partitions in parts, if zero then the full | ||
441 | * MTD device is registered if no partition info is found | ||
438 | * | 442 | * |
439 | * Register an MTD device with the system and optionally, a number of | 443 | * This function aggregates MTD partitions parsing (done by |
440 | * partitions. If nr_parts is 0 then the whole device is registered, otherwise | 444 | * 'parse_mtd_partitions()') and MTD device and partitions registering. It |
441 | * only the partitions are registered. To register both the full device *and* | 445 | * basically follows the most common pattern found in many MTD drivers: |
442 | * the partitions, call mtd_device_register() twice, once with nr_parts == 0 | 446 | * |
443 | * and once equal to the number of partitions. | 447 | * * It first tries to probe partitions on MTD device @mtd using parsers |
448 | * specified in @types (if @types is %NULL, then the default list of parsers | ||
449 | * is used, see 'parse_mtd_partitions()' for more information). If none are | ||
450 | * found this functions tries to fallback to information specified in | ||
451 | * @parts/@nr_parts. | ||
452 | * * If any partitioning info was found, this function registers the found | ||
453 | * partitions. | ||
454 | * * If no partitions were found this function just registers the MTD device | ||
455 | * @mtd and exits. | ||
456 | * | ||
457 | * Returns zero in case of success and a negative error code in case of failure. | ||
444 | */ | 458 | */ |
445 | int mtd_device_register(struct mtd_info *master, | 459 | int mtd_device_parse_register(struct mtd_info *mtd, const char **types, |
446 | const struct mtd_partition *parts, | 460 | struct mtd_part_parser_data *parser_data, |
447 | int nr_parts) | 461 | const struct mtd_partition *parts, |
462 | int nr_parts) | ||
448 | { | 463 | { |
449 | return parts ? add_mtd_partitions(master, parts, nr_parts) : | 464 | int err; |
450 | add_mtd_device(master); | 465 | struct mtd_partition *real_parts; |
466 | |||
467 | err = parse_mtd_partitions(mtd, types, &real_parts, parser_data); | ||
468 | if (err <= 0 && nr_parts && parts) { | ||
469 | real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, | ||
470 | GFP_KERNEL); | ||
471 | if (!real_parts) | ||
472 | err = -ENOMEM; | ||
473 | else | ||
474 | err = nr_parts; | ||
475 | } | ||
476 | |||
477 | if (err > 0) { | ||
478 | err = add_mtd_partitions(mtd, real_parts, err); | ||
479 | kfree(real_parts); | ||
480 | } else if (err == 0) { | ||
481 | err = add_mtd_device(mtd); | ||
482 | if (err == 1) | ||
483 | err = -ENODEV; | ||
484 | } | ||
485 | |||
486 | return err; | ||
451 | } | 487 | } |
452 | EXPORT_SYMBOL_GPL(mtd_device_register); | 488 | EXPORT_SYMBOL_GPL(mtd_device_parse_register); |
453 | 489 | ||
454 | /** | 490 | /** |
455 | * mtd_device_unregister - unregister an existing MTD device. | 491 | * mtd_device_unregister - unregister an existing MTD device. |
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h index 0ed6126b4c1f..961a38408542 100644 --- a/drivers/mtd/mtdcore.h +++ b/drivers/mtd/mtdcore.h | |||
@@ -15,6 +15,9 @@ extern int del_mtd_device(struct mtd_info *mtd); | |||
15 | extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, | 15 | extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, |
16 | int); | 16 | int); |
17 | extern int del_mtd_partitions(struct mtd_info *); | 17 | extern int del_mtd_partitions(struct mtd_info *); |
18 | extern int parse_mtd_partitions(struct mtd_info *master, const char **types, | ||
19 | struct mtd_partition **pparts, | ||
20 | struct mtd_part_parser_data *data); | ||
18 | 21 | ||
19 | #define mtd_for_each_device(mtd) \ | 22 | #define mtd_for_each_device(mtd) \ |
20 | for ((mtd) = __mtd_next_device(0); \ | 23 | for ((mtd) = __mtd_next_device(0); \ |
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index e3e40f440323..1e2fa6236705 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c | |||
@@ -258,7 +258,7 @@ static void find_next_position(struct mtdoops_context *cxt) | |||
258 | ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE, | 258 | ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE, |
259 | &retlen, (u_char *) &count[0]); | 259 | &retlen, (u_char *) &count[0]); |
260 | if (retlen != MTDOOPS_HEADER_SIZE || | 260 | if (retlen != MTDOOPS_HEADER_SIZE || |
261 | (ret < 0 && ret != -EUCLEAN)) { | 261 | (ret < 0 && !mtd_is_bitflip(ret))) { |
262 | printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n", | 262 | printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n", |
263 | page * record_size, retlen, | 263 | page * record_size, retlen, |
264 | MTDOOPS_HEADER_SIZE, ret); | 264 | MTDOOPS_HEADER_SIZE, ret); |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 630be3e7da04..a0bd2de4752b 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -73,9 +73,9 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
73 | res = part->master->read(part->master, from + part->offset, | 73 | res = part->master->read(part->master, from + part->offset, |
74 | len, retlen, buf); | 74 | len, retlen, buf); |
75 | if (unlikely(res)) { | 75 | if (unlikely(res)) { |
76 | if (res == -EUCLEAN) | 76 | if (mtd_is_bitflip(res)) |
77 | mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; | 77 | mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; |
78 | if (res == -EBADMSG) | 78 | if (mtd_is_eccerr(res)) |
79 | mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; | 79 | mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; |
80 | } | 80 | } |
81 | return res; | 81 | return res; |
@@ -130,7 +130,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, | |||
130 | if (ops->oobbuf) { | 130 | if (ops->oobbuf) { |
131 | size_t len, pages; | 131 | size_t len, pages; |
132 | 132 | ||
133 | if (ops->mode == MTD_OOB_AUTO) | 133 | if (ops->mode == MTD_OPS_AUTO_OOB) |
134 | len = mtd->oobavail; | 134 | len = mtd->oobavail; |
135 | else | 135 | else |
136 | len = mtd->oobsize; | 136 | len = mtd->oobsize; |
@@ -142,9 +142,9 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, | |||
142 | 142 | ||
143 | res = part->master->read_oob(part->master, from + part->offset, ops); | 143 | res = part->master->read_oob(part->master, from + part->offset, ops); |
144 | if (unlikely(res)) { | 144 | if (unlikely(res)) { |
145 | if (res == -EUCLEAN) | 145 | if (mtd_is_bitflip(res)) |
146 | mtd->ecc_stats.corrected++; | 146 | mtd->ecc_stats.corrected++; |
147 | if (res == -EBADMSG) | 147 | if (mtd_is_eccerr(res)) |
148 | mtd->ecc_stats.failed++; | 148 | mtd->ecc_stats.failed++; |
149 | } | 149 | } |
150 | return res; | 150 | return res; |
@@ -479,6 +479,19 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, | |||
479 | (unsigned long long)cur_offset, (unsigned long long)slave->offset); | 479 | (unsigned long long)cur_offset, (unsigned long long)slave->offset); |
480 | } | 480 | } |
481 | } | 481 | } |
482 | if (slave->offset == MTDPART_OFS_RETAIN) { | ||
483 | slave->offset = cur_offset; | ||
484 | if (master->size - slave->offset >= slave->mtd.size) { | ||
485 | slave->mtd.size = master->size - slave->offset | ||
486 | - slave->mtd.size; | ||
487 | } else { | ||
488 | printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n", | ||
489 | part->name, master->size - slave->offset, | ||
490 | slave->mtd.size); | ||
491 | /* register to preserve ordering */ | ||
492 | goto out_register; | ||
493 | } | ||
494 | } | ||
482 | if (slave->mtd.size == MTDPART_SIZ_FULL) | 495 | if (slave->mtd.size == MTDPART_SIZ_FULL) |
483 | slave->mtd.size = master->size - slave->offset; | 496 | slave->mtd.size = master->size - slave->offset; |
484 | 497 | ||
@@ -693,6 +706,8 @@ static struct mtd_part_parser *get_partition_parser(const char *name) | |||
693 | return ret; | 706 | return ret; |
694 | } | 707 | } |
695 | 708 | ||
709 | #define put_partition_parser(p) do { module_put((p)->owner); } while (0) | ||
710 | |||
696 | int register_mtd_parser(struct mtd_part_parser *p) | 711 | int register_mtd_parser(struct mtd_part_parser *p) |
697 | { | 712 | { |
698 | spin_lock(&part_parser_lock); | 713 | spin_lock(&part_parser_lock); |
@@ -712,19 +727,51 @@ int deregister_mtd_parser(struct mtd_part_parser *p) | |||
712 | } | 727 | } |
713 | EXPORT_SYMBOL_GPL(deregister_mtd_parser); | 728 | EXPORT_SYMBOL_GPL(deregister_mtd_parser); |
714 | 729 | ||
730 | /* | ||
731 | * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you | ||
732 | * are changing this array! | ||
733 | */ | ||
734 | static const char *default_mtd_part_types[] = { | ||
735 | "cmdlinepart", | ||
736 | "ofpart", | ||
737 | NULL | ||
738 | }; | ||
739 | |||
740 | /** | ||
741 | * parse_mtd_partitions - parse MTD partitions | ||
742 | * @master: the master partition (describes whole MTD device) | ||
743 | * @types: names of partition parsers to try or %NULL | ||
744 | * @pparts: array of partitions found is returned here | ||
745 | * @data: MTD partition parser-specific data | ||
746 | * | ||
747 | * This function tries to find partition on MTD device @master. It uses MTD | ||
748 | * partition parsers, specified in @types. However, if @types is %NULL, then | ||
749 | * the default list of parsers is used. The default list contains only the | ||
750 | * "cmdlinepart" and "ofpart" parsers ATM. | ||
751 | * | ||
752 | * This function may return: | ||
753 | * o a negative error code in case of failure | ||
754 | * o zero if no partitions were found | ||
755 | * o a positive number of found partitions, in which case on exit @pparts will | ||
756 | * point to an array containing this number of &struct mtd_info objects. | ||
757 | */ | ||
715 | int parse_mtd_partitions(struct mtd_info *master, const char **types, | 758 | int parse_mtd_partitions(struct mtd_info *master, const char **types, |
716 | struct mtd_partition **pparts, unsigned long origin) | 759 | struct mtd_partition **pparts, |
760 | struct mtd_part_parser_data *data) | ||
717 | { | 761 | { |
718 | struct mtd_part_parser *parser; | 762 | struct mtd_part_parser *parser; |
719 | int ret = 0; | 763 | int ret = 0; |
720 | 764 | ||
765 | if (!types) | ||
766 | types = default_mtd_part_types; | ||
767 | |||
721 | for ( ; ret <= 0 && *types; types++) { | 768 | for ( ; ret <= 0 && *types; types++) { |
722 | parser = get_partition_parser(*types); | 769 | parser = get_partition_parser(*types); |
723 | if (!parser && !request_module("%s", *types)) | 770 | if (!parser && !request_module("%s", *types)) |
724 | parser = get_partition_parser(*types); | 771 | parser = get_partition_parser(*types); |
725 | if (!parser) | 772 | if (!parser) |
726 | continue; | 773 | continue; |
727 | ret = (*parser->parse_fn)(master, pparts, origin); | 774 | ret = (*parser->parse_fn)(master, pparts, data); |
728 | if (ret > 0) { | 775 | if (ret > 0) { |
729 | printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", | 776 | printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", |
730 | ret, parser->name, master->name); | 777 | ret, parser->name, master->name); |
@@ -733,7 +780,6 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, | |||
733 | } | 780 | } |
734 | return ret; | 781 | return ret; |
735 | } | 782 | } |
736 | EXPORT_SYMBOL_GPL(parse_mtd_partitions); | ||
737 | 783 | ||
738 | int mtd_is_partition(struct mtd_info *mtd) | 784 | int mtd_is_partition(struct mtd_info *mtd) |
739 | { | 785 | { |
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 89f8e66448ab..a90bfe79916d 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c | |||
@@ -27,12 +27,12 @@ static int get_sb_mtd_compare(struct super_block *sb, void *_mtd) | |||
27 | struct mtd_info *mtd = _mtd; | 27 | struct mtd_info *mtd = _mtd; |
28 | 28 | ||
29 | if (sb->s_mtd == mtd) { | 29 | if (sb->s_mtd == mtd) { |
30 | DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n", | 30 | pr_debug("MTDSB: Match on device %d (\"%s\")\n", |
31 | mtd->index, mtd->name); | 31 | mtd->index, mtd->name); |
32 | return 1; | 32 | return 1; |
33 | } | 33 | } |
34 | 34 | ||
35 | DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n", | 35 | pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n", |
36 | sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name); | 36 | sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name); |
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
@@ -71,7 +71,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags, | |||
71 | goto already_mounted; | 71 | goto already_mounted; |
72 | 72 | ||
73 | /* fresh new superblock */ | 73 | /* fresh new superblock */ |
74 | DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n", | 74 | pr_debug("MTDSB: New superblock for device %d (\"%s\")\n", |
75 | mtd->index, mtd->name); | 75 | mtd->index, mtd->name); |
76 | 76 | ||
77 | sb->s_flags = flags; | 77 | sb->s_flags = flags; |
@@ -88,7 +88,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags, | |||
88 | 88 | ||
89 | /* new mountpoint for an already mounted superblock */ | 89 | /* new mountpoint for an already mounted superblock */ |
90 | already_mounted: | 90 | already_mounted: |
91 | DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n", | 91 | pr_debug("MTDSB: Device %d (\"%s\") is already mounted\n", |
92 | mtd->index, mtd->name); | 92 | mtd->index, mtd->name); |
93 | put_mtd_device(mtd); | 93 | put_mtd_device(mtd); |
94 | return dget(sb->s_root); | 94 | return dget(sb->s_root); |
@@ -109,7 +109,7 @@ static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags, | |||
109 | 109 | ||
110 | mtd = get_mtd_device(NULL, mtdnr); | 110 | mtd = get_mtd_device(NULL, mtdnr); |
111 | if (IS_ERR(mtd)) { | 111 | if (IS_ERR(mtd)) { |
112 | DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr); | 112 | pr_debug("MTDSB: Device #%u doesn't appear to exist\n", mtdnr); |
113 | return ERR_CAST(mtd); | 113 | return ERR_CAST(mtd); |
114 | } | 114 | } |
115 | 115 | ||
@@ -132,7 +132,7 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, | |||
132 | if (!dev_name) | 132 | if (!dev_name) |
133 | return ERR_PTR(-EINVAL); | 133 | return ERR_PTR(-EINVAL); |
134 | 134 | ||
135 | DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name); | 135 | pr_debug("MTDSB: dev_name \"%s\"\n", dev_name); |
136 | 136 | ||
137 | /* the preferred way of mounting in future; especially when | 137 | /* the preferred way of mounting in future; especially when |
138 | * CONFIG_BLOCK=n - we specify the underlying MTD device by number or | 138 | * CONFIG_BLOCK=n - we specify the underlying MTD device by number or |
@@ -143,7 +143,7 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, | |||
143 | struct mtd_info *mtd; | 143 | struct mtd_info *mtd; |
144 | 144 | ||
145 | /* mount by MTD device name */ | 145 | /* mount by MTD device name */ |
146 | DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n", | 146 | pr_debug("MTDSB: mtd:%%s, name \"%s\"\n", |
147 | dev_name + 4); | 147 | dev_name + 4); |
148 | 148 | ||
149 | mtd = get_mtd_device_nm(dev_name + 4); | 149 | mtd = get_mtd_device_nm(dev_name + 4); |
@@ -164,7 +164,7 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, | |||
164 | mtdnr = simple_strtoul(dev_name + 3, &endptr, 0); | 164 | mtdnr = simple_strtoul(dev_name + 3, &endptr, 0); |
165 | if (!*endptr) { | 165 | if (!*endptr) { |
166 | /* It was a valid number */ | 166 | /* It was a valid number */ |
167 | DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n", | 167 | pr_debug("MTDSB: mtd%%d, mtdnr %d\n", |
168 | mtdnr); | 168 | mtdnr); |
169 | return mount_mtd_nr(fs_type, flags, | 169 | return mount_mtd_nr(fs_type, flags, |
170 | dev_name, data, | 170 | dev_name, data, |
@@ -180,10 +180,10 @@ struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, | |||
180 | bdev = lookup_bdev(dev_name); | 180 | bdev = lookup_bdev(dev_name); |
181 | if (IS_ERR(bdev)) { | 181 | if (IS_ERR(bdev)) { |
182 | ret = PTR_ERR(bdev); | 182 | ret = PTR_ERR(bdev); |
183 | DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret); | 183 | pr_debug("MTDSB: lookup_bdev() returned %d\n", ret); |
184 | return ERR_PTR(ret); | 184 | return ERR_PTR(ret); |
185 | } | 185 | } |
186 | DEBUG(1, "MTDSB: lookup_bdev() returned 0\n"); | 186 | pr_debug("MTDSB: lookup_bdev() returned 0\n"); |
187 | 187 | ||
188 | ret = -EINVAL; | 188 | ret = -EINVAL; |
189 | 189 | ||
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index fd7885327611..bd9590c723e4 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c | |||
@@ -86,7 +86,7 @@ struct swap_eb { | |||
86 | unsigned int flags; | 86 | unsigned int flags; |
87 | unsigned int active_count; | 87 | unsigned int active_count; |
88 | unsigned int erase_count; | 88 | unsigned int erase_count; |
89 | unsigned int pad; /* speeds up pointer decremtnt */ | 89 | unsigned int pad; /* speeds up pointer decrement */ |
90 | }; | 90 | }; |
91 | 91 | ||
92 | #define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \ | 92 | #define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \ |
@@ -314,7 +314,7 @@ static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from, | |||
314 | { | 314 | { |
315 | int ret = d->mtd->read_oob(d->mtd, from, ops); | 315 | int ret = d->mtd->read_oob(d->mtd, from, ops); |
316 | 316 | ||
317 | if (ret == -EUCLEAN) | 317 | if (mtd_is_bitflip(ret)) |
318 | return ret; | 318 | return ret; |
319 | 319 | ||
320 | if (ret) { | 320 | if (ret) { |
@@ -350,11 +350,11 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) | |||
350 | ops.oobbuf = d->oob_buf; | 350 | ops.oobbuf = d->oob_buf; |
351 | ops.ooboffs = 0; | 351 | ops.ooboffs = 0; |
352 | ops.datbuf = NULL; | 352 | ops.datbuf = NULL; |
353 | ops.mode = MTD_OOB_AUTO; | 353 | ops.mode = MTD_OPS_AUTO_OOB; |
354 | 354 | ||
355 | ret = mtdswap_read_oob(d, offset, &ops); | 355 | ret = mtdswap_read_oob(d, offset, &ops); |
356 | 356 | ||
357 | if (ret && ret != -EUCLEAN) | 357 | if (ret && !mtd_is_bitflip(ret)) |
358 | return ret; | 358 | return ret; |
359 | 359 | ||
360 | data = (struct mtdswap_oobdata *)d->oob_buf; | 360 | data = (struct mtdswap_oobdata *)d->oob_buf; |
@@ -363,7 +363,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb) | |||
363 | 363 | ||
364 | if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) { | 364 | if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) { |
365 | eb->erase_count = le32_to_cpu(data->count); | 365 | eb->erase_count = le32_to_cpu(data->count); |
366 | if (ret == -EUCLEAN) | 366 | if (mtd_is_bitflip(ret)) |
367 | ret = MTDSWAP_SCANNED_BITFLIP; | 367 | ret = MTDSWAP_SCANNED_BITFLIP; |
368 | else { | 368 | else { |
369 | if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY) | 369 | if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY) |
@@ -389,7 +389,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb, | |||
389 | 389 | ||
390 | ops.ooboffs = 0; | 390 | ops.ooboffs = 0; |
391 | ops.oobbuf = (uint8_t *)&n; | 391 | ops.oobbuf = (uint8_t *)&n; |
392 | ops.mode = MTD_OOB_AUTO; | 392 | ops.mode = MTD_OPS_AUTO_OOB; |
393 | ops.datbuf = NULL; | 393 | ops.datbuf = NULL; |
394 | 394 | ||
395 | if (marker == MTDSWAP_TYPE_CLEAN) { | 395 | if (marker == MTDSWAP_TYPE_CLEAN) { |
@@ -408,7 +408,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb, | |||
408 | if (ret) { | 408 | if (ret) { |
409 | dev_warn(d->dev, "Write OOB failed for block at %08llx " | 409 | dev_warn(d->dev, "Write OOB failed for block at %08llx " |
410 | "error %d\n", offset, ret); | 410 | "error %d\n", offset, ret); |
411 | if (ret == -EIO || ret == -EBADMSG) | 411 | if (ret == -EIO || mtd_is_eccerr(ret)) |
412 | mtdswap_handle_write_error(d, eb); | 412 | mtdswap_handle_write_error(d, eb); |
413 | return ret; | 413 | return ret; |
414 | } | 414 | } |
@@ -628,7 +628,7 @@ static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page, | |||
628 | TREE_COUNT(d, CLEAN)--; | 628 | TREE_COUNT(d, CLEAN)--; |
629 | 629 | ||
630 | ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY); | 630 | ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY); |
631 | } while (ret == -EIO || ret == -EBADMSG); | 631 | } while (ret == -EIO || mtd_is_eccerr(ret)); |
632 | 632 | ||
633 | if (ret) | 633 | if (ret) |
634 | return ret; | 634 | return ret; |
@@ -678,7 +678,7 @@ retry: | |||
678 | ret = mtdswap_map_free_block(d, page, bp); | 678 | ret = mtdswap_map_free_block(d, page, bp); |
679 | eb = d->eb_data + (*bp / d->pages_per_eblk); | 679 | eb = d->eb_data + (*bp / d->pages_per_eblk); |
680 | 680 | ||
681 | if (ret == -EIO || ret == -EBADMSG) { | 681 | if (ret == -EIO || mtd_is_eccerr(ret)) { |
682 | d->curr_write = NULL; | 682 | d->curr_write = NULL; |
683 | eb->active_count--; | 683 | eb->active_count--; |
684 | d->revmap[*bp] = PAGE_UNDEF; | 684 | d->revmap[*bp] = PAGE_UNDEF; |
@@ -690,7 +690,7 @@ retry: | |||
690 | 690 | ||
691 | writepos = (loff_t)*bp << PAGE_SHIFT; | 691 | writepos = (loff_t)*bp << PAGE_SHIFT; |
692 | ret = mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf); | 692 | ret = mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf); |
693 | if (ret == -EIO || ret == -EBADMSG) { | 693 | if (ret == -EIO || mtd_is_eccerr(ret)) { |
694 | d->curr_write_pos--; | 694 | d->curr_write_pos--; |
695 | eb->active_count--; | 695 | eb->active_count--; |
696 | d->revmap[*bp] = PAGE_UNDEF; | 696 | d->revmap[*bp] = PAGE_UNDEF; |
@@ -738,7 +738,7 @@ static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock, | |||
738 | retry: | 738 | retry: |
739 | ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf); | 739 | ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf); |
740 | 740 | ||
741 | if (ret < 0 && ret != -EUCLEAN) { | 741 | if (ret < 0 && !mtd_is_bitflip(ret)) { |
742 | oldeb = d->eb_data + oldblock / d->pages_per_eblk; | 742 | oldeb = d->eb_data + oldblock / d->pages_per_eblk; |
743 | oldeb->flags |= EBLOCK_READERR; | 743 | oldeb->flags |= EBLOCK_READERR; |
744 | 744 | ||
@@ -931,7 +931,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d, | |||
931 | struct mtd_oob_ops ops; | 931 | struct mtd_oob_ops ops; |
932 | int ret; | 932 | int ret; |
933 | 933 | ||
934 | ops.mode = MTD_OOB_AUTO; | 934 | ops.mode = MTD_OPS_AUTO_OOB; |
935 | ops.len = mtd->writesize; | 935 | ops.len = mtd->writesize; |
936 | ops.ooblen = mtd->ecclayout->oobavail; | 936 | ops.ooblen = mtd->ecclayout->oobavail; |
937 | ops.ooboffs = 0; | 937 | ops.ooboffs = 0; |
@@ -1016,7 +1016,7 @@ static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background) | |||
1016 | 1016 | ||
1017 | if (ret == 0) | 1017 | if (ret == 0) |
1018 | mtdswap_rb_add(d, eb, MTDSWAP_CLEAN); | 1018 | mtdswap_rb_add(d, eb, MTDSWAP_CLEAN); |
1019 | else if (ret != -EIO && ret != -EBADMSG) | 1019 | else if (ret != -EIO && !mtd_is_eccerr(ret)) |
1020 | mtdswap_rb_add(d, eb, MTDSWAP_DIRTY); | 1020 | mtdswap_rb_add(d, eb, MTDSWAP_DIRTY); |
1021 | 1021 | ||
1022 | return 0; | 1022 | return 0; |
@@ -1164,7 +1164,7 @@ retry: | |||
1164 | ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf); | 1164 | ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf); |
1165 | 1165 | ||
1166 | d->mtd_read_count++; | 1166 | d->mtd_read_count++; |
1167 | if (ret == -EUCLEAN) { | 1167 | if (mtd_is_bitflip(ret)) { |
1168 | eb->flags |= EBLOCK_BITFLIP; | 1168 | eb->flags |= EBLOCK_BITFLIP; |
1169 | mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP); | 1169 | mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP); |
1170 | ret = 0; | 1170 | ret = 0; |
@@ -1374,11 +1374,10 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks, | |||
1374 | goto revmap_fail; | 1374 | goto revmap_fail; |
1375 | 1375 | ||
1376 | eblk_bytes = sizeof(struct swap_eb)*d->eblks; | 1376 | eblk_bytes = sizeof(struct swap_eb)*d->eblks; |
1377 | d->eb_data = vmalloc(eblk_bytes); | 1377 | d->eb_data = vzalloc(eblk_bytes); |
1378 | if (!d->eb_data) | 1378 | if (!d->eb_data) |
1379 | goto eb_data_fail; | 1379 | goto eb_data_fail; |
1380 | 1380 | ||
1381 | memset(d->eb_data, 0, eblk_bytes); | ||
1382 | for (i = 0; i < pages; i++) | 1381 | for (i = 0; i < pages; i++) |
1383 | d->page_data[i] = BLOCK_UNDEF; | 1382 | d->page_data[i] = BLOCK_UNDEF; |
1384 | 1383 | ||
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index dbfa0f7fb464..cce7b70824c3 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -83,16 +83,9 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR | |||
83 | scratch register here to enable this feature. On Intel Moorestown | 83 | scratch register here to enable this feature. On Intel Moorestown |
84 | boards, the scratch register is at 0xFF108018. | 84 | boards, the scratch register is at 0xFF108018. |
85 | 85 | ||
86 | config MTD_NAND_EDB7312 | ||
87 | tristate "Support for Cirrus Logic EBD7312 evaluation board" | ||
88 | depends on ARCH_EDB7312 | ||
89 | help | ||
90 | This enables the driver for the Cirrus Logic EBD7312 evaluation | ||
91 | board to access the onboard NAND Flash. | ||
92 | |||
93 | config MTD_NAND_H1900 | 86 | config MTD_NAND_H1900 |
94 | tristate "iPAQ H1900 flash" | 87 | tristate "iPAQ H1900 flash" |
95 | depends on ARCH_PXA | 88 | depends on ARCH_PXA && BROKEN |
96 | help | 89 | help |
97 | This enables the driver for the iPAQ h1900 flash. | 90 | This enables the driver for the iPAQ h1900 flash. |
98 | 91 | ||
@@ -116,10 +109,11 @@ config MTD_NAND_AMS_DELTA | |||
116 | Support for NAND flash on Amstrad E3 (Delta). | 109 | Support for NAND flash on Amstrad E3 (Delta). |
117 | 110 | ||
118 | config MTD_NAND_OMAP2 | 111 | config MTD_NAND_OMAP2 |
119 | tristate "NAND Flash device on OMAP2 and OMAP3" | 112 | tristate "NAND Flash device on OMAP2, OMAP3 and OMAP4" |
120 | depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3) | 113 | depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4) |
121 | help | 114 | help |
122 | Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. | 115 | Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 |
116 | platforms. | ||
123 | 117 | ||
124 | config MTD_NAND_IDS | 118 | config MTD_NAND_IDS |
125 | tristate | 119 | tristate |
@@ -423,6 +417,19 @@ config MTD_NAND_NANDSIM | |||
423 | The simulator may simulate various NAND flash chips for the | 417 | The simulator may simulate various NAND flash chips for the |
424 | MTD nand layer. | 418 | MTD nand layer. |
425 | 419 | ||
420 | config MTD_NAND_GPMI_NAND | ||
421 | bool "GPMI NAND Flash Controller driver" | ||
422 | depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28) | ||
423 | select MTD_PARTITIONS | ||
424 | select MTD_CMDLINE_PARTS | ||
425 | help | ||
426 | Enables NAND Flash support for IMX23 or IMX28. | ||
427 | The GPMI controller is very powerful, with the help of BCH | ||
428 | module, it can do the hardware ECC. The GPMI supports several | ||
429 | NAND flashs at the same time. The GPMI may conflicts with other | ||
430 | block, such as SD card. So pay attention to it when you enable | ||
431 | the GPMI. | ||
432 | |||
426 | config MTD_NAND_PLATFORM | 433 | config MTD_NAND_PLATFORM |
427 | tristate "Support for generic platform NAND driver" | 434 | tristate "Support for generic platform NAND driver" |
428 | help | 435 | help |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 5745d831168e..618f4ba23699 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -13,7 +13,6 @@ obj-$(CONFIG_MTD_NAND_SPIA) += spia.o | |||
13 | obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o | 13 | obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o |
14 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o | 14 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o |
15 | obj-$(CONFIG_MTD_NAND_DENALI) += denali.o | 15 | obj-$(CONFIG_MTD_NAND_DENALI) += denali.o |
16 | obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o | ||
17 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o | 16 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o |
18 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o | 17 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o |
19 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | 18 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o |
@@ -49,5 +48,6 @@ obj-$(CONFIG_MTD_NAND_BCM_UMI) += bcm_umi_nand.o nand_bcm_umi.o | |||
49 | obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o | 48 | obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o |
50 | obj-$(CONFIG_MTD_NAND_RICOH) += r852.o | 49 | obj-$(CONFIG_MTD_NAND_RICOH) += r852.o |
51 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o | 50 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o |
51 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ | ||
52 | 52 | ||
53 | nand-objs := nand_base.o nand_bbt.o | 53 | nand-objs := nand_base.o nand_bbt.o |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 55da20ccc7a8..23e5d77c39fc 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -161,37 +161,6 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) | |||
161 | !!host->board->rdy_pin_active_low; | 161 | !!host->board->rdy_pin_active_low; |
162 | } | 162 | } |
163 | 163 | ||
164 | /* | ||
165 | * Minimal-overhead PIO for data access. | ||
166 | */ | ||
167 | static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) | ||
168 | { | ||
169 | struct nand_chip *nand_chip = mtd->priv; | ||
170 | |||
171 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); | ||
172 | } | ||
173 | |||
174 | static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) | ||
175 | { | ||
176 | struct nand_chip *nand_chip = mtd->priv; | ||
177 | |||
178 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); | ||
179 | } | ||
180 | |||
181 | static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) | ||
182 | { | ||
183 | struct nand_chip *nand_chip = mtd->priv; | ||
184 | |||
185 | __raw_writesb(nand_chip->IO_ADDR_W, buf, len); | ||
186 | } | ||
187 | |||
188 | static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) | ||
189 | { | ||
190 | struct nand_chip *nand_chip = mtd->priv; | ||
191 | |||
192 | __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); | ||
193 | } | ||
194 | |||
195 | static void dma_complete_func(void *completion) | 164 | static void dma_complete_func(void *completion) |
196 | { | 165 | { |
197 | complete(completion); | 166 | complete(completion); |
@@ -266,33 +235,27 @@ err_buf: | |||
266 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | 235 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) |
267 | { | 236 | { |
268 | struct nand_chip *chip = mtd->priv; | 237 | struct nand_chip *chip = mtd->priv; |
269 | struct atmel_nand_host *host = chip->priv; | ||
270 | 238 | ||
271 | if (use_dma && len > mtd->oobsize) | 239 | if (use_dma && len > mtd->oobsize) |
272 | /* only use DMA for bigger than oob size: better performances */ | 240 | /* only use DMA for bigger than oob size: better performances */ |
273 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) | 241 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) |
274 | return; | 242 | return; |
275 | 243 | ||
276 | if (host->board->bus_width_16) | 244 | /* if no DMA operation possible, use PIO */ |
277 | atmel_read_buf16(mtd, buf, len); | 245 | memcpy_fromio(buf, chip->IO_ADDR_R, len); |
278 | else | ||
279 | atmel_read_buf8(mtd, buf, len); | ||
280 | } | 246 | } |
281 | 247 | ||
282 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | 248 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) |
283 | { | 249 | { |
284 | struct nand_chip *chip = mtd->priv; | 250 | struct nand_chip *chip = mtd->priv; |
285 | struct atmel_nand_host *host = chip->priv; | ||
286 | 251 | ||
287 | if (use_dma && len > mtd->oobsize) | 252 | if (use_dma && len > mtd->oobsize) |
288 | /* only use DMA for bigger than oob size: better performances */ | 253 | /* only use DMA for bigger than oob size: better performances */ |
289 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) | 254 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) |
290 | return; | 255 | return; |
291 | 256 | ||
292 | if (host->board->bus_width_16) | 257 | /* if no DMA operation possible, use PIO */ |
293 | atmel_write_buf16(mtd, buf, len); | 258 | memcpy_toio(chip->IO_ADDR_W, buf, len); |
294 | else | ||
295 | atmel_write_buf8(mtd, buf, len); | ||
296 | } | 259 | } |
297 | 260 | ||
298 | /* | 261 | /* |
@@ -481,10 +444,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
481 | } | 444 | } |
482 | } | 445 | } |
483 | 446 | ||
484 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
485 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
486 | #endif | ||
487 | |||
488 | /* | 447 | /* |
489 | * Probe for the NAND device. | 448 | * Probe for the NAND device. |
490 | */ | 449 | */ |
@@ -496,8 +455,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
496 | struct resource *regs; | 455 | struct resource *regs; |
497 | struct resource *mem; | 456 | struct resource *mem; |
498 | int res; | 457 | int res; |
499 | struct mtd_partition *partitions = NULL; | ||
500 | int num_partitions = 0; | ||
501 | 458 | ||
502 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 459 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
503 | if (!mem) { | 460 | if (!mem) { |
@@ -583,7 +540,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
583 | 540 | ||
584 | if (on_flash_bbt) { | 541 | if (on_flash_bbt) { |
585 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); | 542 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); |
586 | nand_chip->options |= NAND_USE_FLASH_BBT; | 543 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; |
587 | } | 544 | } |
588 | 545 | ||
589 | if (!cpu_has_dma()) | 546 | if (!cpu_has_dma()) |
@@ -594,7 +551,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
594 | 551 | ||
595 | dma_cap_zero(mask); | 552 | dma_cap_zero(mask); |
596 | dma_cap_set(DMA_MEMCPY, mask); | 553 | dma_cap_set(DMA_MEMCPY, mask); |
597 | host->dma_chan = dma_request_channel(mask, 0, NULL); | 554 | host->dma_chan = dma_request_channel(mask, NULL, NULL); |
598 | if (!host->dma_chan) { | 555 | if (!host->dma_chan) { |
599 | dev_err(host->dev, "Failed to request DMA channel\n"); | 556 | dev_err(host->dev, "Failed to request DMA channel\n"); |
600 | use_dma = 0; | 557 | use_dma = 0; |
@@ -655,27 +612,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
655 | goto err_scan_tail; | 612 | goto err_scan_tail; |
656 | } | 613 | } |
657 | 614 | ||
658 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
659 | mtd->name = "atmel_nand"; | 615 | mtd->name = "atmel_nand"; |
660 | num_partitions = parse_mtd_partitions(mtd, part_probes, | 616 | res = mtd_device_parse_register(mtd, NULL, 0, |
661 | &partitions, 0); | 617 | host->board->parts, host->board->num_parts); |
662 | #endif | ||
663 | if (num_partitions <= 0 && host->board->partition_info) | ||
664 | partitions = host->board->partition_info(mtd->size, | ||
665 | &num_partitions); | ||
666 | |||
667 | if ((!partitions) || (num_partitions == 0)) { | ||
668 | printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n"); | ||
669 | res = -ENXIO; | ||
670 | goto err_no_partitions; | ||
671 | } | ||
672 | |||
673 | res = mtd_device_register(mtd, partitions, num_partitions); | ||
674 | if (!res) | 618 | if (!res) |
675 | return res; | 619 | return res; |
676 | 620 | ||
677 | err_no_partitions: | ||
678 | nand_release(mtd); | ||
679 | err_scan_tail: | 621 | err_scan_tail: |
680 | err_scan_ident: | 622 | err_scan_ident: |
681 | err_no_card: | 623 | err_no_card: |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index fa5736b9286c..7dd3700f2303 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -52,7 +52,7 @@ static const struct mtd_partition partition_info[] = { | |||
52 | * au_read_byte - read one byte from the chip | 52 | * au_read_byte - read one byte from the chip |
53 | * @mtd: MTD device structure | 53 | * @mtd: MTD device structure |
54 | * | 54 | * |
55 | * read function for 8bit buswith | 55 | * read function for 8bit buswidth |
56 | */ | 56 | */ |
57 | static u_char au_read_byte(struct mtd_info *mtd) | 57 | static u_char au_read_byte(struct mtd_info *mtd) |
58 | { | 58 | { |
@@ -67,7 +67,7 @@ static u_char au_read_byte(struct mtd_info *mtd) | |||
67 | * @mtd: MTD device structure | 67 | * @mtd: MTD device structure |
68 | * @byte: pointer to data byte to write | 68 | * @byte: pointer to data byte to write |
69 | * | 69 | * |
70 | * write function for 8it buswith | 70 | * write function for 8it buswidth |
71 | */ | 71 | */ |
72 | static void au_write_byte(struct mtd_info *mtd, u_char byte) | 72 | static void au_write_byte(struct mtd_info *mtd, u_char byte) |
73 | { | 73 | { |
@@ -77,11 +77,10 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * au_read_byte16 - read one byte endianess aware from the chip | 80 | * au_read_byte16 - read one byte endianness aware from the chip |
81 | * @mtd: MTD device structure | 81 | * @mtd: MTD device structure |
82 | * | 82 | * |
83 | * read function for 16bit buswith with | 83 | * read function for 16bit buswidth with endianness conversion |
84 | * endianess conversion | ||
85 | */ | 84 | */ |
86 | static u_char au_read_byte16(struct mtd_info *mtd) | 85 | static u_char au_read_byte16(struct mtd_info *mtd) |
87 | { | 86 | { |
@@ -92,12 +91,11 @@ static u_char au_read_byte16(struct mtd_info *mtd) | |||
92 | } | 91 | } |
93 | 92 | ||
94 | /** | 93 | /** |
95 | * au_write_byte16 - write one byte endianess aware to the chip | 94 | * au_write_byte16 - write one byte endianness aware to the chip |
96 | * @mtd: MTD device structure | 95 | * @mtd: MTD device structure |
97 | * @byte: pointer to data byte to write | 96 | * @byte: pointer to data byte to write |
98 | * | 97 | * |
99 | * write function for 16bit buswith with | 98 | * write function for 16bit buswidth with endianness conversion |
100 | * endianess conversion | ||
101 | */ | 99 | */ |
102 | static void au_write_byte16(struct mtd_info *mtd, u_char byte) | 100 | static void au_write_byte16(struct mtd_info *mtd, u_char byte) |
103 | { | 101 | { |
@@ -110,8 +108,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte) | |||
110 | * au_read_word - read one word from the chip | 108 | * au_read_word - read one word from the chip |
111 | * @mtd: MTD device structure | 109 | * @mtd: MTD device structure |
112 | * | 110 | * |
113 | * read function for 16bit buswith without | 111 | * read function for 16bit buswidth without endianness conversion |
114 | * endianess conversion | ||
115 | */ | 112 | */ |
116 | static u16 au_read_word(struct mtd_info *mtd) | 113 | static u16 au_read_word(struct mtd_info *mtd) |
117 | { | 114 | { |
@@ -127,7 +124,7 @@ static u16 au_read_word(struct mtd_info *mtd) | |||
127 | * @buf: data buffer | 124 | * @buf: data buffer |
128 | * @len: number of bytes to write | 125 | * @len: number of bytes to write |
129 | * | 126 | * |
130 | * write function for 8bit buswith | 127 | * write function for 8bit buswidth |
131 | */ | 128 | */ |
132 | static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 129 | static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
133 | { | 130 | { |
@@ -146,7 +143,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
146 | * @buf: buffer to store date | 143 | * @buf: buffer to store date |
147 | * @len: number of bytes to read | 144 | * @len: number of bytes to read |
148 | * | 145 | * |
149 | * read function for 8bit buswith | 146 | * read function for 8bit buswidth |
150 | */ | 147 | */ |
151 | static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 148 | static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
152 | { | 149 | { |
@@ -165,7 +162,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
165 | * @buf: buffer containing the data to compare | 162 | * @buf: buffer containing the data to compare |
166 | * @len: number of bytes to compare | 163 | * @len: number of bytes to compare |
167 | * | 164 | * |
168 | * verify function for 8bit buswith | 165 | * verify function for 8bit buswidth |
169 | */ | 166 | */ |
170 | static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | 167 | static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) |
171 | { | 168 | { |
@@ -187,7 +184,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
187 | * @buf: data buffer | 184 | * @buf: data buffer |
188 | * @len: number of bytes to write | 185 | * @len: number of bytes to write |
189 | * | 186 | * |
190 | * write function for 16bit buswith | 187 | * write function for 16bit buswidth |
191 | */ | 188 | */ |
192 | static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | 189 | static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) |
193 | { | 190 | { |
@@ -209,7 +206,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | |||
209 | * @buf: buffer to store date | 206 | * @buf: buffer to store date |
210 | * @len: number of bytes to read | 207 | * @len: number of bytes to read |
211 | * | 208 | * |
212 | * read function for 16bit buswith | 209 | * read function for 16bit buswidth |
213 | */ | 210 | */ |
214 | static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | 211 | static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) |
215 | { | 212 | { |
@@ -230,7 +227,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | |||
230 | * @buf: buffer containing the data to compare | 227 | * @buf: buffer containing the data to compare |
231 | * @len: number of bytes to compare | 228 | * @len: number of bytes to compare |
232 | * | 229 | * |
233 | * verify function for 16bit buswith | 230 | * verify function for 16bit buswidth |
234 | */ | 231 | */ |
235 | static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) | 232 | static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) |
236 | { | 233 | { |
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index eddc9a224985..2e42ec2e8ff4 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c | |||
@@ -172,9 +172,9 @@ static int __init autcpu12_init(void) | |||
172 | 172 | ||
173 | /* Enable the following for a flash based bad block table */ | 173 | /* Enable the following for a flash based bad block table */ |
174 | /* | 174 | /* |
175 | this->options = NAND_USE_FLASH_BBT; | 175 | this->bbt_options = NAND_BBT_USE_FLASH; |
176 | */ | 176 | */ |
177 | this->options = NAND_USE_FLASH_BBT; | 177 | this->bbt_options = NAND_BBT_USE_FLASH; |
178 | 178 | ||
179 | /* Scan to find existence of the device */ | 179 | /* Scan to find existence of the device */ |
180 | if (nand_scan(autcpu12_mtd, 1)) { | 180 | if (nand_scan(autcpu12_mtd, 1)) { |
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c index 8c569e454dc5..46b58d672847 100644 --- a/drivers/mtd/nand/bcm_umi_nand.c +++ b/drivers/mtd/nand/bcm_umi_nand.c | |||
@@ -52,8 +52,6 @@ | |||
52 | static const __devinitconst char gBanner[] = KERN_INFO \ | 52 | static const __devinitconst char gBanner[] = KERN_INFO \ |
53 | "BCM UMI MTD NAND Driver: 1.00\n"; | 53 | "BCM UMI MTD NAND Driver: 1.00\n"; |
54 | 54 | ||
55 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
56 | |||
57 | #if NAND_ECC_BCH | 55 | #if NAND_ECC_BCH |
58 | static uint8_t scan_ff_pattern[] = { 0xff }; | 56 | static uint8_t scan_ff_pattern[] = { 0xff }; |
59 | 57 | ||
@@ -376,16 +374,18 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
376 | 374 | ||
377 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 375 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
378 | 376 | ||
379 | if (!r) | 377 | if (!r) { |
380 | return -ENXIO; | 378 | err = -ENXIO; |
379 | goto out_free; | ||
380 | } | ||
381 | 381 | ||
382 | /* map physical address */ | 382 | /* map physical address */ |
383 | bcm_umi_io_base = ioremap(r->start, resource_size(r)); | 383 | bcm_umi_io_base = ioremap(r->start, resource_size(r)); |
384 | 384 | ||
385 | if (!bcm_umi_io_base) { | 385 | if (!bcm_umi_io_base) { |
386 | printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n"); | 386 | printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n"); |
387 | kfree(board_mtd); | 387 | err = -EIO; |
388 | return -EIO; | 388 | goto out_free; |
389 | } | 389 | } |
390 | 390 | ||
391 | /* Get pointer to private data */ | 391 | /* Get pointer to private data */ |
@@ -401,9 +401,8 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
401 | /* Initialize the NAND hardware. */ | 401 | /* Initialize the NAND hardware. */ |
402 | if (bcm_umi_nand_inithw() < 0) { | 402 | if (bcm_umi_nand_inithw() < 0) { |
403 | printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n"); | 403 | printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n"); |
404 | iounmap(bcm_umi_io_base); | 404 | err = -EIO; |
405 | kfree(board_mtd); | 405 | goto out_unmap; |
406 | return -EIO; | ||
407 | } | 406 | } |
408 | 407 | ||
409 | /* Set address of NAND IO lines */ | 408 | /* Set address of NAND IO lines */ |
@@ -436,7 +435,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
436 | #if USE_DMA | 435 | #if USE_DMA |
437 | err = nand_dma_init(); | 436 | err = nand_dma_init(); |
438 | if (err != 0) | 437 | if (err != 0) |
439 | return err; | 438 | goto out_unmap; |
440 | #endif | 439 | #endif |
441 | 440 | ||
442 | /* Figure out the size of the device that we have. | 441 | /* Figure out the size of the device that we have. |
@@ -447,9 +446,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
447 | err = nand_scan_ident(board_mtd, 1, NULL); | 446 | err = nand_scan_ident(board_mtd, 1, NULL); |
448 | if (err) { | 447 | if (err) { |
449 | printk(KERN_ERR "nand_scan failed: %d\n", err); | 448 | printk(KERN_ERR "nand_scan failed: %d\n", err); |
450 | iounmap(bcm_umi_io_base); | 449 | goto out_unmap; |
451 | kfree(board_mtd); | ||
452 | return err; | ||
453 | } | 450 | } |
454 | 451 | ||
455 | /* Now that we know the nand size, we can setup the ECC layout */ | 452 | /* Now that we know the nand size, we can setup the ECC layout */ |
@@ -468,13 +465,14 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
468 | { | 465 | { |
469 | printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n", | 466 | printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n", |
470 | board_mtd->writesize); | 467 | board_mtd->writesize); |
471 | return -EINVAL; | 468 | err = -EINVAL; |
469 | goto out_unmap; | ||
472 | } | 470 | } |
473 | } | 471 | } |
474 | 472 | ||
475 | #if NAND_ECC_BCH | 473 | #if NAND_ECC_BCH |
476 | if (board_mtd->writesize > 512) { | 474 | if (board_mtd->writesize > 512) { |
477 | if (this->options & NAND_USE_FLASH_BBT) | 475 | if (this->bbt_options & NAND_BBT_USE_FLASH) |
478 | largepage_bbt.options = NAND_BBT_SCAN2NDPAGE; | 476 | largepage_bbt.options = NAND_BBT_SCAN2NDPAGE; |
479 | this->badblock_pattern = &largepage_bbt; | 477 | this->badblock_pattern = &largepage_bbt; |
480 | } | 478 | } |
@@ -485,33 +483,20 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
485 | err = nand_scan_tail(board_mtd); | 483 | err = nand_scan_tail(board_mtd); |
486 | if (err) { | 484 | if (err) { |
487 | printk(KERN_ERR "nand_scan failed: %d\n", err); | 485 | printk(KERN_ERR "nand_scan failed: %d\n", err); |
488 | iounmap(bcm_umi_io_base); | 486 | goto out_unmap; |
489 | kfree(board_mtd); | ||
490 | return err; | ||
491 | } | 487 | } |
492 | 488 | ||
493 | /* Register the partitions */ | 489 | /* Register the partitions */ |
494 | { | 490 | board_mtd->name = "bcm_umi-nand"; |
495 | int nr_partitions; | 491 | mtd_device_parse_register(board_mtd, NULL, 0, NULL, 0); |
496 | struct mtd_partition *partition_info; | ||
497 | |||
498 | board_mtd->name = "bcm_umi-nand"; | ||
499 | nr_partitions = | ||
500 | parse_mtd_partitions(board_mtd, part_probes, | ||
501 | &partition_info, 0); | ||
502 | |||
503 | if (nr_partitions <= 0) { | ||
504 | printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n", | ||
505 | nr_partitions); | ||
506 | iounmap(bcm_umi_io_base); | ||
507 | kfree(board_mtd); | ||
508 | return -EIO; | ||
509 | } | ||
510 | mtd_device_register(board_mtd, partition_info, nr_partitions); | ||
511 | } | ||
512 | 492 | ||
513 | /* Return happy */ | 493 | /* Return happy */ |
514 | return 0; | 494 | return 0; |
495 | out_unmap: | ||
496 | iounmap(bcm_umi_io_base); | ||
497 | out_free: | ||
498 | kfree(board_mtd); | ||
499 | return err; | ||
515 | } | 500 | } |
516 | 501 | ||
517 | static int bcm_umi_nand_remove(struct platform_device *pdev) | 502 | static int bcm_umi_nand_remove(struct platform_device *pdev) |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 7c8df837d3b8..72d3f23490c5 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -58,7 +58,6 @@ | |||
58 | 58 | ||
59 | struct cafe_priv { | 59 | struct cafe_priv { |
60 | struct nand_chip nand; | 60 | struct nand_chip nand; |
61 | struct mtd_partition *parts; | ||
62 | struct pci_dev *pdev; | 61 | struct pci_dev *pdev; |
63 | void __iomem *mmio; | 62 | void __iomem *mmio; |
64 | struct rs_control *rs; | 63 | struct rs_control *rs; |
@@ -372,7 +371,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
372 | return 1; | 371 | return 1; |
373 | } | 372 | } |
374 | /** | 373 | /** |
375 | * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read | 374 | * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read |
376 | * @mtd: mtd info structure | 375 | * @mtd: mtd info structure |
377 | * @chip: nand chip info structure | 376 | * @chip: nand chip info structure |
378 | * @buf: buffer to store read data | 377 | * @buf: buffer to store read data |
@@ -631,8 +630,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
631 | struct cafe_priv *cafe; | 630 | struct cafe_priv *cafe; |
632 | uint32_t ctrl; | 631 | uint32_t ctrl; |
633 | int err = 0; | 632 | int err = 0; |
634 | struct mtd_partition *parts; | ||
635 | int nr_parts; | ||
636 | 633 | ||
637 | /* Very old versions shared the same PCI ident for all three | 634 | /* Very old versions shared the same PCI ident for all three |
638 | functions on the chip. Verify the class too... */ | 635 | functions on the chip. Verify the class too... */ |
@@ -687,7 +684,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
687 | cafe->nand.chip_delay = 0; | 684 | cafe->nand.chip_delay = 0; |
688 | 685 | ||
689 | /* Enable the following for a flash based bad block table */ | 686 | /* Enable the following for a flash based bad block table */ |
690 | cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; | 687 | cafe->nand.bbt_options = NAND_BBT_USE_FLASH; |
688 | cafe->nand.options = NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; | ||
691 | 689 | ||
692 | if (skipbbt) { | 690 | if (skipbbt) { |
693 | cafe->nand.options |= NAND_SKIP_BBTSCAN; | 691 | cafe->nand.options |= NAND_SKIP_BBTSCAN; |
@@ -800,18 +798,9 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
800 | 798 | ||
801 | pci_set_drvdata(pdev, mtd); | 799 | pci_set_drvdata(pdev, mtd); |
802 | 800 | ||
803 | /* We register the whole device first, separate from the partitions */ | ||
804 | mtd_device_register(mtd, NULL, 0); | ||
805 | |||
806 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
807 | mtd->name = "cafe_nand"; | 801 | mtd->name = "cafe_nand"; |
808 | #endif | 802 | mtd_device_parse_register(mtd, part_probes, 0, NULL, 0); |
809 | nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0); | 803 | |
810 | if (nr_parts > 0) { | ||
811 | cafe->parts = parts; | ||
812 | dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts); | ||
813 | mtd_device_register(mtd, parts, nr_parts); | ||
814 | } | ||
815 | goto out; | 804 | goto out; |
816 | 805 | ||
817 | out_irq: | 806 | out_irq: |
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index be33b0f4634d..737ef9a04fdb 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c | |||
@@ -51,8 +51,6 @@ static struct mtd_partition partition_info[] = { | |||
51 | }; | 51 | }; |
52 | #define NUM_PARTITIONS (ARRAY_SIZE(partition_info)) | 52 | #define NUM_PARTITIONS (ARRAY_SIZE(partition_info)) |
53 | 53 | ||
54 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
55 | |||
56 | static u_char cmx270_read_byte(struct mtd_info *mtd) | 54 | static u_char cmx270_read_byte(struct mtd_info *mtd) |
57 | { | 55 | { |
58 | struct nand_chip *this = mtd->priv; | 56 | struct nand_chip *this = mtd->priv; |
@@ -152,9 +150,6 @@ static int cmx270_device_ready(struct mtd_info *mtd) | |||
152 | static int __init cmx270_init(void) | 150 | static int __init cmx270_init(void) |
153 | { | 151 | { |
154 | struct nand_chip *this; | 152 | struct nand_chip *this; |
155 | const char *part_type; | ||
156 | struct mtd_partition *mtd_parts; | ||
157 | int mtd_parts_nb = 0; | ||
158 | int ret; | 153 | int ret; |
159 | 154 | ||
160 | if (!(machine_is_armcore() && cpu_is_pxa27x())) | 155 | if (!(machine_is_armcore() && cpu_is_pxa27x())) |
@@ -223,23 +218,9 @@ static int __init cmx270_init(void) | |||
223 | goto err_scan; | 218 | goto err_scan; |
224 | } | 219 | } |
225 | 220 | ||
226 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
227 | mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, part_probes, | ||
228 | &mtd_parts, 0); | ||
229 | if (mtd_parts_nb > 0) | ||
230 | part_type = "command line"; | ||
231 | else | ||
232 | mtd_parts_nb = 0; | ||
233 | #endif | ||
234 | if (!mtd_parts_nb) { | ||
235 | mtd_parts = partition_info; | ||
236 | mtd_parts_nb = NUM_PARTITIONS; | ||
237 | part_type = "static"; | ||
238 | } | ||
239 | |||
240 | /* Register the partitions */ | 221 | /* Register the partitions */ |
241 | pr_notice("Using %s partition definition\n", part_type); | 222 | ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, 0, |
242 | ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); | 223 | partition_info, NUM_PARTITIONS); |
243 | if (ret) | 224 | if (ret) |
244 | goto err_scan; | 225 | goto err_scan; |
245 | 226 | ||
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index f59ad1f2d5db..414afa793563 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -239,7 +239,8 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
239 | this->ecc.correct = nand_correct_data; | 239 | this->ecc.correct = nand_correct_data; |
240 | 240 | ||
241 | /* Enable the following for a flash based bad block table */ | 241 | /* Enable the following for a flash based bad block table */ |
242 | this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; | 242 | this->bbt_options = NAND_BBT_USE_FLASH; |
243 | this->options = NAND_NO_AUTOINCR; | ||
243 | 244 | ||
244 | /* Scan to find existence of the device */ | 245 | /* Scan to find existence of the device */ |
245 | if (nand_scan(new_mtd, 1)) { | 246 | if (nand_scan(new_mtd, 1)) { |
@@ -277,15 +278,11 @@ static int is_geode(void) | |||
277 | return 0; | 278 | return 0; |
278 | } | 279 | } |
279 | 280 | ||
280 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
281 | |||
282 | static int __init cs553x_init(void) | 281 | static int __init cs553x_init(void) |
283 | { | 282 | { |
284 | int err = -ENXIO; | 283 | int err = -ENXIO; |
285 | int i; | 284 | int i; |
286 | uint64_t val; | 285 | uint64_t val; |
287 | int mtd_parts_nb = 0; | ||
288 | struct mtd_partition *mtd_parts = NULL; | ||
289 | 286 | ||
290 | /* If the CPU isn't a Geode GX or LX, abort */ | 287 | /* If the CPU isn't a Geode GX or LX, abort */ |
291 | if (!is_geode()) | 288 | if (!is_geode()) |
@@ -315,13 +312,9 @@ static int __init cs553x_init(void) | |||
315 | do mtdconcat etc. if we want to. */ | 312 | do mtdconcat etc. if we want to. */ |
316 | for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { | 313 | for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { |
317 | if (cs553x_mtd[i]) { | 314 | if (cs553x_mtd[i]) { |
318 | |||
319 | /* If any devices registered, return success. Else the last error. */ | 315 | /* If any devices registered, return success. Else the last error. */ |
320 | mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0); | 316 | mtd_device_parse_register(cs553x_mtd[i], NULL, 0, |
321 | if (mtd_parts_nb > 0) | 317 | NULL, 0); |
322 | printk(KERN_NOTICE "Using command line partition definition\n"); | ||
323 | mtd_device_register(cs553x_mtd[i], mtd_parts, | ||
324 | mtd_parts_nb); | ||
325 | err = 0; | 318 | err = 0; |
326 | } | 319 | } |
327 | } | 320 | } |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 1f34951ae1a7..c153e1f77f90 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -57,7 +57,6 @@ struct davinci_nand_info { | |||
57 | 57 | ||
58 | struct device *dev; | 58 | struct device *dev; |
59 | struct clk *clk; | 59 | struct clk *clk; |
60 | bool partitioned; | ||
61 | 60 | ||
62 | bool is_readmode; | 61 | bool is_readmode; |
63 | 62 | ||
@@ -530,8 +529,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
530 | int ret; | 529 | int ret; |
531 | uint32_t val; | 530 | uint32_t val; |
532 | nand_ecc_modes_t ecc_mode; | 531 | nand_ecc_modes_t ecc_mode; |
533 | struct mtd_partition *mtd_parts = NULL; | ||
534 | int mtd_parts_nb = 0; | ||
535 | 532 | ||
536 | /* insist on board-specific configuration */ | 533 | /* insist on board-specific configuration */ |
537 | if (!pdata) | 534 | if (!pdata) |
@@ -581,7 +578,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
581 | info->chip.chip_delay = 0; | 578 | info->chip.chip_delay = 0; |
582 | info->chip.select_chip = nand_davinci_select_chip; | 579 | info->chip.select_chip = nand_davinci_select_chip; |
583 | 580 | ||
584 | /* options such as NAND_USE_FLASH_BBT or 16-bit widths */ | 581 | /* options such as NAND_BBT_USE_FLASH */ |
582 | info->chip.bbt_options = pdata->bbt_options; | ||
583 | /* options such as 16-bit widths */ | ||
585 | info->chip.options = pdata->options; | 584 | info->chip.options = pdata->options; |
586 | info->chip.bbt_td = pdata->bbt_td; | 585 | info->chip.bbt_td = pdata->bbt_td; |
587 | info->chip.bbt_md = pdata->bbt_md; | 586 | info->chip.bbt_md = pdata->bbt_md; |
@@ -751,33 +750,8 @@ syndrome_done: | |||
751 | if (ret < 0) | 750 | if (ret < 0) |
752 | goto err_scan; | 751 | goto err_scan; |
753 | 752 | ||
754 | if (mtd_has_cmdlinepart()) { | 753 | ret = mtd_device_parse_register(&info->mtd, NULL, 0, |
755 | static const char *probes[] __initconst = { | 754 | pdata->parts, pdata->nr_parts); |
756 | "cmdlinepart", NULL | ||
757 | }; | ||
758 | |||
759 | mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes, | ||
760 | &mtd_parts, 0); | ||
761 | } | ||
762 | |||
763 | if (mtd_parts_nb <= 0) { | ||
764 | mtd_parts = pdata->parts; | ||
765 | mtd_parts_nb = pdata->nr_parts; | ||
766 | } | ||
767 | |||
768 | /* Register any partitions */ | ||
769 | if (mtd_parts_nb > 0) { | ||
770 | ret = mtd_device_register(&info->mtd, mtd_parts, | ||
771 | mtd_parts_nb); | ||
772 | if (ret == 0) | ||
773 | info->partitioned = true; | ||
774 | } | ||
775 | |||
776 | /* If there's no partition info, just package the whole chip | ||
777 | * as a single MTD device. | ||
778 | */ | ||
779 | if (!info->partitioned) | ||
780 | ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0; | ||
781 | 755 | ||
782 | if (ret < 0) | 756 | if (ret < 0) |
783 | goto err_scan; | 757 | goto err_scan; |
@@ -816,9 +790,6 @@ err_nomem: | |||
816 | static int __exit nand_davinci_remove(struct platform_device *pdev) | 790 | static int __exit nand_davinci_remove(struct platform_device *pdev) |
817 | { | 791 | { |
818 | struct davinci_nand_info *info = platform_get_drvdata(pdev); | 792 | struct davinci_nand_info *info = platform_get_drvdata(pdev); |
819 | int status; | ||
820 | |||
821 | status = mtd_device_unregister(&info->mtd); | ||
822 | 793 | ||
823 | spin_lock_irq(&davinci_nand_lock); | 794 | spin_lock_irq(&davinci_nand_lock); |
824 | if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME) | 795 | if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME) |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index d5276218945f..3984d488f9ab 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -1346,6 +1346,7 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
1346 | * */ | 1346 | * */ |
1347 | denali->bbtskipbytes = ioread32(denali->flash_reg + | 1347 | denali->bbtskipbytes = ioread32(denali->flash_reg + |
1348 | SPARE_AREA_SKIP_BYTES); | 1348 | SPARE_AREA_SKIP_BYTES); |
1349 | detect_max_banks(denali); | ||
1349 | denali_nand_reset(denali); | 1350 | denali_nand_reset(denali); |
1350 | iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED); | 1351 | iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED); |
1351 | iowrite32(CHIP_EN_DONT_CARE__FLAG, | 1352 | iowrite32(CHIP_EN_DONT_CARE__FLAG, |
@@ -1356,7 +1357,6 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
1356 | /* Should set value for these registers when init */ | 1357 | /* Should set value for these registers when init */ |
1357 | iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); | 1358 | iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); |
1358 | iowrite32(1, denali->flash_reg + ECC_ENABLE); | 1359 | iowrite32(1, denali->flash_reg + ECC_ENABLE); |
1359 | detect_max_banks(denali); | ||
1360 | denali_nand_timing_set(denali); | 1360 | denali_nand_timing_set(denali); |
1361 | denali_irq_init(denali); | 1361 | denali_irq_init(denali); |
1362 | } | 1362 | } |
@@ -1577,7 +1577,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1577 | denali->nand.bbt_md = &bbt_mirror_descr; | 1577 | denali->nand.bbt_md = &bbt_mirror_descr; |
1578 | 1578 | ||
1579 | /* skip the scan for now until we have OOB read and write support */ | 1579 | /* skip the scan for now until we have OOB read and write support */ |
1580 | denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; | 1580 | denali->nand.bbt_options |= NAND_BBT_USE_FLASH; |
1581 | denali->nand.options |= NAND_SKIP_BBTSCAN; | ||
1581 | denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | 1582 | denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; |
1582 | 1583 | ||
1583 | /* Denali Controller only support 15bit and 8bit ECC in MRST, | 1584 | /* Denali Controller only support 15bit and 8bit ECC in MRST, |
@@ -1676,7 +1677,6 @@ static void denali_pci_remove(struct pci_dev *dev) | |||
1676 | struct denali_nand_info *denali = pci_get_drvdata(dev); | 1677 | struct denali_nand_info *denali = pci_get_drvdata(dev); |
1677 | 1678 | ||
1678 | nand_release(&denali->mtd); | 1679 | nand_release(&denali->mtd); |
1679 | mtd_device_unregister(&denali->mtd); | ||
1680 | 1680 | ||
1681 | denali_irq_cleanup(dev->irq, denali); | 1681 | denali_irq_cleanup(dev->irq, denali); |
1682 | 1682 | ||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index e1b84cb90f0d..5780dbab6113 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -133,7 +133,7 @@ static struct rs_control *rs_decoder; | |||
133 | 133 | ||
134 | /* | 134 | /* |
135 | * The HW decoder in the DoC ASIC's provides us a error syndrome, | 135 | * The HW decoder in the DoC ASIC's provides us a error syndrome, |
136 | * which we must convert to a standard syndrom usable by the generic | 136 | * which we must convert to a standard syndrome usable by the generic |
137 | * Reed-Solomon library code. | 137 | * Reed-Solomon library code. |
138 | * | 138 | * |
139 | * Fabrice Bellard figured this out in the old docecc code. I added | 139 | * Fabrice Bellard figured this out in the old docecc code. I added |
@@ -154,7 +154,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
154 | ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); | 154 | ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); |
155 | parity = ecc[1]; | 155 | parity = ecc[1]; |
156 | 156 | ||
157 | /* Initialize the syndrom buffer */ | 157 | /* Initialize the syndrome buffer */ |
158 | for (i = 0; i < NROOTS; i++) | 158 | for (i = 0; i < NROOTS; i++) |
159 | s[i] = ds[0]; | 159 | s[i] = ds[0]; |
160 | /* | 160 | /* |
@@ -1032,7 +1032,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, | |||
1032 | WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); | 1032 | WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); |
1033 | else | 1033 | else |
1034 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | 1034 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); |
1035 | if (no_ecc_failures && (ret == -EBADMSG)) { | 1035 | if (no_ecc_failures && mtd_is_eccerr(ret)) { |
1036 | printk(KERN_ERR "suppressing ECC failure\n"); | 1036 | printk(KERN_ERR "suppressing ECC failure\n"); |
1037 | ret = 0; | 1037 | ret = 0; |
1038 | } | 1038 | } |
@@ -1653,7 +1653,7 @@ static int __init doc_probe(unsigned long physadr) | |||
1653 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; | 1653 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; |
1654 | nand->ecc.size = 512; | 1654 | nand->ecc.size = 512; |
1655 | nand->ecc.bytes = 6; | 1655 | nand->ecc.bytes = 6; |
1656 | nand->options = NAND_USE_FLASH_BBT; | 1656 | nand->bbt_options = NAND_BBT_USE_FLASH; |
1657 | 1657 | ||
1658 | doc->physadr = physadr; | 1658 | doc->physadr = physadr; |
1659 | doc->virtadr = virtadr; | 1659 | doc->virtadr = virtadr; |
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c deleted file mode 100644 index 8400d0f6dada..000000000000 --- a/drivers/mtd/nand/edb7312.c +++ /dev/null | |||
@@ -1,203 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/edb7312.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) | ||
5 | * | ||
6 | * Derived from drivers/mtd/nand/autcpu12.c | ||
7 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * Overview: | ||
14 | * This is a device driver for the NAND flash device found on the | ||
15 | * CLEP7312 board which utilizes the Toshiba TC58V64AFT part. This is | ||
16 | * a 64Mibit (8MiB x 8 bits) NAND flash device. | ||
17 | */ | ||
18 | |||
19 | #include <linux/slab.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/mtd/mtd.h> | ||
23 | #include <linux/mtd/nand.h> | ||
24 | #include <linux/mtd/partitions.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <mach/hardware.h> /* for CLPS7111_VIRT_BASE */ | ||
27 | #include <asm/sizes.h> | ||
28 | #include <asm/hardware/clps7111.h> | ||
29 | |||
30 | /* | ||
31 | * MTD structure for EDB7312 board | ||
32 | */ | ||
33 | static struct mtd_info *ep7312_mtd = NULL; | ||
34 | |||
35 | /* | ||
36 | * Values specific to the EDB7312 board (used with EP7312 processor) | ||
37 | */ | ||
38 | #define EP7312_FIO_PBASE 0x10000000 /* Phys address of flash */ | ||
39 | #define EP7312_PXDR 0x0001 /* | ||
40 | * IO offset to Port B data register | ||
41 | * where the CLE, ALE and NCE pins | ||
42 | * are wired to. | ||
43 | */ | ||
44 | #define EP7312_PXDDR 0x0041 /* | ||
45 | * IO offset to Port B data direction | ||
46 | * register so we can control the IO | ||
47 | * lines. | ||
48 | */ | ||
49 | |||
50 | /* | ||
51 | * Module stuff | ||
52 | */ | ||
53 | |||
54 | static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE; | ||
55 | static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR; | ||
56 | static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR; | ||
57 | |||
58 | /* | ||
59 | * Define static partitions for flash device | ||
60 | */ | ||
61 | static struct mtd_partition partition_info[] = { | ||
62 | {.name = "EP7312 Nand Flash", | ||
63 | .offset = 0, | ||
64 | .size = 8 * 1024 * 1024} | ||
65 | }; | ||
66 | |||
67 | #define NUM_PARTITIONS 1 | ||
68 | |||
69 | /* | ||
70 | * hardware specific access to control-lines | ||
71 | * | ||
72 | * NAND_NCE: bit 0 -> bit 6 (bit 7 = 1) | ||
73 | * NAND_CLE: bit 1 -> bit 4 | ||
74 | * NAND_ALE: bit 2 -> bit 5 | ||
75 | */ | ||
76 | static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
77 | { | ||
78 | struct nand_chip *chip = mtd->priv; | ||
79 | |||
80 | if (ctrl & NAND_CTRL_CHANGE) { | ||
81 | unsigned char bits = 0x80; | ||
82 | |||
83 | bits |= (ctrl & (NAND_CLE | NAND_ALE)) << 3; | ||
84 | bits |= (ctrl & NAND_NCE) ? 0x00 : 0x40; | ||
85 | |||
86 | clps_writeb((clps_readb(ep7312_pxdr) & 0xF0) | bits, | ||
87 | ep7312_pxdr); | ||
88 | } | ||
89 | if (cmd != NAND_CMD_NONE) | ||
90 | writeb(cmd, chip->IO_ADDR_W); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * read device ready pin | ||
95 | */ | ||
96 | static int ep7312_device_ready(struct mtd_info *mtd) | ||
97 | { | ||
98 | return 1; | ||
99 | } | ||
100 | |||
101 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
102 | |||
103 | /* | ||
104 | * Main initialization routine | ||
105 | */ | ||
106 | static int __init ep7312_init(void) | ||
107 | { | ||
108 | struct nand_chip *this; | ||
109 | const char *part_type = 0; | ||
110 | int mtd_parts_nb = 0; | ||
111 | struct mtd_partition *mtd_parts = 0; | ||
112 | void __iomem *ep7312_fio_base; | ||
113 | |||
114 | /* Allocate memory for MTD device structure and private data */ | ||
115 | ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); | ||
116 | if (!ep7312_mtd) { | ||
117 | printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); | ||
118 | return -ENOMEM; | ||
119 | } | ||
120 | |||
121 | /* map physical address */ | ||
122 | ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); | ||
123 | if (!ep7312_fio_base) { | ||
124 | printk("ioremap EDB7312 NAND flash failed\n"); | ||
125 | kfree(ep7312_mtd); | ||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | /* Get pointer to private data */ | ||
130 | this = (struct nand_chip *)(&ep7312_mtd[1]); | ||
131 | |||
132 | /* Initialize structures */ | ||
133 | memset(ep7312_mtd, 0, sizeof(struct mtd_info)); | ||
134 | memset(this, 0, sizeof(struct nand_chip)); | ||
135 | |||
136 | /* Link the private data with the MTD structure */ | ||
137 | ep7312_mtd->priv = this; | ||
138 | ep7312_mtd->owner = THIS_MODULE; | ||
139 | |||
140 | /* | ||
141 | * Set GPIO Port B control register so that the pins are configured | ||
142 | * to be outputs for controlling the NAND flash. | ||
143 | */ | ||
144 | clps_writeb(0xf0, ep7312_pxddr); | ||
145 | |||
146 | /* insert callbacks */ | ||
147 | this->IO_ADDR_R = ep7312_fio_base; | ||
148 | this->IO_ADDR_W = ep7312_fio_base; | ||
149 | this->cmd_ctrl = ep7312_hwcontrol; | ||
150 | this->dev_ready = ep7312_device_ready; | ||
151 | /* 15 us command delay time */ | ||
152 | this->chip_delay = 15; | ||
153 | |||
154 | /* Scan to find existence of the device */ | ||
155 | if (nand_scan(ep7312_mtd, 1)) { | ||
156 | iounmap((void *)ep7312_fio_base); | ||
157 | kfree(ep7312_mtd); | ||
158 | return -ENXIO; | ||
159 | } | ||
160 | ep7312_mtd->name = "edb7312-nand"; | ||
161 | mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0); | ||
162 | if (mtd_parts_nb > 0) | ||
163 | part_type = "command line"; | ||
164 | else | ||
165 | mtd_parts_nb = 0; | ||
166 | if (mtd_parts_nb == 0) { | ||
167 | mtd_parts = partition_info; | ||
168 | mtd_parts_nb = NUM_PARTITIONS; | ||
169 | part_type = "static"; | ||
170 | } | ||
171 | |||
172 | /* Register the partitions */ | ||
173 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | ||
174 | mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb); | ||
175 | |||
176 | /* Return happy */ | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | module_init(ep7312_init); | ||
181 | |||
182 | /* | ||
183 | * Clean up routine | ||
184 | */ | ||
185 | static void __exit ep7312_cleanup(void) | ||
186 | { | ||
187 | struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1]; | ||
188 | |||
189 | /* Release resources, unregister device */ | ||
190 | nand_release(ap7312_mtd); | ||
191 | |||
192 | /* Release io resource */ | ||
193 | iounmap(this->IO_ADDR_R); | ||
194 | |||
195 | /* Free the MTD device structure */ | ||
196 | kfree(ep7312_mtd); | ||
197 | } | ||
198 | |||
199 | module_exit(ep7312_cleanup); | ||
200 | |||
201 | MODULE_LICENSE("GPL"); | ||
202 | MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>"); | ||
203 | MODULE_DESCRIPTION("MTD map driver for Cogent EDB7312 board"); | ||
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 33d8aad8bba5..eedd8ee2c9ac 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -75,7 +75,6 @@ struct fsl_elbc_fcm_ctrl { | |||
75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ | 75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ |
76 | unsigned int oob; /* Non zero if operating on OOB data */ | 76 | unsigned int oob; /* Non zero if operating on OOB data */ |
77 | unsigned int counter; /* counter for the initializations */ | 77 | unsigned int counter; /* counter for the initializations */ |
78 | char *oob_poi; /* Place to write ECC after read back */ | ||
79 | }; | 78 | }; |
80 | 79 | ||
81 | /* These map to the positions used by the FCM hardware ECC generator */ | 80 | /* These map to the positions used by the FCM hardware ECC generator */ |
@@ -244,6 +243,25 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
244 | return -EIO; | 243 | return -EIO; |
245 | } | 244 | } |
246 | 245 | ||
246 | if (chip->ecc.mode != NAND_ECC_HW) | ||
247 | return 0; | ||
248 | |||
249 | if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { | ||
250 | uint32_t lteccr = in_be32(&lbc->lteccr); | ||
251 | /* | ||
252 | * if command was a full page read and the ELBC | ||
253 | * has the LTECCR register, then bits 12-15 (ppc order) of | ||
254 | * LTECCR indicates which 512 byte sub-pages had fixed errors. | ||
255 | * bits 28-31 are uncorrectable errors, marked elsewhere. | ||
256 | * for small page nand only 1 bit is used. | ||
257 | * if the ELBC doesn't have the lteccr register it reads 0 | ||
258 | */ | ||
259 | if (lteccr & 0x000F000F) | ||
260 | out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ | ||
261 | if (lteccr & 0x000F0000) | ||
262 | mtd->ecc_stats.corrected++; | ||
263 | } | ||
264 | |||
247 | return 0; | 265 | return 0; |
248 | } | 266 | } |
249 | 267 | ||
@@ -435,7 +453,6 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
435 | 453 | ||
436 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ | 454 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ |
437 | case NAND_CMD_PAGEPROG: { | 455 | case NAND_CMD_PAGEPROG: { |
438 | int full_page; | ||
439 | dev_vdbg(priv->dev, | 456 | dev_vdbg(priv->dev, |
440 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " | 457 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " |
441 | "writing %d bytes.\n", elbc_fcm_ctrl->index); | 458 | "writing %d bytes.\n", elbc_fcm_ctrl->index); |
@@ -445,34 +462,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
445 | * write so the HW generates the ECC. | 462 | * write so the HW generates the ECC. |
446 | */ | 463 | */ |
447 | if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || | 464 | if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || |
448 | elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) { | 465 | elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) |
449 | out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); | 466 | out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); |
450 | full_page = 0; | 467 | else |
451 | } else { | ||
452 | out_be32(&lbc->fbcr, 0); | 468 | out_be32(&lbc->fbcr, 0); |
453 | full_page = 1; | ||
454 | } | ||
455 | 469 | ||
456 | fsl_elbc_run_command(mtd); | 470 | fsl_elbc_run_command(mtd); |
457 | |||
458 | /* Read back the page in order to fill in the ECC for the | ||
459 | * caller. Is this really needed? | ||
460 | */ | ||
461 | if (full_page && elbc_fcm_ctrl->oob_poi) { | ||
462 | out_be32(&lbc->fbcr, 3); | ||
463 | set_addr(mtd, 6, page_addr, 1); | ||
464 | |||
465 | elbc_fcm_ctrl->read_bytes = mtd->writesize + 9; | ||
466 | |||
467 | fsl_elbc_do_read(chip, 1); | ||
468 | fsl_elbc_run_command(mtd); | ||
469 | |||
470 | memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6, | ||
471 | &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3); | ||
472 | elbc_fcm_ctrl->index += 3; | ||
473 | } | ||
474 | |||
475 | elbc_fcm_ctrl->oob_poi = NULL; | ||
476 | return; | 471 | return; |
477 | } | 472 | } |
478 | 473 | ||
@@ -752,13 +747,8 @@ static void fsl_elbc_write_page(struct mtd_info *mtd, | |||
752 | struct nand_chip *chip, | 747 | struct nand_chip *chip, |
753 | const uint8_t *buf) | 748 | const uint8_t *buf) |
754 | { | 749 | { |
755 | struct fsl_elbc_mtd *priv = chip->priv; | ||
756 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; | ||
757 | |||
758 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); | 750 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
759 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 751 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
760 | |||
761 | elbc_fcm_ctrl->oob_poi = chip->oob_poi; | ||
762 | } | 752 | } |
763 | 753 | ||
764 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | 754 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
@@ -791,8 +781,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
791 | chip->bbt_md = &bbt_mirror_descr; | 781 | chip->bbt_md = &bbt_mirror_descr; |
792 | 782 | ||
793 | /* set up nand options */ | 783 | /* set up nand options */ |
794 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | | 784 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; |
795 | NAND_USE_FLASH_BBT; | 785 | chip->bbt_options = NAND_BBT_USE_FLASH; |
796 | 786 | ||
797 | chip->controller = &elbc_fcm_ctrl->controller; | 787 | chip->controller = &elbc_fcm_ctrl->controller; |
798 | chip->priv = priv; | 788 | chip->priv = priv; |
@@ -829,7 +819,6 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
829 | 819 | ||
830 | elbc_fcm_ctrl->chips[priv->bank] = NULL; | 820 | elbc_fcm_ctrl->chips[priv->bank] = NULL; |
831 | kfree(priv); | 821 | kfree(priv); |
832 | kfree(elbc_fcm_ctrl); | ||
833 | return 0; | 822 | return 0; |
834 | } | 823 | } |
835 | 824 | ||
@@ -842,13 +831,14 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | |||
842 | struct resource res; | 831 | struct resource res; |
843 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; | 832 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; |
844 | static const char *part_probe_types[] | 833 | static const char *part_probe_types[] |
845 | = { "cmdlinepart", "RedBoot", NULL }; | 834 | = { "cmdlinepart", "RedBoot", "ofpart", NULL }; |
846 | struct mtd_partition *parts; | ||
847 | int ret; | 835 | int ret; |
848 | int bank; | 836 | int bank; |
849 | struct device *dev; | 837 | struct device *dev; |
850 | struct device_node *node = pdev->dev.of_node; | 838 | struct device_node *node = pdev->dev.of_node; |
839 | struct mtd_part_parser_data ppdata; | ||
851 | 840 | ||
841 | ppdata.of_node = pdev->dev.of_node; | ||
852 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | 842 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
853 | return -ENODEV; | 843 | return -ENODEV; |
854 | lbc = fsl_lbc_ctrl_dev->regs; | 844 | lbc = fsl_lbc_ctrl_dev->regs; |
@@ -934,17 +924,8 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | |||
934 | 924 | ||
935 | /* First look for RedBoot table or partitions on the command | 925 | /* First look for RedBoot table or partitions on the command |
936 | * line, these take precedence over device tree information */ | 926 | * line, these take precedence over device tree information */ |
937 | ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0); | 927 | mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata, |
938 | if (ret < 0) | 928 | NULL, 0); |
939 | goto err; | ||
940 | |||
941 | if (ret == 0) { | ||
942 | ret = of_mtd_parse_partitions(priv->dev, node, &parts); | ||
943 | if (ret < 0) | ||
944 | goto err; | ||
945 | } | ||
946 | |||
947 | mtd_device_register(&priv->mtd, parts, ret); | ||
948 | 929 | ||
949 | printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", | 930 | printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", |
950 | (unsigned long long)res.start, priv->bank); | 931 | (unsigned long long)res.start, priv->bank); |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 23752fd5bc59..b4f3cc9f32fb 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -158,7 +158,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
158 | { | 158 | { |
159 | int ret; | 159 | int ret; |
160 | struct device_node *flash_np; | 160 | struct device_node *flash_np; |
161 | static const char *part_types[] = { "cmdlinepart", NULL, }; | 161 | struct mtd_part_parser_data ppdata; |
162 | 162 | ||
163 | fun->chip.IO_ADDR_R = fun->io_base; | 163 | fun->chip.IO_ADDR_R = fun->io_base; |
164 | fun->chip.IO_ADDR_W = fun->io_base; | 164 | fun->chip.IO_ADDR_W = fun->io_base; |
@@ -192,18 +192,12 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
192 | if (ret) | 192 | if (ret) |
193 | goto err; | 193 | goto err; |
194 | 194 | ||
195 | ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0); | 195 | ppdata.of_node = flash_np; |
196 | 196 | ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0); | |
197 | #ifdef CONFIG_MTD_OF_PARTS | ||
198 | if (ret == 0) { | ||
199 | ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts); | ||
200 | if (ret < 0) | ||
201 | goto err; | ||
202 | } | ||
203 | #endif | ||
204 | ret = mtd_device_register(&fun->mtd, fun->parts, ret); | ||
205 | err: | 197 | err: |
206 | of_node_put(flash_np); | 198 | of_node_put(flash_np); |
199 | if (ret) | ||
200 | kfree(fun->mtd.name); | ||
207 | return ret; | 201 | return ret; |
208 | } | 202 | } |
209 | 203 | ||
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index e9b275ac381c..e53b76064133 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -146,7 +146,7 @@ static struct mtd_partition partition_info_16KB_blk[] = { | |||
146 | { | 146 | { |
147 | .name = "Root File System", | 147 | .name = "Root File System", |
148 | .offset = 0x460000, | 148 | .offset = 0x460000, |
149 | .size = 0, | 149 | .size = MTDPART_SIZ_FULL, |
150 | }, | 150 | }, |
151 | }; | 151 | }; |
152 | 152 | ||
@@ -173,13 +173,10 @@ static struct mtd_partition partition_info_128KB_blk[] = { | |||
173 | { | 173 | { |
174 | .name = "Root File System", | 174 | .name = "Root File System", |
175 | .offset = 0x800000, | 175 | .offset = 0x800000, |
176 | .size = 0, | 176 | .size = MTDPART_SIZ_FULL, |
177 | }, | 177 | }, |
178 | }; | 178 | }; |
179 | 179 | ||
180 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
181 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
182 | #endif | ||
183 | 180 | ||
184 | /** | 181 | /** |
185 | * struct fsmc_nand_data - structure for FSMC NAND device state | 182 | * struct fsmc_nand_data - structure for FSMC NAND device state |
@@ -187,8 +184,6 @@ const char *part_probes[] = { "cmdlinepart", NULL }; | |||
187 | * @pid: Part ID on the AMBA PrimeCell format | 184 | * @pid: Part ID on the AMBA PrimeCell format |
188 | * @mtd: MTD info for a NAND flash. | 185 | * @mtd: MTD info for a NAND flash. |
189 | * @nand: Chip related info for a NAND flash. | 186 | * @nand: Chip related info for a NAND flash. |
190 | * @partitions: Partition info for a NAND Flash. | ||
191 | * @nr_partitions: Total number of partition of a NAND flash. | ||
192 | * | 187 | * |
193 | * @ecc_place: ECC placing locations in oobfree type format. | 188 | * @ecc_place: ECC placing locations in oobfree type format. |
194 | * @bank: Bank number for probed device. | 189 | * @bank: Bank number for probed device. |
@@ -203,8 +198,6 @@ struct fsmc_nand_data { | |||
203 | u32 pid; | 198 | u32 pid; |
204 | struct mtd_info mtd; | 199 | struct mtd_info mtd; |
205 | struct nand_chip nand; | 200 | struct nand_chip nand; |
206 | struct mtd_partition *partitions; | ||
207 | unsigned int nr_partitions; | ||
208 | 201 | ||
209 | struct fsmc_eccplace *ecc_place; | 202 | struct fsmc_eccplace *ecc_place; |
210 | unsigned int bank; | 203 | unsigned int bank; |
@@ -716,65 +709,17 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
716 | * platform data, | 709 | * platform data, |
717 | * default partition information present in driver. | 710 | * default partition information present in driver. |
718 | */ | 711 | */ |
719 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
720 | /* | 712 | /* |
721 | * Check if partition info passed via command line | 713 | * Check for partition info passed |
722 | */ | 714 | */ |
723 | host->mtd.name = "nand"; | 715 | host->mtd.name = "nand"; |
724 | host->nr_partitions = parse_mtd_partitions(&host->mtd, part_probes, | 716 | ret = mtd_device_parse_register(&host->mtd, NULL, 0, |
725 | &host->partitions, 0); | 717 | host->mtd.size <= 0x04000000 ? |
726 | if (host->nr_partitions <= 0) { | 718 | partition_info_16KB_blk : |
727 | #endif | 719 | partition_info_128KB_blk, |
728 | /* | 720 | host->mtd.size <= 0x04000000 ? |
729 | * Check if partition info passed via command line | 721 | ARRAY_SIZE(partition_info_16KB_blk) : |
730 | */ | 722 | ARRAY_SIZE(partition_info_128KB_blk)); |
731 | if (pdata->partitions) { | ||
732 | host->partitions = pdata->partitions; | ||
733 | host->nr_partitions = pdata->nr_partitions; | ||
734 | } else { | ||
735 | struct mtd_partition *partition; | ||
736 | int i; | ||
737 | |||
738 | /* Select the default partitions info */ | ||
739 | switch (host->mtd.size) { | ||
740 | case 0x01000000: | ||
741 | case 0x02000000: | ||
742 | case 0x04000000: | ||
743 | host->partitions = partition_info_16KB_blk; | ||
744 | host->nr_partitions = | ||
745 | sizeof(partition_info_16KB_blk) / | ||
746 | sizeof(struct mtd_partition); | ||
747 | break; | ||
748 | case 0x08000000: | ||
749 | case 0x10000000: | ||
750 | case 0x20000000: | ||
751 | case 0x40000000: | ||
752 | host->partitions = partition_info_128KB_blk; | ||
753 | host->nr_partitions = | ||
754 | sizeof(partition_info_128KB_blk) / | ||
755 | sizeof(struct mtd_partition); | ||
756 | break; | ||
757 | default: | ||
758 | ret = -ENXIO; | ||
759 | pr_err("Unsupported NAND size\n"); | ||
760 | goto err_probe; | ||
761 | } | ||
762 | |||
763 | partition = host->partitions; | ||
764 | for (i = 0; i < host->nr_partitions; i++, partition++) { | ||
765 | if (partition->size == 0) { | ||
766 | partition->size = host->mtd.size - | ||
767 | partition->offset; | ||
768 | break; | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
773 | } | ||
774 | #endif | ||
775 | |||
776 | ret = mtd_device_register(&host->mtd, host->partitions, | ||
777 | host->nr_partitions); | ||
778 | if (ret) | 723 | if (ret) |
779 | goto err_probe; | 724 | goto err_probe; |
780 | 725 | ||
@@ -822,7 +767,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) | |||
822 | platform_set_drvdata(pdev, NULL); | 767 | platform_set_drvdata(pdev, NULL); |
823 | 768 | ||
824 | if (host) { | 769 | if (host) { |
825 | mtd_device_unregister(&host->mtd); | 770 | nand_release(&host->mtd); |
826 | clk_disable(host->clk); | 771 | clk_disable(host->clk); |
827 | clk_put(host->clk); | 772 | clk_put(host->clk); |
828 | 773 | ||
diff --git a/drivers/mtd/nand/gpmi-nand/Makefile b/drivers/mtd/nand/gpmi-nand/Makefile new file mode 100644 index 000000000000..3a462487c35e --- /dev/null +++ b/drivers/mtd/nand/gpmi-nand/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi_nand.o | ||
2 | gpmi_nand-objs += gpmi-nand.o | ||
3 | gpmi_nand-objs += gpmi-lib.o | ||
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h new file mode 100644 index 000000000000..4effb8c579db --- /dev/null +++ b/drivers/mtd/nand/gpmi-nand/bch-regs.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * Freescale GPMI NAND Flash Driver | ||
3 | * | ||
4 | * Copyright 2008-2011 Freescale Semiconductor, Inc. | ||
5 | * Copyright 2008 Embedded Alley Solutions, Inc. | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | #ifndef __GPMI_NAND_BCH_REGS_H | ||
22 | #define __GPMI_NAND_BCH_REGS_H | ||
23 | |||
24 | #define HW_BCH_CTRL 0x00000000 | ||
25 | #define HW_BCH_CTRL_SET 0x00000004 | ||
26 | #define HW_BCH_CTRL_CLR 0x00000008 | ||
27 | #define HW_BCH_CTRL_TOG 0x0000000c | ||
28 | |||
29 | #define BM_BCH_CTRL_COMPLETE_IRQ_EN (1 << 8) | ||
30 | #define BM_BCH_CTRL_COMPLETE_IRQ (1 << 0) | ||
31 | |||
32 | #define HW_BCH_STATUS0 0x00000010 | ||
33 | #define HW_BCH_MODE 0x00000020 | ||
34 | #define HW_BCH_ENCODEPTR 0x00000030 | ||
35 | #define HW_BCH_DATAPTR 0x00000040 | ||
36 | #define HW_BCH_METAPTR 0x00000050 | ||
37 | #define HW_BCH_LAYOUTSELECT 0x00000070 | ||
38 | |||
39 | #define HW_BCH_FLASH0LAYOUT0 0x00000080 | ||
40 | |||
41 | #define BP_BCH_FLASH0LAYOUT0_NBLOCKS 24 | ||
42 | #define BM_BCH_FLASH0LAYOUT0_NBLOCKS (0xff << BP_BCH_FLASH0LAYOUT0_NBLOCKS) | ||
43 | #define BF_BCH_FLASH0LAYOUT0_NBLOCKS(v) \ | ||
44 | (((v) << BP_BCH_FLASH0LAYOUT0_NBLOCKS) & BM_BCH_FLASH0LAYOUT0_NBLOCKS) | ||
45 | |||
46 | #define BP_BCH_FLASH0LAYOUT0_META_SIZE 16 | ||
47 | #define BM_BCH_FLASH0LAYOUT0_META_SIZE (0xff << BP_BCH_FLASH0LAYOUT0_META_SIZE) | ||
48 | #define BF_BCH_FLASH0LAYOUT0_META_SIZE(v) \ | ||
49 | (((v) << BP_BCH_FLASH0LAYOUT0_META_SIZE)\ | ||
50 | & BM_BCH_FLASH0LAYOUT0_META_SIZE) | ||
51 | |||
52 | #define BP_BCH_FLASH0LAYOUT0_ECC0 12 | ||
53 | #define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0) | ||
54 | #define BF_BCH_FLASH0LAYOUT0_ECC0(v) \ | ||
55 | (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0) | ||
56 | |||
57 | #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0 | ||
58 | #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ | ||
59 | (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) | ||
60 | #define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v) \ | ||
61 | (((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\ | ||
62 | & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) | ||
63 | |||
64 | #define HW_BCH_FLASH0LAYOUT1 0x00000090 | ||
65 | |||
66 | #define BP_BCH_FLASH0LAYOUT1_PAGE_SIZE 16 | ||
67 | #define BM_BCH_FLASH0LAYOUT1_PAGE_SIZE \ | ||
68 | (0xffff << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE) | ||
69 | #define BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(v) \ | ||
70 | (((v) << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE) \ | ||
71 | & BM_BCH_FLASH0LAYOUT1_PAGE_SIZE) | ||
72 | |||
73 | #define BP_BCH_FLASH0LAYOUT1_ECCN 12 | ||
74 | #define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN) | ||
75 | #define BF_BCH_FLASH0LAYOUT1_ECCN(v) \ | ||
76 | (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN) | ||
77 | |||
78 | #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0 | ||
79 | #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ | ||
80 | (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) | ||
81 | #define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v) \ | ||
82 | (((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ | ||
83 | & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) | ||
84 | #endif | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c new file mode 100644 index 000000000000..de4db7604a3f --- /dev/null +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
@@ -0,0 +1,1057 @@ | |||
1 | /* | ||
2 | * Freescale GPMI NAND Flash Driver | ||
3 | * | ||
4 | * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. | ||
5 | * Copyright (C) 2008 Embedded Alley Solutions, Inc. | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | #include <linux/mtd/gpmi-nand.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/clk.h> | ||
24 | #include <mach/mxs.h> | ||
25 | |||
26 | #include "gpmi-nand.h" | ||
27 | #include "gpmi-regs.h" | ||
28 | #include "bch-regs.h" | ||
29 | |||
30 | struct timing_threshod timing_default_threshold = { | ||
31 | .max_data_setup_cycles = (BM_GPMI_TIMING0_DATA_SETUP >> | ||
32 | BP_GPMI_TIMING0_DATA_SETUP), | ||
33 | .internal_data_setup_in_ns = 0, | ||
34 | .max_sample_delay_factor = (BM_GPMI_CTRL1_RDN_DELAY >> | ||
35 | BP_GPMI_CTRL1_RDN_DELAY), | ||
36 | .max_dll_clock_period_in_ns = 32, | ||
37 | .max_dll_delay_in_ns = 16, | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * Clear the bit and poll it cleared. This is usually called with | ||
42 | * a reset address and mask being either SFTRST(bit 31) or CLKGATE | ||
43 | * (bit 30). | ||
44 | */ | ||
45 | static int clear_poll_bit(void __iomem *addr, u32 mask) | ||
46 | { | ||
47 | int timeout = 0x400; | ||
48 | |||
49 | /* clear the bit */ | ||
50 | __mxs_clrl(mask, addr); | ||
51 | |||
52 | /* | ||
53 | * SFTRST needs 3 GPMI clocks to settle, the reference manual | ||
54 | * recommends to wait 1us. | ||
55 | */ | ||
56 | udelay(1); | ||
57 | |||
58 | /* poll the bit becoming clear */ | ||
59 | while ((readl(addr) & mask) && --timeout) | ||
60 | /* nothing */; | ||
61 | |||
62 | return !timeout; | ||
63 | } | ||
64 | |||
65 | #define MODULE_CLKGATE (1 << 30) | ||
66 | #define MODULE_SFTRST (1 << 31) | ||
67 | /* | ||
68 | * The current mxs_reset_block() will do two things: | ||
69 | * [1] enable the module. | ||
70 | * [2] reset the module. | ||
71 | * | ||
72 | * In most of the cases, it's ok. But there is a hardware bug in the BCH block. | ||
73 | * If you try to soft reset the BCH block, it becomes unusable until | ||
74 | * the next hard reset. This case occurs in the NAND boot mode. When the board | ||
75 | * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. | ||
76 | * So If the driver tries to reset the BCH again, the BCH will not work anymore. | ||
77 | * You will see a DMA timeout in this case. | ||
78 | * | ||
79 | * To avoid this bug, just add a new parameter `just_enable` for | ||
80 | * the mxs_reset_block(), and rewrite it here. | ||
81 | */ | ||
82 | int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) | ||
83 | { | ||
84 | int ret; | ||
85 | int timeout = 0x400; | ||
86 | |||
87 | /* clear and poll SFTRST */ | ||
88 | ret = clear_poll_bit(reset_addr, MODULE_SFTRST); | ||
89 | if (unlikely(ret)) | ||
90 | goto error; | ||
91 | |||
92 | /* clear CLKGATE */ | ||
93 | __mxs_clrl(MODULE_CLKGATE, reset_addr); | ||
94 | |||
95 | if (!just_enable) { | ||
96 | /* set SFTRST to reset the block */ | ||
97 | __mxs_setl(MODULE_SFTRST, reset_addr); | ||
98 | udelay(1); | ||
99 | |||
100 | /* poll CLKGATE becoming set */ | ||
101 | while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout) | ||
102 | /* nothing */; | ||
103 | if (unlikely(!timeout)) | ||
104 | goto error; | ||
105 | } | ||
106 | |||
107 | /* clear and poll SFTRST */ | ||
108 | ret = clear_poll_bit(reset_addr, MODULE_SFTRST); | ||
109 | if (unlikely(ret)) | ||
110 | goto error; | ||
111 | |||
112 | /* clear and poll CLKGATE */ | ||
113 | ret = clear_poll_bit(reset_addr, MODULE_CLKGATE); | ||
114 | if (unlikely(ret)) | ||
115 | goto error; | ||
116 | |||
117 | return 0; | ||
118 | |||
119 | error: | ||
120 | pr_err("%s(%p): module reset timeout\n", __func__, reset_addr); | ||
121 | return -ETIMEDOUT; | ||
122 | } | ||
123 | |||
124 | int gpmi_init(struct gpmi_nand_data *this) | ||
125 | { | ||
126 | struct resources *r = &this->resources; | ||
127 | int ret; | ||
128 | |||
129 | ret = clk_enable(r->clock); | ||
130 | if (ret) | ||
131 | goto err_out; | ||
132 | ret = gpmi_reset_block(r->gpmi_regs, false); | ||
133 | if (ret) | ||
134 | goto err_out; | ||
135 | |||
136 | /* Choose NAND mode. */ | ||
137 | writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); | ||
138 | |||
139 | /* Set the IRQ polarity. */ | ||
140 | writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY, | ||
141 | r->gpmi_regs + HW_GPMI_CTRL1_SET); | ||
142 | |||
143 | /* Disable Write-Protection. */ | ||
144 | writel(BM_GPMI_CTRL1_DEV_RESET, r->gpmi_regs + HW_GPMI_CTRL1_SET); | ||
145 | |||
146 | /* Select BCH ECC. */ | ||
147 | writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET); | ||
148 | |||
149 | clk_disable(r->clock); | ||
150 | return 0; | ||
151 | err_out: | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | /* This function is very useful. It is called only when the bug occur. */ | ||
156 | void gpmi_dump_info(struct gpmi_nand_data *this) | ||
157 | { | ||
158 | struct resources *r = &this->resources; | ||
159 | struct bch_geometry *geo = &this->bch_geometry; | ||
160 | u32 reg; | ||
161 | int i; | ||
162 | |||
163 | pr_err("Show GPMI registers :\n"); | ||
164 | for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) { | ||
165 | reg = readl(r->gpmi_regs + i * 0x10); | ||
166 | pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg); | ||
167 | } | ||
168 | |||
169 | /* start to print out the BCH info */ | ||
170 | pr_err("BCH Geometry :\n"); | ||
171 | pr_err("GF length : %u\n", geo->gf_len); | ||
172 | pr_err("ECC Strength : %u\n", geo->ecc_strength); | ||
173 | pr_err("Page Size in Bytes : %u\n", geo->page_size); | ||
174 | pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size); | ||
175 | pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size); | ||
176 | pr_err("ECC Chunk Count : %u\n", geo->ecc_chunk_count); | ||
177 | pr_err("Payload Size in Bytes : %u\n", geo->payload_size); | ||
178 | pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size); | ||
179 | pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset); | ||
180 | pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset); | ||
181 | pr_err("Block Mark Bit Offset : %u\n", geo->block_mark_bit_offset); | ||
182 | } | ||
183 | |||
184 | /* Configures the geometry for BCH. */ | ||
185 | int bch_set_geometry(struct gpmi_nand_data *this) | ||
186 | { | ||
187 | struct resources *r = &this->resources; | ||
188 | struct bch_geometry *bch_geo = &this->bch_geometry; | ||
189 | unsigned int block_count; | ||
190 | unsigned int block_size; | ||
191 | unsigned int metadata_size; | ||
192 | unsigned int ecc_strength; | ||
193 | unsigned int page_size; | ||
194 | int ret; | ||
195 | |||
196 | if (common_nfc_set_geometry(this)) | ||
197 | return !0; | ||
198 | |||
199 | block_count = bch_geo->ecc_chunk_count - 1; | ||
200 | block_size = bch_geo->ecc_chunk_size; | ||
201 | metadata_size = bch_geo->metadata_size; | ||
202 | ecc_strength = bch_geo->ecc_strength >> 1; | ||
203 | page_size = bch_geo->page_size; | ||
204 | |||
205 | ret = clk_enable(r->clock); | ||
206 | if (ret) | ||
207 | goto err_out; | ||
208 | |||
209 | ret = gpmi_reset_block(r->bch_regs, true); | ||
210 | if (ret) | ||
211 | goto err_out; | ||
212 | |||
213 | /* Configure layout 0. */ | ||
214 | writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) | ||
215 | | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) | ||
216 | | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength) | ||
217 | | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size), | ||
218 | r->bch_regs + HW_BCH_FLASH0LAYOUT0); | ||
219 | |||
220 | writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) | ||
221 | | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength) | ||
222 | | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size), | ||
223 | r->bch_regs + HW_BCH_FLASH0LAYOUT1); | ||
224 | |||
225 | /* Set *all* chip selects to use layout 0. */ | ||
226 | writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT); | ||
227 | |||
228 | /* Enable interrupts. */ | ||
229 | writel(BM_BCH_CTRL_COMPLETE_IRQ_EN, | ||
230 | r->bch_regs + HW_BCH_CTRL_SET); | ||
231 | |||
232 | clk_disable(r->clock); | ||
233 | return 0; | ||
234 | err_out: | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | /* Converts time in nanoseconds to cycles. */ | ||
239 | static unsigned int ns_to_cycles(unsigned int time, | ||
240 | unsigned int period, unsigned int min) | ||
241 | { | ||
242 | unsigned int k; | ||
243 | |||
244 | k = (time + period - 1) / period; | ||
245 | return max(k, min); | ||
246 | } | ||
247 | |||
248 | /* Apply timing to current hardware conditions. */ | ||
249 | static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, | ||
250 | struct gpmi_nfc_hardware_timing *hw) | ||
251 | { | ||
252 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
253 | struct timing_threshod *nfc = &timing_default_threshold; | ||
254 | struct nand_chip *nand = &this->nand; | ||
255 | struct nand_timing target = this->timing; | ||
256 | bool improved_timing_is_available; | ||
257 | unsigned long clock_frequency_in_hz; | ||
258 | unsigned int clock_period_in_ns; | ||
259 | bool dll_use_half_periods; | ||
260 | unsigned int dll_delay_shift; | ||
261 | unsigned int max_sample_delay_in_ns; | ||
262 | unsigned int address_setup_in_cycles; | ||
263 | unsigned int data_setup_in_ns; | ||
264 | unsigned int data_setup_in_cycles; | ||
265 | unsigned int data_hold_in_cycles; | ||
266 | int ideal_sample_delay_in_ns; | ||
267 | unsigned int sample_delay_factor; | ||
268 | int tEYE; | ||
269 | unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns; | ||
270 | unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns; | ||
271 | |||
272 | /* | ||
273 | * If there are multiple chips, we need to relax the timings to allow | ||
274 | * for signal distortion due to higher capacitance. | ||
275 | */ | ||
276 | if (nand->numchips > 2) { | ||
277 | target.data_setup_in_ns += 10; | ||
278 | target.data_hold_in_ns += 10; | ||
279 | target.address_setup_in_ns += 10; | ||
280 | } else if (nand->numchips > 1) { | ||
281 | target.data_setup_in_ns += 5; | ||
282 | target.data_hold_in_ns += 5; | ||
283 | target.address_setup_in_ns += 5; | ||
284 | } | ||
285 | |||
286 | /* Check if improved timing information is available. */ | ||
287 | improved_timing_is_available = | ||
288 | (target.tREA_in_ns >= 0) && | ||
289 | (target.tRLOH_in_ns >= 0) && | ||
290 | (target.tRHOH_in_ns >= 0) ; | ||
291 | |||
292 | /* Inspect the clock. */ | ||
293 | clock_frequency_in_hz = nfc->clock_frequency_in_hz; | ||
294 | clock_period_in_ns = 1000000000 / clock_frequency_in_hz; | ||
295 | |||
296 | /* | ||
297 | * The NFC quantizes setup and hold parameters in terms of clock cycles. | ||
298 | * Here, we quantize the setup and hold timing parameters to the | ||
299 | * next-highest clock period to make sure we apply at least the | ||
300 | * specified times. | ||
301 | * | ||
302 | * For data setup and data hold, the hardware interprets a value of zero | ||
303 | * as the largest possible delay. This is not what's intended by a zero | ||
304 | * in the input parameter, so we impose a minimum of one cycle. | ||
305 | */ | ||
306 | data_setup_in_cycles = ns_to_cycles(target.data_setup_in_ns, | ||
307 | clock_period_in_ns, 1); | ||
308 | data_hold_in_cycles = ns_to_cycles(target.data_hold_in_ns, | ||
309 | clock_period_in_ns, 1); | ||
310 | address_setup_in_cycles = ns_to_cycles(target.address_setup_in_ns, | ||
311 | clock_period_in_ns, 0); | ||
312 | |||
313 | /* | ||
314 | * The clock's period affects the sample delay in a number of ways: | ||
315 | * | ||
316 | * (1) The NFC HAL tells us the maximum clock period the sample delay | ||
317 | * DLL can tolerate. If the clock period is greater than half that | ||
318 | * maximum, we must configure the DLL to be driven by half periods. | ||
319 | * | ||
320 | * (2) We need to convert from an ideal sample delay, in ns, to a | ||
321 | * "sample delay factor," which the NFC uses. This factor depends on | ||
322 | * whether we're driving the DLL with full or half periods. | ||
323 | * Paraphrasing the reference manual: | ||
324 | * | ||
325 | * AD = SDF x 0.125 x RP | ||
326 | * | ||
327 | * where: | ||
328 | * | ||
329 | * AD is the applied delay, in ns. | ||
330 | * SDF is the sample delay factor, which is dimensionless. | ||
331 | * RP is the reference period, in ns, which is a full clock period | ||
332 | * if the DLL is being driven by full periods, or half that if | ||
333 | * the DLL is being driven by half periods. | ||
334 | * | ||
335 | * Let's re-arrange this in a way that's more useful to us: | ||
336 | * | ||
337 | * 8 | ||
338 | * SDF = AD x ---- | ||
339 | * RP | ||
340 | * | ||
341 | * The reference period is either the clock period or half that, so this | ||
342 | * is: | ||
343 | * | ||
344 | * 8 AD x DDF | ||
345 | * SDF = AD x ----- = -------- | ||
346 | * f x P P | ||
347 | * | ||
348 | * where: | ||
349 | * | ||
350 | * f is 1 or 1/2, depending on how we're driving the DLL. | ||
351 | * P is the clock period. | ||
352 | * DDF is the DLL Delay Factor, a dimensionless value that | ||
353 | * incorporates all the constants in the conversion. | ||
354 | * | ||
355 | * DDF will be either 8 or 16, both of which are powers of two. We can | ||
356 | * reduce the cost of this conversion by using bit shifts instead of | ||
357 | * multiplication or division. Thus: | ||
358 | * | ||
359 | * AD << DDS | ||
360 | * SDF = --------- | ||
361 | * P | ||
362 | * | ||
363 | * or | ||
364 | * | ||
365 | * AD = (SDF >> DDS) x P | ||
366 | * | ||
367 | * where: | ||
368 | * | ||
369 | * DDS is the DLL Delay Shift, the logarithm to base 2 of the DDF. | ||
370 | */ | ||
371 | if (clock_period_in_ns > (nfc->max_dll_clock_period_in_ns >> 1)) { | ||
372 | dll_use_half_periods = true; | ||
373 | dll_delay_shift = 3 + 1; | ||
374 | } else { | ||
375 | dll_use_half_periods = false; | ||
376 | dll_delay_shift = 3; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * Compute the maximum sample delay the NFC allows, under current | ||
381 | * conditions. If the clock is running too slowly, no sample delay is | ||
382 | * possible. | ||
383 | */ | ||
384 | if (clock_period_in_ns > nfc->max_dll_clock_period_in_ns) | ||
385 | max_sample_delay_in_ns = 0; | ||
386 | else { | ||
387 | /* | ||
388 | * Compute the delay implied by the largest sample delay factor | ||
389 | * the NFC allows. | ||
390 | */ | ||
391 | max_sample_delay_in_ns = | ||
392 | (nfc->max_sample_delay_factor * clock_period_in_ns) >> | ||
393 | dll_delay_shift; | ||
394 | |||
395 | /* | ||
396 | * Check if the implied sample delay larger than the NFC | ||
397 | * actually allows. | ||
398 | */ | ||
399 | if (max_sample_delay_in_ns > nfc->max_dll_delay_in_ns) | ||
400 | max_sample_delay_in_ns = nfc->max_dll_delay_in_ns; | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * Check if improved timing information is available. If not, we have to | ||
405 | * use a less-sophisticated algorithm. | ||
406 | */ | ||
407 | if (!improved_timing_is_available) { | ||
408 | /* | ||
409 | * Fold the read setup time required by the NFC into the ideal | ||
410 | * sample delay. | ||
411 | */ | ||
412 | ideal_sample_delay_in_ns = target.gpmi_sample_delay_in_ns + | ||
413 | nfc->internal_data_setup_in_ns; | ||
414 | |||
415 | /* | ||
416 | * The ideal sample delay may be greater than the maximum | ||
417 | * allowed by the NFC. If so, we can trade off sample delay time | ||
418 | * for more data setup time. | ||
419 | * | ||
420 | * In each iteration of the following loop, we add a cycle to | ||
421 | * the data setup time and subtract a corresponding amount from | ||
422 | * the sample delay until we've satisified the constraints or | ||
423 | * can't do any better. | ||
424 | */ | ||
425 | while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) && | ||
426 | (data_setup_in_cycles < nfc->max_data_setup_cycles)) { | ||
427 | |||
428 | data_setup_in_cycles++; | ||
429 | ideal_sample_delay_in_ns -= clock_period_in_ns; | ||
430 | |||
431 | if (ideal_sample_delay_in_ns < 0) | ||
432 | ideal_sample_delay_in_ns = 0; | ||
433 | |||
434 | } | ||
435 | |||
436 | /* | ||
437 | * Compute the sample delay factor that corresponds most closely | ||
438 | * to the ideal sample delay. If the result is too large for the | ||
439 | * NFC, use the maximum value. | ||
440 | * | ||
441 | * Notice that we use the ns_to_cycles function to compute the | ||
442 | * sample delay factor. We do this because the form of the | ||
443 | * computation is the same as that for calculating cycles. | ||
444 | */ | ||
445 | sample_delay_factor = | ||
446 | ns_to_cycles( | ||
447 | ideal_sample_delay_in_ns << dll_delay_shift, | ||
448 | clock_period_in_ns, 0); | ||
449 | |||
450 | if (sample_delay_factor > nfc->max_sample_delay_factor) | ||
451 | sample_delay_factor = nfc->max_sample_delay_factor; | ||
452 | |||
453 | /* Skip to the part where we return our results. */ | ||
454 | goto return_results; | ||
455 | } | ||
456 | |||
457 | /* | ||
458 | * If control arrives here, we have more detailed timing information, | ||
459 | * so we can use a better algorithm. | ||
460 | */ | ||
461 | |||
462 | /* | ||
463 | * Fold the read setup time required by the NFC into the maximum | ||
464 | * propagation delay. | ||
465 | */ | ||
466 | max_prop_delay_in_ns += nfc->internal_data_setup_in_ns; | ||
467 | |||
468 | /* | ||
469 | * Earlier, we computed the number of clock cycles required to satisfy | ||
470 | * the data setup time. Now, we need to know the actual nanoseconds. | ||
471 | */ | ||
472 | data_setup_in_ns = clock_period_in_ns * data_setup_in_cycles; | ||
473 | |||
474 | /* | ||
475 | * Compute tEYE, the width of the data eye when reading from the NAND | ||
476 | * Flash. The eye width is fundamentally determined by the data setup | ||
477 | * time, perturbed by propagation delays and some characteristics of the | ||
478 | * NAND Flash device. | ||
479 | * | ||
480 | * start of the eye = max_prop_delay + tREA | ||
481 | * end of the eye = min_prop_delay + tRHOH + data_setup | ||
482 | */ | ||
483 | tEYE = (int)min_prop_delay_in_ns + (int)target.tRHOH_in_ns + | ||
484 | (int)data_setup_in_ns; | ||
485 | |||
486 | tEYE -= (int)max_prop_delay_in_ns + (int)target.tREA_in_ns; | ||
487 | |||
488 | /* | ||
489 | * The eye must be open. If it's not, we can try to open it by | ||
490 | * increasing its main forcer, the data setup time. | ||
491 | * | ||
492 | * In each iteration of the following loop, we increase the data setup | ||
493 | * time by a single clock cycle. We do this until either the eye is | ||
494 | * open or we run into NFC limits. | ||
495 | */ | ||
496 | while ((tEYE <= 0) && | ||
497 | (data_setup_in_cycles < nfc->max_data_setup_cycles)) { | ||
498 | /* Give a cycle to data setup. */ | ||
499 | data_setup_in_cycles++; | ||
500 | /* Synchronize the data setup time with the cycles. */ | ||
501 | data_setup_in_ns += clock_period_in_ns; | ||
502 | /* Adjust tEYE accordingly. */ | ||
503 | tEYE += clock_period_in_ns; | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * When control arrives here, the eye is open. The ideal time to sample | ||
508 | * the data is in the center of the eye: | ||
509 | * | ||
510 | * end of the eye + start of the eye | ||
511 | * --------------------------------- - data_setup | ||
512 | * 2 | ||
513 | * | ||
514 | * After some algebra, this simplifies to the code immediately below. | ||
515 | */ | ||
516 | ideal_sample_delay_in_ns = | ||
517 | ((int)max_prop_delay_in_ns + | ||
518 | (int)target.tREA_in_ns + | ||
519 | (int)min_prop_delay_in_ns + | ||
520 | (int)target.tRHOH_in_ns - | ||
521 | (int)data_setup_in_ns) >> 1; | ||
522 | |||
523 | /* | ||
524 | * The following figure illustrates some aspects of a NAND Flash read: | ||
525 | * | ||
526 | * | ||
527 | * __ _____________________________________ | ||
528 | * RDN \_________________/ | ||
529 | * | ||
530 | * <---- tEYE -----> | ||
531 | * /-----------------\ | ||
532 | * Read Data ----------------------------< >--------- | ||
533 | * \-----------------/ | ||
534 | * ^ ^ ^ ^ | ||
535 | * | | | | | ||
536 | * |<--Data Setup -->|<--Delay Time -->| | | ||
537 | * | | | | | ||
538 | * | | | | ||
539 | * | |<-- Quantized Delay Time -->| | ||
540 | * | | | | ||
541 | * | ||
542 | * | ||
543 | * We have some issues we must now address: | ||
544 | * | ||
545 | * (1) The *ideal* sample delay time must not be negative. If it is, we | ||
546 | * jam it to zero. | ||
547 | * | ||
548 | * (2) The *ideal* sample delay time must not be greater than that | ||
549 | * allowed by the NFC. If it is, we can increase the data setup | ||
550 | * time, which will reduce the delay between the end of the data | ||
551 | * setup and the center of the eye. It will also make the eye | ||
552 | * larger, which might help with the next issue... | ||
553 | * | ||
554 | * (3) The *quantized* sample delay time must not fall either before the | ||
555 | * eye opens or after it closes (the latter is the problem | ||
556 | * illustrated in the above figure). | ||
557 | */ | ||
558 | |||
559 | /* Jam a negative ideal sample delay to zero. */ | ||
560 | if (ideal_sample_delay_in_ns < 0) | ||
561 | ideal_sample_delay_in_ns = 0; | ||
562 | |||
563 | /* | ||
564 | * Extend the data setup as needed to reduce the ideal sample delay | ||
565 | * below the maximum permitted by the NFC. | ||
566 | */ | ||
567 | while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) && | ||
568 | (data_setup_in_cycles < nfc->max_data_setup_cycles)) { | ||
569 | |||
570 | /* Give a cycle to data setup. */ | ||
571 | data_setup_in_cycles++; | ||
572 | /* Synchronize the data setup time with the cycles. */ | ||
573 | data_setup_in_ns += clock_period_in_ns; | ||
574 | /* Adjust tEYE accordingly. */ | ||
575 | tEYE += clock_period_in_ns; | ||
576 | |||
577 | /* | ||
578 | * Decrease the ideal sample delay by one half cycle, to keep it | ||
579 | * in the middle of the eye. | ||
580 | */ | ||
581 | ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1); | ||
582 | |||
583 | /* Jam a negative ideal sample delay to zero. */ | ||
584 | if (ideal_sample_delay_in_ns < 0) | ||
585 | ideal_sample_delay_in_ns = 0; | ||
586 | } | ||
587 | |||
588 | /* | ||
589 | * Compute the sample delay factor that corresponds to the ideal sample | ||
590 | * delay. If the result is too large, then use the maximum allowed | ||
591 | * value. | ||
592 | * | ||
593 | * Notice that we use the ns_to_cycles function to compute the sample | ||
594 | * delay factor. We do this because the form of the computation is the | ||
595 | * same as that for calculating cycles. | ||
596 | */ | ||
597 | sample_delay_factor = | ||
598 | ns_to_cycles(ideal_sample_delay_in_ns << dll_delay_shift, | ||
599 | clock_period_in_ns, 0); | ||
600 | |||
601 | if (sample_delay_factor > nfc->max_sample_delay_factor) | ||
602 | sample_delay_factor = nfc->max_sample_delay_factor; | ||
603 | |||
604 | /* | ||
605 | * These macros conveniently encapsulate a computation we'll use to | ||
606 | * continuously evaluate whether or not the data sample delay is inside | ||
607 | * the eye. | ||
608 | */ | ||
609 | #define IDEAL_DELAY ((int) ideal_sample_delay_in_ns) | ||
610 | |||
611 | #define QUANTIZED_DELAY \ | ||
612 | ((int) ((sample_delay_factor * clock_period_in_ns) >> \ | ||
613 | dll_delay_shift)) | ||
614 | |||
615 | #define DELAY_ERROR (abs(QUANTIZED_DELAY - IDEAL_DELAY)) | ||
616 | |||
617 | #define SAMPLE_IS_NOT_WITHIN_THE_EYE (DELAY_ERROR > (tEYE >> 1)) | ||
618 | |||
619 | /* | ||
620 | * While the quantized sample time falls outside the eye, reduce the | ||
621 | * sample delay or extend the data setup to move the sampling point back | ||
622 | * toward the eye. Do not allow the number of data setup cycles to | ||
623 | * exceed the maximum allowed by the NFC. | ||
624 | */ | ||
625 | while (SAMPLE_IS_NOT_WITHIN_THE_EYE && | ||
626 | (data_setup_in_cycles < nfc->max_data_setup_cycles)) { | ||
627 | /* | ||
628 | * If control arrives here, the quantized sample delay falls | ||
629 | * outside the eye. Check if it's before the eye opens, or after | ||
630 | * the eye closes. | ||
631 | */ | ||
632 | if (QUANTIZED_DELAY > IDEAL_DELAY) { | ||
633 | /* | ||
634 | * If control arrives here, the quantized sample delay | ||
635 | * falls after the eye closes. Decrease the quantized | ||
636 | * delay time and then go back to re-evaluate. | ||
637 | */ | ||
638 | if (sample_delay_factor != 0) | ||
639 | sample_delay_factor--; | ||
640 | continue; | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * If control arrives here, the quantized sample delay falls | ||
645 | * before the eye opens. Shift the sample point by increasing | ||
646 | * data setup time. This will also make the eye larger. | ||
647 | */ | ||
648 | |||
649 | /* Give a cycle to data setup. */ | ||
650 | data_setup_in_cycles++; | ||
651 | /* Synchronize the data setup time with the cycles. */ | ||
652 | data_setup_in_ns += clock_period_in_ns; | ||
653 | /* Adjust tEYE accordingly. */ | ||
654 | tEYE += clock_period_in_ns; | ||
655 | |||
656 | /* | ||
657 | * Decrease the ideal sample delay by one half cycle, to keep it | ||
658 | * in the middle of the eye. | ||
659 | */ | ||
660 | ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1); | ||
661 | |||
662 | /* ...and one less period for the delay time. */ | ||
663 | ideal_sample_delay_in_ns -= clock_period_in_ns; | ||
664 | |||
665 | /* Jam a negative ideal sample delay to zero. */ | ||
666 | if (ideal_sample_delay_in_ns < 0) | ||
667 | ideal_sample_delay_in_ns = 0; | ||
668 | |||
669 | /* | ||
670 | * We have a new ideal sample delay, so re-compute the quantized | ||
671 | * delay. | ||
672 | */ | ||
673 | sample_delay_factor = | ||
674 | ns_to_cycles( | ||
675 | ideal_sample_delay_in_ns << dll_delay_shift, | ||
676 | clock_period_in_ns, 0); | ||
677 | |||
678 | if (sample_delay_factor > nfc->max_sample_delay_factor) | ||
679 | sample_delay_factor = nfc->max_sample_delay_factor; | ||
680 | } | ||
681 | |||
682 | /* Control arrives here when we're ready to return our results. */ | ||
683 | return_results: | ||
684 | hw->data_setup_in_cycles = data_setup_in_cycles; | ||
685 | hw->data_hold_in_cycles = data_hold_in_cycles; | ||
686 | hw->address_setup_in_cycles = address_setup_in_cycles; | ||
687 | hw->use_half_periods = dll_use_half_periods; | ||
688 | hw->sample_delay_factor = sample_delay_factor; | ||
689 | |||
690 | /* Return success. */ | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | /* Begin the I/O */ | ||
695 | void gpmi_begin(struct gpmi_nand_data *this) | ||
696 | { | ||
697 | struct resources *r = &this->resources; | ||
698 | struct timing_threshod *nfc = &timing_default_threshold; | ||
699 | unsigned char *gpmi_regs = r->gpmi_regs; | ||
700 | unsigned int clock_period_in_ns; | ||
701 | uint32_t reg; | ||
702 | unsigned int dll_wait_time_in_us; | ||
703 | struct gpmi_nfc_hardware_timing hw; | ||
704 | int ret; | ||
705 | |||
706 | /* Enable the clock. */ | ||
707 | ret = clk_enable(r->clock); | ||
708 | if (ret) { | ||
709 | pr_err("We failed in enable the clk\n"); | ||
710 | goto err_out; | ||
711 | } | ||
712 | |||
713 | /* set ready/busy timeout */ | ||
714 | writel(0x500 << BP_GPMI_TIMING1_BUSY_TIMEOUT, | ||
715 | gpmi_regs + HW_GPMI_TIMING1); | ||
716 | |||
717 | /* Get the timing information we need. */ | ||
718 | nfc->clock_frequency_in_hz = clk_get_rate(r->clock); | ||
719 | clock_period_in_ns = 1000000000 / nfc->clock_frequency_in_hz; | ||
720 | |||
721 | gpmi_nfc_compute_hardware_timing(this, &hw); | ||
722 | |||
723 | /* Set up all the simple timing parameters. */ | ||
724 | reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) | | ||
725 | BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles) | | ||
726 | BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles) ; | ||
727 | |||
728 | writel(reg, gpmi_regs + HW_GPMI_TIMING0); | ||
729 | |||
730 | /* | ||
731 | * DLL_ENABLE must be set to 0 when setting RDN_DELAY or HALF_PERIOD. | ||
732 | */ | ||
733 | writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_CLR); | ||
734 | |||
735 | /* Clear out the DLL control fields. */ | ||
736 | writel(BM_GPMI_CTRL1_RDN_DELAY, gpmi_regs + HW_GPMI_CTRL1_CLR); | ||
737 | writel(BM_GPMI_CTRL1_HALF_PERIOD, gpmi_regs + HW_GPMI_CTRL1_CLR); | ||
738 | |||
739 | /* If no sample delay is called for, return immediately. */ | ||
740 | if (!hw.sample_delay_factor) | ||
741 | return; | ||
742 | |||
743 | /* Configure the HALF_PERIOD flag. */ | ||
744 | if (hw.use_half_periods) | ||
745 | writel(BM_GPMI_CTRL1_HALF_PERIOD, | ||
746 | gpmi_regs + HW_GPMI_CTRL1_SET); | ||
747 | |||
748 | /* Set the delay factor. */ | ||
749 | writel(BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor), | ||
750 | gpmi_regs + HW_GPMI_CTRL1_SET); | ||
751 | |||
752 | /* Enable the DLL. */ | ||
753 | writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_SET); | ||
754 | |||
755 | /* | ||
756 | * After we enable the GPMI DLL, we have to wait 64 clock cycles before | ||
757 | * we can use the GPMI. | ||
758 | * | ||
759 | * Calculate the amount of time we need to wait, in microseconds. | ||
760 | */ | ||
761 | dll_wait_time_in_us = (clock_period_in_ns * 64) / 1000; | ||
762 | |||
763 | if (!dll_wait_time_in_us) | ||
764 | dll_wait_time_in_us = 1; | ||
765 | |||
766 | /* Wait for the DLL to settle. */ | ||
767 | udelay(dll_wait_time_in_us); | ||
768 | |||
769 | err_out: | ||
770 | return; | ||
771 | } | ||
772 | |||
773 | void gpmi_end(struct gpmi_nand_data *this) | ||
774 | { | ||
775 | struct resources *r = &this->resources; | ||
776 | clk_disable(r->clock); | ||
777 | } | ||
778 | |||
779 | /* Clears a BCH interrupt. */ | ||
780 | void gpmi_clear_bch(struct gpmi_nand_data *this) | ||
781 | { | ||
782 | struct resources *r = &this->resources; | ||
783 | writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR); | ||
784 | } | ||
785 | |||
786 | /* Returns the Ready/Busy status of the given chip. */ | ||
787 | int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) | ||
788 | { | ||
789 | struct resources *r = &this->resources; | ||
790 | uint32_t mask = 0; | ||
791 | uint32_t reg = 0; | ||
792 | |||
793 | if (GPMI_IS_MX23(this)) { | ||
794 | mask = MX23_BM_GPMI_DEBUG_READY0 << chip; | ||
795 | reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); | ||
796 | } else if (GPMI_IS_MX28(this)) { | ||
797 | mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); | ||
798 | reg = readl(r->gpmi_regs + HW_GPMI_STAT); | ||
799 | } else | ||
800 | pr_err("unknow arch.\n"); | ||
801 | return reg & mask; | ||
802 | } | ||
803 | |||
804 | static inline void set_dma_type(struct gpmi_nand_data *this, | ||
805 | enum dma_ops_type type) | ||
806 | { | ||
807 | this->last_dma_type = this->dma_type; | ||
808 | this->dma_type = type; | ||
809 | } | ||
810 | |||
811 | int gpmi_send_command(struct gpmi_nand_data *this) | ||
812 | { | ||
813 | struct dma_chan *channel = get_dma_chan(this); | ||
814 | struct dma_async_tx_descriptor *desc; | ||
815 | struct scatterlist *sgl; | ||
816 | int chip = this->current_chip; | ||
817 | u32 pio[3]; | ||
818 | |||
819 | /* [1] send out the PIO words */ | ||
820 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE) | ||
821 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
822 | | BF_GPMI_CTRL0_CS(chip, this) | ||
823 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
824 | | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE) | ||
825 | | BM_GPMI_CTRL0_ADDRESS_INCREMENT | ||
826 | | BF_GPMI_CTRL0_XFER_COUNT(this->command_length); | ||
827 | pio[1] = pio[2] = 0; | ||
828 | desc = channel->device->device_prep_slave_sg(channel, | ||
829 | (struct scatterlist *)pio, | ||
830 | ARRAY_SIZE(pio), DMA_NONE, 0); | ||
831 | if (!desc) { | ||
832 | pr_err("step 1 error\n"); | ||
833 | return -1; | ||
834 | } | ||
835 | |||
836 | /* [2] send out the COMMAND + ADDRESS string stored in @buffer */ | ||
837 | sgl = &this->cmd_sgl; | ||
838 | |||
839 | sg_init_one(sgl, this->cmd_buffer, this->command_length); | ||
840 | dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE); | ||
841 | desc = channel->device->device_prep_slave_sg(channel, | ||
842 | sgl, 1, DMA_TO_DEVICE, 1); | ||
843 | if (!desc) { | ||
844 | pr_err("step 2 error\n"); | ||
845 | return -1; | ||
846 | } | ||
847 | |||
848 | /* [3] submit the DMA */ | ||
849 | set_dma_type(this, DMA_FOR_COMMAND); | ||
850 | return start_dma_without_bch_irq(this, desc); | ||
851 | } | ||
852 | |||
853 | int gpmi_send_data(struct gpmi_nand_data *this) | ||
854 | { | ||
855 | struct dma_async_tx_descriptor *desc; | ||
856 | struct dma_chan *channel = get_dma_chan(this); | ||
857 | int chip = this->current_chip; | ||
858 | uint32_t command_mode; | ||
859 | uint32_t address; | ||
860 | u32 pio[2]; | ||
861 | |||
862 | /* [1] PIO */ | ||
863 | command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE; | ||
864 | address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA; | ||
865 | |||
866 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode) | ||
867 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
868 | | BF_GPMI_CTRL0_CS(chip, this) | ||
869 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
870 | | BF_GPMI_CTRL0_ADDRESS(address) | ||
871 | | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len); | ||
872 | pio[1] = 0; | ||
873 | desc = channel->device->device_prep_slave_sg(channel, | ||
874 | (struct scatterlist *)pio, | ||
875 | ARRAY_SIZE(pio), DMA_NONE, 0); | ||
876 | if (!desc) { | ||
877 | pr_err("step 1 error\n"); | ||
878 | return -1; | ||
879 | } | ||
880 | |||
881 | /* [2] send DMA request */ | ||
882 | prepare_data_dma(this, DMA_TO_DEVICE); | ||
883 | desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, | ||
884 | 1, DMA_TO_DEVICE, 1); | ||
885 | if (!desc) { | ||
886 | pr_err("step 2 error\n"); | ||
887 | return -1; | ||
888 | } | ||
889 | /* [3] submit the DMA */ | ||
890 | set_dma_type(this, DMA_FOR_WRITE_DATA); | ||
891 | return start_dma_without_bch_irq(this, desc); | ||
892 | } | ||
893 | |||
894 | int gpmi_read_data(struct gpmi_nand_data *this) | ||
895 | { | ||
896 | struct dma_async_tx_descriptor *desc; | ||
897 | struct dma_chan *channel = get_dma_chan(this); | ||
898 | int chip = this->current_chip; | ||
899 | u32 pio[2]; | ||
900 | |||
901 | /* [1] : send PIO */ | ||
902 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ) | ||
903 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
904 | | BF_GPMI_CTRL0_CS(chip, this) | ||
905 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
906 | | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA) | ||
907 | | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len); | ||
908 | pio[1] = 0; | ||
909 | desc = channel->device->device_prep_slave_sg(channel, | ||
910 | (struct scatterlist *)pio, | ||
911 | ARRAY_SIZE(pio), DMA_NONE, 0); | ||
912 | if (!desc) { | ||
913 | pr_err("step 1 error\n"); | ||
914 | return -1; | ||
915 | } | ||
916 | |||
917 | /* [2] : send DMA request */ | ||
918 | prepare_data_dma(this, DMA_FROM_DEVICE); | ||
919 | desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl, | ||
920 | 1, DMA_FROM_DEVICE, 1); | ||
921 | if (!desc) { | ||
922 | pr_err("step 2 error\n"); | ||
923 | return -1; | ||
924 | } | ||
925 | |||
926 | /* [3] : submit the DMA */ | ||
927 | set_dma_type(this, DMA_FOR_READ_DATA); | ||
928 | return start_dma_without_bch_irq(this, desc); | ||
929 | } | ||
930 | |||
931 | int gpmi_send_page(struct gpmi_nand_data *this, | ||
932 | dma_addr_t payload, dma_addr_t auxiliary) | ||
933 | { | ||
934 | struct bch_geometry *geo = &this->bch_geometry; | ||
935 | uint32_t command_mode; | ||
936 | uint32_t address; | ||
937 | uint32_t ecc_command; | ||
938 | uint32_t buffer_mask; | ||
939 | struct dma_async_tx_descriptor *desc; | ||
940 | struct dma_chan *channel = get_dma_chan(this); | ||
941 | int chip = this->current_chip; | ||
942 | u32 pio[6]; | ||
943 | |||
944 | /* A DMA descriptor that does an ECC page read. */ | ||
945 | command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE; | ||
946 | address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA; | ||
947 | ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE; | ||
948 | buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE | | ||
949 | BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY; | ||
950 | |||
951 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode) | ||
952 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
953 | | BF_GPMI_CTRL0_CS(chip, this) | ||
954 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
955 | | BF_GPMI_CTRL0_ADDRESS(address) | ||
956 | | BF_GPMI_CTRL0_XFER_COUNT(0); | ||
957 | pio[1] = 0; | ||
958 | pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC | ||
959 | | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command) | ||
960 | | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask); | ||
961 | pio[3] = geo->page_size; | ||
962 | pio[4] = payload; | ||
963 | pio[5] = auxiliary; | ||
964 | |||
965 | desc = channel->device->device_prep_slave_sg(channel, | ||
966 | (struct scatterlist *)pio, | ||
967 | ARRAY_SIZE(pio), DMA_NONE, 0); | ||
968 | if (!desc) { | ||
969 | pr_err("step 2 error\n"); | ||
970 | return -1; | ||
971 | } | ||
972 | set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE); | ||
973 | return start_dma_with_bch_irq(this, desc); | ||
974 | } | ||
975 | |||
976 | int gpmi_read_page(struct gpmi_nand_data *this, | ||
977 | dma_addr_t payload, dma_addr_t auxiliary) | ||
978 | { | ||
979 | struct bch_geometry *geo = &this->bch_geometry; | ||
980 | uint32_t command_mode; | ||
981 | uint32_t address; | ||
982 | uint32_t ecc_command; | ||
983 | uint32_t buffer_mask; | ||
984 | struct dma_async_tx_descriptor *desc; | ||
985 | struct dma_chan *channel = get_dma_chan(this); | ||
986 | int chip = this->current_chip; | ||
987 | u32 pio[6]; | ||
988 | |||
989 | /* [1] Wait for the chip to report ready. */ | ||
990 | command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY; | ||
991 | address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA; | ||
992 | |||
993 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode) | ||
994 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
995 | | BF_GPMI_CTRL0_CS(chip, this) | ||
996 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
997 | | BF_GPMI_CTRL0_ADDRESS(address) | ||
998 | | BF_GPMI_CTRL0_XFER_COUNT(0); | ||
999 | pio[1] = 0; | ||
1000 | desc = channel->device->device_prep_slave_sg(channel, | ||
1001 | (struct scatterlist *)pio, 2, DMA_NONE, 0); | ||
1002 | if (!desc) { | ||
1003 | pr_err("step 1 error\n"); | ||
1004 | return -1; | ||
1005 | } | ||
1006 | |||
1007 | /* [2] Enable the BCH block and read. */ | ||
1008 | command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ; | ||
1009 | address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA; | ||
1010 | ecc_command = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE; | ||
1011 | buffer_mask = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE | ||
1012 | | BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY; | ||
1013 | |||
1014 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode) | ||
1015 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
1016 | | BF_GPMI_CTRL0_CS(chip, this) | ||
1017 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
1018 | | BF_GPMI_CTRL0_ADDRESS(address) | ||
1019 | | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); | ||
1020 | |||
1021 | pio[1] = 0; | ||
1022 | pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC | ||
1023 | | BF_GPMI_ECCCTRL_ECC_CMD(ecc_command) | ||
1024 | | BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask); | ||
1025 | pio[3] = geo->page_size; | ||
1026 | pio[4] = payload; | ||
1027 | pio[5] = auxiliary; | ||
1028 | desc = channel->device->device_prep_slave_sg(channel, | ||
1029 | (struct scatterlist *)pio, | ||
1030 | ARRAY_SIZE(pio), DMA_NONE, 1); | ||
1031 | if (!desc) { | ||
1032 | pr_err("step 2 error\n"); | ||
1033 | return -1; | ||
1034 | } | ||
1035 | |||
1036 | /* [3] Disable the BCH block */ | ||
1037 | command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY; | ||
1038 | address = BV_GPMI_CTRL0_ADDRESS__NAND_DATA; | ||
1039 | |||
1040 | pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode) | ||
1041 | | BM_GPMI_CTRL0_WORD_LENGTH | ||
1042 | | BF_GPMI_CTRL0_CS(chip, this) | ||
1043 | | BF_GPMI_CTRL0_LOCK_CS(LOCK_CS_ENABLE, this) | ||
1044 | | BF_GPMI_CTRL0_ADDRESS(address) | ||
1045 | | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size); | ||
1046 | pio[1] = 0; | ||
1047 | desc = channel->device->device_prep_slave_sg(channel, | ||
1048 | (struct scatterlist *)pio, 2, DMA_NONE, 1); | ||
1049 | if (!desc) { | ||
1050 | pr_err("step 3 error\n"); | ||
1051 | return -1; | ||
1052 | } | ||
1053 | |||
1054 | /* [4] submit the DMA */ | ||
1055 | set_dma_type(this, DMA_FOR_READ_ECC_PAGE); | ||
1056 | return start_dma_with_bch_irq(this, desc); | ||
1057 | } | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c new file mode 100644 index 000000000000..071b63420f0e --- /dev/null +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -0,0 +1,1619 @@ | |||
1 | /* | ||
2 | * Freescale GPMI NAND Flash Driver | ||
3 | * | ||
4 | * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. | ||
5 | * Copyright (C) 2008 Embedded Alley Solutions, Inc. | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/mtd/gpmi-nand.h> | ||
25 | #include <linux/mtd/partitions.h> | ||
26 | |||
27 | #include "gpmi-nand.h" | ||
28 | |||
29 | /* add our owner bbt descriptor */ | ||
30 | static uint8_t scan_ff_pattern[] = { 0xff }; | ||
31 | static struct nand_bbt_descr gpmi_bbt_descr = { | ||
32 | .options = 0, | ||
33 | .offs = 0, | ||
34 | .len = 1, | ||
35 | .pattern = scan_ff_pattern | ||
36 | }; | ||
37 | |||
38 | /* We will use all the (page + OOB). */ | ||
39 | static struct nand_ecclayout gpmi_hw_ecclayout = { | ||
40 | .eccbytes = 0, | ||
41 | .eccpos = { 0, }, | ||
42 | .oobfree = { {.offset = 0, .length = 0} } | ||
43 | }; | ||
44 | |||
45 | static irqreturn_t bch_irq(int irq, void *cookie) | ||
46 | { | ||
47 | struct gpmi_nand_data *this = cookie; | ||
48 | |||
49 | gpmi_clear_bch(this); | ||
50 | complete(&this->bch_done); | ||
51 | return IRQ_HANDLED; | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Calculate the ECC strength by hand: | ||
56 | * E : The ECC strength. | ||
57 | * G : the length of Galois Field. | ||
58 | * N : The chunk count of per page. | ||
59 | * O : the oobsize of the NAND chip. | ||
60 | * M : the metasize of per page. | ||
61 | * | ||
62 | * The formula is : | ||
63 | * E * G * N | ||
64 | * ------------ <= (O - M) | ||
65 | * 8 | ||
66 | * | ||
67 | * So, we get E by: | ||
68 | * (O - M) * 8 | ||
69 | * E <= ------------- | ||
70 | * G * N | ||
71 | */ | ||
72 | static inline int get_ecc_strength(struct gpmi_nand_data *this) | ||
73 | { | ||
74 | struct bch_geometry *geo = &this->bch_geometry; | ||
75 | struct mtd_info *mtd = &this->mtd; | ||
76 | int ecc_strength; | ||
77 | |||
78 | ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8) | ||
79 | / (geo->gf_len * geo->ecc_chunk_count); | ||
80 | |||
81 | /* We need the minor even number. */ | ||
82 | return round_down(ecc_strength, 2); | ||
83 | } | ||
84 | |||
85 | int common_nfc_set_geometry(struct gpmi_nand_data *this) | ||
86 | { | ||
87 | struct bch_geometry *geo = &this->bch_geometry; | ||
88 | struct mtd_info *mtd = &this->mtd; | ||
89 | unsigned int metadata_size; | ||
90 | unsigned int status_size; | ||
91 | unsigned int block_mark_bit_offset; | ||
92 | |||
93 | /* | ||
94 | * The size of the metadata can be changed, though we set it to 10 | ||
95 | * bytes now. But it can't be too large, because we have to save | ||
96 | * enough space for BCH. | ||
97 | */ | ||
98 | geo->metadata_size = 10; | ||
99 | |||
100 | /* The default for the length of Galois Field. */ | ||
101 | geo->gf_len = 13; | ||
102 | |||
103 | /* The default for chunk size. There is no oobsize greater then 512. */ | ||
104 | geo->ecc_chunk_size = 512; | ||
105 | while (geo->ecc_chunk_size < mtd->oobsize) | ||
106 | geo->ecc_chunk_size *= 2; /* keep C >= O */ | ||
107 | |||
108 | geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size; | ||
109 | |||
110 | /* We use the same ECC strength for all chunks. */ | ||
111 | geo->ecc_strength = get_ecc_strength(this); | ||
112 | if (!geo->ecc_strength) { | ||
113 | pr_err("We get a wrong ECC strength.\n"); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | geo->page_size = mtd->writesize + mtd->oobsize; | ||
118 | geo->payload_size = mtd->writesize; | ||
119 | |||
120 | /* | ||
121 | * The auxiliary buffer contains the metadata and the ECC status. The | ||
122 | * metadata is padded to the nearest 32-bit boundary. The ECC status | ||
123 | * contains one byte for every ECC chunk, and is also padded to the | ||
124 | * nearest 32-bit boundary. | ||
125 | */ | ||
126 | metadata_size = ALIGN(geo->metadata_size, 4); | ||
127 | status_size = ALIGN(geo->ecc_chunk_count, 4); | ||
128 | |||
129 | geo->auxiliary_size = metadata_size + status_size; | ||
130 | geo->auxiliary_status_offset = metadata_size; | ||
131 | |||
132 | if (!this->swap_block_mark) | ||
133 | return 0; | ||
134 | |||
135 | /* | ||
136 | * We need to compute the byte and bit offsets of | ||
137 | * the physical block mark within the ECC-based view of the page. | ||
138 | * | ||
139 | * NAND chip with 2K page shows below: | ||
140 | * (Block Mark) | ||
141 | * | | | ||
142 | * | D | | ||
143 | * |<---->| | ||
144 | * V V | ||
145 | * +---+----------+-+----------+-+----------+-+----------+-+ | ||
146 | * | M | data |E| data |E| data |E| data |E| | ||
147 | * +---+----------+-+----------+-+----------+-+----------+-+ | ||
148 | * | ||
149 | * The position of block mark moves forward in the ECC-based view | ||
150 | * of page, and the delta is: | ||
151 | * | ||
152 | * E * G * (N - 1) | ||
153 | * D = (---------------- + M) | ||
154 | * 8 | ||
155 | * | ||
156 | * With the formula to compute the ECC strength, and the condition | ||
157 | * : C >= O (C is the ecc chunk size) | ||
158 | * | ||
159 | * It's easy to deduce to the following result: | ||
160 | * | ||
161 | * E * G (O - M) C - M C - M | ||
162 | * ----------- <= ------- <= -------- < --------- | ||
163 | * 8 N N (N - 1) | ||
164 | * | ||
165 | * So, we get: | ||
166 | * | ||
167 | * E * G * (N - 1) | ||
168 | * D = (---------------- + M) < C | ||
169 | * 8 | ||
170 | * | ||
171 | * The above inequality means the position of block mark | ||
172 | * within the ECC-based view of the page is still in the data chunk, | ||
173 | * and it's NOT in the ECC bits of the chunk. | ||
174 | * | ||
175 | * Use the following to compute the bit position of the | ||
176 | * physical block mark within the ECC-based view of the page: | ||
177 | * (page_size - D) * 8 | ||
178 | * | ||
179 | * --Huang Shijie | ||
180 | */ | ||
181 | block_mark_bit_offset = mtd->writesize * 8 - | ||
182 | (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1) | ||
183 | + geo->metadata_size * 8); | ||
184 | |||
185 | geo->block_mark_byte_offset = block_mark_bit_offset / 8; | ||
186 | geo->block_mark_bit_offset = block_mark_bit_offset % 8; | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | struct dma_chan *get_dma_chan(struct gpmi_nand_data *this) | ||
191 | { | ||
192 | int chipnr = this->current_chip; | ||
193 | |||
194 | return this->dma_chans[chipnr]; | ||
195 | } | ||
196 | |||
197 | /* Can we use the upper's buffer directly for DMA? */ | ||
198 | void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr) | ||
199 | { | ||
200 | struct scatterlist *sgl = &this->data_sgl; | ||
201 | int ret; | ||
202 | |||
203 | this->direct_dma_map_ok = true; | ||
204 | |||
205 | /* first try to map the upper buffer directly */ | ||
206 | sg_init_one(sgl, this->upper_buf, this->upper_len); | ||
207 | ret = dma_map_sg(this->dev, sgl, 1, dr); | ||
208 | if (ret == 0) { | ||
209 | /* We have to use our own DMA buffer. */ | ||
210 | sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE); | ||
211 | |||
212 | if (dr == DMA_TO_DEVICE) | ||
213 | memcpy(this->data_buffer_dma, this->upper_buf, | ||
214 | this->upper_len); | ||
215 | |||
216 | ret = dma_map_sg(this->dev, sgl, 1, dr); | ||
217 | if (ret == 0) | ||
218 | pr_err("map failed.\n"); | ||
219 | |||
220 | this->direct_dma_map_ok = false; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | /* This will be called after the DMA operation is finished. */ | ||
225 | static void dma_irq_callback(void *param) | ||
226 | { | ||
227 | struct gpmi_nand_data *this = param; | ||
228 | struct completion *dma_c = &this->dma_done; | ||
229 | |||
230 | complete(dma_c); | ||
231 | |||
232 | switch (this->dma_type) { | ||
233 | case DMA_FOR_COMMAND: | ||
234 | dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE); | ||
235 | break; | ||
236 | |||
237 | case DMA_FOR_READ_DATA: | ||
238 | dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_FROM_DEVICE); | ||
239 | if (this->direct_dma_map_ok == false) | ||
240 | memcpy(this->upper_buf, this->data_buffer_dma, | ||
241 | this->upper_len); | ||
242 | break; | ||
243 | |||
244 | case DMA_FOR_WRITE_DATA: | ||
245 | dma_unmap_sg(this->dev, &this->data_sgl, 1, DMA_TO_DEVICE); | ||
246 | break; | ||
247 | |||
248 | case DMA_FOR_READ_ECC_PAGE: | ||
249 | case DMA_FOR_WRITE_ECC_PAGE: | ||
250 | /* We have to wait the BCH interrupt to finish. */ | ||
251 | break; | ||
252 | |||
253 | default: | ||
254 | pr_err("in wrong DMA operation.\n"); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | int start_dma_without_bch_irq(struct gpmi_nand_data *this, | ||
259 | struct dma_async_tx_descriptor *desc) | ||
260 | { | ||
261 | struct completion *dma_c = &this->dma_done; | ||
262 | int err; | ||
263 | |||
264 | init_completion(dma_c); | ||
265 | |||
266 | desc->callback = dma_irq_callback; | ||
267 | desc->callback_param = this; | ||
268 | dmaengine_submit(desc); | ||
269 | |||
270 | /* Wait for the interrupt from the DMA block. */ | ||
271 | err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000)); | ||
272 | if (!err) { | ||
273 | pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type); | ||
274 | gpmi_dump_info(this); | ||
275 | return -ETIMEDOUT; | ||
276 | } | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * This function is used in BCH reading or BCH writing pages. | ||
282 | * It will wait for the BCH interrupt as long as ONE second. | ||
283 | * Actually, we must wait for two interrupts : | ||
284 | * [1] firstly the DMA interrupt and | ||
285 | * [2] secondly the BCH interrupt. | ||
286 | */ | ||
287 | int start_dma_with_bch_irq(struct gpmi_nand_data *this, | ||
288 | struct dma_async_tx_descriptor *desc) | ||
289 | { | ||
290 | struct completion *bch_c = &this->bch_done; | ||
291 | int err; | ||
292 | |||
293 | /* Prepare to receive an interrupt from the BCH block. */ | ||
294 | init_completion(bch_c); | ||
295 | |||
296 | /* start the DMA */ | ||
297 | start_dma_without_bch_irq(this, desc); | ||
298 | |||
299 | /* Wait for the interrupt from the BCH block. */ | ||
300 | err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000)); | ||
301 | if (!err) { | ||
302 | pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type); | ||
303 | gpmi_dump_info(this); | ||
304 | return -ETIMEDOUT; | ||
305 | } | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int __devinit | ||
310 | acquire_register_block(struct gpmi_nand_data *this, const char *res_name) | ||
311 | { | ||
312 | struct platform_device *pdev = this->pdev; | ||
313 | struct resources *res = &this->resources; | ||
314 | struct resource *r; | ||
315 | void *p; | ||
316 | |||
317 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); | ||
318 | if (!r) { | ||
319 | pr_err("Can't get resource for %s\n", res_name); | ||
320 | return -ENXIO; | ||
321 | } | ||
322 | |||
323 | p = ioremap(r->start, resource_size(r)); | ||
324 | if (!p) { | ||
325 | pr_err("Can't remap %s\n", res_name); | ||
326 | return -ENOMEM; | ||
327 | } | ||
328 | |||
329 | if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME)) | ||
330 | res->gpmi_regs = p; | ||
331 | else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME)) | ||
332 | res->bch_regs = p; | ||
333 | else | ||
334 | pr_err("unknown resource name : %s\n", res_name); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static void release_register_block(struct gpmi_nand_data *this) | ||
340 | { | ||
341 | struct resources *res = &this->resources; | ||
342 | if (res->gpmi_regs) | ||
343 | iounmap(res->gpmi_regs); | ||
344 | if (res->bch_regs) | ||
345 | iounmap(res->bch_regs); | ||
346 | res->gpmi_regs = NULL; | ||
347 | res->bch_regs = NULL; | ||
348 | } | ||
349 | |||
350 | static int __devinit | ||
351 | acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h) | ||
352 | { | ||
353 | struct platform_device *pdev = this->pdev; | ||
354 | struct resources *res = &this->resources; | ||
355 | const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME; | ||
356 | struct resource *r; | ||
357 | int err; | ||
358 | |||
359 | r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); | ||
360 | if (!r) { | ||
361 | pr_err("Can't get resource for %s\n", res_name); | ||
362 | return -ENXIO; | ||
363 | } | ||
364 | |||
365 | err = request_irq(r->start, irq_h, 0, res_name, this); | ||
366 | if (err) { | ||
367 | pr_err("Can't own %s\n", res_name); | ||
368 | return err; | ||
369 | } | ||
370 | |||
371 | res->bch_low_interrupt = r->start; | ||
372 | res->bch_high_interrupt = r->end; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static void release_bch_irq(struct gpmi_nand_data *this) | ||
377 | { | ||
378 | struct resources *res = &this->resources; | ||
379 | int i = res->bch_low_interrupt; | ||
380 | |||
381 | for (; i <= res->bch_high_interrupt; i++) | ||
382 | free_irq(i, this); | ||
383 | } | ||
384 | |||
385 | static bool gpmi_dma_filter(struct dma_chan *chan, void *param) | ||
386 | { | ||
387 | struct gpmi_nand_data *this = param; | ||
388 | struct resource *r = this->private; | ||
389 | |||
390 | if (!mxs_dma_is_apbh(chan)) | ||
391 | return false; | ||
392 | /* | ||
393 | * only catch the GPMI dma channels : | ||
394 | * for mx23 : MX23_DMA_GPMI0 ~ MX23_DMA_GPMI3 | ||
395 | * (These four channels share the same IRQ!) | ||
396 | * | ||
397 | * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 | ||
398 | * (These eight channels share the same IRQ!) | ||
399 | */ | ||
400 | if (r->start <= chan->chan_id && chan->chan_id <= r->end) { | ||
401 | chan->private = &this->dma_data; | ||
402 | return true; | ||
403 | } | ||
404 | return false; | ||
405 | } | ||
406 | |||
407 | static void release_dma_channels(struct gpmi_nand_data *this) | ||
408 | { | ||
409 | unsigned int i; | ||
410 | for (i = 0; i < DMA_CHANS; i++) | ||
411 | if (this->dma_chans[i]) { | ||
412 | dma_release_channel(this->dma_chans[i]); | ||
413 | this->dma_chans[i] = NULL; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) | ||
418 | { | ||
419 | struct platform_device *pdev = this->pdev; | ||
420 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
421 | struct resources *res = &this->resources; | ||
422 | struct resource *r, *r_dma; | ||
423 | unsigned int i; | ||
424 | |||
425 | r = platform_get_resource_byname(pdev, IORESOURCE_DMA, | ||
426 | GPMI_NAND_DMA_CHANNELS_RES_NAME); | ||
427 | r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
428 | GPMI_NAND_DMA_INTERRUPT_RES_NAME); | ||
429 | if (!r || !r_dma) { | ||
430 | pr_err("Can't get resource for DMA\n"); | ||
431 | return -ENXIO; | ||
432 | } | ||
433 | |||
434 | /* used in gpmi_dma_filter() */ | ||
435 | this->private = r; | ||
436 | |||
437 | for (i = r->start; i <= r->end; i++) { | ||
438 | struct dma_chan *dma_chan; | ||
439 | dma_cap_mask_t mask; | ||
440 | |||
441 | if (i - r->start >= pdata->max_chip_count) | ||
442 | break; | ||
443 | |||
444 | dma_cap_zero(mask); | ||
445 | dma_cap_set(DMA_SLAVE, mask); | ||
446 | |||
447 | /* get the DMA interrupt */ | ||
448 | if (r_dma->start == r_dma->end) { | ||
449 | /* only register the first. */ | ||
450 | if (i == r->start) | ||
451 | this->dma_data.chan_irq = r_dma->start; | ||
452 | else | ||
453 | this->dma_data.chan_irq = NO_IRQ; | ||
454 | } else | ||
455 | this->dma_data.chan_irq = r_dma->start + (i - r->start); | ||
456 | |||
457 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); | ||
458 | if (!dma_chan) | ||
459 | goto acquire_err; | ||
460 | |||
461 | /* fill the first empty item */ | ||
462 | this->dma_chans[i - r->start] = dma_chan; | ||
463 | } | ||
464 | |||
465 | res->dma_low_channel = r->start; | ||
466 | res->dma_high_channel = i; | ||
467 | return 0; | ||
468 | |||
469 | acquire_err: | ||
470 | pr_err("Can't acquire DMA channel %u\n", i); | ||
471 | release_dma_channels(this); | ||
472 | return -EINVAL; | ||
473 | } | ||
474 | |||
475 | static int __devinit acquire_resources(struct gpmi_nand_data *this) | ||
476 | { | ||
477 | struct resources *res = &this->resources; | ||
478 | int ret; | ||
479 | |||
480 | ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME); | ||
481 | if (ret) | ||
482 | goto exit_regs; | ||
483 | |||
484 | ret = acquire_register_block(this, GPMI_NAND_BCH_REGS_ADDR_RES_NAME); | ||
485 | if (ret) | ||
486 | goto exit_regs; | ||
487 | |||
488 | ret = acquire_bch_irq(this, bch_irq); | ||
489 | if (ret) | ||
490 | goto exit_regs; | ||
491 | |||
492 | ret = acquire_dma_channels(this); | ||
493 | if (ret) | ||
494 | goto exit_dma_channels; | ||
495 | |||
496 | res->clock = clk_get(&this->pdev->dev, NULL); | ||
497 | if (IS_ERR(res->clock)) { | ||
498 | pr_err("can not get the clock\n"); | ||
499 | ret = -ENOENT; | ||
500 | goto exit_clock; | ||
501 | } | ||
502 | return 0; | ||
503 | |||
504 | exit_clock: | ||
505 | release_dma_channels(this); | ||
506 | exit_dma_channels: | ||
507 | release_bch_irq(this); | ||
508 | exit_regs: | ||
509 | release_register_block(this); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | static void release_resources(struct gpmi_nand_data *this) | ||
514 | { | ||
515 | struct resources *r = &this->resources; | ||
516 | |||
517 | clk_put(r->clock); | ||
518 | release_register_block(this); | ||
519 | release_bch_irq(this); | ||
520 | release_dma_channels(this); | ||
521 | } | ||
522 | |||
523 | static int __devinit init_hardware(struct gpmi_nand_data *this) | ||
524 | { | ||
525 | int ret; | ||
526 | |||
527 | /* | ||
528 | * This structure contains the "safe" GPMI timing that should succeed | ||
529 | * with any NAND Flash device | ||
530 | * (although, with less-than-optimal performance). | ||
531 | */ | ||
532 | struct nand_timing safe_timing = { | ||
533 | .data_setup_in_ns = 80, | ||
534 | .data_hold_in_ns = 60, | ||
535 | .address_setup_in_ns = 25, | ||
536 | .gpmi_sample_delay_in_ns = 6, | ||
537 | .tREA_in_ns = -1, | ||
538 | .tRLOH_in_ns = -1, | ||
539 | .tRHOH_in_ns = -1, | ||
540 | }; | ||
541 | |||
542 | /* Initialize the hardwares. */ | ||
543 | ret = gpmi_init(this); | ||
544 | if (ret) | ||
545 | return ret; | ||
546 | |||
547 | this->timing = safe_timing; | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int read_page_prepare(struct gpmi_nand_data *this, | ||
552 | void *destination, unsigned length, | ||
553 | void *alt_virt, dma_addr_t alt_phys, unsigned alt_size, | ||
554 | void **use_virt, dma_addr_t *use_phys) | ||
555 | { | ||
556 | struct device *dev = this->dev; | ||
557 | |||
558 | if (virt_addr_valid(destination)) { | ||
559 | dma_addr_t dest_phys; | ||
560 | |||
561 | dest_phys = dma_map_single(dev, destination, | ||
562 | length, DMA_FROM_DEVICE); | ||
563 | if (dma_mapping_error(dev, dest_phys)) { | ||
564 | if (alt_size < length) { | ||
565 | pr_err("Alternate buffer is too small\n"); | ||
566 | return -ENOMEM; | ||
567 | } | ||
568 | goto map_failed; | ||
569 | } | ||
570 | *use_virt = destination; | ||
571 | *use_phys = dest_phys; | ||
572 | this->direct_dma_map_ok = true; | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | map_failed: | ||
577 | *use_virt = alt_virt; | ||
578 | *use_phys = alt_phys; | ||
579 | this->direct_dma_map_ok = false; | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static inline void read_page_end(struct gpmi_nand_data *this, | ||
584 | void *destination, unsigned length, | ||
585 | void *alt_virt, dma_addr_t alt_phys, unsigned alt_size, | ||
586 | void *used_virt, dma_addr_t used_phys) | ||
587 | { | ||
588 | if (this->direct_dma_map_ok) | ||
589 | dma_unmap_single(this->dev, used_phys, length, DMA_FROM_DEVICE); | ||
590 | } | ||
591 | |||
592 | static inline void read_page_swap_end(struct gpmi_nand_data *this, | ||
593 | void *destination, unsigned length, | ||
594 | void *alt_virt, dma_addr_t alt_phys, unsigned alt_size, | ||
595 | void *used_virt, dma_addr_t used_phys) | ||
596 | { | ||
597 | if (!this->direct_dma_map_ok) | ||
598 | memcpy(destination, alt_virt, length); | ||
599 | } | ||
600 | |||
601 | static int send_page_prepare(struct gpmi_nand_data *this, | ||
602 | const void *source, unsigned length, | ||
603 | void *alt_virt, dma_addr_t alt_phys, unsigned alt_size, | ||
604 | const void **use_virt, dma_addr_t *use_phys) | ||
605 | { | ||
606 | struct device *dev = this->dev; | ||
607 | |||
608 | if (virt_addr_valid(source)) { | ||
609 | dma_addr_t source_phys; | ||
610 | |||
611 | source_phys = dma_map_single(dev, (void *)source, length, | ||
612 | DMA_TO_DEVICE); | ||
613 | if (dma_mapping_error(dev, source_phys)) { | ||
614 | if (alt_size < length) { | ||
615 | pr_err("Alternate buffer is too small\n"); | ||
616 | return -ENOMEM; | ||
617 | } | ||
618 | goto map_failed; | ||
619 | } | ||
620 | *use_virt = source; | ||
621 | *use_phys = source_phys; | ||
622 | return 0; | ||
623 | } | ||
624 | map_failed: | ||
625 | /* | ||
626 | * Copy the content of the source buffer into the alternate | ||
627 | * buffer and set up the return values accordingly. | ||
628 | */ | ||
629 | memcpy(alt_virt, source, length); | ||
630 | |||
631 | *use_virt = alt_virt; | ||
632 | *use_phys = alt_phys; | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static void send_page_end(struct gpmi_nand_data *this, | ||
637 | const void *source, unsigned length, | ||
638 | void *alt_virt, dma_addr_t alt_phys, unsigned alt_size, | ||
639 | const void *used_virt, dma_addr_t used_phys) | ||
640 | { | ||
641 | struct device *dev = this->dev; | ||
642 | if (used_virt == source) | ||
643 | dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE); | ||
644 | } | ||
645 | |||
646 | static void gpmi_free_dma_buffer(struct gpmi_nand_data *this) | ||
647 | { | ||
648 | struct device *dev = this->dev; | ||
649 | |||
650 | if (this->page_buffer_virt && virt_addr_valid(this->page_buffer_virt)) | ||
651 | dma_free_coherent(dev, this->page_buffer_size, | ||
652 | this->page_buffer_virt, | ||
653 | this->page_buffer_phys); | ||
654 | kfree(this->cmd_buffer); | ||
655 | kfree(this->data_buffer_dma); | ||
656 | |||
657 | this->cmd_buffer = NULL; | ||
658 | this->data_buffer_dma = NULL; | ||
659 | this->page_buffer_virt = NULL; | ||
660 | this->page_buffer_size = 0; | ||
661 | } | ||
662 | |||
663 | /* Allocate the DMA buffers */ | ||
664 | static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) | ||
665 | { | ||
666 | struct bch_geometry *geo = &this->bch_geometry; | ||
667 | struct device *dev = this->dev; | ||
668 | |||
669 | /* [1] Allocate a command buffer. PAGE_SIZE is enough. */ | ||
670 | this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA); | ||
671 | if (this->cmd_buffer == NULL) | ||
672 | goto error_alloc; | ||
673 | |||
674 | /* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */ | ||
675 | this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA); | ||
676 | if (this->data_buffer_dma == NULL) | ||
677 | goto error_alloc; | ||
678 | |||
679 | /* | ||
680 | * [3] Allocate the page buffer. | ||
681 | * | ||
682 | * Both the payload buffer and the auxiliary buffer must appear on | ||
683 | * 32-bit boundaries. We presume the size of the payload buffer is a | ||
684 | * power of two and is much larger than four, which guarantees the | ||
685 | * auxiliary buffer will appear on a 32-bit boundary. | ||
686 | */ | ||
687 | this->page_buffer_size = geo->payload_size + geo->auxiliary_size; | ||
688 | this->page_buffer_virt = dma_alloc_coherent(dev, this->page_buffer_size, | ||
689 | &this->page_buffer_phys, GFP_DMA); | ||
690 | if (!this->page_buffer_virt) | ||
691 | goto error_alloc; | ||
692 | |||
693 | |||
694 | /* Slice up the page buffer. */ | ||
695 | this->payload_virt = this->page_buffer_virt; | ||
696 | this->payload_phys = this->page_buffer_phys; | ||
697 | this->auxiliary_virt = this->payload_virt + geo->payload_size; | ||
698 | this->auxiliary_phys = this->payload_phys + geo->payload_size; | ||
699 | return 0; | ||
700 | |||
701 | error_alloc: | ||
702 | gpmi_free_dma_buffer(this); | ||
703 | pr_err("allocate DMA buffer ret!!\n"); | ||
704 | return -ENOMEM; | ||
705 | } | ||
706 | |||
707 | static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) | ||
708 | { | ||
709 | struct nand_chip *chip = mtd->priv; | ||
710 | struct gpmi_nand_data *this = chip->priv; | ||
711 | int ret; | ||
712 | |||
713 | /* | ||
714 | * Every operation begins with a command byte and a series of zero or | ||
715 | * more address bytes. These are distinguished by either the Address | ||
716 | * Latch Enable (ALE) or Command Latch Enable (CLE) signals being | ||
717 | * asserted. When MTD is ready to execute the command, it will deassert | ||
718 | * both latch enables. | ||
719 | * | ||
720 | * Rather than run a separate DMA operation for every single byte, we | ||
721 | * queue them up and run a single DMA operation for the entire series | ||
722 | * of command and data bytes. NAND_CMD_NONE means the END of the queue. | ||
723 | */ | ||
724 | if ((ctrl & (NAND_ALE | NAND_CLE))) { | ||
725 | if (data != NAND_CMD_NONE) | ||
726 | this->cmd_buffer[this->command_length++] = data; | ||
727 | return; | ||
728 | } | ||
729 | |||
730 | if (!this->command_length) | ||
731 | return; | ||
732 | |||
733 | ret = gpmi_send_command(this); | ||
734 | if (ret) | ||
735 | pr_err("Chip: %u, Error %d\n", this->current_chip, ret); | ||
736 | |||
737 | this->command_length = 0; | ||
738 | } | ||
739 | |||
740 | static int gpmi_dev_ready(struct mtd_info *mtd) | ||
741 | { | ||
742 | struct nand_chip *chip = mtd->priv; | ||
743 | struct gpmi_nand_data *this = chip->priv; | ||
744 | |||
745 | return gpmi_is_ready(this, this->current_chip); | ||
746 | } | ||
747 | |||
748 | static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) | ||
749 | { | ||
750 | struct nand_chip *chip = mtd->priv; | ||
751 | struct gpmi_nand_data *this = chip->priv; | ||
752 | |||
753 | if ((this->current_chip < 0) && (chipnr >= 0)) | ||
754 | gpmi_begin(this); | ||
755 | else if ((this->current_chip >= 0) && (chipnr < 0)) | ||
756 | gpmi_end(this); | ||
757 | |||
758 | this->current_chip = chipnr; | ||
759 | } | ||
760 | |||
761 | static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
762 | { | ||
763 | struct nand_chip *chip = mtd->priv; | ||
764 | struct gpmi_nand_data *this = chip->priv; | ||
765 | |||
766 | pr_debug("len is %d\n", len); | ||
767 | this->upper_buf = buf; | ||
768 | this->upper_len = len; | ||
769 | |||
770 | gpmi_read_data(this); | ||
771 | } | ||
772 | |||
773 | static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
774 | { | ||
775 | struct nand_chip *chip = mtd->priv; | ||
776 | struct gpmi_nand_data *this = chip->priv; | ||
777 | |||
778 | pr_debug("len is %d\n", len); | ||
779 | this->upper_buf = (uint8_t *)buf; | ||
780 | this->upper_len = len; | ||
781 | |||
782 | gpmi_send_data(this); | ||
783 | } | ||
784 | |||
785 | static uint8_t gpmi_read_byte(struct mtd_info *mtd) | ||
786 | { | ||
787 | struct nand_chip *chip = mtd->priv; | ||
788 | struct gpmi_nand_data *this = chip->priv; | ||
789 | uint8_t *buf = this->data_buffer_dma; | ||
790 | |||
791 | gpmi_read_buf(mtd, buf, 1); | ||
792 | return buf[0]; | ||
793 | } | ||
794 | |||
795 | /* | ||
796 | * Handles block mark swapping. | ||
797 | * It can be called in swapping the block mark, or swapping it back, | ||
798 | * because the the operations are the same. | ||
799 | */ | ||
800 | static void block_mark_swapping(struct gpmi_nand_data *this, | ||
801 | void *payload, void *auxiliary) | ||
802 | { | ||
803 | struct bch_geometry *nfc_geo = &this->bch_geometry; | ||
804 | unsigned char *p; | ||
805 | unsigned char *a; | ||
806 | unsigned int bit; | ||
807 | unsigned char mask; | ||
808 | unsigned char from_data; | ||
809 | unsigned char from_oob; | ||
810 | |||
811 | if (!this->swap_block_mark) | ||
812 | return; | ||
813 | |||
814 | /* | ||
815 | * If control arrives here, we're swapping. Make some convenience | ||
816 | * variables. | ||
817 | */ | ||
818 | bit = nfc_geo->block_mark_bit_offset; | ||
819 | p = payload + nfc_geo->block_mark_byte_offset; | ||
820 | a = auxiliary; | ||
821 | |||
822 | /* | ||
823 | * Get the byte from the data area that overlays the block mark. Since | ||
824 | * the ECC engine applies its own view to the bits in the page, the | ||
825 | * physical block mark won't (in general) appear on a byte boundary in | ||
826 | * the data. | ||
827 | */ | ||
828 | from_data = (p[0] >> bit) | (p[1] << (8 - bit)); | ||
829 | |||
830 | /* Get the byte from the OOB. */ | ||
831 | from_oob = a[0]; | ||
832 | |||
833 | /* Swap them. */ | ||
834 | a[0] = from_data; | ||
835 | |||
836 | mask = (0x1 << bit) - 1; | ||
837 | p[0] = (p[0] & mask) | (from_oob << bit); | ||
838 | |||
839 | mask = ~0 << bit; | ||
840 | p[1] = (p[1] & mask) | (from_oob >> (8 - bit)); | ||
841 | } | ||
842 | |||
843 | static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
844 | uint8_t *buf, int page) | ||
845 | { | ||
846 | struct gpmi_nand_data *this = chip->priv; | ||
847 | struct bch_geometry *nfc_geo = &this->bch_geometry; | ||
848 | void *payload_virt; | ||
849 | dma_addr_t payload_phys; | ||
850 | void *auxiliary_virt; | ||
851 | dma_addr_t auxiliary_phys; | ||
852 | unsigned int i; | ||
853 | unsigned char *status; | ||
854 | unsigned int failed; | ||
855 | unsigned int corrected; | ||
856 | int ret; | ||
857 | |||
858 | pr_debug("page number is : %d\n", page); | ||
859 | ret = read_page_prepare(this, buf, mtd->writesize, | ||
860 | this->payload_virt, this->payload_phys, | ||
861 | nfc_geo->payload_size, | ||
862 | &payload_virt, &payload_phys); | ||
863 | if (ret) { | ||
864 | pr_err("Inadequate DMA buffer\n"); | ||
865 | ret = -ENOMEM; | ||
866 | return ret; | ||
867 | } | ||
868 | auxiliary_virt = this->auxiliary_virt; | ||
869 | auxiliary_phys = this->auxiliary_phys; | ||
870 | |||
871 | /* go! */ | ||
872 | ret = gpmi_read_page(this, payload_phys, auxiliary_phys); | ||
873 | read_page_end(this, buf, mtd->writesize, | ||
874 | this->payload_virt, this->payload_phys, | ||
875 | nfc_geo->payload_size, | ||
876 | payload_virt, payload_phys); | ||
877 | if (ret) { | ||
878 | pr_err("Error in ECC-based read: %d\n", ret); | ||
879 | goto exit_nfc; | ||
880 | } | ||
881 | |||
882 | /* handle the block mark swapping */ | ||
883 | block_mark_swapping(this, payload_virt, auxiliary_virt); | ||
884 | |||
885 | /* Loop over status bytes, accumulating ECC status. */ | ||
886 | failed = 0; | ||
887 | corrected = 0; | ||
888 | status = auxiliary_virt + nfc_geo->auxiliary_status_offset; | ||
889 | |||
890 | for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) { | ||
891 | if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED)) | ||
892 | continue; | ||
893 | |||
894 | if (*status == STATUS_UNCORRECTABLE) { | ||
895 | failed++; | ||
896 | continue; | ||
897 | } | ||
898 | corrected += *status; | ||
899 | } | ||
900 | |||
901 | /* | ||
902 | * Propagate ECC status to the owning MTD only when failed or | ||
903 | * corrected times nearly reaches our ECC correction threshold. | ||
904 | */ | ||
905 | if (failed || corrected >= (nfc_geo->ecc_strength - 1)) { | ||
906 | mtd->ecc_stats.failed += failed; | ||
907 | mtd->ecc_stats.corrected += corrected; | ||
908 | } | ||
909 | |||
910 | /* | ||
911 | * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for | ||
912 | * details about our policy for delivering the OOB. | ||
913 | * | ||
914 | * We fill the caller's buffer with set bits, and then copy the block | ||
915 | * mark to th caller's buffer. Note that, if block mark swapping was | ||
916 | * necessary, it has already been done, so we can rely on the first | ||
917 | * byte of the auxiliary buffer to contain the block mark. | ||
918 | */ | ||
919 | memset(chip->oob_poi, ~0, mtd->oobsize); | ||
920 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; | ||
921 | |||
922 | read_page_swap_end(this, buf, mtd->writesize, | ||
923 | this->payload_virt, this->payload_phys, | ||
924 | nfc_geo->payload_size, | ||
925 | payload_virt, payload_phys); | ||
926 | exit_nfc: | ||
927 | return ret; | ||
928 | } | ||
929 | |||
930 | static void gpmi_ecc_write_page(struct mtd_info *mtd, | ||
931 | struct nand_chip *chip, const uint8_t *buf) | ||
932 | { | ||
933 | struct gpmi_nand_data *this = chip->priv; | ||
934 | struct bch_geometry *nfc_geo = &this->bch_geometry; | ||
935 | const void *payload_virt; | ||
936 | dma_addr_t payload_phys; | ||
937 | const void *auxiliary_virt; | ||
938 | dma_addr_t auxiliary_phys; | ||
939 | int ret; | ||
940 | |||
941 | pr_debug("ecc write page.\n"); | ||
942 | if (this->swap_block_mark) { | ||
943 | /* | ||
944 | * If control arrives here, we're doing block mark swapping. | ||
945 | * Since we can't modify the caller's buffers, we must copy them | ||
946 | * into our own. | ||
947 | */ | ||
948 | memcpy(this->payload_virt, buf, mtd->writesize); | ||
949 | payload_virt = this->payload_virt; | ||
950 | payload_phys = this->payload_phys; | ||
951 | |||
952 | memcpy(this->auxiliary_virt, chip->oob_poi, | ||
953 | nfc_geo->auxiliary_size); | ||
954 | auxiliary_virt = this->auxiliary_virt; | ||
955 | auxiliary_phys = this->auxiliary_phys; | ||
956 | |||
957 | /* Handle block mark swapping. */ | ||
958 | block_mark_swapping(this, | ||
959 | (void *) payload_virt, (void *) auxiliary_virt); | ||
960 | } else { | ||
961 | /* | ||
962 | * If control arrives here, we're not doing block mark swapping, | ||
963 | * so we can to try and use the caller's buffers. | ||
964 | */ | ||
965 | ret = send_page_prepare(this, | ||
966 | buf, mtd->writesize, | ||
967 | this->payload_virt, this->payload_phys, | ||
968 | nfc_geo->payload_size, | ||
969 | &payload_virt, &payload_phys); | ||
970 | if (ret) { | ||
971 | pr_err("Inadequate payload DMA buffer\n"); | ||
972 | return; | ||
973 | } | ||
974 | |||
975 | ret = send_page_prepare(this, | ||
976 | chip->oob_poi, mtd->oobsize, | ||
977 | this->auxiliary_virt, this->auxiliary_phys, | ||
978 | nfc_geo->auxiliary_size, | ||
979 | &auxiliary_virt, &auxiliary_phys); | ||
980 | if (ret) { | ||
981 | pr_err("Inadequate auxiliary DMA buffer\n"); | ||
982 | goto exit_auxiliary; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | /* Ask the NFC. */ | ||
987 | ret = gpmi_send_page(this, payload_phys, auxiliary_phys); | ||
988 | if (ret) | ||
989 | pr_err("Error in ECC-based write: %d\n", ret); | ||
990 | |||
991 | if (!this->swap_block_mark) { | ||
992 | send_page_end(this, chip->oob_poi, mtd->oobsize, | ||
993 | this->auxiliary_virt, this->auxiliary_phys, | ||
994 | nfc_geo->auxiliary_size, | ||
995 | auxiliary_virt, auxiliary_phys); | ||
996 | exit_auxiliary: | ||
997 | send_page_end(this, buf, mtd->writesize, | ||
998 | this->payload_virt, this->payload_phys, | ||
999 | nfc_geo->payload_size, | ||
1000 | payload_virt, payload_phys); | ||
1001 | } | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
1005 | * There are several places in this driver where we have to handle the OOB and | ||
1006 | * block marks. This is the function where things are the most complicated, so | ||
1007 | * this is where we try to explain it all. All the other places refer back to | ||
1008 | * here. | ||
1009 | * | ||
1010 | * These are the rules, in order of decreasing importance: | ||
1011 | * | ||
1012 | * 1) Nothing the caller does can be allowed to imperil the block mark. | ||
1013 | * | ||
1014 | * 2) In read operations, the first byte of the OOB we return must reflect the | ||
1015 | * true state of the block mark, no matter where that block mark appears in | ||
1016 | * the physical page. | ||
1017 | * | ||
1018 | * 3) ECC-based read operations return an OOB full of set bits (since we never | ||
1019 | * allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads | ||
1020 | * return). | ||
1021 | * | ||
1022 | * 4) "Raw" read operations return a direct view of the physical bytes in the | ||
1023 | * page, using the conventional definition of which bytes are data and which | ||
1024 | * are OOB. This gives the caller a way to see the actual, physical bytes | ||
1025 | * in the page, without the distortions applied by our ECC engine. | ||
1026 | * | ||
1027 | * | ||
1028 | * What we do for this specific read operation depends on two questions: | ||
1029 | * | ||
1030 | * 1) Are we doing a "raw" read, or an ECC-based read? | ||
1031 | * | ||
1032 | * 2) Are we using block mark swapping or transcription? | ||
1033 | * | ||
1034 | * There are four cases, illustrated by the following Karnaugh map: | ||
1035 | * | ||
1036 | * | Raw | ECC-based | | ||
1037 | * -------------+-------------------------+-------------------------+ | ||
1038 | * | Read the conventional | | | ||
1039 | * | OOB at the end of the | | | ||
1040 | * Swapping | page and return it. It | | | ||
1041 | * | contains exactly what | | | ||
1042 | * | we want. | Read the block mark and | | ||
1043 | * -------------+-------------------------+ return it in a buffer | | ||
1044 | * | Read the conventional | full of set bits. | | ||
1045 | * | OOB at the end of the | | | ||
1046 | * | page and also the block | | | ||
1047 | * Transcribing | mark in the metadata. | | | ||
1048 | * | Copy the block mark | | | ||
1049 | * | into the first byte of | | | ||
1050 | * | the OOB. | | | ||
1051 | * -------------+-------------------------+-------------------------+ | ||
1052 | * | ||
1053 | * Note that we break rule #4 in the Transcribing/Raw case because we're not | ||
1054 | * giving an accurate view of the actual, physical bytes in the page (we're | ||
1055 | * overwriting the block mark). That's OK because it's more important to follow | ||
1056 | * rule #2. | ||
1057 | * | ||
1058 | * It turns out that knowing whether we want an "ECC-based" or "raw" read is not | ||
1059 | * easy. When reading a page, for example, the NAND Flash MTD code calls our | ||
1060 | * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an | ||
1061 | * ECC-based or raw view of the page is implicit in which function it calls | ||
1062 | * (there is a similar pair of ECC-based/raw functions for writing). | ||
1063 | * | ||
1064 | * Since MTD assumes the OOB is not covered by ECC, there is no pair of | ||
1065 | * ECC-based/raw functions for reading or or writing the OOB. The fact that the | ||
1066 | * caller wants an ECC-based or raw view of the page is not propagated down to | ||
1067 | * this driver. | ||
1068 | */ | ||
1069 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | ||
1070 | int page, int sndcmd) | ||
1071 | { | ||
1072 | struct gpmi_nand_data *this = chip->priv; | ||
1073 | |||
1074 | pr_debug("page number is %d\n", page); | ||
1075 | /* clear the OOB buffer */ | ||
1076 | memset(chip->oob_poi, ~0, mtd->oobsize); | ||
1077 | |||
1078 | /* Read out the conventional OOB. */ | ||
1079 | chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); | ||
1080 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
1081 | |||
1082 | /* | ||
1083 | * Now, we want to make sure the block mark is correct. In the | ||
1084 | * Swapping/Raw case, we already have it. Otherwise, we need to | ||
1085 | * explicitly read it. | ||
1086 | */ | ||
1087 | if (!this->swap_block_mark) { | ||
1088 | /* Read the block mark into the first byte of the OOB buffer. */ | ||
1089 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | ||
1090 | chip->oob_poi[0] = chip->read_byte(mtd); | ||
1091 | } | ||
1092 | |||
1093 | /* | ||
1094 | * Return true, indicating that the next call to this function must send | ||
1095 | * a command. | ||
1096 | */ | ||
1097 | return true; | ||
1098 | } | ||
1099 | |||
1100 | static int | ||
1101 | gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) | ||
1102 | { | ||
1103 | /* | ||
1104 | * The BCH will use all the (page + oob). | ||
1105 | * Our gpmi_hw_ecclayout can only prohibit the JFFS2 to write the oob. | ||
1106 | * But it can not stop some ioctls such MEMWRITEOOB which uses | ||
1107 | * MTD_OPS_PLACE_OOB. So We have to implement this function to prohibit | ||
1108 | * these ioctls too. | ||
1109 | */ | ||
1110 | return -EPERM; | ||
1111 | } | ||
1112 | |||
1113 | static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) | ||
1114 | { | ||
1115 | struct nand_chip *chip = mtd->priv; | ||
1116 | struct gpmi_nand_data *this = chip->priv; | ||
1117 | int block, ret = 0; | ||
1118 | uint8_t *block_mark; | ||
1119 | int column, page, status, chipnr; | ||
1120 | |||
1121 | /* Get block number */ | ||
1122 | block = (int)(ofs >> chip->bbt_erase_shift); | ||
1123 | if (chip->bbt) | ||
1124 | chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | ||
1125 | |||
1126 | /* Do we have a flash based bad block table ? */ | ||
1127 | if (chip->options & NAND_BBT_USE_FLASH) | ||
1128 | ret = nand_update_bbt(mtd, ofs); | ||
1129 | else { | ||
1130 | chipnr = (int)(ofs >> chip->chip_shift); | ||
1131 | chip->select_chip(mtd, chipnr); | ||
1132 | |||
1133 | column = this->swap_block_mark ? mtd->writesize : 0; | ||
1134 | |||
1135 | /* Write the block mark. */ | ||
1136 | block_mark = this->data_buffer_dma; | ||
1137 | block_mark[0] = 0; /* bad block marker */ | ||
1138 | |||
1139 | /* Shift to get page */ | ||
1140 | page = (int)(ofs >> chip->page_shift); | ||
1141 | |||
1142 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); | ||
1143 | chip->write_buf(mtd, block_mark, 1); | ||
1144 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
1145 | |||
1146 | status = chip->waitfunc(mtd, chip); | ||
1147 | if (status & NAND_STATUS_FAIL) | ||
1148 | ret = -EIO; | ||
1149 | |||
1150 | chip->select_chip(mtd, -1); | ||
1151 | } | ||
1152 | if (!ret) | ||
1153 | mtd->ecc_stats.badblocks++; | ||
1154 | |||
1155 | return ret; | ||
1156 | } | ||
1157 | |||
1158 | static int __devinit nand_boot_set_geometry(struct gpmi_nand_data *this) | ||
1159 | { | ||
1160 | struct boot_rom_geometry *geometry = &this->rom_geometry; | ||
1161 | |||
1162 | /* | ||
1163 | * Set the boot block stride size. | ||
1164 | * | ||
1165 | * In principle, we should be reading this from the OTP bits, since | ||
1166 | * that's where the ROM is going to get it. In fact, we don't have any | ||
1167 | * way to read the OTP bits, so we go with the default and hope for the | ||
1168 | * best. | ||
1169 | */ | ||
1170 | geometry->stride_size_in_pages = 64; | ||
1171 | |||
1172 | /* | ||
1173 | * Set the search area stride exponent. | ||
1174 | * | ||
1175 | * In principle, we should be reading this from the OTP bits, since | ||
1176 | * that's where the ROM is going to get it. In fact, we don't have any | ||
1177 | * way to read the OTP bits, so we go with the default and hope for the | ||
1178 | * best. | ||
1179 | */ | ||
1180 | geometry->search_area_stride_exponent = 2; | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static const char *fingerprint = "STMP"; | ||
1185 | static int __devinit mx23_check_transcription_stamp(struct gpmi_nand_data *this) | ||
1186 | { | ||
1187 | struct boot_rom_geometry *rom_geo = &this->rom_geometry; | ||
1188 | struct device *dev = this->dev; | ||
1189 | struct mtd_info *mtd = &this->mtd; | ||
1190 | struct nand_chip *chip = &this->nand; | ||
1191 | unsigned int search_area_size_in_strides; | ||
1192 | unsigned int stride; | ||
1193 | unsigned int page; | ||
1194 | loff_t byte; | ||
1195 | uint8_t *buffer = chip->buffers->databuf; | ||
1196 | int saved_chip_number; | ||
1197 | int found_an_ncb_fingerprint = false; | ||
1198 | |||
1199 | /* Compute the number of strides in a search area. */ | ||
1200 | search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent; | ||
1201 | |||
1202 | saved_chip_number = this->current_chip; | ||
1203 | chip->select_chip(mtd, 0); | ||
1204 | |||
1205 | /* | ||
1206 | * Loop through the first search area, looking for the NCB fingerprint. | ||
1207 | */ | ||
1208 | dev_dbg(dev, "Scanning for an NCB fingerprint...\n"); | ||
1209 | |||
1210 | for (stride = 0; stride < search_area_size_in_strides; stride++) { | ||
1211 | /* Compute the page and byte addresses. */ | ||
1212 | page = stride * rom_geo->stride_size_in_pages; | ||
1213 | byte = page * mtd->writesize; | ||
1214 | |||
1215 | dev_dbg(dev, "Looking for a fingerprint in page 0x%x\n", page); | ||
1216 | |||
1217 | /* | ||
1218 | * Read the NCB fingerprint. The fingerprint is four bytes long | ||
1219 | * and starts in the 12th byte of the page. | ||
1220 | */ | ||
1221 | chip->cmdfunc(mtd, NAND_CMD_READ0, 12, page); | ||
1222 | chip->read_buf(mtd, buffer, strlen(fingerprint)); | ||
1223 | |||
1224 | /* Look for the fingerprint. */ | ||
1225 | if (!memcmp(buffer, fingerprint, strlen(fingerprint))) { | ||
1226 | found_an_ncb_fingerprint = true; | ||
1227 | break; | ||
1228 | } | ||
1229 | |||
1230 | } | ||
1231 | |||
1232 | chip->select_chip(mtd, saved_chip_number); | ||
1233 | |||
1234 | if (found_an_ncb_fingerprint) | ||
1235 | dev_dbg(dev, "\tFound a fingerprint\n"); | ||
1236 | else | ||
1237 | dev_dbg(dev, "\tNo fingerprint found\n"); | ||
1238 | return found_an_ncb_fingerprint; | ||
1239 | } | ||
1240 | |||
1241 | /* Writes a transcription stamp. */ | ||
1242 | static int __devinit mx23_write_transcription_stamp(struct gpmi_nand_data *this) | ||
1243 | { | ||
1244 | struct device *dev = this->dev; | ||
1245 | struct boot_rom_geometry *rom_geo = &this->rom_geometry; | ||
1246 | struct mtd_info *mtd = &this->mtd; | ||
1247 | struct nand_chip *chip = &this->nand; | ||
1248 | unsigned int block_size_in_pages; | ||
1249 | unsigned int search_area_size_in_strides; | ||
1250 | unsigned int search_area_size_in_pages; | ||
1251 | unsigned int search_area_size_in_blocks; | ||
1252 | unsigned int block; | ||
1253 | unsigned int stride; | ||
1254 | unsigned int page; | ||
1255 | loff_t byte; | ||
1256 | uint8_t *buffer = chip->buffers->databuf; | ||
1257 | int saved_chip_number; | ||
1258 | int status; | ||
1259 | |||
1260 | /* Compute the search area geometry. */ | ||
1261 | block_size_in_pages = mtd->erasesize / mtd->writesize; | ||
1262 | search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent; | ||
1263 | search_area_size_in_pages = search_area_size_in_strides * | ||
1264 | rom_geo->stride_size_in_pages; | ||
1265 | search_area_size_in_blocks = | ||
1266 | (search_area_size_in_pages + (block_size_in_pages - 1)) / | ||
1267 | block_size_in_pages; | ||
1268 | |||
1269 | dev_dbg(dev, "Search Area Geometry :\n"); | ||
1270 | dev_dbg(dev, "\tin Blocks : %u\n", search_area_size_in_blocks); | ||
1271 | dev_dbg(dev, "\tin Strides: %u\n", search_area_size_in_strides); | ||
1272 | dev_dbg(dev, "\tin Pages : %u\n", search_area_size_in_pages); | ||
1273 | |||
1274 | /* Select chip 0. */ | ||
1275 | saved_chip_number = this->current_chip; | ||
1276 | chip->select_chip(mtd, 0); | ||
1277 | |||
1278 | /* Loop over blocks in the first search area, erasing them. */ | ||
1279 | dev_dbg(dev, "Erasing the search area...\n"); | ||
1280 | |||
1281 | for (block = 0; block < search_area_size_in_blocks; block++) { | ||
1282 | /* Compute the page address. */ | ||
1283 | page = block * block_size_in_pages; | ||
1284 | |||
1285 | /* Erase this block. */ | ||
1286 | dev_dbg(dev, "\tErasing block 0x%x\n", block); | ||
1287 | chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); | ||
1288 | chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); | ||
1289 | |||
1290 | /* Wait for the erase to finish. */ | ||
1291 | status = chip->waitfunc(mtd, chip); | ||
1292 | if (status & NAND_STATUS_FAIL) | ||
1293 | dev_err(dev, "[%s] Erase failed.\n", __func__); | ||
1294 | } | ||
1295 | |||
1296 | /* Write the NCB fingerprint into the page buffer. */ | ||
1297 | memset(buffer, ~0, mtd->writesize); | ||
1298 | memset(chip->oob_poi, ~0, mtd->oobsize); | ||
1299 | memcpy(buffer + 12, fingerprint, strlen(fingerprint)); | ||
1300 | |||
1301 | /* Loop through the first search area, writing NCB fingerprints. */ | ||
1302 | dev_dbg(dev, "Writing NCB fingerprints...\n"); | ||
1303 | for (stride = 0; stride < search_area_size_in_strides; stride++) { | ||
1304 | /* Compute the page and byte addresses. */ | ||
1305 | page = stride * rom_geo->stride_size_in_pages; | ||
1306 | byte = page * mtd->writesize; | ||
1307 | |||
1308 | /* Write the first page of the current stride. */ | ||
1309 | dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); | ||
1310 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | ||
1311 | chip->ecc.write_page_raw(mtd, chip, buffer); | ||
1312 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
1313 | |||
1314 | /* Wait for the write to finish. */ | ||
1315 | status = chip->waitfunc(mtd, chip); | ||
1316 | if (status & NAND_STATUS_FAIL) | ||
1317 | dev_err(dev, "[%s] Write failed.\n", __func__); | ||
1318 | } | ||
1319 | |||
1320 | /* Deselect chip 0. */ | ||
1321 | chip->select_chip(mtd, saved_chip_number); | ||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | static int __devinit mx23_boot_init(struct gpmi_nand_data *this) | ||
1326 | { | ||
1327 | struct device *dev = this->dev; | ||
1328 | struct nand_chip *chip = &this->nand; | ||
1329 | struct mtd_info *mtd = &this->mtd; | ||
1330 | unsigned int block_count; | ||
1331 | unsigned int block; | ||
1332 | int chipnr; | ||
1333 | int page; | ||
1334 | loff_t byte; | ||
1335 | uint8_t block_mark; | ||
1336 | int ret = 0; | ||
1337 | |||
1338 | /* | ||
1339 | * If control arrives here, we can't use block mark swapping, which | ||
1340 | * means we're forced to use transcription. First, scan for the | ||
1341 | * transcription stamp. If we find it, then we don't have to do | ||
1342 | * anything -- the block marks are already transcribed. | ||
1343 | */ | ||
1344 | if (mx23_check_transcription_stamp(this)) | ||
1345 | return 0; | ||
1346 | |||
1347 | /* | ||
1348 | * If control arrives here, we couldn't find a transcription stamp, so | ||
1349 | * so we presume the block marks are in the conventional location. | ||
1350 | */ | ||
1351 | dev_dbg(dev, "Transcribing bad block marks...\n"); | ||
1352 | |||
1353 | /* Compute the number of blocks in the entire medium. */ | ||
1354 | block_count = chip->chipsize >> chip->phys_erase_shift; | ||
1355 | |||
1356 | /* | ||
1357 | * Loop over all the blocks in the medium, transcribing block marks as | ||
1358 | * we go. | ||
1359 | */ | ||
1360 | for (block = 0; block < block_count; block++) { | ||
1361 | /* | ||
1362 | * Compute the chip, page and byte addresses for this block's | ||
1363 | * conventional mark. | ||
1364 | */ | ||
1365 | chipnr = block >> (chip->chip_shift - chip->phys_erase_shift); | ||
1366 | page = block << (chip->phys_erase_shift - chip->page_shift); | ||
1367 | byte = block << chip->phys_erase_shift; | ||
1368 | |||
1369 | /* Send the command to read the conventional block mark. */ | ||
1370 | chip->select_chip(mtd, chipnr); | ||
1371 | chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); | ||
1372 | block_mark = chip->read_byte(mtd); | ||
1373 | chip->select_chip(mtd, -1); | ||
1374 | |||
1375 | /* | ||
1376 | * Check if the block is marked bad. If so, we need to mark it | ||
1377 | * again, but this time the result will be a mark in the | ||
1378 | * location where we transcribe block marks. | ||
1379 | */ | ||
1380 | if (block_mark != 0xff) { | ||
1381 | dev_dbg(dev, "Transcribing mark in block %u\n", block); | ||
1382 | ret = chip->block_markbad(mtd, byte); | ||
1383 | if (ret) | ||
1384 | dev_err(dev, "Failed to mark block bad with " | ||
1385 | "ret %d\n", ret); | ||
1386 | } | ||
1387 | } | ||
1388 | |||
1389 | /* Write the stamp that indicates we've transcribed the block marks. */ | ||
1390 | mx23_write_transcription_stamp(this); | ||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | static int __devinit nand_boot_init(struct gpmi_nand_data *this) | ||
1395 | { | ||
1396 | nand_boot_set_geometry(this); | ||
1397 | |||
1398 | /* This is ROM arch-specific initilization before the BBT scanning. */ | ||
1399 | if (GPMI_IS_MX23(this)) | ||
1400 | return mx23_boot_init(this); | ||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int __devinit gpmi_set_geometry(struct gpmi_nand_data *this) | ||
1405 | { | ||
1406 | int ret; | ||
1407 | |||
1408 | /* Free the temporary DMA memory for reading ID. */ | ||
1409 | gpmi_free_dma_buffer(this); | ||
1410 | |||
1411 | /* Set up the NFC geometry which is used by BCH. */ | ||
1412 | ret = bch_set_geometry(this); | ||
1413 | if (ret) { | ||
1414 | pr_err("set geometry ret : %d\n", ret); | ||
1415 | return ret; | ||
1416 | } | ||
1417 | |||
1418 | /* Alloc the new DMA buffers according to the pagesize and oobsize */ | ||
1419 | return gpmi_alloc_dma_buffer(this); | ||
1420 | } | ||
1421 | |||
1422 | static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this) | ||
1423 | { | ||
1424 | int ret; | ||
1425 | |||
1426 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ | ||
1427 | if (GPMI_IS_MX23(this)) | ||
1428 | this->swap_block_mark = false; | ||
1429 | else | ||
1430 | this->swap_block_mark = true; | ||
1431 | |||
1432 | /* Set up the medium geometry */ | ||
1433 | ret = gpmi_set_geometry(this); | ||
1434 | if (ret) | ||
1435 | return ret; | ||
1436 | |||
1437 | /* NAND boot init, depends on the gpmi_set_geometry(). */ | ||
1438 | return nand_boot_init(this); | ||
1439 | } | ||
1440 | |||
1441 | static int gpmi_scan_bbt(struct mtd_info *mtd) | ||
1442 | { | ||
1443 | struct nand_chip *chip = mtd->priv; | ||
1444 | struct gpmi_nand_data *this = chip->priv; | ||
1445 | int ret; | ||
1446 | |||
1447 | /* Prepare for the BBT scan. */ | ||
1448 | ret = gpmi_pre_bbt_scan(this); | ||
1449 | if (ret) | ||
1450 | return ret; | ||
1451 | |||
1452 | /* use the default BBT implementation */ | ||
1453 | return nand_default_bbt(mtd); | ||
1454 | } | ||
1455 | |||
1456 | void gpmi_nfc_exit(struct gpmi_nand_data *this) | ||
1457 | { | ||
1458 | nand_release(&this->mtd); | ||
1459 | gpmi_free_dma_buffer(this); | ||
1460 | } | ||
1461 | |||
1462 | static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | ||
1463 | { | ||
1464 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
1465 | struct mtd_info *mtd = &this->mtd; | ||
1466 | struct nand_chip *chip = &this->nand; | ||
1467 | int ret; | ||
1468 | |||
1469 | /* init current chip */ | ||
1470 | this->current_chip = -1; | ||
1471 | |||
1472 | /* init the MTD data structures */ | ||
1473 | mtd->priv = chip; | ||
1474 | mtd->name = "gpmi-nand"; | ||
1475 | mtd->owner = THIS_MODULE; | ||
1476 | |||
1477 | /* init the nand_chip{}, we don't support a 16-bit NAND Flash bus. */ | ||
1478 | chip->priv = this; | ||
1479 | chip->select_chip = gpmi_select_chip; | ||
1480 | chip->cmd_ctrl = gpmi_cmd_ctrl; | ||
1481 | chip->dev_ready = gpmi_dev_ready; | ||
1482 | chip->read_byte = gpmi_read_byte; | ||
1483 | chip->read_buf = gpmi_read_buf; | ||
1484 | chip->write_buf = gpmi_write_buf; | ||
1485 | chip->ecc.read_page = gpmi_ecc_read_page; | ||
1486 | chip->ecc.write_page = gpmi_ecc_write_page; | ||
1487 | chip->ecc.read_oob = gpmi_ecc_read_oob; | ||
1488 | chip->ecc.write_oob = gpmi_ecc_write_oob; | ||
1489 | chip->scan_bbt = gpmi_scan_bbt; | ||
1490 | chip->badblock_pattern = &gpmi_bbt_descr; | ||
1491 | chip->block_markbad = gpmi_block_markbad; | ||
1492 | chip->options |= NAND_NO_SUBPAGE_WRITE; | ||
1493 | chip->ecc.mode = NAND_ECC_HW; | ||
1494 | chip->ecc.size = 1; | ||
1495 | chip->ecc.layout = &gpmi_hw_ecclayout; | ||
1496 | |||
1497 | /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ | ||
1498 | this->bch_geometry.payload_size = 1024; | ||
1499 | this->bch_geometry.auxiliary_size = 128; | ||
1500 | ret = gpmi_alloc_dma_buffer(this); | ||
1501 | if (ret) | ||
1502 | goto err_out; | ||
1503 | |||
1504 | ret = nand_scan(mtd, pdata->max_chip_count); | ||
1505 | if (ret) { | ||
1506 | pr_err("Chip scan failed\n"); | ||
1507 | goto err_out; | ||
1508 | } | ||
1509 | |||
1510 | ret = mtd_device_parse_register(mtd, NULL, NULL, | ||
1511 | pdata->partitions, pdata->partition_count); | ||
1512 | if (ret) | ||
1513 | goto err_out; | ||
1514 | return 0; | ||
1515 | |||
1516 | err_out: | ||
1517 | gpmi_nfc_exit(this); | ||
1518 | return ret; | ||
1519 | } | ||
1520 | |||
1521 | static int __devinit gpmi_nand_probe(struct platform_device *pdev) | ||
1522 | { | ||
1523 | struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data; | ||
1524 | struct gpmi_nand_data *this; | ||
1525 | int ret; | ||
1526 | |||
1527 | this = kzalloc(sizeof(*this), GFP_KERNEL); | ||
1528 | if (!this) { | ||
1529 | pr_err("Failed to allocate per-device memory\n"); | ||
1530 | return -ENOMEM; | ||
1531 | } | ||
1532 | |||
1533 | platform_set_drvdata(pdev, this); | ||
1534 | this->pdev = pdev; | ||
1535 | this->dev = &pdev->dev; | ||
1536 | this->pdata = pdata; | ||
1537 | |||
1538 | if (pdata->platform_init) { | ||
1539 | ret = pdata->platform_init(); | ||
1540 | if (ret) | ||
1541 | goto platform_init_error; | ||
1542 | } | ||
1543 | |||
1544 | ret = acquire_resources(this); | ||
1545 | if (ret) | ||
1546 | goto exit_acquire_resources; | ||
1547 | |||
1548 | ret = init_hardware(this); | ||
1549 | if (ret) | ||
1550 | goto exit_nfc_init; | ||
1551 | |||
1552 | ret = gpmi_nfc_init(this); | ||
1553 | if (ret) | ||
1554 | goto exit_nfc_init; | ||
1555 | |||
1556 | return 0; | ||
1557 | |||
1558 | exit_nfc_init: | ||
1559 | release_resources(this); | ||
1560 | platform_init_error: | ||
1561 | exit_acquire_resources: | ||
1562 | platform_set_drvdata(pdev, NULL); | ||
1563 | kfree(this); | ||
1564 | return ret; | ||
1565 | } | ||
1566 | |||
1567 | static int __exit gpmi_nand_remove(struct platform_device *pdev) | ||
1568 | { | ||
1569 | struct gpmi_nand_data *this = platform_get_drvdata(pdev); | ||
1570 | |||
1571 | gpmi_nfc_exit(this); | ||
1572 | release_resources(this); | ||
1573 | platform_set_drvdata(pdev, NULL); | ||
1574 | kfree(this); | ||
1575 | return 0; | ||
1576 | } | ||
1577 | |||
1578 | static const struct platform_device_id gpmi_ids[] = { | ||
1579 | { | ||
1580 | .name = "imx23-gpmi-nand", | ||
1581 | .driver_data = IS_MX23, | ||
1582 | }, { | ||
1583 | .name = "imx28-gpmi-nand", | ||
1584 | .driver_data = IS_MX28, | ||
1585 | }, {}, | ||
1586 | }; | ||
1587 | |||
1588 | static struct platform_driver gpmi_nand_driver = { | ||
1589 | .driver = { | ||
1590 | .name = "gpmi-nand", | ||
1591 | }, | ||
1592 | .probe = gpmi_nand_probe, | ||
1593 | .remove = __exit_p(gpmi_nand_remove), | ||
1594 | .id_table = gpmi_ids, | ||
1595 | }; | ||
1596 | |||
1597 | static int __init gpmi_nand_init(void) | ||
1598 | { | ||
1599 | int err; | ||
1600 | |||
1601 | err = platform_driver_register(&gpmi_nand_driver); | ||
1602 | if (err == 0) | ||
1603 | printk(KERN_INFO "GPMI NAND driver registered. (IMX)\n"); | ||
1604 | else | ||
1605 | pr_err("i.MX GPMI NAND driver registration failed\n"); | ||
1606 | return err; | ||
1607 | } | ||
1608 | |||
1609 | static void __exit gpmi_nand_exit(void) | ||
1610 | { | ||
1611 | platform_driver_unregister(&gpmi_nand_driver); | ||
1612 | } | ||
1613 | |||
1614 | module_init(gpmi_nand_init); | ||
1615 | module_exit(gpmi_nand_exit); | ||
1616 | |||
1617 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
1618 | MODULE_DESCRIPTION("i.MX GPMI NAND Flash Controller Driver"); | ||
1619 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h new file mode 100644 index 000000000000..e023bccb7781 --- /dev/null +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h | |||
@@ -0,0 +1,273 @@ | |||
1 | /* | ||
2 | * Freescale GPMI NAND Flash Driver | ||
3 | * | ||
4 | * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. | ||
5 | * Copyright (C) 2008 Embedded Alley Solutions, Inc. | ||
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 | #ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H | ||
18 | #define __DRIVERS_MTD_NAND_GPMI_NAND_H | ||
19 | |||
20 | #include <linux/mtd/nand.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/dma-mapping.h> | ||
23 | #include <mach/dma.h> | ||
24 | |||
25 | struct resources { | ||
26 | void *gpmi_regs; | ||
27 | void *bch_regs; | ||
28 | unsigned int bch_low_interrupt; | ||
29 | unsigned int bch_high_interrupt; | ||
30 | unsigned int dma_low_channel; | ||
31 | unsigned int dma_high_channel; | ||
32 | struct clk *clock; | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * struct bch_geometry - BCH geometry description. | ||
37 | * @gf_len: The length of Galois Field. (e.g., 13 or 14) | ||
38 | * @ecc_strength: A number that describes the strength of the ECC | ||
39 | * algorithm. | ||
40 | * @page_size: The size, in bytes, of a physical page, including | ||
41 | * both data and OOB. | ||
42 | * @metadata_size: The size, in bytes, of the metadata. | ||
43 | * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note | ||
44 | * the first chunk in the page includes both data and | ||
45 | * metadata, so it's a bit larger than this value. | ||
46 | * @ecc_chunk_count: The number of ECC chunks in the page, | ||
47 | * @payload_size: The size, in bytes, of the payload buffer. | ||
48 | * @auxiliary_size: The size, in bytes, of the auxiliary buffer. | ||
49 | * @auxiliary_status_offset: The offset into the auxiliary buffer at which | ||
50 | * the ECC status appears. | ||
51 | * @block_mark_byte_offset: The byte offset in the ECC-based page view at | ||
52 | * which the underlying physical block mark appears. | ||
53 | * @block_mark_bit_offset: The bit offset into the ECC-based page view at | ||
54 | * which the underlying physical block mark appears. | ||
55 | */ | ||
56 | struct bch_geometry { | ||
57 | unsigned int gf_len; | ||
58 | unsigned int ecc_strength; | ||
59 | unsigned int page_size; | ||
60 | unsigned int metadata_size; | ||
61 | unsigned int ecc_chunk_size; | ||
62 | unsigned int ecc_chunk_count; | ||
63 | unsigned int payload_size; | ||
64 | unsigned int auxiliary_size; | ||
65 | unsigned int auxiliary_status_offset; | ||
66 | unsigned int block_mark_byte_offset; | ||
67 | unsigned int block_mark_bit_offset; | ||
68 | }; | ||
69 | |||
70 | /** | ||
71 | * struct boot_rom_geometry - Boot ROM geometry description. | ||
72 | * @stride_size_in_pages: The size of a boot block stride, in pages. | ||
73 | * @search_area_stride_exponent: The logarithm to base 2 of the size of a | ||
74 | * search area in boot block strides. | ||
75 | */ | ||
76 | struct boot_rom_geometry { | ||
77 | unsigned int stride_size_in_pages; | ||
78 | unsigned int search_area_stride_exponent; | ||
79 | }; | ||
80 | |||
81 | /* DMA operations types */ | ||
82 | enum dma_ops_type { | ||
83 | DMA_FOR_COMMAND = 1, | ||
84 | DMA_FOR_READ_DATA, | ||
85 | DMA_FOR_WRITE_DATA, | ||
86 | DMA_FOR_READ_ECC_PAGE, | ||
87 | DMA_FOR_WRITE_ECC_PAGE | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct nand_timing - Fundamental timing attributes for NAND. | ||
92 | * @data_setup_in_ns: The data setup time, in nanoseconds. Usually the | ||
93 | * maximum of tDS and tWP. A negative value | ||
94 | * indicates this characteristic isn't known. | ||
95 | * @data_hold_in_ns: The data hold time, in nanoseconds. Usually the | ||
96 | * maximum of tDH, tWH and tREH. A negative value | ||
97 | * indicates this characteristic isn't known. | ||
98 | * @address_setup_in_ns: The address setup time, in nanoseconds. Usually | ||
99 | * the maximum of tCLS, tCS and tALS. A negative | ||
100 | * value indicates this characteristic isn't known. | ||
101 | * @gpmi_sample_delay_in_ns: A GPMI-specific timing parameter. A negative value | ||
102 | * indicates this characteristic isn't known. | ||
103 | * @tREA_in_ns: tREA, in nanoseconds, from the data sheet. A | ||
104 | * negative value indicates this characteristic isn't | ||
105 | * known. | ||
106 | * @tRLOH_in_ns: tRLOH, in nanoseconds, from the data sheet. A | ||
107 | * negative value indicates this characteristic isn't | ||
108 | * known. | ||
109 | * @tRHOH_in_ns: tRHOH, in nanoseconds, from the data sheet. A | ||
110 | * negative value indicates this characteristic isn't | ||
111 | * known. | ||
112 | */ | ||
113 | struct nand_timing { | ||
114 | int8_t data_setup_in_ns; | ||
115 | int8_t data_hold_in_ns; | ||
116 | int8_t address_setup_in_ns; | ||
117 | int8_t gpmi_sample_delay_in_ns; | ||
118 | int8_t tREA_in_ns; | ||
119 | int8_t tRLOH_in_ns; | ||
120 | int8_t tRHOH_in_ns; | ||
121 | }; | ||
122 | |||
123 | struct gpmi_nand_data { | ||
124 | /* System Interface */ | ||
125 | struct device *dev; | ||
126 | struct platform_device *pdev; | ||
127 | struct gpmi_nand_platform_data *pdata; | ||
128 | |||
129 | /* Resources */ | ||
130 | struct resources resources; | ||
131 | |||
132 | /* Flash Hardware */ | ||
133 | struct nand_timing timing; | ||
134 | |||
135 | /* BCH */ | ||
136 | struct bch_geometry bch_geometry; | ||
137 | struct completion bch_done; | ||
138 | |||
139 | /* NAND Boot issue */ | ||
140 | bool swap_block_mark; | ||
141 | struct boot_rom_geometry rom_geometry; | ||
142 | |||
143 | /* MTD / NAND */ | ||
144 | struct nand_chip nand; | ||
145 | struct mtd_info mtd; | ||
146 | |||
147 | /* General-use Variables */ | ||
148 | int current_chip; | ||
149 | unsigned int command_length; | ||
150 | |||
151 | /* passed from upper layer */ | ||
152 | uint8_t *upper_buf; | ||
153 | int upper_len; | ||
154 | |||
155 | /* for DMA operations */ | ||
156 | bool direct_dma_map_ok; | ||
157 | |||
158 | struct scatterlist cmd_sgl; | ||
159 | char *cmd_buffer; | ||
160 | |||
161 | struct scatterlist data_sgl; | ||
162 | char *data_buffer_dma; | ||
163 | |||
164 | void *page_buffer_virt; | ||
165 | dma_addr_t page_buffer_phys; | ||
166 | unsigned int page_buffer_size; | ||
167 | |||
168 | void *payload_virt; | ||
169 | dma_addr_t payload_phys; | ||
170 | |||
171 | void *auxiliary_virt; | ||
172 | dma_addr_t auxiliary_phys; | ||
173 | |||
174 | /* DMA channels */ | ||
175 | #define DMA_CHANS 8 | ||
176 | struct dma_chan *dma_chans[DMA_CHANS]; | ||
177 | struct mxs_dma_data dma_data; | ||
178 | enum dma_ops_type last_dma_type; | ||
179 | enum dma_ops_type dma_type; | ||
180 | struct completion dma_done; | ||
181 | |||
182 | /* private */ | ||
183 | void *private; | ||
184 | }; | ||
185 | |||
186 | /** | ||
187 | * struct gpmi_nfc_hardware_timing - GPMI hardware timing parameters. | ||
188 | * @data_setup_in_cycles: The data setup time, in cycles. | ||
189 | * @data_hold_in_cycles: The data hold time, in cycles. | ||
190 | * @address_setup_in_cycles: The address setup time, in cycles. | ||
191 | * @use_half_periods: Indicates the clock is running slowly, so the | ||
192 | * NFC DLL should use half-periods. | ||
193 | * @sample_delay_factor: The sample delay factor. | ||
194 | */ | ||
195 | struct gpmi_nfc_hardware_timing { | ||
196 | uint8_t data_setup_in_cycles; | ||
197 | uint8_t data_hold_in_cycles; | ||
198 | uint8_t address_setup_in_cycles; | ||
199 | bool use_half_periods; | ||
200 | uint8_t sample_delay_factor; | ||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * struct timing_threshod - Timing threshold | ||
205 | * @max_data_setup_cycles: The maximum number of data setup cycles that | ||
206 | * can be expressed in the hardware. | ||
207 | * @internal_data_setup_in_ns: The time, in ns, that the NFC hardware requires | ||
208 | * for data read internal setup. In the Reference | ||
209 | * Manual, see the chapter "High-Speed NAND | ||
210 | * Timing" for more details. | ||
211 | * @max_sample_delay_factor: The maximum sample delay factor that can be | ||
212 | * expressed in the hardware. | ||
213 | * @max_dll_clock_period_in_ns: The maximum period of the GPMI clock that the | ||
214 | * sample delay DLL hardware can possibly work | ||
215 | * with (the DLL is unusable with longer periods). | ||
216 | * If the full-cycle period is greater than HALF | ||
217 | * this value, the DLL must be configured to use | ||
218 | * half-periods. | ||
219 | * @max_dll_delay_in_ns: The maximum amount of delay, in ns, that the | ||
220 | * DLL can implement. | ||
221 | * @clock_frequency_in_hz: The clock frequency, in Hz, during the current | ||
222 | * I/O transaction. If no I/O transaction is in | ||
223 | * progress, this is the clock frequency during | ||
224 | * the most recent I/O transaction. | ||
225 | */ | ||
226 | struct timing_threshod { | ||
227 | const unsigned int max_chip_count; | ||
228 | const unsigned int max_data_setup_cycles; | ||
229 | const unsigned int internal_data_setup_in_ns; | ||
230 | const unsigned int max_sample_delay_factor; | ||
231 | const unsigned int max_dll_clock_period_in_ns; | ||
232 | const unsigned int max_dll_delay_in_ns; | ||
233 | unsigned long clock_frequency_in_hz; | ||
234 | |||
235 | }; | ||
236 | |||
237 | /* Common Services */ | ||
238 | extern int common_nfc_set_geometry(struct gpmi_nand_data *); | ||
239 | extern struct dma_chan *get_dma_chan(struct gpmi_nand_data *); | ||
240 | extern void prepare_data_dma(struct gpmi_nand_data *, | ||
241 | enum dma_data_direction dr); | ||
242 | extern int start_dma_without_bch_irq(struct gpmi_nand_data *, | ||
243 | struct dma_async_tx_descriptor *); | ||
244 | extern int start_dma_with_bch_irq(struct gpmi_nand_data *, | ||
245 | struct dma_async_tx_descriptor *); | ||
246 | |||
247 | /* GPMI-NAND helper function library */ | ||
248 | extern int gpmi_init(struct gpmi_nand_data *); | ||
249 | extern void gpmi_clear_bch(struct gpmi_nand_data *); | ||
250 | extern void gpmi_dump_info(struct gpmi_nand_data *); | ||
251 | extern int bch_set_geometry(struct gpmi_nand_data *); | ||
252 | extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip); | ||
253 | extern int gpmi_send_command(struct gpmi_nand_data *); | ||
254 | extern void gpmi_begin(struct gpmi_nand_data *); | ||
255 | extern void gpmi_end(struct gpmi_nand_data *); | ||
256 | extern int gpmi_read_data(struct gpmi_nand_data *); | ||
257 | extern int gpmi_send_data(struct gpmi_nand_data *); | ||
258 | extern int gpmi_send_page(struct gpmi_nand_data *, | ||
259 | dma_addr_t payload, dma_addr_t auxiliary); | ||
260 | extern int gpmi_read_page(struct gpmi_nand_data *, | ||
261 | dma_addr_t payload, dma_addr_t auxiliary); | ||
262 | |||
263 | /* BCH : Status Block Completion Codes */ | ||
264 | #define STATUS_GOOD 0x00 | ||
265 | #define STATUS_ERASED 0xff | ||
266 | #define STATUS_UNCORRECTABLE 0xfe | ||
267 | |||
268 | /* Use the platform_id to distinguish different Archs. */ | ||
269 | #define IS_MX23 0x1 | ||
270 | #define IS_MX28 0x2 | ||
271 | #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) | ||
272 | #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) | ||
273 | #endif | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h new file mode 100644 index 000000000000..83431240e2f2 --- /dev/null +++ b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Freescale GPMI NAND Flash Driver | ||
3 | * | ||
4 | * Copyright 2008-2011 Freescale Semiconductor, Inc. | ||
5 | * Copyright 2008 Embedded Alley Solutions, Inc. | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | #ifndef __GPMI_NAND_GPMI_REGS_H | ||
22 | #define __GPMI_NAND_GPMI_REGS_H | ||
23 | |||
24 | #define HW_GPMI_CTRL0 0x00000000 | ||
25 | #define HW_GPMI_CTRL0_SET 0x00000004 | ||
26 | #define HW_GPMI_CTRL0_CLR 0x00000008 | ||
27 | #define HW_GPMI_CTRL0_TOG 0x0000000c | ||
28 | |||
29 | #define BP_GPMI_CTRL0_COMMAND_MODE 24 | ||
30 | #define BM_GPMI_CTRL0_COMMAND_MODE (3 << BP_GPMI_CTRL0_COMMAND_MODE) | ||
31 | #define BF_GPMI_CTRL0_COMMAND_MODE(v) \ | ||
32 | (((v) << BP_GPMI_CTRL0_COMMAND_MODE) & BM_GPMI_CTRL0_COMMAND_MODE) | ||
33 | #define BV_GPMI_CTRL0_COMMAND_MODE__WRITE 0x0 | ||
34 | #define BV_GPMI_CTRL0_COMMAND_MODE__READ 0x1 | ||
35 | #define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE 0x2 | ||
36 | #define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY 0x3 | ||
37 | |||
38 | #define BM_GPMI_CTRL0_WORD_LENGTH (1 << 23) | ||
39 | #define BV_GPMI_CTRL0_WORD_LENGTH__16_BIT 0x0 | ||
40 | #define BV_GPMI_CTRL0_WORD_LENGTH__8_BIT 0x1 | ||
41 | |||
42 | /* | ||
43 | * Difference in LOCK_CS between imx23 and imx28 : | ||
44 | * This bit may impact the _POWER_ consumption. So some chips | ||
45 | * do not set it. | ||
46 | */ | ||
47 | #define MX23_BP_GPMI_CTRL0_LOCK_CS 22 | ||
48 | #define MX28_BP_GPMI_CTRL0_LOCK_CS 27 | ||
49 | #define LOCK_CS_ENABLE 0x1 | ||
50 | #define BF_GPMI_CTRL0_LOCK_CS(v, x) 0x0 | ||
51 | |||
52 | /* Difference in CS between imx23 and imx28 */ | ||
53 | #define BP_GPMI_CTRL0_CS 20 | ||
54 | #define MX23_BM_GPMI_CTRL0_CS (3 << BP_GPMI_CTRL0_CS) | ||
55 | #define MX28_BM_GPMI_CTRL0_CS (7 << BP_GPMI_CTRL0_CS) | ||
56 | #define BF_GPMI_CTRL0_CS(v, x) (((v) << BP_GPMI_CTRL0_CS) & \ | ||
57 | (GPMI_IS_MX23((x)) \ | ||
58 | ? MX23_BM_GPMI_CTRL0_CS \ | ||
59 | : MX28_BM_GPMI_CTRL0_CS)) | ||
60 | |||
61 | #define BP_GPMI_CTRL0_ADDRESS 17 | ||
62 | #define BM_GPMI_CTRL0_ADDRESS (3 << BP_GPMI_CTRL0_ADDRESS) | ||
63 | #define BF_GPMI_CTRL0_ADDRESS(v) \ | ||
64 | (((v) << BP_GPMI_CTRL0_ADDRESS) & BM_GPMI_CTRL0_ADDRESS) | ||
65 | #define BV_GPMI_CTRL0_ADDRESS__NAND_DATA 0x0 | ||
66 | #define BV_GPMI_CTRL0_ADDRESS__NAND_CLE 0x1 | ||
67 | #define BV_GPMI_CTRL0_ADDRESS__NAND_ALE 0x2 | ||
68 | |||
69 | #define BM_GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16) | ||
70 | #define BV_GPMI_CTRL0_ADDRESS_INCREMENT__DISABLED 0x0 | ||
71 | #define BV_GPMI_CTRL0_ADDRESS_INCREMENT__ENABLED 0x1 | ||
72 | |||
73 | #define BP_GPMI_CTRL0_XFER_COUNT 0 | ||
74 | #define BM_GPMI_CTRL0_XFER_COUNT (0xffff << BP_GPMI_CTRL0_XFER_COUNT) | ||
75 | #define BF_GPMI_CTRL0_XFER_COUNT(v) \ | ||
76 | (((v) << BP_GPMI_CTRL0_XFER_COUNT) & BM_GPMI_CTRL0_XFER_COUNT) | ||
77 | |||
78 | #define HW_GPMI_COMPARE 0x00000010 | ||
79 | |||
80 | #define HW_GPMI_ECCCTRL 0x00000020 | ||
81 | #define HW_GPMI_ECCCTRL_SET 0x00000024 | ||
82 | #define HW_GPMI_ECCCTRL_CLR 0x00000028 | ||
83 | #define HW_GPMI_ECCCTRL_TOG 0x0000002c | ||
84 | |||
85 | #define BP_GPMI_ECCCTRL_ECC_CMD 13 | ||
86 | #define BM_GPMI_ECCCTRL_ECC_CMD (3 << BP_GPMI_ECCCTRL_ECC_CMD) | ||
87 | #define BF_GPMI_ECCCTRL_ECC_CMD(v) \ | ||
88 | (((v) << BP_GPMI_ECCCTRL_ECC_CMD) & BM_GPMI_ECCCTRL_ECC_CMD) | ||
89 | #define BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE 0x0 | ||
90 | #define BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE 0x1 | ||
91 | |||
92 | #define BM_GPMI_ECCCTRL_ENABLE_ECC (1 << 12) | ||
93 | #define BV_GPMI_ECCCTRL_ENABLE_ECC__ENABLE 0x1 | ||
94 | #define BV_GPMI_ECCCTRL_ENABLE_ECC__DISABLE 0x0 | ||
95 | |||
96 | #define BP_GPMI_ECCCTRL_BUFFER_MASK 0 | ||
97 | #define BM_GPMI_ECCCTRL_BUFFER_MASK (0x1ff << BP_GPMI_ECCCTRL_BUFFER_MASK) | ||
98 | #define BF_GPMI_ECCCTRL_BUFFER_MASK(v) \ | ||
99 | (((v) << BP_GPMI_ECCCTRL_BUFFER_MASK) & BM_GPMI_ECCCTRL_BUFFER_MASK) | ||
100 | #define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY 0x100 | ||
101 | #define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE 0x1FF | ||
102 | |||
103 | #define HW_GPMI_ECCCOUNT 0x00000030 | ||
104 | #define HW_GPMI_PAYLOAD 0x00000040 | ||
105 | #define HW_GPMI_AUXILIARY 0x00000050 | ||
106 | #define HW_GPMI_CTRL1 0x00000060 | ||
107 | #define HW_GPMI_CTRL1_SET 0x00000064 | ||
108 | #define HW_GPMI_CTRL1_CLR 0x00000068 | ||
109 | #define HW_GPMI_CTRL1_TOG 0x0000006c | ||
110 | |||
111 | #define BM_GPMI_CTRL1_BCH_MODE (1 << 18) | ||
112 | |||
113 | #define BP_GPMI_CTRL1_DLL_ENABLE 17 | ||
114 | #define BM_GPMI_CTRL1_DLL_ENABLE (1 << BP_GPMI_CTRL1_DLL_ENABLE) | ||
115 | |||
116 | #define BP_GPMI_CTRL1_HALF_PERIOD 16 | ||
117 | #define BM_GPMI_CTRL1_HALF_PERIOD (1 << BP_GPMI_CTRL1_HALF_PERIOD) | ||
118 | |||
119 | #define BP_GPMI_CTRL1_RDN_DELAY 12 | ||
120 | #define BM_GPMI_CTRL1_RDN_DELAY (0xf << BP_GPMI_CTRL1_RDN_DELAY) | ||
121 | #define BF_GPMI_CTRL1_RDN_DELAY(v) \ | ||
122 | (((v) << BP_GPMI_CTRL1_RDN_DELAY) & BM_GPMI_CTRL1_RDN_DELAY) | ||
123 | |||
124 | #define BM_GPMI_CTRL1_DEV_RESET (1 << 3) | ||
125 | #define BV_GPMI_CTRL1_DEV_RESET__ENABLED 0x0 | ||
126 | #define BV_GPMI_CTRL1_DEV_RESET__DISABLED 0x1 | ||
127 | |||
128 | #define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY (1 << 2) | ||
129 | #define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVELOW 0x0 | ||
130 | #define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVEHIGH 0x1 | ||
131 | |||
132 | #define BM_GPMI_CTRL1_CAMERA_MODE (1 << 1) | ||
133 | #define BV_GPMI_CTRL1_GPMI_MODE__NAND 0x0 | ||
134 | #define BV_GPMI_CTRL1_GPMI_MODE__ATA 0x1 | ||
135 | |||
136 | #define BM_GPMI_CTRL1_GPMI_MODE (1 << 0) | ||
137 | |||
138 | #define HW_GPMI_TIMING0 0x00000070 | ||
139 | |||
140 | #define BP_GPMI_TIMING0_ADDRESS_SETUP 16 | ||
141 | #define BM_GPMI_TIMING0_ADDRESS_SETUP (0xff << BP_GPMI_TIMING0_ADDRESS_SETUP) | ||
142 | #define BF_GPMI_TIMING0_ADDRESS_SETUP(v) \ | ||
143 | (((v) << BP_GPMI_TIMING0_ADDRESS_SETUP) & BM_GPMI_TIMING0_ADDRESS_SETUP) | ||
144 | |||
145 | #define BP_GPMI_TIMING0_DATA_HOLD 8 | ||
146 | #define BM_GPMI_TIMING0_DATA_HOLD (0xff << BP_GPMI_TIMING0_DATA_HOLD) | ||
147 | #define BF_GPMI_TIMING0_DATA_HOLD(v) \ | ||
148 | (((v) << BP_GPMI_TIMING0_DATA_HOLD) & BM_GPMI_TIMING0_DATA_HOLD) | ||
149 | |||
150 | #define BP_GPMI_TIMING0_DATA_SETUP 0 | ||
151 | #define BM_GPMI_TIMING0_DATA_SETUP (0xff << BP_GPMI_TIMING0_DATA_SETUP) | ||
152 | #define BF_GPMI_TIMING0_DATA_SETUP(v) \ | ||
153 | (((v) << BP_GPMI_TIMING0_DATA_SETUP) & BM_GPMI_TIMING0_DATA_SETUP) | ||
154 | |||
155 | #define HW_GPMI_TIMING1 0x00000080 | ||
156 | #define BP_GPMI_TIMING1_BUSY_TIMEOUT 16 | ||
157 | |||
158 | #define HW_GPMI_TIMING2 0x00000090 | ||
159 | #define HW_GPMI_DATA 0x000000a0 | ||
160 | |||
161 | /* MX28 uses this to detect READY. */ | ||
162 | #define HW_GPMI_STAT 0x000000b0 | ||
163 | #define MX28_BP_GPMI_STAT_READY_BUSY 24 | ||
164 | #define MX28_BM_GPMI_STAT_READY_BUSY (0xff << MX28_BP_GPMI_STAT_READY_BUSY) | ||
165 | #define MX28_BF_GPMI_STAT_READY_BUSY(v) \ | ||
166 | (((v) << MX28_BP_GPMI_STAT_READY_BUSY) & MX28_BM_GPMI_STAT_READY_BUSY) | ||
167 | |||
168 | /* MX23 uses this to detect READY. */ | ||
169 | #define HW_GPMI_DEBUG 0x000000c0 | ||
170 | #define MX23_BP_GPMI_DEBUG_READY0 28 | ||
171 | #define MX23_BM_GPMI_DEBUG_READY0 (1 << MX23_BP_GPMI_DEBUG_READY0) | ||
172 | #endif | ||
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index 02a03e67109c..5dc6f0d92f1a 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c | |||
@@ -81,9 +81,6 @@ static int h1910_device_ready(struct mtd_info *mtd) | |||
81 | static int __init h1910_init(void) | 81 | static int __init h1910_init(void) |
82 | { | 82 | { |
83 | struct nand_chip *this; | 83 | struct nand_chip *this; |
84 | const char *part_type = 0; | ||
85 | int mtd_parts_nb = 0; | ||
86 | struct mtd_partition *mtd_parts = 0; | ||
87 | void __iomem *nandaddr; | 84 | void __iomem *nandaddr; |
88 | 85 | ||
89 | if (!machine_is_h1900()) | 86 | if (!machine_is_h1900()) |
@@ -136,22 +133,10 @@ static int __init h1910_init(void) | |||
136 | iounmap((void *)nandaddr); | 133 | iounmap((void *)nandaddr); |
137 | return -ENXIO; | 134 | return -ENXIO; |
138 | } | 135 | } |
139 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
140 | mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand"); | ||
141 | if (mtd_parts_nb > 0) | ||
142 | part_type = "command line"; | ||
143 | else | ||
144 | mtd_parts_nb = 0; | ||
145 | #endif | ||
146 | if (mtd_parts_nb == 0) { | ||
147 | mtd_parts = partition_info; | ||
148 | mtd_parts_nb = NUM_PARTITIONS; | ||
149 | part_type = "static"; | ||
150 | } | ||
151 | 136 | ||
152 | /* Register the partitions */ | 137 | /* Register the partitions */ |
153 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 138 | mtd_device_parse_register(h1910_nand_mtd, NULL, 0, |
154 | mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb); | 139 | partition_info, NUM_PARTITIONS); |
155 | 140 | ||
156 | /* Return happy */ | 141 | /* Return happy */ |
157 | return 0; | 142 | return 0; |
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 6e813daed068..e2664073a89b 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
@@ -251,10 +251,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, | |||
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
253 | 253 | ||
254 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
255 | static const char *part_probes[] = {"cmdline", NULL}; | ||
256 | #endif | ||
257 | |||
258 | static int jz_nand_ioremap_resource(struct platform_device *pdev, | 254 | static int jz_nand_ioremap_resource(struct platform_device *pdev, |
259 | const char *name, struct resource **res, void __iomem **base) | 255 | const char *name, struct resource **res, void __iomem **base) |
260 | { | 256 | { |
@@ -299,8 +295,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) | |||
299 | struct nand_chip *chip; | 295 | struct nand_chip *chip; |
300 | struct mtd_info *mtd; | 296 | struct mtd_info *mtd; |
301 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; | 297 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; |
302 | struct mtd_partition *partition_info; | ||
303 | int num_partitions = 0; | ||
304 | 298 | ||
305 | nand = kzalloc(sizeof(*nand), GFP_KERNEL); | 299 | nand = kzalloc(sizeof(*nand), GFP_KERNEL); |
306 | if (!nand) { | 300 | if (!nand) { |
@@ -373,15 +367,9 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) | |||
373 | goto err_gpio_free; | 367 | goto err_gpio_free; |
374 | } | 368 | } |
375 | 369 | ||
376 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 370 | ret = mtd_device_parse_register(mtd, NULL, 0, |
377 | num_partitions = parse_mtd_partitions(mtd, part_probes, | 371 | pdata ? pdata->partitions : NULL, |
378 | &partition_info, 0); | 372 | pdata ? pdata->num_partitions : 0); |
379 | #endif | ||
380 | if (num_partitions <= 0 && pdata) { | ||
381 | num_partitions = pdata->num_partitions; | ||
382 | partition_info = pdata->partitions; | ||
383 | } | ||
384 | ret = mtd_device_register(mtd, partition_info, num_partitions); | ||
385 | 373 | ||
386 | if (ret) { | 374 | if (ret) { |
387 | dev_err(&pdev->dev, "Failed to add mtd device\n"); | 375 | dev_err(&pdev->dev, "Failed to add mtd device\n"); |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index eb1fbac63eb6..5ede64706346 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -131,8 +131,6 @@ struct mpc5121_nfc_prv { | |||
131 | 131 | ||
132 | static void mpc5121_nfc_done(struct mtd_info *mtd); | 132 | static void mpc5121_nfc_done(struct mtd_info *mtd); |
133 | 133 | ||
134 | static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL }; | ||
135 | |||
136 | /* Read NFC register */ | 134 | /* Read NFC register */ |
137 | static inline u16 nfc_read(struct mtd_info *mtd, uint reg) | 135 | static inline u16 nfc_read(struct mtd_info *mtd, uint reg) |
138 | { | 136 | { |
@@ -656,13 +654,13 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
656 | struct mpc5121_nfc_prv *prv; | 654 | struct mpc5121_nfc_prv *prv; |
657 | struct resource res; | 655 | struct resource res; |
658 | struct mtd_info *mtd; | 656 | struct mtd_info *mtd; |
659 | struct mtd_partition *parts; | ||
660 | struct nand_chip *chip; | 657 | struct nand_chip *chip; |
661 | unsigned long regs_paddr, regs_size; | 658 | unsigned long regs_paddr, regs_size; |
662 | const __be32 *chips_no; | 659 | const __be32 *chips_no; |
663 | int resettime = 0; | 660 | int resettime = 0; |
664 | int retval = 0; | 661 | int retval = 0; |
665 | int rev, len; | 662 | int rev, len; |
663 | struct mtd_part_parser_data ppdata; | ||
666 | 664 | ||
667 | /* | 665 | /* |
668 | * Check SoC revision. This driver supports only NFC | 666 | * Check SoC revision. This driver supports only NFC |
@@ -727,6 +725,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
727 | } | 725 | } |
728 | 726 | ||
729 | mtd->name = "MPC5121 NAND"; | 727 | mtd->name = "MPC5121 NAND"; |
728 | ppdata.of_node = dn; | ||
730 | chip->dev_ready = mpc5121_nfc_dev_ready; | 729 | chip->dev_ready = mpc5121_nfc_dev_ready; |
731 | chip->cmdfunc = mpc5121_nfc_command; | 730 | chip->cmdfunc = mpc5121_nfc_command; |
732 | chip->read_byte = mpc5121_nfc_read_byte; | 731 | chip->read_byte = mpc5121_nfc_read_byte; |
@@ -735,7 +734,8 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
735 | chip->write_buf = mpc5121_nfc_write_buf; | 734 | chip->write_buf = mpc5121_nfc_write_buf; |
736 | chip->verify_buf = mpc5121_nfc_verify_buf; | 735 | chip->verify_buf = mpc5121_nfc_verify_buf; |
737 | chip->select_chip = mpc5121_nfc_select_chip; | 736 | chip->select_chip = mpc5121_nfc_select_chip; |
738 | chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT; | 737 | chip->options = NAND_NO_AUTOINCR; |
738 | chip->bbt_options = NAND_BBT_USE_FLASH; | ||
739 | chip->ecc.mode = NAND_ECC_SOFT; | 739 | chip->ecc.mode = NAND_ECC_SOFT; |
740 | 740 | ||
741 | /* Support external chip-select logic on ADS5121 board */ | 741 | /* Support external chip-select logic on ADS5121 board */ |
@@ -837,19 +837,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
837 | dev_set_drvdata(dev, mtd); | 837 | dev_set_drvdata(dev, mtd); |
838 | 838 | ||
839 | /* Register device in MTD */ | 839 | /* Register device in MTD */ |
840 | retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0); | 840 | retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
841 | #ifdef CONFIG_MTD_OF_PARTS | ||
842 | if (retval == 0) | ||
843 | retval = of_mtd_parse_partitions(dev, dn, &parts); | ||
844 | #endif | ||
845 | if (retval < 0) { | ||
846 | dev_err(dev, "Error parsing MTD partitions!\n"); | ||
847 | devm_free_irq(dev, prv->irq, mtd); | ||
848 | retval = -EINVAL; | ||
849 | goto error; | ||
850 | } | ||
851 | |||
852 | retval = mtd_device_register(mtd, parts, retval); | ||
853 | if (retval) { | 841 | if (retval) { |
854 | dev_err(dev, "Error adding MTD device!\n"); | 842 | dev_err(dev, "Error adding MTD device!\n"); |
855 | devm_free_irq(dev, prv->irq, mtd); | 843 | devm_free_irq(dev, prv->irq, mtd); |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 90df34c4d26c..74a43b818d0e 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -41,7 +41,7 @@ | |||
41 | 41 | ||
42 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) | 42 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) |
43 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) | 43 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) |
44 | #define nfc_is_v3_2() cpu_is_mx51() | 44 | #define nfc_is_v3_2() (cpu_is_mx51() || cpu_is_mx53()) |
45 | #define nfc_is_v3() nfc_is_v3_2() | 45 | #define nfc_is_v3() nfc_is_v3_2() |
46 | 46 | ||
47 | /* Addresses for NFC registers */ | 47 | /* Addresses for NFC registers */ |
@@ -143,7 +143,6 @@ | |||
143 | struct mxc_nand_host { | 143 | struct mxc_nand_host { |
144 | struct mtd_info mtd; | 144 | struct mtd_info mtd; |
145 | struct nand_chip nand; | 145 | struct nand_chip nand; |
146 | struct mtd_partition *parts; | ||
147 | struct device *dev; | 146 | struct device *dev; |
148 | 147 | ||
149 | void *spare0; | 148 | void *spare0; |
@@ -350,8 +349,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
350 | udelay(1); | 349 | udelay(1); |
351 | } | 350 | } |
352 | if (max_retries < 0) | 351 | if (max_retries < 0) |
353 | DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n", | 352 | pr_debug("%s: INT not set\n", __func__); |
354 | __func__); | ||
355 | } | 353 | } |
356 | } | 354 | } |
357 | 355 | ||
@@ -371,7 +369,7 @@ static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
371 | * waits for completion. */ | 369 | * waits for completion. */ |
372 | static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) | 370 | static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) |
373 | { | 371 | { |
374 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); | 372 | pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq); |
375 | 373 | ||
376 | writew(cmd, NFC_V1_V2_FLASH_CMD); | 374 | writew(cmd, NFC_V1_V2_FLASH_CMD); |
377 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); | 375 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); |
@@ -387,8 +385,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
387 | udelay(1); | 385 | udelay(1); |
388 | } | 386 | } |
389 | if (max_retries < 0) | 387 | if (max_retries < 0) |
390 | DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n", | 388 | pr_debug("%s: RESET failed\n", __func__); |
391 | __func__); | ||
392 | } else { | 389 | } else { |
393 | /* Wait for operation to complete */ | 390 | /* Wait for operation to complete */ |
394 | wait_op_done(host, useirq); | 391 | wait_op_done(host, useirq); |
@@ -411,7 +408,7 @@ static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast) | |||
411 | * a NAND command. */ | 408 | * a NAND command. */ |
412 | static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast) | 409 | static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast) |
413 | { | 410 | { |
414 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); | 411 | pr_debug("send_addr(host, 0x%x %d)\n", addr, islast); |
415 | 412 | ||
416 | writew(addr, NFC_V1_V2_FLASH_ADDR); | 413 | writew(addr, NFC_V1_V2_FLASH_ADDR); |
417 | writew(NFC_ADDR, NFC_V1_V2_CONFIG2); | 414 | writew(NFC_ADDR, NFC_V1_V2_CONFIG2); |
@@ -561,8 +558,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, | |||
561 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); | 558 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); |
562 | 559 | ||
563 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | 560 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { |
564 | DEBUG(MTD_DEBUG_LEVEL0, | 561 | pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); |
565 | "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); | ||
566 | return -1; | 562 | return -1; |
567 | } | 563 | } |
568 | 564 | ||
@@ -849,7 +845,7 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
849 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); | 845 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); |
850 | } else if (nfc_is_v1()) { | 846 | } else if (nfc_is_v1()) { |
851 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | 847 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); |
852 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); | 848 | writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); |
853 | } else | 849 | } else |
854 | BUG(); | 850 | BUG(); |
855 | 851 | ||
@@ -932,8 +928,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
932 | struct nand_chip *nand_chip = mtd->priv; | 928 | struct nand_chip *nand_chip = mtd->priv; |
933 | struct mxc_nand_host *host = nand_chip->priv; | 929 | struct mxc_nand_host *host = nand_chip->priv; |
934 | 930 | ||
935 | DEBUG(MTD_DEBUG_LEVEL3, | 931 | pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", |
936 | "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", | ||
937 | command, column, page_addr); | 932 | command, column, page_addr); |
938 | 933 | ||
939 | /* Reset command state information */ | 934 | /* Reset command state information */ |
@@ -1044,7 +1039,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1044 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | 1039 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; |
1045 | struct mxc_nand_host *host; | 1040 | struct mxc_nand_host *host; |
1046 | struct resource *res; | 1041 | struct resource *res; |
1047 | int err = 0, __maybe_unused nr_parts = 0; | 1042 | int err = 0; |
1048 | struct nand_ecclayout *oob_smallpage, *oob_largepage; | 1043 | struct nand_ecclayout *oob_smallpage, *oob_largepage; |
1049 | 1044 | ||
1050 | /* Allocate memory for MTD device structure and private data */ | 1045 | /* Allocate memory for MTD device structure and private data */ |
@@ -1179,7 +1174,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1179 | this->bbt_td = &bbt_main_descr; | 1174 | this->bbt_td = &bbt_main_descr; |
1180 | this->bbt_md = &bbt_mirror_descr; | 1175 | this->bbt_md = &bbt_mirror_descr; |
1181 | /* update flash based bbt */ | 1176 | /* update flash based bbt */ |
1182 | this->options |= NAND_USE_FLASH_BBT; | 1177 | this->bbt_options |= NAND_BBT_USE_FLASH; |
1183 | } | 1178 | } |
1184 | 1179 | ||
1185 | init_completion(&host->op_completion); | 1180 | init_completion(&host->op_completion); |
@@ -1231,16 +1226,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1231 | } | 1226 | } |
1232 | 1227 | ||
1233 | /* Register the partitions */ | 1228 | /* Register the partitions */ |
1234 | nr_parts = | 1229 | mtd_device_parse_register(mtd, part_probes, 0, |
1235 | parse_mtd_partitions(mtd, part_probes, &host->parts, 0); | 1230 | pdata->parts, pdata->nr_parts); |
1236 | if (nr_parts > 0) | ||
1237 | mtd_device_register(mtd, host->parts, nr_parts); | ||
1238 | else if (pdata->parts) | ||
1239 | mtd_device_register(mtd, pdata->parts, pdata->nr_parts); | ||
1240 | else { | ||
1241 | pr_info("Registering %s as whole device\n", mtd->name); | ||
1242 | mtd_device_register(mtd, NULL, 0); | ||
1243 | } | ||
1244 | 1231 | ||
1245 | platform_set_drvdata(pdev, host); | 1232 | platform_set_drvdata(pdev, host); |
1246 | 1233 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a46e9bb847bd..3ed9c5e4d34e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * TODO: | 21 | * TODO: |
22 | * Enable cached programming for 2k page size chips | 22 | * Enable cached programming for 2k page size chips |
23 | * Check, if mtd->ecctype should be set to MTD_ECC_HW | 23 | * Check, if mtd->ecctype should be set to MTD_ECC_HW |
24 | * if we have HW ecc support. | 24 | * if we have HW ECC support. |
25 | * The AG-AND chips have nice features for speed improvement, | 25 | * The AG-AND chips have nice features for speed improvement, |
26 | * which are not supported yet. Read / program 4 pages in one go. | 26 | * which are not supported yet. Read / program 4 pages in one go. |
27 | * BBT table is not serialized, has to be fixed | 27 | * BBT table is not serialized, has to be fixed |
@@ -113,21 +113,19 @@ static int check_offs_len(struct mtd_info *mtd, | |||
113 | 113 | ||
114 | /* Start address must align on block boundary */ | 114 | /* Start address must align on block boundary */ |
115 | if (ofs & ((1 << chip->phys_erase_shift) - 1)) { | 115 | if (ofs & ((1 << chip->phys_erase_shift) - 1)) { |
116 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__); | 116 | pr_debug("%s: unaligned address\n", __func__); |
117 | ret = -EINVAL; | 117 | ret = -EINVAL; |
118 | } | 118 | } |
119 | 119 | ||
120 | /* Length must align on block boundary */ | 120 | /* Length must align on block boundary */ |
121 | if (len & ((1 << chip->phys_erase_shift) - 1)) { | 121 | if (len & ((1 << chip->phys_erase_shift) - 1)) { |
122 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n", | 122 | pr_debug("%s: length not block aligned\n", __func__); |
123 | __func__); | ||
124 | ret = -EINVAL; | 123 | ret = -EINVAL; |
125 | } | 124 | } |
126 | 125 | ||
127 | /* Do not allow past end of device */ | 126 | /* Do not allow past end of device */ |
128 | if (ofs + len > mtd->size) { | 127 | if (ofs + len > mtd->size) { |
129 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n", | 128 | pr_debug("%s: past end of device\n", __func__); |
130 | __func__); | ||
131 | ret = -EINVAL; | 129 | ret = -EINVAL; |
132 | } | 130 | } |
133 | 131 | ||
@@ -136,9 +134,9 @@ static int check_offs_len(struct mtd_info *mtd, | |||
136 | 134 | ||
137 | /** | 135 | /** |
138 | * nand_release_device - [GENERIC] release chip | 136 | * nand_release_device - [GENERIC] release chip |
139 | * @mtd: MTD device structure | 137 | * @mtd: MTD device structure |
140 | * | 138 | * |
141 | * Deselect, release chip lock and wake up anyone waiting on the device | 139 | * Deselect, release chip lock and wake up anyone waiting on the device. |
142 | */ | 140 | */ |
143 | static void nand_release_device(struct mtd_info *mtd) | 141 | static void nand_release_device(struct mtd_info *mtd) |
144 | { | 142 | { |
@@ -157,9 +155,9 @@ static void nand_release_device(struct mtd_info *mtd) | |||
157 | 155 | ||
158 | /** | 156 | /** |
159 | * nand_read_byte - [DEFAULT] read one byte from the chip | 157 | * nand_read_byte - [DEFAULT] read one byte from the chip |
160 | * @mtd: MTD device structure | 158 | * @mtd: MTD device structure |
161 | * | 159 | * |
162 | * Default read function for 8bit buswith | 160 | * Default read function for 8bit buswidth |
163 | */ | 161 | */ |
164 | static uint8_t nand_read_byte(struct mtd_info *mtd) | 162 | static uint8_t nand_read_byte(struct mtd_info *mtd) |
165 | { | 163 | { |
@@ -169,10 +167,11 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) | |||
169 | 167 | ||
170 | /** | 168 | /** |
171 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip | 169 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip |
172 | * @mtd: MTD device structure | 170 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
171 | * @mtd: MTD device structure | ||
172 | * | ||
173 | * Default read function for 16bit buswidth with endianness conversion. | ||
173 | * | 174 | * |
174 | * Default read function for 16bit buswith with | ||
175 | * endianess conversion | ||
176 | */ | 175 | */ |
177 | static uint8_t nand_read_byte16(struct mtd_info *mtd) | 176 | static uint8_t nand_read_byte16(struct mtd_info *mtd) |
178 | { | 177 | { |
@@ -182,10 +181,9 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd) | |||
182 | 181 | ||
183 | /** | 182 | /** |
184 | * nand_read_word - [DEFAULT] read one word from the chip | 183 | * nand_read_word - [DEFAULT] read one word from the chip |
185 | * @mtd: MTD device structure | 184 | * @mtd: MTD device structure |
186 | * | 185 | * |
187 | * Default read function for 16bit buswith without | 186 | * Default read function for 16bit buswidth without endianness conversion. |
188 | * endianess conversion | ||
189 | */ | 187 | */ |
190 | static u16 nand_read_word(struct mtd_info *mtd) | 188 | static u16 nand_read_word(struct mtd_info *mtd) |
191 | { | 189 | { |
@@ -195,8 +193,8 @@ static u16 nand_read_word(struct mtd_info *mtd) | |||
195 | 193 | ||
196 | /** | 194 | /** |
197 | * nand_select_chip - [DEFAULT] control CE line | 195 | * nand_select_chip - [DEFAULT] control CE line |
198 | * @mtd: MTD device structure | 196 | * @mtd: MTD device structure |
199 | * @chipnr: chipnumber to select, -1 for deselect | 197 | * @chipnr: chipnumber to select, -1 for deselect |
200 | * | 198 | * |
201 | * Default select function for 1 chip devices. | 199 | * Default select function for 1 chip devices. |
202 | */ | 200 | */ |
@@ -218,11 +216,11 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) | |||
218 | 216 | ||
219 | /** | 217 | /** |
220 | * nand_write_buf - [DEFAULT] write buffer to chip | 218 | * nand_write_buf - [DEFAULT] write buffer to chip |
221 | * @mtd: MTD device structure | 219 | * @mtd: MTD device structure |
222 | * @buf: data buffer | 220 | * @buf: data buffer |
223 | * @len: number of bytes to write | 221 | * @len: number of bytes to write |
224 | * | 222 | * |
225 | * Default write function for 8bit buswith | 223 | * Default write function for 8bit buswidth. |
226 | */ | 224 | */ |
227 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 225 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
228 | { | 226 | { |
@@ -235,11 +233,11 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
235 | 233 | ||
236 | /** | 234 | /** |
237 | * nand_read_buf - [DEFAULT] read chip data into buffer | 235 | * nand_read_buf - [DEFAULT] read chip data into buffer |
238 | * @mtd: MTD device structure | 236 | * @mtd: MTD device structure |
239 | * @buf: buffer to store date | 237 | * @buf: buffer to store date |
240 | * @len: number of bytes to read | 238 | * @len: number of bytes to read |
241 | * | 239 | * |
242 | * Default read function for 8bit buswith | 240 | * Default read function for 8bit buswidth. |
243 | */ | 241 | */ |
244 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 242 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
245 | { | 243 | { |
@@ -252,11 +250,11 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
252 | 250 | ||
253 | /** | 251 | /** |
254 | * nand_verify_buf - [DEFAULT] Verify chip data against buffer | 252 | * nand_verify_buf - [DEFAULT] Verify chip data against buffer |
255 | * @mtd: MTD device structure | 253 | * @mtd: MTD device structure |
256 | * @buf: buffer containing the data to compare | 254 | * @buf: buffer containing the data to compare |
257 | * @len: number of bytes to compare | 255 | * @len: number of bytes to compare |
258 | * | 256 | * |
259 | * Default verify function for 8bit buswith | 257 | * Default verify function for 8bit buswidth. |
260 | */ | 258 | */ |
261 | static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 259 | static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
262 | { | 260 | { |
@@ -271,11 +269,11 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
271 | 269 | ||
272 | /** | 270 | /** |
273 | * nand_write_buf16 - [DEFAULT] write buffer to chip | 271 | * nand_write_buf16 - [DEFAULT] write buffer to chip |
274 | * @mtd: MTD device structure | 272 | * @mtd: MTD device structure |
275 | * @buf: data buffer | 273 | * @buf: data buffer |
276 | * @len: number of bytes to write | 274 | * @len: number of bytes to write |
277 | * | 275 | * |
278 | * Default write function for 16bit buswith | 276 | * Default write function for 16bit buswidth. |
279 | */ | 277 | */ |
280 | static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | 278 | static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) |
281 | { | 279 | { |
@@ -291,11 +289,11 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
291 | 289 | ||
292 | /** | 290 | /** |
293 | * nand_read_buf16 - [DEFAULT] read chip data into buffer | 291 | * nand_read_buf16 - [DEFAULT] read chip data into buffer |
294 | * @mtd: MTD device structure | 292 | * @mtd: MTD device structure |
295 | * @buf: buffer to store date | 293 | * @buf: buffer to store date |
296 | * @len: number of bytes to read | 294 | * @len: number of bytes to read |
297 | * | 295 | * |
298 | * Default read function for 16bit buswith | 296 | * Default read function for 16bit buswidth. |
299 | */ | 297 | */ |
300 | static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) | 298 | static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) |
301 | { | 299 | { |
@@ -310,11 +308,11 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) | |||
310 | 308 | ||
311 | /** | 309 | /** |
312 | * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer | 310 | * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer |
313 | * @mtd: MTD device structure | 311 | * @mtd: MTD device structure |
314 | * @buf: buffer containing the data to compare | 312 | * @buf: buffer containing the data to compare |
315 | * @len: number of bytes to compare | 313 | * @len: number of bytes to compare |
316 | * | 314 | * |
317 | * Default verify function for 16bit buswith | 315 | * Default verify function for 16bit buswidth. |
318 | */ | 316 | */ |
319 | static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | 317 | static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) |
320 | { | 318 | { |
@@ -332,9 +330,9 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
332 | 330 | ||
333 | /** | 331 | /** |
334 | * nand_block_bad - [DEFAULT] Read bad block marker from the chip | 332 | * nand_block_bad - [DEFAULT] Read bad block marker from the chip |
335 | * @mtd: MTD device structure | 333 | * @mtd: MTD device structure |
336 | * @ofs: offset from device start | 334 | * @ofs: offset from device start |
337 | * @getchip: 0, if the chip is already selected | 335 | * @getchip: 0, if the chip is already selected |
338 | * | 336 | * |
339 | * Check, if the block is bad. | 337 | * Check, if the block is bad. |
340 | */ | 338 | */ |
@@ -344,7 +342,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
344 | struct nand_chip *chip = mtd->priv; | 342 | struct nand_chip *chip = mtd->priv; |
345 | u16 bad; | 343 | u16 bad; |
346 | 344 | ||
347 | if (chip->options & NAND_BBT_SCANLASTPAGE) | 345 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) |
348 | ofs += mtd->erasesize - mtd->writesize; | 346 | ofs += mtd->erasesize - mtd->writesize; |
349 | 347 | ||
350 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | 348 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; |
@@ -384,11 +382,11 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
384 | 382 | ||
385 | /** | 383 | /** |
386 | * nand_default_block_markbad - [DEFAULT] mark a block bad | 384 | * nand_default_block_markbad - [DEFAULT] mark a block bad |
387 | * @mtd: MTD device structure | 385 | * @mtd: MTD device structure |
388 | * @ofs: offset from device start | 386 | * @ofs: offset from device start |
389 | * | 387 | * |
390 | * This is the default implementation, which can be overridden by | 388 | * This is the default implementation, which can be overridden by a hardware |
391 | * a hardware specific driver. | 389 | * specific driver. |
392 | */ | 390 | */ |
393 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | 391 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) |
394 | { | 392 | { |
@@ -396,7 +394,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
396 | uint8_t buf[2] = { 0, 0 }; | 394 | uint8_t buf[2] = { 0, 0 }; |
397 | int block, ret, i = 0; | 395 | int block, ret, i = 0; |
398 | 396 | ||
399 | if (chip->options & NAND_BBT_SCANLASTPAGE) | 397 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) |
400 | ofs += mtd->erasesize - mtd->writesize; | 398 | ofs += mtd->erasesize - mtd->writesize; |
401 | 399 | ||
402 | /* Get block number */ | 400 | /* Get block number */ |
@@ -404,33 +402,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
404 | if (chip->bbt) | 402 | if (chip->bbt) |
405 | chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | 403 | chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); |
406 | 404 | ||
407 | /* Do we have a flash based bad block table ? */ | 405 | /* Do we have a flash based bad block table? */ |
408 | if (chip->options & NAND_USE_FLASH_BBT) | 406 | if (chip->bbt_options & NAND_BBT_USE_FLASH) |
409 | ret = nand_update_bbt(mtd, ofs); | 407 | ret = nand_update_bbt(mtd, ofs); |
410 | else { | 408 | else { |
409 | struct mtd_oob_ops ops; | ||
410 | |||
411 | nand_get_device(chip, mtd, FL_WRITING); | 411 | nand_get_device(chip, mtd, FL_WRITING); |
412 | 412 | ||
413 | /* Write to first two pages and to byte 1 and 6 if necessary. | 413 | /* |
414 | * If we write to more than one location, the first error | 414 | * Write to first two pages if necessary. If we write to more |
415 | * encountered quits the procedure. We write two bytes per | 415 | * than one location, the first error encountered quits the |
416 | * location, so we dont have to mess with 16 bit access. | 416 | * procedure. We write two bytes per location, so we dont have |
417 | * to mess with 16 bit access. | ||
417 | */ | 418 | */ |
419 | ops.len = ops.ooblen = 2; | ||
420 | ops.datbuf = NULL; | ||
421 | ops.oobbuf = buf; | ||
422 | ops.ooboffs = chip->badblockpos & ~0x01; | ||
423 | ops.mode = MTD_OPS_PLACE_OOB; | ||
418 | do { | 424 | do { |
419 | chip->ops.len = chip->ops.ooblen = 2; | 425 | ret = nand_do_write_oob(mtd, ofs, &ops); |
420 | chip->ops.datbuf = NULL; | ||
421 | chip->ops.oobbuf = buf; | ||
422 | chip->ops.ooboffs = chip->badblockpos & ~0x01; | ||
423 | |||
424 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | ||
425 | 426 | ||
426 | if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) { | ||
427 | chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS | ||
428 | & ~0x01; | ||
429 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | ||
430 | } | ||
431 | i++; | 427 | i++; |
432 | ofs += mtd->writesize; | 428 | ofs += mtd->writesize; |
433 | } while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) && | 429 | } while (!ret && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && |
434 | i < 2); | 430 | i < 2); |
435 | 431 | ||
436 | nand_release_device(mtd); | 432 | nand_release_device(mtd); |
@@ -443,16 +439,16 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
443 | 439 | ||
444 | /** | 440 | /** |
445 | * nand_check_wp - [GENERIC] check if the chip is write protected | 441 | * nand_check_wp - [GENERIC] check if the chip is write protected |
446 | * @mtd: MTD device structure | 442 | * @mtd: MTD device structure |
447 | * Check, if the device is write protected | ||
448 | * | 443 | * |
449 | * The function expects, that the device is already selected | 444 | * Check, if the device is write protected. The function expects, that the |
445 | * device is already selected. | ||
450 | */ | 446 | */ |
451 | static int nand_check_wp(struct mtd_info *mtd) | 447 | static int nand_check_wp(struct mtd_info *mtd) |
452 | { | 448 | { |
453 | struct nand_chip *chip = mtd->priv; | 449 | struct nand_chip *chip = mtd->priv; |
454 | 450 | ||
455 | /* broken xD cards report WP despite being writable */ | 451 | /* Broken xD cards report WP despite being writable */ |
456 | if (chip->options & NAND_BROKEN_XD) | 452 | if (chip->options & NAND_BROKEN_XD) |
457 | return 0; | 453 | return 0; |
458 | 454 | ||
@@ -463,10 +459,10 @@ static int nand_check_wp(struct mtd_info *mtd) | |||
463 | 459 | ||
464 | /** | 460 | /** |
465 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad | 461 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad |
466 | * @mtd: MTD device structure | 462 | * @mtd: MTD device structure |
467 | * @ofs: offset from device start | 463 | * @ofs: offset from device start |
468 | * @getchip: 0, if the chip is already selected | 464 | * @getchip: 0, if the chip is already selected |
469 | * @allowbbt: 1, if its allowed to access the bbt area | 465 | * @allowbbt: 1, if its allowed to access the bbt area |
470 | * | 466 | * |
471 | * Check, if the block is bad. Either by reading the bad block table or | 467 | * Check, if the block is bad. Either by reading the bad block table or |
472 | * calling of the scan function. | 468 | * calling of the scan function. |
@@ -485,8 +481,8 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, | |||
485 | 481 | ||
486 | /** | 482 | /** |
487 | * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands. | 483 | * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands. |
488 | * @mtd: MTD device structure | 484 | * @mtd: MTD device structure |
489 | * @timeo: Timeout | 485 | * @timeo: Timeout |
490 | * | 486 | * |
491 | * Helper function for nand_wait_ready used when needing to wait in interrupt | 487 | * Helper function for nand_wait_ready used when needing to wait in interrupt |
492 | * context. | 488 | * context. |
@@ -505,10 +501,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) | |||
505 | } | 501 | } |
506 | } | 502 | } |
507 | 503 | ||
508 | /* | 504 | /* Wait for the ready pin, after a command. The timeout is caught later. */ |
509 | * Wait for the ready pin, after a command | ||
510 | * The timeout is catched later. | ||
511 | */ | ||
512 | void nand_wait_ready(struct mtd_info *mtd) | 505 | void nand_wait_ready(struct mtd_info *mtd) |
513 | { | 506 | { |
514 | struct nand_chip *chip = mtd->priv; | 507 | struct nand_chip *chip = mtd->priv; |
@@ -519,7 +512,7 @@ void nand_wait_ready(struct mtd_info *mtd) | |||
519 | return panic_nand_wait_ready(mtd, 400); | 512 | return panic_nand_wait_ready(mtd, 400); |
520 | 513 | ||
521 | led_trigger_event(nand_led_trigger, LED_FULL); | 514 | led_trigger_event(nand_led_trigger, LED_FULL); |
522 | /* wait until command is processed or timeout occures */ | 515 | /* Wait until command is processed or timeout occurs */ |
523 | do { | 516 | do { |
524 | if (chip->dev_ready(mtd)) | 517 | if (chip->dev_ready(mtd)) |
525 | break; | 518 | break; |
@@ -531,13 +524,13 @@ EXPORT_SYMBOL_GPL(nand_wait_ready); | |||
531 | 524 | ||
532 | /** | 525 | /** |
533 | * nand_command - [DEFAULT] Send command to NAND device | 526 | * nand_command - [DEFAULT] Send command to NAND device |
534 | * @mtd: MTD device structure | 527 | * @mtd: MTD device structure |
535 | * @command: the command to be sent | 528 | * @command: the command to be sent |
536 | * @column: the column address for this command, -1 if none | 529 | * @column: the column address for this command, -1 if none |
537 | * @page_addr: the page address for this command, -1 if none | 530 | * @page_addr: the page address for this command, -1 if none |
538 | * | 531 | * |
539 | * Send command to NAND device. This function is used for small page | 532 | * Send command to NAND device. This function is used for small page devices |
540 | * devices (256/512 Bytes per page) | 533 | * (256/512 Bytes per page). |
541 | */ | 534 | */ |
542 | static void nand_command(struct mtd_info *mtd, unsigned int command, | 535 | static void nand_command(struct mtd_info *mtd, unsigned int command, |
543 | int column, int page_addr) | 536 | int column, int page_addr) |
@@ -545,9 +538,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
545 | register struct nand_chip *chip = mtd->priv; | 538 | register struct nand_chip *chip = mtd->priv; |
546 | int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; | 539 | int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; |
547 | 540 | ||
548 | /* | 541 | /* Write out the command to the device */ |
549 | * Write out the command to the device. | ||
550 | */ | ||
551 | if (command == NAND_CMD_SEQIN) { | 542 | if (command == NAND_CMD_SEQIN) { |
552 | int readcmd; | 543 | int readcmd; |
553 | 544 | ||
@@ -567,9 +558,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
567 | } | 558 | } |
568 | chip->cmd_ctrl(mtd, command, ctrl); | 559 | chip->cmd_ctrl(mtd, command, ctrl); |
569 | 560 | ||
570 | /* | 561 | /* Address cycle, when necessary */ |
571 | * Address cycle, when necessary | ||
572 | */ | ||
573 | ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; | 562 | ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; |
574 | /* Serially input address */ | 563 | /* Serially input address */ |
575 | if (column != -1) { | 564 | if (column != -1) { |
@@ -590,8 +579,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
590 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); | 579 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
591 | 580 | ||
592 | /* | 581 | /* |
593 | * program and erase have their own busy handlers | 582 | * Program and erase have their own busy handlers status and sequential |
594 | * status and sequential in needs no delay | 583 | * in needs no delay |
595 | */ | 584 | */ |
596 | switch (command) { | 585 | switch (command) { |
597 | 586 | ||
@@ -625,8 +614,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
625 | return; | 614 | return; |
626 | } | 615 | } |
627 | } | 616 | } |
628 | /* Apply this short delay always to ensure that we do wait tWB in | 617 | /* |
629 | * any case on any machine. */ | 618 | * Apply this short delay always to ensure that we do wait tWB in |
619 | * any case on any machine. | ||
620 | */ | ||
630 | ndelay(100); | 621 | ndelay(100); |
631 | 622 | ||
632 | nand_wait_ready(mtd); | 623 | nand_wait_ready(mtd); |
@@ -634,14 +625,14 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
634 | 625 | ||
635 | /** | 626 | /** |
636 | * nand_command_lp - [DEFAULT] Send command to NAND large page device | 627 | * nand_command_lp - [DEFAULT] Send command to NAND large page device |
637 | * @mtd: MTD device structure | 628 | * @mtd: MTD device structure |
638 | * @command: the command to be sent | 629 | * @command: the command to be sent |
639 | * @column: the column address for this command, -1 if none | 630 | * @column: the column address for this command, -1 if none |
640 | * @page_addr: the page address for this command, -1 if none | 631 | * @page_addr: the page address for this command, -1 if none |
641 | * | 632 | * |
642 | * Send command to NAND device. This is the version for the new large page | 633 | * Send command to NAND device. This is the version for the new large page |
643 | * devices We dont have the separate regions as we have in the small page | 634 | * devices. We don't have the separate regions as we have in the small page |
644 | * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. | 635 | * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. |
645 | */ | 636 | */ |
646 | static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | 637 | static void nand_command_lp(struct mtd_info *mtd, unsigned int command, |
647 | int column, int page_addr) | 638 | int column, int page_addr) |
@@ -683,8 +674,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
683 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); | 674 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
684 | 675 | ||
685 | /* | 676 | /* |
686 | * program and erase have their own busy handlers | 677 | * Program and erase have their own busy handlers status, sequential |
687 | * status, sequential in, and deplete1 need no delay | 678 | * in, and deplete1 need no delay. |
688 | */ | 679 | */ |
689 | switch (command) { | 680 | switch (command) { |
690 | 681 | ||
@@ -698,14 +689,12 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
698 | case NAND_CMD_DEPLETE1: | 689 | case NAND_CMD_DEPLETE1: |
699 | return; | 690 | return; |
700 | 691 | ||
701 | /* | ||
702 | * read error status commands require only a short delay | ||
703 | */ | ||
704 | case NAND_CMD_STATUS_ERROR: | 692 | case NAND_CMD_STATUS_ERROR: |
705 | case NAND_CMD_STATUS_ERROR0: | 693 | case NAND_CMD_STATUS_ERROR0: |
706 | case NAND_CMD_STATUS_ERROR1: | 694 | case NAND_CMD_STATUS_ERROR1: |
707 | case NAND_CMD_STATUS_ERROR2: | 695 | case NAND_CMD_STATUS_ERROR2: |
708 | case NAND_CMD_STATUS_ERROR3: | 696 | case NAND_CMD_STATUS_ERROR3: |
697 | /* Read error status commands require only a short delay */ | ||
709 | udelay(chip->chip_delay); | 698 | udelay(chip->chip_delay); |
710 | return; | 699 | return; |
711 | 700 | ||
@@ -739,7 +728,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
739 | default: | 728 | default: |
740 | /* | 729 | /* |
741 | * If we don't have access to the busy pin, we apply the given | 730 | * If we don't have access to the busy pin, we apply the given |
742 | * command delay | 731 | * command delay. |
743 | */ | 732 | */ |
744 | if (!chip->dev_ready) { | 733 | if (!chip->dev_ready) { |
745 | udelay(chip->chip_delay); | 734 | udelay(chip->chip_delay); |
@@ -747,8 +736,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
747 | } | 736 | } |
748 | } | 737 | } |
749 | 738 | ||
750 | /* Apply this short delay always to ensure that we do wait tWB in | 739 | /* |
751 | * any case on any machine. */ | 740 | * Apply this short delay always to ensure that we do wait tWB in |
741 | * any case on any machine. | ||
742 | */ | ||
752 | ndelay(100); | 743 | ndelay(100); |
753 | 744 | ||
754 | nand_wait_ready(mtd); | 745 | nand_wait_ready(mtd); |
@@ -756,25 +747,25 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
756 | 747 | ||
757 | /** | 748 | /** |
758 | * panic_nand_get_device - [GENERIC] Get chip for selected access | 749 | * panic_nand_get_device - [GENERIC] Get chip for selected access |
759 | * @chip: the nand chip descriptor | 750 | * @chip: the nand chip descriptor |
760 | * @mtd: MTD device structure | 751 | * @mtd: MTD device structure |
761 | * @new_state: the state which is requested | 752 | * @new_state: the state which is requested |
762 | * | 753 | * |
763 | * Used when in panic, no locks are taken. | 754 | * Used when in panic, no locks are taken. |
764 | */ | 755 | */ |
765 | static void panic_nand_get_device(struct nand_chip *chip, | 756 | static void panic_nand_get_device(struct nand_chip *chip, |
766 | struct mtd_info *mtd, int new_state) | 757 | struct mtd_info *mtd, int new_state) |
767 | { | 758 | { |
768 | /* Hardware controller shared among independend devices */ | 759 | /* Hardware controller shared among independent devices */ |
769 | chip->controller->active = chip; | 760 | chip->controller->active = chip; |
770 | chip->state = new_state; | 761 | chip->state = new_state; |
771 | } | 762 | } |
772 | 763 | ||
773 | /** | 764 | /** |
774 | * nand_get_device - [GENERIC] Get chip for selected access | 765 | * nand_get_device - [GENERIC] Get chip for selected access |
775 | * @chip: the nand chip descriptor | 766 | * @chip: the nand chip descriptor |
776 | * @mtd: MTD device structure | 767 | * @mtd: MTD device structure |
777 | * @new_state: the state which is requested | 768 | * @new_state: the state which is requested |
778 | * | 769 | * |
779 | * Get the device and lock it for exclusive access | 770 | * Get the device and lock it for exclusive access |
780 | */ | 771 | */ |
@@ -812,10 +803,10 @@ retry: | |||
812 | } | 803 | } |
813 | 804 | ||
814 | /** | 805 | /** |
815 | * panic_nand_wait - [GENERIC] wait until the command is done | 806 | * panic_nand_wait - [GENERIC] wait until the command is done |
816 | * @mtd: MTD device structure | 807 | * @mtd: MTD device structure |
817 | * @chip: NAND chip structure | 808 | * @chip: NAND chip structure |
818 | * @timeo: Timeout | 809 | * @timeo: timeout |
819 | * | 810 | * |
820 | * Wait for command done. This is a helper function for nand_wait used when | 811 | * Wait for command done. This is a helper function for nand_wait used when |
821 | * we are in interrupt context. May happen when in panic and trying to write | 812 | * we are in interrupt context. May happen when in panic and trying to write |
@@ -838,13 +829,13 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, | |||
838 | } | 829 | } |
839 | 830 | ||
840 | /** | 831 | /** |
841 | * nand_wait - [DEFAULT] wait until the command is done | 832 | * nand_wait - [DEFAULT] wait until the command is done |
842 | * @mtd: MTD device structure | 833 | * @mtd: MTD device structure |
843 | * @chip: NAND chip structure | 834 | * @chip: NAND chip structure |
844 | * | 835 | * |
845 | * Wait for command done. This applies to erase and program only | 836 | * Wait for command done. This applies to erase and program only. Erase can |
846 | * Erase can take up to 400ms and program up to 20ms according to | 837 | * take up to 400ms and program up to 20ms according to general NAND and |
847 | * general NAND and SmartMedia specs | 838 | * SmartMedia specs. |
848 | */ | 839 | */ |
849 | static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | 840 | static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) |
850 | { | 841 | { |
@@ -859,8 +850,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
859 | 850 | ||
860 | led_trigger_event(nand_led_trigger, LED_FULL); | 851 | led_trigger_event(nand_led_trigger, LED_FULL); |
861 | 852 | ||
862 | /* Apply this short delay always to ensure that we do wait tWB in | 853 | /* |
863 | * any case on any machine. */ | 854 | * Apply this short delay always to ensure that we do wait tWB in any |
855 | * case on any machine. | ||
856 | */ | ||
864 | ndelay(100); | 857 | ndelay(100); |
865 | 858 | ||
866 | if ((state == FL_ERASING) && (chip->options & NAND_IS_AND)) | 859 | if ((state == FL_ERASING) && (chip->options & NAND_IS_AND)) |
@@ -890,16 +883,15 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
890 | 883 | ||
891 | /** | 884 | /** |
892 | * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks | 885 | * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks |
893 | * | ||
894 | * @mtd: mtd info | 886 | * @mtd: mtd info |
895 | * @ofs: offset to start unlock from | 887 | * @ofs: offset to start unlock from |
896 | * @len: length to unlock | 888 | * @len: length to unlock |
897 | * @invert: when = 0, unlock the range of blocks within the lower and | 889 | * @invert: when = 0, unlock the range of blocks within the lower and |
898 | * upper boundary address | 890 | * upper boundary address |
899 | * when = 1, unlock the range of blocks outside the boundaries | 891 | * when = 1, unlock the range of blocks outside the boundaries |
900 | * of the lower and upper boundary address | 892 | * of the lower and upper boundary address |
901 | * | 893 | * |
902 | * return - unlock status | 894 | * Returs unlock status. |
903 | */ | 895 | */ |
904 | static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, | 896 | static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, |
905 | uint64_t len, int invert) | 897 | uint64_t len, int invert) |
@@ -919,10 +911,9 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, | |||
919 | 911 | ||
920 | /* Call wait ready function */ | 912 | /* Call wait ready function */ |
921 | status = chip->waitfunc(mtd, chip); | 913 | status = chip->waitfunc(mtd, chip); |
922 | udelay(1000); | ||
923 | /* See if device thinks it succeeded */ | 914 | /* See if device thinks it succeeded */ |
924 | if (status & 0x01) { | 915 | if (status & 0x01) { |
925 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n", | 916 | pr_debug("%s: error status = 0x%08x\n", |
926 | __func__, status); | 917 | __func__, status); |
927 | ret = -EIO; | 918 | ret = -EIO; |
928 | } | 919 | } |
@@ -932,12 +923,11 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, | |||
932 | 923 | ||
933 | /** | 924 | /** |
934 | * nand_unlock - [REPLACEABLE] unlocks specified locked blocks | 925 | * nand_unlock - [REPLACEABLE] unlocks specified locked blocks |
935 | * | ||
936 | * @mtd: mtd info | 926 | * @mtd: mtd info |
937 | * @ofs: offset to start unlock from | 927 | * @ofs: offset to start unlock from |
938 | * @len: length to unlock | 928 | * @len: length to unlock |
939 | * | 929 | * |
940 | * return - unlock status | 930 | * Returns unlock status. |
941 | */ | 931 | */ |
942 | int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 932 | int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
943 | { | 933 | { |
@@ -945,7 +935,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
945 | int chipnr; | 935 | int chipnr; |
946 | struct nand_chip *chip = mtd->priv; | 936 | struct nand_chip *chip = mtd->priv; |
947 | 937 | ||
948 | DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n", | 938 | pr_debug("%s: start = 0x%012llx, len = %llu\n", |
949 | __func__, (unsigned long long)ofs, len); | 939 | __func__, (unsigned long long)ofs, len); |
950 | 940 | ||
951 | if (check_offs_len(mtd, ofs, len)) | 941 | if (check_offs_len(mtd, ofs, len)) |
@@ -964,7 +954,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
964 | 954 | ||
965 | /* Check, if it is write protected */ | 955 | /* Check, if it is write protected */ |
966 | if (nand_check_wp(mtd)) { | 956 | if (nand_check_wp(mtd)) { |
967 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n", | 957 | pr_debug("%s: device is write protected!\n", |
968 | __func__); | 958 | __func__); |
969 | ret = -EIO; | 959 | ret = -EIO; |
970 | goto out; | 960 | goto out; |
@@ -981,18 +971,16 @@ EXPORT_SYMBOL(nand_unlock); | |||
981 | 971 | ||
982 | /** | 972 | /** |
983 | * nand_lock - [REPLACEABLE] locks all blocks present in the device | 973 | * nand_lock - [REPLACEABLE] locks all blocks present in the device |
984 | * | ||
985 | * @mtd: mtd info | 974 | * @mtd: mtd info |
986 | * @ofs: offset to start unlock from | 975 | * @ofs: offset to start unlock from |
987 | * @len: length to unlock | 976 | * @len: length to unlock |
988 | * | 977 | * |
989 | * return - lock status | 978 | * This feature is not supported in many NAND parts. 'Micron' NAND parts do |
979 | * have this feature, but it allows only to lock all blocks, not for specified | ||
980 | * range for block. Implementing 'lock' feature by making use of 'unlock', for | ||
981 | * now. | ||
990 | * | 982 | * |
991 | * This feature is not supported in many NAND parts. 'Micron' NAND parts | 983 | * Returns lock status. |
992 | * do have this feature, but it allows only to lock all blocks, not for | ||
993 | * specified range for block. | ||
994 | * | ||
995 | * Implementing 'lock' feature by making use of 'unlock', for now. | ||
996 | */ | 984 | */ |
997 | int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 985 | int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
998 | { | 986 | { |
@@ -1000,7 +988,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
1000 | int chipnr, status, page; | 988 | int chipnr, status, page; |
1001 | struct nand_chip *chip = mtd->priv; | 989 | struct nand_chip *chip = mtd->priv; |
1002 | 990 | ||
1003 | DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n", | 991 | pr_debug("%s: start = 0x%012llx, len = %llu\n", |
1004 | __func__, (unsigned long long)ofs, len); | 992 | __func__, (unsigned long long)ofs, len); |
1005 | 993 | ||
1006 | if (check_offs_len(mtd, ofs, len)) | 994 | if (check_offs_len(mtd, ofs, len)) |
@@ -1015,7 +1003,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
1015 | 1003 | ||
1016 | /* Check, if it is write protected */ | 1004 | /* Check, if it is write protected */ |
1017 | if (nand_check_wp(mtd)) { | 1005 | if (nand_check_wp(mtd)) { |
1018 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n", | 1006 | pr_debug("%s: device is write protected!\n", |
1019 | __func__); | 1007 | __func__); |
1020 | status = MTD_ERASE_FAILED; | 1008 | status = MTD_ERASE_FAILED; |
1021 | ret = -EIO; | 1009 | ret = -EIO; |
@@ -1028,10 +1016,9 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
1028 | 1016 | ||
1029 | /* Call wait ready function */ | 1017 | /* Call wait ready function */ |
1030 | status = chip->waitfunc(mtd, chip); | 1018 | status = chip->waitfunc(mtd, chip); |
1031 | udelay(1000); | ||
1032 | /* See if device thinks it succeeded */ | 1019 | /* See if device thinks it succeeded */ |
1033 | if (status & 0x01) { | 1020 | if (status & 0x01) { |
1034 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n", | 1021 | pr_debug("%s: error status = 0x%08x\n", |
1035 | __func__, status); | 1022 | __func__, status); |
1036 | ret = -EIO; | 1023 | ret = -EIO; |
1037 | goto out; | 1024 | goto out; |
@@ -1047,13 +1034,13 @@ out: | |||
1047 | EXPORT_SYMBOL(nand_lock); | 1034 | EXPORT_SYMBOL(nand_lock); |
1048 | 1035 | ||
1049 | /** | 1036 | /** |
1050 | * nand_read_page_raw - [Intern] read raw page data without ecc | 1037 | * nand_read_page_raw - [INTERN] read raw page data without ecc |
1051 | * @mtd: mtd info structure | 1038 | * @mtd: mtd info structure |
1052 | * @chip: nand chip info structure | 1039 | * @chip: nand chip info structure |
1053 | * @buf: buffer to store read data | 1040 | * @buf: buffer to store read data |
1054 | * @page: page number to read | 1041 | * @page: page number to read |
1055 | * | 1042 | * |
1056 | * Not for syndrome calculating ecc controllers, which use a special oob layout | 1043 | * Not for syndrome calculating ECC controllers, which use a special oob layout. |
1057 | */ | 1044 | */ |
1058 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1045 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1059 | uint8_t *buf, int page) | 1046 | uint8_t *buf, int page) |
@@ -1064,11 +1051,11 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1064 | } | 1051 | } |
1065 | 1052 | ||
1066 | /** | 1053 | /** |
1067 | * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc | 1054 | * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc |
1068 | * @mtd: mtd info structure | 1055 | * @mtd: mtd info structure |
1069 | * @chip: nand chip info structure | 1056 | * @chip: nand chip info structure |
1070 | * @buf: buffer to store read data | 1057 | * @buf: buffer to store read data |
1071 | * @page: page number to read | 1058 | * @page: page number to read |
1072 | * | 1059 | * |
1073 | * We need a special oob layout and handling even when OOB isn't used. | 1060 | * We need a special oob layout and handling even when OOB isn't used. |
1074 | */ | 1061 | */ |
@@ -1107,11 +1094,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, | |||
1107 | } | 1094 | } |
1108 | 1095 | ||
1109 | /** | 1096 | /** |
1110 | * nand_read_page_swecc - [REPLACABLE] software ecc based page read function | 1097 | * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function |
1111 | * @mtd: mtd info structure | 1098 | * @mtd: mtd info structure |
1112 | * @chip: nand chip info structure | 1099 | * @chip: nand chip info structure |
1113 | * @buf: buffer to store read data | 1100 | * @buf: buffer to store read data |
1114 | * @page: page number to read | 1101 | * @page: page number to read |
1115 | */ | 1102 | */ |
1116 | static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | 1103 | static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, |
1117 | uint8_t *buf, int page) | 1104 | uint8_t *buf, int page) |
@@ -1148,12 +1135,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1148 | } | 1135 | } |
1149 | 1136 | ||
1150 | /** | 1137 | /** |
1151 | * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function | 1138 | * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function |
1152 | * @mtd: mtd info structure | 1139 | * @mtd: mtd info structure |
1153 | * @chip: nand chip info structure | 1140 | * @chip: nand chip info structure |
1154 | * @data_offs: offset of requested data within the page | 1141 | * @data_offs: offset of requested data within the page |
1155 | * @readlen: data length | 1142 | * @readlen: data length |
1156 | * @bufpoi: buffer to store read data | 1143 | * @bufpoi: buffer to store read data |
1157 | */ | 1144 | */ |
1158 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | 1145 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, |
1159 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | 1146 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) |
@@ -1166,12 +1153,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1166 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1153 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1167 | int index = 0; | 1154 | int index = 0; |
1168 | 1155 | ||
1169 | /* Column address wihin the page aligned to ECC size (256bytes). */ | 1156 | /* Column address within the page aligned to ECC size (256bytes) */ |
1170 | start_step = data_offs / chip->ecc.size; | 1157 | start_step = data_offs / chip->ecc.size; |
1171 | end_step = (data_offs + readlen - 1) / chip->ecc.size; | 1158 | end_step = (data_offs + readlen - 1) / chip->ecc.size; |
1172 | num_steps = end_step - start_step + 1; | 1159 | num_steps = end_step - start_step + 1; |
1173 | 1160 | ||
1174 | /* Data size aligned to ECC ecc.size*/ | 1161 | /* Data size aligned to ECC ecc.size */ |
1175 | datafrag_len = num_steps * chip->ecc.size; | 1162 | datafrag_len = num_steps * chip->ecc.size; |
1176 | eccfrag_len = num_steps * chip->ecc.bytes; | 1163 | eccfrag_len = num_steps * chip->ecc.bytes; |
1177 | 1164 | ||
@@ -1183,13 +1170,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1183 | p = bufpoi + data_col_addr; | 1170 | p = bufpoi + data_col_addr; |
1184 | chip->read_buf(mtd, p, datafrag_len); | 1171 | chip->read_buf(mtd, p, datafrag_len); |
1185 | 1172 | ||
1186 | /* Calculate ECC */ | 1173 | /* Calculate ECC */ |
1187 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) | 1174 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) |
1188 | chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]); | 1175 | chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]); |
1189 | 1176 | ||
1190 | /* The performance is faster if to position offsets | 1177 | /* |
1191 | according to ecc.pos. Let make sure here that | 1178 | * The performance is faster if we position offsets according to |
1192 | there are no gaps in ecc positions */ | 1179 | * ecc.pos. Let's make sure that there are no gaps in ECC positions. |
1180 | */ | ||
1193 | for (i = 0; i < eccfrag_len - 1; i++) { | 1181 | for (i = 0; i < eccfrag_len - 1; i++) { |
1194 | if (eccpos[i + start_step * chip->ecc.bytes] + 1 != | 1182 | if (eccpos[i + start_step * chip->ecc.bytes] + 1 != |
1195 | eccpos[i + start_step * chip->ecc.bytes + 1]) { | 1183 | eccpos[i + start_step * chip->ecc.bytes + 1]) { |
@@ -1201,8 +1189,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1201 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); | 1189 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); |
1202 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1190 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
1203 | } else { | 1191 | } else { |
1204 | /* send the command to read the particular ecc bytes */ | 1192 | /* |
1205 | /* take care about buswidth alignment in read_buf */ | 1193 | * Send the command to read the particular ECC bytes take care |
1194 | * about buswidth alignment in read_buf. | ||
1195 | */ | ||
1206 | index = start_step * chip->ecc.bytes; | 1196 | index = start_step * chip->ecc.bytes; |
1207 | 1197 | ||
1208 | aligned_pos = eccpos[index] & ~(busw - 1); | 1198 | aligned_pos = eccpos[index] & ~(busw - 1); |
@@ -1235,13 +1225,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1235 | } | 1225 | } |
1236 | 1226 | ||
1237 | /** | 1227 | /** |
1238 | * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function | 1228 | * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function |
1239 | * @mtd: mtd info structure | 1229 | * @mtd: mtd info structure |
1240 | * @chip: nand chip info structure | 1230 | * @chip: nand chip info structure |
1241 | * @buf: buffer to store read data | 1231 | * @buf: buffer to store read data |
1242 | * @page: page number to read | 1232 | * @page: page number to read |
1243 | * | 1233 | * |
1244 | * Not for syndrome calculating ecc controllers which need a special oob layout | 1234 | * Not for syndrome calculating ECC controllers which need a special oob layout. |
1245 | */ | 1235 | */ |
1246 | static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 1236 | static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
1247 | uint8_t *buf, int page) | 1237 | uint8_t *buf, int page) |
@@ -1280,18 +1270,17 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1280 | } | 1270 | } |
1281 | 1271 | ||
1282 | /** | 1272 | /** |
1283 | * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first | 1273 | * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first |
1284 | * @mtd: mtd info structure | 1274 | * @mtd: mtd info structure |
1285 | * @chip: nand chip info structure | 1275 | * @chip: nand chip info structure |
1286 | * @buf: buffer to store read data | 1276 | * @buf: buffer to store read data |
1287 | * @page: page number to read | 1277 | * @page: page number to read |
1288 | * | 1278 | * |
1289 | * Hardware ECC for large page chips, require OOB to be read first. | 1279 | * Hardware ECC for large page chips, require OOB to be read first. For this |
1290 | * For this ECC mode, the write_page method is re-used from ECC_HW. | 1280 | * ECC mode, the write_page method is re-used from ECC_HW. These methods |
1291 | * These methods read/write ECC from the OOB area, unlike the | 1281 | * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with |
1292 | * ECC_HW_SYNDROME support with multiple ECC steps, follows the | 1282 | * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from |
1293 | * "infix ECC" scheme and reads/writes ECC from the data area, by | 1283 | * the data area, by overwriting the NAND manufacturer bad block markings. |
1294 | * overwriting the NAND manufacturer bad block markings. | ||
1295 | */ | 1284 | */ |
1296 | static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | 1285 | static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, |
1297 | struct nand_chip *chip, uint8_t *buf, int page) | 1286 | struct nand_chip *chip, uint8_t *buf, int page) |
@@ -1329,14 +1318,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | |||
1329 | } | 1318 | } |
1330 | 1319 | ||
1331 | /** | 1320 | /** |
1332 | * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read | 1321 | * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read |
1333 | * @mtd: mtd info structure | 1322 | * @mtd: mtd info structure |
1334 | * @chip: nand chip info structure | 1323 | * @chip: nand chip info structure |
1335 | * @buf: buffer to store read data | 1324 | * @buf: buffer to store read data |
1336 | * @page: page number to read | 1325 | * @page: page number to read |
1337 | * | 1326 | * |
1338 | * The hw generator calculates the error syndrome automatically. Therefor | 1327 | * The hw generator calculates the error syndrome automatically. Therefore we |
1339 | * we need a special oob layout and handling. | 1328 | * need a special oob layout and handling. |
1340 | */ | 1329 | */ |
1341 | static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1330 | static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
1342 | uint8_t *buf, int page) | 1331 | uint8_t *buf, int page) |
@@ -1384,29 +1373,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1384 | } | 1373 | } |
1385 | 1374 | ||
1386 | /** | 1375 | /** |
1387 | * nand_transfer_oob - [Internal] Transfer oob to client buffer | 1376 | * nand_transfer_oob - [INTERN] Transfer oob to client buffer |
1388 | * @chip: nand chip structure | 1377 | * @chip: nand chip structure |
1389 | * @oob: oob destination address | 1378 | * @oob: oob destination address |
1390 | * @ops: oob ops structure | 1379 | * @ops: oob ops structure |
1391 | * @len: size of oob to transfer | 1380 | * @len: size of oob to transfer |
1392 | */ | 1381 | */ |
1393 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | 1382 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, |
1394 | struct mtd_oob_ops *ops, size_t len) | 1383 | struct mtd_oob_ops *ops, size_t len) |
1395 | { | 1384 | { |
1396 | switch (ops->mode) { | 1385 | switch (ops->mode) { |
1397 | 1386 | ||
1398 | case MTD_OOB_PLACE: | 1387 | case MTD_OPS_PLACE_OOB: |
1399 | case MTD_OOB_RAW: | 1388 | case MTD_OPS_RAW: |
1400 | memcpy(oob, chip->oob_poi + ops->ooboffs, len); | 1389 | memcpy(oob, chip->oob_poi + ops->ooboffs, len); |
1401 | return oob + len; | 1390 | return oob + len; |
1402 | 1391 | ||
1403 | case MTD_OOB_AUTO: { | 1392 | case MTD_OPS_AUTO_OOB: { |
1404 | struct nand_oobfree *free = chip->ecc.layout->oobfree; | 1393 | struct nand_oobfree *free = chip->ecc.layout->oobfree; |
1405 | uint32_t boffs = 0, roffs = ops->ooboffs; | 1394 | uint32_t boffs = 0, roffs = ops->ooboffs; |
1406 | size_t bytes = 0; | 1395 | size_t bytes = 0; |
1407 | 1396 | ||
1408 | for (; free->length && len; free++, len -= bytes) { | 1397 | for (; free->length && len; free++, len -= bytes) { |
1409 | /* Read request not from offset 0 ? */ | 1398 | /* Read request not from offset 0? */ |
1410 | if (unlikely(roffs)) { | 1399 | if (unlikely(roffs)) { |
1411 | if (roffs >= free->length) { | 1400 | if (roffs >= free->length) { |
1412 | roffs -= free->length; | 1401 | roffs -= free->length; |
@@ -1432,11 +1421,10 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | |||
1432 | } | 1421 | } |
1433 | 1422 | ||
1434 | /** | 1423 | /** |
1435 | * nand_do_read_ops - [Internal] Read data with ECC | 1424 | * nand_do_read_ops - [INTERN] Read data with ECC |
1436 | * | 1425 | * @mtd: MTD device structure |
1437 | * @mtd: MTD device structure | 1426 | * @from: offset to read from |
1438 | * @from: offset to read from | 1427 | * @ops: oob ops structure |
1439 | * @ops: oob ops structure | ||
1440 | * | 1428 | * |
1441 | * Internal function. Called with chip held. | 1429 | * Internal function. Called with chip held. |
1442 | */ | 1430 | */ |
@@ -1451,7 +1439,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1451 | int ret = 0; | 1439 | int ret = 0; |
1452 | uint32_t readlen = ops->len; | 1440 | uint32_t readlen = ops->len; |
1453 | uint32_t oobreadlen = ops->ooblen; | 1441 | uint32_t oobreadlen = ops->ooblen; |
1454 | uint32_t max_oobsize = ops->mode == MTD_OOB_AUTO ? | 1442 | uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ? |
1455 | mtd->oobavail : mtd->oobsize; | 1443 | mtd->oobavail : mtd->oobsize; |
1456 | 1444 | ||
1457 | uint8_t *bufpoi, *oob, *buf; | 1445 | uint8_t *bufpoi, *oob, *buf; |
@@ -1473,7 +1461,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1473 | bytes = min(mtd->writesize - col, readlen); | 1461 | bytes = min(mtd->writesize - col, readlen); |
1474 | aligned = (bytes == mtd->writesize); | 1462 | aligned = (bytes == mtd->writesize); |
1475 | 1463 | ||
1476 | /* Is the current page in the buffer ? */ | 1464 | /* Is the current page in the buffer? */ |
1477 | if (realpage != chip->pagebuf || oob) { | 1465 | if (realpage != chip->pagebuf || oob) { |
1478 | bufpoi = aligned ? buf : chip->buffers->databuf; | 1466 | bufpoi = aligned ? buf : chip->buffers->databuf; |
1479 | 1467 | ||
@@ -1483,7 +1471,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1483 | } | 1471 | } |
1484 | 1472 | ||
1485 | /* Now read the page into the buffer */ | 1473 | /* Now read the page into the buffer */ |
1486 | if (unlikely(ops->mode == MTD_OOB_RAW)) | 1474 | if (unlikely(ops->mode == MTD_OPS_RAW)) |
1487 | ret = chip->ecc.read_page_raw(mtd, chip, | 1475 | ret = chip->ecc.read_page_raw(mtd, chip, |
1488 | bufpoi, page); | 1476 | bufpoi, page); |
1489 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) | 1477 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) |
@@ -1492,14 +1480,22 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1492 | else | 1480 | else |
1493 | ret = chip->ecc.read_page(mtd, chip, bufpoi, | 1481 | ret = chip->ecc.read_page(mtd, chip, bufpoi, |
1494 | page); | 1482 | page); |
1495 | if (ret < 0) | 1483 | if (ret < 0) { |
1484 | if (!aligned) | ||
1485 | /* Invalidate page cache */ | ||
1486 | chip->pagebuf = -1; | ||
1496 | break; | 1487 | break; |
1488 | } | ||
1497 | 1489 | ||
1498 | /* Transfer not aligned data */ | 1490 | /* Transfer not aligned data */ |
1499 | if (!aligned) { | 1491 | if (!aligned) { |
1500 | if (!NAND_SUBPAGE_READ(chip) && !oob && | 1492 | if (!NAND_SUBPAGE_READ(chip) && !oob && |
1501 | !(mtd->ecc_stats.failed - stats.failed)) | 1493 | !(mtd->ecc_stats.failed - stats.failed) && |
1494 | (ops->mode != MTD_OPS_RAW)) | ||
1502 | chip->pagebuf = realpage; | 1495 | chip->pagebuf = realpage; |
1496 | else | ||
1497 | /* Invalidate page cache */ | ||
1498 | chip->pagebuf = -1; | ||
1503 | memcpy(buf, chip->buffers->databuf + col, bytes); | 1499 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1504 | } | 1500 | } |
1505 | 1501 | ||
@@ -1539,7 +1535,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1539 | if (!readlen) | 1535 | if (!readlen) |
1540 | break; | 1536 | break; |
1541 | 1537 | ||
1542 | /* For subsequent reads align to page boundary. */ | 1538 | /* For subsequent reads align to page boundary */ |
1543 | col = 0; | 1539 | col = 0; |
1544 | /* Increment page address */ | 1540 | /* Increment page address */ |
1545 | realpage++; | 1541 | realpage++; |
@@ -1552,8 +1548,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1552 | chip->select_chip(mtd, chipnr); | 1548 | chip->select_chip(mtd, chipnr); |
1553 | } | 1549 | } |
1554 | 1550 | ||
1555 | /* Check, if the chip supports auto page increment | 1551 | /* |
1556 | * or if we have hit a block boundary. | 1552 | * Check, if the chip supports auto page increment or if we |
1553 | * have hit a block boundary. | ||
1557 | */ | 1554 | */ |
1558 | if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) | 1555 | if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) |
1559 | sndcmd = 1; | 1556 | sndcmd = 1; |
@@ -1574,18 +1571,19 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1574 | 1571 | ||
1575 | /** | 1572 | /** |
1576 | * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc | 1573 | * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc |
1577 | * @mtd: MTD device structure | 1574 | * @mtd: MTD device structure |
1578 | * @from: offset to read from | 1575 | * @from: offset to read from |
1579 | * @len: number of bytes to read | 1576 | * @len: number of bytes to read |
1580 | * @retlen: pointer to variable to store the number of read bytes | 1577 | * @retlen: pointer to variable to store the number of read bytes |
1581 | * @buf: the databuffer to put data | 1578 | * @buf: the databuffer to put data |
1582 | * | 1579 | * |
1583 | * Get hold of the chip and call nand_do_read | 1580 | * Get hold of the chip and call nand_do_read. |
1584 | */ | 1581 | */ |
1585 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | 1582 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, |
1586 | size_t *retlen, uint8_t *buf) | 1583 | size_t *retlen, uint8_t *buf) |
1587 | { | 1584 | { |
1588 | struct nand_chip *chip = mtd->priv; | 1585 | struct nand_chip *chip = mtd->priv; |
1586 | struct mtd_oob_ops ops; | ||
1589 | int ret; | 1587 | int ret; |
1590 | 1588 | ||
1591 | /* Do not allow reads past end of device */ | 1589 | /* Do not allow reads past end of device */ |
@@ -1596,13 +1594,14 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1596 | 1594 | ||
1597 | nand_get_device(chip, mtd, FL_READING); | 1595 | nand_get_device(chip, mtd, FL_READING); |
1598 | 1596 | ||
1599 | chip->ops.len = len; | 1597 | ops.len = len; |
1600 | chip->ops.datbuf = buf; | 1598 | ops.datbuf = buf; |
1601 | chip->ops.oobbuf = NULL; | 1599 | ops.oobbuf = NULL; |
1600 | ops.mode = 0; | ||
1602 | 1601 | ||
1603 | ret = nand_do_read_ops(mtd, from, &chip->ops); | 1602 | ret = nand_do_read_ops(mtd, from, &ops); |
1604 | 1603 | ||
1605 | *retlen = chip->ops.retlen; | 1604 | *retlen = ops.retlen; |
1606 | 1605 | ||
1607 | nand_release_device(mtd); | 1606 | nand_release_device(mtd); |
1608 | 1607 | ||
@@ -1610,11 +1609,11 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1610 | } | 1609 | } |
1611 | 1610 | ||
1612 | /** | 1611 | /** |
1613 | * nand_read_oob_std - [REPLACABLE] the most common OOB data read function | 1612 | * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function |
1614 | * @mtd: mtd info structure | 1613 | * @mtd: mtd info structure |
1615 | * @chip: nand chip info structure | 1614 | * @chip: nand chip info structure |
1616 | * @page: page number to read | 1615 | * @page: page number to read |
1617 | * @sndcmd: flag whether to issue read command or not | 1616 | * @sndcmd: flag whether to issue read command or not |
1618 | */ | 1617 | */ |
1619 | static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 1618 | static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, |
1620 | int page, int sndcmd) | 1619 | int page, int sndcmd) |
@@ -1628,12 +1627,12 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
1628 | } | 1627 | } |
1629 | 1628 | ||
1630 | /** | 1629 | /** |
1631 | * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC | 1630 | * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC |
1632 | * with syndromes | 1631 | * with syndromes |
1633 | * @mtd: mtd info structure | 1632 | * @mtd: mtd info structure |
1634 | * @chip: nand chip info structure | 1633 | * @chip: nand chip info structure |
1635 | * @page: page number to read | 1634 | * @page: page number to read |
1636 | * @sndcmd: flag whether to issue read command or not | 1635 | * @sndcmd: flag whether to issue read command or not |
1637 | */ | 1636 | */ |
1638 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1637 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
1639 | int page, int sndcmd) | 1638 | int page, int sndcmd) |
@@ -1667,10 +1666,10 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1667 | } | 1666 | } |
1668 | 1667 | ||
1669 | /** | 1668 | /** |
1670 | * nand_write_oob_std - [REPLACABLE] the most common OOB data write function | 1669 | * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function |
1671 | * @mtd: mtd info structure | 1670 | * @mtd: mtd info structure |
1672 | * @chip: nand chip info structure | 1671 | * @chip: nand chip info structure |
1673 | * @page: page number to write | 1672 | * @page: page number to write |
1674 | */ | 1673 | */ |
1675 | static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 1674 | static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, |
1676 | int page) | 1675 | int page) |
@@ -1690,11 +1689,11 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
1690 | } | 1689 | } |
1691 | 1690 | ||
1692 | /** | 1691 | /** |
1693 | * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC | 1692 | * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC |
1694 | * with syndrome - only for large page flash ! | 1693 | * with syndrome - only for large page flash |
1695 | * @mtd: mtd info structure | 1694 | * @mtd: mtd info structure |
1696 | * @chip: nand chip info structure | 1695 | * @chip: nand chip info structure |
1697 | * @page: page number to write | 1696 | * @page: page number to write |
1698 | */ | 1697 | */ |
1699 | static int nand_write_oob_syndrome(struct mtd_info *mtd, | 1698 | static int nand_write_oob_syndrome(struct mtd_info *mtd, |
1700 | struct nand_chip *chip, int page) | 1699 | struct nand_chip *chip, int page) |
@@ -1749,34 +1748,37 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, | |||
1749 | } | 1748 | } |
1750 | 1749 | ||
1751 | /** | 1750 | /** |
1752 | * nand_do_read_oob - [Intern] NAND read out-of-band | 1751 | * nand_do_read_oob - [INTERN] NAND read out-of-band |
1753 | * @mtd: MTD device structure | 1752 | * @mtd: MTD device structure |
1754 | * @from: offset to read from | 1753 | * @from: offset to read from |
1755 | * @ops: oob operations description structure | 1754 | * @ops: oob operations description structure |
1756 | * | 1755 | * |
1757 | * NAND read out-of-band data from the spare area | 1756 | * NAND read out-of-band data from the spare area. |
1758 | */ | 1757 | */ |
1759 | static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | 1758 | static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, |
1760 | struct mtd_oob_ops *ops) | 1759 | struct mtd_oob_ops *ops) |
1761 | { | 1760 | { |
1762 | int page, realpage, chipnr, sndcmd = 1; | 1761 | int page, realpage, chipnr, sndcmd = 1; |
1763 | struct nand_chip *chip = mtd->priv; | 1762 | struct nand_chip *chip = mtd->priv; |
1763 | struct mtd_ecc_stats stats; | ||
1764 | int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; | 1764 | int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; |
1765 | int readlen = ops->ooblen; | 1765 | int readlen = ops->ooblen; |
1766 | int len; | 1766 | int len; |
1767 | uint8_t *buf = ops->oobbuf; | 1767 | uint8_t *buf = ops->oobbuf; |
1768 | 1768 | ||
1769 | DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n", | 1769 | pr_debug("%s: from = 0x%08Lx, len = %i\n", |
1770 | __func__, (unsigned long long)from, readlen); | 1770 | __func__, (unsigned long long)from, readlen); |
1771 | 1771 | ||
1772 | if (ops->mode == MTD_OOB_AUTO) | 1772 | stats = mtd->ecc_stats; |
1773 | |||
1774 | if (ops->mode == MTD_OPS_AUTO_OOB) | ||
1773 | len = chip->ecc.layout->oobavail; | 1775 | len = chip->ecc.layout->oobavail; |
1774 | else | 1776 | else |
1775 | len = mtd->oobsize; | 1777 | len = mtd->oobsize; |
1776 | 1778 | ||
1777 | if (unlikely(ops->ooboffs >= len)) { | 1779 | if (unlikely(ops->ooboffs >= len)) { |
1778 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read " | 1780 | pr_debug("%s: attempt to start read outside oob\n", |
1779 | "outside oob\n", __func__); | 1781 | __func__); |
1780 | return -EINVAL; | 1782 | return -EINVAL; |
1781 | } | 1783 | } |
1782 | 1784 | ||
@@ -1784,8 +1786,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1784 | if (unlikely(from >= mtd->size || | 1786 | if (unlikely(from >= mtd->size || |
1785 | ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) - | 1787 | ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) - |
1786 | (from >> chip->page_shift)) * len)) { | 1788 | (from >> chip->page_shift)) * len)) { |
1787 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end " | 1789 | pr_debug("%s: attempt to read beyond end of device\n", |
1788 | "of device\n", __func__); | 1790 | __func__); |
1789 | return -EINVAL; | 1791 | return -EINVAL; |
1790 | } | 1792 | } |
1791 | 1793 | ||
@@ -1797,7 +1799,10 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1797 | page = realpage & chip->pagemask; | 1799 | page = realpage & chip->pagemask; |
1798 | 1800 | ||
1799 | while (1) { | 1801 | while (1) { |
1800 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); | 1802 | if (ops->mode == MTD_OPS_RAW) |
1803 | sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd); | ||
1804 | else | ||
1805 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); | ||
1801 | 1806 | ||
1802 | len = min(len, readlen); | 1807 | len = min(len, readlen); |
1803 | buf = nand_transfer_oob(chip, buf, ops, len); | 1808 | buf = nand_transfer_oob(chip, buf, ops, len); |
@@ -1830,24 +1835,29 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1830 | chip->select_chip(mtd, chipnr); | 1835 | chip->select_chip(mtd, chipnr); |
1831 | } | 1836 | } |
1832 | 1837 | ||
1833 | /* Check, if the chip supports auto page increment | 1838 | /* |
1834 | * or if we have hit a block boundary. | 1839 | * Check, if the chip supports auto page increment or if we |
1840 | * have hit a block boundary. | ||
1835 | */ | 1841 | */ |
1836 | if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) | 1842 | if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) |
1837 | sndcmd = 1; | 1843 | sndcmd = 1; |
1838 | } | 1844 | } |
1839 | 1845 | ||
1840 | ops->oobretlen = ops->ooblen; | 1846 | ops->oobretlen = ops->ooblen; |
1841 | return 0; | 1847 | |
1848 | if (mtd->ecc_stats.failed - stats.failed) | ||
1849 | return -EBADMSG; | ||
1850 | |||
1851 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | ||
1842 | } | 1852 | } |
1843 | 1853 | ||
1844 | /** | 1854 | /** |
1845 | * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band | 1855 | * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band |
1846 | * @mtd: MTD device structure | 1856 | * @mtd: MTD device structure |
1847 | * @from: offset to read from | 1857 | * @from: offset to read from |
1848 | * @ops: oob operation description structure | 1858 | * @ops: oob operation description structure |
1849 | * | 1859 | * |
1850 | * NAND read data and/or out-of-band data | 1860 | * NAND read data and/or out-of-band data. |
1851 | */ | 1861 | */ |
1852 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, | 1862 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, |
1853 | struct mtd_oob_ops *ops) | 1863 | struct mtd_oob_ops *ops) |
@@ -1859,17 +1869,17 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1859 | 1869 | ||
1860 | /* Do not allow reads past end of device */ | 1870 | /* Do not allow reads past end of device */ |
1861 | if (ops->datbuf && (from + ops->len) > mtd->size) { | 1871 | if (ops->datbuf && (from + ops->len) > mtd->size) { |
1862 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read " | 1872 | pr_debug("%s: attempt to read beyond end of device\n", |
1863 | "beyond end of device\n", __func__); | 1873 | __func__); |
1864 | return -EINVAL; | 1874 | return -EINVAL; |
1865 | } | 1875 | } |
1866 | 1876 | ||
1867 | nand_get_device(chip, mtd, FL_READING); | 1877 | nand_get_device(chip, mtd, FL_READING); |
1868 | 1878 | ||
1869 | switch (ops->mode) { | 1879 | switch (ops->mode) { |
1870 | case MTD_OOB_PLACE: | 1880 | case MTD_OPS_PLACE_OOB: |
1871 | case MTD_OOB_AUTO: | 1881 | case MTD_OPS_AUTO_OOB: |
1872 | case MTD_OOB_RAW: | 1882 | case MTD_OPS_RAW: |
1873 | break; | 1883 | break; |
1874 | 1884 | ||
1875 | default: | 1885 | default: |
@@ -1888,12 +1898,12 @@ out: | |||
1888 | 1898 | ||
1889 | 1899 | ||
1890 | /** | 1900 | /** |
1891 | * nand_write_page_raw - [Intern] raw page write function | 1901 | * nand_write_page_raw - [INTERN] raw page write function |
1892 | * @mtd: mtd info structure | 1902 | * @mtd: mtd info structure |
1893 | * @chip: nand chip info structure | 1903 | * @chip: nand chip info structure |
1894 | * @buf: data buffer | 1904 | * @buf: data buffer |
1895 | * | 1905 | * |
1896 | * Not for syndrome calculating ecc controllers, which use a special oob layout | 1906 | * Not for syndrome calculating ECC controllers, which use a special oob layout. |
1897 | */ | 1907 | */ |
1898 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1908 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1899 | const uint8_t *buf) | 1909 | const uint8_t *buf) |
@@ -1903,10 +1913,10 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1903 | } | 1913 | } |
1904 | 1914 | ||
1905 | /** | 1915 | /** |
1906 | * nand_write_page_raw_syndrome - [Intern] raw page write function | 1916 | * nand_write_page_raw_syndrome - [INTERN] raw page write function |
1907 | * @mtd: mtd info structure | 1917 | * @mtd: mtd info structure |
1908 | * @chip: nand chip info structure | 1918 | * @chip: nand chip info structure |
1909 | * @buf: data buffer | 1919 | * @buf: data buffer |
1910 | * | 1920 | * |
1911 | * We need a special oob layout and handling even when ECC isn't checked. | 1921 | * We need a special oob layout and handling even when ECC isn't checked. |
1912 | */ | 1922 | */ |
@@ -1942,10 +1952,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, | |||
1942 | chip->write_buf(mtd, oob, size); | 1952 | chip->write_buf(mtd, oob, size); |
1943 | } | 1953 | } |
1944 | /** | 1954 | /** |
1945 | * nand_write_page_swecc - [REPLACABLE] software ecc based page write function | 1955 | * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function |
1946 | * @mtd: mtd info structure | 1956 | * @mtd: mtd info structure |
1947 | * @chip: nand chip info structure | 1957 | * @chip: nand chip info structure |
1948 | * @buf: data buffer | 1958 | * @buf: data buffer |
1949 | */ | 1959 | */ |
1950 | static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | 1960 | static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, |
1951 | const uint8_t *buf) | 1961 | const uint8_t *buf) |
@@ -1957,7 +1967,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1957 | const uint8_t *p = buf; | 1967 | const uint8_t *p = buf; |
1958 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1968 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
1959 | 1969 | ||
1960 | /* Software ecc calculation */ | 1970 | /* Software ECC calculation */ |
1961 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | 1971 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) |
1962 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 1972 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
1963 | 1973 | ||
@@ -1968,10 +1978,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1968 | } | 1978 | } |
1969 | 1979 | ||
1970 | /** | 1980 | /** |
1971 | * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function | 1981 | * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function |
1972 | * @mtd: mtd info structure | 1982 | * @mtd: mtd info structure |
1973 | * @chip: nand chip info structure | 1983 | * @chip: nand chip info structure |
1974 | * @buf: data buffer | 1984 | * @buf: data buffer |
1975 | */ | 1985 | */ |
1976 | static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 1986 | static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
1977 | const uint8_t *buf) | 1987 | const uint8_t *buf) |
@@ -1996,13 +2006,13 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1996 | } | 2006 | } |
1997 | 2007 | ||
1998 | /** | 2008 | /** |
1999 | * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write | 2009 | * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write |
2000 | * @mtd: mtd info structure | 2010 | * @mtd: mtd info structure |
2001 | * @chip: nand chip info structure | 2011 | * @chip: nand chip info structure |
2002 | * @buf: data buffer | 2012 | * @buf: data buffer |
2003 | * | 2013 | * |
2004 | * The hw generator calculates the error syndrome automatically. Therefor | 2014 | * The hw generator calculates the error syndrome automatically. Therefore we |
2005 | * we need a special oob layout and handling. | 2015 | * need a special oob layout and handling. |
2006 | */ | 2016 | */ |
2007 | static void nand_write_page_syndrome(struct mtd_info *mtd, | 2017 | static void nand_write_page_syndrome(struct mtd_info *mtd, |
2008 | struct nand_chip *chip, const uint8_t *buf) | 2018 | struct nand_chip *chip, const uint8_t *buf) |
@@ -2041,12 +2051,12 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, | |||
2041 | 2051 | ||
2042 | /** | 2052 | /** |
2043 | * nand_write_page - [REPLACEABLE] write one page | 2053 | * nand_write_page - [REPLACEABLE] write one page |
2044 | * @mtd: MTD device structure | 2054 | * @mtd: MTD device structure |
2045 | * @chip: NAND chip descriptor | 2055 | * @chip: NAND chip descriptor |
2046 | * @buf: the data to write | 2056 | * @buf: the data to write |
2047 | * @page: page number to write | 2057 | * @page: page number to write |
2048 | * @cached: cached programming | 2058 | * @cached: cached programming |
2049 | * @raw: use _raw version of write_page | 2059 | * @raw: use _raw version of write_page |
2050 | */ | 2060 | */ |
2051 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 2061 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
2052 | const uint8_t *buf, int page, int cached, int raw) | 2062 | const uint8_t *buf, int page, int cached, int raw) |
@@ -2061,8 +2071,8 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2061 | chip->ecc.write_page(mtd, chip, buf); | 2071 | chip->ecc.write_page(mtd, chip, buf); |
2062 | 2072 | ||
2063 | /* | 2073 | /* |
2064 | * Cached progamming disabled for now, Not sure if its worth the | 2074 | * Cached progamming disabled for now. Not sure if it's worth the |
2065 | * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) | 2075 | * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s). |
2066 | */ | 2076 | */ |
2067 | cached = 0; | 2077 | cached = 0; |
2068 | 2078 | ||
@@ -2072,7 +2082,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2072 | status = chip->waitfunc(mtd, chip); | 2082 | status = chip->waitfunc(mtd, chip); |
2073 | /* | 2083 | /* |
2074 | * See if operation failed and additional status checks are | 2084 | * See if operation failed and additional status checks are |
2075 | * available | 2085 | * available. |
2076 | */ | 2086 | */ |
2077 | if ((status & NAND_STATUS_FAIL) && (chip->errstat)) | 2087 | if ((status & NAND_STATUS_FAIL) && (chip->errstat)) |
2078 | status = chip->errstat(mtd, chip, FL_WRITING, status, | 2088 | status = chip->errstat(mtd, chip, FL_WRITING, status, |
@@ -2096,29 +2106,37 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2096 | } | 2106 | } |
2097 | 2107 | ||
2098 | /** | 2108 | /** |
2099 | * nand_fill_oob - [Internal] Transfer client buffer to oob | 2109 | * nand_fill_oob - [INTERN] Transfer client buffer to oob |
2100 | * @chip: nand chip structure | 2110 | * @mtd: MTD device structure |
2101 | * @oob: oob data buffer | 2111 | * @oob: oob data buffer |
2102 | * @len: oob data write length | 2112 | * @len: oob data write length |
2103 | * @ops: oob ops structure | 2113 | * @ops: oob ops structure |
2104 | */ | 2114 | */ |
2105 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | 2115 | static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, |
2106 | struct mtd_oob_ops *ops) | 2116 | struct mtd_oob_ops *ops) |
2107 | { | 2117 | { |
2118 | struct nand_chip *chip = mtd->priv; | ||
2119 | |||
2120 | /* | ||
2121 | * Initialise to all 0xFF, to avoid the possibility of left over OOB | ||
2122 | * data from a previous OOB read. | ||
2123 | */ | ||
2124 | memset(chip->oob_poi, 0xff, mtd->oobsize); | ||
2125 | |||
2108 | switch (ops->mode) { | 2126 | switch (ops->mode) { |
2109 | 2127 | ||
2110 | case MTD_OOB_PLACE: | 2128 | case MTD_OPS_PLACE_OOB: |
2111 | case MTD_OOB_RAW: | 2129 | case MTD_OPS_RAW: |
2112 | memcpy(chip->oob_poi + ops->ooboffs, oob, len); | 2130 | memcpy(chip->oob_poi + ops->ooboffs, oob, len); |
2113 | return oob + len; | 2131 | return oob + len; |
2114 | 2132 | ||
2115 | case MTD_OOB_AUTO: { | 2133 | case MTD_OPS_AUTO_OOB: { |
2116 | struct nand_oobfree *free = chip->ecc.layout->oobfree; | 2134 | struct nand_oobfree *free = chip->ecc.layout->oobfree; |
2117 | uint32_t boffs = 0, woffs = ops->ooboffs; | 2135 | uint32_t boffs = 0, woffs = ops->ooboffs; |
2118 | size_t bytes = 0; | 2136 | size_t bytes = 0; |
2119 | 2137 | ||
2120 | for (; free->length && len; free++, len -= bytes) { | 2138 | for (; free->length && len; free++, len -= bytes) { |
2121 | /* Write request not from offset 0 ? */ | 2139 | /* Write request not from offset 0? */ |
2122 | if (unlikely(woffs)) { | 2140 | if (unlikely(woffs)) { |
2123 | if (woffs >= free->length) { | 2141 | if (woffs >= free->length) { |
2124 | woffs -= free->length; | 2142 | woffs -= free->length; |
@@ -2146,12 +2164,12 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | |||
2146 | #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0) | 2164 | #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0) |
2147 | 2165 | ||
2148 | /** | 2166 | /** |
2149 | * nand_do_write_ops - [Internal] NAND write with ECC | 2167 | * nand_do_write_ops - [INTERN] NAND write with ECC |
2150 | * @mtd: MTD device structure | 2168 | * @mtd: MTD device structure |
2151 | * @to: offset to write to | 2169 | * @to: offset to write to |
2152 | * @ops: oob operations description structure | 2170 | * @ops: oob operations description structure |
2153 | * | 2171 | * |
2154 | * NAND write with ECC | 2172 | * NAND write with ECC. |
2155 | */ | 2173 | */ |
2156 | static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | 2174 | static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, |
2157 | struct mtd_oob_ops *ops) | 2175 | struct mtd_oob_ops *ops) |
@@ -2161,7 +2179,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2161 | uint32_t writelen = ops->len; | 2179 | uint32_t writelen = ops->len; |
2162 | 2180 | ||
2163 | uint32_t oobwritelen = ops->ooblen; | 2181 | uint32_t oobwritelen = ops->ooblen; |
2164 | uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ? | 2182 | uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ? |
2165 | mtd->oobavail : mtd->oobsize; | 2183 | mtd->oobavail : mtd->oobsize; |
2166 | 2184 | ||
2167 | uint8_t *oob = ops->oobbuf; | 2185 | uint8_t *oob = ops->oobbuf; |
@@ -2172,10 +2190,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2172 | if (!writelen) | 2190 | if (!writelen) |
2173 | return 0; | 2191 | return 0; |
2174 | 2192 | ||
2175 | /* reject writes, which are not page aligned */ | 2193 | /* Reject writes, which are not page aligned */ |
2176 | if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { | 2194 | if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { |
2177 | printk(KERN_NOTICE "%s: Attempt to write not " | 2195 | pr_notice("%s: attempt to write non page aligned data\n", |
2178 | "page aligned data\n", __func__); | 2196 | __func__); |
2179 | return -EINVAL; | 2197 | return -EINVAL; |
2180 | } | 2198 | } |
2181 | 2199 | ||
@@ -2201,10 +2219,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2201 | (chip->pagebuf << chip->page_shift) < (to + ops->len)) | 2219 | (chip->pagebuf << chip->page_shift) < (to + ops->len)) |
2202 | chip->pagebuf = -1; | 2220 | chip->pagebuf = -1; |
2203 | 2221 | ||
2204 | /* If we're not given explicit OOB data, let it be 0xFF */ | ||
2205 | if (likely(!oob)) | ||
2206 | memset(chip->oob_poi, 0xff, mtd->oobsize); | ||
2207 | |||
2208 | /* Don't allow multipage oob writes with offset */ | 2222 | /* Don't allow multipage oob writes with offset */ |
2209 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) | 2223 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) |
2210 | return -EINVAL; | 2224 | return -EINVAL; |
@@ -2214,7 +2228,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2214 | int cached = writelen > bytes && page != blockmask; | 2228 | int cached = writelen > bytes && page != blockmask; |
2215 | uint8_t *wbuf = buf; | 2229 | uint8_t *wbuf = buf; |
2216 | 2230 | ||
2217 | /* Partial page write ? */ | 2231 | /* Partial page write? */ |
2218 | if (unlikely(column || writelen < (mtd->writesize - 1))) { | 2232 | if (unlikely(column || writelen < (mtd->writesize - 1))) { |
2219 | cached = 0; | 2233 | cached = 0; |
2220 | bytes = min_t(int, bytes - column, (int) writelen); | 2234 | bytes = min_t(int, bytes - column, (int) writelen); |
@@ -2226,12 +2240,15 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2226 | 2240 | ||
2227 | if (unlikely(oob)) { | 2241 | if (unlikely(oob)) { |
2228 | size_t len = min(oobwritelen, oobmaxlen); | 2242 | size_t len = min(oobwritelen, oobmaxlen); |
2229 | oob = nand_fill_oob(chip, oob, len, ops); | 2243 | oob = nand_fill_oob(mtd, oob, len, ops); |
2230 | oobwritelen -= len; | 2244 | oobwritelen -= len; |
2245 | } else { | ||
2246 | /* We still need to erase leftover OOB data */ | ||
2247 | memset(chip->oob_poi, 0xff, mtd->oobsize); | ||
2231 | } | 2248 | } |
2232 | 2249 | ||
2233 | ret = chip->write_page(mtd, chip, wbuf, page, cached, | 2250 | ret = chip->write_page(mtd, chip, wbuf, page, cached, |
2234 | (ops->mode == MTD_OOB_RAW)); | 2251 | (ops->mode == MTD_OPS_RAW)); |
2235 | if (ret) | 2252 | if (ret) |
2236 | break; | 2253 | break; |
2237 | 2254 | ||
@@ -2260,11 +2277,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2260 | 2277 | ||
2261 | /** | 2278 | /** |
2262 | * panic_nand_write - [MTD Interface] NAND write with ECC | 2279 | * panic_nand_write - [MTD Interface] NAND write with ECC |
2263 | * @mtd: MTD device structure | 2280 | * @mtd: MTD device structure |
2264 | * @to: offset to write to | 2281 | * @to: offset to write to |
2265 | * @len: number of bytes to write | 2282 | * @len: number of bytes to write |
2266 | * @retlen: pointer to variable to store the number of written bytes | 2283 | * @retlen: pointer to variable to store the number of written bytes |
2267 | * @buf: the data to write | 2284 | * @buf: the data to write |
2268 | * | 2285 | * |
2269 | * NAND write with ECC. Used when performing writes in interrupt context, this | 2286 | * NAND write with ECC. Used when performing writes in interrupt context, this |
2270 | * may for example be called by mtdoops when writing an oops while in panic. | 2287 | * may for example be called by mtdoops when writing an oops while in panic. |
@@ -2273,6 +2290,7 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
2273 | size_t *retlen, const uint8_t *buf) | 2290 | size_t *retlen, const uint8_t *buf) |
2274 | { | 2291 | { |
2275 | struct nand_chip *chip = mtd->priv; | 2292 | struct nand_chip *chip = mtd->priv; |
2293 | struct mtd_oob_ops ops; | ||
2276 | int ret; | 2294 | int ret; |
2277 | 2295 | ||
2278 | /* Do not allow reads past end of device */ | 2296 | /* Do not allow reads past end of device */ |
@@ -2281,36 +2299,38 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
2281 | if (!len) | 2299 | if (!len) |
2282 | return 0; | 2300 | return 0; |
2283 | 2301 | ||
2284 | /* Wait for the device to get ready. */ | 2302 | /* Wait for the device to get ready */ |
2285 | panic_nand_wait(mtd, chip, 400); | 2303 | panic_nand_wait(mtd, chip, 400); |
2286 | 2304 | ||
2287 | /* Grab the device. */ | 2305 | /* Grab the device */ |
2288 | panic_nand_get_device(chip, mtd, FL_WRITING); | 2306 | panic_nand_get_device(chip, mtd, FL_WRITING); |
2289 | 2307 | ||
2290 | chip->ops.len = len; | 2308 | ops.len = len; |
2291 | chip->ops.datbuf = (uint8_t *)buf; | 2309 | ops.datbuf = (uint8_t *)buf; |
2292 | chip->ops.oobbuf = NULL; | 2310 | ops.oobbuf = NULL; |
2311 | ops.mode = 0; | ||
2293 | 2312 | ||
2294 | ret = nand_do_write_ops(mtd, to, &chip->ops); | 2313 | ret = nand_do_write_ops(mtd, to, &ops); |
2295 | 2314 | ||
2296 | *retlen = chip->ops.retlen; | 2315 | *retlen = ops.retlen; |
2297 | return ret; | 2316 | return ret; |
2298 | } | 2317 | } |
2299 | 2318 | ||
2300 | /** | 2319 | /** |
2301 | * nand_write - [MTD Interface] NAND write with ECC | 2320 | * nand_write - [MTD Interface] NAND write with ECC |
2302 | * @mtd: MTD device structure | 2321 | * @mtd: MTD device structure |
2303 | * @to: offset to write to | 2322 | * @to: offset to write to |
2304 | * @len: number of bytes to write | 2323 | * @len: number of bytes to write |
2305 | * @retlen: pointer to variable to store the number of written bytes | 2324 | * @retlen: pointer to variable to store the number of written bytes |
2306 | * @buf: the data to write | 2325 | * @buf: the data to write |
2307 | * | 2326 | * |
2308 | * NAND write with ECC | 2327 | * NAND write with ECC. |
2309 | */ | 2328 | */ |
2310 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | 2329 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, |
2311 | size_t *retlen, const uint8_t *buf) | 2330 | size_t *retlen, const uint8_t *buf) |
2312 | { | 2331 | { |
2313 | struct nand_chip *chip = mtd->priv; | 2332 | struct nand_chip *chip = mtd->priv; |
2333 | struct mtd_oob_ops ops; | ||
2314 | int ret; | 2334 | int ret; |
2315 | 2335 | ||
2316 | /* Do not allow reads past end of device */ | 2336 | /* Do not allow reads past end of device */ |
@@ -2321,13 +2341,14 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
2321 | 2341 | ||
2322 | nand_get_device(chip, mtd, FL_WRITING); | 2342 | nand_get_device(chip, mtd, FL_WRITING); |
2323 | 2343 | ||
2324 | chip->ops.len = len; | 2344 | ops.len = len; |
2325 | chip->ops.datbuf = (uint8_t *)buf; | 2345 | ops.datbuf = (uint8_t *)buf; |
2326 | chip->ops.oobbuf = NULL; | 2346 | ops.oobbuf = NULL; |
2347 | ops.mode = 0; | ||
2327 | 2348 | ||
2328 | ret = nand_do_write_ops(mtd, to, &chip->ops); | 2349 | ret = nand_do_write_ops(mtd, to, &ops); |
2329 | 2350 | ||
2330 | *retlen = chip->ops.retlen; | 2351 | *retlen = ops.retlen; |
2331 | 2352 | ||
2332 | nand_release_device(mtd); | 2353 | nand_release_device(mtd); |
2333 | 2354 | ||
@@ -2336,11 +2357,11 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
2336 | 2357 | ||
2337 | /** | 2358 | /** |
2338 | * nand_do_write_oob - [MTD Interface] NAND write out-of-band | 2359 | * nand_do_write_oob - [MTD Interface] NAND write out-of-band |
2339 | * @mtd: MTD device structure | 2360 | * @mtd: MTD device structure |
2340 | * @to: offset to write to | 2361 | * @to: offset to write to |
2341 | * @ops: oob operation description structure | 2362 | * @ops: oob operation description structure |
2342 | * | 2363 | * |
2343 | * NAND write out-of-band | 2364 | * NAND write out-of-band. |
2344 | */ | 2365 | */ |
2345 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | 2366 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, |
2346 | struct mtd_oob_ops *ops) | 2367 | struct mtd_oob_ops *ops) |
@@ -2348,24 +2369,24 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2348 | int chipnr, page, status, len; | 2369 | int chipnr, page, status, len; |
2349 | struct nand_chip *chip = mtd->priv; | 2370 | struct nand_chip *chip = mtd->priv; |
2350 | 2371 | ||
2351 | DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n", | 2372 | pr_debug("%s: to = 0x%08x, len = %i\n", |
2352 | __func__, (unsigned int)to, (int)ops->ooblen); | 2373 | __func__, (unsigned int)to, (int)ops->ooblen); |
2353 | 2374 | ||
2354 | if (ops->mode == MTD_OOB_AUTO) | 2375 | if (ops->mode == MTD_OPS_AUTO_OOB) |
2355 | len = chip->ecc.layout->oobavail; | 2376 | len = chip->ecc.layout->oobavail; |
2356 | else | 2377 | else |
2357 | len = mtd->oobsize; | 2378 | len = mtd->oobsize; |
2358 | 2379 | ||
2359 | /* Do not allow write past end of page */ | 2380 | /* Do not allow write past end of page */ |
2360 | if ((ops->ooboffs + ops->ooblen) > len) { | 2381 | if ((ops->ooboffs + ops->ooblen) > len) { |
2361 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write " | 2382 | pr_debug("%s: attempt to write past end of page\n", |
2362 | "past end of page\n", __func__); | 2383 | __func__); |
2363 | return -EINVAL; | 2384 | return -EINVAL; |
2364 | } | 2385 | } |
2365 | 2386 | ||
2366 | if (unlikely(ops->ooboffs >= len)) { | 2387 | if (unlikely(ops->ooboffs >= len)) { |
2367 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start " | 2388 | pr_debug("%s: attempt to start write outside oob\n", |
2368 | "write outside oob\n", __func__); | 2389 | __func__); |
2369 | return -EINVAL; | 2390 | return -EINVAL; |
2370 | } | 2391 | } |
2371 | 2392 | ||
@@ -2374,8 +2395,8 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2374 | ops->ooboffs + ops->ooblen > | 2395 | ops->ooboffs + ops->ooblen > |
2375 | ((mtd->size >> chip->page_shift) - | 2396 | ((mtd->size >> chip->page_shift) - |
2376 | (to >> chip->page_shift)) * len)) { | 2397 | (to >> chip->page_shift)) * len)) { |
2377 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond " | 2398 | pr_debug("%s: attempt to write beyond end of device\n", |
2378 | "end of device\n", __func__); | 2399 | __func__); |
2379 | return -EINVAL; | 2400 | return -EINVAL; |
2380 | } | 2401 | } |
2381 | 2402 | ||
@@ -2401,10 +2422,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2401 | if (page == chip->pagebuf) | 2422 | if (page == chip->pagebuf) |
2402 | chip->pagebuf = -1; | 2423 | chip->pagebuf = -1; |
2403 | 2424 | ||
2404 | memset(chip->oob_poi, 0xff, mtd->oobsize); | 2425 | nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops); |
2405 | nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops); | 2426 | |
2406 | status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); | 2427 | if (ops->mode == MTD_OPS_RAW) |
2407 | memset(chip->oob_poi, 0xff, mtd->oobsize); | 2428 | status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask); |
2429 | else | ||
2430 | status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); | ||
2408 | 2431 | ||
2409 | if (status) | 2432 | if (status) |
2410 | return status; | 2433 | return status; |
@@ -2416,9 +2439,9 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2416 | 2439 | ||
2417 | /** | 2440 | /** |
2418 | * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band | 2441 | * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band |
2419 | * @mtd: MTD device structure | 2442 | * @mtd: MTD device structure |
2420 | * @to: offset to write to | 2443 | * @to: offset to write to |
2421 | * @ops: oob operation description structure | 2444 | * @ops: oob operation description structure |
2422 | */ | 2445 | */ |
2423 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, | 2446 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, |
2424 | struct mtd_oob_ops *ops) | 2447 | struct mtd_oob_ops *ops) |
@@ -2430,17 +2453,17 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2430 | 2453 | ||
2431 | /* Do not allow writes past end of device */ | 2454 | /* Do not allow writes past end of device */ |
2432 | if (ops->datbuf && (to + ops->len) > mtd->size) { | 2455 | if (ops->datbuf && (to + ops->len) > mtd->size) { |
2433 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond " | 2456 | pr_debug("%s: attempt to write beyond end of device\n", |
2434 | "end of device\n", __func__); | 2457 | __func__); |
2435 | return -EINVAL; | 2458 | return -EINVAL; |
2436 | } | 2459 | } |
2437 | 2460 | ||
2438 | nand_get_device(chip, mtd, FL_WRITING); | 2461 | nand_get_device(chip, mtd, FL_WRITING); |
2439 | 2462 | ||
2440 | switch (ops->mode) { | 2463 | switch (ops->mode) { |
2441 | case MTD_OOB_PLACE: | 2464 | case MTD_OPS_PLACE_OOB: |
2442 | case MTD_OOB_AUTO: | 2465 | case MTD_OPS_AUTO_OOB: |
2443 | case MTD_OOB_RAW: | 2466 | case MTD_OPS_RAW: |
2444 | break; | 2467 | break; |
2445 | 2468 | ||
2446 | default: | 2469 | default: |
@@ -2458,11 +2481,11 @@ out: | |||
2458 | } | 2481 | } |
2459 | 2482 | ||
2460 | /** | 2483 | /** |
2461 | * single_erease_cmd - [GENERIC] NAND standard block erase command function | 2484 | * single_erase_cmd - [GENERIC] NAND standard block erase command function |
2462 | * @mtd: MTD device structure | 2485 | * @mtd: MTD device structure |
2463 | * @page: the page address of the block which will be erased | 2486 | * @page: the page address of the block which will be erased |
2464 | * | 2487 | * |
2465 | * Standard erase command for NAND chips | 2488 | * Standard erase command for NAND chips. |
2466 | */ | 2489 | */ |
2467 | static void single_erase_cmd(struct mtd_info *mtd, int page) | 2490 | static void single_erase_cmd(struct mtd_info *mtd, int page) |
2468 | { | 2491 | { |
@@ -2473,12 +2496,11 @@ static void single_erase_cmd(struct mtd_info *mtd, int page) | |||
2473 | } | 2496 | } |
2474 | 2497 | ||
2475 | /** | 2498 | /** |
2476 | * multi_erease_cmd - [GENERIC] AND specific block erase command function | 2499 | * multi_erase_cmd - [GENERIC] AND specific block erase command function |
2477 | * @mtd: MTD device structure | 2500 | * @mtd: MTD device structure |
2478 | * @page: the page address of the block which will be erased | 2501 | * @page: the page address of the block which will be erased |
2479 | * | 2502 | * |
2480 | * AND multi block erase command function | 2503 | * AND multi block erase command function. Erase 4 consecutive blocks. |
2481 | * Erase 4 consecutive blocks | ||
2482 | */ | 2504 | */ |
2483 | static void multi_erase_cmd(struct mtd_info *mtd, int page) | 2505 | static void multi_erase_cmd(struct mtd_info *mtd, int page) |
2484 | { | 2506 | { |
@@ -2493,10 +2515,10 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page) | |||
2493 | 2515 | ||
2494 | /** | 2516 | /** |
2495 | * nand_erase - [MTD Interface] erase block(s) | 2517 | * nand_erase - [MTD Interface] erase block(s) |
2496 | * @mtd: MTD device structure | 2518 | * @mtd: MTD device structure |
2497 | * @instr: erase instruction | 2519 | * @instr: erase instruction |
2498 | * | 2520 | * |
2499 | * Erase one ore more blocks | 2521 | * Erase one ore more blocks. |
2500 | */ | 2522 | */ |
2501 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) | 2523 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) |
2502 | { | 2524 | { |
@@ -2505,12 +2527,12 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
2505 | 2527 | ||
2506 | #define BBT_PAGE_MASK 0xffffff3f | 2528 | #define BBT_PAGE_MASK 0xffffff3f |
2507 | /** | 2529 | /** |
2508 | * nand_erase_nand - [Internal] erase block(s) | 2530 | * nand_erase_nand - [INTERN] erase block(s) |
2509 | * @mtd: MTD device structure | 2531 | * @mtd: MTD device structure |
2510 | * @instr: erase instruction | 2532 | * @instr: erase instruction |
2511 | * @allowbbt: allow erasing the bbt area | 2533 | * @allowbbt: allow erasing the bbt area |
2512 | * | 2534 | * |
2513 | * Erase one ore more blocks | 2535 | * Erase one ore more blocks. |
2514 | */ | 2536 | */ |
2515 | int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | 2537 | int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, |
2516 | int allowbbt) | 2538 | int allowbbt) |
@@ -2521,9 +2543,9 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2521 | unsigned int bbt_masked_page = 0xffffffff; | 2543 | unsigned int bbt_masked_page = 0xffffffff; |
2522 | loff_t len; | 2544 | loff_t len; |
2523 | 2545 | ||
2524 | DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n", | 2546 | pr_debug("%s: start = 0x%012llx, len = %llu\n", |
2525 | __func__, (unsigned long long)instr->addr, | 2547 | __func__, (unsigned long long)instr->addr, |
2526 | (unsigned long long)instr->len); | 2548 | (unsigned long long)instr->len); |
2527 | 2549 | ||
2528 | if (check_offs_len(mtd, instr->addr, instr->len)) | 2550 | if (check_offs_len(mtd, instr->addr, instr->len)) |
2529 | return -EINVAL; | 2551 | return -EINVAL; |
@@ -2545,8 +2567,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2545 | 2567 | ||
2546 | /* Check, if it is write protected */ | 2568 | /* Check, if it is write protected */ |
2547 | if (nand_check_wp(mtd)) { | 2569 | if (nand_check_wp(mtd)) { |
2548 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n", | 2570 | pr_debug("%s: device is write protected!\n", |
2549 | __func__); | 2571 | __func__); |
2550 | instr->state = MTD_ERASE_FAILED; | 2572 | instr->state = MTD_ERASE_FAILED; |
2551 | goto erase_exit; | 2573 | goto erase_exit; |
2552 | } | 2574 | } |
@@ -2555,7 +2577,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2555 | * If BBT requires refresh, set the BBT page mask to see if the BBT | 2577 | * If BBT requires refresh, set the BBT page mask to see if the BBT |
2556 | * should be rewritten. Otherwise the mask is set to 0xffffffff which | 2578 | * should be rewritten. Otherwise the mask is set to 0xffffffff which |
2557 | * can not be matched. This is also done when the bbt is actually | 2579 | * can not be matched. This is also done when the bbt is actually |
2558 | * erased to avoid recusrsive updates | 2580 | * erased to avoid recursive updates. |
2559 | */ | 2581 | */ |
2560 | if (chip->options & BBT_AUTO_REFRESH && !allowbbt) | 2582 | if (chip->options & BBT_AUTO_REFRESH && !allowbbt) |
2561 | bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK; | 2583 | bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK; |
@@ -2566,20 +2588,18 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2566 | instr->state = MTD_ERASING; | 2588 | instr->state = MTD_ERASING; |
2567 | 2589 | ||
2568 | while (len) { | 2590 | while (len) { |
2569 | /* | 2591 | /* Heck if we have a bad block, we do not erase bad blocks! */ |
2570 | * heck if we have a bad block, we do not erase bad blocks ! | ||
2571 | */ | ||
2572 | if (nand_block_checkbad(mtd, ((loff_t) page) << | 2592 | if (nand_block_checkbad(mtd, ((loff_t) page) << |
2573 | chip->page_shift, 0, allowbbt)) { | 2593 | chip->page_shift, 0, allowbbt)) { |
2574 | printk(KERN_WARNING "%s: attempt to erase a bad block " | 2594 | pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", |
2575 | "at page 0x%08x\n", __func__, page); | 2595 | __func__, page); |
2576 | instr->state = MTD_ERASE_FAILED; | 2596 | instr->state = MTD_ERASE_FAILED; |
2577 | goto erase_exit; | 2597 | goto erase_exit; |
2578 | } | 2598 | } |
2579 | 2599 | ||
2580 | /* | 2600 | /* |
2581 | * Invalidate the page cache, if we erase the block which | 2601 | * Invalidate the page cache, if we erase the block which |
2582 | * contains the current cached page | 2602 | * contains the current cached page. |
2583 | */ | 2603 | */ |
2584 | if (page <= chip->pagebuf && chip->pagebuf < | 2604 | if (page <= chip->pagebuf && chip->pagebuf < |
2585 | (page + pages_per_block)) | 2605 | (page + pages_per_block)) |
@@ -2599,8 +2619,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2599 | 2619 | ||
2600 | /* See if block erase succeeded */ | 2620 | /* See if block erase succeeded */ |
2601 | if (status & NAND_STATUS_FAIL) { | 2621 | if (status & NAND_STATUS_FAIL) { |
2602 | DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, " | 2622 | pr_debug("%s: failed erase, page 0x%08x\n", |
2603 | "page 0x%08x\n", __func__, page); | 2623 | __func__, page); |
2604 | instr->state = MTD_ERASE_FAILED; | 2624 | instr->state = MTD_ERASE_FAILED; |
2605 | instr->fail_addr = | 2625 | instr->fail_addr = |
2606 | ((loff_t)page << chip->page_shift); | 2626 | ((loff_t)page << chip->page_shift); |
@@ -2609,7 +2629,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2609 | 2629 | ||
2610 | /* | 2630 | /* |
2611 | * If BBT requires refresh, set the BBT rewrite flag to the | 2631 | * If BBT requires refresh, set the BBT rewrite flag to the |
2612 | * page being erased | 2632 | * page being erased. |
2613 | */ | 2633 | */ |
2614 | if (bbt_masked_page != 0xffffffff && | 2634 | if (bbt_masked_page != 0xffffffff && |
2615 | (page & BBT_PAGE_MASK) == bbt_masked_page) | 2635 | (page & BBT_PAGE_MASK) == bbt_masked_page) |
@@ -2628,7 +2648,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2628 | 2648 | ||
2629 | /* | 2649 | /* |
2630 | * If BBT requires refresh and BBT-PERCHIP, set the BBT | 2650 | * If BBT requires refresh and BBT-PERCHIP, set the BBT |
2631 | * page mask to see if this BBT should be rewritten | 2651 | * page mask to see if this BBT should be rewritten. |
2632 | */ | 2652 | */ |
2633 | if (bbt_masked_page != 0xffffffff && | 2653 | if (bbt_masked_page != 0xffffffff && |
2634 | (chip->bbt_td->options & NAND_BBT_PERCHIP)) | 2654 | (chip->bbt_td->options & NAND_BBT_PERCHIP)) |
@@ -2651,7 +2671,7 @@ erase_exit: | |||
2651 | 2671 | ||
2652 | /* | 2672 | /* |
2653 | * If BBT requires refresh and erase was successful, rewrite any | 2673 | * If BBT requires refresh and erase was successful, rewrite any |
2654 | * selected bad block tables | 2674 | * selected bad block tables. |
2655 | */ | 2675 | */ |
2656 | if (bbt_masked_page == 0xffffffff || ret) | 2676 | if (bbt_masked_page == 0xffffffff || ret) |
2657 | return ret; | 2677 | return ret; |
@@ -2659,10 +2679,10 @@ erase_exit: | |||
2659 | for (chipnr = 0; chipnr < chip->numchips; chipnr++) { | 2679 | for (chipnr = 0; chipnr < chip->numchips; chipnr++) { |
2660 | if (!rewrite_bbt[chipnr]) | 2680 | if (!rewrite_bbt[chipnr]) |
2661 | continue; | 2681 | continue; |
2662 | /* update the BBT for chip */ | 2682 | /* Update the BBT for chip */ |
2663 | DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt " | 2683 | pr_debug("%s: nand_update_bbt (%d:0x%0llx 0x%0x)\n", |
2664 | "(%d:0x%0llx 0x%0x)\n", __func__, chipnr, | 2684 | __func__, chipnr, rewrite_bbt[chipnr], |
2665 | rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]); | 2685 | chip->bbt_td->pages[chipnr]); |
2666 | nand_update_bbt(mtd, rewrite_bbt[chipnr]); | 2686 | nand_update_bbt(mtd, rewrite_bbt[chipnr]); |
2667 | } | 2687 | } |
2668 | 2688 | ||
@@ -2672,15 +2692,15 @@ erase_exit: | |||
2672 | 2692 | ||
2673 | /** | 2693 | /** |
2674 | * nand_sync - [MTD Interface] sync | 2694 | * nand_sync - [MTD Interface] sync |
2675 | * @mtd: MTD device structure | 2695 | * @mtd: MTD device structure |
2676 | * | 2696 | * |
2677 | * Sync is actually a wait for chip ready function | 2697 | * Sync is actually a wait for chip ready function. |
2678 | */ | 2698 | */ |
2679 | static void nand_sync(struct mtd_info *mtd) | 2699 | static void nand_sync(struct mtd_info *mtd) |
2680 | { | 2700 | { |
2681 | struct nand_chip *chip = mtd->priv; | 2701 | struct nand_chip *chip = mtd->priv; |
2682 | 2702 | ||
2683 | DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__); | 2703 | pr_debug("%s: called\n", __func__); |
2684 | 2704 | ||
2685 | /* Grab the lock and see if the device is available */ | 2705 | /* Grab the lock and see if the device is available */ |
2686 | nand_get_device(chip, mtd, FL_SYNCING); | 2706 | nand_get_device(chip, mtd, FL_SYNCING); |
@@ -2690,8 +2710,8 @@ static void nand_sync(struct mtd_info *mtd) | |||
2690 | 2710 | ||
2691 | /** | 2711 | /** |
2692 | * nand_block_isbad - [MTD Interface] Check if block at offset is bad | 2712 | * nand_block_isbad - [MTD Interface] Check if block at offset is bad |
2693 | * @mtd: MTD device structure | 2713 | * @mtd: MTD device structure |
2694 | * @offs: offset relative to mtd start | 2714 | * @offs: offset relative to mtd start |
2695 | */ | 2715 | */ |
2696 | static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) | 2716 | static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) |
2697 | { | 2717 | { |
@@ -2704,8 +2724,8 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) | |||
2704 | 2724 | ||
2705 | /** | 2725 | /** |
2706 | * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad | 2726 | * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad |
2707 | * @mtd: MTD device structure | 2727 | * @mtd: MTD device structure |
2708 | * @ofs: offset relative to mtd start | 2728 | * @ofs: offset relative to mtd start |
2709 | */ | 2729 | */ |
2710 | static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | 2730 | static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) |
2711 | { | 2731 | { |
@@ -2714,7 +2734,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
2714 | 2734 | ||
2715 | ret = nand_block_isbad(mtd, ofs); | 2735 | ret = nand_block_isbad(mtd, ofs); |
2716 | if (ret) { | 2736 | if (ret) { |
2717 | /* If it was bad already, return success and do nothing. */ | 2737 | /* If it was bad already, return success and do nothing */ |
2718 | if (ret > 0) | 2738 | if (ret > 0) |
2719 | return 0; | 2739 | return 0; |
2720 | return ret; | 2740 | return ret; |
@@ -2725,7 +2745,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
2725 | 2745 | ||
2726 | /** | 2746 | /** |
2727 | * nand_suspend - [MTD Interface] Suspend the NAND flash | 2747 | * nand_suspend - [MTD Interface] Suspend the NAND flash |
2728 | * @mtd: MTD device structure | 2748 | * @mtd: MTD device structure |
2729 | */ | 2749 | */ |
2730 | static int nand_suspend(struct mtd_info *mtd) | 2750 | static int nand_suspend(struct mtd_info *mtd) |
2731 | { | 2751 | { |
@@ -2736,7 +2756,7 @@ static int nand_suspend(struct mtd_info *mtd) | |||
2736 | 2756 | ||
2737 | /** | 2757 | /** |
2738 | * nand_resume - [MTD Interface] Resume the NAND flash | 2758 | * nand_resume - [MTD Interface] Resume the NAND flash |
2739 | * @mtd: MTD device structure | 2759 | * @mtd: MTD device structure |
2740 | */ | 2760 | */ |
2741 | static void nand_resume(struct mtd_info *mtd) | 2761 | static void nand_resume(struct mtd_info *mtd) |
2742 | { | 2762 | { |
@@ -2745,13 +2765,11 @@ static void nand_resume(struct mtd_info *mtd) | |||
2745 | if (chip->state == FL_PM_SUSPENDED) | 2765 | if (chip->state == FL_PM_SUSPENDED) |
2746 | nand_release_device(mtd); | 2766 | nand_release_device(mtd); |
2747 | else | 2767 | else |
2748 | printk(KERN_ERR "%s called for a chip which is not " | 2768 | pr_err("%s called for a chip which is not in suspended state\n", |
2749 | "in suspended state\n", __func__); | 2769 | __func__); |
2750 | } | 2770 | } |
2751 | 2771 | ||
2752 | /* | 2772 | /* Set default functions */ |
2753 | * Set default functions | ||
2754 | */ | ||
2755 | static void nand_set_defaults(struct nand_chip *chip, int busw) | 2773 | static void nand_set_defaults(struct nand_chip *chip, int busw) |
2756 | { | 2774 | { |
2757 | /* check for proper chip_delay setup, set 20us if not */ | 2775 | /* check for proper chip_delay setup, set 20us if not */ |
@@ -2793,23 +2811,21 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | |||
2793 | 2811 | ||
2794 | } | 2812 | } |
2795 | 2813 | ||
2796 | /* | 2814 | /* Sanitize ONFI strings so we can safely print them */ |
2797 | * sanitize ONFI strings so we can safely print them | ||
2798 | */ | ||
2799 | static void sanitize_string(uint8_t *s, size_t len) | 2815 | static void sanitize_string(uint8_t *s, size_t len) |
2800 | { | 2816 | { |
2801 | ssize_t i; | 2817 | ssize_t i; |
2802 | 2818 | ||
2803 | /* null terminate */ | 2819 | /* Null terminate */ |
2804 | s[len - 1] = 0; | 2820 | s[len - 1] = 0; |
2805 | 2821 | ||
2806 | /* remove non printable chars */ | 2822 | /* Remove non printable chars */ |
2807 | for (i = 0; i < len - 1; i++) { | 2823 | for (i = 0; i < len - 1; i++) { |
2808 | if (s[i] < ' ' || s[i] > 127) | 2824 | if (s[i] < ' ' || s[i] > 127) |
2809 | s[i] = '?'; | 2825 | s[i] = '?'; |
2810 | } | 2826 | } |
2811 | 2827 | ||
2812 | /* remove trailing spaces */ | 2828 | /* Remove trailing spaces */ |
2813 | strim(s); | 2829 | strim(s); |
2814 | } | 2830 | } |
2815 | 2831 | ||
@@ -2826,28 +2842,28 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) | |||
2826 | } | 2842 | } |
2827 | 2843 | ||
2828 | /* | 2844 | /* |
2829 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise | 2845 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. |
2830 | */ | 2846 | */ |
2831 | static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | 2847 | static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, |
2832 | int busw) | 2848 | int *busw) |
2833 | { | 2849 | { |
2834 | struct nand_onfi_params *p = &chip->onfi_params; | 2850 | struct nand_onfi_params *p = &chip->onfi_params; |
2835 | int i; | 2851 | int i; |
2836 | int val; | 2852 | int val; |
2837 | 2853 | ||
2838 | /* try ONFI for unknow chip or LP */ | 2854 | /* Try ONFI for unknown chip or LP */ |
2839 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); | 2855 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); |
2840 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || | 2856 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || |
2841 | chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') | 2857 | chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') |
2842 | return 0; | 2858 | return 0; |
2843 | 2859 | ||
2844 | printk(KERN_INFO "ONFI flash detected\n"); | 2860 | pr_info("ONFI flash detected\n"); |
2845 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | 2861 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); |
2846 | for (i = 0; i < 3; i++) { | 2862 | for (i = 0; i < 3; i++) { |
2847 | chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); | 2863 | chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); |
2848 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == | 2864 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == |
2849 | le16_to_cpu(p->crc)) { | 2865 | le16_to_cpu(p->crc)) { |
2850 | printk(KERN_INFO "ONFI param page %d valid\n", i); | 2866 | pr_info("ONFI param page %d valid\n", i); |
2851 | break; | 2867 | break; |
2852 | } | 2868 | } |
2853 | } | 2869 | } |
@@ -2855,7 +2871,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2855 | if (i == 3) | 2871 | if (i == 3) |
2856 | return 0; | 2872 | return 0; |
2857 | 2873 | ||
2858 | /* check version */ | 2874 | /* Check version */ |
2859 | val = le16_to_cpu(p->revision); | 2875 | val = le16_to_cpu(p->revision); |
2860 | if (val & (1 << 5)) | 2876 | if (val & (1 << 5)) |
2861 | chip->onfi_version = 23; | 2877 | chip->onfi_version = 23; |
@@ -2871,8 +2887,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2871 | chip->onfi_version = 0; | 2887 | chip->onfi_version = 0; |
2872 | 2888 | ||
2873 | if (!chip->onfi_version) { | 2889 | if (!chip->onfi_version) { |
2874 | printk(KERN_INFO "%s: unsupported ONFI version: %d\n", | 2890 | pr_info("%s: unsupported ONFI version: %d\n", __func__, val); |
2875 | __func__, val); | ||
2876 | return 0; | 2891 | return 0; |
2877 | } | 2892 | } |
2878 | 2893 | ||
@@ -2884,9 +2899,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2884 | mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; | 2899 | mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; |
2885 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | 2900 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); |
2886 | chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize; | 2901 | chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize; |
2887 | busw = 0; | 2902 | *busw = 0; |
2888 | if (le16_to_cpu(p->features) & 1) | 2903 | if (le16_to_cpu(p->features) & 1) |
2889 | busw = NAND_BUSWIDTH_16; | 2904 | *busw = NAND_BUSWIDTH_16; |
2890 | 2905 | ||
2891 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | 2906 | chip->options &= ~NAND_CHIPOPTIONS_MSK; |
2892 | chip->options |= (NAND_NO_READRDY | | 2907 | chip->options |= (NAND_NO_READRDY | |
@@ -2896,7 +2911,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2896 | } | 2911 | } |
2897 | 2912 | ||
2898 | /* | 2913 | /* |
2899 | * Get the flash and manufacturer id and lookup if the type is supported | 2914 | * Get the flash and manufacturer id and lookup if the type is supported. |
2900 | */ | 2915 | */ |
2901 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | 2916 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, |
2902 | struct nand_chip *chip, | 2917 | struct nand_chip *chip, |
@@ -2913,7 +2928,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2913 | 2928 | ||
2914 | /* | 2929 | /* |
2915 | * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) | 2930 | * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) |
2916 | * after power-up | 2931 | * after power-up. |
2917 | */ | 2932 | */ |
2918 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | 2933 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); |
2919 | 2934 | ||
@@ -2924,7 +2939,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2924 | *maf_id = chip->read_byte(mtd); | 2939 | *maf_id = chip->read_byte(mtd); |
2925 | *dev_id = chip->read_byte(mtd); | 2940 | *dev_id = chip->read_byte(mtd); |
2926 | 2941 | ||
2927 | /* Try again to make sure, as some systems the bus-hold or other | 2942 | /* |
2943 | * Try again to make sure, as some systems the bus-hold or other | ||
2928 | * interface concerns can cause random data which looks like a | 2944 | * interface concerns can cause random data which looks like a |
2929 | * possibly credible NAND flash to appear. If the two results do | 2945 | * possibly credible NAND flash to appear. If the two results do |
2930 | * not match, ignore the device completely. | 2946 | * not match, ignore the device completely. |
@@ -2936,9 +2952,9 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2936 | id_data[i] = chip->read_byte(mtd); | 2952 | id_data[i] = chip->read_byte(mtd); |
2937 | 2953 | ||
2938 | if (id_data[0] != *maf_id || id_data[1] != *dev_id) { | 2954 | if (id_data[0] != *maf_id || id_data[1] != *dev_id) { |
2939 | printk(KERN_INFO "%s: second ID read did not match " | 2955 | pr_info("%s: second ID read did not match " |
2940 | "%02x,%02x against %02x,%02x\n", __func__, | 2956 | "%02x,%02x against %02x,%02x\n", __func__, |
2941 | *maf_id, *dev_id, id_data[0], id_data[1]); | 2957 | *maf_id, *dev_id, id_data[0], id_data[1]); |
2942 | return ERR_PTR(-ENODEV); | 2958 | return ERR_PTR(-ENODEV); |
2943 | } | 2959 | } |
2944 | 2960 | ||
@@ -2952,7 +2968,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2952 | chip->onfi_version = 0; | 2968 | chip->onfi_version = 0; |
2953 | if (!type->name || !type->pagesize) { | 2969 | if (!type->name || !type->pagesize) { |
2954 | /* Check is chip is ONFI compliant */ | 2970 | /* Check is chip is ONFI compliant */ |
2955 | ret = nand_flash_detect_onfi(mtd, chip, busw); | 2971 | ret = nand_flash_detect_onfi(mtd, chip, &busw); |
2956 | if (ret) | 2972 | if (ret) |
2957 | goto ident_done; | 2973 | goto ident_done; |
2958 | } | 2974 | } |
@@ -2973,7 +2989,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2973 | chip->chipsize = (uint64_t)type->chipsize << 20; | 2989 | chip->chipsize = (uint64_t)type->chipsize << 20; |
2974 | 2990 | ||
2975 | if (!type->pagesize && chip->init_size) { | 2991 | if (!type->pagesize && chip->init_size) { |
2976 | /* set the pagesize, oobsize, erasesize by the driver*/ | 2992 | /* Set the pagesize, oobsize, erasesize by the driver */ |
2977 | busw = chip->init_size(mtd, chip, id_data); | 2993 | busw = chip->init_size(mtd, chip, id_data); |
2978 | } else if (!type->pagesize) { | 2994 | } else if (!type->pagesize) { |
2979 | int extid; | 2995 | int extid; |
@@ -3033,7 +3049,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3033 | } | 3049 | } |
3034 | } else { | 3050 | } else { |
3035 | /* | 3051 | /* |
3036 | * Old devices have chip data hardcoded in the device id table | 3052 | * Old devices have chip data hardcoded in the device id table. |
3037 | */ | 3053 | */ |
3038 | mtd->erasesize = type->erasesize; | 3054 | mtd->erasesize = type->erasesize; |
3039 | mtd->writesize = type->pagesize; | 3055 | mtd->writesize = type->pagesize; |
@@ -3043,7 +3059,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3043 | /* | 3059 | /* |
3044 | * Check for Spansion/AMD ID + repeating 5th, 6th byte since | 3060 | * Check for Spansion/AMD ID + repeating 5th, 6th byte since |
3045 | * some Spansion chips have erasesize that conflicts with size | 3061 | * some Spansion chips have erasesize that conflicts with size |
3046 | * listed in nand_ids table | 3062 | * listed in nand_ids table. |
3047 | * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) | 3063 | * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) |
3048 | */ | 3064 | */ |
3049 | if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && | 3065 | if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && |
@@ -3057,15 +3073,16 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3057 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | 3073 | chip->options &= ~NAND_CHIPOPTIONS_MSK; |
3058 | chip->options |= type->options & NAND_CHIPOPTIONS_MSK; | 3074 | chip->options |= type->options & NAND_CHIPOPTIONS_MSK; |
3059 | 3075 | ||
3060 | /* Check if chip is a not a samsung device. Do not clear the | 3076 | /* |
3061 | * options for chips which are not having an extended id. | 3077 | * Check if chip is not a Samsung device. Do not clear the |
3078 | * options for chips which do not have an extended id. | ||
3062 | */ | 3079 | */ |
3063 | if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) | 3080 | if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) |
3064 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; | 3081 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; |
3065 | ident_done: | 3082 | ident_done: |
3066 | 3083 | ||
3067 | /* | 3084 | /* |
3068 | * Set chip as a default. Board drivers can override it, if necessary | 3085 | * Set chip as a default. Board drivers can override it, if necessary. |
3069 | */ | 3086 | */ |
3070 | chip->options |= NAND_NO_AUTOINCR; | 3087 | chip->options |= NAND_NO_AUTOINCR; |
3071 | 3088 | ||
@@ -3077,21 +3094,21 @@ ident_done: | |||
3077 | 3094 | ||
3078 | /* | 3095 | /* |
3079 | * Check, if buswidth is correct. Hardware drivers should set | 3096 | * Check, if buswidth is correct. Hardware drivers should set |
3080 | * chip correct ! | 3097 | * chip correct! |
3081 | */ | 3098 | */ |
3082 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { | 3099 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { |
3083 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 3100 | pr_info("NAND device: Manufacturer ID:" |
3084 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, | 3101 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, |
3085 | *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); | 3102 | *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); |
3086 | printk(KERN_WARNING "NAND bus width %d instead %d bit\n", | 3103 | pr_warn("NAND bus width %d instead %d bit\n", |
3087 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, | 3104 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, |
3088 | busw ? 16 : 8); | 3105 | busw ? 16 : 8); |
3089 | return ERR_PTR(-EINVAL); | 3106 | return ERR_PTR(-EINVAL); |
3090 | } | 3107 | } |
3091 | 3108 | ||
3092 | /* Calculate the address shift from the page size */ | 3109 | /* Calculate the address shift from the page size */ |
3093 | chip->page_shift = ffs(mtd->writesize) - 1; | 3110 | chip->page_shift = ffs(mtd->writesize) - 1; |
3094 | /* Convert chipsize to number of pages per chip -1. */ | 3111 | /* Convert chipsize to number of pages per chip -1 */ |
3095 | chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; | 3112 | chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; |
3096 | 3113 | ||
3097 | chip->bbt_erase_shift = chip->phys_erase_shift = | 3114 | chip->bbt_erase_shift = chip->phys_erase_shift = |
@@ -3121,7 +3138,7 @@ ident_done: | |||
3121 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 3138 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
3122 | (*maf_id == NAND_MFR_SAMSUNG || | 3139 | (*maf_id == NAND_MFR_SAMSUNG || |
3123 | *maf_id == NAND_MFR_HYNIX)) | 3140 | *maf_id == NAND_MFR_HYNIX)) |
3124 | chip->options |= NAND_BBT_SCANLASTPAGE; | 3141 | chip->bbt_options |= NAND_BBT_SCANLASTPAGE; |
3125 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 3142 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
3126 | (*maf_id == NAND_MFR_SAMSUNG || | 3143 | (*maf_id == NAND_MFR_SAMSUNG || |
3127 | *maf_id == NAND_MFR_HYNIX || | 3144 | *maf_id == NAND_MFR_HYNIX || |
@@ -3129,17 +3146,7 @@ ident_done: | |||
3129 | *maf_id == NAND_MFR_AMD)) || | 3146 | *maf_id == NAND_MFR_AMD)) || |
3130 | (mtd->writesize == 2048 && | 3147 | (mtd->writesize == 2048 && |
3131 | *maf_id == NAND_MFR_MICRON)) | 3148 | *maf_id == NAND_MFR_MICRON)) |
3132 | chip->options |= NAND_BBT_SCAN2NDPAGE; | 3149 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; |
3133 | |||
3134 | /* | ||
3135 | * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6 | ||
3136 | */ | ||
3137 | if (!(busw & NAND_BUSWIDTH_16) && | ||
3138 | *maf_id == NAND_MFR_STMICRO && | ||
3139 | mtd->writesize == 2048) { | ||
3140 | chip->options |= NAND_BBT_SCANBYTE1AND6; | ||
3141 | chip->badblockpos = 0; | ||
3142 | } | ||
3143 | 3150 | ||
3144 | /* Check for AND chips with 4 page planes */ | 3151 | /* Check for AND chips with 4 page planes */ |
3145 | if (chip->options & NAND_4PAGE_ARRAY) | 3152 | if (chip->options & NAND_4PAGE_ARRAY) |
@@ -3147,12 +3154,11 @@ ident_done: | |||
3147 | else | 3154 | else |
3148 | chip->erase_cmd = single_erase_cmd; | 3155 | chip->erase_cmd = single_erase_cmd; |
3149 | 3156 | ||
3150 | /* Do not replace user supplied command function ! */ | 3157 | /* Do not replace user supplied command function! */ |
3151 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) | 3158 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) |
3152 | chip->cmdfunc = nand_command_lp; | 3159 | chip->cmdfunc = nand_command_lp; |
3153 | 3160 | ||
3154 | /* TODO onfi flash name */ | 3161 | pr_info("NAND device: Manufacturer ID:" |
3155 | printk(KERN_INFO "NAND device: Manufacturer ID:" | ||
3156 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, | 3162 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, |
3157 | nand_manuf_ids[maf_idx].name, | 3163 | nand_manuf_ids[maf_idx].name, |
3158 | chip->onfi_version ? chip->onfi_params.model : type->name); | 3164 | chip->onfi_version ? chip->onfi_params.model : type->name); |
@@ -3162,12 +3168,12 @@ ident_done: | |||
3162 | 3168 | ||
3163 | /** | 3169 | /** |
3164 | * nand_scan_ident - [NAND Interface] Scan for the NAND device | 3170 | * nand_scan_ident - [NAND Interface] Scan for the NAND device |
3165 | * @mtd: MTD device structure | 3171 | * @mtd: MTD device structure |
3166 | * @maxchips: Number of chips to scan for | 3172 | * @maxchips: number of chips to scan for |
3167 | * @table: Alternative NAND ID table | 3173 | * @table: alternative NAND ID table |
3168 | * | 3174 | * |
3169 | * This is the first phase of the normal nand_scan() function. It | 3175 | * This is the first phase of the normal nand_scan() function. It reads the |
3170 | * reads the flash ID and sets up MTD fields accordingly. | 3176 | * flash ID and sets up MTD fields accordingly. |
3171 | * | 3177 | * |
3172 | * The mtd->owner field must be set to the module of the caller. | 3178 | * The mtd->owner field must be set to the module of the caller. |
3173 | */ | 3179 | */ |
@@ -3189,7 +3195,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3189 | 3195 | ||
3190 | if (IS_ERR(type)) { | 3196 | if (IS_ERR(type)) { |
3191 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | 3197 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) |
3192 | printk(KERN_WARNING "No NAND device found.\n"); | 3198 | pr_warn("No NAND device found\n"); |
3193 | chip->select_chip(mtd, -1); | 3199 | chip->select_chip(mtd, -1); |
3194 | return PTR_ERR(type); | 3200 | return PTR_ERR(type); |
3195 | } | 3201 | } |
@@ -3207,7 +3213,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3207 | break; | 3213 | break; |
3208 | } | 3214 | } |
3209 | if (i > 1) | 3215 | if (i > 1) |
3210 | printk(KERN_INFO "%d NAND chips detected\n", i); | 3216 | pr_info("%d NAND chips detected\n", i); |
3211 | 3217 | ||
3212 | /* Store the number of chips and calc total size for mtd */ | 3218 | /* Store the number of chips and calc total size for mtd */ |
3213 | chip->numchips = i; | 3219 | chip->numchips = i; |
@@ -3220,11 +3226,11 @@ EXPORT_SYMBOL(nand_scan_ident); | |||
3220 | 3226 | ||
3221 | /** | 3227 | /** |
3222 | * nand_scan_tail - [NAND Interface] Scan for the NAND device | 3228 | * nand_scan_tail - [NAND Interface] Scan for the NAND device |
3223 | * @mtd: MTD device structure | 3229 | * @mtd: MTD device structure |
3224 | * | 3230 | * |
3225 | * This is the second phase of the normal nand_scan() function. It | 3231 | * This is the second phase of the normal nand_scan() function. It fills out |
3226 | * fills out all the uninitialized function pointers with the defaults | 3232 | * all the uninitialized function pointers with the defaults and scans for a |
3227 | * and scans for a bad block table if appropriate. | 3233 | * bad block table if appropriate. |
3228 | */ | 3234 | */ |
3229 | int nand_scan_tail(struct mtd_info *mtd) | 3235 | int nand_scan_tail(struct mtd_info *mtd) |
3230 | { | 3236 | { |
@@ -3240,7 +3246,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3240 | chip->oob_poi = chip->buffers->databuf + mtd->writesize; | 3246 | chip->oob_poi = chip->buffers->databuf + mtd->writesize; |
3241 | 3247 | ||
3242 | /* | 3248 | /* |
3243 | * If no default placement scheme is given, select an appropriate one | 3249 | * If no default placement scheme is given, select an appropriate one. |
3244 | */ | 3250 | */ |
3245 | if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) { | 3251 | if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) { |
3246 | switch (mtd->oobsize) { | 3252 | switch (mtd->oobsize) { |
@@ -3257,8 +3263,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3257 | chip->ecc.layout = &nand_oob_128; | 3263 | chip->ecc.layout = &nand_oob_128; |
3258 | break; | 3264 | break; |
3259 | default: | 3265 | default: |
3260 | printk(KERN_WARNING "No oob scheme defined for " | 3266 | pr_warn("No oob scheme defined for oobsize %d\n", |
3261 | "oobsize %d\n", mtd->oobsize); | 3267 | mtd->oobsize); |
3262 | BUG(); | 3268 | BUG(); |
3263 | } | 3269 | } |
3264 | } | 3270 | } |
@@ -3267,7 +3273,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3267 | chip->write_page = nand_write_page; | 3273 | chip->write_page = nand_write_page; |
3268 | 3274 | ||
3269 | /* | 3275 | /* |
3270 | * check ECC mode, default to software if 3byte/512byte hardware ECC is | 3276 | * Check ECC mode, default to software if 3byte/512byte hardware ECC is |
3271 | * selected and we have 256 byte pagesize fallback to software ECC | 3277 | * selected and we have 256 byte pagesize fallback to software ECC |
3272 | */ | 3278 | */ |
3273 | 3279 | ||
@@ -3276,15 +3282,15 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3276 | /* Similar to NAND_ECC_HW, but a separate read_page handle */ | 3282 | /* Similar to NAND_ECC_HW, but a separate read_page handle */ |
3277 | if (!chip->ecc.calculate || !chip->ecc.correct || | 3283 | if (!chip->ecc.calculate || !chip->ecc.correct || |
3278 | !chip->ecc.hwctl) { | 3284 | !chip->ecc.hwctl) { |
3279 | printk(KERN_WARNING "No ECC functions supplied; " | 3285 | pr_warn("No ECC functions supplied; " |
3280 | "Hardware ECC not possible\n"); | 3286 | "hardware ECC not possible\n"); |
3281 | BUG(); | 3287 | BUG(); |
3282 | } | 3288 | } |
3283 | if (!chip->ecc.read_page) | 3289 | if (!chip->ecc.read_page) |
3284 | chip->ecc.read_page = nand_read_page_hwecc_oob_first; | 3290 | chip->ecc.read_page = nand_read_page_hwecc_oob_first; |
3285 | 3291 | ||
3286 | case NAND_ECC_HW: | 3292 | case NAND_ECC_HW: |
3287 | /* Use standard hwecc read page function ? */ | 3293 | /* Use standard hwecc read page function? */ |
3288 | if (!chip->ecc.read_page) | 3294 | if (!chip->ecc.read_page) |
3289 | chip->ecc.read_page = nand_read_page_hwecc; | 3295 | chip->ecc.read_page = nand_read_page_hwecc; |
3290 | if (!chip->ecc.write_page) | 3296 | if (!chip->ecc.write_page) |
@@ -3305,11 +3311,11 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3305 | chip->ecc.read_page == nand_read_page_hwecc || | 3311 | chip->ecc.read_page == nand_read_page_hwecc || |
3306 | !chip->ecc.write_page || | 3312 | !chip->ecc.write_page || |
3307 | chip->ecc.write_page == nand_write_page_hwecc)) { | 3313 | chip->ecc.write_page == nand_write_page_hwecc)) { |
3308 | printk(KERN_WARNING "No ECC functions supplied; " | 3314 | pr_warn("No ECC functions supplied; " |
3309 | "Hardware ECC not possible\n"); | 3315 | "hardware ECC not possible\n"); |
3310 | BUG(); | 3316 | BUG(); |
3311 | } | 3317 | } |
3312 | /* Use standard syndrome read/write page function ? */ | 3318 | /* Use standard syndrome read/write page function? */ |
3313 | if (!chip->ecc.read_page) | 3319 | if (!chip->ecc.read_page) |
3314 | chip->ecc.read_page = nand_read_page_syndrome; | 3320 | chip->ecc.read_page = nand_read_page_syndrome; |
3315 | if (!chip->ecc.write_page) | 3321 | if (!chip->ecc.write_page) |
@@ -3325,9 +3331,9 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3325 | 3331 | ||
3326 | if (mtd->writesize >= chip->ecc.size) | 3332 | if (mtd->writesize >= chip->ecc.size) |
3327 | break; | 3333 | break; |
3328 | printk(KERN_WARNING "%d byte HW ECC not possible on " | 3334 | pr_warn("%d byte HW ECC not possible on " |
3329 | "%d byte page size, fallback to SW ECC\n", | 3335 | "%d byte page size, fallback to SW ECC\n", |
3330 | chip->ecc.size, mtd->writesize); | 3336 | chip->ecc.size, mtd->writesize); |
3331 | chip->ecc.mode = NAND_ECC_SOFT; | 3337 | chip->ecc.mode = NAND_ECC_SOFT; |
3332 | 3338 | ||
3333 | case NAND_ECC_SOFT: | 3339 | case NAND_ECC_SOFT: |
@@ -3347,7 +3353,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3347 | 3353 | ||
3348 | case NAND_ECC_SOFT_BCH: | 3354 | case NAND_ECC_SOFT_BCH: |
3349 | if (!mtd_nand_has_bch()) { | 3355 | if (!mtd_nand_has_bch()) { |
3350 | printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n"); | 3356 | pr_warn("CONFIG_MTD_ECC_BCH not enabled\n"); |
3351 | BUG(); | 3357 | BUG(); |
3352 | } | 3358 | } |
3353 | chip->ecc.calculate = nand_bch_calculate_ecc; | 3359 | chip->ecc.calculate = nand_bch_calculate_ecc; |
@@ -3362,8 +3368,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3362 | /* | 3368 | /* |
3363 | * Board driver should supply ecc.size and ecc.bytes values to | 3369 | * Board driver should supply ecc.size and ecc.bytes values to |
3364 | * select how many bits are correctable; see nand_bch_init() | 3370 | * select how many bits are correctable; see nand_bch_init() |
3365 | * for details. | 3371 | * for details. Otherwise, default to 4 bits for large page |
3366 | * Otherwise, default to 4 bits for large page devices | 3372 | * devices. |
3367 | */ | 3373 | */ |
3368 | if (!chip->ecc.size && (mtd->oobsize >= 64)) { | 3374 | if (!chip->ecc.size && (mtd->oobsize >= 64)) { |
3369 | chip->ecc.size = 512; | 3375 | chip->ecc.size = 512; |
@@ -3374,14 +3380,14 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3374 | chip->ecc.bytes, | 3380 | chip->ecc.bytes, |
3375 | &chip->ecc.layout); | 3381 | &chip->ecc.layout); |
3376 | if (!chip->ecc.priv) { | 3382 | if (!chip->ecc.priv) { |
3377 | printk(KERN_WARNING "BCH ECC initialization failed!\n"); | 3383 | pr_warn("BCH ECC initialization failed!\n"); |
3378 | BUG(); | 3384 | BUG(); |
3379 | } | 3385 | } |
3380 | break; | 3386 | break; |
3381 | 3387 | ||
3382 | case NAND_ECC_NONE: | 3388 | case NAND_ECC_NONE: |
3383 | printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " | 3389 | pr_warn("NAND_ECC_NONE selected by board driver. " |
3384 | "This is not recommended !!\n"); | 3390 | "This is not recommended!\n"); |
3385 | chip->ecc.read_page = nand_read_page_raw; | 3391 | chip->ecc.read_page = nand_read_page_raw; |
3386 | chip->ecc.write_page = nand_write_page_raw; | 3392 | chip->ecc.write_page = nand_write_page_raw; |
3387 | chip->ecc.read_oob = nand_read_oob_std; | 3393 | chip->ecc.read_oob = nand_read_oob_std; |
@@ -3393,14 +3399,19 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3393 | break; | 3399 | break; |
3394 | 3400 | ||
3395 | default: | 3401 | default: |
3396 | printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", | 3402 | pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode); |
3397 | chip->ecc.mode); | ||
3398 | BUG(); | 3403 | BUG(); |
3399 | } | 3404 | } |
3400 | 3405 | ||
3406 | /* For many systems, the standard OOB write also works for raw */ | ||
3407 | if (!chip->ecc.read_oob_raw) | ||
3408 | chip->ecc.read_oob_raw = chip->ecc.read_oob; | ||
3409 | if (!chip->ecc.write_oob_raw) | ||
3410 | chip->ecc.write_oob_raw = chip->ecc.write_oob; | ||
3411 | |||
3401 | /* | 3412 | /* |
3402 | * The number of bytes available for a client to place data into | 3413 | * The number of bytes available for a client to place data into |
3403 | * the out of band area | 3414 | * the out of band area. |
3404 | */ | 3415 | */ |
3405 | chip->ecc.layout->oobavail = 0; | 3416 | chip->ecc.layout->oobavail = 0; |
3406 | for (i = 0; chip->ecc.layout->oobfree[i].length | 3417 | for (i = 0; chip->ecc.layout->oobfree[i].length |
@@ -3411,19 +3422,16 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3411 | 3422 | ||
3412 | /* | 3423 | /* |
3413 | * Set the number of read / write steps for one page depending on ECC | 3424 | * Set the number of read / write steps for one page depending on ECC |
3414 | * mode | 3425 | * mode. |
3415 | */ | 3426 | */ |
3416 | chip->ecc.steps = mtd->writesize / chip->ecc.size; | 3427 | chip->ecc.steps = mtd->writesize / chip->ecc.size; |
3417 | if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { | 3428 | if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { |
3418 | printk(KERN_WARNING "Invalid ecc parameters\n"); | 3429 | pr_warn("Invalid ECC parameters\n"); |
3419 | BUG(); | 3430 | BUG(); |
3420 | } | 3431 | } |
3421 | chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; | 3432 | chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; |
3422 | 3433 | ||
3423 | /* | 3434 | /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ |
3424 | * Allow subpage writes up to ecc.steps. Not possible for MLC | ||
3425 | * FLASH. | ||
3426 | */ | ||
3427 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && | 3435 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && |
3428 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { | 3436 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { |
3429 | switch (chip->ecc.steps) { | 3437 | switch (chip->ecc.steps) { |
@@ -3481,9 +3489,11 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3481 | } | 3489 | } |
3482 | EXPORT_SYMBOL(nand_scan_tail); | 3490 | EXPORT_SYMBOL(nand_scan_tail); |
3483 | 3491 | ||
3484 | /* is_module_text_address() isn't exported, and it's mostly a pointless | 3492 | /* |
3493 | * is_module_text_address() isn't exported, and it's mostly a pointless | ||
3485 | * test if this is a module _anyway_ -- they'd have to try _really_ hard | 3494 | * test if this is a module _anyway_ -- they'd have to try _really_ hard |
3486 | * to call us from in-kernel code if the core NAND support is modular. */ | 3495 | * to call us from in-kernel code if the core NAND support is modular. |
3496 | */ | ||
3487 | #ifdef MODULE | 3497 | #ifdef MODULE |
3488 | #define caller_is_module() (1) | 3498 | #define caller_is_module() (1) |
3489 | #else | 3499 | #else |
@@ -3493,15 +3503,13 @@ EXPORT_SYMBOL(nand_scan_tail); | |||
3493 | 3503 | ||
3494 | /** | 3504 | /** |
3495 | * nand_scan - [NAND Interface] Scan for the NAND device | 3505 | * nand_scan - [NAND Interface] Scan for the NAND device |
3496 | * @mtd: MTD device structure | 3506 | * @mtd: MTD device structure |
3497 | * @maxchips: Number of chips to scan for | 3507 | * @maxchips: number of chips to scan for |
3498 | * | ||
3499 | * This fills out all the uninitialized function pointers | ||
3500 | * with the defaults. | ||
3501 | * The flash ID is read and the mtd/chip structures are | ||
3502 | * filled with the appropriate values. | ||
3503 | * The mtd->owner field must be set to the module of the caller | ||
3504 | * | 3508 | * |
3509 | * This fills out all the uninitialized function pointers with the defaults. | ||
3510 | * The flash ID is read and the mtd/chip structures are filled with the | ||
3511 | * appropriate values. The mtd->owner field must be set to the module of the | ||
3512 | * caller. | ||
3505 | */ | 3513 | */ |
3506 | int nand_scan(struct mtd_info *mtd, int maxchips) | 3514 | int nand_scan(struct mtd_info *mtd, int maxchips) |
3507 | { | 3515 | { |
@@ -3509,8 +3517,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
3509 | 3517 | ||
3510 | /* Many callers got this wrong, so check for it for a while... */ | 3518 | /* Many callers got this wrong, so check for it for a while... */ |
3511 | if (!mtd->owner && caller_is_module()) { | 3519 | if (!mtd->owner && caller_is_module()) { |
3512 | printk(KERN_CRIT "%s called with NULL mtd->owner!\n", | 3520 | pr_crit("%s called with NULL mtd->owner!\n", __func__); |
3513 | __func__); | ||
3514 | BUG(); | 3521 | BUG(); |
3515 | } | 3522 | } |
3516 | 3523 | ||
@@ -3523,8 +3530,8 @@ EXPORT_SYMBOL(nand_scan); | |||
3523 | 3530 | ||
3524 | /** | 3531 | /** |
3525 | * nand_release - [NAND Interface] Free resources held by the NAND device | 3532 | * nand_release - [NAND Interface] Free resources held by the NAND device |
3526 | * @mtd: MTD device structure | 3533 | * @mtd: MTD device structure |
3527 | */ | 3534 | */ |
3528 | void nand_release(struct mtd_info *mtd) | 3535 | void nand_release(struct mtd_info *mtd) |
3529 | { | 3536 | { |
3530 | struct nand_chip *chip = mtd->priv; | 3537 | struct nand_chip *chip = mtd->priv; |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 4165857752ca..69148ae3bf58 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * | 14 | * |
15 | * When nand_scan_bbt is called, then it tries to find the bad block table | 15 | * When nand_scan_bbt is called, then it tries to find the bad block table |
16 | * depending on the options in the BBT descriptor(s). If no flash based BBT | 16 | * depending on the options in the BBT descriptor(s). If no flash based BBT |
17 | * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory | 17 | * (NAND_BBT_USE_FLASH) is specified then the device is scanned for factory |
18 | * marked good / bad blocks. This information is used to create a memory BBT. | 18 | * marked good / bad blocks. This information is used to create a memory BBT. |
19 | * Once a new bad block is discovered then the "factory" information is updated | 19 | * Once a new bad block is discovered then the "factory" information is updated |
20 | * on the device. | 20 | * on the device. |
@@ -36,9 +36,9 @@ | |||
36 | * The table is marked in the OOB area with an ident pattern and a version | 36 | * The table is marked in the OOB area with an ident pattern and a version |
37 | * number which indicates which of both tables is more up to date. If the NAND | 37 | * number which indicates which of both tables is more up to date. If the NAND |
38 | * controller needs the complete OOB area for the ECC information then the | 38 | * controller needs the complete OOB area for the ECC information then the |
39 | * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern | 39 | * option NAND_BBT_NO_OOB should be used (along with NAND_BBT_USE_FLASH, of |
40 | * and the version byte into the data area and the OOB area will remain | 40 | * course): it moves the ident pattern and the version byte into the data area |
41 | * untouched. | 41 | * and the OOB area will remain untouched. |
42 | * | 42 | * |
43 | * The table uses 2 bits per block | 43 | * The table uses 2 bits per block |
44 | * 11b: block is good | 44 | * 11b: block is good |
@@ -81,17 +81,15 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) | |||
81 | 81 | ||
82 | /** | 82 | /** |
83 | * check_pattern - [GENERIC] check if a pattern is in the buffer | 83 | * check_pattern - [GENERIC] check if a pattern is in the buffer |
84 | * @buf: the buffer to search | 84 | * @buf: the buffer to search |
85 | * @len: the length of buffer to search | 85 | * @len: the length of buffer to search |
86 | * @paglen: the pagelength | 86 | * @paglen: the pagelength |
87 | * @td: search pattern descriptor | 87 | * @td: search pattern descriptor |
88 | * | 88 | * |
89 | * Check for a pattern at the given place. Used to search bad block | 89 | * Check for a pattern at the given place. Used to search bad block tables and |
90 | * tables and good / bad block identifiers. | 90 | * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if |
91 | * If the SCAN_EMPTY option is set then check, if all bytes except the | 91 | * all bytes except the pattern area contain 0xff. |
92 | * pattern area contain 0xff | 92 | */ |
93 | * | ||
94 | */ | ||
95 | static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) | 93 | static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) |
96 | { | 94 | { |
97 | int i, end = 0; | 95 | int i, end = 0; |
@@ -110,32 +108,8 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc | |||
110 | p += end; | 108 | p += end; |
111 | 109 | ||
112 | /* Compare the pattern */ | 110 | /* Compare the pattern */ |
113 | for (i = 0; i < td->len; i++) { | 111 | if (memcmp(p, td->pattern, td->len)) |
114 | if (p[i] != td->pattern[i]) | 112 | return -1; |
115 | return -1; | ||
116 | } | ||
117 | |||
118 | /* Check both positions 1 and 6 for pattern? */ | ||
119 | if (td->options & NAND_BBT_SCANBYTE1AND6) { | ||
120 | if (td->options & NAND_BBT_SCANEMPTY) { | ||
121 | p += td->len; | ||
122 | end += NAND_SMALL_BADBLOCK_POS - td->offs; | ||
123 | /* Check region between positions 1 and 6 */ | ||
124 | for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len; | ||
125 | i++) { | ||
126 | if (*p++ != 0xff) | ||
127 | return -1; | ||
128 | } | ||
129 | } | ||
130 | else { | ||
131 | p += NAND_SMALL_BADBLOCK_POS - td->offs; | ||
132 | } | ||
133 | /* Compare the pattern */ | ||
134 | for (i = 0; i < td->len; i++) { | ||
135 | if (p[i] != td->pattern[i]) | ||
136 | return -1; | ||
137 | } | ||
138 | } | ||
139 | 113 | ||
140 | if (td->options & NAND_BBT_SCANEMPTY) { | 114 | if (td->options & NAND_BBT_SCANEMPTY) { |
141 | p += td->len; | 115 | p += td->len; |
@@ -150,14 +124,13 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc | |||
150 | 124 | ||
151 | /** | 125 | /** |
152 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | 126 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer |
153 | * @buf: the buffer to search | 127 | * @buf: the buffer to search |
154 | * @td: search pattern descriptor | 128 | * @td: search pattern descriptor |
155 | * | ||
156 | * Check for a pattern at the given place. Used to search bad block | ||
157 | * tables and good / bad block identifiers. Same as check_pattern, but | ||
158 | * no optional empty check | ||
159 | * | 129 | * |
160 | */ | 130 | * Check for a pattern at the given place. Used to search bad block tables and |
131 | * good / bad block identifiers. Same as check_pattern, but no optional empty | ||
132 | * check. | ||
133 | */ | ||
161 | static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) | 134 | static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) |
162 | { | 135 | { |
163 | int i; | 136 | int i; |
@@ -168,21 +141,14 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) | |||
168 | if (p[td->offs + i] != td->pattern[i]) | 141 | if (p[td->offs + i] != td->pattern[i]) |
169 | return -1; | 142 | return -1; |
170 | } | 143 | } |
171 | /* Need to check location 1 AND 6? */ | ||
172 | if (td->options & NAND_BBT_SCANBYTE1AND6) { | ||
173 | for (i = 0; i < td->len; i++) { | ||
174 | if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i]) | ||
175 | return -1; | ||
176 | } | ||
177 | } | ||
178 | return 0; | 144 | return 0; |
179 | } | 145 | } |
180 | 146 | ||
181 | /** | 147 | /** |
182 | * add_marker_len - compute the length of the marker in data area | 148 | * add_marker_len - compute the length of the marker in data area |
183 | * @td: BBT descriptor used for computation | 149 | * @td: BBT descriptor used for computation |
184 | * | 150 | * |
185 | * The length will be 0 if the markeris located in OOB area. | 151 | * The length will be 0 if the marker is located in OOB area. |
186 | */ | 152 | */ |
187 | static u32 add_marker_len(struct nand_bbt_descr *td) | 153 | static u32 add_marker_len(struct nand_bbt_descr *td) |
188 | { | 154 | { |
@@ -199,34 +165,33 @@ static u32 add_marker_len(struct nand_bbt_descr *td) | |||
199 | 165 | ||
200 | /** | 166 | /** |
201 | * read_bbt - [GENERIC] Read the bad block table starting from page | 167 | * read_bbt - [GENERIC] Read the bad block table starting from page |
202 | * @mtd: MTD device structure | 168 | * @mtd: MTD device structure |
203 | * @buf: temporary buffer | 169 | * @buf: temporary buffer |
204 | * @page: the starting page | 170 | * @page: the starting page |
205 | * @num: the number of bbt descriptors to read | 171 | * @num: the number of bbt descriptors to read |
206 | * @td: the bbt describtion table | 172 | * @td: the bbt describtion table |
207 | * @offs: offset in the memory table | 173 | * @offs: offset in the memory table |
208 | * | 174 | * |
209 | * Read the bad block table starting from page. | 175 | * Read the bad block table starting from page. |
210 | * | ||
211 | */ | 176 | */ |
212 | static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | 177 | static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, |
213 | struct nand_bbt_descr *td, int offs) | 178 | struct nand_bbt_descr *td, int offs) |
214 | { | 179 | { |
215 | int res, i, j, act = 0; | 180 | int res, ret = 0, i, j, act = 0; |
216 | struct nand_chip *this = mtd->priv; | 181 | struct nand_chip *this = mtd->priv; |
217 | size_t retlen, len, totlen; | 182 | size_t retlen, len, totlen; |
218 | loff_t from; | 183 | loff_t from; |
219 | int bits = td->options & NAND_BBT_NRBITS_MSK; | 184 | int bits = td->options & NAND_BBT_NRBITS_MSK; |
220 | uint8_t msk = (uint8_t) ((1 << bits) - 1); | 185 | uint8_t msk = (uint8_t)((1 << bits) - 1); |
221 | u32 marker_len; | 186 | u32 marker_len; |
222 | int reserved_block_code = td->reserved_block_code; | 187 | int reserved_block_code = td->reserved_block_code; |
223 | 188 | ||
224 | totlen = (num * bits) >> 3; | 189 | totlen = (num * bits) >> 3; |
225 | marker_len = add_marker_len(td); | 190 | marker_len = add_marker_len(td); |
226 | from = ((loff_t) page) << this->page_shift; | 191 | from = ((loff_t)page) << this->page_shift; |
227 | 192 | ||
228 | while (totlen) { | 193 | while (totlen) { |
229 | len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); | 194 | len = min(totlen, (size_t)(1 << this->bbt_erase_shift)); |
230 | if (marker_len) { | 195 | if (marker_len) { |
231 | /* | 196 | /* |
232 | * In case the BBT marker is not in the OOB area it | 197 | * In case the BBT marker is not in the OOB area it |
@@ -238,11 +203,18 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
238 | } | 203 | } |
239 | res = mtd->read(mtd, from, len, &retlen, buf); | 204 | res = mtd->read(mtd, from, len, &retlen, buf); |
240 | if (res < 0) { | 205 | if (res < 0) { |
241 | if (retlen != len) { | 206 | if (mtd_is_eccerr(res)) { |
242 | printk(KERN_INFO "nand_bbt: Error reading bad block table\n"); | 207 | pr_info("nand_bbt: ECC error in BBT at " |
208 | "0x%012llx\n", from & ~mtd->writesize); | ||
209 | return res; | ||
210 | } else if (mtd_is_bitflip(res)) { | ||
211 | pr_info("nand_bbt: corrected error in BBT at " | ||
212 | "0x%012llx\n", from & ~mtd->writesize); | ||
213 | ret = res; | ||
214 | } else { | ||
215 | pr_info("nand_bbt: error reading BBT\n"); | ||
243 | return res; | 216 | return res; |
244 | } | 217 | } |
245 | printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); | ||
246 | } | 218 | } |
247 | 219 | ||
248 | /* Analyse data */ | 220 | /* Analyse data */ |
@@ -253,17 +225,19 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
253 | if (tmp == msk) | 225 | if (tmp == msk) |
254 | continue; | 226 | continue; |
255 | if (reserved_block_code && (tmp == reserved_block_code)) { | 227 | if (reserved_block_code && (tmp == reserved_block_code)) { |
256 | printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n", | 228 | pr_info("nand_read_bbt: reserved block at 0x%012llx\n", |
257 | (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | 229 | (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); |
258 | this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); | 230 | this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); |
259 | mtd->ecc_stats.bbtblocks++; | 231 | mtd->ecc_stats.bbtblocks++; |
260 | continue; | 232 | continue; |
261 | } | 233 | } |
262 | /* Leave it for now, if its matured we can move this | 234 | /* |
263 | * message to MTD_DEBUG_LEVEL0 */ | 235 | * Leave it for now, if it's matured we can |
264 | printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n", | 236 | * move this message to pr_debug. |
265 | (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | 237 | */ |
266 | /* Factory marked bad or worn out ? */ | 238 | pr_info("nand_read_bbt: bad block at 0x%012llx\n", |
239 | (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | ||
240 | /* Factory marked bad or worn out? */ | ||
267 | if (tmp == 0) | 241 | if (tmp == 0) |
268 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); | 242 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); |
269 | else | 243 | else |
@@ -274,20 +248,20 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
274 | totlen -= len; | 248 | totlen -= len; |
275 | from += len; | 249 | from += len; |
276 | } | 250 | } |
277 | return 0; | 251 | return ret; |
278 | } | 252 | } |
279 | 253 | ||
280 | /** | 254 | /** |
281 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page | 255 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page |
282 | * @mtd: MTD device structure | 256 | * @mtd: MTD device structure |
283 | * @buf: temporary buffer | 257 | * @buf: temporary buffer |
284 | * @td: descriptor for the bad block table | 258 | * @td: descriptor for the bad block table |
285 | * @chip: read the table for a specific chip, -1 read all chips. | 259 | * @chip: read the table for a specific chip, -1 read all chips; applies only if |
286 | * Applies only if NAND_BBT_PERCHIP option is set | 260 | * NAND_BBT_PERCHIP option is set |
287 | * | 261 | * |
288 | * Read the bad block table for all chips starting at a given page | 262 | * Read the bad block table for all chips starting at a given page. We assume |
289 | * We assume that the bbt bits are in consecutive order. | 263 | * that the bbt bits are in consecutive order. |
290 | */ | 264 | */ |
291 | static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) | 265 | static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) |
292 | { | 266 | { |
293 | struct nand_chip *this = mtd->priv; | 267 | struct nand_chip *this = mtd->priv; |
@@ -313,9 +287,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
313 | return 0; | 287 | return 0; |
314 | } | 288 | } |
315 | 289 | ||
316 | /* | 290 | /* BBT marker is in the first page, no OOB */ |
317 | * BBT marker is in the first page, no OOB. | ||
318 | */ | ||
319 | static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | 291 | static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, |
320 | struct nand_bbt_descr *td) | 292 | struct nand_bbt_descr *td) |
321 | { | 293 | { |
@@ -329,35 +301,26 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | |||
329 | return mtd->read(mtd, offs, len, &retlen, buf); | 301 | return mtd->read(mtd, offs, len, &retlen, buf); |
330 | } | 302 | } |
331 | 303 | ||
332 | /* | 304 | /* Scan read raw data from flash */ |
333 | * Scan read raw data from flash | ||
334 | */ | ||
335 | static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | 305 | static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, |
336 | size_t len) | 306 | size_t len) |
337 | { | 307 | { |
338 | struct mtd_oob_ops ops; | 308 | struct mtd_oob_ops ops; |
339 | int res; | 309 | int res; |
340 | 310 | ||
341 | ops.mode = MTD_OOB_RAW; | 311 | ops.mode = MTD_OPS_RAW; |
342 | ops.ooboffs = 0; | 312 | ops.ooboffs = 0; |
343 | ops.ooblen = mtd->oobsize; | 313 | ops.ooblen = mtd->oobsize; |
344 | 314 | ||
345 | |||
346 | while (len > 0) { | 315 | while (len > 0) { |
347 | if (len <= mtd->writesize) { | 316 | ops.datbuf = buf; |
348 | ops.oobbuf = buf + len; | 317 | ops.len = min(len, (size_t)mtd->writesize); |
349 | ops.datbuf = buf; | 318 | ops.oobbuf = buf + ops.len; |
350 | ops.len = len; | ||
351 | return mtd->read_oob(mtd, offs, &ops); | ||
352 | } else { | ||
353 | ops.oobbuf = buf + mtd->writesize; | ||
354 | ops.datbuf = buf; | ||
355 | ops.len = mtd->writesize; | ||
356 | res = mtd->read_oob(mtd, offs, &ops); | ||
357 | 319 | ||
358 | if (res) | 320 | res = mtd->read_oob(mtd, offs, &ops); |
359 | return res; | 321 | |
360 | } | 322 | if (res) |
323 | return res; | ||
361 | 324 | ||
362 | buf += mtd->oobsize + mtd->writesize; | 325 | buf += mtd->oobsize + mtd->writesize; |
363 | len -= mtd->writesize; | 326 | len -= mtd->writesize; |
@@ -374,15 +337,13 @@ static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | |||
374 | return scan_read_raw_oob(mtd, buf, offs, len); | 337 | return scan_read_raw_oob(mtd, buf, offs, len); |
375 | } | 338 | } |
376 | 339 | ||
377 | /* | 340 | /* Scan write data with oob to flash */ |
378 | * Scan write data with oob to flash | ||
379 | */ | ||
380 | static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, | 341 | static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, |
381 | uint8_t *buf, uint8_t *oob) | 342 | uint8_t *buf, uint8_t *oob) |
382 | { | 343 | { |
383 | struct mtd_oob_ops ops; | 344 | struct mtd_oob_ops ops; |
384 | 345 | ||
385 | ops.mode = MTD_OOB_PLACE; | 346 | ops.mode = MTD_OPS_PLACE_OOB; |
386 | ops.ooboffs = 0; | 347 | ops.ooboffs = 0; |
387 | ops.ooblen = mtd->oobsize; | 348 | ops.ooblen = mtd->oobsize; |
388 | ops.datbuf = buf; | 349 | ops.datbuf = buf; |
@@ -403,15 +364,14 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
403 | 364 | ||
404 | /** | 365 | /** |
405 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page | 366 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page |
406 | * @mtd: MTD device structure | 367 | * @mtd: MTD device structure |
407 | * @buf: temporary buffer | 368 | * @buf: temporary buffer |
408 | * @td: descriptor for the bad block table | 369 | * @td: descriptor for the bad block table |
409 | * @md: descriptor for the bad block table mirror | 370 | * @md: descriptor for the bad block table mirror |
410 | * | 371 | * |
411 | * Read the bad block table(s) for all chips starting at a given page | 372 | * Read the bad block table(s) for all chips starting at a given page. We |
412 | * We assume that the bbt bits are in consecutive order. | 373 | * assume that the bbt bits are in consecutive order. |
413 | * | 374 | */ |
414 | */ | ||
415 | static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | 375 | static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, |
416 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) | 376 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) |
417 | { | 377 | { |
@@ -422,8 +382,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | |||
422 | scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, | 382 | scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, |
423 | mtd->writesize, td); | 383 | mtd->writesize, td); |
424 | td->version[0] = buf[bbt_get_ver_offs(mtd, td)]; | 384 | td->version[0] = buf[bbt_get_ver_offs(mtd, td)]; |
425 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", | 385 | pr_info("Bad block table at page %d, version 0x%02X\n", |
426 | td->pages[0], td->version[0]); | 386 | td->pages[0], td->version[0]); |
427 | } | 387 | } |
428 | 388 | ||
429 | /* Read the mirror version, if available */ | 389 | /* Read the mirror version, if available */ |
@@ -431,15 +391,13 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | |||
431 | scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, | 391 | scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, |
432 | mtd->writesize, td); | 392 | mtd->writesize, td); |
433 | md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; | 393 | md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; |
434 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", | 394 | pr_info("Bad block table at page %d, version 0x%02X\n", |
435 | md->pages[0], md->version[0]); | 395 | md->pages[0], md->version[0]); |
436 | } | 396 | } |
437 | return 1; | 397 | return 1; |
438 | } | 398 | } |
439 | 399 | ||
440 | /* | 400 | /* Scan a given block full */ |
441 | * Scan a given block full | ||
442 | */ | ||
443 | static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, | 401 | static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, |
444 | loff_t offs, uint8_t *buf, size_t readlen, | 402 | loff_t offs, uint8_t *buf, size_t readlen, |
445 | int scanlen, int len) | 403 | int scanlen, int len) |
@@ -447,7 +405,8 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, | |||
447 | int ret, j; | 405 | int ret, j; |
448 | 406 | ||
449 | ret = scan_read_raw_oob(mtd, buf, offs, readlen); | 407 | ret = scan_read_raw_oob(mtd, buf, offs, readlen); |
450 | if (ret) | 408 | /* Ignore ECC errors when checking for BBM */ |
409 | if (ret && !mtd_is_bitflip_or_eccerr(ret)) | ||
451 | return ret; | 410 | return ret; |
452 | 411 | ||
453 | for (j = 0; j < len; j++, buf += scanlen) { | 412 | for (j = 0; j < len; j++, buf += scanlen) { |
@@ -457,9 +416,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, | |||
457 | return 0; | 416 | return 0; |
458 | } | 417 | } |
459 | 418 | ||
460 | /* | 419 | /* Scan a given block partially */ |
461 | * Scan a given block partially | ||
462 | */ | ||
463 | static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, | 420 | static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, |
464 | loff_t offs, uint8_t *buf, int len) | 421 | loff_t offs, uint8_t *buf, int len) |
465 | { | 422 | { |
@@ -470,16 +427,16 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, | |||
470 | ops.oobbuf = buf; | 427 | ops.oobbuf = buf; |
471 | ops.ooboffs = 0; | 428 | ops.ooboffs = 0; |
472 | ops.datbuf = NULL; | 429 | ops.datbuf = NULL; |
473 | ops.mode = MTD_OOB_PLACE; | 430 | ops.mode = MTD_OPS_PLACE_OOB; |
474 | 431 | ||
475 | for (j = 0; j < len; j++) { | 432 | for (j = 0; j < len; j++) { |
476 | /* | 433 | /* |
477 | * Read the full oob until read_oob is fixed to | 434 | * Read the full oob until read_oob is fixed to handle single |
478 | * handle single byte reads for 16 bit | 435 | * byte reads for 16 bit buswidth. |
479 | * buswidth | ||
480 | */ | 436 | */ |
481 | ret = mtd->read_oob(mtd, offs, &ops); | 437 | ret = mtd->read_oob(mtd, offs, &ops); |
482 | if (ret) | 438 | /* Ignore ECC errors when checking for BBM */ |
439 | if (ret && !mtd_is_bitflip_or_eccerr(ret)) | ||
483 | return ret; | 440 | return ret; |
484 | 441 | ||
485 | if (check_short_pattern(buf, bd)) | 442 | if (check_short_pattern(buf, bd)) |
@@ -492,14 +449,14 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, | |||
492 | 449 | ||
493 | /** | 450 | /** |
494 | * create_bbt - [GENERIC] Create a bad block table by scanning the device | 451 | * create_bbt - [GENERIC] Create a bad block table by scanning the device |
495 | * @mtd: MTD device structure | 452 | * @mtd: MTD device structure |
496 | * @buf: temporary buffer | 453 | * @buf: temporary buffer |
497 | * @bd: descriptor for the good/bad block search pattern | 454 | * @bd: descriptor for the good/bad block search pattern |
498 | * @chip: create the table for a specific chip, -1 read all chips. | 455 | * @chip: create the table for a specific chip, -1 read all chips; applies only |
499 | * Applies only if NAND_BBT_PERCHIP option is set | 456 | * if NAND_BBT_PERCHIP option is set |
500 | * | 457 | * |
501 | * Create a bad block table by scanning the device | 458 | * Create a bad block table by scanning the device for the given good/bad block |
502 | * for the given good/bad block identify pattern | 459 | * identify pattern. |
503 | */ | 460 | */ |
504 | static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | 461 | static int create_bbt(struct mtd_info *mtd, uint8_t *buf, |
505 | struct nand_bbt_descr *bd, int chip) | 462 | struct nand_bbt_descr *bd, int chip) |
@@ -510,7 +467,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
510 | loff_t from; | 467 | loff_t from; |
511 | size_t readlen; | 468 | size_t readlen; |
512 | 469 | ||
513 | printk(KERN_INFO "Scanning device for bad blocks\n"); | 470 | pr_info("Scanning device for bad blocks\n"); |
514 | 471 | ||
515 | if (bd->options & NAND_BBT_SCANALLPAGES) | 472 | if (bd->options & NAND_BBT_SCANALLPAGES) |
516 | len = 1 << (this->bbt_erase_shift - this->page_shift); | 473 | len = 1 << (this->bbt_erase_shift - this->page_shift); |
@@ -530,14 +487,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
530 | } | 487 | } |
531 | 488 | ||
532 | if (chip == -1) { | 489 | if (chip == -1) { |
533 | /* Note that numblocks is 2 * (real numblocks) here, see i+=2 | 490 | /* |
534 | * below as it makes shifting and masking less painful */ | 491 | * Note that numblocks is 2 * (real numblocks) here, see i+=2 |
492 | * below as it makes shifting and masking less painful | ||
493 | */ | ||
535 | numblocks = mtd->size >> (this->bbt_erase_shift - 1); | 494 | numblocks = mtd->size >> (this->bbt_erase_shift - 1); |
536 | startblock = 0; | 495 | startblock = 0; |
537 | from = 0; | 496 | from = 0; |
538 | } else { | 497 | } else { |
539 | if (chip >= this->numchips) { | 498 | if (chip >= this->numchips) { |
540 | printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", | 499 | pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n", |
541 | chip + 1, this->numchips); | 500 | chip + 1, this->numchips); |
542 | return -EINVAL; | 501 | return -EINVAL; |
543 | } | 502 | } |
@@ -547,7 +506,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
547 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); | 506 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); |
548 | } | 507 | } |
549 | 508 | ||
550 | if (this->options & NAND_BBT_SCANLASTPAGE) | 509 | if (this->bbt_options & NAND_BBT_SCANLASTPAGE) |
551 | from += mtd->erasesize - (mtd->writesize * len); | 510 | from += mtd->erasesize - (mtd->writesize * len); |
552 | 511 | ||
553 | for (i = startblock; i < numblocks;) { | 512 | for (i = startblock; i < numblocks;) { |
@@ -566,8 +525,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
566 | 525 | ||
567 | if (ret) { | 526 | if (ret) { |
568 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 527 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); |
569 | printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n", | 528 | pr_warn("Bad eraseblock %d at 0x%012llx\n", |
570 | i >> 1, (unsigned long long)from); | 529 | i >> 1, (unsigned long long)from); |
571 | mtd->ecc_stats.badblocks++; | 530 | mtd->ecc_stats.badblocks++; |
572 | } | 531 | } |
573 | 532 | ||
@@ -579,20 +538,18 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
579 | 538 | ||
580 | /** | 539 | /** |
581 | * search_bbt - [GENERIC] scan the device for a specific bad block table | 540 | * search_bbt - [GENERIC] scan the device for a specific bad block table |
582 | * @mtd: MTD device structure | 541 | * @mtd: MTD device structure |
583 | * @buf: temporary buffer | 542 | * @buf: temporary buffer |
584 | * @td: descriptor for the bad block table | 543 | * @td: descriptor for the bad block table |
585 | * | 544 | * |
586 | * Read the bad block table by searching for a given ident pattern. | 545 | * Read the bad block table by searching for a given ident pattern. Search is |
587 | * Search is preformed either from the beginning up or from the end of | 546 | * preformed either from the beginning up or from the end of the device |
588 | * the device downwards. The search starts always at the start of a | 547 | * downwards. The search starts always at the start of a block. If the option |
589 | * block. | 548 | * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains |
590 | * If the option NAND_BBT_PERCHIP is given, each chip is searched | 549 | * the bad block information of this chip. This is necessary to provide support |
591 | * for a bbt, which contains the bad block information of this chip. | 550 | * for certain DOC devices. |
592 | * This is necessary to provide support for certain DOC devices. | ||
593 | * | 551 | * |
594 | * The bbt ident pattern resides in the oob area of the first page | 552 | * The bbt ident pattern resides in the oob area of the first page in a block. |
595 | * in a block. | ||
596 | */ | 553 | */ |
597 | static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) | 554 | static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) |
598 | { | 555 | { |
@@ -603,7 +560,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
603 | int bbtblocks; | 560 | int bbtblocks; |
604 | int blocktopage = this->bbt_erase_shift - this->page_shift; | 561 | int blocktopage = this->bbt_erase_shift - this->page_shift; |
605 | 562 | ||
606 | /* Search direction top -> down ? */ | 563 | /* Search direction top -> down? */ |
607 | if (td->options & NAND_BBT_LASTBLOCK) { | 564 | if (td->options & NAND_BBT_LASTBLOCK) { |
608 | startblock = (mtd->size >> this->bbt_erase_shift) - 1; | 565 | startblock = (mtd->size >> this->bbt_erase_shift) - 1; |
609 | dir = -1; | 566 | dir = -1; |
@@ -612,7 +569,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
612 | dir = 1; | 569 | dir = 1; |
613 | } | 570 | } |
614 | 571 | ||
615 | /* Do we have a bbt per chip ? */ | 572 | /* Do we have a bbt per chip? */ |
616 | if (td->options & NAND_BBT_PERCHIP) { | 573 | if (td->options & NAND_BBT_PERCHIP) { |
617 | chips = this->numchips; | 574 | chips = this->numchips; |
618 | bbtblocks = this->chipsize >> this->bbt_erase_shift; | 575 | bbtblocks = this->chipsize >> this->bbt_erase_shift; |
@@ -651,23 +608,23 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
651 | /* Check, if we found a bbt for each requested chip */ | 608 | /* Check, if we found a bbt for each requested chip */ |
652 | for (i = 0; i < chips; i++) { | 609 | for (i = 0; i < chips; i++) { |
653 | if (td->pages[i] == -1) | 610 | if (td->pages[i] == -1) |
654 | printk(KERN_WARNING "Bad block table not found for chip %d\n", i); | 611 | pr_warn("Bad block table not found for chip %d\n", i); |
655 | else | 612 | else |
656 | printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], | 613 | pr_info("Bad block table found at page %d, version " |
657 | td->version[i]); | 614 | "0x%02X\n", td->pages[i], td->version[i]); |
658 | } | 615 | } |
659 | return 0; | 616 | return 0; |
660 | } | 617 | } |
661 | 618 | ||
662 | /** | 619 | /** |
663 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) | 620 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) |
664 | * @mtd: MTD device structure | 621 | * @mtd: MTD device structure |
665 | * @buf: temporary buffer | 622 | * @buf: temporary buffer |
666 | * @td: descriptor for the bad block table | 623 | * @td: descriptor for the bad block table |
667 | * @md: descriptor for the bad block table mirror | 624 | * @md: descriptor for the bad block table mirror |
668 | * | 625 | * |
669 | * Search and read the bad block table(s) | 626 | * Search and read the bad block table(s). |
670 | */ | 627 | */ |
671 | static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md) | 628 | static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md) |
672 | { | 629 | { |
673 | /* Search the primary table */ | 630 | /* Search the primary table */ |
@@ -683,16 +640,14 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt | |||
683 | 640 | ||
684 | /** | 641 | /** |
685 | * write_bbt - [GENERIC] (Re)write the bad block table | 642 | * write_bbt - [GENERIC] (Re)write the bad block table |
643 | * @mtd: MTD device structure | ||
644 | * @buf: temporary buffer | ||
645 | * @td: descriptor for the bad block table | ||
646 | * @md: descriptor for the bad block table mirror | ||
647 | * @chipsel: selector for a specific chip, -1 for all | ||
686 | * | 648 | * |
687 | * @mtd: MTD device structure | 649 | * (Re)write the bad block table. |
688 | * @buf: temporary buffer | 650 | */ |
689 | * @td: descriptor for the bad block table | ||
690 | * @md: descriptor for the bad block table mirror | ||
691 | * @chipsel: selector for a specific chip, -1 for all | ||
692 | * | ||
693 | * (Re)write the bad block table | ||
694 | * | ||
695 | */ | ||
696 | static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | 651 | static int write_bbt(struct mtd_info *mtd, uint8_t *buf, |
697 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, | 652 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, |
698 | int chipsel) | 653 | int chipsel) |
@@ -711,14 +666,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
711 | ops.ooblen = mtd->oobsize; | 666 | ops.ooblen = mtd->oobsize; |
712 | ops.ooboffs = 0; | 667 | ops.ooboffs = 0; |
713 | ops.datbuf = NULL; | 668 | ops.datbuf = NULL; |
714 | ops.mode = MTD_OOB_PLACE; | 669 | ops.mode = MTD_OPS_PLACE_OOB; |
715 | 670 | ||
716 | if (!rcode) | 671 | if (!rcode) |
717 | rcode = 0xff; | 672 | rcode = 0xff; |
718 | /* Write bad block table per chip rather than per device ? */ | 673 | /* Write bad block table per chip rather than per device? */ |
719 | if (td->options & NAND_BBT_PERCHIP) { | 674 | if (td->options & NAND_BBT_PERCHIP) { |
720 | numblocks = (int)(this->chipsize >> this->bbt_erase_shift); | 675 | numblocks = (int)(this->chipsize >> this->bbt_erase_shift); |
721 | /* Full device write or specific chip ? */ | 676 | /* Full device write or specific chip? */ |
722 | if (chipsel == -1) { | 677 | if (chipsel == -1) { |
723 | nrchips = this->numchips; | 678 | nrchips = this->numchips; |
724 | } else { | 679 | } else { |
@@ -732,8 +687,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
732 | 687 | ||
733 | /* Loop through the chips */ | 688 | /* Loop through the chips */ |
734 | for (; chip < nrchips; chip++) { | 689 | for (; chip < nrchips; chip++) { |
735 | 690 | /* | |
736 | /* There was already a version of the table, reuse the page | 691 | * There was already a version of the table, reuse the page |
737 | * This applies for absolute placement too, as we have the | 692 | * This applies for absolute placement too, as we have the |
738 | * page nr. in td->pages. | 693 | * page nr. in td->pages. |
739 | */ | 694 | */ |
@@ -742,8 +697,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
742 | goto write; | 697 | goto write; |
743 | } | 698 | } |
744 | 699 | ||
745 | /* Automatic placement of the bad block table */ | 700 | /* |
746 | /* Search direction top -> down ? */ | 701 | * Automatic placement of the bad block table. Search direction |
702 | * top -> down? | ||
703 | */ | ||
747 | if (td->options & NAND_BBT_LASTBLOCK) { | 704 | if (td->options & NAND_BBT_LASTBLOCK) { |
748 | startblock = numblocks * (chip + 1) - 1; | 705 | startblock = numblocks * (chip + 1) - 1; |
749 | dir = -1; | 706 | dir = -1; |
@@ -767,7 +724,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
767 | if (!md || md->pages[chip] != page) | 724 | if (!md || md->pages[chip] != page) |
768 | goto write; | 725 | goto write; |
769 | } | 726 | } |
770 | printk(KERN_ERR "No space left to write bad block table\n"); | 727 | pr_err("No space left to write bad block table\n"); |
771 | return -ENOSPC; | 728 | return -ENOSPC; |
772 | write: | 729 | write: |
773 | 730 | ||
@@ -792,24 +749,22 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
792 | 749 | ||
793 | bbtoffs = chip * (numblocks >> 2); | 750 | bbtoffs = chip * (numblocks >> 2); |
794 | 751 | ||
795 | to = ((loff_t) page) << this->page_shift; | 752 | to = ((loff_t)page) << this->page_shift; |
796 | 753 | ||
797 | /* Must we save the block contents ? */ | 754 | /* Must we save the block contents? */ |
798 | if (td->options & NAND_BBT_SAVECONTENT) { | 755 | if (td->options & NAND_BBT_SAVECONTENT) { |
799 | /* Make it block aligned */ | 756 | /* Make it block aligned */ |
800 | to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); | 757 | to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1)); |
801 | len = 1 << this->bbt_erase_shift; | 758 | len = 1 << this->bbt_erase_shift; |
802 | res = mtd->read(mtd, to, len, &retlen, buf); | 759 | res = mtd->read(mtd, to, len, &retlen, buf); |
803 | if (res < 0) { | 760 | if (res < 0) { |
804 | if (retlen != len) { | 761 | if (retlen != len) { |
805 | printk(KERN_INFO "nand_bbt: Error " | 762 | pr_info("nand_bbt: error reading block " |
806 | "reading block for writing " | 763 | "for writing the bad block table\n"); |
807 | "the bad block table\n"); | ||
808 | return res; | 764 | return res; |
809 | } | 765 | } |
810 | printk(KERN_WARNING "nand_bbt: ECC error " | 766 | pr_warn("nand_bbt: ECC error while reading " |
811 | "while reading block for writing " | 767 | "block for writing bad block table\n"); |
812 | "bad block table\n"); | ||
813 | } | 768 | } |
814 | /* Read oob data */ | 769 | /* Read oob data */ |
815 | ops.ooblen = (len >> this->page_shift) * mtd->oobsize; | 770 | ops.ooblen = (len >> this->page_shift) * mtd->oobsize; |
@@ -822,19 +777,19 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
822 | pageoffs = page - (int)(to >> this->page_shift); | 777 | pageoffs = page - (int)(to >> this->page_shift); |
823 | offs = pageoffs << this->page_shift; | 778 | offs = pageoffs << this->page_shift; |
824 | /* Preset the bbt area with 0xff */ | 779 | /* Preset the bbt area with 0xff */ |
825 | memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); | 780 | memset(&buf[offs], 0xff, (size_t)(numblocks >> sft)); |
826 | ooboffs = len + (pageoffs * mtd->oobsize); | 781 | ooboffs = len + (pageoffs * mtd->oobsize); |
827 | 782 | ||
828 | } else if (td->options & NAND_BBT_NO_OOB) { | 783 | } else if (td->options & NAND_BBT_NO_OOB) { |
829 | ooboffs = 0; | 784 | ooboffs = 0; |
830 | offs = td->len; | 785 | offs = td->len; |
831 | /* the version byte */ | 786 | /* The version byte */ |
832 | if (td->options & NAND_BBT_VERSION) | 787 | if (td->options & NAND_BBT_VERSION) |
833 | offs++; | 788 | offs++; |
834 | /* Calc length */ | 789 | /* Calc length */ |
835 | len = (size_t) (numblocks >> sft); | 790 | len = (size_t)(numblocks >> sft); |
836 | len += offs; | 791 | len += offs; |
837 | /* Make it page aligned ! */ | 792 | /* Make it page aligned! */ |
838 | len = ALIGN(len, mtd->writesize); | 793 | len = ALIGN(len, mtd->writesize); |
839 | /* Preset the buffer with 0xff */ | 794 | /* Preset the buffer with 0xff */ |
840 | memset(buf, 0xff, len); | 795 | memset(buf, 0xff, len); |
@@ -842,8 +797,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
842 | memcpy(buf, td->pattern, td->len); | 797 | memcpy(buf, td->pattern, td->len); |
843 | } else { | 798 | } else { |
844 | /* Calc length */ | 799 | /* Calc length */ |
845 | len = (size_t) (numblocks >> sft); | 800 | len = (size_t)(numblocks >> sft); |
846 | /* Make it page aligned ! */ | 801 | /* Make it page aligned! */ |
847 | len = ALIGN(len, mtd->writesize); | 802 | len = ALIGN(len, mtd->writesize); |
848 | /* Preset the buffer with 0xff */ | 803 | /* Preset the buffer with 0xff */ |
849 | memset(buf, 0xff, len + | 804 | memset(buf, 0xff, len + |
@@ -857,13 +812,13 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
857 | if (td->options & NAND_BBT_VERSION) | 812 | if (td->options & NAND_BBT_VERSION) |
858 | buf[ooboffs + td->veroffs] = td->version[chip]; | 813 | buf[ooboffs + td->veroffs] = td->version[chip]; |
859 | 814 | ||
860 | /* walk through the memory table */ | 815 | /* Walk through the memory table */ |
861 | for (i = 0; i < numblocks;) { | 816 | for (i = 0; i < numblocks;) { |
862 | uint8_t dat; | 817 | uint8_t dat; |
863 | dat = this->bbt[bbtoffs + (i >> 2)]; | 818 | dat = this->bbt[bbtoffs + (i >> 2)]; |
864 | for (j = 0; j < 4; j++, i++) { | 819 | for (j = 0; j < 4; j++, i++) { |
865 | int sftcnt = (i << (3 - sft)) & sftmsk; | 820 | int sftcnt = (i << (3 - sft)) & sftmsk; |
866 | /* Do not store the reserved bbt blocks ! */ | 821 | /* Do not store the reserved bbt blocks! */ |
867 | buf[offs + (i >> sft)] &= | 822 | buf[offs + (i >> sft)] &= |
868 | ~(msk[dat & 0x03] << sftcnt); | 823 | ~(msk[dat & 0x03] << sftcnt); |
869 | dat >>= 2; | 824 | dat >>= 2; |
@@ -884,8 +839,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
884 | if (res < 0) | 839 | if (res < 0) |
885 | goto outerr; | 840 | goto outerr; |
886 | 841 | ||
887 | printk(KERN_DEBUG "Bad block table written to 0x%012llx, version " | 842 | pr_info("Bad block table written to 0x%012llx, version 0x%02X\n", |
888 | "0x%02X\n", (unsigned long long)to, td->version[chip]); | 843 | (unsigned long long)to, td->version[chip]); |
889 | 844 | ||
890 | /* Mark it as used */ | 845 | /* Mark it as used */ |
891 | td->pages[chip] = page; | 846 | td->pages[chip] = page; |
@@ -893,19 +848,18 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
893 | return 0; | 848 | return 0; |
894 | 849 | ||
895 | outerr: | 850 | outerr: |
896 | printk(KERN_WARNING | 851 | pr_warn("nand_bbt: error while writing bad block table %d\n", res); |
897 | "nand_bbt: Error while writing bad block table %d\n", res); | ||
898 | return res; | 852 | return res; |
899 | } | 853 | } |
900 | 854 | ||
901 | /** | 855 | /** |
902 | * nand_memory_bbt - [GENERIC] create a memory based bad block table | 856 | * nand_memory_bbt - [GENERIC] create a memory based bad block table |
903 | * @mtd: MTD device structure | 857 | * @mtd: MTD device structure |
904 | * @bd: descriptor for the good/bad block search pattern | 858 | * @bd: descriptor for the good/bad block search pattern |
905 | * | 859 | * |
906 | * The function creates a memory based bbt by scanning the device | 860 | * The function creates a memory based bbt by scanning the device for |
907 | * for manufacturer / software marked good / bad blocks | 861 | * manufacturer / software marked good / bad blocks. |
908 | */ | 862 | */ |
909 | static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | 863 | static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) |
910 | { | 864 | { |
911 | struct nand_chip *this = mtd->priv; | 865 | struct nand_chip *this = mtd->priv; |
@@ -916,25 +870,24 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b | |||
916 | 870 | ||
917 | /** | 871 | /** |
918 | * check_create - [GENERIC] create and write bbt(s) if necessary | 872 | * check_create - [GENERIC] create and write bbt(s) if necessary |
919 | * @mtd: MTD device structure | 873 | * @mtd: MTD device structure |
920 | * @buf: temporary buffer | 874 | * @buf: temporary buffer |
921 | * @bd: descriptor for the good/bad block search pattern | 875 | * @bd: descriptor for the good/bad block search pattern |
922 | * | 876 | * |
923 | * The function checks the results of the previous call to read_bbt | 877 | * The function checks the results of the previous call to read_bbt and creates |
924 | * and creates / updates the bbt(s) if necessary | 878 | * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found |
925 | * Creation is necessary if no bbt was found for the chip/device | 879 | * for the chip/device. Update is necessary if one of the tables is missing or |
926 | * Update is necessary if one of the tables is missing or the | 880 | * the version nr. of one table is less than the other. |
927 | * version nr. of one table is less than the other | 881 | */ |
928 | */ | ||
929 | static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) | 882 | static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) |
930 | { | 883 | { |
931 | int i, chips, writeops, chipsel, res; | 884 | int i, chips, writeops, create, chipsel, res, res2; |
932 | struct nand_chip *this = mtd->priv; | 885 | struct nand_chip *this = mtd->priv; |
933 | struct nand_bbt_descr *td = this->bbt_td; | 886 | struct nand_bbt_descr *td = this->bbt_td; |
934 | struct nand_bbt_descr *md = this->bbt_md; | 887 | struct nand_bbt_descr *md = this->bbt_md; |
935 | struct nand_bbt_descr *rd, *rd2; | 888 | struct nand_bbt_descr *rd, *rd2; |
936 | 889 | ||
937 | /* Do we have a bbt per chip ? */ | 890 | /* Do we have a bbt per chip? */ |
938 | if (td->options & NAND_BBT_PERCHIP) | 891 | if (td->options & NAND_BBT_PERCHIP) |
939 | chips = this->numchips; | 892 | chips = this->numchips; |
940 | else | 893 | else |
@@ -942,86 +895,98 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
942 | 895 | ||
943 | for (i = 0; i < chips; i++) { | 896 | for (i = 0; i < chips; i++) { |
944 | writeops = 0; | 897 | writeops = 0; |
898 | create = 0; | ||
945 | rd = NULL; | 899 | rd = NULL; |
946 | rd2 = NULL; | 900 | rd2 = NULL; |
947 | /* Per chip or per device ? */ | 901 | res = res2 = 0; |
902 | /* Per chip or per device? */ | ||
948 | chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; | 903 | chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; |
949 | /* Mirrored table available ? */ | 904 | /* Mirrored table available? */ |
950 | if (md) { | 905 | if (md) { |
951 | if (td->pages[i] == -1 && md->pages[i] == -1) { | 906 | if (td->pages[i] == -1 && md->pages[i] == -1) { |
907 | create = 1; | ||
952 | writeops = 0x03; | 908 | writeops = 0x03; |
953 | goto create; | 909 | } else if (td->pages[i] == -1) { |
954 | } | ||
955 | |||
956 | if (td->pages[i] == -1) { | ||
957 | rd = md; | 910 | rd = md; |
958 | td->version[i] = md->version[i]; | 911 | writeops = 0x01; |
959 | writeops = 1; | 912 | } else if (md->pages[i] == -1) { |
960 | goto writecheck; | ||
961 | } | ||
962 | |||
963 | if (md->pages[i] == -1) { | ||
964 | rd = td; | 913 | rd = td; |
965 | md->version[i] = td->version[i]; | 914 | writeops = 0x02; |
966 | writeops = 2; | 915 | } else if (td->version[i] == md->version[i]) { |
967 | goto writecheck; | ||
968 | } | ||
969 | |||
970 | if (td->version[i] == md->version[i]) { | ||
971 | rd = td; | 916 | rd = td; |
972 | if (!(td->options & NAND_BBT_VERSION)) | 917 | if (!(td->options & NAND_BBT_VERSION)) |
973 | rd2 = md; | 918 | rd2 = md; |
974 | goto writecheck; | 919 | } else if (((int8_t)(td->version[i] - md->version[i])) > 0) { |
975 | } | ||
976 | |||
977 | if (((int8_t) (td->version[i] - md->version[i])) > 0) { | ||
978 | rd = td; | 920 | rd = td; |
979 | md->version[i] = td->version[i]; | 921 | writeops = 0x02; |
980 | writeops = 2; | ||
981 | } else { | 922 | } else { |
982 | rd = md; | 923 | rd = md; |
983 | td->version[i] = md->version[i]; | 924 | writeops = 0x01; |
984 | writeops = 1; | ||
985 | } | 925 | } |
986 | |||
987 | goto writecheck; | ||
988 | |||
989 | } else { | 926 | } else { |
990 | if (td->pages[i] == -1) { | 927 | if (td->pages[i] == -1) { |
928 | create = 1; | ||
991 | writeops = 0x01; | 929 | writeops = 0x01; |
992 | goto create; | 930 | } else { |
931 | rd = td; | ||
993 | } | 932 | } |
994 | rd = td; | ||
995 | goto writecheck; | ||
996 | } | 933 | } |
997 | create: | ||
998 | /* Create the bad block table by scanning the device ? */ | ||
999 | if (!(td->options & NAND_BBT_CREATE)) | ||
1000 | continue; | ||
1001 | 934 | ||
1002 | /* Create the table in memory by scanning the chip(s) */ | 935 | if (create) { |
1003 | if (!(this->options & NAND_CREATE_EMPTY_BBT)) | 936 | /* Create the bad block table by scanning the device? */ |
1004 | create_bbt(mtd, buf, bd, chipsel); | 937 | if (!(td->options & NAND_BBT_CREATE)) |
1005 | 938 | continue; | |
1006 | td->version[i] = 1; | 939 | |
1007 | if (md) | 940 | /* Create the table in memory by scanning the chip(s) */ |
1008 | md->version[i] = 1; | 941 | if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY)) |
1009 | writecheck: | 942 | create_bbt(mtd, buf, bd, chipsel); |
1010 | /* read back first ? */ | 943 | |
1011 | if (rd) | 944 | td->version[i] = 1; |
1012 | read_abs_bbt(mtd, buf, rd, chipsel); | 945 | if (md) |
1013 | /* If they weren't versioned, read both. */ | 946 | md->version[i] = 1; |
1014 | if (rd2) | 947 | } |
1015 | read_abs_bbt(mtd, buf, rd2, chipsel); | 948 | |
1016 | 949 | /* Read back first? */ | |
1017 | /* Write the bad block table to the device ? */ | 950 | if (rd) { |
951 | res = read_abs_bbt(mtd, buf, rd, chipsel); | ||
952 | if (mtd_is_eccerr(res)) { | ||
953 | /* Mark table as invalid */ | ||
954 | rd->pages[i] = -1; | ||
955 | rd->version[i] = 0; | ||
956 | i--; | ||
957 | continue; | ||
958 | } | ||
959 | } | ||
960 | /* If they weren't versioned, read both */ | ||
961 | if (rd2) { | ||
962 | res2 = read_abs_bbt(mtd, buf, rd2, chipsel); | ||
963 | if (mtd_is_eccerr(res2)) { | ||
964 | /* Mark table as invalid */ | ||
965 | rd2->pages[i] = -1; | ||
966 | rd2->version[i] = 0; | ||
967 | i--; | ||
968 | continue; | ||
969 | } | ||
970 | } | ||
971 | |||
972 | /* Scrub the flash table(s)? */ | ||
973 | if (mtd_is_bitflip(res) || mtd_is_bitflip(res2)) | ||
974 | writeops = 0x03; | ||
975 | |||
976 | /* Update version numbers before writing */ | ||
977 | if (md) { | ||
978 | td->version[i] = max(td->version[i], md->version[i]); | ||
979 | md->version[i] = td->version[i]; | ||
980 | } | ||
981 | |||
982 | /* Write the bad block table to the device? */ | ||
1018 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | 983 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { |
1019 | res = write_bbt(mtd, buf, td, md, chipsel); | 984 | res = write_bbt(mtd, buf, td, md, chipsel); |
1020 | if (res < 0) | 985 | if (res < 0) |
1021 | return res; | 986 | return res; |
1022 | } | 987 | } |
1023 | 988 | ||
1024 | /* Write the mirror bad block table to the device ? */ | 989 | /* Write the mirror bad block table to the device? */ |
1025 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { | 990 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { |
1026 | res = write_bbt(mtd, buf, md, td, chipsel); | 991 | res = write_bbt(mtd, buf, md, td, chipsel); |
1027 | if (res < 0) | 992 | if (res < 0) |
@@ -1033,20 +998,19 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
1033 | 998 | ||
1034 | /** | 999 | /** |
1035 | * mark_bbt_regions - [GENERIC] mark the bad block table regions | 1000 | * mark_bbt_regions - [GENERIC] mark the bad block table regions |
1036 | * @mtd: MTD device structure | 1001 | * @mtd: MTD device structure |
1037 | * @td: bad block table descriptor | 1002 | * @td: bad block table descriptor |
1038 | * | 1003 | * |
1039 | * The bad block table regions are marked as "bad" to prevent | 1004 | * The bad block table regions are marked as "bad" to prevent accidental |
1040 | * accidental erasures / writes. The regions are identified by | 1005 | * erasures / writes. The regions are identified by the mark 0x02. |
1041 | * the mark 0x02. | 1006 | */ |
1042 | */ | ||
1043 | static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | 1007 | static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) |
1044 | { | 1008 | { |
1045 | struct nand_chip *this = mtd->priv; | 1009 | struct nand_chip *this = mtd->priv; |
1046 | int i, j, chips, block, nrblocks, update; | 1010 | int i, j, chips, block, nrblocks, update; |
1047 | uint8_t oldval, newval; | 1011 | uint8_t oldval, newval; |
1048 | 1012 | ||
1049 | /* Do we have a bbt per chip ? */ | 1013 | /* Do we have a bbt per chip? */ |
1050 | if (td->options & NAND_BBT_PERCHIP) { | 1014 | if (td->options & NAND_BBT_PERCHIP) { |
1051 | chips = this->numchips; | 1015 | chips = this->numchips; |
1052 | nrblocks = (int)(this->chipsize >> this->bbt_erase_shift); | 1016 | nrblocks = (int)(this->chipsize >> this->bbt_erase_shift); |
@@ -1083,9 +1047,11 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
1083 | update = 1; | 1047 | update = 1; |
1084 | block += 2; | 1048 | block += 2; |
1085 | } | 1049 | } |
1086 | /* If we want reserved blocks to be recorded to flash, and some | 1050 | /* |
1087 | new ones have been marked, then we need to update the stored | 1051 | * If we want reserved blocks to be recorded to flash, and some |
1088 | bbts. This should only happen once. */ | 1052 | * new ones have been marked, then we need to update the stored |
1053 | * bbts. This should only happen once. | ||
1054 | */ | ||
1089 | if (update && td->reserved_block_code) | 1055 | if (update && td->reserved_block_code) |
1090 | nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); | 1056 | nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); |
1091 | } | 1057 | } |
@@ -1093,8 +1059,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
1093 | 1059 | ||
1094 | /** | 1060 | /** |
1095 | * verify_bbt_descr - verify the bad block description | 1061 | * verify_bbt_descr - verify the bad block description |
1096 | * @mtd: MTD device structure | 1062 | * @mtd: MTD device structure |
1097 | * @bd: the table to verify | 1063 | * @bd: the table to verify |
1098 | * | 1064 | * |
1099 | * This functions performs a few sanity checks on the bad block description | 1065 | * This functions performs a few sanity checks on the bad block description |
1100 | * table. | 1066 | * table. |
@@ -1112,16 +1078,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1112 | pattern_len = bd->len; | 1078 | pattern_len = bd->len; |
1113 | bits = bd->options & NAND_BBT_NRBITS_MSK; | 1079 | bits = bd->options & NAND_BBT_NRBITS_MSK; |
1114 | 1080 | ||
1115 | BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) && | 1081 | BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) && |
1116 | !(this->options & NAND_USE_FLASH_BBT)); | 1082 | !(this->bbt_options & NAND_BBT_USE_FLASH)); |
1117 | BUG_ON(!bits); | 1083 | BUG_ON(!bits); |
1118 | 1084 | ||
1119 | if (bd->options & NAND_BBT_VERSION) | 1085 | if (bd->options & NAND_BBT_VERSION) |
1120 | pattern_len++; | 1086 | pattern_len++; |
1121 | 1087 | ||
1122 | if (bd->options & NAND_BBT_NO_OOB) { | 1088 | if (bd->options & NAND_BBT_NO_OOB) { |
1123 | BUG_ON(!(this->options & NAND_USE_FLASH_BBT)); | 1089 | BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH)); |
1124 | BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB)); | 1090 | BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB)); |
1125 | BUG_ON(bd->offs); | 1091 | BUG_ON(bd->offs); |
1126 | if (bd->options & NAND_BBT_VERSION) | 1092 | if (bd->options & NAND_BBT_VERSION) |
1127 | BUG_ON(bd->veroffs != bd->len); | 1093 | BUG_ON(bd->veroffs != bd->len); |
@@ -1141,18 +1107,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1141 | 1107 | ||
1142 | /** | 1108 | /** |
1143 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) | 1109 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) |
1144 | * @mtd: MTD device structure | 1110 | * @mtd: MTD device structure |
1145 | * @bd: descriptor for the good/bad block search pattern | 1111 | * @bd: descriptor for the good/bad block search pattern |
1146 | * | ||
1147 | * The function checks, if a bad block table(s) is/are already | ||
1148 | * available. If not it scans the device for manufacturer | ||
1149 | * marked good / bad blocks and writes the bad block table(s) to | ||
1150 | * the selected place. | ||
1151 | * | 1112 | * |
1152 | * The bad block table memory is allocated here. It must be freed | 1113 | * The function checks, if a bad block table(s) is/are already available. If |
1153 | * by calling the nand_free_bbt function. | 1114 | * not it scans the device for manufacturer marked good / bad blocks and writes |
1115 | * the bad block table(s) to the selected place. | ||
1154 | * | 1116 | * |
1155 | */ | 1117 | * The bad block table memory is allocated here. It must be freed by calling |
1118 | * the nand_free_bbt function. | ||
1119 | */ | ||
1156 | int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | 1120 | int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) |
1157 | { | 1121 | { |
1158 | struct nand_chip *this = mtd->priv; | 1122 | struct nand_chip *this = mtd->priv; |
@@ -1162,19 +1126,21 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1162 | struct nand_bbt_descr *md = this->bbt_md; | 1126 | struct nand_bbt_descr *md = this->bbt_md; |
1163 | 1127 | ||
1164 | len = mtd->size >> (this->bbt_erase_shift + 2); | 1128 | len = mtd->size >> (this->bbt_erase_shift + 2); |
1165 | /* Allocate memory (2bit per block) and clear the memory bad block table */ | 1129 | /* |
1130 | * Allocate memory (2bit per block) and clear the memory bad block | ||
1131 | * table. | ||
1132 | */ | ||
1166 | this->bbt = kzalloc(len, GFP_KERNEL); | 1133 | this->bbt = kzalloc(len, GFP_KERNEL); |
1167 | if (!this->bbt) { | 1134 | if (!this->bbt) |
1168 | printk(KERN_ERR "nand_scan_bbt: Out of memory\n"); | ||
1169 | return -ENOMEM; | 1135 | return -ENOMEM; |
1170 | } | ||
1171 | 1136 | ||
1172 | /* If no primary table decriptor is given, scan the device | 1137 | /* |
1173 | * to build a memory based bad block table | 1138 | * If no primary table decriptor is given, scan the device to build a |
1139 | * memory based bad block table. | ||
1174 | */ | 1140 | */ |
1175 | if (!td) { | 1141 | if (!td) { |
1176 | if ((res = nand_memory_bbt(mtd, bd))) { | 1142 | if ((res = nand_memory_bbt(mtd, bd))) { |
1177 | printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n"); | 1143 | pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); |
1178 | kfree(this->bbt); | 1144 | kfree(this->bbt); |
1179 | this->bbt = NULL; | 1145 | this->bbt = NULL; |
1180 | } | 1146 | } |
@@ -1188,13 +1154,12 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1188 | len += (len >> this->page_shift) * mtd->oobsize; | 1154 | len += (len >> this->page_shift) * mtd->oobsize; |
1189 | buf = vmalloc(len); | 1155 | buf = vmalloc(len); |
1190 | if (!buf) { | 1156 | if (!buf) { |
1191 | printk(KERN_ERR "nand_bbt: Out of memory\n"); | ||
1192 | kfree(this->bbt); | 1157 | kfree(this->bbt); |
1193 | this->bbt = NULL; | 1158 | this->bbt = NULL; |
1194 | return -ENOMEM; | 1159 | return -ENOMEM; |
1195 | } | 1160 | } |
1196 | 1161 | ||
1197 | /* Is the bbt at a given page ? */ | 1162 | /* Is the bbt at a given page? */ |
1198 | if (td->options & NAND_BBT_ABSPAGE) { | 1163 | if (td->options & NAND_BBT_ABSPAGE) { |
1199 | res = read_abs_bbts(mtd, buf, td, md); | 1164 | res = read_abs_bbts(mtd, buf, td, md); |
1200 | } else { | 1165 | } else { |
@@ -1216,15 +1181,15 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1216 | 1181 | ||
1217 | /** | 1182 | /** |
1218 | * nand_update_bbt - [NAND Interface] update bad block table(s) | 1183 | * nand_update_bbt - [NAND Interface] update bad block table(s) |
1219 | * @mtd: MTD device structure | 1184 | * @mtd: MTD device structure |
1220 | * @offs: the offset of the newly marked block | 1185 | * @offs: the offset of the newly marked block |
1221 | * | 1186 | * |
1222 | * The function updates the bad block table(s) | 1187 | * The function updates the bad block table(s). |
1223 | */ | 1188 | */ |
1224 | int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | 1189 | int nand_update_bbt(struct mtd_info *mtd, loff_t offs) |
1225 | { | 1190 | { |
1226 | struct nand_chip *this = mtd->priv; | 1191 | struct nand_chip *this = mtd->priv; |
1227 | int len, res = 0, writeops = 0; | 1192 | int len, res = 0; |
1228 | int chip, chipsel; | 1193 | int chip, chipsel; |
1229 | uint8_t *buf; | 1194 | uint8_t *buf; |
1230 | struct nand_bbt_descr *td = this->bbt_td; | 1195 | struct nand_bbt_descr *td = this->bbt_td; |
@@ -1237,14 +1202,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1237 | len = (1 << this->bbt_erase_shift); | 1202 | len = (1 << this->bbt_erase_shift); |
1238 | len += (len >> this->page_shift) * mtd->oobsize; | 1203 | len += (len >> this->page_shift) * mtd->oobsize; |
1239 | buf = kmalloc(len, GFP_KERNEL); | 1204 | buf = kmalloc(len, GFP_KERNEL); |
1240 | if (!buf) { | 1205 | if (!buf) |
1241 | printk(KERN_ERR "nand_update_bbt: Out of memory\n"); | ||
1242 | return -ENOMEM; | 1206 | return -ENOMEM; |
1243 | } | ||
1244 | |||
1245 | writeops = md != NULL ? 0x03 : 0x01; | ||
1246 | 1207 | ||
1247 | /* Do we have a bbt per chip ? */ | 1208 | /* Do we have a bbt per chip? */ |
1248 | if (td->options & NAND_BBT_PERCHIP) { | 1209 | if (td->options & NAND_BBT_PERCHIP) { |
1249 | chip = (int)(offs >> this->chip_shift); | 1210 | chip = (int)(offs >> this->chip_shift); |
1250 | chipsel = chip; | 1211 | chipsel = chip; |
@@ -1257,14 +1218,14 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1257 | if (md) | 1218 | if (md) |
1258 | md->version[chip]++; | 1219 | md->version[chip]++; |
1259 | 1220 | ||
1260 | /* Write the bad block table to the device ? */ | 1221 | /* Write the bad block table to the device? */ |
1261 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | 1222 | if (td->options & NAND_BBT_WRITE) { |
1262 | res = write_bbt(mtd, buf, td, md, chipsel); | 1223 | res = write_bbt(mtd, buf, td, md, chipsel); |
1263 | if (res < 0) | 1224 | if (res < 0) |
1264 | goto out; | 1225 | goto out; |
1265 | } | 1226 | } |
1266 | /* Write the mirror bad block table to the device ? */ | 1227 | /* Write the mirror bad block table to the device? */ |
1267 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { | 1228 | if (md && (md->options & NAND_BBT_WRITE)) { |
1268 | res = write_bbt(mtd, buf, md, td, chipsel); | 1229 | res = write_bbt(mtd, buf, md, td, chipsel); |
1269 | } | 1230 | } |
1270 | 1231 | ||
@@ -1273,8 +1234,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1273 | return res; | 1234 | return res; |
1274 | } | 1235 | } |
1275 | 1236 | ||
1276 | /* Define some generic bad / good block scan pattern which are used | 1237 | /* |
1277 | * while scanning a device for factory marked good / bad blocks. */ | 1238 | * Define some generic bad / good block scan pattern which are used |
1239 | * while scanning a device for factory marked good / bad blocks. | ||
1240 | */ | ||
1278 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 1241 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
1279 | 1242 | ||
1280 | static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; | 1243 | static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; |
@@ -1286,8 +1249,7 @@ static struct nand_bbt_descr agand_flashbased = { | |||
1286 | .pattern = scan_agand_pattern | 1249 | .pattern = scan_agand_pattern |
1287 | }; | 1250 | }; |
1288 | 1251 | ||
1289 | /* Generic flash bbt decriptors | 1252 | /* Generic flash bbt descriptors */ |
1290 | */ | ||
1291 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | 1253 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; |
1292 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; | 1254 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; |
1293 | 1255 | ||
@@ -1331,31 +1293,27 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { | |||
1331 | .pattern = mirror_pattern | 1293 | .pattern = mirror_pattern |
1332 | }; | 1294 | }; |
1333 | 1295 | ||
1334 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ | 1296 | #define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB) |
1335 | NAND_BBT_SCANBYTE1AND6) | ||
1336 | /** | 1297 | /** |
1337 | * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure | 1298 | * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure |
1338 | * @this: NAND chip to create descriptor for | 1299 | * @this: NAND chip to create descriptor for |
1339 | * | 1300 | * |
1340 | * This function allocates and initializes a nand_bbt_descr for BBM detection | 1301 | * This function allocates and initializes a nand_bbt_descr for BBM detection |
1341 | * based on the properties of "this". The new descriptor is stored in | 1302 | * based on the properties of @this. The new descriptor is stored in |
1342 | * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when | 1303 | * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when |
1343 | * passed to this function. | 1304 | * passed to this function. |
1344 | * | ||
1345 | */ | 1305 | */ |
1346 | static int nand_create_default_bbt_descr(struct nand_chip *this) | 1306 | static int nand_create_badblock_pattern(struct nand_chip *this) |
1347 | { | 1307 | { |
1348 | struct nand_bbt_descr *bd; | 1308 | struct nand_bbt_descr *bd; |
1349 | if (this->badblock_pattern) { | 1309 | if (this->badblock_pattern) { |
1350 | printk(KERN_WARNING "BBT descr already allocated; not replacing.\n"); | 1310 | pr_warn("Bad block pattern already allocated; not replacing\n"); |
1351 | return -EINVAL; | 1311 | return -EINVAL; |
1352 | } | 1312 | } |
1353 | bd = kzalloc(sizeof(*bd), GFP_KERNEL); | 1313 | bd = kzalloc(sizeof(*bd), GFP_KERNEL); |
1354 | if (!bd) { | 1314 | if (!bd) |
1355 | printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n"); | ||
1356 | return -ENOMEM; | 1315 | return -ENOMEM; |
1357 | } | 1316 | bd->options = this->bbt_options & BADBLOCK_SCAN_MASK; |
1358 | bd->options = this->options & BBT_SCAN_OPTIONS; | ||
1359 | bd->offs = this->badblockpos; | 1317 | bd->offs = this->badblockpos; |
1360 | bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1318 | bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1361 | bd->pattern = scan_ff_pattern; | 1319 | bd->pattern = scan_ff_pattern; |
@@ -1366,22 +1324,20 @@ static int nand_create_default_bbt_descr(struct nand_chip *this) | |||
1366 | 1324 | ||
1367 | /** | 1325 | /** |
1368 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device | 1326 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device |
1369 | * @mtd: MTD device structure | 1327 | * @mtd: MTD device structure |
1370 | * | ||
1371 | * This function selects the default bad block table | ||
1372 | * support for the device and calls the nand_scan_bbt function | ||
1373 | * | 1328 | * |
1374 | */ | 1329 | * This function selects the default bad block table support for the device and |
1330 | * calls the nand_scan_bbt function. | ||
1331 | */ | ||
1375 | int nand_default_bbt(struct mtd_info *mtd) | 1332 | int nand_default_bbt(struct mtd_info *mtd) |
1376 | { | 1333 | { |
1377 | struct nand_chip *this = mtd->priv; | 1334 | struct nand_chip *this = mtd->priv; |
1378 | 1335 | ||
1379 | /* Default for AG-AND. We must use a flash based | 1336 | /* |
1380 | * bad block table as the devices have factory marked | 1337 | * Default for AG-AND. We must use a flash based bad block table as the |
1381 | * _good_ blocks. Erasing those blocks leads to loss | 1338 | * devices have factory marked _good_ blocks. Erasing those blocks |
1382 | * of the good / bad information, so we _must_ store | 1339 | * leads to loss of the good / bad information, so we _must_ store this |
1383 | * this information in a good / bad table during | 1340 | * information in a good / bad table during startup. |
1384 | * startup | ||
1385 | */ | 1341 | */ |
1386 | if (this->options & NAND_IS_AND) { | 1342 | if (this->options & NAND_IS_AND) { |
1387 | /* Use the default pattern descriptors */ | 1343 | /* Use the default pattern descriptors */ |
@@ -1389,15 +1345,15 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1389 | this->bbt_td = &bbt_main_descr; | 1345 | this->bbt_td = &bbt_main_descr; |
1390 | this->bbt_md = &bbt_mirror_descr; | 1346 | this->bbt_md = &bbt_mirror_descr; |
1391 | } | 1347 | } |
1392 | this->options |= NAND_USE_FLASH_BBT; | 1348 | this->bbt_options |= NAND_BBT_USE_FLASH; |
1393 | return nand_scan_bbt(mtd, &agand_flashbased); | 1349 | return nand_scan_bbt(mtd, &agand_flashbased); |
1394 | } | 1350 | } |
1395 | 1351 | ||
1396 | /* Is a flash based bad block table requested ? */ | 1352 | /* Is a flash based bad block table requested? */ |
1397 | if (this->options & NAND_USE_FLASH_BBT) { | 1353 | if (this->bbt_options & NAND_BBT_USE_FLASH) { |
1398 | /* Use the default pattern descriptors */ | 1354 | /* Use the default pattern descriptors */ |
1399 | if (!this->bbt_td) { | 1355 | if (!this->bbt_td) { |
1400 | if (this->options & NAND_USE_FLASH_BBT_NO_OOB) { | 1356 | if (this->bbt_options & NAND_BBT_NO_OOB) { |
1401 | this->bbt_td = &bbt_main_no_bbt_descr; | 1357 | this->bbt_td = &bbt_main_no_bbt_descr; |
1402 | this->bbt_md = &bbt_mirror_no_bbt_descr; | 1358 | this->bbt_md = &bbt_mirror_no_bbt_descr; |
1403 | } else { | 1359 | } else { |
@@ -1411,18 +1367,17 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1411 | } | 1367 | } |
1412 | 1368 | ||
1413 | if (!this->badblock_pattern) | 1369 | if (!this->badblock_pattern) |
1414 | nand_create_default_bbt_descr(this); | 1370 | nand_create_badblock_pattern(this); |
1415 | 1371 | ||
1416 | return nand_scan_bbt(mtd, this->badblock_pattern); | 1372 | return nand_scan_bbt(mtd, this->badblock_pattern); |
1417 | } | 1373 | } |
1418 | 1374 | ||
1419 | /** | 1375 | /** |
1420 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad | 1376 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad |
1421 | * @mtd: MTD device structure | 1377 | * @mtd: MTD device structure |
1422 | * @offs: offset in the device | 1378 | * @offs: offset in the device |
1423 | * @allowbbt: allow access to bad block table region | 1379 | * @allowbbt: allow access to bad block table region |
1424 | * | 1380 | */ |
1425 | */ | ||
1426 | int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) | 1381 | int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) |
1427 | { | 1382 | { |
1428 | struct nand_chip *this = mtd->priv; | 1383 | struct nand_chip *this = mtd->priv; |
@@ -1433,8 +1388,9 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) | |||
1433 | block = (int)(offs >> (this->bbt_erase_shift - 1)); | 1388 | block = (int)(offs >> (this->bbt_erase_shift - 1)); |
1434 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; | 1389 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; |
1435 | 1390 | ||
1436 | DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", | 1391 | pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: " |
1437 | (unsigned int)offs, block >> 1, res); | 1392 | "(block %d) 0x%02x\n", |
1393 | (unsigned int)offs, block >> 1, res); | ||
1438 | 1394 | ||
1439 | switch ((int)res) { | 1395 | switch ((int)res) { |
1440 | case 0x00: | 1396 | case 0x00: |
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index 0f931e757116..3803e0bba23b 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c | |||
@@ -93,8 +93,8 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, | |||
93 | buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7)); | 93 | buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7)); |
94 | /* else error in ecc, no action needed */ | 94 | /* else error in ecc, no action needed */ |
95 | 95 | ||
96 | DEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n", | 96 | pr_debug("%s: corrected bitflip %u\n", __func__, |
97 | __func__, errloc[i]); | 97 | errloc[i]); |
98 | } | 98 | } |
99 | } else if (count < 0) { | 99 | } else if (count < 0) { |
100 | printk(KERN_ERR "ecc unrecoverable error\n"); | 100 | printk(KERN_ERR "ecc unrecoverable error\n"); |
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 271b8e735e8f..b7cfe0d37121 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c | |||
@@ -110,7 +110,7 @@ static const char bitsperbyte[256] = { | |||
110 | 110 | ||
111 | /* | 111 | /* |
112 | * addressbits is a lookup table to filter out the bits from the xor-ed | 112 | * addressbits is a lookup table to filter out the bits from the xor-ed |
113 | * ecc data that identify the faulty location. | 113 | * ECC data that identify the faulty location. |
114 | * this is only used for repairing parity | 114 | * this is only used for repairing parity |
115 | * see the comments in nand_correct_data for more details | 115 | * see the comments in nand_correct_data for more details |
116 | */ | 116 | */ |
@@ -153,7 +153,7 @@ static const char addressbits[256] = { | |||
153 | * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte | 153 | * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte |
154 | * block | 154 | * block |
155 | * @buf: input buffer with raw data | 155 | * @buf: input buffer with raw data |
156 | * @eccsize: data bytes per ecc step (256 or 512) | 156 | * @eccsize: data bytes per ECC step (256 or 512) |
157 | * @code: output buffer with ECC | 157 | * @code: output buffer with ECC |
158 | */ | 158 | */ |
159 | void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, | 159 | void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, |
@@ -348,7 +348,7 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, | |||
348 | rp17 = (par ^ rp16) & 0xff; | 348 | rp17 = (par ^ rp16) & 0xff; |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * Finally calculate the ecc bits. | 351 | * Finally calculate the ECC bits. |
352 | * Again here it might seem that there are performance optimisations | 352 | * Again here it might seem that there are performance optimisations |
353 | * possible, but benchmarks showed that on the system this is developed | 353 | * possible, but benchmarks showed that on the system this is developed |
354 | * the code below is the fastest | 354 | * the code below is the fastest |
@@ -436,7 +436,7 @@ EXPORT_SYMBOL(nand_calculate_ecc); | |||
436 | * @buf: raw data read from the chip | 436 | * @buf: raw data read from the chip |
437 | * @read_ecc: ECC from the chip | 437 | * @read_ecc: ECC from the chip |
438 | * @calc_ecc: the ECC calculated from raw data | 438 | * @calc_ecc: the ECC calculated from raw data |
439 | * @eccsize: data bytes per ecc step (256 or 512) | 439 | * @eccsize: data bytes per ECC step (256 or 512) |
440 | * | 440 | * |
441 | * Detect and correct a 1 bit error for eccsize byte block | 441 | * Detect and correct a 1 bit error for eccsize byte block |
442 | */ | 442 | */ |
@@ -505,7 +505,7 @@ int __nand_correct_data(unsigned char *buf, | |||
505 | } | 505 | } |
506 | /* count nr of bits; use table lookup, faster than calculating it */ | 506 | /* count nr of bits; use table lookup, faster than calculating it */ |
507 | if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1) | 507 | if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1) |
508 | return 1; /* error in ecc data; no action needed */ | 508 | return 1; /* error in ECC data; no action needed */ |
509 | 509 | ||
510 | printk(KERN_ERR "uncorrectable error : "); | 510 | printk(KERN_ERR "uncorrectable error : "); |
511 | return -1; | 511 | return -1; |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 357e8c5252a8..34c03be77301 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -2273,9 +2273,9 @@ static int __init ns_init_module(void) | |||
2273 | 2273 | ||
2274 | switch (bbt) { | 2274 | switch (bbt) { |
2275 | case 2: | 2275 | case 2: |
2276 | chip->options |= NAND_USE_FLASH_BBT_NO_OOB; | 2276 | chip->bbt_options |= NAND_BBT_NO_OOB; |
2277 | case 1: | 2277 | case 1: |
2278 | chip->options |= NAND_USE_FLASH_BBT; | 2278 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
2279 | case 0: | 2279 | case 0: |
2280 | break; | 2280 | break; |
2281 | default: | 2281 | default: |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index ea2dea8a9c88..ee1713907b92 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -42,7 +42,6 @@ struct ndfc_controller { | |||
42 | struct nand_chip chip; | 42 | struct nand_chip chip; |
43 | int chip_select; | 43 | int chip_select; |
44 | struct nand_hw_control ndfc_control; | 44 | struct nand_hw_control ndfc_control; |
45 | struct mtd_partition *parts; | ||
46 | }; | 45 | }; |
47 | 46 | ||
48 | static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; | 47 | static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; |
@@ -159,13 +158,9 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
159 | static int ndfc_chip_init(struct ndfc_controller *ndfc, | 158 | static int ndfc_chip_init(struct ndfc_controller *ndfc, |
160 | struct device_node *node) | 159 | struct device_node *node) |
161 | { | 160 | { |
162 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
163 | static const char *part_types[] = { "cmdlinepart", NULL }; | ||
164 | #else | ||
165 | static const char *part_types[] = { NULL }; | ||
166 | #endif | ||
167 | struct device_node *flash_np; | 161 | struct device_node *flash_np; |
168 | struct nand_chip *chip = &ndfc->chip; | 162 | struct nand_chip *chip = &ndfc->chip; |
163 | struct mtd_part_parser_data ppdata; | ||
169 | int ret; | 164 | int ret; |
170 | 165 | ||
171 | chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; | 166 | chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; |
@@ -193,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, | |||
193 | if (!flash_np) | 188 | if (!flash_np) |
194 | return -ENODEV; | 189 | return -ENODEV; |
195 | 190 | ||
191 | ppdata->of_node = flash_np; | ||
196 | ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", | 192 | ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", |
197 | dev_name(&ndfc->ofdev->dev), flash_np->name); | 193 | dev_name(&ndfc->ofdev->dev), flash_np->name); |
198 | if (!ndfc->mtd.name) { | 194 | if (!ndfc->mtd.name) { |
@@ -204,18 +200,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, | |||
204 | if (ret) | 200 | if (ret) |
205 | goto err; | 201 | goto err; |
206 | 202 | ||
207 | ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0); | 203 | ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0); |
208 | if (ret < 0) | ||
209 | goto err; | ||
210 | |||
211 | if (ret == 0) { | ||
212 | ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np, | ||
213 | &ndfc->parts); | ||
214 | if (ret < 0) | ||
215 | goto err; | ||
216 | } | ||
217 | |||
218 | ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret); | ||
219 | 204 | ||
220 | err: | 205 | err: |
221 | of_node_put(flash_np); | 206 | of_node_put(flash_np); |
@@ -288,6 +273,7 @@ static int __devexit ndfc_remove(struct platform_device *ofdev) | |||
288 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); | 273 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); |
289 | 274 | ||
290 | nand_release(&ndfc->mtd); | 275 | nand_release(&ndfc->mtd); |
276 | kfree(ndfc->mtd.name); | ||
291 | 277 | ||
292 | return 0; | 278 | return 0; |
293 | } | 279 | } |
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c index b6a5c86ab31e..b463ecfb4c1a 100644 --- a/drivers/mtd/nand/nomadik_nand.c +++ b/drivers/mtd/nand/nomadik_nand.c | |||
@@ -187,6 +187,7 @@ static int nomadik_nand_remove(struct platform_device *pdev) | |||
187 | pdata->exit(); | 187 | pdata->exit(); |
188 | 188 | ||
189 | if (host) { | 189 | if (host) { |
190 | nand_release(&host->mtd); | ||
190 | iounmap(host->cmd_va); | 191 | iounmap(host->cmd_va); |
191 | iounmap(host->data_va); | 192 | iounmap(host->data_va); |
192 | iounmap(host->addr_va); | 193 | iounmap(host->addr_va); |
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 9c30a0b03171..fa8faedfad6e 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c | |||
@@ -339,6 +339,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev) | |||
339 | struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); | 339 | struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); |
340 | struct resource *res; | 340 | struct resource *res; |
341 | 341 | ||
342 | nand_release(&nuc900_nand->mtd); | ||
342 | iounmap(nuc900_nand->reg); | 343 | iounmap(nuc900_nand->reg); |
343 | 344 | ||
344 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 345 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ec22a5aab038..f745f00f3167 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -95,8 +95,6 @@ | |||
95 | #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) | 95 | #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) |
96 | #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) | 96 | #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) |
97 | 97 | ||
98 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
99 | |||
100 | /* oob info generated runtime depending on ecc algorithm and layout selected */ | 98 | /* oob info generated runtime depending on ecc algorithm and layout selected */ |
101 | static struct nand_ecclayout omap_oobinfo; | 99 | static struct nand_ecclayout omap_oobinfo; |
102 | /* Define some generic bad / good block scan pattern which are used | 100 | /* Define some generic bad / good block scan pattern which are used |
@@ -115,7 +113,6 @@ struct omap_nand_info { | |||
115 | struct nand_hw_control controller; | 113 | struct nand_hw_control controller; |
116 | struct omap_nand_platform_data *pdata; | 114 | struct omap_nand_platform_data *pdata; |
117 | struct mtd_info mtd; | 115 | struct mtd_info mtd; |
118 | struct mtd_partition *parts; | ||
119 | struct nand_chip nand; | 116 | struct nand_chip nand; |
120 | struct platform_device *pdev; | 117 | struct platform_device *pdev; |
121 | 118 | ||
@@ -745,12 +742,12 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ | |||
745 | 742 | ||
746 | case 1: | 743 | case 1: |
747 | /* Uncorrectable error */ | 744 | /* Uncorrectable error */ |
748 | DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); | 745 | pr_debug("ECC UNCORRECTED_ERROR 1\n"); |
749 | return -1; | 746 | return -1; |
750 | 747 | ||
751 | case 11: | 748 | case 11: |
752 | /* UN-Correctable error */ | 749 | /* UN-Correctable error */ |
753 | DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n"); | 750 | pr_debug("ECC UNCORRECTED_ERROR B\n"); |
754 | return -1; | 751 | return -1; |
755 | 752 | ||
756 | case 12: | 753 | case 12: |
@@ -767,8 +764,8 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ | |||
767 | 764 | ||
768 | find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; | 765 | find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; |
769 | 766 | ||
770 | DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at " | 767 | pr_debug("Correcting single bit ECC error at offset: " |
771 | "offset: %d, bit: %d\n", find_byte, find_bit); | 768 | "%d, bit: %d\n", find_byte, find_bit); |
772 | 769 | ||
773 | page_data[find_byte] ^= (1 << find_bit); | 770 | page_data[find_byte] ^= (1 << find_bit); |
774 | 771 | ||
@@ -780,7 +777,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ | |||
780 | ecc_data2[2] == 0) | 777 | ecc_data2[2] == 0) |
781 | return 0; | 778 | return 0; |
782 | } | 779 | } |
783 | DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n"); | 780 | pr_debug("UNCORRECTED_ERROR default\n"); |
784 | return -1; | 781 | return -1; |
785 | } | 782 | } |
786 | } | 783 | } |
@@ -1104,13 +1101,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) | |||
1104 | goto out_release_mem_region; | 1101 | goto out_release_mem_region; |
1105 | } | 1102 | } |
1106 | 1103 | ||
1107 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); | 1104 | mtd_device_parse_register(&info->mtd, NULL, 0, |
1108 | if (err > 0) | 1105 | pdata->parts, pdata->nr_parts); |
1109 | mtd_device_register(&info->mtd, info->parts, err); | ||
1110 | else if (pdata->parts) | ||
1111 | mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts); | ||
1112 | else | ||
1113 | mtd_device_register(&info->mtd, NULL, 0); | ||
1114 | 1106 | ||
1115 | platform_set_drvdata(pdev, &info->mtd); | 1107 | platform_set_drvdata(pdev, &info->mtd); |
1116 | 1108 | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 7794d0680f91..29f505adaf84 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
22 | #include <plat/orion_nand.h> | 22 | #include <plat/orion_nand.h> |
23 | 23 | ||
24 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
25 | |||
26 | static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 24 | static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
27 | { | 25 | { |
28 | struct nand_chip *nc = mtd->priv; | 26 | struct nand_chip *nc = mtd->priv; |
@@ -81,8 +79,6 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
81 | struct resource *res; | 79 | struct resource *res; |
82 | void __iomem *io_base; | 80 | void __iomem *io_base; |
83 | int ret = 0; | 81 | int ret = 0; |
84 | struct mtd_partition *partitions = NULL; | ||
85 | int num_part = 0; | ||
86 | 82 | ||
87 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); | 83 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); |
88 | if (!nc) { | 84 | if (!nc) { |
@@ -132,17 +128,9 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
132 | goto no_dev; | 128 | goto no_dev; |
133 | } | 129 | } |
134 | 130 | ||
135 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
136 | mtd->name = "orion_nand"; | 131 | mtd->name = "orion_nand"; |
137 | num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0); | 132 | ret = mtd_device_parse_register(mtd, NULL, 0, |
138 | #endif | 133 | board->parts, board->nr_parts); |
139 | /* If cmdline partitions have been passed, let them be used */ | ||
140 | if (num_part <= 0) { | ||
141 | num_part = board->nr_parts; | ||
142 | partitions = board->parts; | ||
143 | } | ||
144 | |||
145 | ret = mtd_device_register(mtd, partitions, num_part); | ||
146 | if (ret) { | 134 | if (ret) { |
147 | nand_release(mtd); | 135 | nand_release(mtd); |
148 | goto no_dev; | 136 | goto no_dev; |
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index b1aa41b8a4eb..a97264ececdb 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -155,7 +155,8 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) | |||
155 | chip->ecc.mode = NAND_ECC_SOFT; | 155 | chip->ecc.mode = NAND_ECC_SOFT; |
156 | 156 | ||
157 | /* Enable the following for a flash based bad block table */ | 157 | /* Enable the following for a flash based bad block table */ |
158 | chip->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; | 158 | chip->options = NAND_NO_AUTOINCR; |
159 | chip->bbt_options = NAND_BBT_USE_FLASH; | ||
159 | 160 | ||
160 | /* Scan to find existence of the device */ | 161 | /* Scan to find existence of the device */ |
161 | if (nand_scan(pasemi_nand_mtd, 1)) { | 162 | if (nand_scan(pasemi_nand_mtd, 1)) { |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 633c04bf76f6..ea8e1234e0e2 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -21,8 +21,6 @@ struct plat_nand_data { | |||
21 | struct nand_chip chip; | 21 | struct nand_chip chip; |
22 | struct mtd_info mtd; | 22 | struct mtd_info mtd; |
23 | void __iomem *io_base; | 23 | void __iomem *io_base; |
24 | int nr_parts; | ||
25 | struct mtd_partition *parts; | ||
26 | }; | 24 | }; |
27 | 25 | ||
28 | /* | 26 | /* |
@@ -79,6 +77,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
79 | data->chip.read_buf = pdata->ctrl.read_buf; | 77 | data->chip.read_buf = pdata->ctrl.read_buf; |
80 | data->chip.chip_delay = pdata->chip.chip_delay; | 78 | data->chip.chip_delay = pdata->chip.chip_delay; |
81 | data->chip.options |= pdata->chip.options; | 79 | data->chip.options |= pdata->chip.options; |
80 | data->chip.bbt_options |= pdata->chip.bbt_options; | ||
82 | 81 | ||
83 | data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; | 82 | data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; |
84 | data->chip.ecc.layout = pdata->chip.ecclayout; | 83 | data->chip.ecc.layout = pdata->chip.ecclayout; |
@@ -99,23 +98,9 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
99 | goto out; | 98 | goto out; |
100 | } | 99 | } |
101 | 100 | ||
102 | if (pdata->chip.part_probe_types) { | 101 | err = mtd_device_parse_register(&data->mtd, |
103 | err = parse_mtd_partitions(&data->mtd, | 102 | pdata->chip.part_probe_types, 0, |
104 | pdata->chip.part_probe_types, | 103 | pdata->chip.partitions, pdata->chip.nr_partitions); |
105 | &data->parts, 0); | ||
106 | if (err > 0) { | ||
107 | mtd_device_register(&data->mtd, data->parts, err); | ||
108 | return 0; | ||
109 | } | ||
110 | } | ||
111 | if (pdata->chip.set_parts) | ||
112 | pdata->chip.set_parts(data->mtd.size, &pdata->chip); | ||
113 | if (pdata->chip.partitions) { | ||
114 | data->parts = pdata->chip.partitions; | ||
115 | err = mtd_device_register(&data->mtd, data->parts, | ||
116 | pdata->chip.nr_partitions); | ||
117 | } else | ||
118 | err = mtd_device_register(&data->mtd, NULL, 0); | ||
119 | 104 | ||
120 | if (!err) | 105 | if (!err) |
121 | return err; | 106 | return err; |
@@ -145,8 +130,6 @@ static int __devexit plat_nand_remove(struct platform_device *pdev) | |||
145 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
146 | 131 | ||
147 | nand_release(&data->mtd); | 132 | nand_release(&data->mtd); |
148 | if (data->parts && data->parts != pdata->chip.partitions) | ||
149 | kfree(data->parts); | ||
150 | if (pdata->ctrl.remove) | 133 | if (pdata->ctrl.remove) |
151 | pdata->ctrl.remove(pdev); | 134 | pdata->ctrl.remove(pdev); |
152 | iounmap(data->io_base); | 135 | iounmap(data->io_base); |
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index 3bbb796b451c..7e52af51a198 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c | |||
@@ -99,8 +99,6 @@ static struct mtd_partition partition_info_evb[] = { | |||
99 | 99 | ||
100 | #define NUM_PARTITIONS 1 | 100 | #define NUM_PARTITIONS 1 |
101 | 101 | ||
102 | extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id); | ||
103 | |||
104 | /* | 102 | /* |
105 | * hardware specific access to control-lines | 103 | * hardware specific access to control-lines |
106 | */ | 104 | */ |
@@ -187,18 +185,12 @@ static int ppchameleonevb_device_ready(struct mtd_info *minfo) | |||
187 | } | 185 | } |
188 | #endif | 186 | #endif |
189 | 187 | ||
190 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
191 | const char *part_probes_evb[] = { "cmdlinepart", NULL }; | ||
192 | |||
193 | /* | 188 | /* |
194 | * Main initialization routine | 189 | * Main initialization routine |
195 | */ | 190 | */ |
196 | static int __init ppchameleonevb_init(void) | 191 | static int __init ppchameleonevb_init(void) |
197 | { | 192 | { |
198 | struct nand_chip *this; | 193 | struct nand_chip *this; |
199 | const char *part_type = 0; | ||
200 | int mtd_parts_nb = 0; | ||
201 | struct mtd_partition *mtd_parts = 0; | ||
202 | void __iomem *ppchameleon_fio_base; | 194 | void __iomem *ppchameleon_fio_base; |
203 | void __iomem *ppchameleonevb_fio_base; | 195 | void __iomem *ppchameleonevb_fio_base; |
204 | 196 | ||
@@ -281,24 +273,13 @@ static int __init ppchameleonevb_init(void) | |||
281 | #endif | 273 | #endif |
282 | 274 | ||
283 | ppchameleon_mtd->name = "ppchameleon-nand"; | 275 | ppchameleon_mtd->name = "ppchameleon-nand"; |
284 | mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0); | ||
285 | if (mtd_parts_nb > 0) | ||
286 | part_type = "command line"; | ||
287 | else | ||
288 | mtd_parts_nb = 0; | ||
289 | |||
290 | if (mtd_parts_nb == 0) { | ||
291 | if (ppchameleon_mtd->size == NAND_SMALL_SIZE) | ||
292 | mtd_parts = partition_info_me; | ||
293 | else | ||
294 | mtd_parts = partition_info_hi; | ||
295 | mtd_parts_nb = NUM_PARTITIONS; | ||
296 | part_type = "static"; | ||
297 | } | ||
298 | 276 | ||
299 | /* Register the partitions */ | 277 | /* Register the partitions */ |
300 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 278 | mtd_device_parse_register(ppchameleon_mtd, NULL, 0, |
301 | mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb); | 279 | ppchameleon_mtd->size == NAND_SMALL_SIZE ? |
280 | partition_info_me : | ||
281 | partition_info_hi, | ||
282 | NUM_PARTITIONS); | ||
302 | 283 | ||
303 | nand_evb_init: | 284 | nand_evb_init: |
304 | /**************************** | 285 | /**************************** |
@@ -382,21 +363,13 @@ static int __init ppchameleonevb_init(void) | |||
382 | } | 363 | } |
383 | 364 | ||
384 | ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; | 365 | ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; |
385 | mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0); | ||
386 | if (mtd_parts_nb > 0) | ||
387 | part_type = "command line"; | ||
388 | else | ||
389 | mtd_parts_nb = 0; | ||
390 | |||
391 | if (mtd_parts_nb == 0) { | ||
392 | mtd_parts = partition_info_evb; | ||
393 | mtd_parts_nb = NUM_PARTITIONS; | ||
394 | part_type = "static"; | ||
395 | } | ||
396 | 366 | ||
397 | /* Register the partitions */ | 367 | /* Register the partitions */ |
398 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 368 | mtd_device_parse_register(ppchameleonevb_mtd, NULL, 0, |
399 | mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb); | 369 | ppchameleon_mtd->size == NAND_SMALL_SIZE ? |
370 | partition_info_me : | ||
371 | partition_info_hi, | ||
372 | NUM_PARTITIONS); | ||
400 | 373 | ||
401 | /* Return happy */ | 374 | /* Return happy */ |
402 | return 0; | 375 | return 0; |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 1fb3b3a80581..9eb7f879969e 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -110,6 +110,7 @@ enum { | |||
110 | 110 | ||
111 | enum { | 111 | enum { |
112 | STATE_IDLE = 0, | 112 | STATE_IDLE = 0, |
113 | STATE_PREPARED, | ||
113 | STATE_CMD_HANDLE, | 114 | STATE_CMD_HANDLE, |
114 | STATE_DMA_READING, | 115 | STATE_DMA_READING, |
115 | STATE_DMA_WRITING, | 116 | STATE_DMA_WRITING, |
@@ -120,21 +121,40 @@ enum { | |||
120 | STATE_READY, | 121 | STATE_READY, |
121 | }; | 122 | }; |
122 | 123 | ||
123 | struct pxa3xx_nand_info { | 124 | struct pxa3xx_nand_host { |
124 | struct nand_chip nand_chip; | 125 | struct nand_chip chip; |
126 | struct pxa3xx_nand_cmdset *cmdset; | ||
127 | struct mtd_info *mtd; | ||
128 | void *info_data; | ||
129 | |||
130 | /* page size of attached chip */ | ||
131 | unsigned int page_size; | ||
132 | int use_ecc; | ||
133 | int cs; | ||
125 | 134 | ||
135 | /* calculated from pxa3xx_nand_flash data */ | ||
136 | unsigned int col_addr_cycles; | ||
137 | unsigned int row_addr_cycles; | ||
138 | size_t read_id_bytes; | ||
139 | |||
140 | /* cached register value */ | ||
141 | uint32_t reg_ndcr; | ||
142 | uint32_t ndtr0cs0; | ||
143 | uint32_t ndtr1cs0; | ||
144 | }; | ||
145 | |||
146 | struct pxa3xx_nand_info { | ||
126 | struct nand_hw_control controller; | 147 | struct nand_hw_control controller; |
127 | struct platform_device *pdev; | 148 | struct platform_device *pdev; |
128 | struct pxa3xx_nand_cmdset *cmdset; | ||
129 | 149 | ||
130 | struct clk *clk; | 150 | struct clk *clk; |
131 | void __iomem *mmio_base; | 151 | void __iomem *mmio_base; |
132 | unsigned long mmio_phys; | 152 | unsigned long mmio_phys; |
153 | struct completion cmd_complete; | ||
133 | 154 | ||
134 | unsigned int buf_start; | 155 | unsigned int buf_start; |
135 | unsigned int buf_count; | 156 | unsigned int buf_count; |
136 | 157 | ||
137 | struct mtd_info *mtd; | ||
138 | /* DMA information */ | 158 | /* DMA information */ |
139 | int drcmr_dat; | 159 | int drcmr_dat; |
140 | int drcmr_cmd; | 160 | int drcmr_cmd; |
@@ -142,44 +162,27 @@ struct pxa3xx_nand_info { | |||
142 | unsigned char *data_buff; | 162 | unsigned char *data_buff; |
143 | unsigned char *oob_buff; | 163 | unsigned char *oob_buff; |
144 | dma_addr_t data_buff_phys; | 164 | dma_addr_t data_buff_phys; |
145 | size_t data_buff_size; | ||
146 | int data_dma_ch; | 165 | int data_dma_ch; |
147 | struct pxa_dma_desc *data_desc; | 166 | struct pxa_dma_desc *data_desc; |
148 | dma_addr_t data_desc_addr; | 167 | dma_addr_t data_desc_addr; |
149 | 168 | ||
150 | uint32_t reg_ndcr; | 169 | struct pxa3xx_nand_host *host[NUM_CHIP_SELECT]; |
151 | |||
152 | /* saved column/page_addr during CMD_SEQIN */ | ||
153 | int seqin_column; | ||
154 | int seqin_page_addr; | ||
155 | |||
156 | /* relate to the command */ | ||
157 | unsigned int state; | 170 | unsigned int state; |
158 | 171 | ||
172 | int cs; | ||
159 | int use_ecc; /* use HW ECC ? */ | 173 | int use_ecc; /* use HW ECC ? */ |
160 | int use_dma; /* use DMA ? */ | 174 | int use_dma; /* use DMA ? */ |
161 | int is_ready; | 175 | int is_ready; |
162 | 176 | ||
163 | unsigned int page_size; /* page size of attached chip */ | 177 | unsigned int page_size; /* page size of attached chip */ |
164 | unsigned int data_size; /* data size in FIFO */ | 178 | unsigned int data_size; /* data size in FIFO */ |
179 | unsigned int oob_size; | ||
165 | int retcode; | 180 | int retcode; |
166 | struct completion cmd_complete; | ||
167 | 181 | ||
168 | /* generated NDCBx register values */ | 182 | /* generated NDCBx register values */ |
169 | uint32_t ndcb0; | 183 | uint32_t ndcb0; |
170 | uint32_t ndcb1; | 184 | uint32_t ndcb1; |
171 | uint32_t ndcb2; | 185 | uint32_t ndcb2; |
172 | |||
173 | /* timing calcuted from setting */ | ||
174 | uint32_t ndtr0cs0; | ||
175 | uint32_t ndtr1cs0; | ||
176 | |||
177 | /* calculated from pxa3xx_nand_flash data */ | ||
178 | size_t oob_size; | ||
179 | size_t read_id_bytes; | ||
180 | |||
181 | unsigned int col_addr_cycles; | ||
182 | unsigned int row_addr_cycles; | ||
183 | }; | 186 | }; |
184 | 187 | ||
185 | static int use_dma = 1; | 188 | static int use_dma = 1; |
@@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { | |||
225 | /* Define a default flash type setting serve as flash detecting only */ | 228 | /* Define a default flash type setting serve as flash detecting only */ |
226 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) | 229 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) |
227 | 230 | ||
228 | const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; | 231 | const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; |
229 | 232 | ||
230 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 233 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
231 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 234 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
@@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; | |||
241 | /* convert nano-seconds to nand flash controller clock cycles */ | 244 | /* convert nano-seconds to nand flash controller clock cycles */ |
242 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) | 245 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) |
243 | 246 | ||
244 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | 247 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, |
245 | const struct pxa3xx_nand_timing *t) | 248 | const struct pxa3xx_nand_timing *t) |
246 | { | 249 | { |
250 | struct pxa3xx_nand_info *info = host->info_data; | ||
247 | unsigned long nand_clk = clk_get_rate(info->clk); | 251 | unsigned long nand_clk = clk_get_rate(info->clk); |
248 | uint32_t ndtr0, ndtr1; | 252 | uint32_t ndtr0, ndtr1; |
249 | 253 | ||
@@ -258,23 +262,24 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | |||
258 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | | 262 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | |
259 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); | 263 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); |
260 | 264 | ||
261 | info->ndtr0cs0 = ndtr0; | 265 | host->ndtr0cs0 = ndtr0; |
262 | info->ndtr1cs0 = ndtr1; | 266 | host->ndtr1cs0 = ndtr1; |
263 | nand_writel(info, NDTR0CS0, ndtr0); | 267 | nand_writel(info, NDTR0CS0, ndtr0); |
264 | nand_writel(info, NDTR1CS0, ndtr1); | 268 | nand_writel(info, NDTR1CS0, ndtr1); |
265 | } | 269 | } |
266 | 270 | ||
267 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | 271 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) |
268 | { | 272 | { |
269 | int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; | 273 | struct pxa3xx_nand_host *host = info->host[info->cs]; |
274 | int oob_enable = host->reg_ndcr & NDCR_SPARE_EN; | ||
270 | 275 | ||
271 | info->data_size = info->page_size; | 276 | info->data_size = host->page_size; |
272 | if (!oob_enable) { | 277 | if (!oob_enable) { |
273 | info->oob_size = 0; | 278 | info->oob_size = 0; |
274 | return; | 279 | return; |
275 | } | 280 | } |
276 | 281 | ||
277 | switch (info->page_size) { | 282 | switch (host->page_size) { |
278 | case 2048: | 283 | case 2048: |
279 | info->oob_size = (info->use_ecc) ? 40 : 64; | 284 | info->oob_size = (info->use_ecc) ? 40 : 64; |
280 | break; | 285 | break; |
@@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | |||
292 | */ | 297 | */ |
293 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) | 298 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) |
294 | { | 299 | { |
300 | struct pxa3xx_nand_host *host = info->host[info->cs]; | ||
295 | uint32_t ndcr; | 301 | uint32_t ndcr; |
296 | 302 | ||
297 | ndcr = info->reg_ndcr; | 303 | ndcr = host->reg_ndcr; |
298 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; | 304 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; |
299 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; | 305 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; |
300 | ndcr |= NDCR_ND_RUN; | 306 | ndcr |= NDCR_ND_RUN; |
@@ -359,7 +365,7 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) | |||
359 | DIV_ROUND_UP(info->oob_size, 4)); | 365 | DIV_ROUND_UP(info->oob_size, 4)); |
360 | break; | 366 | break; |
361 | default: | 367 | default: |
362 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 368 | dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, |
363 | info->state); | 369 | info->state); |
364 | BUG(); | 370 | BUG(); |
365 | } | 371 | } |
@@ -385,7 +391,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info) | |||
385 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; | 391 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; |
386 | break; | 392 | break; |
387 | default: | 393 | default: |
388 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 394 | dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, |
389 | info->state); | 395 | info->state); |
390 | BUG(); | 396 | BUG(); |
391 | } | 397 | } |
@@ -416,6 +422,15 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | |||
416 | { | 422 | { |
417 | struct pxa3xx_nand_info *info = devid; | 423 | struct pxa3xx_nand_info *info = devid; |
418 | unsigned int status, is_completed = 0; | 424 | unsigned int status, is_completed = 0; |
425 | unsigned int ready, cmd_done; | ||
426 | |||
427 | if (info->cs == 0) { | ||
428 | ready = NDSR_FLASH_RDY; | ||
429 | cmd_done = NDSR_CS0_CMDD; | ||
430 | } else { | ||
431 | ready = NDSR_RDY; | ||
432 | cmd_done = NDSR_CS1_CMDD; | ||
433 | } | ||
419 | 434 | ||
420 | status = nand_readl(info, NDSR); | 435 | status = nand_readl(info, NDSR); |
421 | 436 | ||
@@ -437,11 +452,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | |||
437 | handle_data_pio(info); | 452 | handle_data_pio(info); |
438 | } | 453 | } |
439 | } | 454 | } |
440 | if (status & NDSR_CS0_CMDD) { | 455 | if (status & cmd_done) { |
441 | info->state = STATE_CMD_DONE; | 456 | info->state = STATE_CMD_DONE; |
442 | is_completed = 1; | 457 | is_completed = 1; |
443 | } | 458 | } |
444 | if (status & NDSR_FLASH_RDY) { | 459 | if (status & ready) { |
445 | info->is_ready = 1; | 460 | info->is_ready = 1; |
446 | info->state = STATE_READY; | 461 | info->state = STATE_READY; |
447 | } | 462 | } |
@@ -463,12 +478,6 @@ NORMAL_IRQ_EXIT: | |||
463 | return IRQ_HANDLED; | 478 | return IRQ_HANDLED; |
464 | } | 479 | } |
465 | 480 | ||
466 | static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) | ||
467 | { | ||
468 | struct pxa3xx_nand_info *info = mtd->priv; | ||
469 | return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0; | ||
470 | } | ||
471 | |||
472 | static inline int is_buf_blank(uint8_t *buf, size_t len) | 481 | static inline int is_buf_blank(uint8_t *buf, size_t len) |
473 | { | 482 | { |
474 | for (; len > 0; len--) | 483 | for (; len > 0; len--) |
@@ -481,10 +490,12 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
481 | uint16_t column, int page_addr) | 490 | uint16_t column, int page_addr) |
482 | { | 491 | { |
483 | uint16_t cmd; | 492 | uint16_t cmd; |
484 | int addr_cycle, exec_cmd, ndcb0; | 493 | int addr_cycle, exec_cmd; |
485 | struct mtd_info *mtd = info->mtd; | 494 | struct pxa3xx_nand_host *host; |
495 | struct mtd_info *mtd; | ||
486 | 496 | ||
487 | ndcb0 = 0; | 497 | host = info->host[info->cs]; |
498 | mtd = host->mtd; | ||
488 | addr_cycle = 0; | 499 | addr_cycle = 0; |
489 | exec_cmd = 1; | 500 | exec_cmd = 1; |
490 | 501 | ||
@@ -495,6 +506,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
495 | info->use_ecc = 0; | 506 | info->use_ecc = 0; |
496 | info->is_ready = 0; | 507 | info->is_ready = 0; |
497 | info->retcode = ERR_NONE; | 508 | info->retcode = ERR_NONE; |
509 | if (info->cs != 0) | ||
510 | info->ndcb0 = NDCB0_CSEL; | ||
511 | else | ||
512 | info->ndcb0 = 0; | ||
498 | 513 | ||
499 | switch (command) { | 514 | switch (command) { |
500 | case NAND_CMD_READ0: | 515 | case NAND_CMD_READ0: |
@@ -512,20 +527,19 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
512 | break; | 527 | break; |
513 | } | 528 | } |
514 | 529 | ||
515 | info->ndcb0 = ndcb0; | 530 | addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles |
516 | addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles | 531 | + host->col_addr_cycles); |
517 | + info->col_addr_cycles); | ||
518 | 532 | ||
519 | switch (command) { | 533 | switch (command) { |
520 | case NAND_CMD_READOOB: | 534 | case NAND_CMD_READOOB: |
521 | case NAND_CMD_READ0: | 535 | case NAND_CMD_READ0: |
522 | cmd = info->cmdset->read1; | 536 | cmd = host->cmdset->read1; |
523 | if (command == NAND_CMD_READOOB) | 537 | if (command == NAND_CMD_READOOB) |
524 | info->buf_start = mtd->writesize + column; | 538 | info->buf_start = mtd->writesize + column; |
525 | else | 539 | else |
526 | info->buf_start = column; | 540 | info->buf_start = column; |
527 | 541 | ||
528 | if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) | 542 | if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) |
529 | info->ndcb0 |= NDCB0_CMD_TYPE(0) | 543 | info->ndcb0 |= NDCB0_CMD_TYPE(0) |
530 | | addr_cycle | 544 | | addr_cycle |
531 | | (cmd & NDCB0_CMD1_MASK); | 545 | | (cmd & NDCB0_CMD1_MASK); |
@@ -537,7 +551,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
537 | 551 | ||
538 | case NAND_CMD_SEQIN: | 552 | case NAND_CMD_SEQIN: |
539 | /* small page addr setting */ | 553 | /* small page addr setting */ |
540 | if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) { | 554 | if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) { |
541 | info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) | 555 | info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) |
542 | | (column & 0xFF); | 556 | | (column & 0xFF); |
543 | 557 | ||
@@ -564,7 +578,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
564 | break; | 578 | break; |
565 | } | 579 | } |
566 | 580 | ||
567 | cmd = info->cmdset->program; | 581 | cmd = host->cmdset->program; |
568 | info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | 582 | info->ndcb0 |= NDCB0_CMD_TYPE(0x1) |
569 | | NDCB0_AUTO_RS | 583 | | NDCB0_AUTO_RS |
570 | | NDCB0_ST_ROW_EN | 584 | | NDCB0_ST_ROW_EN |
@@ -574,8 +588,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
574 | break; | 588 | break; |
575 | 589 | ||
576 | case NAND_CMD_READID: | 590 | case NAND_CMD_READID: |
577 | cmd = info->cmdset->read_id; | 591 | cmd = host->cmdset->read_id; |
578 | info->buf_count = info->read_id_bytes; | 592 | info->buf_count = host->read_id_bytes; |
579 | info->ndcb0 |= NDCB0_CMD_TYPE(3) | 593 | info->ndcb0 |= NDCB0_CMD_TYPE(3) |
580 | | NDCB0_ADDR_CYC(1) | 594 | | NDCB0_ADDR_CYC(1) |
581 | | cmd; | 595 | | cmd; |
@@ -583,7 +597,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
583 | info->data_size = 8; | 597 | info->data_size = 8; |
584 | break; | 598 | break; |
585 | case NAND_CMD_STATUS: | 599 | case NAND_CMD_STATUS: |
586 | cmd = info->cmdset->read_status; | 600 | cmd = host->cmdset->read_status; |
587 | info->buf_count = 1; | 601 | info->buf_count = 1; |
588 | info->ndcb0 |= NDCB0_CMD_TYPE(4) | 602 | info->ndcb0 |= NDCB0_CMD_TYPE(4) |
589 | | NDCB0_ADDR_CYC(1) | 603 | | NDCB0_ADDR_CYC(1) |
@@ -593,7 +607,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
593 | break; | 607 | break; |
594 | 608 | ||
595 | case NAND_CMD_ERASE1: | 609 | case NAND_CMD_ERASE1: |
596 | cmd = info->cmdset->erase; | 610 | cmd = host->cmdset->erase; |
597 | info->ndcb0 |= NDCB0_CMD_TYPE(2) | 611 | info->ndcb0 |= NDCB0_CMD_TYPE(2) |
598 | | NDCB0_AUTO_RS | 612 | | NDCB0_AUTO_RS |
599 | | NDCB0_ADDR_CYC(3) | 613 | | NDCB0_ADDR_CYC(3) |
@@ -604,7 +618,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
604 | 618 | ||
605 | break; | 619 | break; |
606 | case NAND_CMD_RESET: | 620 | case NAND_CMD_RESET: |
607 | cmd = info->cmdset->reset; | 621 | cmd = host->cmdset->reset; |
608 | info->ndcb0 |= NDCB0_CMD_TYPE(5) | 622 | info->ndcb0 |= NDCB0_CMD_TYPE(5) |
609 | | cmd; | 623 | | cmd; |
610 | 624 | ||
@@ -616,8 +630,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
616 | 630 | ||
617 | default: | 631 | default: |
618 | exec_cmd = 0; | 632 | exec_cmd = 0; |
619 | printk(KERN_ERR "pxa3xx-nand: non-supported" | 633 | dev_err(&info->pdev->dev, "non-supported command %x\n", |
620 | " command %x\n", command); | 634 | command); |
621 | break; | 635 | break; |
622 | } | 636 | } |
623 | 637 | ||
@@ -627,7 +641,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
627 | static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | 641 | static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, |
628 | int column, int page_addr) | 642 | int column, int page_addr) |
629 | { | 643 | { |
630 | struct pxa3xx_nand_info *info = mtd->priv; | 644 | struct pxa3xx_nand_host *host = mtd->priv; |
645 | struct pxa3xx_nand_info *info = host->info_data; | ||
631 | int ret, exec_cmd; | 646 | int ret, exec_cmd; |
632 | 647 | ||
633 | /* | 648 | /* |
@@ -635,9 +650,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
635 | * "byte" address into a "word" address appropriate | 650 | * "byte" address into a "word" address appropriate |
636 | * for indexing a word-oriented device | 651 | * for indexing a word-oriented device |
637 | */ | 652 | */ |
638 | if (info->reg_ndcr & NDCR_DWIDTH_M) | 653 | if (host->reg_ndcr & NDCR_DWIDTH_M) |
639 | column /= 2; | 654 | column /= 2; |
640 | 655 | ||
656 | /* | ||
657 | * There may be different NAND chip hooked to | ||
658 | * different chip select, so check whether | ||
659 | * chip select has been changed, if yes, reset the timing | ||
660 | */ | ||
661 | if (info->cs != host->cs) { | ||
662 | info->cs = host->cs; | ||
663 | nand_writel(info, NDTR0CS0, host->ndtr0cs0); | ||
664 | nand_writel(info, NDTR1CS0, host->ndtr1cs0); | ||
665 | } | ||
666 | |||
667 | info->state = STATE_PREPARED; | ||
641 | exec_cmd = prepare_command_pool(info, command, column, page_addr); | 668 | exec_cmd = prepare_command_pool(info, command, column, page_addr); |
642 | if (exec_cmd) { | 669 | if (exec_cmd) { |
643 | init_completion(&info->cmd_complete); | 670 | init_completion(&info->cmd_complete); |
@@ -646,12 +673,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
646 | ret = wait_for_completion_timeout(&info->cmd_complete, | 673 | ret = wait_for_completion_timeout(&info->cmd_complete, |
647 | CHIP_DELAY_TIMEOUT); | 674 | CHIP_DELAY_TIMEOUT); |
648 | if (!ret) { | 675 | if (!ret) { |
649 | printk(KERN_ERR "Wait time out!!!\n"); | 676 | dev_err(&info->pdev->dev, "Wait time out!!!\n"); |
650 | /* Stop State Machine for next command cycle */ | 677 | /* Stop State Machine for next command cycle */ |
651 | pxa3xx_nand_stop(info); | 678 | pxa3xx_nand_stop(info); |
652 | } | 679 | } |
653 | info->state = STATE_IDLE; | ||
654 | } | 680 | } |
681 | info->state = STATE_IDLE; | ||
655 | } | 682 | } |
656 | 683 | ||
657 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, | 684 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, |
@@ -664,7 +691,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, | |||
664 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | 691 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, |
665 | struct nand_chip *chip, uint8_t *buf, int page) | 692 | struct nand_chip *chip, uint8_t *buf, int page) |
666 | { | 693 | { |
667 | struct pxa3xx_nand_info *info = mtd->priv; | 694 | struct pxa3xx_nand_host *host = mtd->priv; |
695 | struct pxa3xx_nand_info *info = host->info_data; | ||
668 | 696 | ||
669 | chip->read_buf(mtd, buf, mtd->writesize); | 697 | chip->read_buf(mtd, buf, mtd->writesize); |
670 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 698 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -685,6 +713,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | |||
685 | * OOB, ignore such double bit errors | 713 | * OOB, ignore such double bit errors |
686 | */ | 714 | */ |
687 | if (is_buf_blank(buf, mtd->writesize)) | 715 | if (is_buf_blank(buf, mtd->writesize)) |
716 | info->retcode = ERR_NONE; | ||
717 | else | ||
688 | mtd->ecc_stats.failed++; | 718 | mtd->ecc_stats.failed++; |
689 | } | 719 | } |
690 | 720 | ||
@@ -693,7 +723,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | |||
693 | 723 | ||
694 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) | 724 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) |
695 | { | 725 | { |
696 | struct pxa3xx_nand_info *info = mtd->priv; | 726 | struct pxa3xx_nand_host *host = mtd->priv; |
727 | struct pxa3xx_nand_info *info = host->info_data; | ||
697 | char retval = 0xFF; | 728 | char retval = 0xFF; |
698 | 729 | ||
699 | if (info->buf_start < info->buf_count) | 730 | if (info->buf_start < info->buf_count) |
@@ -705,7 +736,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) | |||
705 | 736 | ||
706 | static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) | 737 | static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) |
707 | { | 738 | { |
708 | struct pxa3xx_nand_info *info = mtd->priv; | 739 | struct pxa3xx_nand_host *host = mtd->priv; |
740 | struct pxa3xx_nand_info *info = host->info_data; | ||
709 | u16 retval = 0xFFFF; | 741 | u16 retval = 0xFFFF; |
710 | 742 | ||
711 | if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) { | 743 | if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) { |
@@ -717,7 +749,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) | |||
717 | 749 | ||
718 | static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 750 | static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
719 | { | 751 | { |
720 | struct pxa3xx_nand_info *info = mtd->priv; | 752 | struct pxa3xx_nand_host *host = mtd->priv; |
753 | struct pxa3xx_nand_info *info = host->info_data; | ||
721 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); | 754 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); |
722 | 755 | ||
723 | memcpy(buf, info->data_buff + info->buf_start, real_len); | 756 | memcpy(buf, info->data_buff + info->buf_start, real_len); |
@@ -727,7 +760,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
727 | static void pxa3xx_nand_write_buf(struct mtd_info *mtd, | 760 | static void pxa3xx_nand_write_buf(struct mtd_info *mtd, |
728 | const uint8_t *buf, int len) | 761 | const uint8_t *buf, int len) |
729 | { | 762 | { |
730 | struct pxa3xx_nand_info *info = mtd->priv; | 763 | struct pxa3xx_nand_host *host = mtd->priv; |
764 | struct pxa3xx_nand_info *info = host->info_data; | ||
731 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); | 765 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); |
732 | 766 | ||
733 | memcpy(info->data_buff + info->buf_start, buf, real_len); | 767 | memcpy(info->data_buff + info->buf_start, buf, real_len); |
@@ -747,7 +781,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) | |||
747 | 781 | ||
748 | static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) | 782 | static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) |
749 | { | 783 | { |
750 | struct pxa3xx_nand_info *info = mtd->priv; | 784 | struct pxa3xx_nand_host *host = mtd->priv; |
785 | struct pxa3xx_nand_info *info = host->info_data; | ||
751 | 786 | ||
752 | /* pxa3xx_nand_send_command has waited for command complete */ | 787 | /* pxa3xx_nand_send_command has waited for command complete */ |
753 | if (this->state == FL_WRITING || this->state == FL_ERASING) { | 788 | if (this->state == FL_WRITING || this->state == FL_ERASING) { |
@@ -770,54 +805,70 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
770 | { | 805 | { |
771 | struct platform_device *pdev = info->pdev; | 806 | struct platform_device *pdev = info->pdev; |
772 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 807 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
808 | struct pxa3xx_nand_host *host = info->host[info->cs]; | ||
773 | uint32_t ndcr = 0x0; /* enable all interrupts */ | 809 | uint32_t ndcr = 0x0; /* enable all interrupts */ |
774 | 810 | ||
775 | if (f->page_size != 2048 && f->page_size != 512) | 811 | if (f->page_size != 2048 && f->page_size != 512) { |
812 | dev_err(&pdev->dev, "Current only support 2048 and 512 size\n"); | ||
776 | return -EINVAL; | 813 | return -EINVAL; |
814 | } | ||
777 | 815 | ||
778 | if (f->flash_width != 16 && f->flash_width != 8) | 816 | if (f->flash_width != 16 && f->flash_width != 8) { |
817 | dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n"); | ||
779 | return -EINVAL; | 818 | return -EINVAL; |
819 | } | ||
780 | 820 | ||
781 | /* calculate flash information */ | 821 | /* calculate flash information */ |
782 | info->cmdset = &default_cmdset; | 822 | host->cmdset = &default_cmdset; |
783 | info->page_size = f->page_size; | 823 | host->page_size = f->page_size; |
784 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | 824 | host->read_id_bytes = (f->page_size == 2048) ? 4 : 2; |
785 | 825 | ||
786 | /* calculate addressing information */ | 826 | /* calculate addressing information */ |
787 | info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; | 827 | host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; |
788 | 828 | ||
789 | if (f->num_blocks * f->page_per_block > 65536) | 829 | if (f->num_blocks * f->page_per_block > 65536) |
790 | info->row_addr_cycles = 3; | 830 | host->row_addr_cycles = 3; |
791 | else | 831 | else |
792 | info->row_addr_cycles = 2; | 832 | host->row_addr_cycles = 2; |
793 | 833 | ||
794 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | 834 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; |
795 | ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0; | 835 | ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; |
796 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; | 836 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; |
797 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; | 837 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; |
798 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; | 838 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; |
799 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; | 839 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; |
800 | 840 | ||
801 | ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes); | 841 | ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes); |
802 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ | 842 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ |
803 | 843 | ||
804 | info->reg_ndcr = ndcr; | 844 | host->reg_ndcr = ndcr; |
805 | 845 | ||
806 | pxa3xx_nand_set_timing(info, f->timing); | 846 | pxa3xx_nand_set_timing(host, f->timing); |
807 | return 0; | 847 | return 0; |
808 | } | 848 | } |
809 | 849 | ||
810 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | 850 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) |
811 | { | 851 | { |
852 | /* | ||
853 | * We set 0 by hard coding here, for we don't support keep_config | ||
854 | * when there is more than one chip attached to the controller | ||
855 | */ | ||
856 | struct pxa3xx_nand_host *host = info->host[0]; | ||
812 | uint32_t ndcr = nand_readl(info, NDCR); | 857 | uint32_t ndcr = nand_readl(info, NDCR); |
813 | info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; | ||
814 | /* set info fields needed to read id */ | ||
815 | info->read_id_bytes = (info->page_size == 2048) ? 4 : 2; | ||
816 | info->reg_ndcr = ndcr; | ||
817 | info->cmdset = &default_cmdset; | ||
818 | 858 | ||
819 | info->ndtr0cs0 = nand_readl(info, NDTR0CS0); | 859 | if (ndcr & NDCR_PAGE_SZ) { |
820 | info->ndtr1cs0 = nand_readl(info, NDTR1CS0); | 860 | host->page_size = 2048; |
861 | host->read_id_bytes = 4; | ||
862 | } else { | ||
863 | host->page_size = 512; | ||
864 | host->read_id_bytes = 2; | ||
865 | } | ||
866 | |||
867 | host->reg_ndcr = ndcr & ~NDCR_INT_MASK; | ||
868 | host->cmdset = &default_cmdset; | ||
869 | |||
870 | host->ndtr0cs0 = nand_readl(info, NDTR0CS0); | ||
871 | host->ndtr1cs0 = nand_readl(info, NDTR1CS0); | ||
821 | 872 | ||
822 | return 0; | 873 | return 0; |
823 | } | 874 | } |
@@ -847,7 +898,6 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
847 | return -ENOMEM; | 898 | return -ENOMEM; |
848 | } | 899 | } |
849 | 900 | ||
850 | info->data_buff_size = MAX_BUFF_SIZE; | ||
851 | info->data_desc = (void *)info->data_buff + data_desc_offset; | 901 | info->data_desc = (void *)info->data_buff + data_desc_offset; |
852 | info->data_desc_addr = info->data_buff_phys + data_desc_offset; | 902 | info->data_desc_addr = info->data_buff_phys + data_desc_offset; |
853 | 903 | ||
@@ -855,7 +905,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
855 | pxa3xx_nand_data_dma_irq, info); | 905 | pxa3xx_nand_data_dma_irq, info); |
856 | if (info->data_dma_ch < 0) { | 906 | if (info->data_dma_ch < 0) { |
857 | dev_err(&pdev->dev, "failed to request data dma\n"); | 907 | dev_err(&pdev->dev, "failed to request data dma\n"); |
858 | dma_free_coherent(&pdev->dev, info->data_buff_size, | 908 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, |
859 | info->data_buff, info->data_buff_phys); | 909 | info->data_buff, info->data_buff_phys); |
860 | return info->data_dma_ch; | 910 | return info->data_dma_ch; |
861 | } | 911 | } |
@@ -865,24 +915,28 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
865 | 915 | ||
866 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) | 916 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) |
867 | { | 917 | { |
868 | struct mtd_info *mtd = info->mtd; | 918 | struct mtd_info *mtd; |
869 | struct nand_chip *chip = mtd->priv; | 919 | int ret; |
870 | 920 | mtd = info->host[info->cs]->mtd; | |
871 | /* use the common timing to make a try */ | 921 | /* use the common timing to make a try */ |
872 | pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); | 922 | ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); |
873 | chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); | 923 | if (ret) |
924 | return ret; | ||
925 | |||
926 | pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0); | ||
874 | if (info->is_ready) | 927 | if (info->is_ready) |
875 | return 1; | ||
876 | else | ||
877 | return 0; | 928 | return 0; |
929 | |||
930 | return -ENODEV; | ||
878 | } | 931 | } |
879 | 932 | ||
880 | static int pxa3xx_nand_scan(struct mtd_info *mtd) | 933 | static int pxa3xx_nand_scan(struct mtd_info *mtd) |
881 | { | 934 | { |
882 | struct pxa3xx_nand_info *info = mtd->priv; | 935 | struct pxa3xx_nand_host *host = mtd->priv; |
936 | struct pxa3xx_nand_info *info = host->info_data; | ||
883 | struct platform_device *pdev = info->pdev; | 937 | struct platform_device *pdev = info->pdev; |
884 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 938 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
885 | struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} }; | 939 | struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL; |
886 | const struct pxa3xx_nand_flash *f = NULL; | 940 | const struct pxa3xx_nand_flash *f = NULL; |
887 | struct nand_chip *chip = mtd->priv; | 941 | struct nand_chip *chip = mtd->priv; |
888 | uint32_t id = -1; | 942 | uint32_t id = -1; |
@@ -893,22 +947,20 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
893 | goto KEEP_CONFIG; | 947 | goto KEEP_CONFIG; |
894 | 948 | ||
895 | ret = pxa3xx_nand_sensing(info); | 949 | ret = pxa3xx_nand_sensing(info); |
896 | if (!ret) { | 950 | if (ret) { |
897 | kfree(mtd); | 951 | dev_info(&info->pdev->dev, "There is no chip on cs %d!\n", |
898 | info->mtd = NULL; | 952 | info->cs); |
899 | printk(KERN_INFO "There is no nand chip on cs 0!\n"); | ||
900 | 953 | ||
901 | return -EINVAL; | 954 | return ret; |
902 | } | 955 | } |
903 | 956 | ||
904 | chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); | 957 | chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); |
905 | id = *((uint16_t *)(info->data_buff)); | 958 | id = *((uint16_t *)(info->data_buff)); |
906 | if (id != 0) | 959 | if (id != 0) |
907 | printk(KERN_INFO "Detect a flash id %x\n", id); | 960 | dev_info(&info->pdev->dev, "Detect a flash id %x\n", id); |
908 | else { | 961 | else { |
909 | kfree(mtd); | 962 | dev_warn(&info->pdev->dev, |
910 | info->mtd = NULL; | 963 | "Read out ID 0, potential timing set wrong!!\n"); |
911 | printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); | ||
912 | 964 | ||
913 | return -EINVAL; | 965 | return -EINVAL; |
914 | } | 966 | } |
@@ -926,14 +978,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
926 | } | 978 | } |
927 | 979 | ||
928 | if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) { | 980 | if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) { |
929 | kfree(mtd); | 981 | dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n"); |
930 | info->mtd = NULL; | ||
931 | printk(KERN_ERR "ERROR!! flash not defined!!!\n"); | ||
932 | 982 | ||
933 | return -EINVAL; | 983 | return -EINVAL; |
934 | } | 984 | } |
935 | 985 | ||
936 | pxa3xx_nand_config_flash(info, f); | 986 | ret = pxa3xx_nand_config_flash(info, f); |
987 | if (ret) { | ||
988 | dev_err(&info->pdev->dev, "ERROR! Configure failed\n"); | ||
989 | return ret; | ||
990 | } | ||
991 | |||
937 | pxa3xx_flash_ids[0].name = f->name; | 992 | pxa3xx_flash_ids[0].name = f->name; |
938 | pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff; | 993 | pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff; |
939 | pxa3xx_flash_ids[0].pagesize = f->page_size; | 994 | pxa3xx_flash_ids[0].pagesize = f->page_size; |
@@ -942,62 +997,78 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
942 | pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block; | 997 | pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block; |
943 | if (f->flash_width == 16) | 998 | if (f->flash_width == 16) |
944 | pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16; | 999 | pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16; |
1000 | pxa3xx_flash_ids[1].name = NULL; | ||
1001 | def = pxa3xx_flash_ids; | ||
945 | KEEP_CONFIG: | 1002 | KEEP_CONFIG: |
946 | if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids)) | 1003 | chip->ecc.mode = NAND_ECC_HW; |
1004 | chip->ecc.size = host->page_size; | ||
1005 | |||
1006 | chip->options = NAND_NO_AUTOINCR; | ||
1007 | chip->options |= NAND_NO_READRDY; | ||
1008 | if (host->reg_ndcr & NDCR_DWIDTH_M) | ||
1009 | chip->options |= NAND_BUSWIDTH_16; | ||
1010 | |||
1011 | if (nand_scan_ident(mtd, 1, def)) | ||
947 | return -ENODEV; | 1012 | return -ENODEV; |
948 | /* calculate addressing information */ | 1013 | /* calculate addressing information */ |
949 | info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1; | 1014 | if (mtd->writesize >= 2048) |
1015 | host->col_addr_cycles = 2; | ||
1016 | else | ||
1017 | host->col_addr_cycles = 1; | ||
1018 | |||
950 | info->oob_buff = info->data_buff + mtd->writesize; | 1019 | info->oob_buff = info->data_buff + mtd->writesize; |
951 | if ((mtd->size >> chip->page_shift) > 65536) | 1020 | if ((mtd->size >> chip->page_shift) > 65536) |
952 | info->row_addr_cycles = 3; | 1021 | host->row_addr_cycles = 3; |
953 | else | 1022 | else |
954 | info->row_addr_cycles = 2; | 1023 | host->row_addr_cycles = 2; |
955 | mtd->name = mtd_names[0]; | ||
956 | chip->ecc.mode = NAND_ECC_HW; | ||
957 | chip->ecc.size = f->page_size; | ||
958 | |||
959 | chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0; | ||
960 | chip->options |= NAND_NO_AUTOINCR; | ||
961 | chip->options |= NAND_NO_READRDY; | ||
962 | 1024 | ||
1025 | mtd->name = mtd_names[0]; | ||
963 | return nand_scan_tail(mtd); | 1026 | return nand_scan_tail(mtd); |
964 | } | 1027 | } |
965 | 1028 | ||
966 | static | 1029 | static int alloc_nand_resource(struct platform_device *pdev) |
967 | struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | ||
968 | { | 1030 | { |
1031 | struct pxa3xx_nand_platform_data *pdata; | ||
969 | struct pxa3xx_nand_info *info; | 1032 | struct pxa3xx_nand_info *info; |
1033 | struct pxa3xx_nand_host *host; | ||
970 | struct nand_chip *chip; | 1034 | struct nand_chip *chip; |
971 | struct mtd_info *mtd; | 1035 | struct mtd_info *mtd; |
972 | struct resource *r; | 1036 | struct resource *r; |
973 | int ret, irq; | 1037 | int ret, irq, cs; |
974 | 1038 | ||
975 | mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), | 1039 | pdata = pdev->dev.platform_data; |
976 | GFP_KERNEL); | 1040 | info = kzalloc(sizeof(*info) + (sizeof(*mtd) + |
977 | if (!mtd) { | 1041 | sizeof(*host)) * pdata->num_cs, GFP_KERNEL); |
1042 | if (!info) { | ||
978 | dev_err(&pdev->dev, "failed to allocate memory\n"); | 1043 | dev_err(&pdev->dev, "failed to allocate memory\n"); |
979 | return NULL; | 1044 | return -ENOMEM; |
980 | } | 1045 | } |
981 | 1046 | ||
982 | info = (struct pxa3xx_nand_info *)(&mtd[1]); | ||
983 | chip = (struct nand_chip *)(&mtd[1]); | ||
984 | info->pdev = pdev; | 1047 | info->pdev = pdev; |
985 | info->mtd = mtd; | 1048 | for (cs = 0; cs < pdata->num_cs; cs++) { |
986 | mtd->priv = info; | 1049 | mtd = (struct mtd_info *)((unsigned int)&info[1] + |
987 | mtd->owner = THIS_MODULE; | 1050 | (sizeof(*mtd) + sizeof(*host)) * cs); |
988 | 1051 | chip = (struct nand_chip *)(&mtd[1]); | |
989 | chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; | 1052 | host = (struct pxa3xx_nand_host *)chip; |
990 | chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; | 1053 | info->host[cs] = host; |
991 | chip->controller = &info->controller; | 1054 | host->mtd = mtd; |
992 | chip->waitfunc = pxa3xx_nand_waitfunc; | 1055 | host->cs = cs; |
993 | chip->select_chip = pxa3xx_nand_select_chip; | 1056 | host->info_data = info; |
994 | chip->dev_ready = pxa3xx_nand_dev_ready; | 1057 | mtd->priv = host; |
995 | chip->cmdfunc = pxa3xx_nand_cmdfunc; | 1058 | mtd->owner = THIS_MODULE; |
996 | chip->read_word = pxa3xx_nand_read_word; | 1059 | |
997 | chip->read_byte = pxa3xx_nand_read_byte; | 1060 | chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; |
998 | chip->read_buf = pxa3xx_nand_read_buf; | 1061 | chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; |
999 | chip->write_buf = pxa3xx_nand_write_buf; | 1062 | chip->controller = &info->controller; |
1000 | chip->verify_buf = pxa3xx_nand_verify_buf; | 1063 | chip->waitfunc = pxa3xx_nand_waitfunc; |
1064 | chip->select_chip = pxa3xx_nand_select_chip; | ||
1065 | chip->cmdfunc = pxa3xx_nand_cmdfunc; | ||
1066 | chip->read_word = pxa3xx_nand_read_word; | ||
1067 | chip->read_byte = pxa3xx_nand_read_byte; | ||
1068 | chip->read_buf = pxa3xx_nand_read_buf; | ||
1069 | chip->write_buf = pxa3xx_nand_write_buf; | ||
1070 | chip->verify_buf = pxa3xx_nand_verify_buf; | ||
1071 | } | ||
1001 | 1072 | ||
1002 | spin_lock_init(&chip->controller->lock); | 1073 | spin_lock_init(&chip->controller->lock); |
1003 | init_waitqueue_head(&chip->controller->wq); | 1074 | init_waitqueue_head(&chip->controller->wq); |
@@ -1070,13 +1141,13 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | |||
1070 | 1141 | ||
1071 | platform_set_drvdata(pdev, info); | 1142 | platform_set_drvdata(pdev, info); |
1072 | 1143 | ||
1073 | return info; | 1144 | return 0; |
1074 | 1145 | ||
1075 | fail_free_buf: | 1146 | fail_free_buf: |
1076 | free_irq(irq, info); | 1147 | free_irq(irq, info); |
1077 | if (use_dma) { | 1148 | if (use_dma) { |
1078 | pxa_free_dma(info->data_dma_ch); | 1149 | pxa_free_dma(info->data_dma_ch); |
1079 | dma_free_coherent(&pdev->dev, info->data_buff_size, | 1150 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, |
1080 | info->data_buff, info->data_buff_phys); | 1151 | info->data_buff, info->data_buff_phys); |
1081 | } else | 1152 | } else |
1082 | kfree(info->data_buff); | 1153 | kfree(info->data_buff); |
@@ -1088,17 +1159,21 @@ fail_put_clk: | |||
1088 | clk_disable(info->clk); | 1159 | clk_disable(info->clk); |
1089 | clk_put(info->clk); | 1160 | clk_put(info->clk); |
1090 | fail_free_mtd: | 1161 | fail_free_mtd: |
1091 | kfree(mtd); | 1162 | kfree(info); |
1092 | return NULL; | 1163 | return ret; |
1093 | } | 1164 | } |
1094 | 1165 | ||
1095 | static int pxa3xx_nand_remove(struct platform_device *pdev) | 1166 | static int pxa3xx_nand_remove(struct platform_device *pdev) |
1096 | { | 1167 | { |
1097 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); | 1168 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1098 | struct mtd_info *mtd = info->mtd; | 1169 | struct pxa3xx_nand_platform_data *pdata; |
1099 | struct resource *r; | 1170 | struct resource *r; |
1100 | int irq; | 1171 | int irq, cs; |
1101 | 1172 | ||
1173 | if (!info) | ||
1174 | return 0; | ||
1175 | |||
1176 | pdata = pdev->dev.platform_data; | ||
1102 | platform_set_drvdata(pdev, NULL); | 1177 | platform_set_drvdata(pdev, NULL); |
1103 | 1178 | ||
1104 | irq = platform_get_irq(pdev, 0); | 1179 | irq = platform_get_irq(pdev, 0); |
@@ -1106,7 +1181,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1106 | free_irq(irq, info); | 1181 | free_irq(irq, info); |
1107 | if (use_dma) { | 1182 | if (use_dma) { |
1108 | pxa_free_dma(info->data_dma_ch); | 1183 | pxa_free_dma(info->data_dma_ch); |
1109 | dma_free_writecombine(&pdev->dev, info->data_buff_size, | 1184 | dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE, |
1110 | info->data_buff, info->data_buff_phys); | 1185 | info->data_buff, info->data_buff_phys); |
1111 | } else | 1186 | } else |
1112 | kfree(info->data_buff); | 1187 | kfree(info->data_buff); |
@@ -1118,10 +1193,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1118 | clk_disable(info->clk); | 1193 | clk_disable(info->clk); |
1119 | clk_put(info->clk); | 1194 | clk_put(info->clk); |
1120 | 1195 | ||
1121 | if (mtd) { | 1196 | for (cs = 0; cs < pdata->num_cs; cs++) |
1122 | mtd_device_unregister(mtd); | 1197 | nand_release(info->host[cs]->mtd); |
1123 | kfree(mtd); | 1198 | kfree(info); |
1124 | } | ||
1125 | return 0; | 1199 | return 0; |
1126 | } | 1200 | } |
1127 | 1201 | ||
@@ -1129,6 +1203,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1129 | { | 1203 | { |
1130 | struct pxa3xx_nand_platform_data *pdata; | 1204 | struct pxa3xx_nand_platform_data *pdata; |
1131 | struct pxa3xx_nand_info *info; | 1205 | struct pxa3xx_nand_info *info; |
1206 | int ret, cs, probe_success; | ||
1132 | 1207 | ||
1133 | pdata = pdev->dev.platform_data; | 1208 | pdata = pdev->dev.platform_data; |
1134 | if (!pdata) { | 1209 | if (!pdata) { |
@@ -1136,52 +1211,88 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1136 | return -ENODEV; | 1211 | return -ENODEV; |
1137 | } | 1212 | } |
1138 | 1213 | ||
1139 | info = alloc_nand_resource(pdev); | 1214 | ret = alloc_nand_resource(pdev); |
1140 | if (info == NULL) | 1215 | if (ret) { |
1141 | return -ENOMEM; | 1216 | dev_err(&pdev->dev, "alloc nand resource failed\n"); |
1142 | 1217 | return ret; | |
1143 | if (pxa3xx_nand_scan(info->mtd)) { | ||
1144 | dev_err(&pdev->dev, "failed to scan nand\n"); | ||
1145 | pxa3xx_nand_remove(pdev); | ||
1146 | return -ENODEV; | ||
1147 | } | 1218 | } |
1148 | 1219 | ||
1149 | if (mtd_has_cmdlinepart()) { | 1220 | info = platform_get_drvdata(pdev); |
1150 | const char *probes[] = { "cmdlinepart", NULL }; | 1221 | probe_success = 0; |
1151 | struct mtd_partition *parts; | 1222 | for (cs = 0; cs < pdata->num_cs; cs++) { |
1152 | int nr_parts; | 1223 | info->cs = cs; |
1224 | ret = pxa3xx_nand_scan(info->host[cs]->mtd); | ||
1225 | if (ret) { | ||
1226 | dev_warn(&pdev->dev, "failed to scan nand at cs %d\n", | ||
1227 | cs); | ||
1228 | continue; | ||
1229 | } | ||
1153 | 1230 | ||
1154 | nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); | 1231 | ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0, |
1232 | pdata->parts[cs], pdata->nr_parts[cs]); | ||
1233 | if (!ret) | ||
1234 | probe_success = 1; | ||
1235 | } | ||
1155 | 1236 | ||
1156 | if (nr_parts) | 1237 | if (!probe_success) { |
1157 | return mtd_device_register(info->mtd, parts, nr_parts); | 1238 | pxa3xx_nand_remove(pdev); |
1239 | return -ENODEV; | ||
1158 | } | 1240 | } |
1159 | 1241 | ||
1160 | return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts); | 1242 | return 0; |
1161 | } | 1243 | } |
1162 | 1244 | ||
1163 | #ifdef CONFIG_PM | 1245 | #ifdef CONFIG_PM |
1164 | static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) | 1246 | static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) |
1165 | { | 1247 | { |
1166 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); | 1248 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1167 | struct mtd_info *mtd = info->mtd; | 1249 | struct pxa3xx_nand_platform_data *pdata; |
1250 | struct mtd_info *mtd; | ||
1251 | int cs; | ||
1168 | 1252 | ||
1253 | pdata = pdev->dev.platform_data; | ||
1169 | if (info->state) { | 1254 | if (info->state) { |
1170 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); | 1255 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); |
1171 | return -EAGAIN; | 1256 | return -EAGAIN; |
1172 | } | 1257 | } |
1173 | 1258 | ||
1259 | for (cs = 0; cs < pdata->num_cs; cs++) { | ||
1260 | mtd = info->host[cs]->mtd; | ||
1261 | mtd->suspend(mtd); | ||
1262 | } | ||
1263 | |||
1174 | return 0; | 1264 | return 0; |
1175 | } | 1265 | } |
1176 | 1266 | ||
1177 | static int pxa3xx_nand_resume(struct platform_device *pdev) | 1267 | static int pxa3xx_nand_resume(struct platform_device *pdev) |
1178 | { | 1268 | { |
1179 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); | 1269 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1180 | struct mtd_info *mtd = info->mtd; | 1270 | struct pxa3xx_nand_platform_data *pdata; |
1271 | struct mtd_info *mtd; | ||
1272 | int cs; | ||
1181 | 1273 | ||
1182 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); | 1274 | pdata = pdev->dev.platform_data; |
1183 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); | 1275 | /* We don't want to handle interrupt without calling mtd routine */ |
1184 | clk_enable(info->clk); | 1276 | disable_int(info, NDCR_INT_MASK); |
1277 | |||
1278 | /* | ||
1279 | * Directly set the chip select to a invalid value, | ||
1280 | * then the driver would reset the timing according | ||
1281 | * to current chip select at the beginning of cmdfunc | ||
1282 | */ | ||
1283 | info->cs = 0xff; | ||
1284 | |||
1285 | /* | ||
1286 | * As the spec says, the NDSR would be updated to 0x1800 when | ||
1287 | * doing the nand_clk disable/enable. | ||
1288 | * To prevent it damaging state machine of the driver, clear | ||
1289 | * all status before resume | ||
1290 | */ | ||
1291 | nand_writel(info, NDSR, NDSR_MASK); | ||
1292 | for (cs = 0; cs < pdata->num_cs; cs++) { | ||
1293 | mtd = info->host[cs]->mtd; | ||
1294 | mtd->resume(mtd); | ||
1295 | } | ||
1185 | 1296 | ||
1186 | return 0; | 1297 | return 0; |
1187 | } | 1298 | } |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index cae2e013c986..f20f393bfda6 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -1027,7 +1027,7 @@ void r852_shutdown(struct pci_dev *pci_dev) | |||
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | #ifdef CONFIG_PM | 1029 | #ifdef CONFIG_PM |
1030 | int r852_suspend(struct device *device) | 1030 | static int r852_suspend(struct device *device) |
1031 | { | 1031 | { |
1032 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1032 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
1033 | 1033 | ||
@@ -1048,7 +1048,7 @@ int r852_suspend(struct device *device) | |||
1048 | return 0; | 1048 | return 0; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | int r852_resume(struct device *device) | 1051 | static int r852_resume(struct device *device) |
1052 | { | 1052 | { |
1053 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1053 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
1054 | 1054 | ||
@@ -1092,7 +1092,7 @@ static const struct pci_device_id r852_pci_id_tbl[] = { | |||
1092 | 1092 | ||
1093 | MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl); | 1093 | MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl); |
1094 | 1094 | ||
1095 | SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); | 1095 | static SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); |
1096 | 1096 | ||
1097 | static struct pci_driver r852_pci_driver = { | 1097 | static struct pci_driver r852_pci_driver = { |
1098 | .name = DRV_NAME, | 1098 | .name = DRV_NAME, |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index c9f9127ff770..f309addc2fa0 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -351,7 +351,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha | |||
351 | return 0; | 351 | return 0; |
352 | } | 352 | } |
353 | 353 | ||
354 | /* Read the syndrom pattern from the FPGA and correct the bitorder */ | 354 | /* Read the syndrome pattern from the FPGA and correct the bitorder */ |
355 | rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); | 355 | rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); |
356 | for (i = 0; i < 8; i++) { | 356 | for (i = 0; i < 8; i++) { |
357 | ecc[i] = bitrev8(*rs_ecc); | 357 | ecc[i] = bitrev8(*rs_ecc); |
@@ -380,7 +380,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha | |||
380 | /* Let the library code do its magic. */ | 380 | /* Let the library code do its magic. */ |
381 | res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL); | 381 | res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL); |
382 | if (res > 0) { | 382 | if (res > 0) { |
383 | DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res); | 383 | pr_debug("rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res); |
384 | } | 384 | } |
385 | return res; | 385 | return res; |
386 | } | 386 | } |
@@ -444,7 +444,6 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, | |||
444 | len = mtd->writesize; | 444 | len = mtd->writesize; |
445 | buf = kmalloc(len, GFP_KERNEL); | 445 | buf = kmalloc(len, GFP_KERNEL); |
446 | if (!buf) { | 446 | if (!buf) { |
447 | printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n"); | ||
448 | er_stat = 1; | 447 | er_stat = 1; |
449 | goto out; | 448 | goto out; |
450 | } | 449 | } |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 4405468f196b..868685db6712 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -723,7 +723,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) | |||
723 | 723 | ||
724 | /* free the common resources */ | 724 | /* free the common resources */ |
725 | 725 | ||
726 | if (info->clk != NULL && !IS_ERR(info->clk)) { | 726 | if (!IS_ERR(info->clk)) { |
727 | s3c2410_nand_clk_set_state(info, CLOCK_DISABLE); | 727 | s3c2410_nand_clk_set_state(info, CLOCK_DISABLE); |
728 | clk_put(info->clk); | 728 | clk_put(info->clk); |
729 | } | 729 | } |
@@ -744,26 +744,15 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) | |||
744 | return 0; | 744 | return 0; |
745 | } | 745 | } |
746 | 746 | ||
747 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
748 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | 747 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, |
749 | struct s3c2410_nand_mtd *mtd, | 748 | struct s3c2410_nand_mtd *mtd, |
750 | struct s3c2410_nand_set *set) | 749 | struct s3c2410_nand_set *set) |
751 | { | 750 | { |
752 | struct mtd_partition *part_info; | 751 | if (set) |
753 | int nr_part = 0; | 752 | mtd->mtd.name = set->name; |
754 | 753 | ||
755 | if (set == NULL) | 754 | return mtd_device_parse_register(&mtd->mtd, NULL, 0, |
756 | return mtd_device_register(&mtd->mtd, NULL, 0); | 755 | set->partitions, set->nr_partitions); |
757 | |||
758 | mtd->mtd.name = set->name; | ||
759 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0); | ||
760 | |||
761 | if (nr_part <= 0 && set->nr_partitions > 0) { | ||
762 | nr_part = set->nr_partitions; | ||
763 | part_info = set->partitions; | ||
764 | } | ||
765 | |||
766 | return mtd_device_register(&mtd->mtd, part_info, nr_part); | ||
767 | } | 756 | } |
768 | 757 | ||
769 | /** | 758 | /** |
@@ -880,8 +869,10 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
880 | /* If you use u-boot BBT creation code, specifying this flag will | 869 | /* If you use u-boot BBT creation code, specifying this flag will |
881 | * let the kernel fish out the BBT from the NAND, and also skip the | 870 | * let the kernel fish out the BBT from the NAND, and also skip the |
882 | * full NAND scan that can take 1/2s or so. Little things... */ | 871 | * full NAND scan that can take 1/2s or so. Little things... */ |
883 | if (set->flash_bbt) | 872 | if (set->flash_bbt) { |
884 | chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; | 873 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
874 | chip->options |= NAND_SKIP_BBTSCAN; | ||
875 | } | ||
885 | } | 876 | } |
886 | 877 | ||
887 | /** | 878 | /** |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 19e24ed089ea..619d2a504788 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -103,16 +103,12 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, | |||
103 | return readb(sharpsl->io + ECCCNTR) != 0; | 103 | return readb(sharpsl->io + ECCCNTR) != 0; |
104 | } | 104 | } |
105 | 105 | ||
106 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
107 | |||
108 | /* | 106 | /* |
109 | * Main initialization routine | 107 | * Main initialization routine |
110 | */ | 108 | */ |
111 | static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | 109 | static int __devinit sharpsl_nand_probe(struct platform_device *pdev) |
112 | { | 110 | { |
113 | struct nand_chip *this; | 111 | struct nand_chip *this; |
114 | struct mtd_partition *sharpsl_partition_info; | ||
115 | int nr_partitions; | ||
116 | struct resource *r; | 112 | struct resource *r; |
117 | int err = 0; | 113 | int err = 0; |
118 | struct sharpsl_nand *sharpsl; | 114 | struct sharpsl_nand *sharpsl; |
@@ -184,14 +180,9 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | |||
184 | 180 | ||
185 | /* Register the partitions */ | 181 | /* Register the partitions */ |
186 | sharpsl->mtd.name = "sharpsl-nand"; | 182 | sharpsl->mtd.name = "sharpsl-nand"; |
187 | nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0); | ||
188 | if (nr_partitions <= 0) { | ||
189 | nr_partitions = data->nr_partitions; | ||
190 | sharpsl_partition_info = data->partitions; | ||
191 | } | ||
192 | 183 | ||
193 | err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info, | 184 | err = mtd_device_parse_register(&sharpsl->mtd, NULL, 0, |
194 | nr_partitions); | 185 | data->partitions, data->nr_partitions); |
195 | if (err) | 186 | if (err) |
196 | goto err_add; | 187 | goto err_add; |
197 | 188 | ||
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index 43469715b3fa..32ae5af7444f 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
@@ -48,7 +48,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
48 | 48 | ||
49 | /* As long as this function is called on erase block boundaries | 49 | /* As long as this function is called on erase block boundaries |
50 | it will work correctly for 256 byte nand */ | 50 | it will work correctly for 256 byte nand */ |
51 | ops.mode = MTD_OOB_PLACE; | 51 | ops.mode = MTD_OPS_PLACE_OOB; |
52 | ops.ooboffs = 0; | 52 | ops.ooboffs = 0; |
53 | ops.ooblen = mtd->oobsize; | 53 | ops.ooblen = mtd->oobsize; |
54 | ops.oobbuf = (void *)&oob; | 54 | ops.oobbuf = (void *)&oob; |
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index ca2d0555729e..0fb24f9c2327 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c | |||
@@ -155,8 +155,6 @@ static int socrates_nand_device_ready(struct mtd_info *mtd) | |||
155 | return 1; | 155 | return 1; |
156 | } | 156 | } |
157 | 157 | ||
158 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
159 | |||
160 | /* | 158 | /* |
161 | * Probe for the NAND device. | 159 | * Probe for the NAND device. |
162 | */ | 160 | */ |
@@ -166,8 +164,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
166 | struct mtd_info *mtd; | 164 | struct mtd_info *mtd; |
167 | struct nand_chip *nand_chip; | 165 | struct nand_chip *nand_chip; |
168 | int res; | 166 | int res; |
169 | struct mtd_partition *partitions = NULL; | 167 | struct mtd_part_parser_data ppdata; |
170 | int num_partitions = 0; | ||
171 | 168 | ||
172 | /* Allocate memory for the device structure (and zero it) */ | 169 | /* Allocate memory for the device structure (and zero it) */ |
173 | host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL); | 170 | host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL); |
@@ -193,6 +190,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
193 | mtd->name = "socrates_nand"; | 190 | mtd->name = "socrates_nand"; |
194 | mtd->owner = THIS_MODULE; | 191 | mtd->owner = THIS_MODULE; |
195 | mtd->dev.parent = &ofdev->dev; | 192 | mtd->dev.parent = &ofdev->dev; |
193 | ppdata.of_node = ofdev->dev.of_node; | ||
196 | 194 | ||
197 | /*should never be accessed directly */ | 195 | /*should never be accessed directly */ |
198 | nand_chip->IO_ADDR_R = (void *)0xdeadbeef; | 196 | nand_chip->IO_ADDR_R = (void *)0xdeadbeef; |
@@ -225,30 +223,10 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
225 | goto out; | 223 | goto out; |
226 | } | 224 | } |
227 | 225 | ||
228 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 226 | res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
229 | num_partitions = parse_mtd_partitions(mtd, part_probes, | ||
230 | &partitions, 0); | ||
231 | if (num_partitions < 0) { | ||
232 | res = num_partitions; | ||
233 | goto release; | ||
234 | } | ||
235 | #endif | ||
236 | |||
237 | if (num_partitions == 0) { | ||
238 | num_partitions = of_mtd_parse_partitions(&ofdev->dev, | ||
239 | ofdev->dev.of_node, | ||
240 | &partitions); | ||
241 | if (num_partitions < 0) { | ||
242 | res = num_partitions; | ||
243 | goto release; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | res = mtd_device_register(mtd, partitions, num_partitions); | ||
248 | if (!res) | 227 | if (!res) |
249 | return res; | 228 | return res; |
250 | 229 | ||
251 | release: | ||
252 | nand_release(mtd); | 230 | nand_release(mtd); |
253 | 231 | ||
254 | out: | 232 | out: |
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 11e8371b5683..beebd95f7690 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c | |||
@@ -121,9 +121,6 @@ struct tmio_nand { | |||
121 | 121 | ||
122 | #define mtd_to_tmio(m) container_of(m, struct tmio_nand, mtd) | 122 | #define mtd_to_tmio(m) container_of(m, struct tmio_nand, mtd) |
123 | 123 | ||
124 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
125 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
126 | #endif | ||
127 | 124 | ||
128 | /*--------------------------------------------------------------------------*/ | 125 | /*--------------------------------------------------------------------------*/ |
129 | 126 | ||
@@ -381,8 +378,6 @@ static int tmio_probe(struct platform_device *dev) | |||
381 | struct tmio_nand *tmio; | 378 | struct tmio_nand *tmio; |
382 | struct mtd_info *mtd; | 379 | struct mtd_info *mtd; |
383 | struct nand_chip *nand_chip; | 380 | struct nand_chip *nand_chip; |
384 | struct mtd_partition *parts; | ||
385 | int nbparts = 0; | ||
386 | int retval; | 381 | int retval; |
387 | 382 | ||
388 | if (data == NULL) | 383 | if (data == NULL) |
@@ -461,15 +456,9 @@ static int tmio_probe(struct platform_device *dev) | |||
461 | goto err_scan; | 456 | goto err_scan; |
462 | } | 457 | } |
463 | /* Register the partitions */ | 458 | /* Register the partitions */ |
464 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 459 | retval = mtd_device_parse_register(mtd, NULL, 0, |
465 | nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0); | 460 | data ? data->partition : NULL, |
466 | #endif | 461 | data ? data->num_partitions : 0); |
467 | if (nbparts <= 0 && data) { | ||
468 | parts = data->partition; | ||
469 | nbparts = data->num_partitions; | ||
470 | } | ||
471 | |||
472 | retval = mtd_device_register(mtd, parts, nbparts); | ||
473 | if (!retval) | 462 | if (!retval) |
474 | return retval; | 463 | return retval; |
475 | 464 | ||
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index bfba4e39a6c5..ace46fdaef58 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c | |||
@@ -74,7 +74,6 @@ struct txx9ndfmc_drvdata { | |||
74 | unsigned char hold; /* in gbusclock */ | 74 | unsigned char hold; /* in gbusclock */ |
75 | unsigned char spw; /* in gbusclock */ | 75 | unsigned char spw; /* in gbusclock */ |
76 | struct nand_hw_control hw_control; | 76 | struct nand_hw_control hw_control; |
77 | struct mtd_partition *parts[MAX_TXX9NDFMC_DEV]; | ||
78 | }; | 77 | }; |
79 | 78 | ||
80 | static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) | 79 | static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) |
@@ -287,7 +286,6 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd) | |||
287 | static int __init txx9ndfmc_probe(struct platform_device *dev) | 286 | static int __init txx9ndfmc_probe(struct platform_device *dev) |
288 | { | 287 | { |
289 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | 288 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; |
290 | static const char *probes[] = { "cmdlinepart", NULL }; | ||
291 | int hold, spw; | 289 | int hold, spw; |
292 | int i; | 290 | int i; |
293 | struct txx9ndfmc_drvdata *drvdata; | 291 | struct txx9ndfmc_drvdata *drvdata; |
@@ -333,7 +331,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) | |||
333 | struct txx9ndfmc_priv *txx9_priv; | 331 | struct txx9ndfmc_priv *txx9_priv; |
334 | struct nand_chip *chip; | 332 | struct nand_chip *chip; |
335 | struct mtd_info *mtd; | 333 | struct mtd_info *mtd; |
336 | int nr_parts; | ||
337 | 334 | ||
338 | if (!(plat->ch_mask & (1 << i))) | 335 | if (!(plat->ch_mask & (1 << i))) |
339 | continue; | 336 | continue; |
@@ -393,9 +390,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) | |||
393 | } | 390 | } |
394 | mtd->name = txx9_priv->mtdname; | 391 | mtd->name = txx9_priv->mtdname; |
395 | 392 | ||
396 | nr_parts = parse_mtd_partitions(mtd, probes, | 393 | mtd_device_parse_register(mtd, NULL, 0, NULL, 0); |
397 | &drvdata->parts[i], 0); | ||
398 | mtd_device_register(mtd, drvdata->parts[i], nr_parts); | ||
399 | drvdata->mtds[i] = mtd; | 394 | drvdata->mtds[i] = mtd; |
400 | } | 395 | } |
401 | 396 | ||
@@ -421,7 +416,6 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) | |||
421 | txx9_priv = chip->priv; | 416 | txx9_priv = chip->priv; |
422 | 417 | ||
423 | nand_release(mtd); | 418 | nand_release(mtd); |
424 | kfree(drvdata->parts[i]); | ||
425 | kfree(txx9_priv->mtdname); | 419 | kfree(txx9_priv->mtdname); |
426 | kfree(txx9_priv); | 420 | kfree(txx9_priv); |
427 | } | 421 | } |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index b155666acfbe..cda77b562ad4 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -63,14 +63,12 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
63 | return; | 63 | return; |
64 | } | 64 | } |
65 | 65 | ||
66 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); | 66 | pr_debug("NFTL: add_mtd for %s\n", mtd->name); |
67 | 67 | ||
68 | nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL); | 68 | nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL); |
69 | 69 | ||
70 | if (!nftl) { | 70 | if (!nftl) |
71 | printk(KERN_WARNING "NFTL: out of memory for data structures\n"); | ||
72 | return; | 71 | return; |
73 | } | ||
74 | 72 | ||
75 | nftl->mbd.mtd = mtd; | 73 | nftl->mbd.mtd = mtd; |
76 | nftl->mbd.devnum = -1; | 74 | nftl->mbd.devnum = -1; |
@@ -132,7 +130,7 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev) | |||
132 | { | 130 | { |
133 | struct NFTLrecord *nftl = (void *)dev; | 131 | struct NFTLrecord *nftl = (void *)dev; |
134 | 132 | ||
135 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum); | 133 | pr_debug("NFTL: remove_dev (i=%d)\n", dev->devnum); |
136 | 134 | ||
137 | del_mtd_blktrans_dev(dev); | 135 | del_mtd_blktrans_dev(dev); |
138 | kfree(nftl->ReplUnitTable); | 136 | kfree(nftl->ReplUnitTable); |
@@ -149,7 +147,7 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | |||
149 | struct mtd_oob_ops ops; | 147 | struct mtd_oob_ops ops; |
150 | int res; | 148 | int res; |
151 | 149 | ||
152 | ops.mode = MTD_OOB_PLACE; | 150 | ops.mode = MTD_OPS_PLACE_OOB; |
153 | ops.ooboffs = offs & mask; | 151 | ops.ooboffs = offs & mask; |
154 | ops.ooblen = len; | 152 | ops.ooblen = len; |
155 | ops.oobbuf = buf; | 153 | ops.oobbuf = buf; |
@@ -170,7 +168,7 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | |||
170 | struct mtd_oob_ops ops; | 168 | struct mtd_oob_ops ops; |
171 | int res; | 169 | int res; |
172 | 170 | ||
173 | ops.mode = MTD_OOB_PLACE; | 171 | ops.mode = MTD_OPS_PLACE_OOB; |
174 | ops.ooboffs = offs & mask; | 172 | ops.ooboffs = offs & mask; |
175 | ops.ooblen = len; | 173 | ops.ooblen = len; |
176 | ops.oobbuf = buf; | 174 | ops.oobbuf = buf; |
@@ -193,7 +191,7 @@ static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, | |||
193 | struct mtd_oob_ops ops; | 191 | struct mtd_oob_ops ops; |
194 | int res; | 192 | int res; |
195 | 193 | ||
196 | ops.mode = MTD_OOB_PLACE; | 194 | ops.mode = MTD_OPS_PLACE_OOB; |
197 | ops.ooboffs = offs & mask; | 195 | ops.ooboffs = offs & mask; |
198 | ops.ooblen = mtd->oobsize; | 196 | ops.ooblen = mtd->oobsize; |
199 | ops.oobbuf = oob; | 197 | ops.oobbuf = oob; |
@@ -220,7 +218,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) | |||
220 | 218 | ||
221 | /* Normally, we force a fold to happen before we run out of free blocks completely */ | 219 | /* Normally, we force a fold to happen before we run out of free blocks completely */ |
222 | if (!desperate && nftl->numfreeEUNs < 2) { | 220 | if (!desperate && nftl->numfreeEUNs < 2) { |
223 | DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); | 221 | pr_debug("NFTL_findfreeblock: there are too few free EUNs\n"); |
224 | return BLOCK_NIL; | 222 | return BLOCK_NIL; |
225 | } | 223 | } |
226 | 224 | ||
@@ -291,8 +289,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
291 | if (block == 2) { | 289 | if (block == 2) { |
292 | foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; | 290 | foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; |
293 | if (foldmark == FOLD_MARK_IN_PROGRESS) { | 291 | if (foldmark == FOLD_MARK_IN_PROGRESS) { |
294 | DEBUG(MTD_DEBUG_LEVEL1, | 292 | pr_debug("Write Inhibited on EUN %d\n", thisEUN); |
295 | "Write Inhibited on EUN %d\n", thisEUN); | ||
296 | inplace = 0; | 293 | inplace = 0; |
297 | } else { | 294 | } else { |
298 | /* There's no other reason not to do inplace, | 295 | /* There's no other reason not to do inplace, |
@@ -357,7 +354,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
357 | if (BlockLastState[block] != SECTOR_FREE && | 354 | if (BlockLastState[block] != SECTOR_FREE && |
358 | BlockMap[block] != BLOCK_NIL && | 355 | BlockMap[block] != BLOCK_NIL && |
359 | BlockMap[block] != targetEUN) { | 356 | BlockMap[block] != targetEUN) { |
360 | DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, " | 357 | pr_debug("Setting inplace to 0. VUC %d, " |
361 | "block %d was %x lastEUN, " | 358 | "block %d was %x lastEUN, " |
362 | "and is in EUN %d (%s) %d\n", | 359 | "and is in EUN %d (%s) %d\n", |
363 | thisVUC, block, BlockLastState[block], | 360 | thisVUC, block, BlockLastState[block], |
@@ -373,14 +370,14 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
373 | pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) && | 370 | pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) && |
374 | BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] != | 371 | BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] != |
375 | SECTOR_FREE) { | 372 | SECTOR_FREE) { |
376 | DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. " | 373 | pr_debug("Pending write not free in EUN %d. " |
377 | "Folding out of place.\n", targetEUN); | 374 | "Folding out of place.\n", targetEUN); |
378 | inplace = 0; | 375 | inplace = 0; |
379 | } | 376 | } |
380 | } | 377 | } |
381 | 378 | ||
382 | if (!inplace) { | 379 | if (!inplace) { |
383 | DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. " | 380 | pr_debug("Cannot fold Virtual Unit Chain %d in place. " |
384 | "Trying out-of-place\n", thisVUC); | 381 | "Trying out-of-place\n", thisVUC); |
385 | /* We need to find a targetEUN to fold into. */ | 382 | /* We need to find a targetEUN to fold into. */ |
386 | targetEUN = NFTL_findfreeblock(nftl, 1); | 383 | targetEUN = NFTL_findfreeblock(nftl, 1); |
@@ -410,7 +407,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
410 | and the Erase Unit into which we are supposed to be copying. | 407 | and the Erase Unit into which we are supposed to be copying. |
411 | Go for it. | 408 | Go for it. |
412 | */ | 409 | */ |
413 | DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN); | 410 | pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN); |
414 | for (block = 0; block < nftl->EraseSize / 512 ; block++) { | 411 | for (block = 0; block < nftl->EraseSize / 512 ; block++) { |
415 | unsigned char movebuf[512]; | 412 | unsigned char movebuf[512]; |
416 | int ret; | 413 | int ret; |
@@ -428,7 +425,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
428 | 425 | ||
429 | ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), | 426 | ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), |
430 | 512, &retlen, movebuf); | 427 | 512, &retlen, movebuf); |
431 | if (ret < 0 && ret != -EUCLEAN) { | 428 | if (ret < 0 && !mtd_is_bitflip(ret)) { |
432 | ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) | 429 | ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) |
433 | + (block * 512), 512, &retlen, | 430 | + (block * 512), 512, &retlen, |
434 | movebuf); | 431 | movebuf); |
@@ -457,7 +454,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p | |||
457 | has duplicate chains, we need to free one of the chains because it's not necessary any more. | 454 | has duplicate chains, we need to free one of the chains because it's not necessary any more. |
458 | */ | 455 | */ |
459 | thisEUN = nftl->EUNtable[thisVUC]; | 456 | thisEUN = nftl->EUNtable[thisVUC]; |
460 | DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n"); | 457 | pr_debug("Want to erase\n"); |
461 | 458 | ||
462 | /* For each block in the old chain (except the targetEUN of course), | 459 | /* For each block in the old chain (except the targetEUN of course), |
463 | free it and make it available for future use */ | 460 | free it and make it available for future use */ |
@@ -570,7 +567,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
570 | (writeEUN * nftl->EraseSize) + blockofs, | 567 | (writeEUN * nftl->EraseSize) + blockofs, |
571 | 8, &retlen, (char *)&bci); | 568 | 8, &retlen, (char *)&bci); |
572 | 569 | ||
573 | DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", | 570 | pr_debug("Status of block %d in EUN %d is %x\n", |
574 | block , writeEUN, le16_to_cpu(bci.Status)); | 571 | block , writeEUN, le16_to_cpu(bci.Status)); |
575 | 572 | ||
576 | status = bci.Status | bci.Status1; | 573 | status = bci.Status | bci.Status1; |
@@ -623,7 +620,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) | |||
623 | but they are reserved for when we're | 620 | but they are reserved for when we're |
624 | desperate. Well, now we're desperate. | 621 | desperate. Well, now we're desperate. |
625 | */ | 622 | */ |
626 | DEBUG(MTD_DEBUG_LEVEL1, "Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC); | 623 | pr_debug("Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC); |
627 | writeEUN = NFTL_findfreeblock(nftl, 1); | 624 | writeEUN = NFTL_findfreeblock(nftl, 1); |
628 | } | 625 | } |
629 | if (writeEUN == BLOCK_NIL) { | 626 | if (writeEUN == BLOCK_NIL) { |
@@ -776,7 +773,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, | |||
776 | size_t retlen; | 773 | size_t retlen; |
777 | int res = mtd->read(mtd, ptr, 512, &retlen, buffer); | 774 | int res = mtd->read(mtd, ptr, 512, &retlen, buffer); |
778 | 775 | ||
779 | if (res < 0 && res != -EUCLEAN) | 776 | if (res < 0 && !mtd_is_bitflip(res)) |
780 | return -EIO; | 777 | return -EIO; |
781 | } | 778 | } |
782 | return 0; | 779 | return 0; |
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index e3cd1ffad2f6..ac4092591aea 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the | 33 | /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the |
34 | * various device information of the NFTL partition and Bad Unit Table. Update | 34 | * various device information of the NFTL partition and Bad Unit Table. Update |
35 | * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] | 35 | * the ReplUnitTable[] table according to the Bad Unit Table. ReplUnitTable[] |
36 | * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c | 36 | * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c |
37 | */ | 37 | */ |
38 | static int find_boot_record(struct NFTLrecord *nftl) | 38 | static int find_boot_record(struct NFTLrecord *nftl) |
@@ -297,7 +297,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int | |||
297 | * | 297 | * |
298 | * Return: 0 when succeed, -1 on error. | 298 | * Return: 0 when succeed, -1 on error. |
299 | * | 299 | * |
300 | * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? | 300 | * ToDo: 1. Is it necessary to check_free_sector after erasing ?? |
301 | */ | 301 | */ |
302 | int NFTL_formatblock(struct NFTLrecord *nftl, int block) | 302 | int NFTL_formatblock(struct NFTLrecord *nftl, int block) |
303 | { | 303 | { |
@@ -337,7 +337,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block) | |||
337 | nb_erases = le32_to_cpu(uci.WearInfo); | 337 | nb_erases = le32_to_cpu(uci.WearInfo); |
338 | nb_erases++; | 338 | nb_erases++; |
339 | 339 | ||
340 | /* wrap (almost impossible with current flashs) or free block */ | 340 | /* wrap (almost impossible with current flash) or free block */ |
341 | if (nb_erases == 0) | 341 | if (nb_erases == 0) |
342 | nb_erases = 1; | 342 | nb_erases = 1; |
343 | 343 | ||
@@ -363,10 +363,10 @@ fail: | |||
363 | * Mark as 'IGNORE' each incorrect sector. This check is only done if the chain | 363 | * Mark as 'IGNORE' each incorrect sector. This check is only done if the chain |
364 | * was being folded when NFTL was interrupted. | 364 | * was being folded when NFTL was interrupted. |
365 | * | 365 | * |
366 | * The check_free_sectors in this function is neceressary. There is a possible | 366 | * The check_free_sectors in this function is necessary. There is a possible |
367 | * situation that after writing the Data area, the Block Control Information is | 367 | * situation that after writing the Data area, the Block Control Information is |
368 | * not updated according (due to power failure or something) which leaves the block | 368 | * not updated according (due to power failure or something) which leaves the block |
369 | * in an umconsistent state. So we have to check if a block is really FREE in this | 369 | * in an inconsistent state. So we have to check if a block is really FREE in this |
370 | * case. */ | 370 | * case. */ |
371 | static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block) | 371 | static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block) |
372 | { | 372 | { |
@@ -428,7 +428,7 @@ static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block) | |||
428 | 428 | ||
429 | for (;;) { | 429 | for (;;) { |
430 | length++; | 430 | length++; |
431 | /* avoid infinite loops, although this is guaranted not to | 431 | /* avoid infinite loops, although this is guaranteed not to |
432 | happen because of the previous checks */ | 432 | happen because of the previous checks */ |
433 | if (length >= nftl->nb_blocks) { | 433 | if (length >= nftl->nb_blocks) { |
434 | printk("nftl: length too long %d !\n", length); | 434 | printk("nftl: length too long %d !\n", length); |
@@ -447,11 +447,11 @@ static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block) | |||
447 | /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a | 447 | /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a |
448 | * Virtual Unit Chain, i.e. all the units are disconnected. | 448 | * Virtual Unit Chain, i.e. all the units are disconnected. |
449 | * | 449 | * |
450 | * It is not stricly correct to begin from the first block of the chain because | 450 | * It is not strictly correct to begin from the first block of the chain because |
451 | * if we stop the code, we may see again a valid chain if there was a first_block | 451 | * if we stop the code, we may see again a valid chain if there was a first_block |
452 | * flag in a block inside it. But is it really a problem ? | 452 | * flag in a block inside it. But is it really a problem ? |
453 | * | 453 | * |
454 | * FixMe: Figure out what the last statesment means. What if power failure when we are | 454 | * FixMe: Figure out what the last statement means. What if power failure when we are |
455 | * in the for (;;) loop formatting blocks ?? | 455 | * in the for (;;) loop formatting blocks ?? |
456 | */ | 456 | */ |
457 | static void format_chain(struct NFTLrecord *nftl, unsigned int first_block) | 457 | static void format_chain(struct NFTLrecord *nftl, unsigned int first_block) |
@@ -485,7 +485,7 @@ static void format_chain(struct NFTLrecord *nftl, unsigned int first_block) | |||
485 | * totally free (only 0xff). | 485 | * totally free (only 0xff). |
486 | * | 486 | * |
487 | * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the | 487 | * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the |
488 | * following critia: | 488 | * following criteria: |
489 | * 1. */ | 489 | * 1. */ |
490 | static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | 490 | static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) |
491 | { | 491 | { |
@@ -502,7 +502,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | |||
502 | erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); | 502 | erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); |
503 | if (erase_mark != ERASE_MARK) { | 503 | if (erase_mark != ERASE_MARK) { |
504 | /* if no erase mark, the block must be totally free. This is | 504 | /* if no erase mark, the block must be totally free. This is |
505 | possible in two cases : empty filsystem or interrupted erase (very unlikely) */ | 505 | possible in two cases : empty filesystem or interrupted erase (very unlikely) */ |
506 | if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0) | 506 | if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0) |
507 | return -1; | 507 | return -1; |
508 | 508 | ||
@@ -544,7 +544,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | |||
544 | /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS | 544 | /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS |
545 | * to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2 | 545 | * to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2 |
546 | * is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted | 546 | * is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted |
547 | * for some reason. A clean up/check of the VUC is neceressary in this case. | 547 | * for some reason. A clean up/check of the VUC is necessary in this case. |
548 | * | 548 | * |
549 | * WARNING: return 0 if read error | 549 | * WARNING: return 0 if read error |
550 | */ | 550 | */ |
@@ -657,7 +657,7 @@ int NFTL_mount(struct NFTLrecord *s) | |||
657 | printk("Block %d: incorrect logical block: %d expected: %d\n", | 657 | printk("Block %d: incorrect logical block: %d expected: %d\n", |
658 | block, logical_block, first_logical_block); | 658 | block, logical_block, first_logical_block); |
659 | /* the chain is incorrect : we must format it, | 659 | /* the chain is incorrect : we must format it, |
660 | but we need to read it completly */ | 660 | but we need to read it completely */ |
661 | do_format_chain = 1; | 661 | do_format_chain = 1; |
662 | } | 662 | } |
663 | if (is_first_block) { | 663 | if (is_first_block) { |
@@ -669,7 +669,7 @@ int NFTL_mount(struct NFTLrecord *s) | |||
669 | printk("Block %d: incorrectly marked as first block in chain\n", | 669 | printk("Block %d: incorrectly marked as first block in chain\n", |
670 | block); | 670 | block); |
671 | /* the chain is incorrect : we must format it, | 671 | /* the chain is incorrect : we must format it, |
672 | but we need to read it completly */ | 672 | but we need to read it completely */ |
673 | do_format_chain = 1; | 673 | do_format_chain = 1; |
674 | } else { | 674 | } else { |
675 | printk("Block %d: folding in progress - ignoring first block flag\n", | 675 | printk("Block %d: folding in progress - ignoring first block flag\n", |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index a996718fa6b0..64be8f0848b0 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -20,14 +20,23 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/mtd/partitions.h> | 21 | #include <linux/mtd/partitions.h> |
22 | 22 | ||
23 | int __devinit of_mtd_parse_partitions(struct device *dev, | 23 | static int parse_ofpart_partitions(struct mtd_info *master, |
24 | struct device_node *node, | 24 | struct mtd_partition **pparts, |
25 | struct mtd_partition **pparts) | 25 | struct mtd_part_parser_data *data) |
26 | { | 26 | { |
27 | struct device_node *node; | ||
27 | const char *partname; | 28 | const char *partname; |
28 | struct device_node *pp; | 29 | struct device_node *pp; |
29 | int nr_parts, i; | 30 | int nr_parts, i; |
30 | 31 | ||
32 | |||
33 | if (!data) | ||
34 | return 0; | ||
35 | |||
36 | node = data->of_node; | ||
37 | if (!node) | ||
38 | return 0; | ||
39 | |||
31 | /* First count the subnodes */ | 40 | /* First count the subnodes */ |
32 | pp = NULL; | 41 | pp = NULL; |
33 | nr_parts = 0; | 42 | nr_parts = 0; |
@@ -69,7 +78,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev, | |||
69 | 78 | ||
70 | if (!i) { | 79 | if (!i) { |
71 | of_node_put(pp); | 80 | of_node_put(pp); |
72 | dev_err(dev, "No valid partition found on %s\n", node->full_name); | 81 | pr_err("No valid partition found on %s\n", node->full_name); |
73 | kfree(*pparts); | 82 | kfree(*pparts); |
74 | *pparts = NULL; | 83 | *pparts = NULL; |
75 | return -EINVAL; | 84 | return -EINVAL; |
@@ -77,6 +86,99 @@ int __devinit of_mtd_parse_partitions(struct device *dev, | |||
77 | 86 | ||
78 | return nr_parts; | 87 | return nr_parts; |
79 | } | 88 | } |
80 | EXPORT_SYMBOL(of_mtd_parse_partitions); | 89 | |
90 | static struct mtd_part_parser ofpart_parser = { | ||
91 | .owner = THIS_MODULE, | ||
92 | .parse_fn = parse_ofpart_partitions, | ||
93 | .name = "ofpart", | ||
94 | }; | ||
95 | |||
96 | static int parse_ofoldpart_partitions(struct mtd_info *master, | ||
97 | struct mtd_partition **pparts, | ||
98 | struct mtd_part_parser_data *data) | ||
99 | { | ||
100 | struct device_node *dp; | ||
101 | int i, plen, nr_parts; | ||
102 | const struct { | ||
103 | __be32 offset, len; | ||
104 | } *part; | ||
105 | const char *names; | ||
106 | |||
107 | if (!data) | ||
108 | return 0; | ||
109 | |||
110 | dp = data->of_node; | ||
111 | if (!dp) | ||
112 | return 0; | ||
113 | |||
114 | part = of_get_property(dp, "partitions", &plen); | ||
115 | if (!part) | ||
116 | return 0; /* No partitions found */ | ||
117 | |||
118 | pr_warning("Device tree uses obsolete partition map binding: %s\n", | ||
119 | dp->full_name); | ||
120 | |||
121 | nr_parts = plen / sizeof(part[0]); | ||
122 | |||
123 | *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); | ||
124 | if (!pparts) | ||
125 | return -ENOMEM; | ||
126 | |||
127 | names = of_get_property(dp, "partition-names", &plen); | ||
128 | |||
129 | for (i = 0; i < nr_parts; i++) { | ||
130 | (*pparts)[i].offset = be32_to_cpu(part->offset); | ||
131 | (*pparts)[i].size = be32_to_cpu(part->len) & ~1; | ||
132 | /* bit 0 set signifies read only partition */ | ||
133 | if (be32_to_cpu(part->len) & 1) | ||
134 | (*pparts)[i].mask_flags = MTD_WRITEABLE; | ||
135 | |||
136 | if (names && (plen > 0)) { | ||
137 | int len = strlen(names) + 1; | ||
138 | |||
139 | (*pparts)[i].name = (char *)names; | ||
140 | plen -= len; | ||
141 | names += len; | ||
142 | } else { | ||
143 | (*pparts)[i].name = "unnamed"; | ||
144 | } | ||
145 | |||
146 | part++; | ||
147 | } | ||
148 | |||
149 | return nr_parts; | ||
150 | } | ||
151 | |||
152 | static struct mtd_part_parser ofoldpart_parser = { | ||
153 | .owner = THIS_MODULE, | ||
154 | .parse_fn = parse_ofoldpart_partitions, | ||
155 | .name = "ofoldpart", | ||
156 | }; | ||
157 | |||
158 | static int __init ofpart_parser_init(void) | ||
159 | { | ||
160 | int rc; | ||
161 | rc = register_mtd_parser(&ofpart_parser); | ||
162 | if (rc) | ||
163 | goto out; | ||
164 | |||
165 | rc = register_mtd_parser(&ofoldpart_parser); | ||
166 | if (!rc) | ||
167 | return 0; | ||
168 | |||
169 | deregister_mtd_parser(&ofoldpart_parser); | ||
170 | out: | ||
171 | return rc; | ||
172 | } | ||
173 | |||
174 | module_init(ofpart_parser_init); | ||
81 | 175 | ||
82 | MODULE_LICENSE("GPL"); | 176 | MODULE_LICENSE("GPL"); |
177 | MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree"); | ||
178 | MODULE_AUTHOR("Vitaly Wool, David Gibson"); | ||
179 | /* | ||
180 | * When MTD core cannot find the requested parser, it tries to load the module | ||
181 | * with the same name. Since we provide the ofoldpart parser, we should have | ||
182 | * the corresponding alias. | ||
183 | */ | ||
184 | MODULE_ALIAS("ofoldpart"); | ||
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 2d70d354d846..7813095264a5 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -30,11 +30,8 @@ | |||
30 | */ | 30 | */ |
31 | #define DRIVER_NAME "onenand-flash" | 31 | #define DRIVER_NAME "onenand-flash" |
32 | 32 | ||
33 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
34 | |||
35 | struct onenand_info { | 33 | struct onenand_info { |
36 | struct mtd_info mtd; | 34 | struct mtd_info mtd; |
37 | struct mtd_partition *parts; | ||
38 | struct onenand_chip onenand; | 35 | struct onenand_chip onenand; |
39 | }; | 36 | }; |
40 | 37 | ||
@@ -73,13 +70,9 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev) | |||
73 | goto out_iounmap; | 70 | goto out_iounmap; |
74 | } | 71 | } |
75 | 72 | ||
76 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); | 73 | err = mtd_device_parse_register(&info->mtd, NULL, 0, |
77 | if (err > 0) | 74 | pdata ? pdata->parts : NULL, |
78 | mtd_device_register(&info->mtd, info->parts, err); | 75 | pdata ? pdata->nr_parts : 0); |
79 | else if (err <= 0 && pdata && pdata->parts) | ||
80 | mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts); | ||
81 | else | ||
82 | err = mtd_device_register(&info->mtd, NULL, 0); | ||
83 | 76 | ||
84 | platform_set_drvdata(pdev, info); | 77 | platform_set_drvdata(pdev, info); |
85 | 78 | ||
@@ -104,7 +97,6 @@ static int __devexit generic_onenand_remove(struct platform_device *pdev) | |||
104 | platform_set_drvdata(pdev, NULL); | 97 | platform_set_drvdata(pdev, NULL); |
105 | 98 | ||
106 | if (info) { | 99 | if (info) { |
107 | mtd_device_unregister(&info->mtd); | ||
108 | onenand_release(&info->mtd); | 100 | onenand_release(&info->mtd); |
109 | release_mem_region(res->start, size); | 101 | release_mem_region(res->start, size); |
110 | iounmap(info->onenand.base); | 102 | iounmap(info->onenand.base); |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 6a1d6d9a2df9..7e9ea6852b67 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -57,7 +57,6 @@ struct omap2_onenand { | |||
57 | unsigned long phys_base; | 57 | unsigned long phys_base; |
58 | int gpio_irq; | 58 | int gpio_irq; |
59 | struct mtd_info mtd; | 59 | struct mtd_info mtd; |
60 | struct mtd_partition *parts; | ||
61 | struct onenand_chip onenand; | 60 | struct onenand_chip onenand; |
62 | struct completion irq_done; | 61 | struct completion irq_done; |
63 | struct completion dma_done; | 62 | struct completion dma_done; |
@@ -67,8 +66,6 @@ struct omap2_onenand { | |||
67 | struct regulator *regulator; | 66 | struct regulator *regulator; |
68 | }; | 67 | }; |
69 | 68 | ||
70 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
71 | |||
72 | static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) | 69 | static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) |
73 | { | 70 | { |
74 | struct omap2_onenand *c = data; | 71 | struct omap2_onenand *c = data; |
@@ -741,6 +738,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) | |||
741 | c->regulator = regulator_get(&pdev->dev, "vonenand"); | 738 | c->regulator = regulator_get(&pdev->dev, "vonenand"); |
742 | if (IS_ERR(c->regulator)) { | 739 | if (IS_ERR(c->regulator)) { |
743 | dev_err(&pdev->dev, "Failed to get regulator\n"); | 740 | dev_err(&pdev->dev, "Failed to get regulator\n"); |
741 | r = PTR_ERR(c->regulator); | ||
744 | goto err_release_dma; | 742 | goto err_release_dma; |
745 | } | 743 | } |
746 | c->onenand.enable = omap2_onenand_enable; | 744 | c->onenand.enable = omap2_onenand_enable; |
@@ -753,13 +751,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) | |||
753 | if ((r = onenand_scan(&c->mtd, 1)) < 0) | 751 | if ((r = onenand_scan(&c->mtd, 1)) < 0) |
754 | goto err_release_regulator; | 752 | goto err_release_regulator; |
755 | 753 | ||
756 | r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0); | 754 | r = mtd_device_parse_register(&c->mtd, NULL, 0, |
757 | if (r > 0) | 755 | pdata ? pdata->parts : NULL, |
758 | r = mtd_device_register(&c->mtd, c->parts, r); | 756 | pdata ? pdata->nr_parts : 0); |
759 | else if (pdata->parts != NULL) | ||
760 | r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts); | ||
761 | else | ||
762 | r = mtd_device_register(&c->mtd, NULL, 0); | ||
763 | if (r) | 757 | if (r) |
764 | goto err_release_onenand; | 758 | goto err_release_onenand; |
765 | 759 | ||
@@ -786,7 +780,6 @@ err_release_mem_region: | |||
786 | err_free_cs: | 780 | err_free_cs: |
787 | gpmc_cs_free(c->gpmc_cs); | 781 | gpmc_cs_free(c->gpmc_cs); |
788 | err_kfree: | 782 | err_kfree: |
789 | kfree(c->parts); | ||
790 | kfree(c); | 783 | kfree(c); |
791 | 784 | ||
792 | return r; | 785 | return r; |
@@ -809,7 +802,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) | |||
809 | iounmap(c->onenand.base); | 802 | iounmap(c->onenand.base); |
810 | release_mem_region(c->phys_base, ONENAND_IO_SIZE); | 803 | release_mem_region(c->phys_base, ONENAND_IO_SIZE); |
811 | gpmc_cs_free(c->gpmc_cs); | 804 | gpmc_cs_free(c->gpmc_cs); |
812 | kfree(c->parts); | ||
813 | kfree(c); | 805 | kfree(c); |
814 | 806 | ||
815 | return 0; | 807 | return 0; |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index ac9e959802a7..a8394730b4b6 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -1015,7 +1015,7 @@ static void onenand_release_device(struct mtd_info *mtd) | |||
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | /** | 1017 | /** |
1018 | * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer | 1018 | * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer |
1019 | * @param mtd MTD device structure | 1019 | * @param mtd MTD device structure |
1020 | * @param buf destination address | 1020 | * @param buf destination address |
1021 | * @param column oob offset to read from | 1021 | * @param column oob offset to read from |
@@ -1079,7 +1079,7 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status) | |||
1079 | return status; | 1079 | return status; |
1080 | 1080 | ||
1081 | /* check if we failed due to uncorrectable error */ | 1081 | /* check if we failed due to uncorrectable error */ |
1082 | if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR) | 1082 | if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR) |
1083 | return status; | 1083 | return status; |
1084 | 1084 | ||
1085 | /* check if address lies in MLC region */ | 1085 | /* check if address lies in MLC region */ |
@@ -1122,10 +1122,10 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1122 | int ret = 0; | 1122 | int ret = 0; |
1123 | int writesize = this->writesize; | 1123 | int writesize = this->writesize; |
1124 | 1124 | ||
1125 | DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n", | 1125 | pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from, |
1126 | __func__, (unsigned int) from, (int) len); | 1126 | (int)len); |
1127 | 1127 | ||
1128 | if (ops->mode == MTD_OOB_AUTO) | 1128 | if (ops->mode == MTD_OPS_AUTO_OOB) |
1129 | oobsize = this->ecclayout->oobavail; | 1129 | oobsize = this->ecclayout->oobavail; |
1130 | else | 1130 | else |
1131 | oobsize = mtd->oobsize; | 1131 | oobsize = mtd->oobsize; |
@@ -1159,7 +1159,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1159 | if (unlikely(ret)) | 1159 | if (unlikely(ret)) |
1160 | ret = onenand_recover_lsb(mtd, from, ret); | 1160 | ret = onenand_recover_lsb(mtd, from, ret); |
1161 | onenand_update_bufferram(mtd, from, !ret); | 1161 | onenand_update_bufferram(mtd, from, !ret); |
1162 | if (ret == -EBADMSG) | 1162 | if (mtd_is_eccerr(ret)) |
1163 | ret = 0; | 1163 | ret = 0; |
1164 | if (ret) | 1164 | if (ret) |
1165 | break; | 1165 | break; |
@@ -1170,7 +1170,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1170 | thisooblen = oobsize - oobcolumn; | 1170 | thisooblen = oobsize - oobcolumn; |
1171 | thisooblen = min_t(int, thisooblen, ooblen - oobread); | 1171 | thisooblen = min_t(int, thisooblen, ooblen - oobread); |
1172 | 1172 | ||
1173 | if (ops->mode == MTD_OOB_AUTO) | 1173 | if (ops->mode == MTD_OPS_AUTO_OOB) |
1174 | onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); | 1174 | onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); |
1175 | else | 1175 | else |
1176 | this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); | 1176 | this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); |
@@ -1226,10 +1226,10 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1226 | int ret = 0, boundary = 0; | 1226 | int ret = 0, boundary = 0; |
1227 | int writesize = this->writesize; | 1227 | int writesize = this->writesize; |
1228 | 1228 | ||
1229 | DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n", | 1229 | pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from, |
1230 | __func__, (unsigned int) from, (int) len); | 1230 | (int)len); |
1231 | 1231 | ||
1232 | if (ops->mode == MTD_OOB_AUTO) | 1232 | if (ops->mode == MTD_OPS_AUTO_OOB) |
1233 | oobsize = this->ecclayout->oobavail; | 1233 | oobsize = this->ecclayout->oobavail; |
1234 | else | 1234 | else |
1235 | oobsize = mtd->oobsize; | 1235 | oobsize = mtd->oobsize; |
@@ -1255,7 +1255,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1255 | this->command(mtd, ONENAND_CMD_READ, from, writesize); | 1255 | this->command(mtd, ONENAND_CMD_READ, from, writesize); |
1256 | ret = this->wait(mtd, FL_READING); | 1256 | ret = this->wait(mtd, FL_READING); |
1257 | onenand_update_bufferram(mtd, from, !ret); | 1257 | onenand_update_bufferram(mtd, from, !ret); |
1258 | if (ret == -EBADMSG) | 1258 | if (mtd_is_eccerr(ret)) |
1259 | ret = 0; | 1259 | ret = 0; |
1260 | } | 1260 | } |
1261 | } | 1261 | } |
@@ -1291,7 +1291,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1291 | thisooblen = oobsize - oobcolumn; | 1291 | thisooblen = oobsize - oobcolumn; |
1292 | thisooblen = min_t(int, thisooblen, ooblen - oobread); | 1292 | thisooblen = min_t(int, thisooblen, ooblen - oobread); |
1293 | 1293 | ||
1294 | if (ops->mode == MTD_OOB_AUTO) | 1294 | if (ops->mode == MTD_OPS_AUTO_OOB) |
1295 | onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); | 1295 | onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); |
1296 | else | 1296 | else |
1297 | this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); | 1297 | this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); |
@@ -1315,7 +1315,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1315 | /* Now wait for load */ | 1315 | /* Now wait for load */ |
1316 | ret = this->wait(mtd, FL_READING); | 1316 | ret = this->wait(mtd, FL_READING); |
1317 | onenand_update_bufferram(mtd, from, !ret); | 1317 | onenand_update_bufferram(mtd, from, !ret); |
1318 | if (ret == -EBADMSG) | 1318 | if (mtd_is_eccerr(ret)) |
1319 | ret = 0; | 1319 | ret = 0; |
1320 | } | 1320 | } |
1321 | 1321 | ||
@@ -1351,19 +1351,19 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, | |||
1351 | struct mtd_ecc_stats stats; | 1351 | struct mtd_ecc_stats stats; |
1352 | int read = 0, thislen, column, oobsize; | 1352 | int read = 0, thislen, column, oobsize; |
1353 | size_t len = ops->ooblen; | 1353 | size_t len = ops->ooblen; |
1354 | mtd_oob_mode_t mode = ops->mode; | 1354 | unsigned int mode = ops->mode; |
1355 | u_char *buf = ops->oobbuf; | 1355 | u_char *buf = ops->oobbuf; |
1356 | int ret = 0, readcmd; | 1356 | int ret = 0, readcmd; |
1357 | 1357 | ||
1358 | from += ops->ooboffs; | 1358 | from += ops->ooboffs; |
1359 | 1359 | ||
1360 | DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n", | 1360 | pr_debug("%s: from = 0x%08x, len = %i\n", __func__, (unsigned int)from, |
1361 | __func__, (unsigned int) from, (int) len); | 1361 | (int)len); |
1362 | 1362 | ||
1363 | /* Initialize return length value */ | 1363 | /* Initialize return length value */ |
1364 | ops->oobretlen = 0; | 1364 | ops->oobretlen = 0; |
1365 | 1365 | ||
1366 | if (mode == MTD_OOB_AUTO) | 1366 | if (mode == MTD_OPS_AUTO_OOB) |
1367 | oobsize = this->ecclayout->oobavail; | 1367 | oobsize = this->ecclayout->oobavail; |
1368 | else | 1368 | else |
1369 | oobsize = mtd->oobsize; | 1369 | oobsize = mtd->oobsize; |
@@ -1403,13 +1403,13 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, | |||
1403 | if (unlikely(ret)) | 1403 | if (unlikely(ret)) |
1404 | ret = onenand_recover_lsb(mtd, from, ret); | 1404 | ret = onenand_recover_lsb(mtd, from, ret); |
1405 | 1405 | ||
1406 | if (ret && ret != -EBADMSG) { | 1406 | if (ret && !mtd_is_eccerr(ret)) { |
1407 | printk(KERN_ERR "%s: read failed = 0x%x\n", | 1407 | printk(KERN_ERR "%s: read failed = 0x%x\n", |
1408 | __func__, ret); | 1408 | __func__, ret); |
1409 | break; | 1409 | break; |
1410 | } | 1410 | } |
1411 | 1411 | ||
1412 | if (mode == MTD_OOB_AUTO) | 1412 | if (mode == MTD_OPS_AUTO_OOB) |
1413 | onenand_transfer_auto_oob(mtd, buf, column, thislen); | 1413 | onenand_transfer_auto_oob(mtd, buf, column, thislen); |
1414 | else | 1414 | else |
1415 | this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); | 1415 | this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); |
@@ -1487,10 +1487,10 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1487 | int ret; | 1487 | int ret; |
1488 | 1488 | ||
1489 | switch (ops->mode) { | 1489 | switch (ops->mode) { |
1490 | case MTD_OOB_PLACE: | 1490 | case MTD_OPS_PLACE_OOB: |
1491 | case MTD_OOB_AUTO: | 1491 | case MTD_OPS_AUTO_OOB: |
1492 | break; | 1492 | break; |
1493 | case MTD_OOB_RAW: | 1493 | case MTD_OPS_RAW: |
1494 | /* Not implemented yet */ | 1494 | /* Not implemented yet */ |
1495 | default: | 1495 | default: |
1496 | return -EINVAL; | 1496 | return -EINVAL; |
@@ -1576,8 +1576,8 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, | |||
1576 | size_t len = ops->ooblen; | 1576 | size_t len = ops->ooblen; |
1577 | u_char *buf = ops->oobbuf; | 1577 | u_char *buf = ops->oobbuf; |
1578 | 1578 | ||
1579 | DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n", | 1579 | pr_debug("%s: from = 0x%08x, len = %zi\n", __func__, (unsigned int)from, |
1580 | __func__, (unsigned int) from, len); | 1580 | len); |
1581 | 1581 | ||
1582 | /* Initialize return value */ | 1582 | /* Initialize return value */ |
1583 | ops->oobretlen = 0; | 1583 | ops->oobretlen = 0; |
@@ -1750,8 +1750,8 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
1750 | /* Wait for any existing operation to clear */ | 1750 | /* Wait for any existing operation to clear */ |
1751 | onenand_panic_wait(mtd); | 1751 | onenand_panic_wait(mtd); |
1752 | 1752 | ||
1753 | DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n", | 1753 | pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, |
1754 | __func__, (unsigned int) to, (int) len); | 1754 | (int)len); |
1755 | 1755 | ||
1756 | /* Initialize retlen, in case of early exit */ | 1756 | /* Initialize retlen, in case of early exit */ |
1757 | *retlen = 0; | 1757 | *retlen = 0; |
@@ -1821,7 +1821,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
1821 | } | 1821 | } |
1822 | 1822 | ||
1823 | /** | 1823 | /** |
1824 | * onenand_fill_auto_oob - [Internal] oob auto-placement transfer | 1824 | * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer |
1825 | * @param mtd MTD device structure | 1825 | * @param mtd MTD device structure |
1826 | * @param oob_buf oob buffer | 1826 | * @param oob_buf oob buffer |
1827 | * @param buf source address | 1827 | * @param buf source address |
@@ -1883,8 +1883,8 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
1883 | u_char *oobbuf; | 1883 | u_char *oobbuf; |
1884 | int ret = 0, cmd; | 1884 | int ret = 0, cmd; |
1885 | 1885 | ||
1886 | DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n", | 1886 | pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, |
1887 | __func__, (unsigned int) to, (int) len); | 1887 | (int)len); |
1888 | 1888 | ||
1889 | /* Initialize retlen, in case of early exit */ | 1889 | /* Initialize retlen, in case of early exit */ |
1890 | ops->retlen = 0; | 1890 | ops->retlen = 0; |
@@ -1908,7 +1908,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
1908 | if (!len) | 1908 | if (!len) |
1909 | return 0; | 1909 | return 0; |
1910 | 1910 | ||
1911 | if (ops->mode == MTD_OOB_AUTO) | 1911 | if (ops->mode == MTD_OPS_AUTO_OOB) |
1912 | oobsize = this->ecclayout->oobavail; | 1912 | oobsize = this->ecclayout->oobavail; |
1913 | else | 1913 | else |
1914 | oobsize = mtd->oobsize; | 1914 | oobsize = mtd->oobsize; |
@@ -1945,7 +1945,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
1945 | /* We send data to spare ram with oobsize | 1945 | /* We send data to spare ram with oobsize |
1946 | * to prevent byte access */ | 1946 | * to prevent byte access */ |
1947 | memset(oobbuf, 0xff, mtd->oobsize); | 1947 | memset(oobbuf, 0xff, mtd->oobsize); |
1948 | if (ops->mode == MTD_OOB_AUTO) | 1948 | if (ops->mode == MTD_OPS_AUTO_OOB) |
1949 | onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen); | 1949 | onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen); |
1950 | else | 1950 | else |
1951 | memcpy(oobbuf + oobcolumn, oob, thisooblen); | 1951 | memcpy(oobbuf + oobcolumn, oob, thisooblen); |
@@ -2055,7 +2055,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
2055 | 2055 | ||
2056 | 2056 | ||
2057 | /** | 2057 | /** |
2058 | * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band | 2058 | * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band |
2059 | * @param mtd MTD device structure | 2059 | * @param mtd MTD device structure |
2060 | * @param to offset to write to | 2060 | * @param to offset to write to |
2061 | * @param len number of bytes to write | 2061 | * @param len number of bytes to write |
@@ -2074,17 +2074,17 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, | |||
2074 | u_char *oobbuf; | 2074 | u_char *oobbuf; |
2075 | size_t len = ops->ooblen; | 2075 | size_t len = ops->ooblen; |
2076 | const u_char *buf = ops->oobbuf; | 2076 | const u_char *buf = ops->oobbuf; |
2077 | mtd_oob_mode_t mode = ops->mode; | 2077 | unsigned int mode = ops->mode; |
2078 | 2078 | ||
2079 | to += ops->ooboffs; | 2079 | to += ops->ooboffs; |
2080 | 2080 | ||
2081 | DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n", | 2081 | pr_debug("%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, |
2082 | __func__, (unsigned int) to, (int) len); | 2082 | (int)len); |
2083 | 2083 | ||
2084 | /* Initialize retlen, in case of early exit */ | 2084 | /* Initialize retlen, in case of early exit */ |
2085 | ops->oobretlen = 0; | 2085 | ops->oobretlen = 0; |
2086 | 2086 | ||
2087 | if (mode == MTD_OOB_AUTO) | 2087 | if (mode == MTD_OPS_AUTO_OOB) |
2088 | oobsize = this->ecclayout->oobavail; | 2088 | oobsize = this->ecclayout->oobavail; |
2089 | else | 2089 | else |
2090 | oobsize = mtd->oobsize; | 2090 | oobsize = mtd->oobsize; |
@@ -2128,7 +2128,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, | |||
2128 | /* We send data to spare ram with oobsize | 2128 | /* We send data to spare ram with oobsize |
2129 | * to prevent byte access */ | 2129 | * to prevent byte access */ |
2130 | memset(oobbuf, 0xff, mtd->oobsize); | 2130 | memset(oobbuf, 0xff, mtd->oobsize); |
2131 | if (mode == MTD_OOB_AUTO) | 2131 | if (mode == MTD_OPS_AUTO_OOB) |
2132 | onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen); | 2132 | onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen); |
2133 | else | 2133 | else |
2134 | memcpy(oobbuf + column, buf, thislen); | 2134 | memcpy(oobbuf + column, buf, thislen); |
@@ -2217,10 +2217,10 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2217 | int ret; | 2217 | int ret; |
2218 | 2218 | ||
2219 | switch (ops->mode) { | 2219 | switch (ops->mode) { |
2220 | case MTD_OOB_PLACE: | 2220 | case MTD_OPS_PLACE_OOB: |
2221 | case MTD_OOB_AUTO: | 2221 | case MTD_OPS_AUTO_OOB: |
2222 | break; | 2222 | break; |
2223 | case MTD_OOB_RAW: | 2223 | case MTD_OPS_RAW: |
2224 | /* Not implemented yet */ | 2224 | /* Not implemented yet */ |
2225 | default: | 2225 | default: |
2226 | return -EINVAL; | 2226 | return -EINVAL; |
@@ -2281,7 +2281,7 @@ static int onenand_multiblock_erase_verify(struct mtd_info *mtd, | |||
2281 | } | 2281 | } |
2282 | 2282 | ||
2283 | /** | 2283 | /** |
2284 | * onenand_multiblock_erase - [Internal] erase block(s) using multiblock erase | 2284 | * onenand_multiblock_erase - [INTERN] erase block(s) using multiblock erase |
2285 | * @param mtd MTD device structure | 2285 | * @param mtd MTD device structure |
2286 | * @param instr erase instruction | 2286 | * @param instr erase instruction |
2287 | * @param region erase region | 2287 | * @param region erase region |
@@ -2397,7 +2397,7 @@ static int onenand_multiblock_erase(struct mtd_info *mtd, | |||
2397 | 2397 | ||
2398 | 2398 | ||
2399 | /** | 2399 | /** |
2400 | * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase | 2400 | * onenand_block_by_block_erase - [INTERN] erase block(s) using regular erase |
2401 | * @param mtd MTD device structure | 2401 | * @param mtd MTD device structure |
2402 | * @param instr erase instruction | 2402 | * @param instr erase instruction |
2403 | * @param region erase region | 2403 | * @param region erase region |
@@ -2489,8 +2489,9 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
2489 | struct mtd_erase_region_info *region = NULL; | 2489 | struct mtd_erase_region_info *region = NULL; |
2490 | loff_t region_offset = 0; | 2490 | loff_t region_offset = 0; |
2491 | 2491 | ||
2492 | DEBUG(MTD_DEBUG_LEVEL3, "%s: start=0x%012llx, len=%llu\n", __func__, | 2492 | pr_debug("%s: start=0x%012llx, len=%llu\n", __func__, |
2493 | (unsigned long long) instr->addr, (unsigned long long) instr->len); | 2493 | (unsigned long long)instr->addr, |
2494 | (unsigned long long)instr->len); | ||
2494 | 2495 | ||
2495 | /* Do not allow erase past end of device */ | 2496 | /* Do not allow erase past end of device */ |
2496 | if (unlikely((len + addr) > mtd->size)) { | 2497 | if (unlikely((len + addr) > mtd->size)) { |
@@ -2558,7 +2559,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
2558 | */ | 2559 | */ |
2559 | static void onenand_sync(struct mtd_info *mtd) | 2560 | static void onenand_sync(struct mtd_info *mtd) |
2560 | { | 2561 | { |
2561 | DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__); | 2562 | pr_debug("%s: called\n", __func__); |
2562 | 2563 | ||
2563 | /* Grab the lock and see if the device is available */ | 2564 | /* Grab the lock and see if the device is available */ |
2564 | onenand_get_device(mtd, FL_SYNCING); | 2565 | onenand_get_device(mtd, FL_SYNCING); |
@@ -2602,7 +2603,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
2602 | struct bbm_info *bbm = this->bbm; | 2603 | struct bbm_info *bbm = this->bbm; |
2603 | u_char buf[2] = {0, 0}; | 2604 | u_char buf[2] = {0, 0}; |
2604 | struct mtd_oob_ops ops = { | 2605 | struct mtd_oob_ops ops = { |
2605 | .mode = MTD_OOB_PLACE, | 2606 | .mode = MTD_OPS_PLACE_OOB, |
2606 | .ooblen = 2, | 2607 | .ooblen = 2, |
2607 | .oobbuf = buf, | 2608 | .oobbuf = buf, |
2608 | .ooboffs = 0, | 2609 | .ooboffs = 0, |
@@ -2922,7 +2923,7 @@ static int onenand_otp_command(struct mtd_info *mtd, int cmd, loff_t addr, | |||
2922 | } | 2923 | } |
2923 | 2924 | ||
2924 | /** | 2925 | /** |
2925 | * onenand_otp_write_oob_nolock - [Internal] OneNAND write out-of-band, specific to OTP | 2926 | * onenand_otp_write_oob_nolock - [INTERN] OneNAND write out-of-band, specific to OTP |
2926 | * @param mtd MTD device structure | 2927 | * @param mtd MTD device structure |
2927 | * @param to offset to write to | 2928 | * @param to offset to write to |
2928 | * @param len number of bytes to write | 2929 | * @param len number of bytes to write |
@@ -3170,7 +3171,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len, | |||
3170 | this->command(mtd, ONENAND_CMD_RESET, 0, 0); | 3171 | this->command(mtd, ONENAND_CMD_RESET, 0, 0); |
3171 | this->wait(mtd, FL_RESETING); | 3172 | this->wait(mtd, FL_RESETING); |
3172 | } else { | 3173 | } else { |
3173 | ops.mode = MTD_OOB_PLACE; | 3174 | ops.mode = MTD_OPS_PLACE_OOB; |
3174 | ops.ooblen = len; | 3175 | ops.ooblen = len; |
3175 | ops.oobbuf = buf; | 3176 | ops.oobbuf = buf; |
3176 | ops.ooboffs = 0; | 3177 | ops.ooboffs = 0; |
@@ -3429,6 +3430,19 @@ static void onenand_check_features(struct mtd_info *mtd) | |||
3429 | else if (numbufs == 1) { | 3430 | else if (numbufs == 1) { |
3430 | this->options |= ONENAND_HAS_4KB_PAGE; | 3431 | this->options |= ONENAND_HAS_4KB_PAGE; |
3431 | this->options |= ONENAND_HAS_CACHE_PROGRAM; | 3432 | this->options |= ONENAND_HAS_CACHE_PROGRAM; |
3433 | /* | ||
3434 | * There are two different 4KiB pagesize chips | ||
3435 | * and no way to detect it by H/W config values. | ||
3436 | * | ||
3437 | * To detect the correct NOP for each chips, | ||
3438 | * It should check the version ID as workaround. | ||
3439 | * | ||
3440 | * Now it has as following | ||
3441 | * KFM4G16Q4M has NOP 4 with version ID 0x0131 | ||
3442 | * KFM4G16Q5M has NOP 1 with versoin ID 0x013e | ||
3443 | */ | ||
3444 | if ((this->version_id & 0xf) == 0xe) | ||
3445 | this->options |= ONENAND_HAS_NOP_1; | ||
3432 | } | 3446 | } |
3433 | 3447 | ||
3434 | case ONENAND_DEVICE_DENSITY_2Gb: | 3448 | case ONENAND_DEVICE_DENSITY_2Gb: |
@@ -3663,7 +3677,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int | |||
3663 | int i, ret; | 3677 | int i, ret; |
3664 | int block; | 3678 | int block; |
3665 | struct mtd_oob_ops ops = { | 3679 | struct mtd_oob_ops ops = { |
3666 | .mode = MTD_OOB_PLACE, | 3680 | .mode = MTD_OPS_PLACE_OOB, |
3667 | .ooboffs = 0, | 3681 | .ooboffs = 0, |
3668 | .ooblen = mtd->oobsize, | 3682 | .ooblen = mtd->oobsize, |
3669 | .datbuf = NULL, | 3683 | .datbuf = NULL, |
@@ -4054,6 +4068,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
4054 | this->ecclayout = &onenand_oob_128; | 4068 | this->ecclayout = &onenand_oob_128; |
4055 | mtd->subpage_sft = 2; | 4069 | mtd->subpage_sft = 2; |
4056 | } | 4070 | } |
4071 | if (ONENAND_IS_NOP_1(this)) | ||
4072 | mtd->subpage_sft = 0; | ||
4057 | break; | 4073 | break; |
4058 | case 64: | 4074 | case 64: |
4059 | this->ecclayout = &onenand_oob_64; | 4075 | this->ecclayout = &onenand_oob_64; |
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index b2d7fc5ea25d..66fe3b7e7851 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c | |||
@@ -81,7 +81,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
81 | startblock = 0; | 81 | startblock = 0; |
82 | from = 0; | 82 | from = 0; |
83 | 83 | ||
84 | ops.mode = MTD_OOB_PLACE; | 84 | ops.mode = MTD_OPS_PLACE_OOB; |
85 | ops.ooblen = readlen; | 85 | ops.ooblen = readlen; |
86 | ops.oobbuf = buf; | 86 | ops.oobbuf = buf; |
87 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; | 87 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; |
@@ -154,7 +154,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) | |||
154 | block = (int) (onenand_block(this, offs) << 1); | 154 | block = (int) (onenand_block(this, offs) << 1); |
155 | res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; | 155 | res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; |
156 | 156 | ||
157 | DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", | 157 | pr_debug("onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", |
158 | (unsigned int) offs, block >> 1, res); | 158 | (unsigned int) offs, block >> 1, res); |
159 | 159 | ||
160 | switch ((int) res) { | 160 | switch ((int) res) { |
@@ -189,10 +189,8 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
189 | len = this->chipsize >> (this->erase_shift + 2); | 189 | len = this->chipsize >> (this->erase_shift + 2); |
190 | /* Allocate memory (2bit per block) and clear the memory bad block table */ | 190 | /* Allocate memory (2bit per block) and clear the memory bad block table */ |
191 | bbm->bbt = kzalloc(len, GFP_KERNEL); | 191 | bbm->bbt = kzalloc(len, GFP_KERNEL); |
192 | if (!bbm->bbt) { | 192 | if (!bbm->bbt) |
193 | printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); | ||
194 | return -ENOMEM; | 193 | return -ENOMEM; |
195 | } | ||
196 | 194 | ||
197 | /* Set the bad block position */ | 195 | /* Set the bad block position */ |
198 | bbm->badblockpos = ONENAND_BADBLOCK_POS; | 196 | bbm->badblockpos = ONENAND_BADBLOCK_POS; |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 3306b5b3c736..5474547eafc2 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -147,7 +147,6 @@ struct s3c_onenand { | |||
147 | struct resource *dma_res; | 147 | struct resource *dma_res; |
148 | unsigned long phys_base; | 148 | unsigned long phys_base; |
149 | struct completion complete; | 149 | struct completion complete; |
150 | struct mtd_partition *parts; | ||
151 | }; | 150 | }; |
152 | 151 | ||
153 | #define CMD_MAP_00(dev, addr) (dev->cmd_map(MAP_00, ((addr) << 1))) | 152 | #define CMD_MAP_00(dev, addr) (dev->cmd_map(MAP_00, ((addr) << 1))) |
@@ -157,8 +156,6 @@ struct s3c_onenand { | |||
157 | 156 | ||
158 | static struct s3c_onenand *onenand; | 157 | static struct s3c_onenand *onenand; |
159 | 158 | ||
160 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
161 | |||
162 | static inline int s3c_read_reg(int offset) | 159 | static inline int s3c_read_reg(int offset) |
163 | { | 160 | { |
164 | return readl(onenand->base + offset); | 161 | return readl(onenand->base + offset); |
@@ -1017,13 +1014,9 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
1017 | if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ) | 1014 | if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ) |
1018 | dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n"); | 1015 | dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n"); |
1019 | 1016 | ||
1020 | err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0); | 1017 | err = mtd_device_parse_register(mtd, NULL, 0, |
1021 | if (err > 0) | 1018 | pdata ? pdata->parts : NULL, |
1022 | mtd_device_register(mtd, onenand->parts, err); | 1019 | pdata ? pdata->nr_parts : 0); |
1023 | else if (err <= 0 && pdata && pdata->parts) | ||
1024 | mtd_device_register(mtd, pdata->parts, pdata->nr_parts); | ||
1025 | else | ||
1026 | err = mtd_device_register(mtd, NULL, 0); | ||
1027 | 1020 | ||
1028 | platform_set_drvdata(pdev, mtd); | 1021 | platform_set_drvdata(pdev, mtd); |
1029 | 1022 | ||
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 84b4dda023f4..e366b1d84ead 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c | |||
@@ -57,8 +57,8 @@ static inline int redboot_checksum(struct fis_image_desc *img) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | static int parse_redboot_partitions(struct mtd_info *master, | 59 | static int parse_redboot_partitions(struct mtd_info *master, |
60 | struct mtd_partition **pparts, | 60 | struct mtd_partition **pparts, |
61 | unsigned long fis_origin) | 61 | struct mtd_part_parser_data *data) |
62 | { | 62 | { |
63 | int nrparts = 0; | 63 | int nrparts = 0; |
64 | struct fis_image_desc *buf; | 64 | struct fis_image_desc *buf; |
@@ -198,11 +198,10 @@ static int parse_redboot_partitions(struct mtd_info *master, | |||
198 | goto out; | 198 | goto out; |
199 | } | 199 | } |
200 | new_fl->img = &buf[i]; | 200 | new_fl->img = &buf[i]; |
201 | if (fis_origin) { | 201 | if (data && data->origin) |
202 | buf[i].flash_base -= fis_origin; | 202 | buf[i].flash_base -= data->origin; |
203 | } else { | 203 | else |
204 | buf[i].flash_base &= master->size-1; | 204 | buf[i].flash_base &= master->size-1; |
205 | } | ||
206 | 205 | ||
207 | /* I'm sure the JFFS2 code has done me permanent damage. | 206 | /* I'm sure the JFFS2 code has done me permanent damage. |
208 | * I now think the following is _normal_ | 207 | * I now think the following is _normal_ |
@@ -298,6 +297,9 @@ static struct mtd_part_parser redboot_parser = { | |||
298 | .name = "RedBoot", | 297 | .name = "RedBoot", |
299 | }; | 298 | }; |
300 | 299 | ||
300 | /* mtd parsers will request the module by parser name */ | ||
301 | MODULE_ALIAS("RedBoot"); | ||
302 | |||
301 | static int __init redboot_parser_init(void) | 303 | static int __init redboot_parser_init(void) |
302 | { | 304 | { |
303 | return register_mtd_parser(&redboot_parser); | 305 | return register_mtd_parser(&redboot_parser); |
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index ed3d6cd2c6dc..fddb714e323c 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c | |||
@@ -34,7 +34,7 @@ module_param(debug, int, S_IRUGO | S_IWUSR); | |||
34 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | 34 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); |
35 | 35 | ||
36 | 36 | ||
37 | /* ------------------- sysfs attributtes ---------------------------------- */ | 37 | /* ------------------- sysfs attributes ---------------------------------- */ |
38 | struct sm_sysfs_attribute { | 38 | struct sm_sysfs_attribute { |
39 | struct device_attribute dev_attr; | 39 | struct device_attribute dev_attr; |
40 | char *data; | 40 | char *data; |
@@ -138,7 +138,7 @@ static int sm_get_lba(uint8_t *lba) | |||
138 | if ((lba[0] & 0xF8) != 0x10) | 138 | if ((lba[0] & 0xF8) != 0x10) |
139 | return -2; | 139 | return -2; |
140 | 140 | ||
141 | /* check parity - endianess doesn't matter */ | 141 | /* check parity - endianness doesn't matter */ |
142 | if (hweight16(*(uint16_t *)lba) & 1) | 142 | if (hweight16(*(uint16_t *)lba) & 1) |
143 | return -2; | 143 | return -2; |
144 | 144 | ||
@@ -147,7 +147,7 @@ static int sm_get_lba(uint8_t *lba) | |||
147 | 147 | ||
148 | 148 | ||
149 | /* | 149 | /* |
150 | * Read LBA asscociated with block | 150 | * Read LBA associated with block |
151 | * returns -1, if block is erased | 151 | * returns -1, if block is erased |
152 | * returns -2 if error happens | 152 | * returns -2 if error happens |
153 | */ | 153 | */ |
@@ -252,11 +252,11 @@ static int sm_read_sector(struct sm_ftl *ftl, | |||
252 | return 0; | 252 | return 0; |
253 | } | 253 | } |
254 | 254 | ||
255 | /* User might not need the oob, but we do for data vertification */ | 255 | /* User might not need the oob, but we do for data verification */ |
256 | if (!oob) | 256 | if (!oob) |
257 | oob = &tmp_oob; | 257 | oob = &tmp_oob; |
258 | 258 | ||
259 | ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE; | 259 | ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB; |
260 | ops.ooboffs = 0; | 260 | ops.ooboffs = 0; |
261 | ops.ooblen = SM_OOB_SIZE; | 261 | ops.ooblen = SM_OOB_SIZE; |
262 | ops.oobbuf = (void *)oob; | 262 | ops.oobbuf = (void *)oob; |
@@ -276,12 +276,12 @@ again: | |||
276 | return ret; | 276 | return ret; |
277 | } | 277 | } |
278 | 278 | ||
279 | /* Unfortunelly, oob read will _always_ succeed, | 279 | /* Unfortunately, oob read will _always_ succeed, |
280 | despite card removal..... */ | 280 | despite card removal..... */ |
281 | ret = mtd->read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); | 281 | ret = mtd->read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); |
282 | 282 | ||
283 | /* Test for unknown errors */ | 283 | /* Test for unknown errors */ |
284 | if (ret != 0 && ret != -EUCLEAN && ret != -EBADMSG) { | 284 | if (ret != 0 && !mtd_is_bitflip_or_eccerr(ret)) { |
285 | dbg("read of block %d at zone %d, failed due to error (%d)", | 285 | dbg("read of block %d at zone %d, failed due to error (%d)", |
286 | block, zone, ret); | 286 | block, zone, ret); |
287 | goto again; | 287 | goto again; |
@@ -306,7 +306,7 @@ again: | |||
306 | } | 306 | } |
307 | 307 | ||
308 | /* Test ECC*/ | 308 | /* Test ECC*/ |
309 | if (ret == -EBADMSG || | 309 | if (mtd_is_eccerr(ret) || |
310 | (ftl->smallpagenand && sm_correct_sector(buffer, oob))) { | 310 | (ftl->smallpagenand && sm_correct_sector(buffer, oob))) { |
311 | 311 | ||
312 | dbg("read of block %d at zone %d, failed due to ECC error", | 312 | dbg("read of block %d at zone %d, failed due to ECC error", |
@@ -336,7 +336,7 @@ static int sm_write_sector(struct sm_ftl *ftl, | |||
336 | if (ftl->unstable) | 336 | if (ftl->unstable) |
337 | return -EIO; | 337 | return -EIO; |
338 | 338 | ||
339 | ops.mode = ftl->smallpagenand ? MTD_OOB_RAW : MTD_OOB_PLACE; | 339 | ops.mode = ftl->smallpagenand ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB; |
340 | ops.len = SM_SECTOR_SIZE; | 340 | ops.len = SM_SECTOR_SIZE; |
341 | ops.datbuf = buffer; | 341 | ops.datbuf = buffer; |
342 | ops.ooboffs = 0; | 342 | ops.ooboffs = 0; |
@@ -447,14 +447,14 @@ static void sm_mark_block_bad(struct sm_ftl *ftl, int zone, int block) | |||
447 | 447 | ||
448 | /* We aren't checking the return value, because we don't care */ | 448 | /* We aren't checking the return value, because we don't care */ |
449 | /* This also fails on fake xD cards, but I guess these won't expose | 449 | /* This also fails on fake xD cards, but I guess these won't expose |
450 | any bad blocks till fail completly */ | 450 | any bad blocks till fail completely */ |
451 | for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE) | 451 | for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE) |
452 | sm_write_sector(ftl, zone, block, boffset, NULL, &oob); | 452 | sm_write_sector(ftl, zone, block, boffset, NULL, &oob); |
453 | } | 453 | } |
454 | 454 | ||
455 | /* | 455 | /* |
456 | * Erase a block within a zone | 456 | * Erase a block within a zone |
457 | * If erase succedes, it updates free block fifo, otherwise marks block as bad | 457 | * If erase succeeds, it updates free block fifo, otherwise marks block as bad |
458 | */ | 458 | */ |
459 | static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block, | 459 | static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block, |
460 | int put_free) | 460 | int put_free) |
@@ -510,7 +510,7 @@ static void sm_erase_callback(struct erase_info *self) | |||
510 | complete(&ftl->erase_completion); | 510 | complete(&ftl->erase_completion); |
511 | } | 511 | } |
512 | 512 | ||
513 | /* Throughtly test that block is valid. */ | 513 | /* Thoroughly test that block is valid. */ |
514 | static int sm_check_block(struct sm_ftl *ftl, int zone, int block) | 514 | static int sm_check_block(struct sm_ftl *ftl, int zone, int block) |
515 | { | 515 | { |
516 | int boffset; | 516 | int boffset; |
@@ -526,7 +526,7 @@ static int sm_check_block(struct sm_ftl *ftl, int zone, int block) | |||
526 | for (boffset = 0; boffset < ftl->block_size; | 526 | for (boffset = 0; boffset < ftl->block_size; |
527 | boffset += SM_SECTOR_SIZE) { | 527 | boffset += SM_SECTOR_SIZE) { |
528 | 528 | ||
529 | /* This shoudn't happen anyway */ | 529 | /* This shouldn't happen anyway */ |
530 | if (sm_read_sector(ftl, zone, block, boffset, NULL, &oob)) | 530 | if (sm_read_sector(ftl, zone, block, boffset, NULL, &oob)) |
531 | return -2; | 531 | return -2; |
532 | 532 | ||
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index 5cd189793332..976e3d28b962 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c | |||
@@ -135,8 +135,7 @@ static int get_valid_cis_sector(struct mtd_info *mtd) | |||
135 | /* Found */ | 135 | /* Found */ |
136 | cis_sector = (int)(offset >> SECTOR_SHIFT); | 136 | cis_sector = (int)(offset >> SECTOR_SHIFT); |
137 | } else { | 137 | } else { |
138 | DEBUG(MTD_DEBUG_LEVEL1, | 138 | pr_debug("SSFDC_RO: CIS/IDI sector not found" |
139 | "SSFDC_RO: CIS/IDI sector not found" | ||
140 | " on %s (mtd%d)\n", mtd->name, | 139 | " on %s (mtd%d)\n", mtd->name, |
141 | mtd->index); | 140 | mtd->index); |
142 | } | 141 | } |
@@ -170,7 +169,7 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf) | |||
170 | struct mtd_oob_ops ops; | 169 | struct mtd_oob_ops ops; |
171 | int ret; | 170 | int ret; |
172 | 171 | ||
173 | ops.mode = MTD_OOB_RAW; | 172 | ops.mode = MTD_OPS_RAW; |
174 | ops.ooboffs = 0; | 173 | ops.ooboffs = 0; |
175 | ops.ooblen = OOB_SIZE; | 174 | ops.ooblen = OOB_SIZE; |
176 | ops.oobbuf = buf; | 175 | ops.oobbuf = buf; |
@@ -221,8 +220,7 @@ static int get_logical_address(uint8_t *oob_buf) | |||
221 | block_address >>= 1; | 220 | block_address >>= 1; |
222 | 221 | ||
223 | if (get_parity(block_address, 10) != parity) { | 222 | if (get_parity(block_address, 10) != parity) { |
224 | DEBUG(MTD_DEBUG_LEVEL0, | 223 | pr_debug("SSFDC_RO: logical address field%d" |
225 | "SSFDC_RO: logical address field%d" | ||
226 | "parity error(0x%04X)\n", j+1, | 224 | "parity error(0x%04X)\n", j+1, |
227 | block_address); | 225 | block_address); |
228 | } else { | 226 | } else { |
@@ -235,7 +233,7 @@ static int get_logical_address(uint8_t *oob_buf) | |||
235 | if (!ok) | 233 | if (!ok) |
236 | block_address = -2; | 234 | block_address = -2; |
237 | 235 | ||
238 | DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n", | 236 | pr_debug("SSFDC_RO: get_logical_address() %d\n", |
239 | block_address); | 237 | block_address); |
240 | 238 | ||
241 | return block_address; | 239 | return block_address; |
@@ -249,7 +247,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc) | |||
249 | int ret, block_address, phys_block; | 247 | int ret, block_address, phys_block; |
250 | struct mtd_info *mtd = ssfdc->mbd.mtd; | 248 | struct mtd_info *mtd = ssfdc->mbd.mtd; |
251 | 249 | ||
252 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n", | 250 | pr_debug("SSFDC_RO: build_block_map() nblks=%d (%luK)\n", |
253 | ssfdc->map_len, | 251 | ssfdc->map_len, |
254 | (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024); | 252 | (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024); |
255 | 253 | ||
@@ -262,8 +260,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc) | |||
262 | 260 | ||
263 | ret = read_raw_oob(mtd, offset, oob_buf); | 261 | ret = read_raw_oob(mtd, offset, oob_buf); |
264 | if (ret < 0) { | 262 | if (ret < 0) { |
265 | DEBUG(MTD_DEBUG_LEVEL0, | 263 | pr_debug("SSFDC_RO: mtd read_oob() failed at %lu\n", |
266 | "SSFDC_RO: mtd read_oob() failed at %lu\n", | ||
267 | offset); | 264 | offset); |
268 | return -1; | 265 | return -1; |
269 | } | 266 | } |
@@ -279,8 +276,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc) | |||
279 | ssfdc->logic_block_map[block_address] = | 276 | ssfdc->logic_block_map[block_address] = |
280 | (unsigned short)phys_block; | 277 | (unsigned short)phys_block; |
281 | 278 | ||
282 | DEBUG(MTD_DEBUG_LEVEL2, | 279 | pr_debug("SSFDC_RO: build_block_map() phys_block=%d," |
283 | "SSFDC_RO: build_block_map() phys_block=%d," | ||
284 | "logic_block_addr=%d, zone=%d\n", | 280 | "logic_block_addr=%d, zone=%d\n", |
285 | phys_block, block_address, zone_index); | 281 | phys_block, block_address, zone_index); |
286 | } | 282 | } |
@@ -304,11 +300,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
304 | return; | 300 | return; |
305 | 301 | ||
306 | ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL); | 302 | ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL); |
307 | if (!ssfdc) { | 303 | if (!ssfdc) |
308 | printk(KERN_WARNING | ||
309 | "SSFDC_RO: out of memory for data structures\n"); | ||
310 | return; | 304 | return; |
311 | } | ||
312 | 305 | ||
313 | ssfdc->mbd.mtd = mtd; | 306 | ssfdc->mbd.mtd = mtd; |
314 | ssfdc->mbd.devnum = -1; | 307 | ssfdc->mbd.devnum = -1; |
@@ -319,8 +312,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
319 | ssfdc->erase_size = mtd->erasesize; | 312 | ssfdc->erase_size = mtd->erasesize; |
320 | ssfdc->map_len = (u32)mtd->size / mtd->erasesize; | 313 | ssfdc->map_len = (u32)mtd->size / mtd->erasesize; |
321 | 314 | ||
322 | DEBUG(MTD_DEBUG_LEVEL1, | 315 | pr_debug("SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n", |
323 | "SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n", | ||
324 | ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len, | 316 | ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len, |
325 | DIV_ROUND_UP(ssfdc->map_len, MAX_PHYS_BLK_PER_ZONE)); | 317 | DIV_ROUND_UP(ssfdc->map_len, MAX_PHYS_BLK_PER_ZONE)); |
326 | 318 | ||
@@ -331,7 +323,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
331 | ssfdc->cylinders = (unsigned short)(((u32)mtd->size >> SECTOR_SHIFT) / | 323 | ssfdc->cylinders = (unsigned short)(((u32)mtd->size >> SECTOR_SHIFT) / |
332 | ((long)ssfdc->sectors * (long)ssfdc->heads)); | 324 | ((long)ssfdc->sectors * (long)ssfdc->heads)); |
333 | 325 | ||
334 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n", | 326 | pr_debug("SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n", |
335 | ssfdc->cylinders, ssfdc->heads , ssfdc->sectors, | 327 | ssfdc->cylinders, ssfdc->heads , ssfdc->sectors, |
336 | (long)ssfdc->cylinders * (long)ssfdc->heads * | 328 | (long)ssfdc->cylinders * (long)ssfdc->heads * |
337 | (long)ssfdc->sectors); | 329 | (long)ssfdc->sectors); |
@@ -342,11 +334,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
342 | /* Allocate logical block map */ | 334 | /* Allocate logical block map */ |
343 | ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) * | 335 | ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) * |
344 | ssfdc->map_len, GFP_KERNEL); | 336 | ssfdc->map_len, GFP_KERNEL); |
345 | if (!ssfdc->logic_block_map) { | 337 | if (!ssfdc->logic_block_map) |
346 | printk(KERN_WARNING | ||
347 | "SSFDC_RO: out of memory for data structures\n"); | ||
348 | goto out_err; | 338 | goto out_err; |
349 | } | ||
350 | memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) * | 339 | memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) * |
351 | ssfdc->map_len); | 340 | ssfdc->map_len); |
352 | 341 | ||
@@ -371,7 +360,7 @@ static void ssfdcr_remove_dev(struct mtd_blktrans_dev *dev) | |||
371 | { | 360 | { |
372 | struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; | 361 | struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; |
373 | 362 | ||
374 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: remove_dev (i=%d)\n", dev->devnum); | 363 | pr_debug("SSFDC_RO: remove_dev (i=%d)\n", dev->devnum); |
375 | 364 | ||
376 | del_mtd_blktrans_dev(dev); | 365 | del_mtd_blktrans_dev(dev); |
377 | kfree(ssfdc->logic_block_map); | 366 | kfree(ssfdc->logic_block_map); |
@@ -387,8 +376,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev, | |||
387 | offset = (int)(logic_sect_no % sectors_per_block); | 376 | offset = (int)(logic_sect_no % sectors_per_block); |
388 | block_address = (int)(logic_sect_no / sectors_per_block); | 377 | block_address = (int)(logic_sect_no / sectors_per_block); |
389 | 378 | ||
390 | DEBUG(MTD_DEBUG_LEVEL3, | 379 | pr_debug("SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d," |
391 | "SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d," | ||
392 | " block_addr=%d\n", logic_sect_no, sectors_per_block, offset, | 380 | " block_addr=%d\n", logic_sect_no, sectors_per_block, offset, |
393 | block_address); | 381 | block_address); |
394 | 382 | ||
@@ -397,8 +385,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev, | |||
397 | 385 | ||
398 | block_address = ssfdc->logic_block_map[block_address]; | 386 | block_address = ssfdc->logic_block_map[block_address]; |
399 | 387 | ||
400 | DEBUG(MTD_DEBUG_LEVEL3, | 388 | pr_debug("SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n", |
401 | "SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n", | ||
402 | block_address); | 389 | block_address); |
403 | 390 | ||
404 | if (block_address < 0xffff) { | 391 | if (block_address < 0xffff) { |
@@ -407,8 +394,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev, | |||
407 | sect_no = (unsigned long)block_address * sectors_per_block + | 394 | sect_no = (unsigned long)block_address * sectors_per_block + |
408 | offset; | 395 | offset; |
409 | 396 | ||
410 | DEBUG(MTD_DEBUG_LEVEL3, | 397 | pr_debug("SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n", |
411 | "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n", | ||
412 | sect_no); | 398 | sect_no); |
413 | 399 | ||
414 | if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0) | 400 | if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0) |
@@ -424,7 +410,7 @@ static int ssfdcr_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) | |||
424 | { | 410 | { |
425 | struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; | 411 | struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; |
426 | 412 | ||
427 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n", | 413 | pr_debug("SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n", |
428 | ssfdc->cylinders, ssfdc->heads, ssfdc->sectors); | 414 | ssfdc->cylinders, ssfdc->heads, ssfdc->sectors); |
429 | 415 | ||
430 | geo->heads = ssfdc->heads; | 416 | geo->heads = ssfdc->heads; |
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c index dec92ae6111a..933f7e5f32d3 100644 --- a/drivers/mtd/tests/mtd_oobtest.c +++ b/drivers/mtd/tests/mtd_oobtest.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #define PRINT_PREF KERN_INFO "mtd_oobtest: " | 31 | #define PRINT_PREF KERN_INFO "mtd_oobtest: " |
32 | 32 | ||
33 | static int dev; | 33 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 34 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 35 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
36 | 36 | ||
@@ -131,7 +131,7 @@ static int write_eraseblock(int ebnum) | |||
131 | 131 | ||
132 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { | 132 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { |
133 | set_random_data(writebuf, use_len); | 133 | set_random_data(writebuf, use_len); |
134 | ops.mode = MTD_OOB_AUTO; | 134 | ops.mode = MTD_OPS_AUTO_OOB; |
135 | ops.len = 0; | 135 | ops.len = 0; |
136 | ops.retlen = 0; | 136 | ops.retlen = 0; |
137 | ops.ooblen = use_len; | 137 | ops.ooblen = use_len; |
@@ -184,7 +184,7 @@ static int verify_eraseblock(int ebnum) | |||
184 | 184 | ||
185 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { | 185 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { |
186 | set_random_data(writebuf, use_len); | 186 | set_random_data(writebuf, use_len); |
187 | ops.mode = MTD_OOB_AUTO; | 187 | ops.mode = MTD_OPS_AUTO_OOB; |
188 | ops.len = 0; | 188 | ops.len = 0; |
189 | ops.retlen = 0; | 189 | ops.retlen = 0; |
190 | ops.ooblen = use_len; | 190 | ops.ooblen = use_len; |
@@ -211,7 +211,7 @@ static int verify_eraseblock(int ebnum) | |||
211 | if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) { | 211 | if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) { |
212 | int k; | 212 | int k; |
213 | 213 | ||
214 | ops.mode = MTD_OOB_AUTO; | 214 | ops.mode = MTD_OPS_AUTO_OOB; |
215 | ops.len = 0; | 215 | ops.len = 0; |
216 | ops.retlen = 0; | 216 | ops.retlen = 0; |
217 | ops.ooblen = mtd->ecclayout->oobavail; | 217 | ops.ooblen = mtd->ecclayout->oobavail; |
@@ -276,7 +276,7 @@ static int verify_eraseblock_in_one_go(int ebnum) | |||
276 | size_t len = mtd->ecclayout->oobavail * pgcnt; | 276 | size_t len = mtd->ecclayout->oobavail * pgcnt; |
277 | 277 | ||
278 | set_random_data(writebuf, len); | 278 | set_random_data(writebuf, len); |
279 | ops.mode = MTD_OOB_AUTO; | 279 | ops.mode = MTD_OPS_AUTO_OOB; |
280 | ops.len = 0; | 280 | ops.len = 0; |
281 | ops.retlen = 0; | 281 | ops.retlen = 0; |
282 | ops.ooblen = len; | 282 | ops.ooblen = len; |
@@ -366,6 +366,13 @@ static int __init mtd_oobtest_init(void) | |||
366 | 366 | ||
367 | printk(KERN_INFO "\n"); | 367 | printk(KERN_INFO "\n"); |
368 | printk(KERN_INFO "=================================================\n"); | 368 | printk(KERN_INFO "=================================================\n"); |
369 | |||
370 | if (dev < 0) { | ||
371 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
372 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | |||
369 | printk(PRINT_PREF "MTD device: %d\n", dev); | 376 | printk(PRINT_PREF "MTD device: %d\n", dev); |
370 | 377 | ||
371 | mtd = get_mtd_device(NULL, dev); | 378 | mtd = get_mtd_device(NULL, dev); |
@@ -507,7 +514,7 @@ static int __init mtd_oobtest_init(void) | |||
507 | addr0 += mtd->erasesize; | 514 | addr0 += mtd->erasesize; |
508 | 515 | ||
509 | /* Attempt to write off end of OOB */ | 516 | /* Attempt to write off end of OOB */ |
510 | ops.mode = MTD_OOB_AUTO; | 517 | ops.mode = MTD_OPS_AUTO_OOB; |
511 | ops.len = 0; | 518 | ops.len = 0; |
512 | ops.retlen = 0; | 519 | ops.retlen = 0; |
513 | ops.ooblen = 1; | 520 | ops.ooblen = 1; |
@@ -527,7 +534,7 @@ static int __init mtd_oobtest_init(void) | |||
527 | } | 534 | } |
528 | 535 | ||
529 | /* Attempt to read off end of OOB */ | 536 | /* Attempt to read off end of OOB */ |
530 | ops.mode = MTD_OOB_AUTO; | 537 | ops.mode = MTD_OPS_AUTO_OOB; |
531 | ops.len = 0; | 538 | ops.len = 0; |
532 | ops.retlen = 0; | 539 | ops.retlen = 0; |
533 | ops.ooblen = 1; | 540 | ops.ooblen = 1; |
@@ -551,7 +558,7 @@ static int __init mtd_oobtest_init(void) | |||
551 | "block is bad\n"); | 558 | "block is bad\n"); |
552 | else { | 559 | else { |
553 | /* Attempt to write off end of device */ | 560 | /* Attempt to write off end of device */ |
554 | ops.mode = MTD_OOB_AUTO; | 561 | ops.mode = MTD_OPS_AUTO_OOB; |
555 | ops.len = 0; | 562 | ops.len = 0; |
556 | ops.retlen = 0; | 563 | ops.retlen = 0; |
557 | ops.ooblen = mtd->ecclayout->oobavail + 1; | 564 | ops.ooblen = mtd->ecclayout->oobavail + 1; |
@@ -571,7 +578,7 @@ static int __init mtd_oobtest_init(void) | |||
571 | } | 578 | } |
572 | 579 | ||
573 | /* Attempt to read off end of device */ | 580 | /* Attempt to read off end of device */ |
574 | ops.mode = MTD_OOB_AUTO; | 581 | ops.mode = MTD_OPS_AUTO_OOB; |
575 | ops.len = 0; | 582 | ops.len = 0; |
576 | ops.retlen = 0; | 583 | ops.retlen = 0; |
577 | ops.ooblen = mtd->ecclayout->oobavail + 1; | 584 | ops.ooblen = mtd->ecclayout->oobavail + 1; |
@@ -595,7 +602,7 @@ static int __init mtd_oobtest_init(void) | |||
595 | goto out; | 602 | goto out; |
596 | 603 | ||
597 | /* Attempt to write off end of device */ | 604 | /* Attempt to write off end of device */ |
598 | ops.mode = MTD_OOB_AUTO; | 605 | ops.mode = MTD_OPS_AUTO_OOB; |
599 | ops.len = 0; | 606 | ops.len = 0; |
600 | ops.retlen = 0; | 607 | ops.retlen = 0; |
601 | ops.ooblen = mtd->ecclayout->oobavail; | 608 | ops.ooblen = mtd->ecclayout->oobavail; |
@@ -615,7 +622,7 @@ static int __init mtd_oobtest_init(void) | |||
615 | } | 622 | } |
616 | 623 | ||
617 | /* Attempt to read off end of device */ | 624 | /* Attempt to read off end of device */ |
618 | ops.mode = MTD_OOB_AUTO; | 625 | ops.mode = MTD_OPS_AUTO_OOB; |
619 | ops.len = 0; | 626 | ops.len = 0; |
620 | ops.retlen = 0; | 627 | ops.retlen = 0; |
621 | ops.ooblen = mtd->ecclayout->oobavail; | 628 | ops.ooblen = mtd->ecclayout->oobavail; |
@@ -655,7 +662,7 @@ static int __init mtd_oobtest_init(void) | |||
655 | addr = (i + 1) * mtd->erasesize - mtd->writesize; | 662 | addr = (i + 1) * mtd->erasesize - mtd->writesize; |
656 | for (pg = 0; pg < cnt; ++pg) { | 663 | for (pg = 0; pg < cnt; ++pg) { |
657 | set_random_data(writebuf, sz); | 664 | set_random_data(writebuf, sz); |
658 | ops.mode = MTD_OOB_AUTO; | 665 | ops.mode = MTD_OPS_AUTO_OOB; |
659 | ops.len = 0; | 666 | ops.len = 0; |
660 | ops.retlen = 0; | 667 | ops.retlen = 0; |
661 | ops.ooblen = sz; | 668 | ops.ooblen = sz; |
@@ -683,7 +690,7 @@ static int __init mtd_oobtest_init(void) | |||
683 | continue; | 690 | continue; |
684 | set_random_data(writebuf, mtd->ecclayout->oobavail * 2); | 691 | set_random_data(writebuf, mtd->ecclayout->oobavail * 2); |
685 | addr = (i + 1) * mtd->erasesize - mtd->writesize; | 692 | addr = (i + 1) * mtd->erasesize - mtd->writesize; |
686 | ops.mode = MTD_OOB_AUTO; | 693 | ops.mode = MTD_OPS_AUTO_OOB; |
687 | ops.len = 0; | 694 | ops.len = 0; |
688 | ops.retlen = 0; | 695 | ops.retlen = 0; |
689 | ops.ooblen = mtd->ecclayout->oobavail * 2; | 696 | ops.ooblen = mtd->ecclayout->oobavail * 2; |
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c index 00b937e38c1d..afafb6935fd0 100644 --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/mtd_pagetest.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #define PRINT_PREF KERN_INFO "mtd_pagetest: " | 31 | #define PRINT_PREF KERN_INFO "mtd_pagetest: " |
32 | 32 | ||
33 | static int dev; | 33 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 34 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 35 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
36 | 36 | ||
@@ -128,7 +128,7 @@ static int verify_eraseblock(int ebnum) | |||
128 | for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { | 128 | for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { |
129 | /* Do a read to set the internal dataRAMs to different data */ | 129 | /* Do a read to set the internal dataRAMs to different data */ |
130 | err = mtd->read(mtd, addr0, bufsize, &read, twopages); | 130 | err = mtd->read(mtd, addr0, bufsize, &read, twopages); |
131 | if (err == -EUCLEAN) | 131 | if (mtd_is_bitflip(err)) |
132 | err = 0; | 132 | err = 0; |
133 | if (err || read != bufsize) { | 133 | if (err || read != bufsize) { |
134 | printk(PRINT_PREF "error: read failed at %#llx\n", | 134 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -136,7 +136,7 @@ static int verify_eraseblock(int ebnum) | |||
136 | return err; | 136 | return err; |
137 | } | 137 | } |
138 | err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); | 138 | err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); |
139 | if (err == -EUCLEAN) | 139 | if (mtd_is_bitflip(err)) |
140 | err = 0; | 140 | err = 0; |
141 | if (err || read != bufsize) { | 141 | if (err || read != bufsize) { |
142 | printk(PRINT_PREF "error: read failed at %#llx\n", | 142 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -146,7 +146,7 @@ static int verify_eraseblock(int ebnum) | |||
146 | memset(twopages, 0, bufsize); | 146 | memset(twopages, 0, bufsize); |
147 | read = 0; | 147 | read = 0; |
148 | err = mtd->read(mtd, addr, bufsize, &read, twopages); | 148 | err = mtd->read(mtd, addr, bufsize, &read, twopages); |
149 | if (err == -EUCLEAN) | 149 | if (mtd_is_bitflip(err)) |
150 | err = 0; | 150 | err = 0; |
151 | if (err || read != bufsize) { | 151 | if (err || read != bufsize) { |
152 | printk(PRINT_PREF "error: read failed at %#llx\n", | 152 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -164,7 +164,7 @@ static int verify_eraseblock(int ebnum) | |||
164 | unsigned long oldnext = next; | 164 | unsigned long oldnext = next; |
165 | /* Do a read to set the internal dataRAMs to different data */ | 165 | /* Do a read to set the internal dataRAMs to different data */ |
166 | err = mtd->read(mtd, addr0, bufsize, &read, twopages); | 166 | err = mtd->read(mtd, addr0, bufsize, &read, twopages); |
167 | if (err == -EUCLEAN) | 167 | if (mtd_is_bitflip(err)) |
168 | err = 0; | 168 | err = 0; |
169 | if (err || read != bufsize) { | 169 | if (err || read != bufsize) { |
170 | printk(PRINT_PREF "error: read failed at %#llx\n", | 170 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -172,7 +172,7 @@ static int verify_eraseblock(int ebnum) | |||
172 | return err; | 172 | return err; |
173 | } | 173 | } |
174 | err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); | 174 | err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); |
175 | if (err == -EUCLEAN) | 175 | if (mtd_is_bitflip(err)) |
176 | err = 0; | 176 | err = 0; |
177 | if (err || read != bufsize) { | 177 | if (err || read != bufsize) { |
178 | printk(PRINT_PREF "error: read failed at %#llx\n", | 178 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -182,7 +182,7 @@ static int verify_eraseblock(int ebnum) | |||
182 | memset(twopages, 0, bufsize); | 182 | memset(twopages, 0, bufsize); |
183 | read = 0; | 183 | read = 0; |
184 | err = mtd->read(mtd, addr, bufsize, &read, twopages); | 184 | err = mtd->read(mtd, addr, bufsize, &read, twopages); |
185 | if (err == -EUCLEAN) | 185 | if (mtd_is_bitflip(err)) |
186 | err = 0; | 186 | err = 0; |
187 | if (err || read != bufsize) { | 187 | if (err || read != bufsize) { |
188 | printk(PRINT_PREF "error: read failed at %#llx\n", | 188 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -231,7 +231,7 @@ static int crosstest(void) | |||
231 | read = 0; | 231 | read = 0; |
232 | addr = addrn - pgsize - pgsize; | 232 | addr = addrn - pgsize - pgsize; |
233 | err = mtd->read(mtd, addr, pgsize, &read, pp1); | 233 | err = mtd->read(mtd, addr, pgsize, &read, pp1); |
234 | if (err == -EUCLEAN) | 234 | if (mtd_is_bitflip(err)) |
235 | err = 0; | 235 | err = 0; |
236 | if (err || read != pgsize) { | 236 | if (err || read != pgsize) { |
237 | printk(PRINT_PREF "error: read failed at %#llx\n", | 237 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -244,7 +244,7 @@ static int crosstest(void) | |||
244 | read = 0; | 244 | read = 0; |
245 | addr = addrn - pgsize - pgsize - pgsize; | 245 | addr = addrn - pgsize - pgsize - pgsize; |
246 | err = mtd->read(mtd, addr, pgsize, &read, pp1); | 246 | err = mtd->read(mtd, addr, pgsize, &read, pp1); |
247 | if (err == -EUCLEAN) | 247 | if (mtd_is_bitflip(err)) |
248 | err = 0; | 248 | err = 0; |
249 | if (err || read != pgsize) { | 249 | if (err || read != pgsize) { |
250 | printk(PRINT_PREF "error: read failed at %#llx\n", | 250 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -258,7 +258,7 @@ static int crosstest(void) | |||
258 | addr = addr0; | 258 | addr = addr0; |
259 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); | 259 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); |
260 | err = mtd->read(mtd, addr, pgsize, &read, pp2); | 260 | err = mtd->read(mtd, addr, pgsize, &read, pp2); |
261 | if (err == -EUCLEAN) | 261 | if (mtd_is_bitflip(err)) |
262 | err = 0; | 262 | err = 0; |
263 | if (err || read != pgsize) { | 263 | if (err || read != pgsize) { |
264 | printk(PRINT_PREF "error: read failed at %#llx\n", | 264 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -272,7 +272,7 @@ static int crosstest(void) | |||
272 | addr = addrn - pgsize; | 272 | addr = addrn - pgsize; |
273 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); | 273 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); |
274 | err = mtd->read(mtd, addr, pgsize, &read, pp3); | 274 | err = mtd->read(mtd, addr, pgsize, &read, pp3); |
275 | if (err == -EUCLEAN) | 275 | if (mtd_is_bitflip(err)) |
276 | err = 0; | 276 | err = 0; |
277 | if (err || read != pgsize) { | 277 | if (err || read != pgsize) { |
278 | printk(PRINT_PREF "error: read failed at %#llx\n", | 278 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -286,7 +286,7 @@ static int crosstest(void) | |||
286 | addr = addr0; | 286 | addr = addr0; |
287 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); | 287 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); |
288 | err = mtd->read(mtd, addr, pgsize, &read, pp4); | 288 | err = mtd->read(mtd, addr, pgsize, &read, pp4); |
289 | if (err == -EUCLEAN) | 289 | if (mtd_is_bitflip(err)) |
290 | err = 0; | 290 | err = 0; |
291 | if (err || read != pgsize) { | 291 | if (err || read != pgsize) { |
292 | printk(PRINT_PREF "error: read failed at %#llx\n", | 292 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -345,7 +345,7 @@ static int erasecrosstest(void) | |||
345 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); | 345 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); |
346 | memset(readbuf, 0, pgsize); | 346 | memset(readbuf, 0, pgsize); |
347 | err = mtd->read(mtd, addr0, pgsize, &read, readbuf); | 347 | err = mtd->read(mtd, addr0, pgsize, &read, readbuf); |
348 | if (err == -EUCLEAN) | 348 | if (mtd_is_bitflip(err)) |
349 | err = 0; | 349 | err = 0; |
350 | if (err || read != pgsize) { | 350 | if (err || read != pgsize) { |
351 | printk(PRINT_PREF "error: read failed at %#llx\n", | 351 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -383,7 +383,7 @@ static int erasecrosstest(void) | |||
383 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); | 383 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); |
384 | memset(readbuf, 0, pgsize); | 384 | memset(readbuf, 0, pgsize); |
385 | err = mtd->read(mtd, addr0, pgsize, &read, readbuf); | 385 | err = mtd->read(mtd, addr0, pgsize, &read, readbuf); |
386 | if (err == -EUCLEAN) | 386 | if (mtd_is_bitflip(err)) |
387 | err = 0; | 387 | err = 0; |
388 | if (err || read != pgsize) { | 388 | if (err || read != pgsize) { |
389 | printk(PRINT_PREF "error: read failed at %#llx\n", | 389 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -439,7 +439,7 @@ static int erasetest(void) | |||
439 | 439 | ||
440 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); | 440 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); |
441 | err = mtd->read(mtd, addr0, pgsize, &read, twopages); | 441 | err = mtd->read(mtd, addr0, pgsize, &read, twopages); |
442 | if (err == -EUCLEAN) | 442 | if (mtd_is_bitflip(err)) |
443 | err = 0; | 443 | err = 0; |
444 | if (err || read != pgsize) { | 444 | if (err || read != pgsize) { |
445 | printk(PRINT_PREF "error: read failed at %#llx\n", | 445 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -504,6 +504,13 @@ static int __init mtd_pagetest_init(void) | |||
504 | 504 | ||
505 | printk(KERN_INFO "\n"); | 505 | printk(KERN_INFO "\n"); |
506 | printk(KERN_INFO "=================================================\n"); | 506 | printk(KERN_INFO "=================================================\n"); |
507 | |||
508 | if (dev < 0) { | ||
509 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
510 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | |||
507 | printk(PRINT_PREF "MTD device: %d\n", dev); | 514 | printk(PRINT_PREF "MTD device: %d\n", dev); |
508 | 515 | ||
509 | mtd = get_mtd_device(NULL, dev); | 516 | mtd = get_mtd_device(NULL, dev); |
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c index afe71aa15c4b..550fe51225a7 100644 --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/mtd_readtest.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #define PRINT_PREF KERN_INFO "mtd_readtest: " | 30 | #define PRINT_PREF KERN_INFO "mtd_readtest: " |
31 | 31 | ||
32 | static int dev; | 32 | static int dev = -EINVAL; |
33 | module_param(dev, int, S_IRUGO); | 33 | module_param(dev, int, S_IRUGO); |
34 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 34 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
35 | 35 | ||
@@ -66,7 +66,7 @@ static int read_eraseblock_by_page(int ebnum) | |||
66 | if (mtd->oobsize) { | 66 | if (mtd->oobsize) { |
67 | struct mtd_oob_ops ops; | 67 | struct mtd_oob_ops ops; |
68 | 68 | ||
69 | ops.mode = MTD_OOB_PLACE; | 69 | ops.mode = MTD_OPS_PLACE_OOB; |
70 | ops.len = 0; | 70 | ops.len = 0; |
71 | ops.retlen = 0; | 71 | ops.retlen = 0; |
72 | ops.ooblen = mtd->oobsize; | 72 | ops.ooblen = mtd->oobsize; |
@@ -75,7 +75,8 @@ static int read_eraseblock_by_page(int ebnum) | |||
75 | ops.datbuf = NULL; | 75 | ops.datbuf = NULL; |
76 | ops.oobbuf = oobbuf; | 76 | ops.oobbuf = oobbuf; |
77 | ret = mtd->read_oob(mtd, addr, &ops); | 77 | ret = mtd->read_oob(mtd, addr, &ops); |
78 | if (ret || ops.oobretlen != mtd->oobsize) { | 78 | if ((ret && !mtd_is_bitflip(ret)) || |
79 | ops.oobretlen != mtd->oobsize) { | ||
79 | printk(PRINT_PREF "error: read oob failed at " | 80 | printk(PRINT_PREF "error: read oob failed at " |
80 | "%#llx\n", (long long)addr); | 81 | "%#llx\n", (long long)addr); |
81 | if (!err) | 82 | if (!err) |
@@ -169,6 +170,12 @@ static int __init mtd_readtest_init(void) | |||
169 | 170 | ||
170 | printk(KERN_INFO "\n"); | 171 | printk(KERN_INFO "\n"); |
171 | printk(KERN_INFO "=================================================\n"); | 172 | printk(KERN_INFO "=================================================\n"); |
173 | |||
174 | if (dev < 0) { | ||
175 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | |||
172 | printk(PRINT_PREF "MTD device: %d\n", dev); | 179 | printk(PRINT_PREF "MTD device: %d\n", dev); |
173 | 180 | ||
174 | mtd = get_mtd_device(NULL, dev); | 181 | mtd = get_mtd_device(NULL, dev); |
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 627d4e2466a3..493b367bdd35 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #define PRINT_PREF KERN_INFO "mtd_speedtest: " | 30 | #define PRINT_PREF KERN_INFO "mtd_speedtest: " |
31 | 31 | ||
32 | static int dev; | 32 | static int dev = -EINVAL; |
33 | module_param(dev, int, S_IRUGO); | 33 | module_param(dev, int, S_IRUGO); |
34 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 34 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
35 | 35 | ||
@@ -216,7 +216,7 @@ static int read_eraseblock(int ebnum) | |||
216 | 216 | ||
217 | err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf); | 217 | err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf); |
218 | /* Ignore corrected ECC errors */ | 218 | /* Ignore corrected ECC errors */ |
219 | if (err == -EUCLEAN) | 219 | if (mtd_is_bitflip(err)) |
220 | err = 0; | 220 | err = 0; |
221 | if (err || read != mtd->erasesize) { | 221 | if (err || read != mtd->erasesize) { |
222 | printk(PRINT_PREF "error: read failed at %#llx\n", addr); | 222 | printk(PRINT_PREF "error: read failed at %#llx\n", addr); |
@@ -237,7 +237,7 @@ static int read_eraseblock_by_page(int ebnum) | |||
237 | for (i = 0; i < pgcnt; i++) { | 237 | for (i = 0; i < pgcnt; i++) { |
238 | err = mtd->read(mtd, addr, pgsize, &read, buf); | 238 | err = mtd->read(mtd, addr, pgsize, &read, buf); |
239 | /* Ignore corrected ECC errors */ | 239 | /* Ignore corrected ECC errors */ |
240 | if (err == -EUCLEAN) | 240 | if (mtd_is_bitflip(err)) |
241 | err = 0; | 241 | err = 0; |
242 | if (err || read != pgsize) { | 242 | if (err || read != pgsize) { |
243 | printk(PRINT_PREF "error: read failed at %#llx\n", | 243 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -263,7 +263,7 @@ static int read_eraseblock_by_2pages(int ebnum) | |||
263 | for (i = 0; i < n; i++) { | 263 | for (i = 0; i < n; i++) { |
264 | err = mtd->read(mtd, addr, sz, &read, buf); | 264 | err = mtd->read(mtd, addr, sz, &read, buf); |
265 | /* Ignore corrected ECC errors */ | 265 | /* Ignore corrected ECC errors */ |
266 | if (err == -EUCLEAN) | 266 | if (mtd_is_bitflip(err)) |
267 | err = 0; | 267 | err = 0; |
268 | if (err || read != sz) { | 268 | if (err || read != sz) { |
269 | printk(PRINT_PREF "error: read failed at %#llx\n", | 269 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -278,7 +278,7 @@ static int read_eraseblock_by_2pages(int ebnum) | |||
278 | if (pgcnt % 2) { | 278 | if (pgcnt % 2) { |
279 | err = mtd->read(mtd, addr, pgsize, &read, buf); | 279 | err = mtd->read(mtd, addr, pgsize, &read, buf); |
280 | /* Ignore corrected ECC errors */ | 280 | /* Ignore corrected ECC errors */ |
281 | if (err == -EUCLEAN) | 281 | if (mtd_is_bitflip(err)) |
282 | err = 0; | 282 | err = 0; |
283 | if (err || read != pgsize) { | 283 | if (err || read != pgsize) { |
284 | printk(PRINT_PREF "error: read failed at %#llx\n", | 284 | printk(PRINT_PREF "error: read failed at %#llx\n", |
@@ -361,6 +361,13 @@ static int __init mtd_speedtest_init(void) | |||
361 | 361 | ||
362 | printk(KERN_INFO "\n"); | 362 | printk(KERN_INFO "\n"); |
363 | printk(KERN_INFO "=================================================\n"); | 363 | printk(KERN_INFO "=================================================\n"); |
364 | |||
365 | if (dev < 0) { | ||
366 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
367 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
364 | if (count) | 371 | if (count) |
365 | printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count); | 372 | printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count); |
366 | else | 373 | else |
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c index 531625fc9259..52ffd9120e0d 100644 --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/mtd_stresstest.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #define PRINT_PREF KERN_INFO "mtd_stresstest: " | 31 | #define PRINT_PREF KERN_INFO "mtd_stresstest: " |
32 | 32 | ||
33 | static int dev; | 33 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 34 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 35 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
36 | 36 | ||
@@ -154,7 +154,7 @@ static int do_read(void) | |||
154 | } | 154 | } |
155 | addr = eb * mtd->erasesize + offs; | 155 | addr = eb * mtd->erasesize + offs; |
156 | err = mtd->read(mtd, addr, len, &read, readbuf); | 156 | err = mtd->read(mtd, addr, len, &read, readbuf); |
157 | if (err == -EUCLEAN) | 157 | if (mtd_is_bitflip(err)) |
158 | err = 0; | 158 | err = 0; |
159 | if (unlikely(err || read != len)) { | 159 | if (unlikely(err || read != len)) { |
160 | printk(PRINT_PREF "error: read failed at 0x%llx\n", | 160 | printk(PRINT_PREF "error: read failed at 0x%llx\n", |
@@ -250,6 +250,13 @@ static int __init mtd_stresstest_init(void) | |||
250 | 250 | ||
251 | printk(KERN_INFO "\n"); | 251 | printk(KERN_INFO "\n"); |
252 | printk(KERN_INFO "=================================================\n"); | 252 | printk(KERN_INFO "=================================================\n"); |
253 | |||
254 | if (dev < 0) { | ||
255 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
256 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
253 | printk(PRINT_PREF "MTD device: %d\n", dev); | 260 | printk(PRINT_PREF "MTD device: %d\n", dev); |
254 | 261 | ||
255 | mtd = get_mtd_device(NULL, dev); | 262 | mtd = get_mtd_device(NULL, dev); |
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c index 334eae53a3db..1a05bfac4eee 100644 --- a/drivers/mtd/tests/mtd_subpagetest.c +++ b/drivers/mtd/tests/mtd_subpagetest.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #define PRINT_PREF KERN_INFO "mtd_subpagetest: " | 30 | #define PRINT_PREF KERN_INFO "mtd_subpagetest: " |
31 | 31 | ||
32 | static int dev; | 32 | static int dev = -EINVAL; |
33 | module_param(dev, int, S_IRUGO); | 33 | module_param(dev, int, S_IRUGO); |
34 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 34 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
35 | 35 | ||
@@ -198,7 +198,7 @@ static int verify_eraseblock(int ebnum) | |||
198 | read = 0; | 198 | read = 0; |
199 | err = mtd->read(mtd, addr, subpgsize, &read, readbuf); | 199 | err = mtd->read(mtd, addr, subpgsize, &read, readbuf); |
200 | if (unlikely(err || read != subpgsize)) { | 200 | if (unlikely(err || read != subpgsize)) { |
201 | if (err == -EUCLEAN && read == subpgsize) { | 201 | if (mtd_is_bitflip(err) && read == subpgsize) { |
202 | printk(PRINT_PREF "ECC correction at %#llx\n", | 202 | printk(PRINT_PREF "ECC correction at %#llx\n", |
203 | (long long)addr); | 203 | (long long)addr); |
204 | err = 0; | 204 | err = 0; |
@@ -226,7 +226,7 @@ static int verify_eraseblock(int ebnum) | |||
226 | read = 0; | 226 | read = 0; |
227 | err = mtd->read(mtd, addr, subpgsize, &read, readbuf); | 227 | err = mtd->read(mtd, addr, subpgsize, &read, readbuf); |
228 | if (unlikely(err || read != subpgsize)) { | 228 | if (unlikely(err || read != subpgsize)) { |
229 | if (err == -EUCLEAN && read == subpgsize) { | 229 | if (mtd_is_bitflip(err) && read == subpgsize) { |
230 | printk(PRINT_PREF "ECC correction at %#llx\n", | 230 | printk(PRINT_PREF "ECC correction at %#llx\n", |
231 | (long long)addr); | 231 | (long long)addr); |
232 | err = 0; | 232 | err = 0; |
@@ -264,7 +264,7 @@ static int verify_eraseblock2(int ebnum) | |||
264 | read = 0; | 264 | read = 0; |
265 | err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf); | 265 | err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf); |
266 | if (unlikely(err || read != subpgsize * k)) { | 266 | if (unlikely(err || read != subpgsize * k)) { |
267 | if (err == -EUCLEAN && read == subpgsize * k) { | 267 | if (mtd_is_bitflip(err) && read == subpgsize * k) { |
268 | printk(PRINT_PREF "ECC correction at %#llx\n", | 268 | printk(PRINT_PREF "ECC correction at %#llx\n", |
269 | (long long)addr); | 269 | (long long)addr); |
270 | err = 0; | 270 | err = 0; |
@@ -298,7 +298,7 @@ static int verify_eraseblock_ff(int ebnum) | |||
298 | read = 0; | 298 | read = 0; |
299 | err = mtd->read(mtd, addr, subpgsize, &read, readbuf); | 299 | err = mtd->read(mtd, addr, subpgsize, &read, readbuf); |
300 | if (unlikely(err || read != subpgsize)) { | 300 | if (unlikely(err || read != subpgsize)) { |
301 | if (err == -EUCLEAN && read == subpgsize) { | 301 | if (mtd_is_bitflip(err) && read == subpgsize) { |
302 | printk(PRINT_PREF "ECC correction at %#llx\n", | 302 | printk(PRINT_PREF "ECC correction at %#llx\n", |
303 | (long long)addr); | 303 | (long long)addr); |
304 | err = 0; | 304 | err = 0; |
@@ -379,6 +379,13 @@ static int __init mtd_subpagetest_init(void) | |||
379 | 379 | ||
380 | printk(KERN_INFO "\n"); | 380 | printk(KERN_INFO "\n"); |
381 | printk(KERN_INFO "=================================================\n"); | 381 | printk(KERN_INFO "=================================================\n"); |
382 | |||
383 | if (dev < 0) { | ||
384 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
385 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | |||
382 | printk(PRINT_PREF "MTD device: %d\n", dev); | 389 | printk(PRINT_PREF "MTD device: %d\n", dev); |
383 | 390 | ||
384 | mtd = get_mtd_device(NULL, dev); | 391 | mtd = get_mtd_device(NULL, dev); |
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c index 5c6c3d248901..03ab649a6964 100644 --- a/drivers/mtd/tests/mtd_torturetest.c +++ b/drivers/mtd/tests/mtd_torturetest.c | |||
@@ -46,7 +46,7 @@ static int pgcnt; | |||
46 | module_param(pgcnt, int, S_IRUGO); | 46 | module_param(pgcnt, int, S_IRUGO); |
47 | MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)"); | 47 | MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)"); |
48 | 48 | ||
49 | static int dev; | 49 | static int dev = -EINVAL; |
50 | module_param(dev, int, S_IRUGO); | 50 | module_param(dev, int, S_IRUGO); |
51 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 51 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
52 | 52 | ||
@@ -138,7 +138,7 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf) | |||
138 | 138 | ||
139 | retry: | 139 | retry: |
140 | err = mtd->read(mtd, addr, len, &read, check_buf); | 140 | err = mtd->read(mtd, addr, len, &read, check_buf); |
141 | if (err == -EUCLEAN) | 141 | if (mtd_is_bitflip(err)) |
142 | printk(PRINT_PREF "single bit flip occurred at EB %d " | 142 | printk(PRINT_PREF "single bit flip occurred at EB %d " |
143 | "MTD reported that it was fixed.\n", ebnum); | 143 | "MTD reported that it was fixed.\n", ebnum); |
144 | else if (err) { | 144 | else if (err) { |
@@ -213,6 +213,13 @@ static int __init tort_init(void) | |||
213 | printk(KERN_INFO "=================================================\n"); | 213 | printk(KERN_INFO "=================================================\n"); |
214 | printk(PRINT_PREF "Warning: this program is trying to wear out your " | 214 | printk(PRINT_PREF "Warning: this program is trying to wear out your " |
215 | "flash, stop it if this is not wanted.\n"); | 215 | "flash, stop it if this is not wanted.\n"); |
216 | |||
217 | if (dev < 0) { | ||
218 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | ||
219 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
216 | printk(PRINT_PREF "MTD device: %d\n", dev); | 223 | printk(PRINT_PREF "MTD device: %d\n", dev); |
217 | printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", | 224 | printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", |
218 | ebcnt, eb, eb + ebcnt - 1, dev); | 225 | ebcnt, eb, eb + ebcnt - 1, dev); |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 4be671815014..fb7f19b62d91 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -443,7 +443,7 @@ retry: | |||
443 | if (err == UBI_IO_BITFLIPS) { | 443 | if (err == UBI_IO_BITFLIPS) { |
444 | scrub = 1; | 444 | scrub = 1; |
445 | err = 0; | 445 | err = 0; |
446 | } else if (err == -EBADMSG) { | 446 | } else if (mtd_is_eccerr(err)) { |
447 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) | 447 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) |
448 | goto out_unlock; | 448 | goto out_unlock; |
449 | scrub = 1; | 449 | scrub = 1; |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 6ba55c235873..f20b6f22f240 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -172,9 +172,9 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, | |||
172 | retry: | 172 | retry: |
173 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); | 173 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); |
174 | if (err) { | 174 | if (err) { |
175 | const char *errstr = (err == -EBADMSG) ? " (ECC error)" : ""; | 175 | const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : ""; |
176 | 176 | ||
177 | if (err == -EUCLEAN) { | 177 | if (mtd_is_bitflip(err)) { |
178 | /* | 178 | /* |
179 | * -EUCLEAN is reported if there was a bit-flip which | 179 | * -EUCLEAN is reported if there was a bit-flip which |
180 | * was corrected, so this is harmless. | 180 | * was corrected, so this is harmless. |
@@ -205,7 +205,7 @@ retry: | |||
205 | * all the requested data. But some buggy drivers might do | 205 | * all the requested data. But some buggy drivers might do |
206 | * this, so we change it to -EIO. | 206 | * this, so we change it to -EIO. |
207 | */ | 207 | */ |
208 | if (read != len && err == -EBADMSG) { | 208 | if (read != len && mtd_is_eccerr(err)) { |
209 | ubi_assert(0); | 209 | ubi_assert(0); |
210 | err = -EIO; | 210 | err = -EIO; |
211 | } | 211 | } |
@@ -469,7 +469,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) | |||
469 | 469 | ||
470 | out: | 470 | out: |
471 | mutex_unlock(&ubi->buf_mutex); | 471 | mutex_unlock(&ubi->buf_mutex); |
472 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) { | 472 | if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) { |
473 | /* | 473 | /* |
474 | * If a bit-flip or data integrity error was detected, the test | 474 | * If a bit-flip or data integrity error was detected, the test |
475 | * has not passed because it happened on a freshly erased | 475 | * has not passed because it happened on a freshly erased |
@@ -760,7 +760,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
760 | 760 | ||
761 | read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); | 761 | read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); |
762 | if (read_err) { | 762 | if (read_err) { |
763 | if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG) | 763 | if (read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err)) |
764 | return read_err; | 764 | return read_err; |
765 | 765 | ||
766 | /* | 766 | /* |
@@ -776,7 +776,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
776 | 776 | ||
777 | magic = be32_to_cpu(ec_hdr->magic); | 777 | magic = be32_to_cpu(ec_hdr->magic); |
778 | if (magic != UBI_EC_HDR_MAGIC) { | 778 | if (magic != UBI_EC_HDR_MAGIC) { |
779 | if (read_err == -EBADMSG) | 779 | if (mtd_is_eccerr(read_err)) |
780 | return UBI_IO_BAD_HDR_EBADMSG; | 780 | return UBI_IO_BAD_HDR_EBADMSG; |
781 | 781 | ||
782 | /* | 782 | /* |
@@ -1032,12 +1032,12 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, | |||
1032 | p = (char *)vid_hdr - ubi->vid_hdr_shift; | 1032 | p = (char *)vid_hdr - ubi->vid_hdr_shift; |
1033 | read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, | 1033 | read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, |
1034 | ubi->vid_hdr_alsize); | 1034 | ubi->vid_hdr_alsize); |
1035 | if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG) | 1035 | if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err)) |
1036 | return read_err; | 1036 | return read_err; |
1037 | 1037 | ||
1038 | magic = be32_to_cpu(vid_hdr->magic); | 1038 | magic = be32_to_cpu(vid_hdr->magic); |
1039 | if (magic != UBI_VID_HDR_MAGIC) { | 1039 | if (magic != UBI_VID_HDR_MAGIC) { |
1040 | if (read_err == -EBADMSG) | 1040 | if (mtd_is_eccerr(read_err)) |
1041 | return UBI_IO_BAD_HDR_EBADMSG; | 1041 | return UBI_IO_BAD_HDR_EBADMSG; |
1042 | 1042 | ||
1043 | if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { | 1043 | if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { |
@@ -1219,7 +1219,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) | |||
1219 | return -ENOMEM; | 1219 | return -ENOMEM; |
1220 | 1220 | ||
1221 | err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); | 1221 | err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); |
1222 | if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) | 1222 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) |
1223 | goto exit; | 1223 | goto exit; |
1224 | 1224 | ||
1225 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); | 1225 | crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); |
@@ -1306,7 +1306,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) | |||
1306 | p = (char *)vid_hdr - ubi->vid_hdr_shift; | 1306 | p = (char *)vid_hdr - ubi->vid_hdr_shift; |
1307 | err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, | 1307 | err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, |
1308 | ubi->vid_hdr_alsize); | 1308 | ubi->vid_hdr_alsize); |
1309 | if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) | 1309 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) |
1310 | goto exit; | 1310 | goto exit; |
1311 | 1311 | ||
1312 | crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC); | 1312 | crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC); |
@@ -1358,7 +1358,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, | |||
1358 | } | 1358 | } |
1359 | 1359 | ||
1360 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1); | 1360 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1); |
1361 | if (err && err != -EUCLEAN) | 1361 | if (err && !mtd_is_bitflip(err)) |
1362 | goto out_free; | 1362 | goto out_free; |
1363 | 1363 | ||
1364 | for (i = 0; i < len; i++) { | 1364 | for (i = 0; i < len; i++) { |
@@ -1422,7 +1422,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) | |||
1422 | } | 1422 | } |
1423 | 1423 | ||
1424 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); | 1424 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); |
1425 | if (err && err != -EUCLEAN) { | 1425 | if (err && !mtd_is_bitflip(err)) { |
1426 | ubi_err("error %d while reading %d bytes from PEB %d:%d, " | 1426 | ubi_err("error %d while reading %d bytes from PEB %d:%d, " |
1427 | "read %zd bytes", err, len, pnum, offset, read); | 1427 | "read %zd bytes", err, len, pnum, offset, read); |
1428 | goto error; | 1428 | goto error; |
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index d39716e5b204..1a35fc5e3b40 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c | |||
@@ -410,7 +410,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, | |||
410 | return 0; | 410 | return 0; |
411 | 411 | ||
412 | err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); | 412 | err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); |
413 | if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) { | 413 | if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { |
414 | ubi_warn("mark volume %d as corrupted", vol_id); | 414 | ubi_warn("mark volume %d as corrupted", vol_id); |
415 | vol->corrupted = 1; | 415 | vol->corrupted = 1; |
416 | } | 416 | } |
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c index ff2a65c37f69..f6a7d7ac4b98 100644 --- a/drivers/mtd/ubi/misc.c +++ b/drivers/mtd/ubi/misc.c | |||
@@ -81,7 +81,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id) | |||
81 | 81 | ||
82 | err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1); | 82 | err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1); |
83 | if (err) { | 83 | if (err) { |
84 | if (err == -EBADMSG) | 84 | if (mtd_is_eccerr(err)) |
85 | err = 1; | 85 | err = 1; |
86 | break; | 86 | break; |
87 | } | 87 | } |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index a3a198f9b98d..0cb17d936b5a 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -395,7 +395,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, | |||
395 | } | 395 | } |
396 | 396 | ||
397 | err = ubi_io_read_data(ubi, buf, pnum, 0, len); | 397 | err = ubi_io_read_data(ubi, buf, pnum, 0, len); |
398 | if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) | 398 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) |
399 | goto out_free_buf; | 399 | goto out_free_buf; |
400 | 400 | ||
401 | data_crc = be32_to_cpu(vid_hdr->data_crc); | 401 | data_crc = be32_to_cpu(vid_hdr->data_crc); |
@@ -793,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | |||
793 | 793 | ||
794 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start, | 794 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start, |
795 | ubi->leb_size); | 795 | ubi->leb_size); |
796 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) { | 796 | if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) { |
797 | /* | 797 | /* |
798 | * Bit-flips or integrity errors while reading the data area. | 798 | * Bit-flips or integrity errors while reading the data area. |
799 | * It is difficult to say for sure what type of corruption is | 799 | * It is difficult to say for sure what type of corruption is |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 4b50a3029b84..9ad18da1891d 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
@@ -423,7 +423,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, | |||
423 | 423 | ||
424 | err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, | 424 | err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, |
425 | ubi->vtbl_size); | 425 | ubi->vtbl_size); |
426 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) | 426 | if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) |
427 | /* | 427 | /* |
428 | * Scrub the PEB later. Note, -EBADMSG indicates an | 428 | * Scrub the PEB later. Note, -EBADMSG indicates an |
429 | * uncorrectable ECC error, but we have our own CRC and | 429 | * uncorrectable ECC error, but we have our own CRC and |