aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-22 22:32:13 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-22 22:32:13 -0500
commitebcccd14b73831fa7fbc197e1d2b9c710a65731e (patch)
tree88af3e74135bdb3d0af7bc9ef48de0c2f879fcbb
parente00154891137e3b0659556b877d45a16cabd700c (diff)
parent9cdf083f981b8d37b3212400a359368661385099 (diff)
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (84 commits) [JFFS2] debug.h: include <linux/sched.h> for current->pid [MTD] OneNAND: Handle DDP chip boundary during read-while-load [MTD] OneNAND: return ecc error code only when 2-bit ecc occurs [MTD] OneNAND: Implement read-while-load [MTD] OneNAND: fix onenand_wait bug in read ecc error [MTD] OneNAND: release CPU in cycles [MTD] OneNAND: add subpage write support [MTD] OneNAND: fix onenand_wait bug [JFFS2] use the ref_offset macro [JFFS2] Reschedule in loops [JFFS2] Fix error-path leak in summary scan [JFFS2] add cond_resched() when garbage collecting deletion dirent [MTD] Nuke IVR leftovers [MTD] OneNAND: fix oob handling in recent oob patch [MTD] Fix ssfdc blksize typo [JFFS2] replace kmalloc+memset with kzalloc [MTD] Fix SSFDC build for variable blocksize. [MTD] ESB2ROM uses PCI [MTD] of_device-based physmap driver [MTD] Support combined RedBoot FIS directory and configuration area ...
-rw-r--r--arch/ppc/platforms/ev64360.c3
-rw-r--r--drivers/mtd/Kconfig15
-rw-r--r--drivers/mtd/Makefile15
-rw-r--r--drivers/mtd/afs.c3
-rw-r--r--drivers/mtd/chips/amd_flash.c3
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c5
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c11
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c3
-rw-r--r--drivers/mtd/chips/gen_probe.c5
-rw-r--r--drivers/mtd/chips/jedec.c3
-rw-r--r--drivers/mtd/chips/jedec_probe.c17
-rw-r--r--drivers/mtd/chips/map_absent.c4
-rw-r--r--drivers/mtd/chips/map_ram.c4
-rw-r--r--drivers/mtd/chips/map_rom.c4
-rw-r--r--drivers/mtd/chips/sharp.c7
-rw-r--r--drivers/mtd/cmdlinepart.c5
-rw-r--r--drivers/mtd/devices/block2mtd.c3
-rw-r--r--drivers/mtd/devices/ms02-nv.c18
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/devices/phram.c4
-rw-r--r--drivers/mtd/devices/slram.c7
-rw-r--r--drivers/mtd/ftl.c7
-rw-r--r--drivers/mtd/inftlcore.c12
-rw-r--r--drivers/mtd/maps/Kconfig71
-rw-r--r--drivers/mtd/maps/Makefile4
-rw-r--r--drivers/mtd/maps/amd76xrom.c34
-rw-r--r--drivers/mtd/maps/bast-flash.c2
-rw-r--r--drivers/mtd/maps/ceiva.c3
-rw-r--r--drivers/mtd/maps/ck804xrom.c356
-rw-r--r--drivers/mtd/maps/cstm_mips_ixx.c283
-rw-r--r--drivers/mtd/maps/esb2rom.c450
-rw-r--r--drivers/mtd/maps/integrator-flash.c4
-rw-r--r--drivers/mtd/maps/nettel.c5
-rw-r--r--drivers/mtd/maps/omap_nor.c4
-rw-r--r--drivers/mtd/maps/pcmciamtd.c3
-rw-r--r--drivers/mtd/maps/physmap.c5
-rw-r--r--drivers/mtd/maps/physmap_of.c255
-rw-r--r--drivers/mtd/maps/plat-ram.c3
-rw-r--r--drivers/mtd/maps/sa1100-flash.c4
-rw-r--r--drivers/mtd/maps/tqm834x.c8
-rw-r--r--drivers/mtd/maps/tqm8xxl.c3
-rw-r--r--drivers/mtd/mtd_blkdevs.c19
-rw-r--r--drivers/mtd/mtdblock.c10
-rw-r--r--drivers/mtd/mtdblock_ro.c7
-rw-r--r--drivers/mtd/mtdchar.c23
-rw-r--r--drivers/mtd/mtdconcat.c43
-rw-r--r--drivers/mtd/mtdcore.c93
-rw-r--r--drivers/mtd/mtdpart.c8
-rw-r--r--drivers/mtd/nand/Kconfig16
-rw-r--r--drivers/mtd/nand/Makefile5
-rw-r--r--drivers/mtd/nand/at91_nand.c223
-rw-r--r--drivers/mtd/nand/cafe.c770
-rw-r--r--drivers/mtd/nand/cafe_ecc.c1381
-rw-r--r--drivers/mtd/nand/cs553x_nand.c4
-rw-r--r--drivers/mtd/nand/diskonchip.c3
-rw-r--r--drivers/mtd/nand/nand_base.c133
-rw-r--r--drivers/mtd/nand/nand_bbt.c11
-rw-r--r--drivers/mtd/nand/nand_ecc.c4
-rw-r--r--drivers/mtd/nand/nandsim.c243
-rw-r--r--drivers/mtd/nand/ndfc.c2
-rw-r--r--drivers/mtd/nand/rtc_from4.c46
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/nftlcore.c12
-rw-r--r--drivers/mtd/onenand/generic.c5
-rw-r--r--drivers/mtd/onenand/onenand_base.c374
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c14
-rw-r--r--drivers/mtd/redboot.c30
-rw-r--r--drivers/mtd/rfd_ftl.c3
-rw-r--r--drivers/mtd/ssfdc.c7
-rw-r--r--fs/jffs/jffs_fm.c3
-rw-r--r--fs/jffs2/debug.c4
-rw-r--r--fs/jffs2/debug.h1
-rw-r--r--fs/jffs2/fs.c3
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/jffs2/nodelist.h10
-rw-r--r--fs/jffs2/readinode.c3
-rw-r--r--fs/jffs2/scan.c6
-rw-r--r--fs/jffs2/summary.c6
-rw-r--r--fs/jffs2/super.c7
-rw-r--r--fs/jffs2/symlink.c2
-rw-r--r--fs/jffs2/wbuf.c21
-rw-r--r--fs/jffs2/xattr.c5
-rw-r--r--include/linux/mtd/blktrans.h3
-rw-r--r--include/linux/mtd/mtd.h24
-rw-r--r--include/linux/mtd/nand.h15
-rw-r--r--include/linux/mtd/onenand.h8
-rw-r--r--include/linux/mtd/onenand_regs.h1
87 files changed, 4404 insertions, 868 deletions
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
index 90ed375c9b90..f87e06f6bab9 100644
--- a/arch/ppc/platforms/ev64360.c
+++ b/arch/ppc/platforms/ev64360.c
@@ -358,13 +358,12 @@ ev64360_setup_mtd(void)
358 358
359 ptbl_entries = 3; 359 ptbl_entries = 3;
360 360
361 if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition), 361 if ((ptbl = kzalloc(ptbl_entries * sizeof(struct mtd_partition),
362 GFP_KERNEL)) == NULL) { 362 GFP_KERNEL)) == NULL) {
363 363
364 printk(KERN_WARNING "Can't alloc MTD partition table\n"); 364 printk(KERN_WARNING "Can't alloc MTD partition table\n");
365 return -ENOMEM; 365 return -ENOMEM;
366 } 366 }
367 memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
368 367
369 ptbl[0].name = "reserved"; 368 ptbl[0].name = "reserved";
370 ptbl[0].offset = 0; 369 ptbl[0].offset = 0;
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index a304b34c2632..26f75c299440 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -164,9 +164,15 @@ config MTD_CHAR
164 memory chips, and also use ioctl() to obtain information about 164 memory chips, and also use ioctl() to obtain information about
165 the device, or to erase parts of it. 165 the device, or to erase parts of it.
166 166
167config MTD_BLKDEVS
168 tristate "Common interface to block layer for MTD 'translation layers'"
169 depends on MTD && BLOCK
170 default n
171
167config MTD_BLOCK 172config MTD_BLOCK
168 tristate "Caching block device access to MTD devices" 173 tristate "Caching block device access to MTD devices"
169 depends on MTD && BLOCK 174 depends on MTD && BLOCK
175 select MTD_BLKDEVS
170 ---help--- 176 ---help---
171 Although most flash chips have an erase size too large to be useful 177 Although most flash chips have an erase size too large to be useful
172 as block devices, it is possible to use MTD devices which are based 178 as block devices, it is possible to use MTD devices which are based
@@ -189,6 +195,7 @@ config MTD_BLOCK
189config MTD_BLOCK_RO 195config MTD_BLOCK_RO
190 tristate "Readonly block device access to MTD devices" 196 tristate "Readonly block device access to MTD devices"
191 depends on MTD_BLOCK!=y && MTD && BLOCK 197 depends on MTD_BLOCK!=y && MTD && BLOCK
198 select MTD_BLKDEVS
192 help 199 help
193 This allows you to mount read-only file systems (such as cramfs) 200 This allows you to mount read-only file systems (such as cramfs)
194 from an MTD device, without the overhead (and danger) of the caching 201 from an MTD device, without the overhead (and danger) of the caching
@@ -200,6 +207,7 @@ config MTD_BLOCK_RO
200config FTL 207config FTL
201 tristate "FTL (Flash Translation Layer) support" 208 tristate "FTL (Flash Translation Layer) support"
202 depends on MTD && BLOCK 209 depends on MTD && BLOCK
210 select MTD_BLKDEVS
203 ---help--- 211 ---help---
204 This provides support for the original Flash Translation Layer which 212 This provides support for the original Flash Translation Layer which
205 is part of the PCMCIA specification. It uses a kind of pseudo- 213 is part of the PCMCIA specification. It uses a kind of pseudo-
@@ -216,6 +224,7 @@ config FTL
216config NFTL 224config NFTL
217 tristate "NFTL (NAND Flash Translation Layer) support" 225 tristate "NFTL (NAND Flash Translation Layer) support"
218 depends on MTD && BLOCK 226 depends on MTD && BLOCK
227 select MTD_BLKDEVS
219 ---help--- 228 ---help---
220 This provides support for the NAND Flash Translation Layer which is 229 This provides support for the NAND Flash Translation Layer which is
221 used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- 230 used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
@@ -239,6 +248,7 @@ config NFTL_RW
239config INFTL 248config INFTL
240 tristate "INFTL (Inverse NAND Flash Translation Layer) support" 249 tristate "INFTL (Inverse NAND Flash Translation Layer) support"
241 depends on MTD && BLOCK 250 depends on MTD && BLOCK
251 select MTD_BLKDEVS
242 ---help--- 252 ---help---
243 This provides support for the Inverse NAND Flash Translation 253 This provides support for the Inverse NAND Flash Translation
244 Layer which is used on M-Systems' newer DiskOnChip devices. It 254 Layer which is used on M-Systems' newer DiskOnChip devices. It
@@ -256,6 +266,7 @@ config INFTL
256config RFD_FTL 266config RFD_FTL
257 tristate "Resident Flash Disk (Flash Translation Layer) support" 267 tristate "Resident Flash Disk (Flash Translation Layer) support"
258 depends on MTD && BLOCK 268 depends on MTD && BLOCK
269 select MTD_BLKDEVS
259 ---help--- 270 ---help---
260 This provides support for the flash translation layer known 271 This provides support for the flash translation layer known
261 as the Resident Flash Disk (RFD), as used by the Embedded BIOS 272 as the Resident Flash Disk (RFD), as used by the Embedded BIOS
@@ -265,8 +276,8 @@ config RFD_FTL
265 276
266config SSFDC 277config SSFDC
267 tristate "NAND SSFDC (SmartMedia) read only translation layer" 278 tristate "NAND SSFDC (SmartMedia) read only translation layer"
268 depends on MTD 279 depends on MTD && BLOCK
269 default n 280 select MTD_BLKDEVS
270 help 281 help
271 This enables read only access to SmartMedia formatted NAND 282 This enables read only access to SmartMedia formatted NAND
272 flash. You can mount it with FAT file system. 283 flash. You can mount it with FAT file system.
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 1e36b9aed98b..c130e6261adf 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -15,13 +15,14 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
15 15
16# 'Users' - code which presents functionality to userspace. 16# 'Users' - code which presents functionality to userspace.
17obj-$(CONFIG_MTD_CHAR) += mtdchar.o 17obj-$(CONFIG_MTD_CHAR) += mtdchar.o
18obj-$(CONFIG_MTD_BLOCK) += mtdblock.o mtd_blkdevs.o 18obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
19obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o 19obj-$(CONFIG_MTD_BLOCK) += mtdblock.o
20obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o 20obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o
21obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o 21obj-$(CONFIG_FTL) += ftl.o
22obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o 22obj-$(CONFIG_NFTL) += nftl.o
23obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o 23obj-$(CONFIG_INFTL) += inftl.o
24obj-$(CONFIG_SSFDC) += ssfdc.o mtd_blkdevs.o 24obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
25obj-$(CONFIG_SSFDC) += ssfdc.o
25 26
26nftl-objs := nftlcore.o nftlmount.o 27nftl-objs := nftlcore.o nftlmount.o
27inftl-objs := inftlcore.o inftlmount.o 28inftl-objs := inftlcore.o inftlmount.o
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index 6a45be04564b..52d51eb91c16 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -207,11 +207,10 @@ static int parse_afs_partitions(struct mtd_info *mtd,
207 if (!sz) 207 if (!sz)
208 return ret; 208 return ret;
209 209
210 parts = kmalloc(sz, GFP_KERNEL); 210 parts = kzalloc(sz, GFP_KERNEL);
211 if (!parts) 211 if (!parts)
212 return -ENOMEM; 212 return -ENOMEM;
213 213
214 memset(parts, 0, sz);
215 str = (char *)(parts + idx); 214 str = (char *)(parts + idx);
216 215
217 /* 216 /*
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
index 16eaca69fb5a..e7999f15d85a 100644
--- a/drivers/mtd/chips/amd_flash.c
+++ b/drivers/mtd/chips/amd_flash.c
@@ -643,13 +643,12 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
643 int reg_idx; 643 int reg_idx;
644 int offset; 644 int offset;
645 645
646 mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL); 646 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
647 if (!mtd) { 647 if (!mtd) {
648 printk(KERN_WARNING 648 printk(KERN_WARNING
649 "%s: kmalloc failed for info structure\n", map->name); 649 "%s: kmalloc failed for info structure\n", map->name);
650 return NULL; 650 return NULL;
651 } 651 }
652 memset(mtd, 0, sizeof(*mtd));
653 mtd->priv = map; 652 mtd->priv = map;
654 653
655 memset(&temp, 0, sizeof(temp)); 654 memset(&temp, 0, sizeof(temp));
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 296159ec5189..f69184a92eb2 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -337,12 +337,11 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
337 struct mtd_info *mtd; 337 struct mtd_info *mtd;
338 int i; 338 int i;
339 339
340 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 340 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
341 if (!mtd) { 341 if (!mtd) {
342 printk(KERN_ERR "Failed to allocate memory for MTD device\n"); 342 printk(KERN_ERR "Failed to allocate memory for MTD device\n");
343 return NULL; 343 return NULL;
344 } 344 }
345 memset(mtd, 0, sizeof(*mtd));
346 mtd->priv = map; 345 mtd->priv = map;
347 mtd->type = MTD_NORFLASH; 346 mtd->type = MTD_NORFLASH;
348 347
@@ -2224,6 +2223,8 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
2224 case FL_CFI_QUERY: 2223 case FL_CFI_QUERY:
2225 case FL_JEDEC_QUERY: 2224 case FL_JEDEC_QUERY:
2226 if (chip->oldstate == FL_READY) { 2225 if (chip->oldstate == FL_READY) {
2226 /* place the chip in a known state before suspend */
2227 map_write(map, CMD(0xFF), cfi->chips[i].start);
2227 chip->oldstate = chip->state; 2228 chip->oldstate = chip->state;
2228 chip->state = FL_PM_SUSPENDED; 2229 chip->state = FL_PM_SUSPENDED;
2229 /* No need to wake_up() on this state change - 2230 /* No need to wake_up() on this state change -
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 702ae4cd8691..e3acd398fb37 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -48,6 +48,7 @@
48#define MANUFACTURER_ATMEL 0x001F 48#define MANUFACTURER_ATMEL 0x001F
49#define MANUFACTURER_SST 0x00BF 49#define MANUFACTURER_SST 0x00BF
50#define SST49LF004B 0x0060 50#define SST49LF004B 0x0060
51#define SST49LF040B 0x0050
51#define SST49LF008A 0x005a 52#define SST49LF008A 0x005a
52#define AT49BV6416 0x00d6 53#define AT49BV6416 0x00d6
53 54
@@ -233,6 +234,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
233}; 234};
234static struct cfi_fixup jedec_fixup_table[] = { 235static struct cfi_fixup jedec_fixup_table[] = {
235 { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, 236 { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
237 { MANUFACTURER_SST, SST49LF040B, fixup_use_fwh_lock, NULL, },
236 { MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, }, 238 { MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },
237 { 0, 0, NULL, NULL } 239 { 0, 0, NULL, NULL }
238}; 240};
@@ -255,12 +257,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
255 struct mtd_info *mtd; 257 struct mtd_info *mtd;
256 int i; 258 int i;
257 259
258 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 260 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
259 if (!mtd) { 261 if (!mtd) {
260 printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); 262 printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
261 return NULL; 263 return NULL;
262 } 264 }
263 memset(mtd, 0, sizeof(*mtd));
264 mtd->priv = map; 265 mtd->priv = map;
265 mtd->type = MTD_NORFLASH; 266 mtd->type = MTD_NORFLASH;
266 267
@@ -519,10 +520,12 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
519 if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */ 520 if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
520 goto sleep; 521 goto sleep;
521 522
522 if (!(mode == FL_READY || mode == FL_POINT 523 if (!( mode == FL_READY
524 || mode == FL_POINT
523 || !cfip 525 || !cfip
524 || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) 526 || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
525 || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)))) 527 || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)
528 )))
526 goto sleep; 529 goto sleep;
527 530
528 /* We could check to see if we're trying to access the sector 531 /* We could check to see if we're trying to access the sector
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index fae70a5db540..d56849f5f107 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -172,7 +172,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
172 int i,j; 172 int i,j;
173 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave; 173 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
174 174
175 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 175 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
176 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); 176 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
177 177
178 if (!mtd) { 178 if (!mtd) {
@@ -181,7 +181,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
181 return NULL; 181 return NULL;
182 } 182 }
183 183
184 memset(mtd, 0, sizeof(*mtd));
185 mtd->priv = map; 184 mtd->priv = map;
186 mtd->type = MTD_NORFLASH; 185 mtd->type = MTD_NORFLASH;
187 mtd->size = devsize * cfi->numchips; 186 mtd->size = devsize * cfi->numchips;
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index cdb0f590b40c..2eb696d7b97b 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -40,7 +40,7 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
40 if (mtd) { 40 if (mtd) {
41 if (mtd->size > map->size) { 41 if (mtd->size > map->size) {
42 printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", 42 printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n",
43 (unsigned long)mtd->size >> 10, 43 (unsigned long)mtd->size >> 10,
44 (unsigned long)map->size >> 10); 44 (unsigned long)map->size >> 10);
45 mtd->size = map->size; 45 mtd->size = map->size;
46 } 46 }
@@ -113,13 +113,12 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
113 } 113 }
114 114
115 mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG; 115 mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG;
116 chip_map = kmalloc(mapsize, GFP_KERNEL); 116 chip_map = kzalloc(mapsize, GFP_KERNEL);
117 if (!chip_map) { 117 if (!chip_map) {
118 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); 118 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
119 kfree(cfi.cfiq); 119 kfree(cfi.cfiq);
120 return NULL; 120 return NULL;
121 } 121 }
122 memset (chip_map, 0, mapsize);
123 122
124 set_bit(0, chip_map); /* Mark first chip valid */ 123 set_bit(0, chip_map); /* Mark first chip valid */
125 124
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index 2c3f019197c1..14e57b2bf842 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -116,11 +116,10 @@ static struct mtd_info *jedec_probe(struct map_info *map)
116 char Part[200]; 116 char Part[200];
117 memset(&priv,0,sizeof(priv)); 117 memset(&priv,0,sizeof(priv));
118 118
119 MTD = kmalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL); 119 MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
120 if (!MTD) 120 if (!MTD)
121 return NULL; 121 return NULL;
122 122
123 memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));
124 priv = (struct jedec_private *)&MTD[1]; 123 priv = (struct jedec_private *)&MTD[1];
125 124
126 my_bank_size = map->size; 125 my_bank_size = map->size;
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 1154dac715aa..58e561e87699 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -154,6 +154,7 @@
154#define SST39SF010A 0x00B5 154#define SST39SF010A 0x00B5
155#define SST39SF020A 0x00B6 155#define SST39SF020A 0x00B6
156#define SST49LF004B 0x0060 156#define SST49LF004B 0x0060
157#define SST49LF040B 0x0050
157#define SST49LF008A 0x005a 158#define SST49LF008A 0x005a
158#define SST49LF030A 0x001C 159#define SST49LF030A 0x001C
159#define SST49LF040A 0x0051 160#define SST49LF040A 0x0051
@@ -1401,6 +1402,20 @@ static const struct amd_flash_info jedec_table[] = {
1401 } 1402 }
1402 }, { 1403 }, {
1403 .mfr_id = MANUFACTURER_SST, 1404 .mfr_id = MANUFACTURER_SST,
1405 .dev_id = SST49LF040B,
1406 .name = "SST 49LF040B",
1407 .uaddr = {
1408 [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
1409 },
1410 .DevSize = SIZE_512KiB,
1411 .CmdSet = P_ID_AMD_STD,
1412 .NumEraseRegions= 1,
1413 .regions = {
1414 ERASEINFO(0x01000,128),
1415 }
1416 }, {
1417
1418 .mfr_id = MANUFACTURER_SST,
1404 .dev_id = SST49LF004B, 1419 .dev_id = SST49LF004B,
1405 .name = "SST 49LF004B", 1420 .name = "SST 49LF004B",
1406 .uaddr = { 1421 .uaddr = {
@@ -1874,7 +1889,7 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
1874 1889
1875 1890
1876/* 1891/*
1877 * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing 1892 * There is a BIG problem properly ID'ing the JEDEC device and guaranteeing
1878 * the mapped address, unlock addresses, and proper chip ID. This function 1893 * the mapped address, unlock addresses, and proper chip ID. This function
1879 * attempts to minimize errors. It is doubtfull that this probe will ever 1894 * attempts to minimize errors. It is doubtfull that this probe will ever
1880 * be perfect - consequently there should be some module parameters that 1895 * be perfect - consequently there should be some module parameters that
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c
index ac01a949b687..fc478c0f93f5 100644
--- a/drivers/mtd/chips/map_absent.c
+++ b/drivers/mtd/chips/map_absent.c
@@ -47,13 +47,11 @@ static struct mtd_info *map_absent_probe(struct map_info *map)
47{ 47{
48 struct mtd_info *mtd; 48 struct mtd_info *mtd;
49 49
50 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 50 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
51 if (!mtd) { 51 if (!mtd) {
52 return NULL; 52 return NULL;
53 } 53 }
54 54
55 memset(mtd, 0, sizeof(*mtd));
56
57 map->fldrv = &map_absent_chipdrv; 55 map->fldrv = &map_absent_chipdrv;
58 mtd->priv = map; 56 mtd->priv = map;
59 mtd->name = map->name; 57 mtd->name = map->name;
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c
index 3a66680abfd0..5cb6d5263661 100644
--- a/drivers/mtd/chips/map_ram.c
+++ b/drivers/mtd/chips/map_ram.c
@@ -55,12 +55,10 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
55#endif 55#endif
56 /* OK. It seems to be RAM. */ 56 /* OK. It seems to be RAM. */
57 57
58 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 58 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
59 if (!mtd) 59 if (!mtd)
60 return NULL; 60 return NULL;
61 61
62 memset(mtd, 0, sizeof(*mtd));
63
64 map->fldrv = &mapram_chipdrv; 62 map->fldrv = &mapram_chipdrv;
65 mtd->priv = map; 63 mtd->priv = map;
66 mtd->name = map->name; 64 mtd->name = map->name;
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 1b328b1378fd..cb27f855074c 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -31,12 +31,10 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
31{ 31{
32 struct mtd_info *mtd; 32 struct mtd_info *mtd;
33 33
34 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 34 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
35 if (!mtd) 35 if (!mtd)
36 return NULL; 36 return NULL;
37 37
38 memset(mtd, 0, sizeof(*mtd));
39
40 map->fldrv = &maprom_chipdrv; 38 map->fldrv = &maprom_chipdrv;
41 mtd->priv = map; 39 mtd->priv = map;
42 mtd->name = map->name; 40 mtd->name = map->name;
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index 967abbecdff9..c9cd3d21ccfa 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -112,18 +112,16 @@ static struct mtd_info *sharp_probe(struct map_info *map)
112 struct sharp_info *sharp = NULL; 112 struct sharp_info *sharp = NULL;
113 int width; 113 int width;
114 114
115 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 115 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
116 if(!mtd) 116 if(!mtd)
117 return NULL; 117 return NULL;
118 118
119 sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); 119 sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
120 if(!sharp) { 120 if(!sharp) {
121 kfree(mtd); 121 kfree(mtd);
122 return NULL; 122 return NULL;
123 } 123 }
124 124
125 memset(mtd, 0, sizeof(*mtd));
126
127 width = sharp_probe_map(map,mtd); 125 width = sharp_probe_map(map,mtd);
128 if(!width){ 126 if(!width){
129 kfree(mtd); 127 kfree(mtd);
@@ -143,7 +141,6 @@ static struct mtd_info *sharp_probe(struct map_info *map)
143 mtd->writesize = 1; 141 mtd->writesize = 1;
144 mtd->name = map->name; 142 mtd->name = map->name;
145 143
146 memset(sharp, 0, sizeof(*sharp));
147 sharp->chipshift = 23; 144 sharp->chipshift = 23;
148 sharp->numchips = 1; 145 sharp->numchips = 1;
149 sharp->chips[0].start = 0; 146 sharp->chips[0].start = 0;
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index a7a7bfe33879..23fab14f1637 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -163,13 +163,12 @@ static struct mtd_partition * newpart(char *s,
163 *num_parts = this_part + 1; 163 *num_parts = this_part + 1;
164 alloc_size = *num_parts * sizeof(struct mtd_partition) + 164 alloc_size = *num_parts * sizeof(struct mtd_partition) +
165 extra_mem_size; 165 extra_mem_size;
166 parts = kmalloc(alloc_size, GFP_KERNEL); 166 parts = kzalloc(alloc_size, GFP_KERNEL);
167 if (!parts) 167 if (!parts)
168 { 168 {
169 printk(KERN_ERR ERRP "out of memory\n"); 169 printk(KERN_ERR ERRP "out of memory\n");
170 return NULL; 170 return NULL;
171 } 171 }
172 memset(parts, 0, alloc_size);
173 extra_mem = (unsigned char *)(parts + *num_parts); 172 extra_mem = (unsigned char *)(parts + *num_parts);
174 } 173 }
175 /* enter this partition (offset will be calculated later if it is zero at this point) */ 174 /* enter this partition (offset will be calculated later if it is zero at this point) */
@@ -346,7 +345,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
346 * 345 *
347 * This function needs to be visible for bootloaders. 346 * This function needs to be visible for bootloaders.
348 */ 347 */
349int mtdpart_setup(char *s) 348static int mtdpart_setup(char *s)
350{ 349{
351 cmdline = s; 350 cmdline = s;
352 return 1; 351 return 1;
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 401c6a294baa..6d917a4daa9d 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -295,10 +295,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
295 if (!devname) 295 if (!devname)
296 return NULL; 296 return NULL;
297 297
298 dev = kmalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 298 dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
299 if (!dev) 299 if (!dev)
300 return NULL; 300 return NULL;
301 memset(dev, 0, sizeof(*dev));
302 301
303 /* Get a handle on the device */ 302 /* Get a handle on the device */
304 bdev = open_bdev_excl(devname, O_RDWR, NULL); 303 bdev = open_bdev_excl(devname, O_RDWR, NULL);
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 08dfb899b272..9cff119a2024 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -131,11 +131,10 @@ static int __init ms02nv_init_one(ulong addr)
131 int ret = -ENODEV; 131 int ret = -ENODEV;
132 132
133 /* The module decodes 8MiB of address space. */ 133 /* The module decodes 8MiB of address space. */
134 mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL); 134 mod_res = kzalloc(sizeof(*mod_res), GFP_KERNEL);
135 if (!mod_res) 135 if (!mod_res)
136 return -ENOMEM; 136 return -ENOMEM;
137 137
138 memset(mod_res, 0, sizeof(*mod_res));
139 mod_res->name = ms02nv_name; 138 mod_res->name = ms02nv_name;
140 mod_res->start = addr; 139 mod_res->start = addr;
141 mod_res->end = addr + MS02NV_SLOT_SIZE - 1; 140 mod_res->end = addr + MS02NV_SLOT_SIZE - 1;
@@ -153,24 +152,21 @@ static int __init ms02nv_init_one(ulong addr)
153 } 152 }
154 153
155 ret = -ENOMEM; 154 ret = -ENOMEM;
156 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 155 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
157 if (!mtd) 156 if (!mtd)
158 goto err_out_mod_res_rel; 157 goto err_out_mod_res_rel;
159 memset(mtd, 0, sizeof(*mtd)); 158 mp = kzalloc(sizeof(*mp), GFP_KERNEL);
160 mp = kmalloc(sizeof(*mp), GFP_KERNEL);
161 if (!mp) 159 if (!mp)
162 goto err_out_mtd; 160 goto err_out_mtd;
163 memset(mp, 0, sizeof(*mp));
164 161
165 mtd->priv = mp; 162 mtd->priv = mp;
166 mp->resource.module = mod_res; 163 mp->resource.module = mod_res;
167 164
168 /* Firmware's diagnostic NVRAM area. */ 165 /* Firmware's diagnostic NVRAM area. */
169 diag_res = kmalloc(sizeof(*diag_res), GFP_KERNEL); 166 diag_res = kzalloc(sizeof(*diag_res), GFP_KERNEL);
170 if (!diag_res) 167 if (!diag_res)
171 goto err_out_mp; 168 goto err_out_mp;
172 169
173 memset(diag_res, 0, sizeof(*diag_res));
174 diag_res->name = ms02nv_res_diag_ram; 170 diag_res->name = ms02nv_res_diag_ram;
175 diag_res->start = addr; 171 diag_res->start = addr;
176 diag_res->end = addr + MS02NV_RAM - 1; 172 diag_res->end = addr + MS02NV_RAM - 1;
@@ -180,11 +176,10 @@ static int __init ms02nv_init_one(ulong addr)
180 mp->resource.diag_ram = diag_res; 176 mp->resource.diag_ram = diag_res;
181 177
182 /* User-available general-purpose NVRAM area. */ 178 /* User-available general-purpose NVRAM area. */
183 user_res = kmalloc(sizeof(*user_res), GFP_KERNEL); 179 user_res = kzalloc(sizeof(*user_res), GFP_KERNEL);
184 if (!user_res) 180 if (!user_res)
185 goto err_out_diag_res; 181 goto err_out_diag_res;
186 182
187 memset(user_res, 0, sizeof(*user_res));
188 user_res->name = ms02nv_res_user_ram; 183 user_res->name = ms02nv_res_user_ram;
189 user_res->start = addr + MS02NV_RAM; 184 user_res->start = addr + MS02NV_RAM;
190 user_res->end = addr + size - 1; 185 user_res->end = addr + size - 1;
@@ -194,11 +189,10 @@ static int __init ms02nv_init_one(ulong addr)
194 mp->resource.user_ram = user_res; 189 mp->resource.user_ram = user_res;
195 190
196 /* Control and status register. */ 191 /* Control and status register. */
197 csr_res = kmalloc(sizeof(*csr_res), GFP_KERNEL); 192 csr_res = kzalloc(sizeof(*csr_res), GFP_KERNEL);
198 if (!csr_res) 193 if (!csr_res)
199 goto err_out_user_res; 194 goto err_out_user_res;
200 195
201 memset(csr_res, 0, sizeof(*csr_res));
202 csr_res->name = ms02nv_res_csr; 196 csr_res->name = ms02nv_res_csr;
203 csr_res->start = addr + MS02NV_CSR; 197 csr_res->start = addr + MS02NV_CSR;
204 csr_res->end = addr + MS02NV_CSR + 3; 198 csr_res->end = addr + MS02NV_CSR + 3;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 910e4061dfd2..a987e917f4e0 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -480,7 +480,7 @@ add_dataflash(struct spi_device *spi, char *name,
480 device->writesize = pagesize; 480 device->writesize = pagesize;
481 device->owner = THIS_MODULE; 481 device->owner = THIS_MODULE;
482 device->type = MTD_DATAFLASH; 482 device->type = MTD_DATAFLASH;
483 device->flags = MTD_CAP_NORFLASH; 483 device->flags = MTD_WRITEABLE;
484 device->erase = dataflash_erase; 484 device->erase = dataflash_erase;
485 device->read = dataflash_read; 485 device->read = dataflash_read;
486 device->write = dataflash_write; 486 device->write = dataflash_write;
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 6c7337f9ebbb..56cc1ca7ffd5 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -126,12 +126,10 @@ static int register_device(char *name, unsigned long start, unsigned long len)
126 struct phram_mtd_list *new; 126 struct phram_mtd_list *new;
127 int ret = -ENOMEM; 127 int ret = -ENOMEM;
128 128
129 new = kmalloc(sizeof(*new), GFP_KERNEL); 129 new = kzalloc(sizeof(*new), GFP_KERNEL);
130 if (!new) 130 if (!new)
131 goto out0; 131 goto out0;
132 132
133 memset(new, 0, sizeof(*new));
134
135 ret = -EIO; 133 ret = -EIO;
136 new->mtd.priv = ioremap(start, len); 134 new->mtd.priv = ioremap(start, len);
137 if (!new->mtd.priv) { 135 if (!new->mtd.priv) {
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 542a0c009006..5f49248a4856 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -168,19 +168,16 @@ static int register_device(char *name, unsigned long start, unsigned long length
168 E("slram: Cannot allocate new MTD device.\n"); 168 E("slram: Cannot allocate new MTD device.\n");
169 return(-ENOMEM); 169 return(-ENOMEM);
170 } 170 }
171 (*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 171 (*curmtd)->mtdinfo = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
172 (*curmtd)->next = NULL; 172 (*curmtd)->next = NULL;
173 173
174 if ((*curmtd)->mtdinfo) { 174 if ((*curmtd)->mtdinfo) {
175 memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info));
176 (*curmtd)->mtdinfo->priv = 175 (*curmtd)->mtdinfo->priv =
177 kmalloc(sizeof(slram_priv_t), GFP_KERNEL); 176 kzalloc(sizeof(slram_priv_t), GFP_KERNEL);
178 177
179 if (!(*curmtd)->mtdinfo->priv) { 178 if (!(*curmtd)->mtdinfo->priv) {
180 kfree((*curmtd)->mtdinfo); 179 kfree((*curmtd)->mtdinfo);
181 (*curmtd)->mtdinfo = NULL; 180 (*curmtd)->mtdinfo = NULL;
182 } else {
183 memset((*curmtd)->mtdinfo->priv,0,sizeof(slram_priv_t));
184 } 181 }
185 } 182 }
186 183
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 8a878b34eca0..24235d4f1d23 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1033,7 +1033,7 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
1033{ 1033{
1034 partition_t *partition; 1034 partition_t *partition;
1035 1035
1036 partition = kmalloc(sizeof(partition_t), GFP_KERNEL); 1036 partition = kzalloc(sizeof(partition_t), GFP_KERNEL);
1037 1037
1038 if (!partition) { 1038 if (!partition) {
1039 printk(KERN_WARNING "No memory to scan for FTL on %s\n", 1039 printk(KERN_WARNING "No memory to scan for FTL on %s\n",
@@ -1041,8 +1041,6 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
1041 return; 1041 return;
1042 } 1042 }
1043 1043
1044 memset(partition, 0, sizeof(partition_t));
1045
1046 partition->mbd.mtd = mtd; 1044 partition->mbd.mtd = mtd;
1047 1045
1048 if ((scan_header(partition) == 0) && 1046 if ((scan_header(partition) == 0) &&
@@ -1054,7 +1052,7 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
1054 le32_to_cpu(partition->header.FormattedSize) >> 10); 1052 le32_to_cpu(partition->header.FormattedSize) >> 10);
1055#endif 1053#endif
1056 partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9; 1054 partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9;
1057 partition->mbd.blksize = SECTOR_SIZE; 1055
1058 partition->mbd.tr = tr; 1056 partition->mbd.tr = tr;
1059 partition->mbd.devnum = -1; 1057 partition->mbd.devnum = -1;
1060 if (!add_mtd_blktrans_dev((void *)partition)) 1058 if (!add_mtd_blktrans_dev((void *)partition))
@@ -1076,6 +1074,7 @@ struct mtd_blktrans_ops ftl_tr = {
1076 .name = "ftl", 1074 .name = "ftl",
1077 .major = FTL_MAJOR, 1075 .major = FTL_MAJOR,
1078 .part_bits = PART_BITS, 1076 .part_bits = PART_BITS,
1077 .blksize = SECTOR_SIZE,
1079 .readsect = ftl_readsect, 1078 .readsect = ftl_readsect,
1080 .writesect = ftl_writesect, 1079 .writesect = ftl_writesect,
1081 .getgeo = ftl_getgeo, 1080 .getgeo = ftl_getgeo,
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 4116535805f1..b0e396504e67 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -67,17 +67,16 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
67 67
68 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name); 68 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
69 69
70 inftl = kmalloc(sizeof(*inftl), GFP_KERNEL); 70 inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
71 71
72 if (!inftl) { 72 if (!inftl) {
73 printk(KERN_WARNING "INFTL: Out of memory for data structures\n"); 73 printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
74 return; 74 return;
75 } 75 }
76 memset(inftl, 0, sizeof(*inftl));
77 76
78 inftl->mbd.mtd = mtd; 77 inftl->mbd.mtd = mtd;
79 inftl->mbd.devnum = -1; 78 inftl->mbd.devnum = -1;
80 inftl->mbd.blksize = 512; 79
81 inftl->mbd.tr = tr; 80 inftl->mbd.tr = tr;
82 81
83 if (INFTL_mount(inftl) < 0) { 82 if (INFTL_mount(inftl) < 0) {
@@ -163,10 +162,9 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
163 ops.ooblen = len; 162 ops.ooblen = len;
164 ops.oobbuf = buf; 163 ops.oobbuf = buf;
165 ops.datbuf = NULL; 164 ops.datbuf = NULL;
166 ops.len = len;
167 165
168 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 166 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
169 *retlen = ops.retlen; 167 *retlen = ops.oobretlen;
170 return res; 168 return res;
171} 169}
172 170
@@ -184,10 +182,9 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
184 ops.ooblen = len; 182 ops.ooblen = len;
185 ops.oobbuf = buf; 183 ops.oobbuf = buf;
186 ops.datbuf = NULL; 184 ops.datbuf = NULL;
187 ops.len = len;
188 185
189 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 186 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
190 *retlen = ops.retlen; 187 *retlen = ops.oobretlen;
191 return res; 188 return res;
192} 189}
193 190
@@ -945,6 +942,7 @@ static struct mtd_blktrans_ops inftl_tr = {
945 .name = "inftl", 942 .name = "inftl",
946 .major = INFTL_MAJOR, 943 .major = INFTL_MAJOR,
947 .part_bits = INFTL_PARTN_BITS, 944 .part_bits = INFTL_PARTN_BITS,
945 .blksize = 512,
948 .getgeo = inftl_getgeo, 946 .getgeo = inftl_getgeo,
949 .readsect = inftl_readblock, 947 .readsect = inftl_readblock,
950 .writesect = inftl_writeblock, 948 .writesect = inftl_writeblock,
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index d132ed571f13..f457315579db 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -60,6 +60,15 @@ config MTD_PHYSMAP_BANKWIDTH
60 Ignore this option if you use run-time physmap configuration 60 Ignore this option if you use run-time physmap configuration
61 (i.e., run-time calling physmap_configure()). 61 (i.e., run-time calling physmap_configure()).
62 62
63config MTD_PHYSMAP_OF
64 tristate "Flash device in physical memory map based on OF descirption"
65 depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM)
66 help
67 This provides a 'mapping' driver which allows the NOR Flash and
68 ROM driver code to communicate with chips which are mapped
69 physically into the CPU's memory. The mapping description here is
70 taken from OF device tree.
71
63config MTD_SUN_UFLASH 72config MTD_SUN_UFLASH
64 tristate "Sun Microsystems userflash support" 73 tristate "Sun Microsystems userflash support"
65 depends on SPARC && MTD_CFI 74 depends on SPARC && MTD_CFI
@@ -184,6 +193,24 @@ config MTD_ICHXROM
184 193
185 BE VERY CAREFUL. 194 BE VERY CAREFUL.
186 195
196config MTD_ESB2ROM
197 tristate "BIOS flash chip on Intel ESB Controller Hub 2"
198 depends on X86 && MTD_JEDECPROBE && PCI
199 help
200 Support for treating the BIOS flash chip on ESB2 motherboards
201 as an MTD device - with this you can reprogram your BIOS.
202
203 BE VERY CAREFUL.
204
205config MTD_CK804XROM
206 tristate "BIOS flash chip on Nvidia CK804"
207 depends on X86 && MTD_JEDECPROBE
208 help
209 Support for treating the BIOS flash chip on nvidia motherboards
210 as an MTD device - with this you can reprogram your BIOS.
211
212 BE VERY CAREFUL.
213
187config MTD_SCB2_FLASH 214config MTD_SCB2_FLASH
188 tristate "BIOS flash chip on Intel SCB2 boards" 215 tristate "BIOS flash chip on Intel SCB2 boards"
189 depends on X86 && MTD_JEDECPROBE 216 depends on X86 && MTD_JEDECPROBE
@@ -355,50 +382,6 @@ config MTD_TQM834x
355 TQ Components TQM834x boards. If you have one of these boards 382 TQ Components TQM834x boards. If you have one of these boards
356 and would like to use the flash chips on it, say 'Y'. 383 and would like to use the flash chips on it, say 'Y'.
357 384
358config MTD_CSTM_MIPS_IXX
359 tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board"
360 depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS
361 help
362 This provides a mapping driver for the Integrated Technology
363 Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR
364 Reference Board. It provides the necessary addressing, length,
365 buswidth, vpp code and addition setup of the flash device for
366 these boards. In addition, this mapping driver can be used for
367 other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/
368 LEN/BUSWIDTH parameters. This mapping will provide one mtd device
369 using one partition. The start address can be offset from the
370 beginning of flash and the len can be less than the total flash
371 device size to allow a window into the flash. Both CFI and JEDEC
372 probes are called.
373
374config MTD_CSTM_MIPS_IXX_START
375 hex "Physical start address of flash mapping"
376 depends on MTD_CSTM_MIPS_IXX
377 default "0x8000000"
378 help
379 This is the physical memory location that the MTD driver will
380 use for the flash chips on your particular target board.
381 Refer to the memory map which should hopefully be in the
382 documentation for your board.
383
384config MTD_CSTM_MIPS_IXX_LEN
385 hex "Physical length of flash mapping"
386 depends on MTD_CSTM_MIPS_IXX
387 default "0x4000000"
388 help
389 This is the total length that the MTD driver will use for the
390 flash chips on your particular board. Refer to the memory
391 map which should hopefully be in the documentation for your
392 board.
393
394config MTD_CSTM_MIPS_IXX_BUSWIDTH
395 int "Bus width in octets"
396 depends on MTD_CSTM_MIPS_IXX
397 default "2"
398 help
399 This is the total bus width of the mapping of the flash chips
400 on your particular board.
401
402config MTD_OCELOT 385config MTD_OCELOT
403 tristate "Momenco Ocelot boot flash device" 386 tristate "Momenco Ocelot boot flash device"
404 depends on MIPS && MOMENCO_OCELOT 387 depends on MIPS && MOMENCO_OCELOT
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 191c1928bbec..071d0bf922b6 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -12,12 +12,13 @@ obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
12obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o 12obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
13obj-$(CONFIG_MTD_BAST) += bast-flash.o 13obj-$(CONFIG_MTD_BAST) += bast-flash.o
14obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o 14obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
15obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
16obj-$(CONFIG_MTD_DC21285) += dc21285.o 15obj-$(CONFIG_MTD_DC21285) += dc21285.o
17obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o 16obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
18obj-$(CONFIG_MTD_L440GX) += l440gx.o 17obj-$(CONFIG_MTD_L440GX) += l440gx.o
19obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o 18obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
19obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o
20obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o 20obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
21obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
21obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o 22obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
22obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o 23obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
23obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o 24obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_MTD_MBX860) += mbx860.o
25obj-$(CONFIG_MTD_CEIVA) += ceiva.o 26obj-$(CONFIG_MTD_CEIVA) += ceiva.o
26obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o 27obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
27obj-$(CONFIG_MTD_PHYSMAP) += physmap.o 28obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
29obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
28obj-$(CONFIG_MTD_PNC2000) += pnc2000.o 30obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
29obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o 31obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
30obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o 32obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 797caffb20b1..78b671172bb2 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -7,6 +7,7 @@
7 7
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/version.h>
10#include <linux/kernel.h> 11#include <linux/kernel.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <asm/io.h> 13#include <asm/io.h>
@@ -44,6 +45,23 @@ struct amd76xrom_map_info {
44 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; 45 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
45}; 46};
46 47
48/* The 2 bits controlling the window size are often set to allow reading
49 * the BIOS, but too small to allow writing, since the lock registers are
50 * 4MiB lower in the address space than the data.
51 *
52 * This is intended to prevent flashing the bios, perhaps accidentally.
53 *
54 * This parameter allows the normal driver to over-ride the BIOS settings.
55 *
56 * The bits are 6 and 7. If both bits are set, it is a 5MiB window.
57 * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a
58 * 64KiB window.
59 *
60 */
61static uint win_size_bits;
62module_param(win_size_bits, uint, 0);
63MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x43 byte, normally set by BIOS.");
64
47static struct amd76xrom_window amd76xrom_window = { 65static struct amd76xrom_window amd76xrom_window = {
48 .maps = LIST_HEAD_INIT(amd76xrom_window.maps), 66 .maps = LIST_HEAD_INIT(amd76xrom_window.maps),
49}; 67};
@@ -95,6 +113,16 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
95 /* Remember the pci dev I find the window in - already have a ref */ 113 /* Remember the pci dev I find the window in - already have a ref */
96 window->pdev = pdev; 114 window->pdev = pdev;
97 115
116 /* Enable the selected rom window. This is often incorrectly
117 * set up by the BIOS, and the 4MiB offset for the lock registers
118 * requires the full 5MiB of window space.
119 *
120 * This 'write, then read' approach leaves the bits for
121 * other uses of the hardware info.
122 */
123 pci_read_config_byte(pdev, 0x43, &byte);
124 pci_write_config_byte(pdev, 0x43, byte | win_size_bits );
125
98 /* Assume the rom window is properly setup, and find it's size */ 126 /* Assume the rom window is properly setup, and find it's size */
99 pci_read_config_byte(pdev, 0x43, &byte); 127 pci_read_config_byte(pdev, 0x43, &byte);
100 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) { 128 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
@@ -129,12 +157,6 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
129 (unsigned long long)window->rsrc.end); 157 (unsigned long long)window->rsrc.end);
130 } 158 }
131 159
132#if 0
133
134 /* Enable the selected rom window */
135 pci_read_config_byte(pdev, 0x43, &byte);
136 pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
137#endif
138 160
139 /* Enable writes through the rom window */ 161 /* Enable writes through the rom window */
140 pci_read_config_byte(pdev, 0x40, &byte); 162 pci_read_config_byte(pdev, 0x40, &byte);
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
index e074bb6787d2..fc3b2672d1e2 100644
--- a/drivers/mtd/maps/bast-flash.c
+++ b/drivers/mtd/maps/bast-flash.c
@@ -131,7 +131,7 @@ static int bast_flash_probe(struct platform_device *pdev)
131 131
132 info->map.phys = res->start; 132 info->map.phys = res->start;
133 info->map.size = res->end - res->start + 1; 133 info->map.size = res->end - res->start + 1;
134 info->map.name = pdev->dev.bus_id; 134 info->map.name = pdev->dev.bus_id;
135 info->map.bankwidth = 2; 135 info->map.bankwidth = 2;
136 136
137 if (info->map.size > AREA_MAXSIZE) 137 if (info->map.size > AREA_MAXSIZE)
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index 0402c21e291d..629e6e2641a8 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -122,10 +122,9 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info
122 /* 122 /*
123 * Allocate the map_info structs in one go. 123 * Allocate the map_info structs in one go.
124 */ 124 */
125 maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); 125 maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
126 if (!maps) 126 if (!maps)
127 return -ENOMEM; 127 return -ENOMEM;
128 memset(maps, 0, sizeof(struct map_info) * nr);
129 /* 128 /*
130 * Claim and then map the memory regions. 129 * Claim and then map the memory regions.
131 */ 130 */
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
new file mode 100644
index 000000000000..238d42e88ec5
--- /dev/null
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -0,0 +1,356 @@
1/*
2 * ck804xrom.c
3 *
4 * Normal mappings of chips in physical memory
5 *
6 * Dave Olsen <dolsen@lnxi.com>
7 * Ryan Jackson <rjackson@lnxi.com>
8 */
9
10#include <linux/module.h>
11#include <linux/types.h>
12#include <linux/version.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/cfi.h>
19#include <linux/mtd/flashchip.h>
20#include <linux/pci.h>
21#include <linux/pci_ids.h>
22#include <linux/list.h>
23
24
25#define MOD_NAME KBUILD_BASENAME
26
27#define ADDRESS_NAME_LEN 18
28
29#define ROM_PROBE_STEP_SIZE (64*1024)
30
31struct ck804xrom_window {
32 void __iomem *virt;
33 unsigned long phys;
34 unsigned long size;
35 struct list_head maps;
36 struct resource rsrc;
37 struct pci_dev *pdev;
38};
39
40struct ck804xrom_map_info {
41 struct list_head list;
42 struct map_info map;
43 struct mtd_info *mtd;
44 struct resource rsrc;
45 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
46};
47
48
49/* The 2 bits controlling the window size are often set to allow reading
50 * the BIOS, but too small to allow writing, since the lock registers are
51 * 4MiB lower in the address space than the data.
52 *
53 * This is intended to prevent flashing the bios, perhaps accidentally.
54 *
55 * This parameter allows the normal driver to override the BIOS settings.
56 *
57 * The bits are 6 and 7. If both bits are set, it is a 5MiB window.
58 * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a
59 * 64KiB window.
60 *
61 */
62static uint win_size_bits = 0;
63module_param(win_size_bits, uint, 0);
64MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS.");
65
66static struct ck804xrom_window ck804xrom_window = {
67 .maps = LIST_HEAD_INIT(ck804xrom_window.maps),
68};
69
70static void ck804xrom_cleanup(struct ck804xrom_window *window)
71{
72 struct ck804xrom_map_info *map, *scratch;
73 u8 byte;
74
75 if (window->pdev) {
76 /* Disable writes through the rom window */
77 pci_read_config_byte(window->pdev, 0x6d, &byte);
78 pci_write_config_byte(window->pdev, 0x6d, byte & ~1);
79 }
80
81 /* Free all of the mtd devices */
82 list_for_each_entry_safe(map, scratch, &window->maps, list) {
83 if (map->rsrc.parent)
84 release_resource(&map->rsrc);
85
86 del_mtd_device(map->mtd);
87 map_destroy(map->mtd);
88 list_del(&map->list);
89 kfree(map);
90 }
91 if (window->rsrc.parent)
92 release_resource(&window->rsrc);
93
94 if (window->virt) {
95 iounmap(window->virt);
96 window->virt = NULL;
97 window->phys = 0;
98 window->size = 0;
99 }
100 pci_dev_put(window->pdev);
101}
102
103
104static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
105 const struct pci_device_id *ent)
106{
107 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
108 u8 byte;
109 struct ck804xrom_window *window = &ck804xrom_window;
110 struct ck804xrom_map_info *map = NULL;
111 unsigned long map_top;
112
113 /* Remember the pci dev I find the window in */
114 window->pdev = pci_dev_get(pdev);
115
116 /* Enable the selected rom window. This is often incorrectly
117 * set up by the BIOS, and the 4MiB offset for the lock registers
118 * requires the full 5MiB of window space.
119 *
120 * This 'write, then read' approach leaves the bits for
121 * other uses of the hardware info.
122 */
123 pci_read_config_byte(pdev, 0x88, &byte);
124 pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
125
126
127 /* Assume the rom window is properly setup, and find it's size */
128 pci_read_config_byte(pdev, 0x88, &byte);
129
130 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
131 window->phys = 0xffb00000; /* 5MiB */
132 else if ((byte & (1<<7)) == (1<<7))
133 window->phys = 0xffc00000; /* 4MiB */
134 else
135 window->phys = 0xffff0000; /* 64KiB */
136
137 window->size = 0xffffffffUL - window->phys + 1UL;
138
139 /*
140 * Try to reserve the window mem region. If this fails then
141 * it is likely due to a fragment of the window being
142 * "reserved" by the BIOS. In the case that the
143 * request_mem_region() fails then once the rom size is
144 * discovered we will try to reserve the unreserved fragment.
145 */
146 window->rsrc.name = MOD_NAME;
147 window->rsrc.start = window->phys;
148 window->rsrc.end = window->phys + window->size - 1;
149 window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
150 if (request_resource(&iomem_resource, &window->rsrc)) {
151 window->rsrc.parent = NULL;
152 printk(KERN_ERR MOD_NAME
153 " %s(): Unable to register resource"
154 " 0x%.016llx-0x%.016llx - kernel bug?\n",
155 __func__,
156 (unsigned long long)window->rsrc.start,
157 (unsigned long long)window->rsrc.end);
158 }
159
160
161 /* Enable writes through the rom window */
162 pci_read_config_byte(pdev, 0x6d, &byte);
163 pci_write_config_byte(pdev, 0x6d, byte | 1);
164
165 /* FIXME handle registers 0x80 - 0x8C the bios region locks */
166
167 /* For write accesses caches are useless */
168 window->virt = ioremap_nocache(window->phys, window->size);
169 if (!window->virt) {
170 printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
171 window->phys, window->size);
172 goto out;
173 }
174
175 /* Get the first address to look for a rom chip at */
176 map_top = window->phys;
177#if 1
178 /* The probe sequence run over the firmware hub lock
179 * registers sets them to 0x7 (no access).
180 * Probe at most the last 4MiB of the address space.
181 */
182 if (map_top < 0xffc00000)
183 map_top = 0xffc00000;
184#endif
185 /* Loop through and look for rom chips. Since we don't know the
186 * starting address for each chip, probe every ROM_PROBE_STEP_SIZE
187 * bytes from the starting address of the window.
188 */
189 while((map_top - 1) < 0xffffffffUL) {
190 struct cfi_private *cfi;
191 unsigned long offset;
192 int i;
193
194 if (!map)
195 map = kmalloc(sizeof(*map), GFP_KERNEL);
196
197 if (!map) {
198 printk(KERN_ERR MOD_NAME ": kmalloc failed");
199 goto out;
200 }
201 memset(map, 0, sizeof(*map));
202 INIT_LIST_HEAD(&map->list);
203 map->map.name = map->map_name;
204 map->map.phys = map_top;
205 offset = map_top - window->phys;
206 map->map.virt = (void __iomem *)
207 (((unsigned long)(window->virt)) + offset);
208 map->map.size = 0xffffffffUL - map_top + 1UL;
209 /* Set the name of the map to the address I am trying */
210 sprintf(map->map_name, "%s @%08lx",
211 MOD_NAME, map->map.phys);
212
213 /* There is no generic VPP support */
214 for(map->map.bankwidth = 32; map->map.bankwidth;
215 map->map.bankwidth >>= 1)
216 {
217 char **probe_type;
218 /* Skip bankwidths that are not supported */
219 if (!map_bankwidth_supported(map->map.bankwidth))
220 continue;
221
222 /* Setup the map methods */
223 simple_map_init(&map->map);
224
225 /* Try all of the probe methods */
226 probe_type = rom_probe_types;
227 for(; *probe_type; probe_type++) {
228 map->mtd = do_map_probe(*probe_type, &map->map);
229 if (map->mtd)
230 goto found;
231 }
232 }
233 map_top += ROM_PROBE_STEP_SIZE;
234 continue;
235 found:
236 /* Trim the size if we are larger than the map */
237 if (map->mtd->size > map->map.size) {
238 printk(KERN_WARNING MOD_NAME
239 " rom(%u) larger than window(%lu). fixing...\n",
240 map->mtd->size, map->map.size);
241 map->mtd->size = map->map.size;
242 }
243 if (window->rsrc.parent) {
244 /*
245 * Registering the MTD device in iomem may not be possible
246 * if there is a BIOS "reserved" and BUSY range. If this
247 * fails then continue anyway.
248 */
249 map->rsrc.name = map->map_name;
250 map->rsrc.start = map->map.phys;
251 map->rsrc.end = map->map.phys + map->mtd->size - 1;
252 map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
253 if (request_resource(&window->rsrc, &map->rsrc)) {
254 printk(KERN_ERR MOD_NAME
255 ": cannot reserve MTD resource\n");
256 map->rsrc.parent = NULL;
257 }
258 }
259
260 /* Make the whole region visible in the map */
261 map->map.virt = window->virt;
262 map->map.phys = window->phys;
263 cfi = map->map.fldrv_priv;
264 for(i = 0; i < cfi->numchips; i++)
265 cfi->chips[i].start += offset;
266
267 /* Now that the mtd devices is complete claim and export it */
268 map->mtd->owner = THIS_MODULE;
269 if (add_mtd_device(map->mtd)) {
270 map_destroy(map->mtd);
271 map->mtd = NULL;
272 goto out;
273 }
274
275
276 /* Calculate the new value of map_top */
277 map_top += map->mtd->size;
278
279 /* File away the map structure */
280 list_add(&map->list, &window->maps);
281 map = NULL;
282 }
283
284 out:
285 /* Free any left over map structures */
286 if (map)
287 kfree(map);
288
289 /* See if I have any map structures */
290 if (list_empty(&window->maps)) {
291 ck804xrom_cleanup(window);
292 return -ENODEV;
293 }
294 return 0;
295}
296
297
298static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
299{
300 struct ck804xrom_window *window = &ck804xrom_window;
301
302 ck804xrom_cleanup(window);
303}
304
305static struct pci_device_id ck804xrom_pci_tbl[] = {
306 { PCI_VENDOR_ID_NVIDIA, 0x0051,
307 PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */
308 { 0, }
309};
310
311MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
312
313#if 0
314static struct pci_driver ck804xrom_driver = {
315 .name = MOD_NAME,
316 .id_table = ck804xrom_pci_tbl,
317 .probe = ck804xrom_init_one,
318 .remove = ck804xrom_remove_one,
319};
320#endif
321
322static int __init init_ck804xrom(void)
323{
324 struct pci_dev *pdev;
325 struct pci_device_id *id;
326 int retVal;
327 pdev = NULL;
328
329 for(id = ck804xrom_pci_tbl; id->vendor; id++) {
330 pdev = pci_find_device(id->vendor, id->device, NULL);
331 if (pdev)
332 break;
333 }
334 if (pdev) {
335 retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]);
336 pci_dev_put(pdev);
337 return retVal;
338 }
339 return -ENXIO;
340#if 0
341 return pci_module_init(&ck804xrom_driver);
342#endif
343}
344
345static void __exit cleanup_ck804xrom(void)
346{
347 ck804xrom_remove_one(ck804xrom_window.pdev);
348}
349
350module_init(init_ck804xrom);
351module_exit(cleanup_ck804xrom);
352
353MODULE_LICENSE("GPL");
354MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>, Dave Olsen <dolsen@lnxi.com>");
355MODULE_DESCRIPTION("MTD map driver for BIOS chips on the Nvidia ck804 southbridge");
356
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c
deleted file mode 100644
index df2c38ef105a..000000000000
--- a/drivers/mtd/maps/cstm_mips_ixx.c
+++ /dev/null
@@ -1,283 +0,0 @@
1/*
2 * $Id: cstm_mips_ixx.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
3 *
4 * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
5 * Config with both CFI and JEDEC device support.
6 *
7 * Basically physmap.c with the addition of partitions and
8 * an array of mapping info to accomodate more than one flash type per board.
9 *
10 * Copyright 2000 MontaVista Software Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 675 Mass Ave, Cambridge, MA 02139, USA.
31 */
32
33#include <linux/module.h>
34#include <linux/types.h>
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <asm/io.h>
38#include <linux/mtd/mtd.h>
39#include <linux/mtd/map.h>
40#include <linux/mtd/partitions.h>
41#include <linux/delay.h>
42
43#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
44#define CC_GCR 0xB4013818
45#define CC_GPBCR 0xB401380A
46#define CC_GPBDR 0xB4013808
47#define CC_M68K_DEVICE 1
48#define CC_M68K_FUNCTION 6
49#define CC_CONFADDR 0xB8004000
50#define CC_CONFDATA 0xB8004004
51#define CC_FC_FCR 0xB8002004
52#define CC_FC_DCR 0xB8002008
53#define CC_GPACR 0xB4013802
54#define CC_GPAICR 0xB4013804
55#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
56
57#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
58void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp)
59{
60 static DEFINE_SPINLOCK(vpp_lock);
61 static int vpp_count = 0;
62 unsigned long flags;
63
64 spin_lock_irqsave(&vpp_lock, flags);
65
66 if (vpp) {
67 if (!vpp_count++) {
68 __u16 data;
69 __u8 data1;
70 static u8 first = 1;
71
72 // Set GPIO port B pin3 to high
73 data = *(__u16 *)(CC_GPBCR);
74 data = (data & 0xff0f) | 0x0040;
75 *(__u16 *)CC_GPBCR = data;
76 *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08;
77 if (first) {
78 first = 0;
79 /* need to have this delay for first
80 enabling vpp after powerup */
81 udelay(40);
82 }
83 }
84 } else {
85 if (!--vpp_count) {
86 __u16 data;
87
88 // Set GPIO port B pin3 to high
89 data = *(__u16 *)(CC_GPBCR);
90 data = (data & 0xff3f) | 0x0040;
91 *(__u16 *)CC_GPBCR = data;
92 *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7;
93 }
94 }
95 spin_unlock_irqrestore(&vpp_lock, flags);
96}
97#endif
98
99/* board and partition description */
100
101#define MAX_PHYSMAP_PARTITIONS 8
102struct cstm_mips_ixx_info {
103 char *name;
104 unsigned long window_addr;
105 unsigned long window_size;
106 int bankwidth;
107 int num_partitions;
108};
109
110#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
111#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
112const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
113{
114 { // 28F128J3A in 2x16 configuration
115 "big flash", // name
116 0x08000000, // window_addr
117 0x02000000, // window_size
118 4, // bankwidth
119 1, // num_partitions
120 }
121
122};
123static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
124{ // 28F128J3A in 2x16 configuration
125 {
126 .name = "main partition ",
127 .size = 0x02000000, // 128 x 2 x 128k byte sectors
128 .offset = 0,
129 },
130},
131};
132#else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
133#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
134const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
135{
136 {
137 "MTD flash", // name
138 CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr
139 CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size
140 CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth
141 1, // num_partitions
142 },
143
144};
145static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
146{
147 {
148 .name = "main partition",
149 .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN,
150 .offset = 0,
151 },
152},
153};
154#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
155
156struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER];
157
158int __init init_cstm_mips_ixx(void)
159{
160 int i;
161 int jedec;
162 struct mtd_info *mymtd;
163 struct mtd_partition *parts;
164
165 /* Initialize mapping */
166 for (i=0;i<PHYSMAP_NUMBER;i++) {
167 printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n",
168 cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr);
169
170
171 cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
172 cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
173 if (!cstm_mips_ixx_map[i].virt) {
174 int j = 0;
175 printk(KERN_WARNING "Failed to ioremap\n");
176 for (j = 0; j < i; j++) {
177 if (cstm_mips_ixx_map[j].virt) {
178 iounmap(cstm_mips_ixx_map[j].virt);
179 cstm_mips_ixx_map[j].virt = NULL;
180 }
181 }
182 return -EIO;
183 }
184 cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
185 cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size;
186 cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth;
187#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
188 cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp;
189#endif
190 simple_map_init(&cstm_mips_ixx_map[i]);
191 //printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt));
192 }
193
194#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
195 setup_ITE_IVR_flash();
196#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
197
198 for (i=0;i<PHYSMAP_NUMBER;i++) {
199 parts = &cstm_mips_ixx_partitions[i][0];
200 jedec = 0;
201 mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]);
202 //printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd);
203 if (!mymtd) {
204 jedec = 1;
205 mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]);
206 printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd);
207 }
208 if (mymtd) {
209 mymtd->owner = THIS_MODULE;
210
211 cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd;
212 add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions);
213 }
214 else {
215 for (i = 0; i < PHYSMAP_NUMBER; i++) {
216 if (cstm_mips_ixx_map[i].virt) {
217 iounmap(cstm_mips_ixx_map[i].virt);
218 cstm_mips_ixx_map[i].virt = NULL;
219 }
220 }
221 return -ENXIO;
222 }
223 }
224 return 0;
225}
226
227static void __exit cleanup_cstm_mips_ixx(void)
228{
229 int i;
230 struct mtd_info *mymtd;
231
232 for (i=0;i<PHYSMAP_NUMBER;i++) {
233 mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2;
234 if (mymtd) {
235 del_mtd_partitions(mymtd);
236 map_destroy(mymtd);
237 }
238 if (cstm_mips_ixx_map[i].virt) {
239 iounmap((void *)cstm_mips_ixx_map[i].virt);
240 cstm_mips_ixx_map[i].virt = 0;
241 }
242 }
243}
244#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
245void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data)
246{
247 __u32 offset;
248
249 offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ;
250
251 *(__u32 *)CC_CONFADDR = offset;
252 *(__u32 *)CC_CONFDATA = data;
253}
254void setup_ITE_IVR_flash()
255{
256 __u32 size, base;
257
258 size = 0x0e000000; // 32MiB
259 base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit
260
261 /* need to set ITE flash to 32 bits instead of default 8 */
262#ifdef CONFIG_MIPS_IVR
263 *(__u32 *)CC_FC_FCR = 0x55;
264 *(__u32 *)CC_GPACR = 0xfffc;
265#else
266 *(__u32 *)CC_FC_FCR = 0x77;
267#endif
268 /* turn bursting off */
269 *(__u32 *)CC_FC_DCR = 0x0;
270
271 /* setup for one chip 4 byte PCI access */
272 PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base);
273 PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02);
274}
275#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
276
277module_init(init_cstm_mips_ixx);
278module_exit(cleanup_cstm_mips_ixx);
279
280
281MODULE_LICENSE("GPL");
282MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
283MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards");
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
new file mode 100644
index 000000000000..a9d808a617c9
--- /dev/null
+++ b/drivers/mtd/maps/esb2rom.c
@@ -0,0 +1,450 @@
1/*
2 * esb2rom.c
3 *
4 * Normal mappings of flash chips in physical memory
5 * through the Intel ESB2 Southbridge.
6 *
7 * This was derived from ichxrom.c in May 2006 by
8 * Lew Glendenning <lglendenning@lnxi.com>
9 *
10 * Eric Biederman, of course, was a major help in this effort.
11 */
12
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/version.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <asm/io.h>
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/cfi.h>
22#include <linux/mtd/flashchip.h>
23#include <linux/pci.h>
24#include <linux/pci_ids.h>
25#include <linux/list.h>
26
27#define MOD_NAME KBUILD_BASENAME
28
29#define ADDRESS_NAME_LEN 18
30
31#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
32
33#define BIOS_CNTL 0xDC
34#define BIOS_LOCK_ENABLE 0x02
35#define BIOS_WRITE_ENABLE 0x01
36
37/* This became a 16-bit register, and EN2 has disappeared */
38#define FWH_DEC_EN1 0xD8
39#define FWH_F8_EN 0x8000
40#define FWH_F0_EN 0x4000
41#define FWH_E8_EN 0x2000
42#define FWH_E0_EN 0x1000
43#define FWH_D8_EN 0x0800
44#define FWH_D0_EN 0x0400
45#define FWH_C8_EN 0x0200
46#define FWH_C0_EN 0x0100
47#define FWH_LEGACY_F_EN 0x0080
48#define FWH_LEGACY_E_EN 0x0040
49/* reserved 0x0020 and 0x0010 */
50#define FWH_70_EN 0x0008
51#define FWH_60_EN 0x0004
52#define FWH_50_EN 0x0002
53#define FWH_40_EN 0x0001
54
55/* these are 32-bit values */
56#define FWH_SEL1 0xD0
57#define FWH_SEL2 0xD4
58
59#define FWH_8MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
60 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
61 FWH_70_EN | FWH_60_EN | FWH_50_EN | FWH_40_EN)
62
63#define FWH_7MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
64 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
65 FWH_70_EN | FWH_60_EN | FWH_50_EN)
66
67#define FWH_6MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
68 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
69 FWH_70_EN | FWH_60_EN)
70
71#define FWH_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
72 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
73 FWH_70_EN)
74
75#define FWH_4MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
76 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN)
77
78#define FWH_3_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
79 FWH_D8_EN | FWH_D0_EN | FWH_C8_EN)
80
81#define FWH_3MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
82 FWH_D8_EN | FWH_D0_EN)
83
84#define FWH_2_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
85 FWH_D8_EN)
86
87#define FWH_2MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN)
88
89#define FWH_1_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN)
90
91#define FWH_1MiB (FWH_F8_EN | FWH_F0_EN)
92
93#define FWH_0_5MiB (FWH_F8_EN)
94
95
96struct esb2rom_window {
97 void __iomem* virt;
98 unsigned long phys;
99 unsigned long size;
100 struct list_head maps;
101 struct resource rsrc;
102 struct pci_dev *pdev;
103};
104
105struct esb2rom_map_info {
106 struct list_head list;
107 struct map_info map;
108 struct mtd_info *mtd;
109 struct resource rsrc;
110 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
111};
112
113static struct esb2rom_window esb2rom_window = {
114 .maps = LIST_HEAD_INIT(esb2rom_window.maps),
115};
116
117static void esb2rom_cleanup(struct esb2rom_window *window)
118{
119 struct esb2rom_map_info *map, *scratch;
120 u8 byte;
121
122 /* Disable writes through the rom window */
123 pci_read_config_byte(window->pdev, BIOS_CNTL, &byte);
124 pci_write_config_byte(window->pdev, BIOS_CNTL,
125 byte & ~BIOS_WRITE_ENABLE);
126
127 /* Free all of the mtd devices */
128 list_for_each_entry_safe(map, scratch, &window->maps, list) {
129 if (map->rsrc.parent)
130 release_resource(&map->rsrc);
131 del_mtd_device(map->mtd);
132 map_destroy(map->mtd);
133 list_del(&map->list);
134 kfree(map);
135 }
136 if (window->rsrc.parent)
137 release_resource(&window->rsrc);
138 if (window->virt) {
139 iounmap(window->virt);
140 window->virt = NULL;
141 window->phys = 0;
142 window->size = 0;
143 }
144 pci_dev_put(window->pdev);
145}
146
147static int __devinit esb2rom_init_one(struct pci_dev *pdev,
148 const struct pci_device_id *ent)
149{
150 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
151 struct esb2rom_window *window = &esb2rom_window;
152 struct esb2rom_map_info *map = NULL;
153 unsigned long map_top;
154 u8 byte;
155 u16 word;
156
157 /* For now I just handle the ecb2 and I assume there
158 * are not a lot of resources up at the top of the address
159 * space. It is possible to handle other devices in the
160 * top 16MiB but it is very painful. Also since
161 * you can only really attach a FWH to an ICHX there
162 * a number of simplifications you can make.
163 *
164 * Also you can page firmware hubs if an 8MiB window isn't enough
165 * but don't currently handle that case either.
166 */
167 window->pdev = pci_dev_get(pdev);
168
169 /* RLG: experiment 2. Force the window registers to the widest values */
170
171/*
172 pci_read_config_word(pdev, FWH_DEC_EN1, &word);
173 printk(KERN_DEBUG "Original FWH_DEC_EN1 : %x\n", word);
174 pci_write_config_byte(pdev, FWH_DEC_EN1, 0xff);
175 pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
176 printk(KERN_DEBUG "New FWH_DEC_EN1 : %x\n", byte);
177
178 pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
179 printk(KERN_DEBUG "Original FWH_DEC_EN2 : %x\n", byte);
180 pci_write_config_byte(pdev, FWH_DEC_EN2, 0x0f);
181 pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
182 printk(KERN_DEBUG "New FWH_DEC_EN2 : %x\n", byte);
183*/
184
185 /* Find a region continuous to the end of the ROM window */
186 window->phys = 0;
187 pci_read_config_word(pdev, FWH_DEC_EN1, &word);
188 printk(KERN_DEBUG "pci_read_config_byte : %x\n", word);
189
190 if ((word & FWH_8MiB) == FWH_8MiB)
191 window->phys = 0xff400000;
192 else if ((word & FWH_7MiB) == FWH_7MiB)
193 window->phys = 0xff500000;
194 else if ((word & FWH_6MiB) == FWH_6MiB)
195 window->phys = 0xff600000;
196 else if ((word & FWH_5MiB) == FWH_5MiB)
197 window->phys = 0xFF700000;
198 else if ((word & FWH_4MiB) == FWH_4MiB)
199 window->phys = 0xffc00000;
200 else if ((word & FWH_3_5MiB) == FWH_3_5MiB)
201 window->phys = 0xffc80000;
202 else if ((word & FWH_3MiB) == FWH_3MiB)
203 window->phys = 0xffd00000;
204 else if ((word & FWH_2_5MiB) == FWH_2_5MiB)
205 window->phys = 0xffd80000;
206 else if ((word & FWH_2MiB) == FWH_2MiB)
207 window->phys = 0xffe00000;
208 else if ((word & FWH_1_5MiB) == FWH_1_5MiB)
209 window->phys = 0xffe80000;
210 else if ((word & FWH_1MiB) == FWH_1MiB)
211 window->phys = 0xfff00000;
212 else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
213 window->phys = 0xfff80000;
214
215 /* reserved 0x0020 and 0x0010 */
216 window->phys -= 0x400000UL;
217 window->size = (0xffffffffUL - window->phys) + 1UL;
218
219 /* Enable writes through the rom window */
220 pci_read_config_byte(pdev, BIOS_CNTL, &byte);
221 if (!(byte & BIOS_WRITE_ENABLE) && (byte & (BIOS_LOCK_ENABLE))) {
222 /* The BIOS will generate an error if I enable
223 * this device, so don't even try.
224 */
225 printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
226 goto out;
227 }
228 pci_write_config_byte(pdev, BIOS_CNTL, byte | BIOS_WRITE_ENABLE);
229
230 /*
231 * Try to reserve the window mem region. If this fails then
232 * it is likely due to the window being "reseved" by the BIOS.
233 */
234 window->rsrc.name = MOD_NAME;
235 window->rsrc.start = window->phys;
236 window->rsrc.end = window->phys + window->size - 1;
237 window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
238 if (request_resource(&iomem_resource, &window->rsrc)) {
239 window->rsrc.parent = NULL;
240 printk(KERN_DEBUG MOD_NAME
241 ": %s(): Unable to register resource"
242 " 0x%.08llx-0x%.08llx - kernel bug?\n",
243 __func__,
244 (unsigned long long)window->rsrc.start,
245 (unsigned long long)window->rsrc.end);
246 }
247
248 /* Map the firmware hub into my address space. */
249 window->virt = ioremap_nocache(window->phys, window->size);
250 if (!window->virt) {
251 printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
252 window->phys, window->size);
253 goto out;
254 }
255
256 /* Get the first address to look for an rom chip at */
257 map_top = window->phys;
258 if ((window->phys & 0x3fffff) != 0) {
259 /* if not aligned on 4MiB, look 4MiB lower in address space */
260 map_top = window->phys + 0x400000;
261 }
262#if 1
263 /* The probe sequence run over the firmware hub lock
264 * registers sets them to 0x7 (no access).
265 * (Insane hardware design, but most copied Intel's.)
266 * ==> Probe at most the last 4M of the address space.
267 */
268 if (map_top < 0xffc00000)
269 map_top = 0xffc00000;
270#endif
271 /* Loop through and look for rom chips */
272 while ((map_top - 1) < 0xffffffffUL) {
273 struct cfi_private *cfi;
274 unsigned long offset;
275 int i;
276
277 if (!map)
278 map = kmalloc(sizeof(*map), GFP_KERNEL);
279 if (!map) {
280 printk(KERN_ERR MOD_NAME ": kmalloc failed");
281 goto out;
282 }
283 memset(map, 0, sizeof(*map));
284 INIT_LIST_HEAD(&map->list);
285 map->map.name = map->map_name;
286 map->map.phys = map_top;
287 offset = map_top - window->phys;
288 map->map.virt = (void __iomem *)
289 (((unsigned long)(window->virt)) + offset);
290 map->map.size = 0xffffffffUL - map_top + 1UL;
291 /* Set the name of the map to the address I am trying */
292 sprintf(map->map_name, "%s @%08lx",
293 MOD_NAME, map->map.phys);
294
295 /* Firmware hubs only use vpp when being programmed
296 * in a factory setting. So in-place programming
297 * needs to use a different method.
298 */
299 for(map->map.bankwidth = 32; map->map.bankwidth;
300 map->map.bankwidth >>= 1) {
301 char **probe_type;
302 /* Skip bankwidths that are not supported */
303 if (!map_bankwidth_supported(map->map.bankwidth))
304 continue;
305
306 /* Setup the map methods */
307 simple_map_init(&map->map);
308
309 /* Try all of the probe methods */
310 probe_type = rom_probe_types;
311 for(; *probe_type; probe_type++) {
312 map->mtd = do_map_probe(*probe_type, &map->map);
313 if (map->mtd)
314 goto found;
315 }
316 }
317 map_top += ROM_PROBE_STEP_SIZE;
318 continue;
319 found:
320 /* Trim the size if we are larger than the map */
321 if (map->mtd->size > map->map.size) {
322 printk(KERN_WARNING MOD_NAME
323 " rom(%u) larger than window(%lu). fixing...\n",
324 map->mtd->size, map->map.size);
325 map->mtd->size = map->map.size;
326 }
327 if (window->rsrc.parent) {
328 /*
329 * Registering the MTD device in iomem may not be possible
330 * if there is a BIOS "reserved" and BUSY range. If this
331 * fails then continue anyway.
332 */
333 map->rsrc.name = map->map_name;
334 map->rsrc.start = map->map.phys;
335 map->rsrc.end = map->map.phys + map->mtd->size - 1;
336 map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
337 if (request_resource(&window->rsrc, &map->rsrc)) {
338 printk(KERN_ERR MOD_NAME
339 ": cannot reserve MTD resource\n");
340 map->rsrc.parent = NULL;
341 }
342 }
343
344 /* Make the whole region visible in the map */
345 map->map.virt = window->virt;
346 map->map.phys = window->phys;
347 cfi = map->map.fldrv_priv;
348 for(i = 0; i < cfi->numchips; i++)
349 cfi->chips[i].start += offset;
350
351 /* Now that the mtd devices is complete claim and export it */
352 map->mtd->owner = THIS_MODULE;
353 if (add_mtd_device(map->mtd)) {
354 map_destroy(map->mtd);
355 map->mtd = NULL;
356 goto out;
357 }
358
359 /* Calculate the new value of map_top */
360 map_top += map->mtd->size;
361
362 /* File away the map structure */
363 list_add(&map->list, &window->maps);
364 map = NULL;
365 }
366
367 out:
368 /* Free any left over map structures */
369 kfree(map);
370
371 /* See if I have any map structures */
372 if (list_empty(&window->maps)) {
373 esb2rom_cleanup(window);
374 return -ENODEV;
375 }
376 return 0;
377}
378
379static void __devexit esb2rom_remove_one (struct pci_dev *pdev)
380{
381 struct esb2rom_window *window = &esb2rom_window;
382 esb2rom_cleanup(window);
383}
384
385static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = {
386 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
387 PCI_ANY_ID, PCI_ANY_ID, },
388 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
389 PCI_ANY_ID, PCI_ANY_ID, },
390 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
391 PCI_ANY_ID, PCI_ANY_ID, },
392 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
393 PCI_ANY_ID, PCI_ANY_ID, },
394 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
395 PCI_ANY_ID, PCI_ANY_ID, },
396 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
397 PCI_ANY_ID, PCI_ANY_ID, },
398 { 0, },
399};
400
401#if 0
402MODULE_DEVICE_TABLE(pci, esb2rom_pci_tbl);
403
404static struct pci_driver esb2rom_driver = {
405 .name = MOD_NAME,
406 .id_table = esb2rom_pci_tbl,
407 .probe = esb2rom_init_one,
408 .remove = esb2rom_remove_one,
409};
410#endif
411
412static int __init init_esb2rom(void)
413{
414 struct pci_dev *pdev;
415 struct pci_device_id *id;
416 int retVal;
417
418 pdev = NULL;
419 for (id = esb2rom_pci_tbl; id->vendor; id++) {
420 printk(KERN_DEBUG "device id = %x\n", id->device);
421 pdev = pci_get_device(id->vendor, id->device, NULL);
422 if (pdev) {
423 printk(KERN_DEBUG "matched device = %x\n", id->device);
424 break;
425 }
426 }
427 if (pdev) {
428 printk(KERN_DEBUG "matched device id %x\n", id->device);
429 retVal = esb2rom_init_one(pdev, &esb2rom_pci_tbl[0]);
430 pci_dev_put(pdev);
431 printk(KERN_DEBUG "retVal = %d\n", retVal);
432 return retVal;
433 }
434 return -ENXIO;
435#if 0
436 return pci_register_driver(&esb2rom_driver);
437#endif
438}
439
440static void __exit cleanup_esb2rom(void)
441{
442 esb2rom_remove_one(esb2rom_window.pdev);
443}
444
445module_init(init_esb2rom);
446module_exit(cleanup_esb2rom);
447
448MODULE_LICENSE("GPL");
449MODULE_AUTHOR("Lew Glendenning <lglendenning@lnxi.com>");
450MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ESB2 southbridge");
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index c8db01b3e45f..6946d802e6f6 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -75,14 +75,12 @@ static int armflash_probe(struct platform_device *dev)
75 int err; 75 int err;
76 void __iomem *base; 76 void __iomem *base;
77 77
78 info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL); 78 info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL);
79 if (!info) { 79 if (!info) {
80 err = -ENOMEM; 80 err = -ENOMEM;
81 goto out; 81 goto out;
82 } 82 }
83 83
84 memset(info, 0, sizeof(struct armflash_info));
85
86 info->plat = plat; 84 info->plat = plat;
87 if (plat && plat->init) { 85 if (plat && plat->init) {
88 err = plat->init(); 86 err = plat->init();
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index f9e8e5bcbc33..9f53c655af3a 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -20,6 +20,7 @@
20#include <linux/mtd/partitions.h> 20#include <linux/mtd/partitions.h>
21#include <linux/mtd/cfi.h> 21#include <linux/mtd/cfi.h>
22#include <linux/reboot.h> 22#include <linux/reboot.h>
23#include <linux/err.h>
23#include <linux/kdev_t.h> 24#include <linux/kdev_t.h>
24#include <linux/root_dev.h> 25#include <linux/root_dev.h>
25#include <asm/io.h> 26#include <asm/io.h>
@@ -178,7 +179,7 @@ int nettel_eraseconfig(void)
178 179
179 init_waitqueue_head(&wait_q); 180 init_waitqueue_head(&wait_q);
180 mtd = get_mtd_device(NULL, 2); 181 mtd = get_mtd_device(NULL, 2);
181 if (mtd) { 182 if (!IS_ERR(mtd)) {
182 nettel_erase.mtd = mtd; 183 nettel_erase.mtd = mtd;
183 nettel_erase.callback = nettel_erasecallback; 184 nettel_erase.callback = nettel_erasecallback;
184 nettel_erase.callback = NULL; 185 nettel_erase.callback = NULL;
@@ -471,7 +472,7 @@ out_unmap2:
471 iounmap(nettel_amd_map.virt); 472 iounmap(nettel_amd_map.virt);
472 473
473 return(rc); 474 return(rc);
474 475
475} 476}
476 477
477/****************************************************************************/ 478/****************************************************************************/
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index 418afffb2d80..e8d9ae535673 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -78,12 +78,10 @@ static int __devinit omapflash_probe(struct platform_device *pdev)
78 struct resource *res = pdev->resource; 78 struct resource *res = pdev->resource;
79 unsigned long size = res->end - res->start + 1; 79 unsigned long size = res->end - res->start + 1;
80 80
81 info = kmalloc(sizeof(struct omapflash_info), GFP_KERNEL); 81 info = kzalloc(sizeof(struct omapflash_info), GFP_KERNEL);
82 if (!info) 82 if (!info)
83 return -ENOMEM; 83 return -ENOMEM;
84 84
85 memset(info, 0, sizeof(struct omapflash_info));
86
87 if (!request_mem_region(res->start, size, "flash")) { 85 if (!request_mem_region(res->start, size, "flash")) {
88 err = -EBUSY; 86 err = -EBUSY;
89 goto out_free_info; 87 goto out_free_info;
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 995347b1beba..eaeb56a4070a 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -735,11 +735,10 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
735 struct pcmciamtd_dev *dev; 735 struct pcmciamtd_dev *dev;
736 736
737 /* Create new memory card device */ 737 /* Create new memory card device */
738 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 738 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
739 if (!dev) return -ENOMEM; 739 if (!dev) return -ENOMEM;
740 DEBUG(1, "dev=0x%p", dev); 740 DEBUG(1, "dev=0x%p", dev);
741 741
742 memset(dev, 0, sizeof(*dev));
743 dev->p_dev = link; 742 dev->p_dev = link;
744 link->priv = dev; 743 link->priv = dev;
745 744
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index d1717763f719..28c5ffd75233 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -89,15 +89,14 @@ static int physmap_flash_probe(struct platform_device *dev)
89 return -ENODEV; 89 return -ENODEV;
90 90
91 printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", 91 printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
92 (unsigned long long)dev->resource->end - dev->resource->start + 1, 92 (unsigned long long)(dev->resource->end - dev->resource->start + 1),
93 (unsigned long long)dev->resource->start); 93 (unsigned long long)dev->resource->start);
94 94
95 info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); 95 info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
96 if (info == NULL) { 96 if (info == NULL) {
97 err = -ENOMEM; 97 err = -ENOMEM;
98 goto err_out; 98 goto err_out;
99 } 99 }
100 memset(info, 0, sizeof(*info));
101 100
102 platform_set_drvdata(dev, info); 101 platform_set_drvdata(dev, info);
103 102
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
new file mode 100644
index 000000000000..7efe744ad31e
--- /dev/null
+++ b/drivers/mtd/maps/physmap_of.c
@@ -0,0 +1,255 @@
1/*
2 * Normal mappings of chips in physical memory for OF devices
3 *
4 * Copyright (C) 2006 MontaVista Software Inc.
5 * Author: Vitaly Wool <vwool@ru.mvista.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/device.h>
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h>
22#include <linux/mtd/physmap.h>
23#include <asm/io.h>
24#include <asm/prom.h>
25#include <asm/of_device.h>
26#include <asm/of_platform.h>
27
28struct physmap_flash_info {
29 struct mtd_info *mtd;
30 struct map_info map;
31 struct resource *res;
32#ifdef CONFIG_MTD_PARTITIONS
33 int nr_parts;
34 struct mtd_partition *parts;
35#endif
36};
37
38static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
39#ifdef CONFIG_MTD_PARTITIONS
40static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
41#endif
42
43#ifdef CONFIG_MTD_PARTITIONS
44static int parse_flash_partitions(struct device_node *node,
45 struct mtd_partition **parts)
46{
47 int i, plen, retval = -ENOMEM;
48 const u32 *part;
49 const char *name;
50
51 part = get_property(node, "partitions", &plen);
52 if (part == NULL)
53 goto err;
54
55 retval = plen / (2 * sizeof(u32));
56 *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL);
57 if (*parts == NULL) {
58 printk(KERN_ERR "Can't allocate the flash partition data!\n");
59 goto err;
60 }
61
62 name = get_property(node, "partition-names", &plen);
63
64 for (i = 0; i < retval; i++) {
65 (*parts)[i].offset = *part++;
66 (*parts)[i].size = *part & ~1;
67 if (*part++ & 1) /* bit 0 set signifies read only partition */
68 (*parts)[i].mask_flags = MTD_WRITEABLE;
69
70 if (name != NULL && plen > 0) {
71 int len = strlen(name) + 1;
72
73 (*parts)[i].name = (char *)name;
74 plen -= len;
75 name += len;
76 } else
77 (*parts)[i].name = "unnamed";
78 }
79err:
80 return retval;
81}
82#endif
83
84static int of_physmap_remove(struct of_device *dev)
85{
86 struct physmap_flash_info *info;
87
88 info = dev_get_drvdata(&dev->dev);
89 if (info == NULL)
90 return 0;
91 dev_set_drvdata(&dev->dev, NULL);
92
93 if (info->mtd != NULL) {
94#ifdef CONFIG_MTD_PARTITIONS
95 if (info->nr_parts) {
96 del_mtd_partitions(info->mtd);
97 kfree(info->parts);
98 } else {
99 del_mtd_device(info->mtd);
100 }
101#else
102 del_mtd_device(info->mtd);
103#endif
104 map_destroy(info->mtd);
105 }
106
107 if (info->map.virt != NULL)
108 iounmap(info->map.virt);
109
110 if (info->res != NULL) {
111 release_resource(info->res);
112 kfree(info->res);
113 }
114
115 return 0;
116}
117
118static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match)
119{
120 struct device_node *dp = dev->node;
121 struct resource res;
122 struct physmap_flash_info *info;
123 const char **probe_type;
124 const char *of_probe;
125 const u32 *width;
126 int err;
127
128
129 if (of_address_to_resource(dp, 0, &res)) {
130 dev_err(&dev->dev, "Can't get the flash mapping!\n");
131 err = -EINVAL;
132 goto err_out;
133 }
134
135 dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n",
136 (unsigned long long)res.end - res.start + 1,
137 (unsigned long long)res.start);
138
139 info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
140 if (info == NULL) {
141 err = -ENOMEM;
142 goto err_out;
143 }
144 memset(info, 0, sizeof(*info));
145
146 dev_set_drvdata(&dev->dev, info);
147
148 info->res = request_mem_region(res.start, res.end - res.start + 1,
149 dev->dev.bus_id);
150 if (info->res == NULL) {
151 dev_err(&dev->dev, "Could not reserve memory region\n");
152 err = -ENOMEM;
153 goto err_out;
154 }
155
156 width = get_property(dp, "bank-width", NULL);
157 if (width == NULL) {
158 dev_err(&dev->dev, "Can't get the flash bank width!\n");
159 err = -EINVAL;
160 goto err_out;
161 }
162
163 info->map.name = dev->dev.bus_id;
164 info->map.phys = res.start;
165 info->map.size = res.end - res.start + 1;
166 info->map.bankwidth = *width;
167
168 info->map.virt = ioremap(info->map.phys, info->map.size);
169 if (info->map.virt == NULL) {
170 dev_err(&dev->dev, "Failed to ioremap flash region\n");
171 err = EIO;
172 goto err_out;
173 }
174
175 simple_map_init(&info->map);
176
177 of_probe = get_property(dp, "probe-type", NULL);
178 if (of_probe == NULL) {
179 probe_type = rom_probe_types;
180 for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
181 info->mtd = do_map_probe(*probe_type, &info->map);
182 } else if (!strcmp(of_probe, "CFI"))
183 info->mtd = do_map_probe("cfi_probe", &info->map);
184 else if (!strcmp(of_probe, "JEDEC"))
185 info->mtd = do_map_probe("jedec_probe", &info->map);
186 else {
187 if (strcmp(of_probe, "ROM"))
188 dev_dbg(&dev->dev, "map_probe: don't know probe type "
189 "'%s', mapping as rom\n");
190 info->mtd = do_map_probe("mtd_rom", &info->map);
191 }
192 if (info->mtd == NULL) {
193 dev_err(&dev->dev, "map_probe failed\n");
194 err = -ENXIO;
195 goto err_out;
196 }
197 info->mtd->owner = THIS_MODULE;
198
199#ifdef CONFIG_MTD_PARTITIONS
200 err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
201 if (err > 0) {
202 add_mtd_partitions(info->mtd, info->parts, err);
203 } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) {
204 dev_info(&dev->dev, "Using OF partition information\n");
205 add_mtd_partitions(info->mtd, info->parts, err);
206 info->nr_parts = err;
207 } else
208#endif
209
210 add_mtd_device(info->mtd);
211 return 0;
212
213err_out:
214 of_physmap_remove(dev);
215 return err;
216
217 return 0;
218
219
220}
221
222static struct of_device_id of_physmap_match[] = {
223 {
224 .type = "rom",
225 .compatible = "direct-mapped"
226 },
227 { },
228};
229
230MODULE_DEVICE_TABLE(of, of_physmap_match);
231
232
233static struct of_platform_driver of_physmap_flash_driver = {
234 .name = "physmap-flash",
235 .match_table = of_physmap_match,
236 .probe = of_physmap_probe,
237 .remove = of_physmap_remove,
238};
239
240static int __init of_physmap_init(void)
241{
242 return of_register_platform_driver(&of_physmap_flash_driver);
243}
244
245static void __exit of_physmap_exit(void)
246{
247 of_unregister_platform_driver(&of_physmap_flash_driver);
248}
249
250module_init(of_physmap_init);
251module_exit(of_physmap_exit);
252
253MODULE_LICENSE("GPL");
254MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
255MODULE_DESCRIPTION("Configurable MTD map driver for OF");
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 5d3c75451ca2..2b6504ecbbd1 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -147,14 +147,13 @@ static int platram_probe(struct platform_device *pdev)
147 147
148 pdata = pdev->dev.platform_data; 148 pdata = pdev->dev.platform_data;
149 149
150 info = kmalloc(sizeof(*info), GFP_KERNEL); 150 info = kzalloc(sizeof(*info), GFP_KERNEL);
151 if (info == NULL) { 151 if (info == NULL) {
152 dev_err(&pdev->dev, "no memory for flash info\n"); 152 dev_err(&pdev->dev, "no memory for flash info\n");
153 err = -ENOMEM; 153 err = -ENOMEM;
154 goto exit_error; 154 goto exit_error;
155 } 155 }
156 156
157 memset(info, 0, sizeof(*info));
158 platform_set_drvdata(pdev, info); 157 platform_set_drvdata(pdev, info);
159 158
160 info->dev = &pdev->dev; 159 info->dev = &pdev->dev;
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 950bf1c57841..f904e6bd02e0 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -273,14 +273,12 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
273 /* 273 /*
274 * Allocate the map_info structs in one go. 274 * Allocate the map_info structs in one go.
275 */ 275 */
276 info = kmalloc(size, GFP_KERNEL); 276 info = kzalloc(size, GFP_KERNEL);
277 if (!info) { 277 if (!info) {
278 ret = -ENOMEM; 278 ret = -ENOMEM;
279 goto out; 279 goto out;
280 } 280 }
281 281
282 memset(info, 0, size);
283
284 if (plat->init) { 282 if (plat->init) {
285 ret = plat->init(); 283 ret = plat->init();
286 if (ret) 284 if (ret)
diff --git a/drivers/mtd/maps/tqm834x.c b/drivers/mtd/maps/tqm834x.c
index 58e5912bd381..9adc970e55e6 100644
--- a/drivers/mtd/maps/tqm834x.c
+++ b/drivers/mtd/maps/tqm834x.c
@@ -132,20 +132,16 @@ static int __init init_tqm834x_mtd(void)
132 132
133 pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx); 133 pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx);
134 134
135 map_banks[idx] = 135 map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
136 (struct map_info *)kmalloc(sizeof(struct map_info),
137 GFP_KERNEL);
138 if (map_banks[idx] == NULL) { 136 if (map_banks[idx] == NULL) {
139 ret = -ENOMEM; 137 ret = -ENOMEM;
140 goto error_mem; 138 goto error_mem;
141 } 139 }
142 memset((void *)map_banks[idx], 0, sizeof(struct map_info)); 140 map_banks[idx]->name = kzalloc(16, GFP_KERNEL);
143 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
144 if (map_banks[idx]->name == NULL) { 141 if (map_banks[idx]->name == NULL) {
145 ret = -ENOMEM; 142 ret = -ENOMEM;
146 goto error_mem; 143 goto error_mem;
147 } 144 }
148 memset((void *)map_banks[idx]->name, 0, 16);
149 145
150 sprintf(map_banks[idx]->name, "TQM834x-%d", idx); 146 sprintf(map_banks[idx]->name, "TQM834x-%d", idx);
151 map_banks[idx]->size = flash_size; 147 map_banks[idx]->size = flash_size;
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 19578ba84ee8..37e4ded9b600 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -134,14 +134,13 @@ int __init init_tqm_mtd(void)
134 134
135 printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); 135 printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
136 136
137 map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL); 137 map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
138 if(map_banks[idx] == NULL) { 138 if(map_banks[idx] == NULL) {
139 ret = -ENOMEM; 139 ret = -ENOMEM;
140 /* FIXME: What if some MTD devices were probed already? */ 140 /* FIXME: What if some MTD devices were probed already? */
141 goto error_mem; 141 goto error_mem;
142 } 142 }
143 143
144 memset((void *)map_banks[idx], 0, sizeof(struct map_info));
145 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); 144 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
146 145
147 if (!map_banks[idx]->name) { 146 if (!map_banks[idx]->name) {
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 178b53b56be9..b879a66daa9e 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -42,19 +42,20 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
42 unsigned long block, nsect; 42 unsigned long block, nsect;
43 char *buf; 43 char *buf;
44 44
45 block = req->sector; 45 block = req->sector << 9 >> tr->blkshift;
46 nsect = req->current_nr_sectors; 46 nsect = req->current_nr_sectors << 9 >> tr->blkshift;
47
47 buf = req->buffer; 48 buf = req->buffer;
48 49
49 if (!blk_fs_request(req)) 50 if (!blk_fs_request(req))
50 return 0; 51 return 0;
51 52
52 if (block + nsect > get_capacity(req->rq_disk)) 53 if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk))
53 return 0; 54 return 0;
54 55
55 switch(rq_data_dir(req)) { 56 switch(rq_data_dir(req)) {
56 case READ: 57 case READ:
57 for (; nsect > 0; nsect--, block++, buf += 512) 58 for (; nsect > 0; nsect--, block++, buf += tr->blksize)
58 if (tr->readsect(dev, block, buf)) 59 if (tr->readsect(dev, block, buf))
59 return 0; 60 return 0;
60 return 1; 61 return 1;
@@ -63,7 +64,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
63 if (!tr->writesect) 64 if (!tr->writesect)
64 return 0; 65 return 0;
65 66
66 for (; nsect > 0; nsect--, block++, buf += 512) 67 for (; nsect > 0; nsect--, block++, buf += tr->blksize)
67 if (tr->writesect(dev, block, buf)) 68 if (tr->writesect(dev, block, buf))
68 return 0; 69 return 0;
69 return 1; 70 return 1;
@@ -297,7 +298,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
297 298
298 /* 2.5 has capacity in units of 512 bytes while still 299 /* 2.5 has capacity in units of 512 bytes while still
299 having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ 300 having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
300 set_capacity(gd, (new->size * new->blksize) >> 9); 301 set_capacity(gd, (new->size * tr->blksize) >> 9);
301 302
302 gd->private_data = new; 303 gd->private_data = new;
303 new->blkcore_priv = gd; 304 new->blkcore_priv = gd;
@@ -372,12 +373,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
372 if (!blktrans_notifier.list.next) 373 if (!blktrans_notifier.list.next)
373 register_mtd_user(&blktrans_notifier); 374 register_mtd_user(&blktrans_notifier);
374 375
375 tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); 376 tr->blkcore_priv = kzalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
376 if (!tr->blkcore_priv) 377 if (!tr->blkcore_priv)
377 return -ENOMEM; 378 return -ENOMEM;
378 379
379 memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
380
381 mutex_lock(&mtd_table_mutex); 380 mutex_lock(&mtd_table_mutex);
382 381
383 ret = register_blkdev(tr->major, tr->name); 382 ret = register_blkdev(tr->major, tr->name);
@@ -401,6 +400,8 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
401 } 400 }
402 401
403 tr->blkcore_priv->rq->queuedata = tr; 402 tr->blkcore_priv->rq->queuedata = tr;
403 blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
404 tr->blkshift = ffs(tr->blksize) - 1;
404 405
405 ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL); 406 ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL);
406 if (ret < 0) { 407 if (ret < 0) {
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 04ed34694b14..952da30b1745 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -278,11 +278,10 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
278 } 278 }
279 279
280 /* OK, it's not open. Create cache info for it */ 280 /* OK, it's not open. Create cache info for it */
281 mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); 281 mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
282 if (!mtdblk) 282 if (!mtdblk)
283 return -ENOMEM; 283 return -ENOMEM;
284 284
285 memset(mtdblk, 0, sizeof(*mtdblk));
286 mtdblk->count = 1; 285 mtdblk->count = 1;
287 mtdblk->mtd = mtd; 286 mtdblk->mtd = mtd;
288 287
@@ -339,16 +338,14 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev)
339 338
340static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) 339static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
341{ 340{
342 struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); 341 struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
343 342
344 if (!dev) 343 if (!dev)
345 return; 344 return;
346 345
347 memset(dev, 0, sizeof(*dev));
348
349 dev->mtd = mtd; 346 dev->mtd = mtd;
350 dev->devnum = mtd->index; 347 dev->devnum = mtd->index;
351 dev->blksize = 512; 348
352 dev->size = mtd->size >> 9; 349 dev->size = mtd->size >> 9;
353 dev->tr = tr; 350 dev->tr = tr;
354 351
@@ -368,6 +365,7 @@ static struct mtd_blktrans_ops mtdblock_tr = {
368 .name = "mtdblock", 365 .name = "mtdblock",
369 .major = 31, 366 .major = 31,
370 .part_bits = 0, 367 .part_bits = 0,
368 .blksize = 512,
371 .open = mtdblock_open, 369 .open = mtdblock_open,
372 .flush = mtdblock_flush, 370 .flush = mtdblock_flush,
373 .release = mtdblock_release, 371 .release = mtdblock_release,
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index 29563ed258a4..f79dbb49b1a2 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -33,16 +33,14 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
33 33
34static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) 34static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
35{ 35{
36 struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); 36 struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
37 37
38 if (!dev) 38 if (!dev)
39 return; 39 return;
40 40
41 memset(dev, 0, sizeof(*dev));
42
43 dev->mtd = mtd; 41 dev->mtd = mtd;
44 dev->devnum = mtd->index; 42 dev->devnum = mtd->index;
45 dev->blksize = 512; 43
46 dev->size = mtd->size >> 9; 44 dev->size = mtd->size >> 9;
47 dev->tr = tr; 45 dev->tr = tr;
48 dev->readonly = 1; 46 dev->readonly = 1;
@@ -60,6 +58,7 @@ static struct mtd_blktrans_ops mtdblock_tr = {
60 .name = "mtdblock", 58 .name = "mtdblock",
61 .major = 31, 59 .major = 31,
62 .part_bits = 0, 60 .part_bits = 0,
61 .blksize = 512,
63 .readsect = mtdblock_readsect, 62 .readsect = mtdblock_readsect,
64 .writesect = mtdblock_writesect, 63 .writesect = mtdblock_writesect,
65 .add_mtd = mtdblock_add_mtd, 64 .add_mtd = mtdblock_add_mtd,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 5b6acfcb2b88..3013d0883b97 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -7,6 +7,7 @@
7 7
8#include <linux/device.h> 8#include <linux/device.h>
9#include <linux/fs.h> 9#include <linux/fs.h>
10#include <linux/err.h>
10#include <linux/init.h> 11#include <linux/init.h>
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/module.h> 13#include <linux/module.h>
@@ -100,8 +101,8 @@ static int mtd_open(struct inode *inode, struct file *file)
100 101
101 mtd = get_mtd_device(NULL, devnum); 102 mtd = get_mtd_device(NULL, devnum);
102 103
103 if (!mtd) 104 if (IS_ERR(mtd))
104 return -ENODEV; 105 return PTR_ERR(mtd);
105 106
106 if (MTD_ABSENT == mtd->type) { 107 if (MTD_ABSENT == mtd->type) {
107 put_mtd_device(mtd); 108 put_mtd_device(mtd);
@@ -431,7 +432,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
431 if(!(file->f_mode & 2)) 432 if(!(file->f_mode & 2))
432 return -EPERM; 433 return -EPERM;
433 434
434 erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL); 435 erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
435 if (!erase) 436 if (!erase)
436 ret = -ENOMEM; 437 ret = -ENOMEM;
437 else { 438 else {
@@ -440,7 +441,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
440 441
441 init_waitqueue_head(&waitq); 442 init_waitqueue_head(&waitq);
442 443
443 memset (erase,0,sizeof(struct erase_info));
444 if (copy_from_user(&erase->addr, argp, 444 if (copy_from_user(&erase->addr, argp,
445 sizeof(struct erase_info_user))) { 445 sizeof(struct erase_info_user))) {
446 kfree(erase); 446 kfree(erase);
@@ -499,13 +499,12 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
499 if (ret) 499 if (ret)
500 return ret; 500 return ret;
501 501
502 ops.len = buf.length;
503 ops.ooblen = buf.length; 502 ops.ooblen = buf.length;
504 ops.ooboffs = buf.start & (mtd->oobsize - 1); 503 ops.ooboffs = buf.start & (mtd->oobsize - 1);
505 ops.datbuf = NULL; 504 ops.datbuf = NULL;
506 ops.mode = MTD_OOB_PLACE; 505 ops.mode = MTD_OOB_PLACE;
507 506
508 if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs)) 507 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
509 return -EINVAL; 508 return -EINVAL;
510 509
511 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); 510 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
@@ -520,7 +519,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
520 buf.start &= ~(mtd->oobsize - 1); 519 buf.start &= ~(mtd->oobsize - 1);
521 ret = mtd->write_oob(mtd, buf.start, &ops); 520 ret = mtd->write_oob(mtd, buf.start, &ops);
522 521
523 if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen, 522 if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen,
524 sizeof(uint32_t))) 523 sizeof(uint32_t)))
525 ret = -EFAULT; 524 ret = -EFAULT;
526 525
@@ -548,7 +547,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
548 if (ret) 547 if (ret)
549 return ret; 548 return ret;
550 549
551 ops.len = buf.length;
552 ops.ooblen = buf.length; 550 ops.ooblen = buf.length;
553 ops.ooboffs = buf.start & (mtd->oobsize - 1); 551 ops.ooboffs = buf.start & (mtd->oobsize - 1);
554 ops.datbuf = NULL; 552 ops.datbuf = NULL;
@@ -564,10 +562,10 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
564 buf.start &= ~(mtd->oobsize - 1); 562 buf.start &= ~(mtd->oobsize - 1);
565 ret = mtd->read_oob(mtd, buf.start, &ops); 563 ret = mtd->read_oob(mtd, buf.start, &ops);
566 564
567 if (put_user(ops.retlen, (uint32_t __user *)argp)) 565 if (put_user(ops.oobretlen, (uint32_t __user *)argp))
568 ret = -EFAULT; 566 ret = -EFAULT;
569 else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf, 567 else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf,
570 ops.retlen)) 568 ops.oobretlen))
571 ret = -EFAULT; 569 ret = -EFAULT;
572 570
573 kfree(ops.oobbuf); 571 kfree(ops.oobbuf);
@@ -616,6 +614,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
616 memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); 614 memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
617 memcpy(&oi.oobfree, mtd->ecclayout->oobfree, 615 memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
618 sizeof(oi.oobfree)); 616 sizeof(oi.oobfree));
617 oi.eccbytes = mtd->ecclayout->eccbytes;
619 618
620 if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) 619 if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
621 return -EFAULT; 620 return -EFAULT;
@@ -715,7 +714,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
715 if (!mtd->ecclayout) 714 if (!mtd->ecclayout)
716 return -EOPNOTSUPP; 715 return -EOPNOTSUPP;
717 716
718 if (copy_to_user(argp, &mtd->ecclayout, 717 if (copy_to_user(argp, mtd->ecclayout,
719 sizeof(struct nand_ecclayout))) 718 sizeof(struct nand_ecclayout)))
720 return -EFAULT; 719 return -EFAULT;
721 break; 720 break;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 1fea631b5852..06902683bc2a 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -247,7 +247,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
247 struct mtd_oob_ops devops = *ops; 247 struct mtd_oob_ops devops = *ops;
248 int i, err, ret = 0; 248 int i, err, ret = 0;
249 249
250 ops->retlen = 0; 250 ops->retlen = ops->oobretlen = 0;
251 251
252 for (i = 0; i < concat->num_subdev; i++) { 252 for (i = 0; i < concat->num_subdev; i++) {
253 struct mtd_info *subdev = concat->subdev[i]; 253 struct mtd_info *subdev = concat->subdev[i];
@@ -263,6 +263,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
263 263
264 err = subdev->read_oob(subdev, from, &devops); 264 err = subdev->read_oob(subdev, from, &devops);
265 ops->retlen += devops.retlen; 265 ops->retlen += devops.retlen;
266 ops->oobretlen += devops.oobretlen;
266 267
267 /* Save information about bitflips! */ 268 /* Save information about bitflips! */
268 if (unlikely(err)) { 269 if (unlikely(err)) {
@@ -278,14 +279,18 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
278 return err; 279 return err;
279 } 280 }
280 281
281 devops.len = ops->len - ops->retlen; 282 if (devops.datbuf) {
282 if (!devops.len) 283 devops.len = ops->len - ops->retlen;
283 return ret; 284 if (!devops.len)
284 285 return ret;
285 if (devops.datbuf)
286 devops.datbuf += devops.retlen; 286 devops.datbuf += devops.retlen;
287 if (devops.oobbuf) 287 }
288 devops.oobbuf += devops.ooblen; 288 if (devops.oobbuf) {
289 devops.ooblen = ops->ooblen - ops->oobretlen;
290 if (!devops.ooblen)
291 return ret;
292 devops.oobbuf += ops->oobretlen;
293 }
289 294
290 from = 0; 295 from = 0;
291 } 296 }
@@ -321,14 +326,18 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
321 if (err) 326 if (err)
322 return err; 327 return err;
323 328
324 devops.len = ops->len - ops->retlen; 329 if (devops.datbuf) {
325 if (!devops.len) 330 devops.len = ops->len - ops->retlen;
326 return 0; 331 if (!devops.len)
327 332 return 0;
328 if (devops.datbuf)
329 devops.datbuf += devops.retlen; 333 devops.datbuf += devops.retlen;
330 if (devops.oobbuf) 334 }
331 devops.oobbuf += devops.ooblen; 335 if (devops.oobbuf) {
336 devops.ooblen = ops->ooblen - ops->oobretlen;
337 if (!devops.ooblen)
338 return 0;
339 devops.oobbuf += devops.oobretlen;
340 }
332 to = 0; 341 to = 0;
333 } 342 }
334 return -EINVAL; 343 return -EINVAL;
@@ -699,14 +708,13 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
699 708
700 /* allocate the device structure */ 709 /* allocate the device structure */
701 size = SIZEOF_STRUCT_MTD_CONCAT(num_devs); 710 size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
702 concat = kmalloc(size, GFP_KERNEL); 711 concat = kzalloc(size, GFP_KERNEL);
703 if (!concat) { 712 if (!concat) {
704 printk 713 printk
705 ("memory allocation error while creating concatenated device \"%s\"\n", 714 ("memory allocation error while creating concatenated device \"%s\"\n",
706 name); 715 name);
707 return NULL; 716 return NULL;
708 } 717 }
709 memset(concat, 0, size);
710 concat->subdev = (struct mtd_info **) (concat + 1); 718 concat->subdev = (struct mtd_info **) (concat + 1);
711 719
712 /* 720 /*
@@ -764,6 +772,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
764 concat->mtd.ecc_stats.badblocks += 772 concat->mtd.ecc_stats.badblocks +=
765 subdev[i]->ecc_stats.badblocks; 773 subdev[i]->ecc_stats.badblocks;
766 if (concat->mtd.writesize != subdev[i]->writesize || 774 if (concat->mtd.writesize != subdev[i]->writesize ||
775 concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
767 concat->mtd.oobsize != subdev[i]->oobsize || 776 concat->mtd.oobsize != subdev[i]->oobsize ||
768 concat->mtd.ecctype != subdev[i]->ecctype || 777 concat->mtd.ecctype != subdev[i]->ecctype ||
769 concat->mtd.eccsize != subdev[i]->eccsize || 778 concat->mtd.eccsize != subdev[i]->eccsize ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c4d26de74349..7070110aba2a 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -15,6 +15,7 @@
15#include <linux/timer.h> 15#include <linux/timer.h>
16#include <linux/major.h> 16#include <linux/major.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/err.h>
18#include <linux/ioctl.h> 19#include <linux/ioctl.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/mtd/compatmac.h> 21#include <linux/mtd/compatmac.h>
@@ -192,14 +193,14 @@ int unregister_mtd_user (struct mtd_notifier *old)
192 * Given a number and NULL address, return the num'th entry in the device 193 * Given a number and NULL address, return the num'th entry in the device
193 * table, if any. Given an address and num == -1, search the device table 194 * table, if any. Given an address and num == -1, search the device table
194 * for a device with that address and return if it's still present. Given 195 * for a device with that address and return if it's still present. Given
195 * both, return the num'th driver only if its address matches. Return NULL 196 * both, return the num'th driver only if its address matches. Return
196 * if not. 197 * error code if not.
197 */ 198 */
198 199
199struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 200struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
200{ 201{
201 struct mtd_info *ret = NULL; 202 struct mtd_info *ret = NULL;
202 int i; 203 int i, err = -ENODEV;
203 204
204 mutex_lock(&mtd_table_mutex); 205 mutex_lock(&mtd_table_mutex);
205 206
@@ -213,14 +214,73 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
213 ret = NULL; 214 ret = NULL;
214 } 215 }
215 216
216 if (ret && !try_module_get(ret->owner)) 217 if (!ret)
217 ret = NULL; 218 goto out_unlock;
219
220 if (!try_module_get(ret->owner))
221 goto out_unlock;
218 222
219 if (ret) 223 if (ret->get_device) {
220 ret->usecount++; 224 err = ret->get_device(ret);
225 if (err)
226 goto out_put;
227 }
221 228
229 ret->usecount++;
222 mutex_unlock(&mtd_table_mutex); 230 mutex_unlock(&mtd_table_mutex);
223 return ret; 231 return ret;
232
233out_put:
234 module_put(ret->owner);
235out_unlock:
236 mutex_unlock(&mtd_table_mutex);
237 return ERR_PTR(err);
238}
239
240/**
241 * get_mtd_device_nm - obtain a validated handle for an MTD device by
242 * device name
243 * @name: MTD device name to open
244 *
245 * This function returns MTD device description structure in case of
246 * success and an error code in case of failure.
247 */
248
249struct mtd_info *get_mtd_device_nm(const char *name)
250{
251 int i, err = -ENODEV;
252 struct mtd_info *mtd = NULL;
253
254 mutex_lock(&mtd_table_mutex);
255
256 for (i = 0; i < MAX_MTD_DEVICES; i++) {
257 if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
258 mtd = mtd_table[i];
259 break;
260 }
261 }
262
263 if (!mtd)
264 goto out_unlock;
265
266 if (!try_module_get(mtd->owner))
267 goto out_unlock;
268
269 if (mtd->get_device) {
270 err = mtd->get_device(mtd);
271 if (err)
272 goto out_put;
273 }
274
275 mtd->usecount++;
276 mutex_unlock(&mtd_table_mutex);
277 return mtd;
278
279out_put:
280 module_put(mtd->owner);
281out_unlock:
282 mutex_unlock(&mtd_table_mutex);
283 return ERR_PTR(err);
224} 284}
225 285
226void put_mtd_device(struct mtd_info *mtd) 286void put_mtd_device(struct mtd_info *mtd)
@@ -229,6 +289,8 @@ void put_mtd_device(struct mtd_info *mtd)
229 289
230 mutex_lock(&mtd_table_mutex); 290 mutex_lock(&mtd_table_mutex);
231 c = --mtd->usecount; 291 c = --mtd->usecount;
292 if (mtd->put_device)
293 mtd->put_device(mtd);
232 mutex_unlock(&mtd_table_mutex); 294 mutex_unlock(&mtd_table_mutex);
233 BUG_ON(c < 0); 295 BUG_ON(c < 0);
234 296
@@ -236,7 +298,7 @@ void put_mtd_device(struct mtd_info *mtd)
236} 298}
237 299
238/* default_mtd_writev - default mtd writev method for MTD devices that 300/* default_mtd_writev - default mtd writev method for MTD devices that
239 * dont implement their own 301 * don't implement their own
240 */ 302 */
241 303
242int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 304int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
@@ -264,13 +326,14 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
264 return ret; 326 return ret;
265} 327}
266 328
267EXPORT_SYMBOL(add_mtd_device); 329EXPORT_SYMBOL_GPL(add_mtd_device);
268EXPORT_SYMBOL(del_mtd_device); 330EXPORT_SYMBOL_GPL(del_mtd_device);
269EXPORT_SYMBOL(get_mtd_device); 331EXPORT_SYMBOL_GPL(get_mtd_device);
270EXPORT_SYMBOL(put_mtd_device); 332EXPORT_SYMBOL_GPL(get_mtd_device_nm);
271EXPORT_SYMBOL(register_mtd_user); 333EXPORT_SYMBOL_GPL(put_mtd_device);
272EXPORT_SYMBOL(unregister_mtd_user); 334EXPORT_SYMBOL_GPL(register_mtd_user);
273EXPORT_SYMBOL(default_mtd_writev); 335EXPORT_SYMBOL_GPL(unregister_mtd_user);
336EXPORT_SYMBOL_GPL(default_mtd_writev);
274 337
275#ifdef CONFIG_PROC_FS 338#ifdef CONFIG_PROC_FS
276 339
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 06a930372b7a..bafd2fba87bd 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -94,7 +94,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
94 94
95 if (from >= mtd->size) 95 if (from >= mtd->size)
96 return -EINVAL; 96 return -EINVAL;
97 if (from + ops->len > mtd->size) 97 if (ops->datbuf && from + ops->len > mtd->size)
98 return -EINVAL; 98 return -EINVAL;
99 res = part->master->read_oob(part->master, from + part->offset, ops); 99 res = part->master->read_oob(part->master, from + part->offset, ops);
100 100
@@ -161,7 +161,7 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
161 161
162 if (to >= mtd->size) 162 if (to >= mtd->size)
163 return -EINVAL; 163 return -EINVAL;
164 if (to + ops->len > mtd->size) 164 if (ops->datbuf && to + ops->len > mtd->size)
165 return -EINVAL; 165 return -EINVAL;
166 return part->master->write_oob(part->master, to + part->offset, ops); 166 return part->master->write_oob(part->master, to + part->offset, ops);
167} 167}
@@ -323,14 +323,13 @@ int add_mtd_partitions(struct mtd_info *master,
323 for (i = 0; i < nbparts; i++) { 323 for (i = 0; i < nbparts; i++) {
324 324
325 /* allocate the partition structure */ 325 /* allocate the partition structure */
326 slave = kmalloc (sizeof(*slave), GFP_KERNEL); 326 slave = kzalloc (sizeof(*slave), GFP_KERNEL);
327 if (!slave) { 327 if (!slave) {
328 printk ("memory allocation error while creating partitions for \"%s\"\n", 328 printk ("memory allocation error while creating partitions for \"%s\"\n",
329 master->name); 329 master->name);
330 del_mtd_partitions(master); 330 del_mtd_partitions(master);
331 return -ENOMEM; 331 return -ENOMEM;
332 } 332 }
333 memset(slave, 0, sizeof(*slave));
334 list_add(&slave->list, &mtd_partitions); 333 list_add(&slave->list, &mtd_partitions);
335 334
336 /* set up the MTD object for this partition */ 335 /* set up the MTD object for this partition */
@@ -341,6 +340,7 @@ int add_mtd_partitions(struct mtd_info *master,
341 slave->mtd.oobsize = master->oobsize; 340 slave->mtd.oobsize = master->oobsize;
342 slave->mtd.ecctype = master->ecctype; 341 slave->mtd.ecctype = master->ecctype;
343 slave->mtd.eccsize = master->eccsize; 342 slave->mtd.eccsize = master->eccsize;
343 slave->mtd.subpage_sft = master->subpage_sft;
344 344
345 slave->mtd.name = parts[i].name; 345 slave->mtd.name = parts[i].name;
346 slave->mtd.bank_size = master->bank_size; 346 slave->mtd.bank_size = master->bank_size;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1831340e5f51..358f55a82dbe 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -90,6 +90,7 @@ config MTD_NAND_RTC_FROM4
90 depends on MTD_NAND && SH_SOLUTION_ENGINE 90 depends on MTD_NAND && SH_SOLUTION_ENGINE
91 select REED_SOLOMON 91 select REED_SOLOMON
92 select REED_SOLOMON_DEC8 92 select REED_SOLOMON_DEC8
93 select BITREVERSE
93 help 94 help
94 This enables the driver for the Renesas Technology AG-AND 95 This enables the driver for the Renesas Technology AG-AND
95 flash interface board (FROM_BOARD4) 96 flash interface board (FROM_BOARD4)
@@ -132,6 +133,7 @@ config MTD_NAND_S3C2410_HWECC
132config MTD_NAND_NDFC 133config MTD_NAND_NDFC
133 tristate "NDFC NanD Flash Controller" 134 tristate "NDFC NanD Flash Controller"
134 depends on MTD_NAND && 44x 135 depends on MTD_NAND && 44x
136 select MTD_NAND_ECC_SMC
135 help 137 help
136 NDFC Nand Flash Controllers are integrated in EP44x SoCs 138 NDFC Nand Flash Controllers are integrated in EP44x SoCs
137 139
@@ -219,6 +221,13 @@ config MTD_NAND_SHARPSL
219 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" 221 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
220 depends on MTD_NAND && ARCH_PXA 222 depends on MTD_NAND && ARCH_PXA
221 223
224config MTD_NAND_CAFE
225 tristate "NAND support for OLPC CAFÉ chip"
226 depends on PCI
227 help
228 Use NAND flash attached to the CAFÉ chip designed for the $100
229 laptop.
230
222config MTD_NAND_CS553X 231config MTD_NAND_CS553X
223 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" 232 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
224 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) 233 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
@@ -232,6 +241,13 @@ config MTD_NAND_CS553X
232 241
233 If you say "m", the module will be called "cs553x_nand.ko". 242 If you say "m", the module will be called "cs553x_nand.ko".
234 243
244config MTD_NAND_AT91
245 bool "Support for NAND Flash / SmartMedia on AT91"
246 depends on MTD_NAND && ARCH_AT91
247 help
248 Enables support for NAND Flash / Smart Media Card interface
249 on Atmel AT91 processors.
250
235config MTD_NAND_NANDSIM 251config MTD_NAND_NANDSIM
236 tristate "Support for NAND Flash Simulator" 252 tristate "Support for NAND Flash Simulator"
237 depends on MTD_NAND && MTD_PARTITIONS 253 depends on MTD_NAND && MTD_PARTITIONS
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index f74759351c91..f7a53f0b7017 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -6,6 +6,7 @@
6obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o 6obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o 7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
8 8
9obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
9obj-$(CONFIG_MTD_NAND_SPIA) += spia.o 10obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
10obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o 11obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
11obj-$(CONFIG_MTD_NAND_TOTO) += toto.o 12obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
@@ -22,5 +23,7 @@ obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o
22obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o 23obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
23obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o 24obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
24obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
26obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
25 27
26nand-objs = nand_base.o nand_bbt.o 28nand-objs := nand_base.o nand_bbt.o
29cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
new file mode 100644
index 000000000000..14b80cc90a7b
--- /dev/null
+++ b/drivers/mtd/nand/at91_nand.c
@@ -0,0 +1,223 @@
1/*
2 * drivers/mtd/nand/at91_nand.c
3 *
4 * Copyright (C) 2003 Rick Bronson
5 *
6 * Derived from drivers/mtd/nand/autcpu12.c
7 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
8 *
9 * Derived from drivers/mtd/spia.c
10 * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/nand.h>
23#include <linux/mtd/partitions.h>
24
25#include <asm/io.h>
26#include <asm/sizes.h>
27
28#include <asm/hardware.h>
29#include <asm/arch/board.h>
30#include <asm/arch/gpio.h>
31
32struct at91_nand_host {
33 struct nand_chip nand_chip;
34 struct mtd_info mtd;
35 void __iomem *io_base;
36 struct at91_nand_data *board;
37};
38
39/*
40 * Hardware specific access to control-lines
41 */
42static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
43{
44 struct nand_chip *nand_chip = mtd->priv;
45 struct at91_nand_host *host = nand_chip->priv;
46
47 if (cmd == NAND_CMD_NONE)
48 return;
49
50 if (ctrl & NAND_CLE)
51 writeb(cmd, host->io_base + (1 << host->board->cle));
52 else
53 writeb(cmd, host->io_base + (1 << host->board->ale));
54}
55
56/*
57 * Read the Device Ready pin.
58 */
59static int at91_nand_device_ready(struct mtd_info *mtd)
60{
61 struct nand_chip *nand_chip = mtd->priv;
62 struct at91_nand_host *host = nand_chip->priv;
63
64 return at91_get_gpio_value(host->board->rdy_pin);
65}
66
67/*
68 * Enable NAND.
69 */
70static void at91_nand_enable(struct at91_nand_host *host)
71{
72 if (host->board->enable_pin)
73 at91_set_gpio_value(host->board->enable_pin, 0);
74}
75
76/*
77 * Disable NAND.
78 */
79static void at91_nand_disable(struct at91_nand_host *host)
80{
81 if (host->board->enable_pin)
82 at91_set_gpio_value(host->board->enable_pin, 1);
83}
84
85/*
86 * Probe for the NAND device.
87 */
88static int __init at91_nand_probe(struct platform_device *pdev)
89{
90 struct at91_nand_host *host;
91 struct mtd_info *mtd;
92 struct nand_chip *nand_chip;
93 int res;
94
95#ifdef CONFIG_MTD_PARTITIONS
96 struct mtd_partition *partitions = NULL;
97 int num_partitions = 0;
98#endif
99
100 /* Allocate memory for the device structure (and zero it) */
101 host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
102 if (!host) {
103 printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
104 return -ENOMEM;
105 }
106
107 host->io_base = ioremap(pdev->resource[0].start,
108 pdev->resource[0].end - pdev->resource[0].start + 1);
109 if (host->io_base == NULL) {
110 printk(KERN_ERR "at91_nand: ioremap failed\n");
111 kfree(host);
112 return -EIO;
113 }
114
115 mtd = &host->mtd;
116 nand_chip = &host->nand_chip;
117 host->board = pdev->dev.platform_data;
118
119 nand_chip->priv = host; /* link the private data structures */
120 mtd->priv = nand_chip;
121 mtd->owner = THIS_MODULE;
122
123 /* Set address of NAND IO lines */
124 nand_chip->IO_ADDR_R = host->io_base;
125 nand_chip->IO_ADDR_W = host->io_base;
126 nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
127 nand_chip->dev_ready = at91_nand_device_ready;
128 nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
129 nand_chip->chip_delay = 20; /* 20us command delay time */
130
131 if (host->board->bus_width_16) /* 16-bit bus width */
132 nand_chip->options |= NAND_BUSWIDTH_16;
133
134 platform_set_drvdata(pdev, host);
135 at91_nand_enable(host);
136
137 if (host->board->det_pin) {
138 if (at91_get_gpio_value(host->board->det_pin)) {
139 printk ("No SmartMedia card inserted.\n");
140 res = ENXIO;
141 goto out;
142 }
143 }
144
145 /* Scan to find existance of the device */
146 if (nand_scan(mtd, 1)) {
147 res = -ENXIO;
148 goto out;
149 }
150
151#ifdef CONFIG_MTD_PARTITIONS
152 if (host->board->partition_info)
153 partitions = host->board->partition_info(mtd->size, &num_partitions);
154
155 if ((!partitions) || (num_partitions == 0)) {
156 printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
157 res = ENXIO;
158 goto release;
159 }
160
161 res = add_mtd_partitions(mtd, partitions, num_partitions);
162#else
163 res = add_mtd_device(mtd);
164#endif
165
166 if (!res)
167 return res;
168
169release:
170 nand_release(mtd);
171out:
172 at91_nand_disable(host);
173 platform_set_drvdata(pdev, NULL);
174 iounmap(host->io_base);
175 kfree(host);
176 return res;
177}
178
179/*
180 * Remove a NAND device.
181 */
182static int __devexit at91_nand_remove(struct platform_device *pdev)
183{
184 struct at91_nand_host *host = platform_get_drvdata(pdev);
185 struct mtd_info *mtd = &host->mtd;
186
187 nand_release(mtd);
188
189 at91_nand_disable(host);
190
191 iounmap(host->io_base);
192 kfree(host);
193
194 return 0;
195}
196
197static struct platform_driver at91_nand_driver = {
198 .probe = at91_nand_probe,
199 .remove = at91_nand_remove,
200 .driver = {
201 .name = "at91_nand",
202 .owner = THIS_MODULE,
203 },
204};
205
206static int __init at91_nand_init(void)
207{
208 return platform_driver_register(&at91_nand_driver);
209}
210
211
212static void __exit at91_nand_exit(void)
213{
214 platform_driver_unregister(&at91_nand_driver);
215}
216
217
218module_init(at91_nand_init);
219module_exit(at91_nand_exit);
220
221MODULE_LICENSE("GPL");
222MODULE_AUTHOR("Rick Bronson");
223MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
new file mode 100644
index 000000000000..b8d9b64cccc0
--- /dev/null
+++ b/drivers/mtd/nand/cafe.c
@@ -0,0 +1,770 @@
1/*
2 * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
3 *
4 * Copyright © 2006 Red Hat, Inc.
5 * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
6 */
7
8#define DEBUG
9
10#include <linux/device.h>
11#undef DEBUG
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/nand.h>
14#include <linux/pci.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <asm/io.h>
18
19#define CAFE_NAND_CTRL1 0x00
20#define CAFE_NAND_CTRL2 0x04
21#define CAFE_NAND_CTRL3 0x08
22#define CAFE_NAND_STATUS 0x0c
23#define CAFE_NAND_IRQ 0x10
24#define CAFE_NAND_IRQ_MASK 0x14
25#define CAFE_NAND_DATA_LEN 0x18
26#define CAFE_NAND_ADDR1 0x1c
27#define CAFE_NAND_ADDR2 0x20
28#define CAFE_NAND_TIMING1 0x24
29#define CAFE_NAND_TIMING2 0x28
30#define CAFE_NAND_TIMING3 0x2c
31#define CAFE_NAND_NONMEM 0x30
32#define CAFE_NAND_ECC_RESULT 0x3C
33#define CAFE_NAND_DMA_CTRL 0x40
34#define CAFE_NAND_DMA_ADDR0 0x44
35#define CAFE_NAND_DMA_ADDR1 0x48
36#define CAFE_NAND_ECC_SYN01 0x50
37#define CAFE_NAND_ECC_SYN23 0x54
38#define CAFE_NAND_ECC_SYN45 0x58
39#define CAFE_NAND_ECC_SYN67 0x5c
40#define CAFE_NAND_READ_DATA 0x1000
41#define CAFE_NAND_WRITE_DATA 0x2000
42
43#define CAFE_GLOBAL_CTRL 0x3004
44#define CAFE_GLOBAL_IRQ 0x3008
45#define CAFE_GLOBAL_IRQ_MASK 0x300c
46#define CAFE_NAND_RESET 0x3034
47
48int cafe_correct_ecc(unsigned char *buf,
49 unsigned short *chk_syndrome_list);
50
51struct cafe_priv {
52 struct nand_chip nand;
53 struct pci_dev *pdev;
54 void __iomem *mmio;
55 uint32_t ctl1;
56 uint32_t ctl2;
57 int datalen;
58 int nr_data;
59 int data_pos;
60 int page_addr;
61 dma_addr_t dmaaddr;
62 unsigned char *dmabuf;
63};
64
65static int usedma = 1;
66module_param(usedma, int, 0644);
67
68static int skipbbt = 0;
69module_param(skipbbt, int, 0644);
70
71static int debug = 0;
72module_param(debug, int, 0644);
73
74static int regdebug = 0;
75module_param(regdebug, int, 0644);
76
77static int checkecc = 1;
78module_param(checkecc, int, 0644);
79
80static int slowtiming = 0;
81module_param(slowtiming, int, 0644);
82
83/* Hrm. Why isn't this already conditional on something in the struct device? */
84#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
85
86/* Make it easier to switch to PIO if we need to */
87#define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr)
88#define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr)
89
90static int cafe_device_ready(struct mtd_info *mtd)
91{
92 struct cafe_priv *cafe = mtd->priv;
93 int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000);
94 uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
95
96 cafe_writel(cafe, irqs, NAND_IRQ);
97
98 cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
99 result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ),
100 cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK));
101
102 return result;
103}
104
105
106static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
107{
108 struct cafe_priv *cafe = mtd->priv;
109
110 if (usedma)
111 memcpy(cafe->dmabuf + cafe->datalen, buf, len);
112 else
113 memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len);
114
115 cafe->datalen += len;
116
117 cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
118 len, cafe->datalen);
119}
120
121static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
122{
123 struct cafe_priv *cafe = mtd->priv;
124
125 if (usedma)
126 memcpy(buf, cafe->dmabuf + cafe->datalen, len);
127 else
128 memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len);
129
130 cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
131 len, cafe->datalen);
132 cafe->datalen += len;
133}
134
135static uint8_t cafe_read_byte(struct mtd_info *mtd)
136{
137 struct cafe_priv *cafe = mtd->priv;
138 uint8_t d;
139
140 cafe_read_buf(mtd, &d, 1);
141 cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
142
143 return d;
144}
145
146static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
147 int column, int page_addr)
148{
149 struct cafe_priv *cafe = mtd->priv;
150 int adrbytes = 0;
151 uint32_t ctl1;
152 uint32_t doneint = 0x80000000;
153
154 cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
155 command, column, page_addr);
156
157 if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
158 /* Second half of a command we already calculated */
159 cafe_writel(cafe, cafe->ctl2 | 0x100 | command, NAND_CTRL2);
160 ctl1 = cafe->ctl1;
161 cafe->ctl2 &= ~(1<<30);
162 cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
163 cafe->ctl1, cafe->nr_data);
164 goto do_command;
165 }
166 /* Reset ECC engine */
167 cafe_writel(cafe, 0, NAND_CTRL2);
168
169 /* Emulate NAND_CMD_READOOB on large-page chips */
170 if (mtd->writesize > 512 &&
171 command == NAND_CMD_READOOB) {
172 column += mtd->writesize;
173 command = NAND_CMD_READ0;
174 }
175
176 /* FIXME: Do we need to send read command before sending data
177 for small-page chips, to position the buffer correctly? */
178
179 if (column != -1) {
180 cafe_writel(cafe, column, NAND_ADDR1);
181 adrbytes = 2;
182 if (page_addr != -1)
183 goto write_adr2;
184 } else if (page_addr != -1) {
185 cafe_writel(cafe, page_addr & 0xffff, NAND_ADDR1);
186 page_addr >>= 16;
187 write_adr2:
188 cafe_writel(cafe, page_addr, NAND_ADDR2);
189 adrbytes += 2;
190 if (mtd->size > mtd->writesize << 16)
191 adrbytes++;
192 }
193
194 cafe->data_pos = cafe->datalen = 0;
195
196 /* Set command valid bit */
197 ctl1 = 0x80000000 | command;
198
199 /* Set RD or WR bits as appropriate */
200 if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
201 ctl1 |= (1<<26); /* rd */
202 /* Always 5 bytes, for now */
203 cafe->datalen = 4;
204 /* And one address cycle -- even for STATUS, since the controller doesn't work without */
205 adrbytes = 1;
206 } else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
207 command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) {
208 ctl1 |= 1<<26; /* rd */
209 /* For now, assume just read to end of page */
210 cafe->datalen = mtd->writesize + mtd->oobsize - column;
211 } else if (command == NAND_CMD_SEQIN)
212 ctl1 |= 1<<25; /* wr */
213
214 /* Set number of address bytes */
215 if (adrbytes)
216 ctl1 |= ((adrbytes-1)|8) << 27;
217
218 if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) {
219 /* Ignore the first command of a pair; the hardware
220 deals with them both at once, later */
221 cafe->ctl1 = ctl1;
222 cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
223 cafe->ctl1, cafe->datalen);
224 return;
225 }
226 /* RNDOUT and READ0 commands need a following byte */
227 if (command == NAND_CMD_RNDOUT)
228 cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_RNDOUTSTART, NAND_CTRL2);
229 else if (command == NAND_CMD_READ0 && mtd->writesize > 512)
230 cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_READSTART, NAND_CTRL2);
231
232 do_command:
233 cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
234 cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2));
235
236 /* NB: The datasheet lies -- we really should be subtracting 1 here */
237 cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN);
238 cafe_writel(cafe, 0x90000000, NAND_IRQ);
239 if (usedma && (ctl1 & (3<<25))) {
240 uint32_t dmactl = 0xc0000000 + cafe->datalen;
241 /* If WR or RD bits set, set up DMA */
242 if (ctl1 & (1<<26)) {
243 /* It's a read */
244 dmactl |= (1<<29);
245 /* ... so it's done when the DMA is done, not just
246 the command. */
247 doneint = 0x10000000;
248 }
249 cafe_writel(cafe, dmactl, NAND_DMA_CTRL);
250 }
251 cafe->datalen = 0;
252
253 if (unlikely(regdebug)) {
254 int i;
255 printk("About to write command %08x to register 0\n", ctl1);
256 for (i=4; i< 0x5c; i+=4)
257 printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
258 }
259
260 cafe_writel(cafe, ctl1, NAND_CTRL1);
261 /* Apply this short delay always to ensure that we do wait tWB in
262 * any case on any machine. */
263 ndelay(100);
264
265 if (1) {
266 int c = 500000;
267 uint32_t irqs;
268
269 while (c--) {
270 irqs = cafe_readl(cafe, NAND_IRQ);
271 if (irqs & doneint)
272 break;
273 udelay(1);
274 if (!(c % 100000))
275 cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
276 cpu_relax();
277 }
278 cafe_writel(cafe, doneint, NAND_IRQ);
279 cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
280 command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
281 }
282
283 WARN_ON(cafe->ctl2 & (1<<30));
284
285 switch (command) {
286
287 case NAND_CMD_CACHEDPROG:
288 case NAND_CMD_PAGEPROG:
289 case NAND_CMD_ERASE1:
290 case NAND_CMD_ERASE2:
291 case NAND_CMD_SEQIN:
292 case NAND_CMD_RNDIN:
293 case NAND_CMD_STATUS:
294 case NAND_CMD_DEPLETE1:
295 case NAND_CMD_RNDOUT:
296 case NAND_CMD_STATUS_ERROR:
297 case NAND_CMD_STATUS_ERROR0:
298 case NAND_CMD_STATUS_ERROR1:
299 case NAND_CMD_STATUS_ERROR2:
300 case NAND_CMD_STATUS_ERROR3:
301 cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
302 return;
303 }
304 nand_wait_ready(mtd);
305 cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
306}
307
308static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
309{
310 //struct cafe_priv *cafe = mtd->priv;
311 // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
312}
313
314static int cafe_nand_interrupt(int irq, void *id)
315{
316 struct mtd_info *mtd = id;
317 struct cafe_priv *cafe = mtd->priv;
318 uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
319 cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
320 if (!irqs)
321 return IRQ_NONE;
322
323 cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
324 return IRQ_HANDLED;
325}
326
327static void cafe_nand_bug(struct mtd_info *mtd)
328{
329 BUG();
330}
331
332static int cafe_nand_write_oob(struct mtd_info *mtd,
333 struct nand_chip *chip, int page)
334{
335 int status = 0;
336
337 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
338 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
339 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
340 status = chip->waitfunc(mtd, chip);
341
342 return status & NAND_STATUS_FAIL ? -EIO : 0;
343}
344
345/* Don't use -- use nand_read_oob_std for now */
346static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
347 int page, int sndcmd)
348{
349 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
350 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
351 return 1;
352}
353/**
354 * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
355 * @mtd: mtd info structure
356 * @chip: nand chip info structure
357 * @buf: buffer to store read data
358 *
359 * The hw generator calculates the error syndrome automatically. Therefor
360 * we need a special oob layout and handling.
361 */
362static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
363 uint8_t *buf)
364{
365 struct cafe_priv *cafe = mtd->priv;
366
367 cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
368 cafe_readl(cafe, NAND_ECC_RESULT),
369 cafe_readl(cafe, NAND_ECC_SYN01));
370
371 chip->read_buf(mtd, buf, mtd->writesize);
372 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
373
374 if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
375 unsigned short syn[8];
376 int i;
377
378 for (i=0; i<8; i+=2) {
379 uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
380 syn[i] = tmp & 0xfff;
381 syn[i+1] = (tmp >> 16) & 0xfff;
382 }
383
384 if ((i = cafe_correct_ecc(buf, syn)) < 0) {
385 dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
386 cafe_readl(cafe, NAND_ADDR2) * 2048);
387 for (i=0; i< 0x5c; i+=4)
388 printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
389 mtd->ecc_stats.failed++;
390 } else {
391 dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i);
392 mtd->ecc_stats.corrected += i;
393 }
394 }
395
396
397 return 0;
398}
399
400static struct nand_ecclayout cafe_oobinfo_2048 = {
401 .eccbytes = 14,
402 .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
403 .oobfree = {{14, 50}}
404};
405
406/* Ick. The BBT code really ought to be able to work this bit out
407 for itself from the above, at least for the 2KiB case */
408static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
409static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
410
411static uint8_t cafe_bbt_pattern_512[] = { 0xBB };
412static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
413
414
415static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
416 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
417 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
418 .offs = 14,
419 .len = 4,
420 .veroffs = 18,
421 .maxblocks = 4,
422 .pattern = cafe_bbt_pattern_2048
423};
424
425static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
426 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
427 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
428 .offs = 14,
429 .len = 4,
430 .veroffs = 18,
431 .maxblocks = 4,
432 .pattern = cafe_mirror_pattern_2048
433};
434
435static struct nand_ecclayout cafe_oobinfo_512 = {
436 .eccbytes = 14,
437 .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
438 .oobfree = {{14, 2}}
439};
440
441static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
442 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
443 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
444 .offs = 14,
445 .len = 1,
446 .veroffs = 15,
447 .maxblocks = 4,
448 .pattern = cafe_bbt_pattern_512
449};
450
451static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
452 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
453 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
454 .offs = 14,
455 .len = 1,
456 .veroffs = 15,
457 .maxblocks = 4,
458 .pattern = cafe_mirror_pattern_512
459};
460
461
462static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
463 struct nand_chip *chip, const uint8_t *buf)
464{
465 struct cafe_priv *cafe = mtd->priv;
466
467 chip->write_buf(mtd, buf, mtd->writesize);
468 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
469
470 /* Set up ECC autogeneration */
471 cafe->ctl2 |= (1<<30);
472}
473
474static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
475 const uint8_t *buf, int page, int cached, int raw)
476{
477 int status;
478
479 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
480
481 if (unlikely(raw))
482 chip->ecc.write_page_raw(mtd, chip, buf);
483 else
484 chip->ecc.write_page(mtd, chip, buf);
485
486 /*
487 * Cached progamming disabled for now, Not sure if its worth the
488 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
489 */
490 cached = 0;
491
492 if (!cached || !(chip->options & NAND_CACHEPRG)) {
493
494 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
495 status = chip->waitfunc(mtd, chip);
496 /*
497 * See if operation failed and additional status checks are
498 * available
499 */
500 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
501 status = chip->errstat(mtd, chip, FL_WRITING, status,
502 page);
503
504 if (status & NAND_STATUS_FAIL)
505 return -EIO;
506 } else {
507 chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
508 status = chip->waitfunc(mtd, chip);
509 }
510
511#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
512 /* Send command to read back the data */
513 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
514
515 if (chip->verify_buf(mtd, buf, mtd->writesize))
516 return -EIO;
517#endif
518 return 0;
519}
520
521static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
522{
523 return 0;
524}
525
526static int __devinit cafe_nand_probe(struct pci_dev *pdev,
527 const struct pci_device_id *ent)
528{
529 struct mtd_info *mtd;
530 struct cafe_priv *cafe;
531 uint32_t ctrl;
532 int err = 0;
533
534 err = pci_enable_device(pdev);
535 if (err)
536 return err;
537
538 pci_set_master(pdev);
539
540 mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
541 if (!mtd) {
542 dev_warn(&pdev->dev, "failed to alloc mtd_info\n");
543 return -ENOMEM;
544 }
545 cafe = (void *)(&mtd[1]);
546
547 mtd->priv = cafe;
548 mtd->owner = THIS_MODULE;
549
550 cafe->pdev = pdev;
551 cafe->mmio = pci_iomap(pdev, 0, 0);
552 if (!cafe->mmio) {
553 dev_warn(&pdev->dev, "failed to iomap\n");
554 err = -ENOMEM;
555 goto out_free_mtd;
556 }
557 cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers),
558 &cafe->dmaaddr, GFP_KERNEL);
559 if (!cafe->dmabuf) {
560 err = -ENOMEM;
561 goto out_ior;
562 }
563 cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
564
565 cafe->nand.cmdfunc = cafe_nand_cmdfunc;
566 cafe->nand.dev_ready = cafe_device_ready;
567 cafe->nand.read_byte = cafe_read_byte;
568 cafe->nand.read_buf = cafe_read_buf;
569 cafe->nand.write_buf = cafe_write_buf;
570 cafe->nand.select_chip = cafe_select_chip;
571
572 cafe->nand.chip_delay = 0;
573
574 /* Enable the following for a flash based bad block table */
575 cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
576
577 if (skipbbt) {
578 cafe->nand.options |= NAND_SKIP_BBTSCAN;
579 cafe->nand.block_bad = cafe_nand_block_bad;
580 }
581
582 /* Start off by resetting the NAND controller completely */
583 cafe_writel(cafe, 1, NAND_RESET);
584 cafe_writel(cafe, 0, NAND_RESET);
585
586 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
587
588 /* Timings from Marvell's test code (not verified or calculated by us) */
589 if (!slowtiming) {
590 cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
591 cafe_writel(cafe, 0x24121212, NAND_TIMING2);
592 cafe_writel(cafe, 0x11000000, NAND_TIMING3);
593 } else {
594 cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
595 cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
596 cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
597 }
598 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
599 err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd);
600 if (err) {
601 dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
602
603 goto out_free_dma;
604 }
605#if 1
606 /* Disable master reset, enable NAND clock */
607 ctrl = cafe_readl(cafe, GLOBAL_CTRL);
608 ctrl &= 0xffffeff0;
609 ctrl |= 0x00007000;
610 cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
611 cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
612 cafe_writel(cafe, 0, NAND_DMA_CTRL);
613
614 cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
615 cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
616
617 /* Set up DMA address */
618 cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
619 if (sizeof(cafe->dmaaddr) > 4)
620 /* Shift in two parts to shut the compiler up */
621 cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
622 else
623 cafe_writel(cafe, 0, NAND_DMA_ADDR1);
624
625 cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
626 cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
627
628 /* Enable NAND IRQ in global IRQ mask register */
629 cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
630 cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
631 cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
632#endif
633#if 1
634 mtd->writesize=2048;
635 mtd->oobsize = 0x40;
636 memset(cafe->dmabuf, 0x5a, 2112);
637 cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
638 cafe->nand.read_byte(mtd);
639 cafe->nand.read_byte(mtd);
640 cafe->nand.read_byte(mtd);
641 cafe->nand.read_byte(mtd);
642 cafe->nand.read_byte(mtd);
643#endif
644#if 0
645 cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
646 // nand_wait_ready(mtd);
647 cafe->nand.read_byte(mtd);
648 cafe->nand.read_byte(mtd);
649 cafe->nand.read_byte(mtd);
650 cafe->nand.read_byte(mtd);
651#endif
652#if 0
653 writel(0x84600070, cafe->mmio);
654 udelay(10);
655 cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
656#endif
657 /* Scan to find existance of the device */
658 if (nand_scan_ident(mtd, 1)) {
659 err = -ENXIO;
660 goto out_irq;
661 }
662
663 cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
664 if (mtd->writesize == 2048)
665 cafe->ctl2 |= 1<<29; /* 2KiB page size */
666
667 /* Set up ECC according to the type of chip we found */
668 if (mtd->writesize == 2048) {
669 cafe->nand.ecc.layout = &cafe_oobinfo_2048;
670 cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
671 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
672 } else if (mtd->writesize == 512) {
673 cafe->nand.ecc.layout = &cafe_oobinfo_512;
674 cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
675 cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
676 } else {
677 printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
678 mtd->writesize);
679 goto out_irq;
680 }
681 cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
682 cafe->nand.ecc.size = mtd->writesize;
683 cafe->nand.ecc.bytes = 14;
684 cafe->nand.ecc.hwctl = (void *)cafe_nand_bug;
685 cafe->nand.ecc.calculate = (void *)cafe_nand_bug;
686 cafe->nand.ecc.correct = (void *)cafe_nand_bug;
687 cafe->nand.write_page = cafe_nand_write_page;
688 cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
689 cafe->nand.ecc.write_oob = cafe_nand_write_oob;
690 cafe->nand.ecc.read_page = cafe_nand_read_page;
691 cafe->nand.ecc.read_oob = cafe_nand_read_oob;
692
693 err = nand_scan_tail(mtd);
694 if (err)
695 goto out_irq;
696
697 pci_set_drvdata(pdev, mtd);
698 add_mtd_device(mtd);
699 goto out;
700
701 out_irq:
702 /* Disable NAND IRQ in global IRQ mask register */
703 cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
704 free_irq(pdev->irq, mtd);
705 out_free_dma:
706 dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
707 out_ior:
708 pci_iounmap(pdev, cafe->mmio);
709 out_free_mtd:
710 kfree(mtd);
711 out:
712 return err;
713}
714
715static void __devexit cafe_nand_remove(struct pci_dev *pdev)
716{
717 struct mtd_info *mtd = pci_get_drvdata(pdev);
718 struct cafe_priv *cafe = mtd->priv;
719
720 del_mtd_device(mtd);
721 /* Disable NAND IRQ in global IRQ mask register */
722 cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
723 free_irq(pdev->irq, mtd);
724 nand_release(mtd);
725 pci_iounmap(pdev, cafe->mmio);
726 dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
727 kfree(mtd);
728}
729
730static struct pci_device_id cafe_nand_tbl[] = {
731 { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
732};
733
734MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
735
736static struct pci_driver cafe_nand_pci_driver = {
737 .name = "CAFÉ NAND",
738 .id_table = cafe_nand_tbl,
739 .probe = cafe_nand_probe,
740 .remove = __devexit_p(cafe_nand_remove),
741#ifdef CONFIG_PMx
742 .suspend = cafe_nand_suspend,
743 .resume = cafe_nand_resume,
744#endif
745};
746
747static int cafe_nand_init(void)
748{
749 return pci_register_driver(&cafe_nand_pci_driver);
750}
751
752static void cafe_nand_exit(void)
753{
754 pci_unregister_driver(&cafe_nand_pci_driver);
755}
756module_init(cafe_nand_init);
757module_exit(cafe_nand_exit);
758
759MODULE_LICENSE("GPL");
760MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
761MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
762
763/* Correct ECC for 2048 bytes of 0xff:
764 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
765
766/* dwmw2's B-test board, in case of completely screwing it:
767Bad eraseblock 2394 at 0x12b40000
768Bad eraseblock 2627 at 0x14860000
769Bad eraseblock 3349 at 0x1a2a0000
770*/
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
new file mode 100644
index 000000000000..1b9fa05a4474
--- /dev/null
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -0,0 +1,1381 @@
1/* Error correction for CAFÉ NAND controller
2 *
3 * © 2006 Marvell, Inc.
4 * Author: Tom Chiou
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/errno.h>
24
25static unsigned short gf4096_mul(unsigned short, unsigned short);
26static unsigned short gf64_mul(unsigned short, unsigned short);
27static unsigned short gf4096_inv(unsigned short);
28static unsigned short err_pos(unsigned short);
29static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short,
30 unsigned short, unsigned short, unsigned short,
31 unsigned short, unsigned short, unsigned short *);
32static void zero_4x5_col3(unsigned short[4][5]);
33static void zero_4x5_col2(unsigned short[4][5]);
34static void zero_4x5_col1(unsigned short[4][5]);
35static void swap_4x5_rows(unsigned short[4][5], int, int, int);
36static void swap_2x3_rows(unsigned short m[2][3]);
37static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
38static void sort_coefs(int *, unsigned short *, int);
39static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short,
40 unsigned short, unsigned short, unsigned short,
41 unsigned short, unsigned short, unsigned short *);
42static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
43 unsigned short, unsigned short, unsigned short,
44 unsigned short *);
45static void zero_3x4_col2(unsigned short[3][4]);
46static void zero_3x4_col1(unsigned short[3][4]);
47static void swap_3x4_rows(unsigned short[3][4], int, int, int);
48static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
49static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
50 unsigned short, unsigned short, unsigned short,
51 unsigned short *);
52
53static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
54 unsigned short, unsigned short *);
55static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
56 unsigned short, unsigned short, unsigned short,
57 unsigned short *);
58static void solve_2x3(unsigned short[2][3], unsigned short *);
59static int chk_no_err_only(unsigned short *, unsigned short *);
60static int chk_1_err_only(unsigned short *, unsigned short *);
61static int chk_2_err_only(unsigned short *, unsigned short *);
62static int chk_3_err_only(unsigned short *, unsigned short *);
63static int chk_4_err_only(unsigned short *, unsigned short *);
64
65static unsigned short gf64_mul(unsigned short a, unsigned short b)
66{
67 unsigned short tmp1, tmp2, tmp3, tmp4, tmp5;
68 unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c;
69
70 tmp1 = ((a) ^ (a >> 5));
71 tmp2 = ((a >> 4) ^ (a >> 5));
72 tmp3 = ((a >> 3) ^ (a >> 4));
73 tmp4 = ((a >> 2) ^ (a >> 3));
74 tmp5 = ((a >> 1) ^ (a >> 2));
75
76 c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^
77 ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1;
78
79 c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^
80 (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1;
81
82 c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^
83 (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1;
84
85 c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^
86 (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1;
87
88 c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^
89 ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1;
90
91 c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^
92 ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1;
93
94 c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5);
95
96 return c;
97}
98
99static unsigned short gf4096_mul(unsigned short a, unsigned short b)
100{
101 unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c;
102
103 ah = (a >> 6) & 0x3f;
104 al = a & 0x3f;
105 bh = (b >> 6) & 0x3f;
106 bl = b & 0x3f;
107 alxah = al ^ ah;
108 blxbh = bl ^ bh;
109
110 ablh = gf64_mul(alxah, blxbh);
111 albl = gf64_mul(al, bl);
112 ahbh = gf64_mul(ah, bh);
113
114 ahbhB = ((ahbh & 0x1) << 5) |
115 ((ahbh & 0x20) >> 1) |
116 ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1);
117
118 c = ((ablh ^ albl) << 6) | (ahbhB ^ albl);
119 return c;
120}
121
122static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats)
123{
124 find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats);
125}
126
127static void find_3bit_err_coefs(unsigned short s0, unsigned short s1,
128 unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs)
129{
130 unsigned short m[3][4];
131 int row_order[3];
132
133 row_order[0] = 0;
134 row_order[1] = 1;
135 row_order[2] = 2;
136 m[0][0] = s2;
137 m[0][1] = s1;
138 m[0][2] = s0;
139 m[0][3] = s3;
140 m[1][0] = s3;
141 m[1][1] = s2;
142 m[1][2] = s1;
143 m[1][3] = s4;
144 m[2][0] = s4;
145 m[2][1] = s3;
146 m[2][2] = s2;
147 m[2][3] = s5;
148
149 if (m[0][2] != 0x0) {
150 zero_3x4_col2(m);
151 } else if (m[1][2] != 0x0) {
152 swap_3x4_rows(m, 0, 1, 4);
153 zero_3x4_col2(m);
154 } else if (m[2][2] != 0x0) {
155 swap_3x4_rows(m, 0, 2, 4);
156 zero_3x4_col2(m);
157 } else {
158 printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n");
159 }
160
161 if (m[1][1] != 0x0) {
162 zero_3x4_col1(m);
163 } else if (m[2][1] != 0x0) {
164 swap_3x4_rows(m, 1, 2, 4);
165 zero_3x4_col1(m);
166 } else {
167 printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n");
168 }
169
170 /* solve coefs */
171 solve_3x4(m, coefs, row_order);
172}
173
174static void zero_3x4_col2(unsigned short m[3][4])
175{
176 unsigned short minv1, minv2;
177
178 minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2]));
179 minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2]));
180 m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
181 m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
182 m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1);
183 m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
184 m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
185 m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2);
186}
187
188static void zero_3x4_col1(unsigned short m[3][4])
189{
190 unsigned short minv;
191 minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1]));
192 m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv);
193 m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv);
194}
195
196static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width)
197{
198 unsigned short tmp0;
199 int cnt;
200 for (cnt = 0; cnt < col_width; cnt++) {
201 tmp0 = m[i][cnt];
202 m[i][cnt] = m[j][cnt];
203 m[j][cnt] = tmp0;
204 }
205}
206
207static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order)
208{
209 unsigned short tmp[3];
210 tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0]));
211 tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1]));
212 tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2]));
213 sort_coefs(row_order, tmp, 3);
214 coefs[0] = tmp[0];
215 coefs[1] = tmp[1];
216 coefs[2] = tmp[2];
217}
218
219static void find_3bit_err_pats(unsigned short s0, unsigned short s1,
220 unsigned short s2, unsigned short r0,
221 unsigned short r1, unsigned short r2,
222 unsigned short *pats)
223{
224 find_2x2_soln(r0 ^ r2, r1 ^ r2,
225 gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2),
226 gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats);
227 pats[2] = s0 ^ pats[0] ^ pats[1];
228}
229
230static void find_4bit_err_coefs(unsigned short s0, unsigned short s1,
231 unsigned short s2, unsigned short s3,
232 unsigned short s4, unsigned short s5,
233 unsigned short s6, unsigned short s7,
234 unsigned short *coefs)
235{
236 unsigned short m[4][5];
237 int row_order[4];
238
239 row_order[0] = 0;
240 row_order[1] = 1;
241 row_order[2] = 2;
242 row_order[3] = 3;
243
244 m[0][0] = s3;
245 m[0][1] = s2;
246 m[0][2] = s1;
247 m[0][3] = s0;
248 m[0][4] = s4;
249 m[1][0] = s4;
250 m[1][1] = s3;
251 m[1][2] = s2;
252 m[1][3] = s1;
253 m[1][4] = s5;
254 m[2][0] = s5;
255 m[2][1] = s4;
256 m[2][2] = s3;
257 m[2][3] = s2;
258 m[2][4] = s6;
259 m[3][0] = s6;
260 m[3][1] = s5;
261 m[3][2] = s4;
262 m[3][3] = s3;
263 m[3][4] = s7;
264
265 if (m[0][3] != 0x0) {
266 zero_4x5_col3(m);
267 } else if (m[1][3] != 0x0) {
268 swap_4x5_rows(m, 0, 1, 5);
269 zero_4x5_col3(m);
270 } else if (m[2][3] != 0x0) {
271 swap_4x5_rows(m, 0, 2, 5);
272 zero_4x5_col3(m);
273 } else if (m[3][3] != 0x0) {
274 swap_4x5_rows(m, 0, 3, 5);
275 zero_4x5_col3(m);
276 } else {
277 printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n");
278 }
279
280 if (m[1][2] != 0x0) {
281 zero_4x5_col2(m);
282 } else if (m[2][2] != 0x0) {
283 swap_4x5_rows(m, 1, 2, 5);
284 zero_4x5_col2(m);
285 } else if (m[3][2] != 0x0) {
286 swap_4x5_rows(m, 1, 3, 5);
287 zero_4x5_col2(m);
288 } else {
289 printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n");
290 }
291
292 if (m[2][1] != 0x0) {
293 zero_4x5_col1(m);
294 } else if (m[3][1] != 0x0) {
295 swap_4x5_rows(m, 2, 3, 5);
296 zero_4x5_col1(m);
297 } else {
298 printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n");
299 }
300
301 solve_4x5(m, coefs, row_order);
302}
303
304static void zero_4x5_col3(unsigned short m[4][5])
305{
306 unsigned short minv1, minv2, minv3;
307
308 minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3]));
309 minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3]));
310 minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3]));
311
312 m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
313 m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
314 m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1);
315 m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1);
316 m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
317 m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
318 m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2);
319 m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2);
320 m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3);
321 m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3);
322 m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3);
323 m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3);
324}
325
326static void zero_4x5_col2(unsigned short m[4][5])
327{
328 unsigned short minv2, minv3;
329
330 minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2]));
331 minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2]));
332
333 m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2);
334 m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2);
335 m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2);
336 m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3);
337 m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3);
338 m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3);
339}
340
341static void zero_4x5_col1(unsigned short m[4][5])
342{
343 unsigned short minv;
344
345 minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1]));
346
347 m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv);
348 m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv);
349}
350
351static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width)
352{
353 unsigned short tmp0;
354 int cnt;
355
356 for (cnt = 0; cnt < col_width; cnt++) {
357 tmp0 = m[i][cnt];
358 m[i][cnt] = m[j][cnt];
359 m[j][cnt] = tmp0;
360 }
361}
362
363static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order)
364{
365 unsigned short tmp[4];
366
367 tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0]));
368 tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1]));
369 tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2]));
370 tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^
371 gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3]));
372 sort_coefs(row_order, tmp, 4);
373 coefs[0] = tmp[0];
374 coefs[1] = tmp[1];
375 coefs[2] = tmp[2];
376 coefs[3] = tmp[3];
377}
378
379static void sort_coefs(int *order, unsigned short *soln, int len)
380{
381 int cnt, start_cnt, least_ord, least_cnt;
382 unsigned short tmp0;
383 for (start_cnt = 0; start_cnt < len; start_cnt++) {
384 for (cnt = start_cnt; cnt < len; cnt++) {
385 if (cnt == start_cnt) {
386 least_ord = order[cnt];
387 least_cnt = start_cnt;
388 } else {
389 if (least_ord > order[cnt]) {
390 least_ord = order[cnt];
391 least_cnt = cnt;
392 }
393 }
394 }
395 if (least_cnt != start_cnt) {
396 tmp0 = order[least_cnt];
397 order[least_cnt] = order[start_cnt];
398 order[start_cnt] = tmp0;
399 tmp0 = soln[least_cnt];
400 soln[least_cnt] = soln[start_cnt];
401 soln[start_cnt] = tmp0;
402 }
403 }
404}
405
406static void find_4bit_err_pats(unsigned short s0, unsigned short s1,
407 unsigned short s2, unsigned short s3,
408 unsigned short z1, unsigned short z2,
409 unsigned short z3, unsigned short z4,
410 unsigned short *pats)
411{
412 unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1,
413 z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3;
414 unsigned short tmp0, tmp1, tmp2, tmp3;
415
416 z4_z1 = z4 ^ z1;
417 z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3);
418 z4_z2 = z4 ^ z2;
419 s0z4_s1 = gf4096_mul(s0, z4) ^ s1;
420 z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1);
421 z4_z3 = z4 ^ z3;
422 z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2);
423 s1z4_s2 = gf4096_mul(s1, z4) ^ s2;
424 z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3);
425 z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1);
426 z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2);
427 s2z4_s3 = gf4096_mul(s2, z4) ^ s3;
428
429 //find err pat 0,1
430 find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^
431 gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2,
432 z3z4_z3z3) ^
433 gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1,
434 z3z3z4_z3z3z3) ^
435 gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3),
436 gf4096_mul(z2z4_z2z2,
437 z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2,
438 z3z4_z3z3),
439 gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2,
440 z4_z3),
441 gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats);
442 tmp0 = pats[0];
443 tmp1 = pats[1];
444 tmp2 = pats[0] ^ pats[1] ^ s0;
445 tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1;
446
447 //find err pat 2,3
448 find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats);
449 pats[2] = pats[0];
450 pats[3] = pats[1];
451 pats[0] = tmp0;
452 pats[1] = tmp1;
453}
454
455static void find_2x2_soln(unsigned short c00, unsigned short c01,
456 unsigned short c10, unsigned short c11,
457 unsigned short lval0, unsigned short lval1,
458 unsigned short *soln)
459{
460 unsigned short m[2][3];
461 m[0][0] = c00;
462 m[0][1] = c01;
463 m[0][2] = lval0;
464 m[1][0] = c10;
465 m[1][1] = c11;
466 m[1][2] = lval1;
467
468 if (m[0][1] != 0x0) {
469 /* */
470 } else if (m[1][1] != 0x0) {
471 swap_2x3_rows(m);
472 } else {
473 printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n");
474 }
475
476 solve_2x3(m, soln);
477}
478
479static void swap_2x3_rows(unsigned short m[2][3])
480{
481 unsigned short tmp0;
482 int cnt;
483
484 for (cnt = 0; cnt < 3; cnt++) {
485 tmp0 = m[0][cnt];
486 m[0][cnt] = m[1][cnt];
487 m[1][cnt] = tmp0;
488 }
489}
490
491static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
492{
493 unsigned short minv;
494
495 minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1]));
496 m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv);
497 m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv);
498 coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0]));
499 coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1]));
500}
501
502static unsigned char gf64_inv[64] = {
503 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
504 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6,
505 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41,
506 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32
507};
508
509static unsigned short gf4096_inv(unsigned short din)
510{
511 unsigned short alahxal, ah2B, deno, inv, bl, bh;
512 unsigned short ah, al, ahxal;
513 unsigned short dout;
514
515 ah = (din >> 6) & 0x3f;
516 al = din & 0x3f;
517 ahxal = ah ^ al;
518 ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) |
519 ((ah >> 1) & 0x10) |
520 ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) |
521 ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1);
522 alahxal = gf64_mul(ahxal, al);
523 deno = alahxal ^ ah2B;
524 inv = gf64_inv[deno];
525 bl = gf64_mul(inv, ahxal);
526 bh = gf64_mul(inv, ah);
527 dout = ((bh & 0x3f) << 6) | (bl & 0x3f);
528 return (((bh & 0x3f) << 6) | (bl & 0x3f));
529}
530
531static unsigned short err_pos_lut[4096] = {
532 0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041,
533 0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff,
534 0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff,
535 0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7,
536 0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff,
537 0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
538 0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff,
539 0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
540 0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff,
541 0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1,
542 0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff,
543 0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
544 0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff,
545 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7,
546 0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff,
547 0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
548 0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
549 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff,
550 0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff,
551 0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d,
552 0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f,
553 0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8,
554 0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
555 0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe,
556 0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff,
557 0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff,
558 0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1,
559 0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff,
560 0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff,
561 0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff,
562 0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff,
563 0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff,
564 0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff,
565 0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff,
566 0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff,
567 0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8,
568 0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e,
569 0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff,
570 0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff,
571 0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff,
572 0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff,
573 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535,
574 0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
575 0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482,
576 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff,
577 0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff,
578 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
579 0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d,
580 0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff,
581 0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5,
582 0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff,
583 0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294,
584 0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130,
585 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
586 0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
587 0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff,
588 0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff,
589 0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
590 0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
591 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
592 0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
593 0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff,
594 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4,
595 0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f,
596 0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b,
597 0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff,
598 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff,
599 0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff,
600 0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff,
601 0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff,
602 0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff,
603 0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff,
604 0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff,
605 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff,
606 0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158,
607 0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a,
608 0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff,
609 0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff,
610 0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff,
611 0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017,
612 0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a,
613 0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351,
614 0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff,
615 0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3,
616 0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff,
617 0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074,
618 0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff,
619 0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c,
620 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262,
621 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da,
622 0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433,
623 0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285,
624 0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff,
625 0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d,
626 0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff,
627 0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
628 0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
629 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
630 0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff,
631 0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff,
632 0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331,
633 0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8,
634 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
635 0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff,
636 0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6,
637 0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff,
638 0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3,
639 0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff,
640 0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff,
641 0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff,
642 0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
643 0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff,
644 0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf,
645 0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff,
646 0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff,
647 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff,
648 0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc,
649 0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
650 0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381,
651 0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff,
652 0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
653 0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f,
654 0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff,
655 0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488,
656 0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442,
657 0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6,
658 0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1,
659 0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae,
660 0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff,
661 0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff,
662 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff,
663 0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff,
664 0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff,
665 0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2,
666 0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec,
667 0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff,
668 0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134,
669 0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b,
670 0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff,
671 0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff,
672 0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff,
673 0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff,
674 0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5,
675 0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff,
676 0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e,
677 0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff,
678 0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff,
679 0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff,
680 0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2,
681 0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff,
682 0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff,
683 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff,
684 0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff,
685 0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff,
686 0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff,
687 0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
688 0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff,
689 0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff,
690 0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
691 0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff,
692 0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8,
693 0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb,
694 0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff,
695 0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff,
696 0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
697 0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260,
698 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd,
699 0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
700 0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff,
701 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
702 0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
703 0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff,
704 0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
705 0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff,
706 0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff,
707 0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8,
708 0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424,
709 0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9,
710 0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f,
711 0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff,
712 0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff,
713 0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7,
714 0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff,
715 0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d,
716 0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff,
717 0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178,
718 0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff,
719 0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba,
720 0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff,
721 0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff,
722 0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff,
723 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e,
724 0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
725 0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff,
726 0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057,
727 0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6,
728 0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff,
729 0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff,
730 0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff,
731 0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff,
732 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc,
733 0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6,
734 0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f,
735 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5,
736 0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff,
737 0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff,
738 0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff,
739 0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff,
740 0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff,
741 0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc,
742 0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff,
743 0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff,
744 0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
745 0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff,
746 0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b,
747 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274,
748 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3,
749 0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff,
750 0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff,
751 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff,
752 0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6,
753 0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff,
754 0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff,
755 0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a,
756 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff,
757 0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a,
758 0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
759 0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff,
760 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
761 0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff,
762 0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff,
763 0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
764 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff,
765 0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb,
766 0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff,
767 0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff,
768 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a,
769 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff,
770 0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff,
771 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7,
772 0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
773 0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff,
774 0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff,
775 0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff,
776 0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff,
777 0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff,
778 0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff,
779 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af,
780 0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff,
781 0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff,
782 0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2,
783 0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
784 0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
785 0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff,
786 0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
787 0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff,
788 0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff,
789 0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff,
790 0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff,
791 0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339,
792 0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
793 0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff,
794 0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
795 0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff,
796 0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402,
797 0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff,
798 0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff,
799 0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff,
800 0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368,
801 0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148,
802 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff,
803 0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff,
804 0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
805 0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4,
806 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b,
807 0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff,
808 0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f,
809 0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff,
810 0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1,
811 0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
812 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
813 0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff,
814 0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff,
815 0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff,
816 0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb,
817 0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff,
818 0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc,
819 0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
820 0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097,
821 0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
822 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
823 0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
824 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
825 0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431,
826 0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1,
827 0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
828 0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a,
829 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4,
830 0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff,
831 0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff,
832 0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6,
833 0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd,
834 0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff,
835 0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff,
836 0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff,
837 0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb,
838 0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
839 0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff,
840 0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
841 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd,
842 0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff,
843 0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff,
844 0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519,
845 0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff,
846 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
847 0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff,
848 0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084,
849 0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0,
850 0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c,
851 0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff,
852 0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f,
853 0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448,
854 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a,
855 0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
856 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211,
857 0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff,
858 0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
859 0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff,
860 0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff,
861 0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
862 0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
863 0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff,
864 0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff,
865 0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff,
866 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff,
867 0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff,
868 0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff,
869 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff,
870 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff,
871 0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff,
872 0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180,
873 0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0,
874 0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
875 0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004,
876 0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302,
877 0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
878 0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff,
879 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff,
880 0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff,
881 0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff,
882 0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
883 0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
884 0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff,
885 0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072,
886 0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272,
887 0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
888 0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff,
889 0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344,
890 0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125,
891 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
892 0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff,
893 0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
894 0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff,
895 0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e,
896 0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d,
897 0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff,
898 0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff,
899 0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330,
900 0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042,
901 0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364,
902 0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff,
903 0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff,
904 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff,
905 0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f,
906 0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff,
907 0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb,
908 0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e,
909 0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c,
910 0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb,
911 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
912 0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
913 0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b,
914 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038,
915 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194,
916 0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff,
917 0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff,
918 0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff,
919 0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff,
920 0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff,
921 0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff,
922 0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff,
923 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6,
924 0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
925 0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387,
926 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff,
927 0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290,
928 0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff,
929 0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b,
930 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9,
931 0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff,
932 0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d,
933 0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff,
934 0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9,
935 0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167,
936 0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020,
937 0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347,
938 0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff,
939 0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff,
940 0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff,
941 0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff,
942 0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff,
943 0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff,
944 0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439,
945 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
946 0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff,
947 0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
948 0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff,
949 0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff,
950 0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039,
951 0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff,
952 0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff,
953 0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096,
954 0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff,
955 0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff,
956 0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
957 0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff,
958 0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a,
959 0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8,
960 0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff,
961 0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd,
962 0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff,
963 0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069,
964 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e,
965 0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f,
966 0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff,
967 0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff,
968 0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff,
969 0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7,
970 0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb,
971 0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff,
972 0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff,
973 0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078,
974 0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
975 0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300,
976 0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200,
977 0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff,
978 0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff,
979 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
980 0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f,
981 0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff,
982 0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f,
983 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff,
984 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216,
985 0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff,
986 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d,
987 0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0,
988 0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff,
989 0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff,
990 0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff,
991 0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff,
992 0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
993 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
994 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
995 0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
996 0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220,
997 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
998 0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff,
999 0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff,
1000 0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086,
1001 0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff,
1002 0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff,
1003 0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444,
1004 0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff,
1005 0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff,
1006 0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff,
1007 0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110,
1008 0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099,
1009 0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff,
1010 0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da,
1011 0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff,
1012 0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff,
1013 0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff,
1014 0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff,
1015 0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff,
1016 0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff,
1017 0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283,
1018 0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff,
1019 0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff,
1020 0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff,
1021 0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff,
1022 0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff,
1023 0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195,
1024 0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff,
1025 0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff,
1026 0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff,
1027 0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff,
1028 0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff,
1029 0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff,
1030 0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff,
1031 0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245,
1032 0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff,
1033 0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6,
1034 0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
1035 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
1036 0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
1037 0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1,
1038 0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da,
1039 0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff,
1040 0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff,
1041 0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5,
1042 0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223,
1043 0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002
1044};
1045
1046static unsigned short err_pos(unsigned short din)
1047{
1048 BUG_ON(din > 4096);
1049 return err_pos_lut[din];
1050}
1051static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1052{
1053 if ((chk_syndrome_list[0] | chk_syndrome_list[1] |
1054 chk_syndrome_list[2] | chk_syndrome_list[3] |
1055 chk_syndrome_list[4] | chk_syndrome_list[5] |
1056 chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) {
1057 return -EINVAL;
1058 } else {
1059 err_info[0] = 0x0;
1060 return 0;
1061 }
1062}
1063static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1064{
1065 unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
1066 tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0]));
1067 tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1]));
1068 tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2]));
1069 tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3]));
1070 tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4]));
1071 tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5]));
1072 tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6]));
1073 if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) {
1074 err_info[0] = 0x1; // encode 1-symbol error as 0x1
1075 err_info[1] = err_pos(tmp0);
1076 err_info[1] = (unsigned short)(0x55e - err_info[1]);
1077 err_info[5] = chk_syndrome_list[0];
1078 return 0;
1079 } else
1080 return -EINVAL;
1081}
1082static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1083{
1084 unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
1085 unsigned short coefs[4];
1086 unsigned short err_pats[4];
1087 int found_num_root = 0;
1088 unsigned short bit2_root0, bit2_root1;
1089 unsigned short bit2_root0_inv, bit2_root1_inv;
1090 unsigned short err_loc_eqn, test_root;
1091 unsigned short bit2_loc0, bit2_loc1;
1092 unsigned short bit2_pat0, bit2_pat1;
1093
1094 find_2x2_soln(chk_syndrome_list[1],
1095 chk_syndrome_list[0],
1096 chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs);
1097 for (test_root = 0x1; test_root < 0xfff; test_root++) {
1098 err_loc_eqn =
1099 gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
1100 if (err_loc_eqn == 0x0) {
1101 if (found_num_root == 0) {
1102 bit2_root0 = test_root;
1103 found_num_root = 1;
1104 } else if (found_num_root == 1) {
1105 bit2_root1 = test_root;
1106 found_num_root = 2;
1107 break;
1108 }
1109 }
1110 }
1111 if (found_num_root != 2)
1112 return -EINVAL;
1113 else {
1114 bit2_root0_inv = gf4096_inv(bit2_root0);
1115 bit2_root1_inv = gf4096_inv(bit2_root1);
1116 find_2bit_err_pats(chk_syndrome_list[0],
1117 chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats);
1118 bit2_pat0 = err_pats[0];
1119 bit2_pat1 = err_pats[1];
1120 //for(x+1)
1121 tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv)); //rinv0^4
1122 tmp1 = gf4096_mul(bit2_root0_inv, tmp0); //rinv0^5
1123 tmp2 = gf4096_mul(bit2_root0_inv, tmp1); //rinv0^6
1124 tmp3 = gf4096_mul(bit2_root0_inv, tmp2); //rinv0^7
1125 tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv)); //rinv1^4
1126 tmp5 = gf4096_mul(bit2_root1_inv, tmp4); //rinv1^5
1127 tmp6 = gf4096_mul(bit2_root1_inv, tmp5); //rinv1^6
1128 tmp7 = gf4096_mul(bit2_root1_inv, tmp6); //rinv1^7
1129 //check if only 2-bit error
1130 if ((chk_syndrome_list[4] ==
1131 (gf4096_mul(bit2_pat0, tmp0) ^
1132 gf4096_mul(bit2_pat1,
1133 tmp4))) & (chk_syndrome_list[5] ==
1134 (gf4096_mul(bit2_pat0, tmp1) ^
1135 gf4096_mul(bit2_pat1,
1136 tmp5))) &
1137 (chk_syndrome_list[6] ==
1138 (gf4096_mul(bit2_pat0, tmp2) ^
1139 gf4096_mul(bit2_pat1,
1140 tmp6))) & (chk_syndrome_list[7] ==
1141 (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) {
1142 if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) {
1143 return -EINVAL;
1144 } else {
1145 bit2_loc0 = 0x55e - err_pos(bit2_root0_inv);
1146 bit2_loc1 = 0x55e - err_pos(bit2_root1_inv);
1147 err_info[0] = 0x2; // encode 2-symbol error as 0x2
1148 err_info[1] = bit2_loc0;
1149 err_info[2] = bit2_loc1;
1150 err_info[5] = bit2_pat0;
1151 err_info[6] = bit2_pat1;
1152 return 0;
1153 }
1154 } else
1155 return -EINVAL;
1156 }
1157}
1158static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1159{
1160 unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
1161 unsigned short coefs[4];
1162 unsigned short err_pats[4];
1163 int found_num_root = 0;
1164 unsigned short bit3_root0, bit3_root1, bit3_root2;
1165 unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv;
1166 unsigned short err_loc_eqn, test_root;
1167
1168 find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1],
1169 chk_syndrome_list[2], chk_syndrome_list[3],
1170 chk_syndrome_list[4], chk_syndrome_list[5], coefs);
1171
1172 for (test_root = 0x1; test_root < 0xfff; test_root++) {
1173 err_loc_eqn = gf4096_mul(coefs[2],
1174 gf4096_mul(gf4096_mul(test_root, test_root),
1175 test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root))
1176 ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
1177
1178 if (err_loc_eqn == 0x0) {
1179 if (found_num_root == 0) {
1180 bit3_root0 = test_root;
1181 found_num_root = 1;
1182 } else if (found_num_root == 1) {
1183 bit3_root1 = test_root;
1184 found_num_root = 2;
1185 } else if (found_num_root == 2) {
1186 bit3_root2 = test_root;
1187 found_num_root = 3;
1188 break;
1189 }
1190 }
1191 }
1192 if (found_num_root != 3)
1193 return -EINVAL;
1194 else {
1195 bit3_root0_inv = gf4096_inv(bit3_root0);
1196 bit3_root1_inv = gf4096_inv(bit3_root1);
1197 bit3_root2_inv = gf4096_inv(bit3_root2);
1198
1199 find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1],
1200 chk_syndrome_list[2], bit3_root0_inv,
1201 bit3_root1_inv, bit3_root2_inv, err_pats);
1202
1203 //check if only 3-bit error
1204 tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv);
1205 tmp0 = gf4096_mul(tmp0, tmp0);
1206 tmp0 = gf4096_mul(tmp0, bit3_root0_inv);
1207 tmp0 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^6
1208 tmp1 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^7
1209 tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv);
1210 tmp2 = gf4096_mul(tmp2, tmp2);
1211 tmp2 = gf4096_mul(tmp2, bit3_root1_inv);
1212 tmp2 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^6
1213 tmp3 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^7
1214 tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv);
1215 tmp4 = gf4096_mul(tmp4, tmp4);
1216 tmp4 = gf4096_mul(tmp4, bit3_root2_inv);
1217 tmp4 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^6
1218 tmp5 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^7
1219
1220 //check if only 3 errors
1221 if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^
1222 gf4096_mul(err_pats[1], tmp2) ^
1223 gf4096_mul(err_pats[2], tmp4))) &
1224 (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^
1225 gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) {
1226 if ((err_pos(bit3_root0_inv) == 0xfff) |
1227 (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) {
1228 return -EINVAL;
1229 } else {
1230 err_info[0] = 0x3;
1231 err_info[1] = (0x55e - err_pos(bit3_root0_inv));
1232 err_info[2] = (0x55e - err_pos(bit3_root1_inv));
1233 err_info[3] = (0x55e - err_pos(bit3_root2_inv));
1234 err_info[5] = err_pats[0];
1235 err_info[6] = err_pats[1];
1236 err_info[7] = err_pats[2];
1237 return 0;
1238 }
1239 } else
1240 return -EINVAL;
1241 }
1242}
1243static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
1244{
1245 unsigned short coefs[4];
1246 unsigned short err_pats[4];
1247 int found_num_root = 0;
1248 unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3;
1249 unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv;
1250 unsigned short err_loc_eqn, test_root;
1251
1252 find_4bit_err_coefs(chk_syndrome_list[0],
1253 chk_syndrome_list[1],
1254 chk_syndrome_list[2],
1255 chk_syndrome_list[3],
1256 chk_syndrome_list[4],
1257 chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs);
1258
1259 for (test_root = 0x1; test_root < 0xfff; test_root++) {
1260 err_loc_eqn =
1261 gf4096_mul(coefs[3],
1262 gf4096_mul(gf4096_mul
1263 (gf4096_mul(test_root, test_root),
1264 test_root),
1265 test_root)) ^ gf4096_mul(coefs[2],
1266 gf4096_mul
1267 (gf4096_mul(test_root, test_root), test_root))
1268 ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root)
1269 ^ 0x1;
1270 if (err_loc_eqn == 0x0) {
1271 if (found_num_root == 0) {
1272 bit4_root0 = test_root;
1273 found_num_root = 1;
1274 } else if (found_num_root == 1) {
1275 bit4_root1 = test_root;
1276 found_num_root = 2;
1277 } else if (found_num_root == 2) {
1278 bit4_root2 = test_root;
1279 found_num_root = 3;
1280 } else {
1281 found_num_root = 4;
1282 bit4_root3 = test_root;
1283 break;
1284 }
1285 }
1286 }
1287 if (found_num_root != 4) {
1288 return -EINVAL;
1289 } else {
1290 bit4_root0_inv = gf4096_inv(bit4_root0);
1291 bit4_root1_inv = gf4096_inv(bit4_root1);
1292 bit4_root2_inv = gf4096_inv(bit4_root2);
1293 bit4_root3_inv = gf4096_inv(bit4_root3);
1294 find_4bit_err_pats(chk_syndrome_list[0],
1295 chk_syndrome_list[1],
1296 chk_syndrome_list[2],
1297 chk_syndrome_list[3],
1298 bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats);
1299 err_info[0] = 0x4;
1300 err_info[1] = (0x55e - err_pos(bit4_root0_inv));
1301 err_info[2] = (0x55e - err_pos(bit4_root1_inv));
1302 err_info[3] = (0x55e - err_pos(bit4_root2_inv));
1303 err_info[4] = (0x55e - err_pos(bit4_root3_inv));
1304 err_info[5] = err_pats[0];
1305 err_info[6] = err_pats[1];
1306 err_info[7] = err_pats[2];
1307 err_info[8] = err_pats[3];
1308 return 0;
1309 }
1310}
1311
1312void correct_12bit_symbol(unsigned char *buf, unsigned short sym,
1313 unsigned short val)
1314{
1315 if (unlikely(sym > 1366)) {
1316 printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym);
1317 } else if (sym == 0) {
1318 buf[0] ^= val;
1319 } else if (sym & 1) {
1320 buf[1+(3*(sym-1))/2] ^= (val >> 4);
1321 buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4);
1322 } else {
1323 buf[2+(3*(sym-2))/2] ^= (val >> 8);
1324 buf[3+(3*(sym-2))/2] ^= (val & 0xff);
1325 }
1326}
1327
1328static int debugecc = 0;
1329module_param(debugecc, int, 0644);
1330
1331int cafe_correct_ecc(unsigned char *buf,
1332 unsigned short *chk_syndrome_list)
1333{
1334 unsigned short err_info[9];
1335 int i;
1336
1337 if (debugecc) {
1338 printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n",
1339 chk_syndrome_list[0], chk_syndrome_list[1],
1340 chk_syndrome_list[2], chk_syndrome_list[3],
1341 chk_syndrome_list[4], chk_syndrome_list[5],
1342 chk_syndrome_list[6], chk_syndrome_list[7]);
1343 for (i=0; i < 2048; i+=16) {
1344 printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
1345 i,
1346 buf[i], buf[i+1], buf[i+2], buf[i+3],
1347 buf[i+4], buf[i+5], buf[i+6], buf[i+7],
1348 buf[i+8], buf[i+9], buf[i+10], buf[i+11],
1349 buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
1350 }
1351 for ( ; i < 2112; i+=16) {
1352 printk(KERN_WARNING "O %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
1353 i - 2048,
1354 buf[i], buf[i+1], buf[i+2], buf[i+3],
1355 buf[i+4], buf[i+5], buf[i+6], buf[i+7],
1356 buf[i+8], buf[i+9], buf[i+10], buf[i+11],
1357 buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
1358 }
1359 }
1360
1361
1362
1363 if (chk_no_err_only(chk_syndrome_list, err_info) &&
1364 chk_1_err_only(chk_syndrome_list, err_info) &&
1365 chk_2_err_only(chk_syndrome_list, err_info) &&
1366 chk_3_err_only(chk_syndrome_list, err_info) &&
1367 chk_4_err_only(chk_syndrome_list, err_info)) {
1368 return -EIO;
1369 }
1370
1371 for (i=0; i < err_info[0]; i++) {
1372 if (debugecc)
1373 printk(KERN_WARNING "Correct symbol %d with 0x%03x\n",
1374 err_info[1+i], err_info[5+i]);
1375
1376 correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]);
1377 }
1378
1379 return err_info[0];
1380}
1381
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 94924d52a9b9..8296305c8297 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -11,7 +11,7 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 * 12 *
13 * Overview: 13 * Overview:
14 * This is a device driver for the NAND flash controller found on 14 * This is a device driver for the NAND flash controller found on
15 * the AMD CS5535/CS5536 companion chipsets for the Geode processor. 15 * the AMD CS5535/CS5536 companion chipsets for the Geode processor.
16 * 16 *
17 */ 17 */
@@ -303,7 +303,7 @@ static int __init cs553x_init(void)
303 err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF); 303 err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
304 } 304 }
305 305
306 /* Register all devices together here. This means we can easily hack it to 306 /* Register all devices together here. This means we can easily hack it to
307 do mtdconcat etc. if we want to. */ 307 do mtdconcat etc. if we want to. */
308 for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { 308 for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
309 if (cs553x_mtd[i]) { 309 if (cs553x_mtd[i]) {
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 6107f532855b..12608c13cce5 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1635,13 +1635,12 @@ static int __init doc_probe(unsigned long physadr)
1635 1635
1636 len = sizeof(struct mtd_info) + 1636 len = sizeof(struct mtd_info) +
1637 sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); 1637 sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
1638 mtd = kmalloc(len, GFP_KERNEL); 1638 mtd = kzalloc(len, GFP_KERNEL);
1639 if (!mtd) { 1639 if (!mtd) {
1640 printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); 1640 printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
1641 ret = -ENOMEM; 1641 ret = -ENOMEM;
1642 goto fail; 1642 goto fail;
1643 } 1643 }
1644 memset(mtd, 0, len);
1645 1644
1646 nand = (struct nand_chip *) (mtd + 1); 1645 nand = (struct nand_chip *) (mtd + 1);
1647 doc = (struct doc_priv *) (nand + 1); 1646 doc = (struct doc_priv *) (nand + 1);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 41bfcae1fbf4..dfe56e03e48b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -362,7 +362,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
362 * access 362 * access
363 */ 363 */
364 ofs += mtd->oobsize; 364 ofs += mtd->oobsize;
365 chip->ops.len = 2; 365 chip->ops.len = chip->ops.ooblen = 2;
366 chip->ops.datbuf = NULL; 366 chip->ops.datbuf = NULL;
367 chip->ops.oobbuf = buf; 367 chip->ops.oobbuf = buf;
368 chip->ops.ooboffs = chip->badblockpos & ~0x01; 368 chip->ops.ooboffs = chip->badblockpos & ~0x01;
@@ -755,7 +755,7 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
755} 755}
756 756
757/** 757/**
758 * nand_read_page_swecc - {REPLACABLE] software ecc based page read function 758 * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
759 * @mtd: mtd info structure 759 * @mtd: mtd info structure
760 * @chip: nand chip info structure 760 * @chip: nand chip info structure
761 * @buf: buffer to store read data 761 * @buf: buffer to store read data
@@ -795,7 +795,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
795} 795}
796 796
797/** 797/**
798 * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function 798 * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
799 * @mtd: mtd info structure 799 * @mtd: mtd info structure
800 * @chip: nand chip info structure 800 * @chip: nand chip info structure
801 * @buf: buffer to store read data 801 * @buf: buffer to store read data
@@ -839,7 +839,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
839} 839}
840 840
841/** 841/**
842 * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read 842 * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
843 * @mtd: mtd info structure 843 * @mtd: mtd info structure
844 * @chip: nand chip info structure 844 * @chip: nand chip info structure
845 * @buf: buffer to store read data 845 * @buf: buffer to store read data
@@ -897,12 +897,11 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
897 * @chip: nand chip structure 897 * @chip: nand chip structure
898 * @oob: oob destination address 898 * @oob: oob destination address
899 * @ops: oob ops structure 899 * @ops: oob ops structure
900 * @len: size of oob to transfer
900 */ 901 */
901static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, 902static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
902 struct mtd_oob_ops *ops) 903 struct mtd_oob_ops *ops, size_t len)
903{ 904{
904 size_t len = ops->ooblen;
905
906 switch(ops->mode) { 905 switch(ops->mode) {
907 906
908 case MTD_OOB_PLACE: 907 case MTD_OOB_PLACE:
@@ -960,6 +959,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
960 int sndcmd = 1; 959 int sndcmd = 1;
961 int ret = 0; 960 int ret = 0;
962 uint32_t readlen = ops->len; 961 uint32_t readlen = ops->len;
962 uint32_t oobreadlen = ops->ooblen;
963 uint8_t *bufpoi, *oob, *buf; 963 uint8_t *bufpoi, *oob, *buf;
964 964
965 stats = mtd->ecc_stats; 965 stats = mtd->ecc_stats;
@@ -971,7 +971,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
971 page = realpage & chip->pagemask; 971 page = realpage & chip->pagemask;
972 972
973 col = (int)(from & (mtd->writesize - 1)); 973 col = (int)(from & (mtd->writesize - 1));
974 chip->oob_poi = chip->buffers->oobrbuf;
975 974
976 buf = ops->datbuf; 975 buf = ops->datbuf;
977 oob = ops->oobbuf; 976 oob = ops->oobbuf;
@@ -1007,10 +1006,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1007 1006
1008 if (unlikely(oob)) { 1007 if (unlikely(oob)) {
1009 /* Raw mode does data:oob:data:oob */ 1008 /* Raw mode does data:oob:data:oob */
1010 if (ops->mode != MTD_OOB_RAW) 1009 if (ops->mode != MTD_OOB_RAW) {
1011 oob = nand_transfer_oob(chip, oob, ops); 1010 int toread = min(oobreadlen,
1012 else 1011 chip->ecc.layout->oobavail);
1013 buf = nand_transfer_oob(chip, buf, ops); 1012 if (toread) {
1013 oob = nand_transfer_oob(chip,
1014 oob, ops, toread);
1015 oobreadlen -= toread;
1016 }
1017 } else
1018 buf = nand_transfer_oob(chip,
1019 buf, ops, mtd->oobsize);
1014 } 1020 }
1015 1021
1016 if (!(chip->options & NAND_NO_READRDY)) { 1022 if (!(chip->options & NAND_NO_READRDY)) {
@@ -1057,6 +1063,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1057 } 1063 }
1058 1064
1059 ops->retlen = ops->len - (size_t) readlen; 1065 ops->retlen = ops->len - (size_t) readlen;
1066 if (oob)
1067 ops->oobretlen = ops->ooblen - oobreadlen;
1060 1068
1061 if (ret) 1069 if (ret)
1062 return ret; 1070 return ret;
@@ -1257,12 +1265,18 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1257 int page, realpage, chipnr, sndcmd = 1; 1265 int page, realpage, chipnr, sndcmd = 1;
1258 struct nand_chip *chip = mtd->priv; 1266 struct nand_chip *chip = mtd->priv;
1259 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1267 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1260 int readlen = ops->len; 1268 int readlen = ops->ooblen;
1269 int len;
1261 uint8_t *buf = ops->oobbuf; 1270 uint8_t *buf = ops->oobbuf;
1262 1271
1263 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", 1272 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
1264 (unsigned long long)from, readlen); 1273 (unsigned long long)from, readlen);
1265 1274
1275 if (ops->mode == MTD_OOB_RAW)
1276 len = mtd->oobsize;
1277 else
1278 len = chip->ecc.layout->oobavail;
1279
1266 chipnr = (int)(from >> chip->chip_shift); 1280 chipnr = (int)(from >> chip->chip_shift);
1267 chip->select_chip(mtd, chipnr); 1281 chip->select_chip(mtd, chipnr);
1268 1282
@@ -1270,11 +1284,11 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1270 realpage = (int)(from >> chip->page_shift); 1284 realpage = (int)(from >> chip->page_shift);
1271 page = realpage & chip->pagemask; 1285 page = realpage & chip->pagemask;
1272 1286
1273 chip->oob_poi = chip->buffers->oobrbuf;
1274
1275 while(1) { 1287 while(1) {
1276 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1288 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
1277 buf = nand_transfer_oob(chip, buf, ops); 1289
1290 len = min(len, readlen);
1291 buf = nand_transfer_oob(chip, buf, ops, len);
1278 1292
1279 if (!(chip->options & NAND_NO_READRDY)) { 1293 if (!(chip->options & NAND_NO_READRDY)) {
1280 /* 1294 /*
@@ -1289,7 +1303,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1289 nand_wait_ready(mtd); 1303 nand_wait_ready(mtd);
1290 } 1304 }
1291 1305
1292 readlen -= ops->ooblen; 1306 readlen -= len;
1293 if (!readlen) 1307 if (!readlen)
1294 break; 1308 break;
1295 1309
@@ -1311,7 +1325,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
1311 sndcmd = 1; 1325 sndcmd = 1;
1312 } 1326 }
1313 1327
1314 ops->retlen = ops->len; 1328 ops->oobretlen = ops->ooblen;
1315 return 0; 1329 return 0;
1316} 1330}
1317 1331
@@ -1332,7 +1346,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
1332 ops->retlen = 0; 1346 ops->retlen = 0;
1333 1347
1334 /* Do not allow reads past end of device */ 1348 /* Do not allow reads past end of device */
1335 if ((from + ops->len) > mtd->size) { 1349 if (ops->datbuf && (from + ops->len) > mtd->size) {
1336 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1350 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1337 "Attempt read beyond end of device\n"); 1351 "Attempt read beyond end of device\n");
1338 return -EINVAL; 1352 return -EINVAL;
@@ -1375,7 +1389,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1375} 1389}
1376 1390
1377/** 1391/**
1378 * nand_write_page_swecc - {REPLACABLE] software ecc based page write function 1392 * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
1379 * @mtd: mtd info structure 1393 * @mtd: mtd info structure
1380 * @chip: nand chip info structure 1394 * @chip: nand chip info structure
1381 * @buf: data buffer 1395 * @buf: data buffer
@@ -1401,7 +1415,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1401} 1415}
1402 1416
1403/** 1417/**
1404 * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function 1418 * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
1405 * @mtd: mtd info structure 1419 * @mtd: mtd info structure
1406 * @chip: nand chip info structure 1420 * @chip: nand chip info structure
1407 * @buf: data buffer 1421 * @buf: data buffer
@@ -1429,7 +1443,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
1429} 1443}
1430 1444
1431/** 1445/**
1432 * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write 1446 * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
1433 * @mtd: mtd info structure 1447 * @mtd: mtd info structure
1434 * @chip: nand chip info structure 1448 * @chip: nand chip info structure
1435 * @buf: data buffer 1449 * @buf: data buffer
@@ -1577,7 +1591,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
1577 return NULL; 1591 return NULL;
1578} 1592}
1579 1593
1580#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 1594#define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0
1581 1595
1582/** 1596/**
1583 * nand_do_write_ops - [Internal] NAND write with ECC 1597 * nand_do_write_ops - [Internal] NAND write with ECC
@@ -1590,15 +1604,16 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
1590static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, 1604static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1591 struct mtd_oob_ops *ops) 1605 struct mtd_oob_ops *ops)
1592{ 1606{
1593 int chipnr, realpage, page, blockmask; 1607 int chipnr, realpage, page, blockmask, column;
1594 struct nand_chip *chip = mtd->priv; 1608 struct nand_chip *chip = mtd->priv;
1595 uint32_t writelen = ops->len; 1609 uint32_t writelen = ops->len;
1596 uint8_t *oob = ops->oobbuf; 1610 uint8_t *oob = ops->oobbuf;
1597 uint8_t *buf = ops->datbuf; 1611 uint8_t *buf = ops->datbuf;
1598 int bytes = mtd->writesize; 1612 int ret, subpage;
1599 int ret;
1600 1613
1601 ops->retlen = 0; 1614 ops->retlen = 0;
1615 if (!writelen)
1616 return 0;
1602 1617
1603 /* reject writes, which are not page aligned */ 1618 /* reject writes, which are not page aligned */
1604 if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { 1619 if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
@@ -1607,8 +1622,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1607 return -EINVAL; 1622 return -EINVAL;
1608 } 1623 }
1609 1624
1610 if (!writelen) 1625 column = to & (mtd->writesize - 1);
1611 return 0; 1626 subpage = column || (writelen & (mtd->writesize - 1));
1627
1628 if (subpage && oob)
1629 return -EINVAL;
1612 1630
1613 chipnr = (int)(to >> chip->chip_shift); 1631 chipnr = (int)(to >> chip->chip_shift);
1614 chip->select_chip(mtd, chipnr); 1632 chip->select_chip(mtd, chipnr);
@@ -1626,15 +1644,29 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1626 (chip->pagebuf << chip->page_shift) < (to + ops->len)) 1644 (chip->pagebuf << chip->page_shift) < (to + ops->len))
1627 chip->pagebuf = -1; 1645 chip->pagebuf = -1;
1628 1646
1629 chip->oob_poi = chip->buffers->oobwbuf; 1647 /* If we're not given explicit OOB data, let it be 0xFF */
1648 if (likely(!oob))
1649 memset(chip->oob_poi, 0xff, mtd->oobsize);
1630 1650
1631 while(1) { 1651 while(1) {
1652 int bytes = mtd->writesize;
1632 int cached = writelen > bytes && page != blockmask; 1653 int cached = writelen > bytes && page != blockmask;
1654 uint8_t *wbuf = buf;
1655
1656 /* Partial page write ? */
1657 if (unlikely(column || writelen < (mtd->writesize - 1))) {
1658 cached = 0;
1659 bytes = min_t(int, bytes - column, (int) writelen);
1660 chip->pagebuf = -1;
1661 memset(chip->buffers->databuf, 0xff, mtd->writesize);
1662 memcpy(&chip->buffers->databuf[column], buf, bytes);
1663 wbuf = chip->buffers->databuf;
1664 }
1633 1665
1634 if (unlikely(oob)) 1666 if (unlikely(oob))
1635 oob = nand_fill_oob(chip, oob, ops); 1667 oob = nand_fill_oob(chip, oob, ops);
1636 1668
1637 ret = chip->write_page(mtd, chip, buf, page, cached, 1669 ret = chip->write_page(mtd, chip, wbuf, page, cached,
1638 (ops->mode == MTD_OOB_RAW)); 1670 (ops->mode == MTD_OOB_RAW));
1639 if (ret) 1671 if (ret)
1640 break; 1672 break;
@@ -1643,6 +1675,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1643 if (!writelen) 1675 if (!writelen)
1644 break; 1676 break;
1645 1677
1678 column = 0;
1646 buf += bytes; 1679 buf += bytes;
1647 realpage++; 1680 realpage++;
1648 1681
@@ -1655,10 +1688,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1655 } 1688 }
1656 } 1689 }
1657 1690
1658 if (unlikely(oob))
1659 memset(chip->oob_poi, 0xff, mtd->oobsize);
1660
1661 ops->retlen = ops->len - writelen; 1691 ops->retlen = ops->len - writelen;
1692 if (unlikely(oob))
1693 ops->oobretlen = ops->ooblen;
1662 return ret; 1694 return ret;
1663} 1695}
1664 1696
@@ -1714,10 +1746,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1714 struct nand_chip *chip = mtd->priv; 1746 struct nand_chip *chip = mtd->priv;
1715 1747
1716 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", 1748 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1717 (unsigned int)to, (int)ops->len); 1749 (unsigned int)to, (int)ops->ooblen);
1718 1750
1719 /* Do not allow write past end of page */ 1751 /* Do not allow write past end of page */
1720 if ((ops->ooboffs + ops->len) > mtd->oobsize) { 1752 if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
1721 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1753 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1722 "Attempt to write past end of page\n"); 1754 "Attempt to write past end of page\n");
1723 return -EINVAL; 1755 return -EINVAL;
@@ -1745,7 +1777,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1745 if (page == chip->pagebuf) 1777 if (page == chip->pagebuf)
1746 chip->pagebuf = -1; 1778 chip->pagebuf = -1;
1747 1779
1748 chip->oob_poi = chip->buffers->oobwbuf;
1749 memset(chip->oob_poi, 0xff, mtd->oobsize); 1780 memset(chip->oob_poi, 0xff, mtd->oobsize);
1750 nand_fill_oob(chip, ops->oobbuf, ops); 1781 nand_fill_oob(chip, ops->oobbuf, ops);
1751 status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); 1782 status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
@@ -1754,7 +1785,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
1754 if (status) 1785 if (status)
1755 return status; 1786 return status;
1756 1787
1757 ops->retlen = ops->len; 1788 ops->oobretlen = ops->ooblen;
1758 1789
1759 return 0; 1790 return 0;
1760} 1791}
@@ -1774,7 +1805,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
1774 ops->retlen = 0; 1805 ops->retlen = 0;
1775 1806
1776 /* Do not allow writes past end of device */ 1807 /* Do not allow writes past end of device */
1777 if ((to + ops->len) > mtd->size) { 1808 if (ops->datbuf && (to + ops->len) > mtd->size) {
1778 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1809 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1779 "Attempt read beyond end of device\n"); 1810 "Attempt read beyond end of device\n");
1780 return -EINVAL; 1811 return -EINVAL;
@@ -2188,8 +2219,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2188 /* Newer devices have all the information in additional id bytes */ 2219 /* Newer devices have all the information in additional id bytes */
2189 if (!type->pagesize) { 2220 if (!type->pagesize) {
2190 int extid; 2221 int extid;
2191 /* The 3rd id byte contains non relevant data ATM */ 2222 /* The 3rd id byte holds MLC / multichip data */
2192 extid = chip->read_byte(mtd); 2223 chip->cellinfo = chip->read_byte(mtd);
2193 /* The 4th id byte is the important one */ 2224 /* The 4th id byte is the important one */
2194 extid = chip->read_byte(mtd); 2225 extid = chip->read_byte(mtd);
2195 /* Calc pagesize */ 2226 /* Calc pagesize */
@@ -2349,8 +2380,8 @@ int nand_scan_tail(struct mtd_info *mtd)
2349 if (!chip->buffers) 2380 if (!chip->buffers)
2350 return -ENOMEM; 2381 return -ENOMEM;
2351 2382
2352 /* Preset the internal oob write buffer */ 2383 /* Set the internal oob buffer location, just after the page data */
2353 memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize); 2384 chip->oob_poi = chip->buffers->databuf + mtd->writesize;
2354 2385
2355 /* 2386 /*
2356 * If no default placement scheme is given, select an appropriate one 2387 * If no default placement scheme is given, select an appropriate one
@@ -2469,6 +2500,24 @@ int nand_scan_tail(struct mtd_info *mtd)
2469 } 2500 }
2470 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; 2501 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
2471 2502
2503 /*
2504 * Allow subpage writes up to ecc.steps. Not possible for MLC
2505 * FLASH.
2506 */
2507 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
2508 !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
2509 switch(chip->ecc.steps) {
2510 case 2:
2511 mtd->subpage_sft = 1;
2512 break;
2513 case 4:
2514 case 8:
2515 mtd->subpage_sft = 2;
2516 break;
2517 }
2518 }
2519 chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
2520
2472 /* Initialize state */ 2521 /* Initialize state */
2473 chip->state = FL_READY; 2522 chip->state = FL_READY;
2474 2523
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 9402653eb09b..5e121ceaa598 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -333,7 +333,6 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
333 struct mtd_oob_ops ops; 333 struct mtd_oob_ops ops;
334 int j, ret; 334 int j, ret;
335 335
336 ops.len = mtd->oobsize;
337 ops.ooblen = mtd->oobsize; 336 ops.ooblen = mtd->oobsize;
338 ops.oobbuf = buf; 337 ops.oobbuf = buf;
339 ops.ooboffs = 0; 338 ops.ooboffs = 0;
@@ -676,10 +675,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
676 "bad block table\n"); 675 "bad block table\n");
677 } 676 }
678 /* Read oob data */ 677 /* Read oob data */
679 ops.len = (len >> this->page_shift) * mtd->oobsize; 678 ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
680 ops.oobbuf = &buf[len]; 679 ops.oobbuf = &buf[len];
681 res = mtd->read_oob(mtd, to + mtd->writesize, &ops); 680 res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
682 if (res < 0 || ops.retlen != ops.len) 681 if (res < 0 || ops.oobretlen != ops.ooblen)
683 goto outerr; 682 goto outerr;
684 683
685 /* Calc the byte offset in the buffer */ 684 /* Calc the byte offset in the buffer */
@@ -961,14 +960,12 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
961 struct nand_bbt_descr *md = this->bbt_md; 960 struct nand_bbt_descr *md = this->bbt_md;
962 961
963 len = mtd->size >> (this->bbt_erase_shift + 2); 962 len = mtd->size >> (this->bbt_erase_shift + 2);
964 /* Allocate memory (2bit per block) */ 963 /* Allocate memory (2bit per block) and clear the memory bad block table */
965 this->bbt = kmalloc(len, GFP_KERNEL); 964 this->bbt = kzalloc(len, GFP_KERNEL);
966 if (!this->bbt) { 965 if (!this->bbt) {
967 printk(KERN_ERR "nand_scan_bbt: Out of memory\n"); 966 printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
968 return -ENOMEM; 967 return -ENOMEM;
969 } 968 }
970 /* Clear the memory bad block table */
971 memset(this->bbt, 0x00, len);
972 969
973 /* If no primary table decriptor is given, scan the device 970 /* If no primary table decriptor is given, scan the device
974 * to build a memory based bad block table 971 * to build a memory based bad block table
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index dd438ca47d9a..fde593e5e634 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -112,7 +112,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
112 tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ 112 tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
113 113
114 /* Calculate final ECC code */ 114 /* Calculate final ECC code */
115#ifdef CONFIG_NAND_ECC_SMC 115#ifdef CONFIG_MTD_NAND_ECC_SMC
116 ecc_code[0] = ~tmp2; 116 ecc_code[0] = ~tmp2;
117 ecc_code[1] = ~tmp1; 117 ecc_code[1] = ~tmp1;
118#else 118#else
@@ -148,7 +148,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
148{ 148{
149 uint8_t s0, s1, s2; 149 uint8_t s0, s1, s2;
150 150
151#ifdef CONFIG_NAND_ECC_SMC 151#ifdef CONFIG_MTD_NAND_ECC_SMC
152 s0 = calc_ecc[0] ^ read_ecc[0]; 152 s0 = calc_ecc[0] ^ read_ecc[0];
153 s1 = calc_ecc[1] ^ read_ecc[1]; 153 s1 = calc_ecc[1] ^ read_ecc[1];
154 s2 = calc_ecc[2] ^ read_ecc[2]; 154 s2 = calc_ecc[2] ^ read_ecc[2];
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 545ff252d81e..c3bca9590ad2 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -37,10 +37,6 @@
37#include <linux/mtd/nand.h> 37#include <linux/mtd/nand.h>
38#include <linux/mtd/partitions.h> 38#include <linux/mtd/partitions.h>
39#include <linux/delay.h> 39#include <linux/delay.h>
40#ifdef CONFIG_NS_ABS_POS
41#include <asm/io.h>
42#endif
43
44 40
45/* Default simulator parameters values */ 41/* Default simulator parameters values */
46#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ 42#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -164,7 +160,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero");
164/* After a command is input, the simulator goes to one of the following states */ 160/* After a command is input, the simulator goes to one of the following states */
165#define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */ 161#define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */
166#define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */ 162#define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */
167#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */ 163#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
168#define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */ 164#define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */
169#define STATE_CMD_READOOB 0x00000005 /* read OOB area */ 165#define STATE_CMD_READOOB 0x00000005 /* read OOB area */
170#define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */ 166#define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */
@@ -231,6 +227,14 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero");
231#define NS_MAX_PREVSTATES 1 227#define NS_MAX_PREVSTATES 1
232 228
233/* 229/*
230 * A union to represent flash memory contents and flash buffer.
231 */
232union ns_mem {
233 u_char *byte; /* for byte access */
234 uint16_t *word; /* for 16-bit word access */
235};
236
237/*
234 * The structure which describes all the internal simulator data. 238 * The structure which describes all the internal simulator data.
235 */ 239 */
236struct nandsim { 240struct nandsim {
@@ -247,17 +251,11 @@ struct nandsim {
247 uint16_t npstates; /* number of previous states saved */ 251 uint16_t npstates; /* number of previous states saved */
248 uint16_t stateidx; /* current state index */ 252 uint16_t stateidx; /* current state index */
249 253
250 /* The simulated NAND flash image */ 254 /* The simulated NAND flash pages array */
251 union flash_media { 255 union ns_mem *pages;
252 u_char *byte;
253 uint16_t *word;
254 } mem;
255 256
256 /* Internal buffer of page + OOB size bytes */ 257 /* Internal buffer of page + OOB size bytes */
257 union internal_buffer { 258 union ns_mem buf;
258 u_char *byte; /* for byte access */
259 uint16_t *word; /* for 16-bit word access */
260 } buf;
261 259
262 /* NAND flash "geometry" */ 260 /* NAND flash "geometry" */
263 struct nandsin_geometry { 261 struct nandsin_geometry {
@@ -346,12 +344,49 @@ static struct mtd_info *nsmtd;
346static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; 344static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
347 345
348/* 346/*
347 * Allocate array of page pointers and initialize the array to NULL
348 * pointers.
349 *
350 * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
351 */
352static int alloc_device(struct nandsim *ns)
353{
354 int i;
355
356 ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
357 if (!ns->pages) {
358 NS_ERR("alloc_map: unable to allocate page array\n");
359 return -ENOMEM;
360 }
361 for (i = 0; i < ns->geom.pgnum; i++) {
362 ns->pages[i].byte = NULL;
363 }
364
365 return 0;
366}
367
368/*
369 * Free any allocated pages, and free the array of page pointers.
370 */
371static void free_device(struct nandsim *ns)
372{
373 int i;
374
375 if (ns->pages) {
376 for (i = 0; i < ns->geom.pgnum; i++) {
377 if (ns->pages[i].byte)
378 kfree(ns->pages[i].byte);
379 }
380 vfree(ns->pages);
381 }
382}
383
384/*
349 * Initialize the nandsim structure. 385 * Initialize the nandsim structure.
350 * 386 *
351 * RETURNS: 0 if success, -ERRNO if failure. 387 * RETURNS: 0 if success, -ERRNO if failure.
352 */ 388 */
353static int 389static int init_nandsim(struct mtd_info *mtd)
354init_nandsim(struct mtd_info *mtd)
355{ 390{
356 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 391 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
357 struct nandsim *ns = (struct nandsim *)(chip->priv); 392 struct nandsim *ns = (struct nandsim *)(chip->priv);
@@ -405,7 +440,7 @@ init_nandsim(struct mtd_info *mtd)
405 } 440 }
406 } else { 441 } else {
407 if (ns->geom.totsz <= (128 << 20)) { 442 if (ns->geom.totsz <= (128 << 20)) {
408 ns->geom.pgaddrbytes = 5; 443 ns->geom.pgaddrbytes = 4;
409 ns->geom.secaddrbytes = 2; 444 ns->geom.secaddrbytes = 2;
410 } else { 445 } else {
411 ns->geom.pgaddrbytes = 5; 446 ns->geom.pgaddrbytes = 5;
@@ -439,23 +474,8 @@ init_nandsim(struct mtd_info *mtd)
439 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 474 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
440 printk("options: %#x\n", ns->options); 475 printk("options: %#x\n", ns->options);
441 476
442 /* Map / allocate and initialize the flash image */ 477 if (alloc_device(ns) != 0)
443#ifdef CONFIG_NS_ABS_POS 478 goto error;
444 ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob);
445 if (!ns->mem.byte) {
446 NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n",
447 (void *)CONFIG_NS_ABS_POS);
448 return -ENOMEM;
449 }
450#else
451 ns->mem.byte = vmalloc(ns->geom.totszoob);
452 if (!ns->mem.byte) {
453 NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n",
454 ns->geom.totszoob);
455 return -ENOMEM;
456 }
457 memset(ns->mem.byte, 0xFF, ns->geom.totszoob);
458#endif
459 479
460 /* Allocate / initialize the internal buffer */ 480 /* Allocate / initialize the internal buffer */
461 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); 481 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
@@ -474,11 +494,7 @@ init_nandsim(struct mtd_info *mtd)
474 return 0; 494 return 0;
475 495
476error: 496error:
477#ifdef CONFIG_NS_ABS_POS 497 free_device(ns);
478 iounmap(ns->mem.byte);
479#else
480 vfree(ns->mem.byte);
481#endif
482 498
483 return -ENOMEM; 499 return -ENOMEM;
484} 500}
@@ -486,16 +502,10 @@ error:
486/* 502/*
487 * Free the nandsim structure. 503 * Free the nandsim structure.
488 */ 504 */
489static void 505static void free_nandsim(struct nandsim *ns)
490free_nandsim(struct nandsim *ns)
491{ 506{
492 kfree(ns->buf.byte); 507 kfree(ns->buf.byte);
493 508 free_device(ns);
494#ifdef CONFIG_NS_ABS_POS
495 iounmap(ns->mem.byte);
496#else
497 vfree(ns->mem.byte);
498#endif
499 509
500 return; 510 return;
501} 511}
@@ -503,8 +513,7 @@ free_nandsim(struct nandsim *ns)
503/* 513/*
504 * Returns the string representation of 'state' state. 514 * Returns the string representation of 'state' state.
505 */ 515 */
506static char * 516static char *get_state_name(uint32_t state)
507get_state_name(uint32_t state)
508{ 517{
509 switch (NS_STATE(state)) { 518 switch (NS_STATE(state)) {
510 case STATE_CMD_READ0: 519 case STATE_CMD_READ0:
@@ -562,8 +571,7 @@ get_state_name(uint32_t state)
562 * 571 *
563 * RETURNS: 1 if wrong command, 0 if right. 572 * RETURNS: 1 if wrong command, 0 if right.
564 */ 573 */
565static int 574static int check_command(int cmd)
566check_command(int cmd)
567{ 575{
568 switch (cmd) { 576 switch (cmd) {
569 577
@@ -589,8 +597,7 @@ check_command(int cmd)
589/* 597/*
590 * Returns state after command is accepted by command number. 598 * Returns state after command is accepted by command number.
591 */ 599 */
592static uint32_t 600static uint32_t get_state_by_command(unsigned command)
593get_state_by_command(unsigned command)
594{ 601{
595 switch (command) { 602 switch (command) {
596 case NAND_CMD_READ0: 603 case NAND_CMD_READ0:
@@ -626,8 +633,7 @@ get_state_by_command(unsigned command)
626/* 633/*
627 * Move an address byte to the correspondent internal register. 634 * Move an address byte to the correspondent internal register.
628 */ 635 */
629static inline void 636static inline void accept_addr_byte(struct nandsim *ns, u_char bt)
630accept_addr_byte(struct nandsim *ns, u_char bt)
631{ 637{
632 uint byte = (uint)bt; 638 uint byte = (uint)bt;
633 639
@@ -645,8 +651,7 @@ accept_addr_byte(struct nandsim *ns, u_char bt)
645/* 651/*
646 * Switch to STATE_READY state. 652 * Switch to STATE_READY state.
647 */ 653 */
648static inline void 654static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
649switch_to_ready_state(struct nandsim *ns, u_char status)
650{ 655{
651 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); 656 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY));
652 657
@@ -705,8 +710,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status)
705 * -1 - several matches. 710 * -1 - several matches.
706 * 0 - operation is found. 711 * 0 - operation is found.
707 */ 712 */
708static int 713static int find_operation(struct nandsim *ns, uint32_t flag)
709find_operation(struct nandsim *ns, uint32_t flag)
710{ 714{
711 int opsfound = 0; 715 int opsfound = 0;
712 int i, j, idx = 0; 716 int i, j, idx = 0;
@@ -791,14 +795,93 @@ find_operation(struct nandsim *ns, uint32_t flag)
791} 795}
792 796
793/* 797/*
798 * Returns a pointer to the current page.
799 */
800static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns)
801{
802 return &(ns->pages[ns->regs.row]);
803}
804
805/*
806 * Retuns a pointer to the current byte, within the current page.
807 */
808static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
809{
810 return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
811}
812
813/*
814 * Fill the NAND buffer with data read from the specified page.
815 */
816static void read_page(struct nandsim *ns, int num)
817{
818 union ns_mem *mypage;
819
820 mypage = NS_GET_PAGE(ns);
821 if (mypage->byte == NULL) {
822 NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
823 memset(ns->buf.byte, 0xFF, num);
824 } else {
825 NS_DBG("read_page: page %d allocated, reading from %d\n",
826 ns->regs.row, ns->regs.column + ns->regs.off);
827 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
828 }
829}
830
831/*
832 * Erase all pages in the specified sector.
833 */
834static void erase_sector(struct nandsim *ns)
835{
836 union ns_mem *mypage;
837 int i;
838
839 mypage = NS_GET_PAGE(ns);
840 for (i = 0; i < ns->geom.pgsec; i++) {
841 if (mypage->byte != NULL) {
842 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
843 kfree(mypage->byte);
844 mypage->byte = NULL;
845 }
846 mypage++;
847 }
848}
849
850/*
851 * Program the specified page with the contents from the NAND buffer.
852 */
853static int prog_page(struct nandsim *ns, int num)
854{
855 int i;
856 union ns_mem *mypage;
857 u_char *pg_off;
858
859 mypage = NS_GET_PAGE(ns);
860 if (mypage->byte == NULL) {
861 NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
862 mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
863 if (mypage->byte == NULL) {
864 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
865 return -1;
866 }
867 memset(mypage->byte, 0xFF, ns->geom.pgszoob);
868 }
869
870 pg_off = NS_PAGE_BYTE_OFF(ns);
871 for (i = 0; i < num; i++)
872 pg_off[i] &= ns->buf.byte[i];
873
874 return 0;
875}
876
877/*
794 * If state has any action bit, perform this action. 878 * If state has any action bit, perform this action.
795 * 879 *
796 * RETURNS: 0 if success, -1 if error. 880 * RETURNS: 0 if success, -1 if error.
797 */ 881 */
798static int 882static int do_state_action(struct nandsim *ns, uint32_t action)
799do_state_action(struct nandsim *ns, uint32_t action)
800{ 883{
801 int i, num; 884 int num;
802 int busdiv = ns->busw == 8 ? 1 : 2; 885 int busdiv = ns->busw == 8 ? 1 : 2;
803 886
804 action &= ACTION_MASK; 887 action &= ACTION_MASK;
@@ -822,7 +905,7 @@ do_state_action(struct nandsim *ns, uint32_t action)
822 break; 905 break;
823 } 906 }
824 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; 907 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
825 memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num); 908 read_page(ns, num);
826 909
827 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", 910 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n",
828 num, NS_RAW_OFFSET(ns) + ns->regs.off); 911 num, NS_RAW_OFFSET(ns) + ns->regs.off);
@@ -863,7 +946,7 @@ do_state_action(struct nandsim *ns, uint32_t action)
863 ns->regs.row, NS_RAW_OFFSET(ns)); 946 ns->regs.row, NS_RAW_OFFSET(ns));
864 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); 947 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift));
865 948
866 memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); 949 erase_sector(ns);
867 950
868 NS_MDELAY(erase_delay); 951 NS_MDELAY(erase_delay);
869 952
@@ -886,8 +969,8 @@ do_state_action(struct nandsim *ns, uint32_t action)
886 return -1; 969 return -1;
887 } 970 }
888 971
889 for (i = 0; i < num; i++) 972 if (prog_page(ns, num) == -1)
890 ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i]; 973 return -1;
891 974
892 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", 975 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
893 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); 976 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
@@ -928,8 +1011,7 @@ do_state_action(struct nandsim *ns, uint32_t action)
928/* 1011/*
929 * Switch simulator's state. 1012 * Switch simulator's state.
930 */ 1013 */
931static void 1014static void switch_state(struct nandsim *ns)
932switch_state(struct nandsim *ns)
933{ 1015{
934 if (ns->op) { 1016 if (ns->op) {
935 /* 1017 /*
@@ -1070,8 +1152,7 @@ switch_state(struct nandsim *ns)
1070 } 1152 }
1071} 1153}
1072 1154
1073static u_char 1155static u_char ns_nand_read_byte(struct mtd_info *mtd)
1074ns_nand_read_byte(struct mtd_info *mtd)
1075{ 1156{
1076 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1157 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1077 u_char outb = 0x00; 1158 u_char outb = 0x00;
@@ -1144,8 +1225,7 @@ ns_nand_read_byte(struct mtd_info *mtd)
1144 return outb; 1225 return outb;
1145} 1226}
1146 1227
1147static void 1228static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
1148ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
1149{ 1229{
1150 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1230 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1151 1231
@@ -1308,15 +1388,13 @@ static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
1308 ns_nand_write_byte(mtd, cmd); 1388 ns_nand_write_byte(mtd, cmd);
1309} 1389}
1310 1390
1311static int 1391static int ns_device_ready(struct mtd_info *mtd)
1312ns_device_ready(struct mtd_info *mtd)
1313{ 1392{
1314 NS_DBG("device_ready\n"); 1393 NS_DBG("device_ready\n");
1315 return 1; 1394 return 1;
1316} 1395}
1317 1396
1318static uint16_t 1397static uint16_t ns_nand_read_word(struct mtd_info *mtd)
1319ns_nand_read_word(struct mtd_info *mtd)
1320{ 1398{
1321 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 1399 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
1322 1400
@@ -1325,8 +1403,7 @@ ns_nand_read_word(struct mtd_info *mtd)
1325 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); 1403 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
1326} 1404}
1327 1405
1328static void 1406static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
1329ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
1330{ 1407{
1331 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1408 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1332 1409
@@ -1353,8 +1430,7 @@ ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
1353 } 1430 }
1354} 1431}
1355 1432
1356static void 1433static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
1357ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
1358{ 1434{
1359 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1435 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1360 1436
@@ -1407,8 +1483,7 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
1407 return; 1483 return;
1408} 1484}
1409 1485
1410static int 1486static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
1411ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
1412{ 1487{
1413 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); 1488 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
1414 1489
@@ -1436,14 +1511,12 @@ static int __init ns_init_module(void)
1436 } 1511 }
1437 1512
1438 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ 1513 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */
1439 nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) 1514 nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
1440 + sizeof(struct nandsim), GFP_KERNEL); 1515 + sizeof(struct nandsim), GFP_KERNEL);
1441 if (!nsmtd) { 1516 if (!nsmtd) {
1442 NS_ERR("unable to allocate core structures.\n"); 1517 NS_ERR("unable to allocate core structures.\n");
1443 return -ENOMEM; 1518 return -ENOMEM;
1444 } 1519 }
1445 memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) +
1446 sizeof(struct nandsim));
1447 chip = (struct nand_chip *)(nsmtd + 1); 1520 chip = (struct nand_chip *)(nsmtd + 1);
1448 nsmtd->priv = (void *)chip; 1521 nsmtd->priv = (void *)chip;
1449 nand = (struct nandsim *)(chip + 1); 1522 nand = (struct nandsim *)(chip + 1);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 039c759cfbfc..fd7a8d5ba29a 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -56,7 +56,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
56 ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); 56 ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
57 } else 57 } else
58 ccr |= NDFC_CCR_RESET_CE; 58 ccr |= NDFC_CCR_RESET_CE;
59 writel(ccr, ndfc->ndfcbase + NDFC_CCR); 59 __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
60} 60}
61 61
62static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) 62static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index f8c49645324d..9189ec8f243e 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -24,6 +24,7 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/rslib.h> 26#include <linux/rslib.h>
27#include <linux/bitrev.h>
27#include <linux/module.h> 28#include <linux/module.h>
28#include <linux/mtd/compatmac.h> 29#include <linux/mtd/compatmac.h>
29#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
@@ -152,47 +153,6 @@ static struct nand_ecclayout rtc_from4_nand_oobinfo = {
152 .oobfree = {{32, 32}} 153 .oobfree = {{32, 32}}
153}; 154};
154 155
155/* Aargh. I missed the reversed bit order, when I
156 * was talking to Renesas about the FPGA.
157 *
158 * The table is used for bit reordering and inversion
159 * of the ecc byte which we get from the FPGA
160 */
161static uint8_t revbits[256] = {
162 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
163 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
164 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
165 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
166 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
167 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
168 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
169 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
170 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
171 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
172 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
173 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
174 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
175 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
176 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
177 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
178 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
179 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
180 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
181 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
182 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
183 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
184 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
185 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
186 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
187 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
188 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
189 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
190 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
191 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
192 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
193 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
194};
195
196#endif 156#endif
197 157
198/* 158/*
@@ -397,7 +357,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
397 /* Read the syndrom pattern from the FPGA and correct the bitorder */ 357 /* Read the syndrom pattern from the FPGA and correct the bitorder */
398 rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); 358 rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
399 for (i = 0; i < 8; i++) { 359 for (i = 0; i < 8; i++) {
400 ecc[i] = revbits[(*rs_ecc) & 0xFF]; 360 ecc[i] = bitrev8(*rs_ecc);
401 rs_ecc++; 361 rs_ecc++;
402 } 362 }
403 363
@@ -496,7 +456,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
496 rtn = nand_do_read(mtd, page, len, &retlen, buf); 456 rtn = nand_do_read(mtd, page, len, &retlen, buf);
497 457
498 /* if read failed or > 1-bit error corrected */ 458 /* if read failed or > 1-bit error corrected */
499 if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) { 459 if (rtn || (mtd->ecc_stats.corrected - corrected) > 1)
500 er_stat |= 1 << 1; 460 er_stat |= 1 << 1;
501 kfree(buf); 461 kfree(buf);
502 } 462 }
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index ff5cef24d5bb..8b3203571eeb 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -283,7 +283,7 @@ static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
283 unsigned int ctrl) 283 unsigned int ctrl)
284{ 284{
285 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 285 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
286 286
287 if (cmd == NAND_CMD_NONE) 287 if (cmd == NAND_CMD_NONE)
288 return; 288 return;
289 289
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index b5a5f8da4722..4b1ba4fcfcd3 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -57,17 +57,16 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
57 57
58 DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); 58 DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
59 59
60 nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); 60 nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
61 61
62 if (!nftl) { 62 if (!nftl) {
63 printk(KERN_WARNING "NFTL: out of memory for data structures\n"); 63 printk(KERN_WARNING "NFTL: out of memory for data structures\n");
64 return; 64 return;
65 } 65 }
66 memset(nftl, 0, sizeof(*nftl));
67 66
68 nftl->mbd.mtd = mtd; 67 nftl->mbd.mtd = mtd;
69 nftl->mbd.devnum = -1; 68 nftl->mbd.devnum = -1;
70 nftl->mbd.blksize = 512; 69
71 nftl->mbd.tr = tr; 70 nftl->mbd.tr = tr;
72 71
73 if (NFTL_mount(nftl) < 0) { 72 if (NFTL_mount(nftl) < 0) {
@@ -147,10 +146,9 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
147 ops.ooblen = len; 146 ops.ooblen = len;
148 ops.oobbuf = buf; 147 ops.oobbuf = buf;
149 ops.datbuf = NULL; 148 ops.datbuf = NULL;
150 ops.len = len;
151 149
152 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 150 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
153 *retlen = ops.retlen; 151 *retlen = ops.oobretlen;
154 return res; 152 return res;
155} 153}
156 154
@@ -168,10 +166,9 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
168 ops.ooblen = len; 166 ops.ooblen = len;
169 ops.oobbuf = buf; 167 ops.oobbuf = buf;
170 ops.datbuf = NULL; 168 ops.datbuf = NULL;
171 ops.len = len;
172 169
173 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 170 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
174 *retlen = ops.retlen; 171 *retlen = ops.oobretlen;
175 return res; 172 return res;
176} 173}
177 174
@@ -797,6 +794,7 @@ static struct mtd_blktrans_ops nftl_tr = {
797 .name = "nftl", 794 .name = "nftl",
798 .major = NFTL_MAJOR, 795 .major = NFTL_MAJOR,
799 .part_bits = NFTL_PARTN_BITS, 796 .part_bits = NFTL_PARTN_BITS,
797 .blksize = 512,
800 .getgeo = nftl_getgeo, 798 .getgeo = nftl_getgeo,
801 .readsect = nftl_readblock, 799 .readsect = nftl_readblock,
802#ifdef CONFIG_NFTL_RW 800#ifdef CONFIG_NFTL_RW
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index af06a80f44de..3d44d040a47d 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -45,12 +45,10 @@ static int __devinit generic_onenand_probe(struct device *dev)
45 unsigned long size = res->end - res->start + 1; 45 unsigned long size = res->end - res->start + 1;
46 int err; 46 int err;
47 47
48 info = kmalloc(sizeof(struct onenand_info), GFP_KERNEL); 48 info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
49 if (!info) 49 if (!info)
50 return -ENOMEM; 50 return -ENOMEM;
51 51
52 memset(info, 0, sizeof(struct onenand_info));
53
54 if (!request_mem_region(res->start, size, dev->driver->name)) { 52 if (!request_mem_region(res->start, size, dev->driver->name)) {
55 err = -EBUSY; 53 err = -EBUSY;
56 goto out_free_info; 54 goto out_free_info;
@@ -63,6 +61,7 @@ static int __devinit generic_onenand_probe(struct device *dev)
63 } 61 }
64 62
65 info->onenand.mmcontrol = pdata->mmcontrol; 63 info->onenand.mmcontrol = pdata->mmcontrol;
64 info->onenand.irq = platform_get_irq(pdev, 0);
66 65
67 info->mtd.name = pdev->dev.bus_id; 66 info->mtd.name = pdev->dev.bus_id;
68 info->mtd.priv = &info->onenand; 67 info->mtd.priv = &info->onenand;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 8ed68b28afe3..2da6bb26353e 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/interrupt.h>
16#include <linux/jiffies.h> 17#include <linux/jiffies.h>
17#include <linux/mtd/mtd.h> 18#include <linux/mtd/mtd.h>
18#include <linux/mtd/onenand.h> 19#include <linux/mtd/onenand.h>
@@ -191,8 +192,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
191 struct onenand_chip *this = mtd->priv; 192 struct onenand_chip *this = mtd->priv;
192 int value, readcmd = 0, block_cmd = 0; 193 int value, readcmd = 0, block_cmd = 0;
193 int block, page; 194 int block, page;
194 /* Now we use page size operation */
195 int sectors = 4, count = 4;
196 195
197 /* Address translation */ 196 /* Address translation */
198 switch (cmd) { 197 switch (cmd) {
@@ -244,6 +243,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
244 } 243 }
245 244
246 if (page != -1) { 245 if (page != -1) {
246 /* Now we use page size operation */
247 int sectors = 4, count = 4;
247 int dataram; 248 int dataram;
248 249
249 switch (cmd) { 250 switch (cmd) {
@@ -297,7 +298,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
297 unsigned long timeout; 298 unsigned long timeout;
298 unsigned int flags = ONENAND_INT_MASTER; 299 unsigned int flags = ONENAND_INT_MASTER;
299 unsigned int interrupt = 0; 300 unsigned int interrupt = 0;
300 unsigned int ctrl, ecc; 301 unsigned int ctrl;
301 302
302 /* The 20 msec is enough */ 303 /* The 20 msec is enough */
303 timeout = jiffies + msecs_to_jiffies(20); 304 timeout = jiffies + msecs_to_jiffies(20);
@@ -309,7 +310,6 @@ static int onenand_wait(struct mtd_info *mtd, int state)
309 310
310 if (state != FL_READING) 311 if (state != FL_READING)
311 cond_resched(); 312 cond_resched();
312 touch_softlockup_watchdog();
313 } 313 }
314 /* To get correct interrupt status in timeout case */ 314 /* To get correct interrupt status in timeout case */
315 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); 315 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -317,28 +317,126 @@ static int onenand_wait(struct mtd_info *mtd, int state)
317 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 317 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
318 318
319 if (ctrl & ONENAND_CTRL_ERROR) { 319 if (ctrl & ONENAND_CTRL_ERROR) {
320 /* It maybe occur at initial bad block */
321 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); 320 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
322 /* Clear other interrupt bits for preventing ECC error */ 321 if (ctrl & ONENAND_CTRL_LOCK)
323 interrupt &= ONENAND_INT_MASTER; 322 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");
324 } 323 return ctrl;
325
326 if (ctrl & ONENAND_CTRL_LOCK) {
327 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
328 return -EACCES;
329 } 324 }
330 325
331 if (interrupt & ONENAND_INT_READ) { 326 if (interrupt & ONENAND_INT_READ) {
332 ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 327 int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
333 if (ecc & ONENAND_ECC_2BIT_ALL) { 328 if (ecc) {
334 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); 329 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
335 return -EBADMSG; 330 if (ecc & ONENAND_ECC_2BIT_ALL) {
331 mtd->ecc_stats.failed++;
332 return ecc;
333 } else if (ecc & ONENAND_ECC_1BIT_ALL)
334 mtd->ecc_stats.corrected++;
336 } 335 }
337 } 336 }
338 337
339 return 0; 338 return 0;
340} 339}
341 340
341/*
342 * onenand_interrupt - [DEFAULT] onenand interrupt handler
343 * @param irq onenand interrupt number
344 * @param dev_id interrupt data
345 *
346 * complete the work
347 */
348static irqreturn_t onenand_interrupt(int irq, void *data)
349{
350 struct onenand_chip *this = (struct onenand_chip *) data;
351
352 /* To handle shared interrupt */
353 if (!this->complete.done)
354 complete(&this->complete);
355
356 return IRQ_HANDLED;
357}
358
359/*
360 * onenand_interrupt_wait - [DEFAULT] wait until the command is done
361 * @param mtd MTD device structure
362 * @param state state to select the max. timeout value
363 *
364 * Wait for command done.
365 */
366static int onenand_interrupt_wait(struct mtd_info *mtd, int state)
367{
368 struct onenand_chip *this = mtd->priv;
369
370 wait_for_completion(&this->complete);
371
372 return onenand_wait(mtd, state);
373}
374
375/*
376 * onenand_try_interrupt_wait - [DEFAULT] try interrupt wait
377 * @param mtd MTD device structure
378 * @param state state to select the max. timeout value
379 *
380 * Try interrupt based wait (It is used one-time)
381 */
382static int onenand_try_interrupt_wait(struct mtd_info *mtd, int state)
383{
384 struct onenand_chip *this = mtd->priv;
385 unsigned long remain, timeout;
386
387 /* We use interrupt wait first */
388 this->wait = onenand_interrupt_wait;
389
390 timeout = msecs_to_jiffies(100);
391 remain = wait_for_completion_timeout(&this->complete, timeout);
392 if (!remain) {
393 printk(KERN_INFO "OneNAND: There's no interrupt. "
394 "We use the normal wait\n");
395
396 /* Release the irq */
397 free_irq(this->irq, this);
398
399 this->wait = onenand_wait;
400 }
401
402 return onenand_wait(mtd, state);
403}
404
405/*
406 * onenand_setup_wait - [OneNAND Interface] setup onenand wait method
407 * @param mtd MTD device structure
408 *
409 * There's two method to wait onenand work
410 * 1. polling - read interrupt status register
411 * 2. interrupt - use the kernel interrupt method
412 */
413static void onenand_setup_wait(struct mtd_info *mtd)
414{
415 struct onenand_chip *this = mtd->priv;
416 int syscfg;
417
418 init_completion(&this->complete);
419
420 if (this->irq <= 0) {
421 this->wait = onenand_wait;
422 return;
423 }
424
425 if (request_irq(this->irq, &onenand_interrupt,
426 IRQF_SHARED, "onenand", this)) {
427 /* If we can't get irq, use the normal wait */
428 this->wait = onenand_wait;
429 return;
430 }
431
432 /* Enable interrupt */
433 syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
434 syscfg |= ONENAND_SYS_CFG1_IOBE;
435 this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
436
437 this->wait = onenand_try_interrupt_wait;
438}
439
342/** 440/**
343 * onenand_bufferram_offset - [DEFAULT] BufferRAM offset 441 * onenand_bufferram_offset - [DEFAULT] BufferRAM offset
344 * @param mtd MTD data structure 442 * @param mtd MTD data structure
@@ -609,9 +707,10 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
609 size_t *retlen, u_char *buf) 707 size_t *retlen, u_char *buf)
610{ 708{
611 struct onenand_chip *this = mtd->priv; 709 struct onenand_chip *this = mtd->priv;
710 struct mtd_ecc_stats stats;
612 int read = 0, column; 711 int read = 0, column;
613 int thislen; 712 int thislen;
614 int ret = 0; 713 int ret = 0, boundary = 0;
615 714
616 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 715 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
617 716
@@ -627,38 +726,61 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
627 726
628 /* TODO handling oob */ 727 /* TODO handling oob */
629 728
630 while (read < len) { 729 stats = mtd->ecc_stats;
631 thislen = min_t(int, mtd->writesize, len - read); 730
632 731 /* Read-while-load method */
633 column = from & (mtd->writesize - 1); 732
634 if (column + thislen > mtd->writesize) 733 /* Do first load to bufferRAM */
635 thislen = mtd->writesize - column; 734 if (read < len) {
636 735 if (!onenand_check_bufferram(mtd, from)) {
637 if (!onenand_check_bufferram(mtd, from)) { 736 this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
638 this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); 737 ret = this->wait(mtd, FL_READING);
639 738 onenand_update_bufferram(mtd, from, !ret);
640 ret = this->wait(mtd, FL_READING); 739 }
641 /* First copy data and check return value for ECC handling */ 740 }
642 onenand_update_bufferram(mtd, from, 1); 741
643 } 742 thislen = min_t(int, mtd->writesize, len - read);
644 743 column = from & (mtd->writesize - 1);
645 this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); 744 if (column + thislen > mtd->writesize)
646 745 thislen = mtd->writesize - column;
647 read += thislen; 746
648 747 while (!ret) {
649 if (read == len) 748 /* If there is more to load then start next load */
650 break; 749 from += thislen;
651 750 if (read + thislen < len) {
652 if (ret) { 751 this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
653 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret); 752 /*
654 goto out; 753 * Chip boundary handling in DDP
655 } 754 * Now we issued chip 1 read and pointed chip 1
656 755 * bufferam so we have to point chip 0 bufferam.
657 from += thislen; 756 */
658 buf += thislen; 757 if (this->device_id & ONENAND_DEVICE_IS_DDP &&
659 } 758 unlikely(from == (this->chipsize >> 1))) {
759 this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2);
760 boundary = 1;
761 } else
762 boundary = 0;
763 ONENAND_SET_PREV_BUFFERRAM(this);
764 }
765 /* While load is going, read from last bufferRAM */
766 this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
767 /* See if we are done */
768 read += thislen;
769 if (read == len)
770 break;
771 /* Set up for next read from bufferRAM */
772 if (unlikely(boundary))
773 this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2);
774 ONENAND_SET_NEXT_BUFFERRAM(this);
775 buf += thislen;
776 thislen = min_t(int, mtd->writesize, len - read);
777 column = 0;
778 cond_resched();
779 /* Now wait for load */
780 ret = this->wait(mtd, FL_READING);
781 onenand_update_bufferram(mtd, from, !ret);
782 }
660 783
661out:
662 /* Deselect and wake up anyone waiting on the device */ 784 /* Deselect and wake up anyone waiting on the device */
663 onenand_release_device(mtd); 785 onenand_release_device(mtd);
664 786
@@ -668,7 +790,14 @@ out:
668 * retlen == desired len and result == -EBADMSG 790 * retlen == desired len and result == -EBADMSG
669 */ 791 */
670 *retlen = read; 792 *retlen = read;
671 return ret; 793
794 if (mtd->ecc_stats.failed - stats.failed)
795 return -EBADMSG;
796
797 if (ret)
798 return ret;
799
800 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
672} 801}
673 802
674/** 803/**
@@ -705,6 +834,8 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
705 column = from & (mtd->oobsize - 1); 834 column = from & (mtd->oobsize - 1);
706 835
707 while (read < len) { 836 while (read < len) {
837 cond_resched();
838
708 thislen = mtd->oobsize - column; 839 thislen = mtd->oobsize - column;
709 thislen = min_t(int, thislen, len); 840 thislen = min_t(int, thislen, len);
710 841
@@ -717,16 +848,16 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
717 848
718 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 849 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
719 850
851 if (ret) {
852 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);
853 goto out;
854 }
855
720 read += thislen; 856 read += thislen;
721 857
722 if (read == len) 858 if (read == len)
723 break; 859 break;
724 860
725 if (ret) {
726 DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret);
727 goto out;
728 }
729
730 buf += thislen; 861 buf += thislen;
731 862
732 /* Read more? */ 863 /* Read more? */
@@ -756,8 +887,8 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
756{ 887{
757 BUG_ON(ops->mode != MTD_OOB_PLACE); 888 BUG_ON(ops->mode != MTD_OOB_PLACE);
758 889
759 return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len, 890 return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen,
760 &ops->retlen, ops->oobbuf); 891 &ops->oobretlen, ops->oobbuf);
761} 892}
762 893
763#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE 894#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
@@ -804,6 +935,10 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
804 void __iomem *dataram0, *dataram1; 935 void __iomem *dataram0, *dataram1;
805 int ret = 0; 936 int ret = 0;
806 937
938 /* In partial page write, just skip it */
939 if ((addr & (mtd->writesize - 1)) != 0)
940 return 0;
941
807 this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize); 942 this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
808 943
809 ret = this->wait(mtd, FL_READING); 944 ret = this->wait(mtd, FL_READING);
@@ -826,7 +961,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
826#define onenand_verify_oob(...) (0) 961#define onenand_verify_oob(...) (0)
827#endif 962#endif
828 963
829#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0) 964#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)
830 965
831/** 966/**
832 * onenand_write - [MTD Interface] write buffer to FLASH 967 * onenand_write - [MTD Interface] write buffer to FLASH
@@ -844,6 +979,7 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
844 struct onenand_chip *this = mtd->priv; 979 struct onenand_chip *this = mtd->priv;
845 int written = 0; 980 int written = 0;
846 int ret = 0; 981 int ret = 0;
982 int column, subpage;
847 983
848 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 984 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
849 985
@@ -862,45 +998,63 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
862 return -EINVAL; 998 return -EINVAL;
863 } 999 }
864 1000
1001 column = to & (mtd->writesize - 1);
1002 subpage = column || (len & (mtd->writesize - 1));
1003
865 /* Grab the lock and see if the device is available */ 1004 /* Grab the lock and see if the device is available */
866 onenand_get_device(mtd, FL_WRITING); 1005 onenand_get_device(mtd, FL_WRITING);
867 1006
868 /* Loop until all data write */ 1007 /* Loop until all data write */
869 while (written < len) { 1008 while (written < len) {
870 int thislen = min_t(int, mtd->writesize, len - written); 1009 int bytes = mtd->writesize;
871 1010 int thislen = min_t(int, bytes, len - written);
872 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize); 1011 u_char *wbuf = (u_char *) buf;
1012
1013 cond_resched();
1014
1015 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes);
1016
1017 /* Partial page write */
1018 if (subpage) {
1019 bytes = min_t(int, bytes - column, (int) len);
1020 memset(this->page_buf, 0xff, mtd->writesize);
1021 memcpy(this->page_buf + column, buf, bytes);
1022 wbuf = this->page_buf;
1023 /* Even though partial write, we need page size */
1024 thislen = mtd->writesize;
1025 }
873 1026
874 this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); 1027 this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen);
875 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); 1028 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
876 1029
877 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize); 1030 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
878 1031
879 onenand_update_bufferram(mtd, to, 1); 1032 /* In partial page write we don't update bufferram */
1033 onenand_update_bufferram(mtd, to, !subpage);
880 1034
881 ret = this->wait(mtd, FL_WRITING); 1035 ret = this->wait(mtd, FL_WRITING);
882 if (ret) { 1036 if (ret) {
883 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret); 1037 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
884 goto out; 1038 break;
885 } 1039 }
886 1040
887 written += thislen;
888
889 /* Only check verify write turn on */ 1041 /* Only check verify write turn on */
890 ret = onenand_verify_page(mtd, (u_char *) buf, to); 1042 ret = onenand_verify_page(mtd, (u_char *) wbuf, to);
891 if (ret) { 1043 if (ret) {
892 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret); 1044 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
893 goto out; 1045 break;
894 } 1046 }
895 1047
1048 written += thislen;
1049
896 if (written == len) 1050 if (written == len)
897 break; 1051 break;
898 1052
1053 column = 0;
899 to += thislen; 1054 to += thislen;
900 buf += thislen; 1055 buf += thislen;
901 } 1056 }
902 1057
903out:
904 /* Deselect and wake up anyone waiting on the device */ 1058 /* Deselect and wake up anyone waiting on the device */
905 onenand_release_device(mtd); 1059 onenand_release_device(mtd);
906 1060
@@ -944,6 +1098,8 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
944 while (written < len) { 1098 while (written < len) {
945 int thislen = min_t(int, mtd->oobsize, len - written); 1099 int thislen = min_t(int, mtd->oobsize, len - written);
946 1100
1101 cond_resched();
1102
947 column = to & (mtd->oobsize - 1); 1103 column = to & (mtd->oobsize - 1);
948 1104
949 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize); 1105 this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
@@ -999,8 +1155,8 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
999{ 1155{
1000 BUG_ON(ops->mode != MTD_OOB_PLACE); 1156 BUG_ON(ops->mode != MTD_OOB_PLACE);
1001 1157
1002 return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len, 1158 return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen,
1003 &ops->retlen, ops->oobbuf); 1159 &ops->oobretlen, ops->oobbuf);
1004} 1160}
1005 1161
1006/** 1162/**
@@ -1071,6 +1227,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1071 instr->state = MTD_ERASING; 1227 instr->state = MTD_ERASING;
1072 1228
1073 while (len) { 1229 while (len) {
1230 cond_resched();
1074 1231
1075 /* Check if we have a bad block, we do not erase bad blocks */ 1232 /* Check if we have a bad block, we do not erase bad blocks */
1076 if (onenand_block_checkbad(mtd, addr, 0, 0)) { 1233 if (onenand_block_checkbad(mtd, addr, 0, 0)) {
@@ -1084,10 +1241,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
1084 ret = this->wait(mtd, FL_ERASING); 1241 ret = this->wait(mtd, FL_ERASING);
1085 /* Check, if it is write protected */ 1242 /* Check, if it is write protected */
1086 if (ret) { 1243 if (ret) {
1087 if (ret == -EPERM) 1244 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
1088 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n");
1089 else
1090 DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
1091 instr->state = MTD_ERASE_FAILED; 1245 instr->state = MTD_ERASE_FAILED;
1092 instr->fail_addr = addr; 1246 instr->fail_addr = addr;
1093 goto erase_exit; 1247 goto erase_exit;
@@ -1129,7 +1283,6 @@ static void onenand_sync(struct mtd_info *mtd)
1129 onenand_release_device(mtd); 1283 onenand_release_device(mtd);
1130} 1284}
1131 1285
1132
1133/** 1286/**
1134 * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad 1287 * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
1135 * @param mtd MTD device structure 1288 * @param mtd MTD device structure
@@ -1196,32 +1349,38 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
1196} 1349}
1197 1350
1198/** 1351/**
1199 * onenand_unlock - [MTD Interface] Unlock block(s) 1352 * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s)
1200 * @param mtd MTD device structure 1353 * @param mtd MTD device structure
1201 * @param ofs offset relative to mtd start 1354 * @param ofs offset relative to mtd start
1202 * @param len number of bytes to unlock 1355 * @param len number of bytes to lock or unlock
1203 * 1356 *
1204 * Unlock one or more blocks 1357 * Lock or unlock one or more blocks
1205 */ 1358 */
1206static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1359static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
1207{ 1360{
1208 struct onenand_chip *this = mtd->priv; 1361 struct onenand_chip *this = mtd->priv;
1209 int start, end, block, value, status; 1362 int start, end, block, value, status;
1363 int wp_status_mask;
1210 1364
1211 start = ofs >> this->erase_shift; 1365 start = ofs >> this->erase_shift;
1212 end = len >> this->erase_shift; 1366 end = len >> this->erase_shift;
1213 1367
1368 if (cmd == ONENAND_CMD_LOCK)
1369 wp_status_mask = ONENAND_WP_LS;
1370 else
1371 wp_status_mask = ONENAND_WP_US;
1372
1214 /* Continuous lock scheme */ 1373 /* Continuous lock scheme */
1215 if (this->options & ONENAND_HAS_CONT_LOCK) { 1374 if (this->options & ONENAND_HAS_CONT_LOCK) {
1216 /* Set start block address */ 1375 /* Set start block address */
1217 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1376 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
1218 /* Set end block address */ 1377 /* Set end block address */
1219 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 1378 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
1220 /* Write unlock command */ 1379 /* Write lock command */
1221 this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1380 this->command(mtd, cmd, 0, 0);
1222 1381
1223 /* There's no return value */ 1382 /* There's no return value */
1224 this->wait(mtd, FL_UNLOCKING); 1383 this->wait(mtd, FL_LOCKING);
1225 1384
1226 /* Sanity check */ 1385 /* Sanity check */
1227 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1386 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1230,7 +1389,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1230 1389
1231 /* Check lock status */ 1390 /* Check lock status */
1232 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1391 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
1233 if (!(status & ONENAND_WP_US)) 1392 if (!(status & wp_status_mask))
1234 printk(KERN_ERR "wp status = 0x%x\n", status); 1393 printk(KERN_ERR "wp status = 0x%x\n", status);
1235 1394
1236 return 0; 1395 return 0;
@@ -1246,11 +1405,11 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1246 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 1405 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
1247 /* Set start block address */ 1406 /* Set start block address */
1248 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1407 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
1249 /* Write unlock command */ 1408 /* Write lock command */
1250 this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1409 this->command(mtd, cmd, 0, 0);
1251 1410
1252 /* There's no return value */ 1411 /* There's no return value */
1253 this->wait(mtd, FL_UNLOCKING); 1412 this->wait(mtd, FL_LOCKING);
1254 1413
1255 /* Sanity check */ 1414 /* Sanity check */
1256 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1415 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1259,7 +1418,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1259 1418
1260 /* Check lock status */ 1419 /* Check lock status */
1261 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1420 status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
1262 if (!(status & ONENAND_WP_US)) 1421 if (!(status & wp_status_mask))
1263 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); 1422 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
1264 } 1423 }
1265 1424
@@ -1267,6 +1426,32 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1267} 1426}
1268 1427
1269/** 1428/**
1429 * onenand_lock - [MTD Interface] Lock block(s)
1430 * @param mtd MTD device structure
1431 * @param ofs offset relative to mtd start
1432 * @param len number of bytes to unlock
1433 *
1434 * Lock one or more blocks
1435 */
1436static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
1437{
1438 return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
1439}
1440
1441/**
1442 * onenand_unlock - [MTD Interface] Unlock block(s)
1443 * @param mtd MTD device structure
1444 * @param ofs offset relative to mtd start
1445 * @param len number of bytes to unlock
1446 *
1447 * Unlock one or more blocks
1448 */
1449static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1450{
1451 return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
1452}
1453
1454/**
1270 * onenand_check_lock_status - [OneNAND Interface] Check lock status 1455 * onenand_check_lock_status - [OneNAND Interface] Check lock status
1271 * @param this onenand chip data structure 1456 * @param this onenand chip data structure
1272 * 1457 *
@@ -1310,7 +1495,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
1310 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0); 1495 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
1311 1496
1312 /* There's no return value */ 1497 /* There's no return value */
1313 this->wait(mtd, FL_UNLOCKING); 1498 this->wait(mtd, FL_LOCKING);
1314 1499
1315 /* Sanity check */ 1500 /* Sanity check */
1316 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) 1501 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1334,7 +1519,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
1334 return 0; 1519 return 0;
1335 } 1520 }
1336 1521
1337 mtd->unlock(mtd, 0x0, this->chipsize); 1522 onenand_unlock(mtd, 0x0, this->chipsize);
1338 1523
1339 return 0; 1524 return 0;
1340} 1525}
@@ -1762,7 +1947,7 @@ static int onenand_probe(struct mtd_info *mtd)
1762 /* Read manufacturer and device IDs from Register */ 1947 /* Read manufacturer and device IDs from Register */
1763 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 1948 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
1764 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 1949 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
1765 ver_id= this->read_word(this->base + ONENAND_REG_VERSION_ID); 1950 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
1766 1951
1767 /* Check OneNAND device */ 1952 /* Check OneNAND device */
1768 if (maf_id != bram_maf_id || dev_id != bram_dev_id) 1953 if (maf_id != bram_maf_id || dev_id != bram_dev_id)
@@ -1846,7 +2031,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
1846 if (!this->command) 2031 if (!this->command)
1847 this->command = onenand_command; 2032 this->command = onenand_command;
1848 if (!this->wait) 2033 if (!this->wait)
1849 this->wait = onenand_wait; 2034 onenand_setup_wait(mtd);
1850 2035
1851 if (!this->read_bufferram) 2036 if (!this->read_bufferram)
1852 this->read_bufferram = onenand_read_bufferram; 2037 this->read_bufferram = onenand_read_bufferram;
@@ -1883,23 +2068,30 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
1883 init_waitqueue_head(&this->wq); 2068 init_waitqueue_head(&this->wq);
1884 spin_lock_init(&this->chip_lock); 2069 spin_lock_init(&this->chip_lock);
1885 2070
2071 /*
2072 * Allow subpage writes up to oobsize.
2073 */
1886 switch (mtd->oobsize) { 2074 switch (mtd->oobsize) {
1887 case 64: 2075 case 64:
1888 this->ecclayout = &onenand_oob_64; 2076 this->ecclayout = &onenand_oob_64;
2077 mtd->subpage_sft = 2;
1889 break; 2078 break;
1890 2079
1891 case 32: 2080 case 32:
1892 this->ecclayout = &onenand_oob_32; 2081 this->ecclayout = &onenand_oob_32;
2082 mtd->subpage_sft = 1;
1893 break; 2083 break;
1894 2084
1895 default: 2085 default:
1896 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", 2086 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
1897 mtd->oobsize); 2087 mtd->oobsize);
2088 mtd->subpage_sft = 0;
1898 /* To prevent kernel oops */ 2089 /* To prevent kernel oops */
1899 this->ecclayout = &onenand_oob_32; 2090 this->ecclayout = &onenand_oob_32;
1900 break; 2091 break;
1901 } 2092 }
1902 2093
2094 this->subpagesize = mtd->writesize >> mtd->subpage_sft;
1903 mtd->ecclayout = this->ecclayout; 2095 mtd->ecclayout = this->ecclayout;
1904 2096
1905 /* Fill in remaining MTD driver data */ 2097 /* Fill in remaining MTD driver data */
@@ -1922,7 +2114,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
1922 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg; 2114 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
1923#endif 2115#endif
1924 mtd->sync = onenand_sync; 2116 mtd->sync = onenand_sync;
1925 mtd->lock = NULL; 2117 mtd->lock = onenand_lock;
1926 mtd->unlock = onenand_unlock; 2118 mtd->unlock = onenand_unlock;
1927 mtd->suspend = onenand_suspend; 2119 mtd->suspend = onenand_suspend;
1928 mtd->resume = onenand_resume; 2120 mtd->resume = onenand_resume;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 1b00dac3d7d6..98f8fd1c6375 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -93,13 +93,15 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
93 ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs, 93 ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
94 readlen, &retlen, &buf[0]); 94 readlen, &retlen, &buf[0]);
95 95
96 if (ret) 96 /* If it is a initial bad block, just ignore it */
97 if (ret && !(ret & ONENAND_CTRL_LOAD))
97 return ret; 98 return ret;
98 99
99 if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { 100 if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
100 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); 101 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
101 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 102 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
102 i >> 1, (unsigned int) from); 103 i >> 1, (unsigned int) from);
104 mtd->ecc_stats.badblocks++;
103 break; 105 break;
104 } 106 }
105 } 107 }
@@ -177,14 +179,12 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
177 int len, ret = 0; 179 int len, ret = 0;
178 180
179 len = mtd->size >> (this->erase_shift + 2); 181 len = mtd->size >> (this->erase_shift + 2);
180 /* Allocate memory (2bit per block) */ 182 /* Allocate memory (2bit per block) and clear the memory bad block table */
181 bbm->bbt = kmalloc(len, GFP_KERNEL); 183 bbm->bbt = kzalloc(len, GFP_KERNEL);
182 if (!bbm->bbt) { 184 if (!bbm->bbt) {
183 printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); 185 printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
184 return -ENOMEM; 186 return -ENOMEM;
185 } 187 }
186 /* Clear the memory bad block table */
187 memset(bbm->bbt, 0x00, len);
188 188
189 /* Set the bad block position */ 189 /* Set the bad block position */
190 bbm->badblockpos = ONENAND_BADBLOCK_POS; 190 bbm->badblockpos = ONENAND_BADBLOCK_POS;
@@ -230,14 +230,12 @@ int onenand_default_bbt(struct mtd_info *mtd)
230 struct onenand_chip *this = mtd->priv; 230 struct onenand_chip *this = mtd->priv;
231 struct bbm_info *bbm; 231 struct bbm_info *bbm;
232 232
233 this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL); 233 this->bbm = kzalloc(sizeof(struct bbm_info), GFP_KERNEL);
234 if (!this->bbm) 234 if (!this->bbm)
235 return -ENOMEM; 235 return -ENOMEM;
236 236
237 bbm = this->bbm; 237 bbm = this->bbm;
238 238
239 memset(bbm, 0, sizeof(struct bbm_info));
240
241 /* 1KB page has same configuration as 2KB page */ 239 /* 1KB page has same configuration as 2KB page */
242 if (!bbm->badblock_pattern) 240 if (!bbm->badblock_pattern)
243 bbm->badblock_pattern = &largepage_memorybased; 241 bbm->badblock_pattern = &largepage_memorybased;
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 5b58523e4d4e..035cd9b0cc08 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -96,7 +96,19 @@ static int parse_redboot_partitions(struct mtd_info *master,
96 */ 96 */
97 if (swab32(buf[i].size) == master->erasesize) { 97 if (swab32(buf[i].size) == master->erasesize) {
98 int j; 98 int j;
99 for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) { 99 for (j = 0; j < numslots; ++j) {
100
101 /* A single 0xff denotes a deleted entry.
102 * Two of them in a row is the end of the table.
103 */
104 if (buf[j].name[0] == 0xff) {
105 if (buf[j].name[1] == 0xff) {
106 break;
107 } else {
108 continue;
109 }
110 }
111
100 /* The unsigned long fields were written with the 112 /* The unsigned long fields were written with the
101 * wrong byte sex, name and pad have no byte sex. 113 * wrong byte sex, name and pad have no byte sex.
102 */ 114 */
@@ -110,6 +122,9 @@ static int parse_redboot_partitions(struct mtd_info *master,
110 } 122 }
111 } 123 }
112 break; 124 break;
125 } else {
126 /* re-calculate of real numslots */
127 numslots = buf[i].size / sizeof(struct fis_image_desc);
113 } 128 }
114 } 129 }
115 if (i == numslots) { 130 if (i == numslots) {
@@ -123,8 +138,13 @@ static int parse_redboot_partitions(struct mtd_info *master,
123 for (i = 0; i < numslots; i++) { 138 for (i = 0; i < numslots; i++) {
124 struct fis_list *new_fl, **prev; 139 struct fis_list *new_fl, **prev;
125 140
126 if (buf[i].name[0] == 0xff) 141 if (buf[i].name[0] == 0xff) {
127 continue; 142 if (buf[i].name[1] == 0xff) {
143 break;
144 } else {
145 continue;
146 }
147 }
128 if (!redboot_checksum(&buf[i])) 148 if (!redboot_checksum(&buf[i]))
129 break; 149 break;
130 150
@@ -165,15 +185,13 @@ static int parse_redboot_partitions(struct mtd_info *master,
165 } 185 }
166 } 186 }
167#endif 187#endif
168 parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL); 188 parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
169 189
170 if (!parts) { 190 if (!parts) {
171 ret = -ENOMEM; 191 ret = -ENOMEM;
172 goto out; 192 goto out;
173 } 193 }
174 194
175 memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
176
177 nullname = (char *)&parts[nrparts]; 195 nullname = (char *)&parts[nrparts];
178#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED 196#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
179 if (nulllen > 0) { 197 if (nulllen > 0) {
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 0f3baa5d9c2a..d4b1ba8f23ef 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -787,7 +787,6 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
787 787
788 if (scan_header(part) == 0) { 788 if (scan_header(part) == 0) {
789 part->mbd.size = part->sector_count; 789 part->mbd.size = part->sector_count;
790 part->mbd.blksize = SECTOR_SIZE;
791 part->mbd.tr = tr; 790 part->mbd.tr = tr;
792 part->mbd.devnum = -1; 791 part->mbd.devnum = -1;
793 if (!(mtd->flags & MTD_WRITEABLE)) 792 if (!(mtd->flags & MTD_WRITEABLE))
@@ -829,6 +828,8 @@ struct mtd_blktrans_ops rfd_ftl_tr = {
829 .name = "rfd", 828 .name = "rfd",
830 .major = RFD_FTL_MAJOR, 829 .major = RFD_FTL_MAJOR,
831 .part_bits = PART_BITS, 830 .part_bits = PART_BITS,
831 .blksize = SECTOR_SIZE,
832
832 .readsect = rfd_ftl_readsect, 833 .readsect = rfd_ftl_readsect,
833 .writesect = rfd_ftl_writesect, 834 .writesect = rfd_ftl_writesect,
834 .getgeo = rfd_ftl_getgeo, 835 .getgeo = rfd_ftl_getgeo,
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 79d3bb659bfe..a5f3d60047d4 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -172,13 +172,12 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
172 172
173 ops.mode = MTD_OOB_RAW; 173 ops.mode = MTD_OOB_RAW;
174 ops.ooboffs = 0; 174 ops.ooboffs = 0;
175 ops.ooblen = mtd->oobsize; 175 ops.ooblen = OOB_SIZE;
176 ops.len = OOB_SIZE;
177 ops.oobbuf = buf; 176 ops.oobbuf = buf;
178 ops.datbuf = NULL; 177 ops.datbuf = NULL;
179 178
180 ret = mtd->read_oob(mtd, offs, &ops); 179 ret = mtd->read_oob(mtd, offs, &ops);
181 if (ret < 0 || ops.retlen != OOB_SIZE) 180 if (ret < 0 || ops.oobretlen != OOB_SIZE)
182 return -1; 181 return -1;
183 182
184 return 0; 183 return 0;
@@ -312,7 +311,6 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
312 311
313 ssfdc->mbd.mtd = mtd; 312 ssfdc->mbd.mtd = mtd;
314 ssfdc->mbd.devnum = -1; 313 ssfdc->mbd.devnum = -1;
315 ssfdc->mbd.blksize = SECTOR_SIZE;
316 ssfdc->mbd.tr = tr; 314 ssfdc->mbd.tr = tr;
317 ssfdc->mbd.readonly = 1; 315 ssfdc->mbd.readonly = 1;
318 316
@@ -447,6 +445,7 @@ static struct mtd_blktrans_ops ssfdcr_tr = {
447 .name = "ssfdc", 445 .name = "ssfdc",
448 .major = SSFDCR_MAJOR, 446 .major = SSFDCR_MAJOR,
449 .part_bits = SSFDCR_PARTN_BITS, 447 .part_bits = SSFDCR_PARTN_BITS,
448 .blksize = SECTOR_SIZE,
450 .getgeo = ssfdcr_getgeo, 449 .getgeo = ssfdcr_getgeo,
451 .readsect = ssfdcr_readsect, 450 .readsect = ssfdcr_readsect,
452 .add_mtd = ssfdcr_add_mtd, 451 .add_mtd = ssfdcr_add_mtd,
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index 077258b2103e..5a95fbdd6fdb 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -17,6 +17,7 @@
17 * 17 *
18 */ 18 */
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/err.h>
20#include <linux/blkdev.h> 21#include <linux/blkdev.h>
21#include <linux/jffs.h> 22#include <linux/jffs.h>
22#include "jffs_fm.h" 23#include "jffs_fm.h"
@@ -104,7 +105,7 @@ jffs_build_begin(struct jffs_control *c, int unit)
104 105
105 mtd = get_mtd_device(NULL, unit); 106 mtd = get_mtd_device(NULL, unit);
106 107
107 if (!mtd) { 108 if (IS_ERR(mtd)) {
108 kfree(fmc); 109 kfree(fmc);
109 DJM(no_jffs_fmcontrol--); 110 DJM(no_jffs_fmcontrol--);
110 return NULL; 111 return NULL;
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 72b4fc13a106..4189e4a36050 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -178,8 +178,8 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
178 while (ref2) { 178 while (ref2) {
179 uint32_t totlen = ref_totlen(c, jeb, ref2); 179 uint32_t totlen = ref_totlen(c, jeb, ref2);
180 180
181 if (ref2->flash_offset < jeb->offset || 181 if (ref_offset(ref2) < jeb->offset ||
182 ref2->flash_offset > jeb->offset + c->sector_size) { 182 ref_offset(ref2) > jeb->offset + c->sector_size) {
183 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", 183 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
184 ref_offset(ref2), jeb->offset); 184 ref_offset(ref2), jeb->offset);
185 goto error; 185 goto error;
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 3daf3bca0376..f89c85d5a3f8 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -13,6 +13,7 @@
13#ifndef _JFFS2_DEBUG_H_ 13#ifndef _JFFS2_DEBUG_H_
14#define _JFFS2_DEBUG_H_ 14#define _JFFS2_DEBUG_H_
15 15
16#include <linux/sched.h>
16 17
17#ifndef CONFIG_JFFS2_FS_DEBUG 18#ifndef CONFIG_JFFS2_FS_DEBUG
18#define CONFIG_JFFS2_FS_DEBUG 0 19#define CONFIG_JFFS2_FS_DEBUG 0
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 7bc1a4201c0c..abb90c0c09cc 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -502,12 +502,11 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
502 if (ret) 502 if (ret)
503 return ret; 503 return ret;
504 504
505 c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL); 505 c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
506 if (!c->inocache_list) { 506 if (!c->inocache_list) {
507 ret = -ENOMEM; 507 ret = -ENOMEM;
508 goto out_wbuf; 508 goto out_wbuf;
509 } 509 }
510 memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
511 510
512 jffs2_init_xattr_subsystem(c); 511 jffs2_init_xattr_subsystem(c);
513 512
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index daff3341ff92..3a3cf225981f 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -838,6 +838,8 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
838 838
839 for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { 839 for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
840 840
841 cond_resched();
842
841 /* We only care about obsolete ones */ 843 /* We only care about obsolete ones */
842 if (!(ref_obsolete(raw))) 844 if (!(ref_obsolete(raw)))
843 continue; 845 continue;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 0ddfd70307fb..4178b4b55948 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -294,23 +294,21 @@ static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
294 294
295static inline struct jffs2_node_frag *frag_first(struct rb_root *root) 295static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
296{ 296{
297 struct rb_node *node = root->rb_node; 297 struct rb_node *node = rb_first(root);
298 298
299 if (!node) 299 if (!node)
300 return NULL; 300 return NULL;
301 while(node->rb_left) 301
302 node = node->rb_left;
303 return rb_entry(node, struct jffs2_node_frag, rb); 302 return rb_entry(node, struct jffs2_node_frag, rb);
304} 303}
305 304
306static inline struct jffs2_node_frag *frag_last(struct rb_root *root) 305static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
307{ 306{
308 struct rb_node *node = root->rb_node; 307 struct rb_node *node = rb_last(root);
309 308
310 if (!node) 309 if (!node)
311 return NULL; 310 return NULL;
312 while(node->rb_right) 311
313 node = node->rb_right;
314 return rb_entry(node, struct jffs2_node_frag, rb); 312 return rb_entry(node, struct jffs2_node_frag, rb);
315} 313}
316 314
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 266423b2709d..58a0b912e9d0 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -944,13 +944,12 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
944int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 944int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
945{ 945{
946 struct jffs2_raw_inode n; 946 struct jffs2_raw_inode n;
947 struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); 947 struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL);
948 int ret; 948 int ret;
949 949
950 if (!f) 950 if (!f)
951 return -ENOMEM; 951 return -ENOMEM;
952 952
953 memset(f, 0, sizeof(*f));
954 init_MUTEX_LOCKED(&f->sem); 953 init_MUTEX_LOCKED(&f->sem);
955 f->inocache = ic; 954 f->inocache = ic;
956 955
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index e2413466ddd5..3af746eaff0e 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -128,17 +128,19 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
128 } 128 }
129 129
130 if (jffs2_sum_active()) { 130 if (jffs2_sum_active()) {
131 s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); 131 s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
132 if (!s) { 132 if (!s) {
133 kfree(flashbuf);
133 JFFS2_WARNING("Can't allocate memory for summary\n"); 134 JFFS2_WARNING("Can't allocate memory for summary\n");
134 return -ENOMEM; 135 return -ENOMEM;
135 } 136 }
136 memset(s, 0, sizeof(struct jffs2_summary));
137 } 137 }
138 138
139 for (i=0; i<c->nr_blocks; i++) { 139 for (i=0; i<c->nr_blocks; i++) {
140 struct jffs2_eraseblock *jeb = &c->blocks[i]; 140 struct jffs2_eraseblock *jeb = &c->blocks[i];
141 141
142 cond_resched();
143
142 /* reset summary info for next eraseblock scan */ 144 /* reset summary info for next eraseblock scan */
143 jffs2_sum_reset_collected(s); 145 jffs2_sum_reset_collected(s);
144 146
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index e52cef526d90..25265965bdc1 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -26,15 +26,13 @@
26 26
27int jffs2_sum_init(struct jffs2_sb_info *c) 27int jffs2_sum_init(struct jffs2_sb_info *c)
28{ 28{
29 c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); 29 c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
30 30
31 if (!c->summary) { 31 if (!c->summary) {
32 JFFS2_WARNING("Can't allocate memory for summary information!\n"); 32 JFFS2_WARNING("Can't allocate memory for summary information!\n");
33 return -ENOMEM; 33 return -ENOMEM;
34 } 34 }
35 35
36 memset(c->summary, 0, sizeof(struct jffs2_summary));
37
38 c->summary->sum_buf = vmalloc(c->sector_size); 36 c->summary->sum_buf = vmalloc(c->sector_size);
39 37
40 if (!c->summary->sum_buf) { 38 if (!c->summary->sum_buf) {
@@ -398,6 +396,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
398 for (i=0; i<je32_to_cpu(summary->sum_num); i++) { 396 for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
399 dbg_summary("processing summary index %d\n", i); 397 dbg_summary("processing summary index %d\n", i);
400 398
399 cond_resched();
400
401 /* Make sure there's a spare ref for dirty space */ 401 /* Make sure there's a spare ref for dirty space */
402 err = jffs2_prealloc_raw_node_refs(c, jeb, 2); 402 err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
403 if (err) 403 if (err)
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 7deb78254021..08a0e6c49e61 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/err.h>
20#include <linux/mount.h> 21#include <linux/mount.h>
21#include <linux/jffs2.h> 22#include <linux/jffs2.h>
22#include <linux/pagemap.h> 23#include <linux/pagemap.h>
@@ -184,9 +185,9 @@ static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
184 struct mtd_info *mtd; 185 struct mtd_info *mtd;
185 186
186 mtd = get_mtd_device(NULL, mtdnr); 187 mtd = get_mtd_device(NULL, mtdnr);
187 if (!mtd) { 188 if (IS_ERR(mtd)) {
188 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); 189 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
189 return -EINVAL; 190 return PTR_ERR(mtd);
190 } 191 }
191 192
192 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); 193 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
@@ -221,7 +222,7 @@ static int jffs2_get_sb(struct file_system_type *fs_type,
221 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); 222 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
222 for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { 223 for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
223 mtd = get_mtd_device(NULL, mtdnr); 224 mtd = get_mtd_device(NULL, mtdnr);
224 if (mtd) { 225 if (!IS_ERR(mtd)) {
225 if (!strcmp(mtd->name, dev_name+4)) 226 if (!strcmp(mtd->name, dev_name+4))
226 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); 227 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
227 put_mtd_device(mtd); 228 put_mtd_device(mtd);
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index fc211b6e9b03..b90d5aa3d969 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -51,7 +51,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
51 */ 51 */
52 52
53 if (!p) { 53 if (!p) {
54 printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); 54 printk(KERN_ERR "jffs2_follow_link(): can't find symlink target\n");
55 p = ERR_PTR(-EIO); 55 p = ERR_PTR(-EIO);
56 } 56 }
57 D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); 57 D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target));
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 70707309dfa1..9c99859f5edd 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -969,8 +969,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
969 int oobsize = c->mtd->oobsize; 969 int oobsize = c->mtd->oobsize;
970 struct mtd_oob_ops ops; 970 struct mtd_oob_ops ops;
971 971
972 ops.len = NR_OOB_SCAN_PAGES * oobsize; 972 ops.ooblen = NR_OOB_SCAN_PAGES * oobsize;
973 ops.ooblen = oobsize;
974 ops.oobbuf = c->oobbuf; 973 ops.oobbuf = c->oobbuf;
975 ops.ooboffs = 0; 974 ops.ooboffs = 0;
976 ops.datbuf = NULL; 975 ops.datbuf = NULL;
@@ -983,10 +982,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
983 return ret; 982 return ret;
984 } 983 }
985 984
986 if (ops.retlen < ops.len) { 985 if (ops.oobretlen < ops.ooblen) {
987 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " 986 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
988 "returned short read (%zd bytes not %d) for block " 987 "returned short read (%zd bytes not %d) for block "
989 "at %08x\n", ops.retlen, ops.len, jeb->offset)); 988 "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset));
990 return -EIO; 989 return -EIO;
991 } 990 }
992 991
@@ -1005,7 +1004,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
1005 } 1004 }
1006 1005
1007 /* we know, we are aligned :) */ 1006 /* we know, we are aligned :) */
1008 for (page = oobsize; page < ops.len; page += sizeof(long)) { 1007 for (page = oobsize; page < ops.ooblen; page += sizeof(long)) {
1009 long dat = *(long *)(&ops.oobbuf[page]); 1008 long dat = *(long *)(&ops.oobbuf[page]);
1010 if(dat != -1) 1009 if(dat != -1)
1011 return 1; 1010 return 1;
@@ -1033,7 +1032,6 @@ int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
1033 return 2; 1032 return 2;
1034 } 1033 }
1035 1034
1036 ops.len = oobsize;
1037 ops.ooblen = oobsize; 1035 ops.ooblen = oobsize;
1038 ops.oobbuf = c->oobbuf; 1036 ops.oobbuf = c->oobbuf;
1039 ops.ooboffs = 0; 1037 ops.ooboffs = 0;
@@ -1048,10 +1046,10 @@ int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
1048 return ret; 1046 return ret;
1049 } 1047 }
1050 1048
1051 if (ops.retlen < ops.len) { 1049 if (ops.oobretlen < ops.ooblen) {
1052 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): " 1050 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
1053 "Read OOB return short read (%zd bytes not %d) " 1051 "Read OOB return short read (%zd bytes not %d) "
1054 "for block at %08x\n", ops.retlen, ops.len, 1052 "for block at %08x\n", ops.oobretlen, ops.ooblen,
1055 jeb->offset)); 1053 jeb->offset));
1056 return -EIO; 1054 return -EIO;
1057 } 1055 }
@@ -1090,8 +1088,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
1090 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); 1088 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
1091 n.totlen = cpu_to_je32(8); 1089 n.totlen = cpu_to_je32(8);
1092 1090
1093 ops.len = c->fsdata_len; 1091 ops.ooblen = c->fsdata_len;
1094 ops.ooblen = c->fsdata_len;;
1095 ops.oobbuf = (uint8_t *)&n; 1092 ops.oobbuf = (uint8_t *)&n;
1096 ops.ooboffs = c->fsdata_pos; 1093 ops.ooboffs = c->fsdata_pos;
1097 ops.datbuf = NULL; 1094 ops.datbuf = NULL;
@@ -1105,10 +1102,10 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
1105 jeb->offset, ret)); 1102 jeb->offset, ret));
1106 return ret; 1103 return ret;
1107 } 1104 }
1108 if (ops.retlen != ops.len) { 1105 if (ops.oobretlen != ops.ooblen) {
1109 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " 1106 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
1110 "Short write for block at %08x: %zd not %d\n", 1107 "Short write for block at %08x: %zd not %d\n",
1111 jeb->offset, ops.retlen, ops.len)); 1108 jeb->offset, ops.oobretlen, ops.ooblen));
1112 return -EIO; 1109 return -EIO;
1113 } 1110 }
1114 return 0; 1111 return 0;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 4da09ce1d1f5..4bb3f1897330 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -399,8 +399,6 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu
399{ 399{
400 /* must be called under down_write(xattr_sem) */ 400 /* must be called under down_write(xattr_sem) */
401 if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) { 401 if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
402 uint32_t xid = xd->xid, version = xd->version;
403
404 unload_xattr_datum(c, xd); 402 unload_xattr_datum(c, xd);
405 xd->flags |= JFFS2_XFLAGS_DEAD; 403 xd->flags |= JFFS2_XFLAGS_DEAD;
406 if (xd->node == (void *)xd) { 404 if (xd->node == (void *)xd) {
@@ -411,7 +409,8 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu
411 } 409 }
412 spin_unlock(&c->erase_completion_lock); 410 spin_unlock(&c->erase_completion_lock);
413 411
414 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version); 412 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n",
413 xd->xid, xd->version);
415 } 414 }
416} 415}
417 416
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index 72fc68c5ee96..9a6e2f953cba 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -24,7 +24,6 @@ struct mtd_blktrans_dev {
24 struct mtd_info *mtd; 24 struct mtd_info *mtd;
25 struct mutex lock; 25 struct mutex lock;
26 int devnum; 26 int devnum;
27 int blksize;
28 unsigned long size; 27 unsigned long size;
29 int readonly; 28 int readonly;
30 void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */ 29 void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
@@ -36,6 +35,8 @@ struct mtd_blktrans_ops {
36 char *name; 35 char *name;
37 int major; 36 int major;
38 int part_bits; 37 int part_bits;
38 int blksize;
39 int blkshift;
39 40
40 /* Access functions */ 41 /* Access functions */
41 int (*readsect)(struct mtd_blktrans_dev *dev, 42 int (*readsect)(struct mtd_blktrans_dev *dev,
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 94a443d45258..d644e57703ad 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -23,7 +23,7 @@
23 23
24#define MTD_CHAR_MAJOR 90 24#define MTD_CHAR_MAJOR 90
25#define MTD_BLOCK_MAJOR 31 25#define MTD_BLOCK_MAJOR 31
26#define MAX_MTD_DEVICES 16 26#define MAX_MTD_DEVICES 32
27 27
28#define MTD_ERASE_PENDING 0x01 28#define MTD_ERASE_PENDING 0x01
29#define MTD_ERASING 0x02 29#define MTD_ERASING 0x02
@@ -75,15 +75,12 @@ typedef enum {
75 * struct mtd_oob_ops - oob operation operands 75 * struct mtd_oob_ops - oob operation operands
76 * @mode: operation mode 76 * @mode: operation mode
77 * 77 *
78 * @len: number of bytes to write/read. When a data buffer is given 78 * @len: number of data bytes to write/read
79 * (datbuf != NULL) this is the number of data bytes. When
80 * no data buffer is available this is the number of oob bytes.
81 * 79 *
82 * @retlen: number of bytes written/read. When a data buffer is given 80 * @retlen: number of data bytes written/read
83 * (datbuf != NULL) this is the number of data bytes. When
84 * no data buffer is available this is the number of oob bytes.
85 * 81 *
86 * @ooblen: number of oob bytes per page 82 * @ooblen: number of oob bytes to write/read
83 * @oobretlen: number of oob bytes written/read
87 * @ooboffs: offset of oob data in the oob area (only relevant when 84 * @ooboffs: offset of oob data in the oob area (only relevant when
88 * mode = MTD_OOB_PLACE) 85 * mode = MTD_OOB_PLACE)
89 * @datbuf: data buffer - if NULL only oob data are read/written 86 * @datbuf: data buffer - if NULL only oob data are read/written
@@ -94,6 +91,7 @@ struct mtd_oob_ops {
94 size_t len; 91 size_t len;
95 size_t retlen; 92 size_t retlen;
96 size_t ooblen; 93 size_t ooblen;
94 size_t oobretlen;
97 uint32_t ooboffs; 95 uint32_t ooboffs;
98 uint8_t *datbuf; 96 uint8_t *datbuf;
99 uint8_t *oobbuf; 97 uint8_t *oobbuf;
@@ -202,11 +200,20 @@ struct mtd_info {
202 200
203 /* ECC status information */ 201 /* ECC status information */
204 struct mtd_ecc_stats ecc_stats; 202 struct mtd_ecc_stats ecc_stats;
203 /* Subpage shift (NAND) */
204 int subpage_sft;
205 205
206 void *priv; 206 void *priv;
207 207
208 struct module *owner; 208 struct module *owner;
209 int usecount; 209 int usecount;
210
211 /* If the driver is something smart, like UBI, it may need to maintain
212 * its own reference counting. The below functions are only for driver.
213 * The driver may register its callbacks. These callbacks are not
214 * supposed to be called by MTD users */
215 int (*get_device) (struct mtd_info *mtd);
216 void (*put_device) (struct mtd_info *mtd);
210}; 217};
211 218
212 219
@@ -216,6 +223,7 @@ extern int add_mtd_device(struct mtd_info *mtd);
216extern int del_mtd_device (struct mtd_info *mtd); 223extern int del_mtd_device (struct mtd_info *mtd);
217 224
218extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 225extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
226extern struct mtd_info *get_mtd_device_nm(const char *name);
219 227
220extern void put_mtd_device(struct mtd_info *mtd); 228extern void put_mtd_device(struct mtd_info *mtd);
221 229
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8b3ef4187219..2071b02f0526 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -166,6 +166,9 @@ typedef enum {
166 * for all large page devices, as they do not support 166 * for all large page devices, as they do not support
167 * autoincrement.*/ 167 * autoincrement.*/
168#define NAND_NO_READRDY 0x00000100 168#define NAND_NO_READRDY 0x00000100
169/* Chip does not allow subpage writes */
170#define NAND_NO_SUBPAGE_WRITE 0x00000200
171
169 172
170/* Options valid for Samsung large page devices */ 173/* Options valid for Samsung large page devices */
171#define NAND_SAMSUNG_LP_OPTIONS \ 174#define NAND_SAMSUNG_LP_OPTIONS \
@@ -193,6 +196,9 @@ typedef enum {
193/* Nand scan has allocated controller struct */ 196/* Nand scan has allocated controller struct */
194#define NAND_CONTROLLER_ALLOC 0x80000000 197#define NAND_CONTROLLER_ALLOC 0x80000000
195 198
199/* Cell info constants */
200#define NAND_CI_CHIPNR_MSK 0x03
201#define NAND_CI_CELLTYPE_MSK 0x0C
196 202
197/* 203/*
198 * nand_state_t - chip states 204 * nand_state_t - chip states
@@ -286,9 +292,7 @@ struct nand_ecc_ctrl {
286 * struct nand_buffers - buffer structure for read/write 292 * struct nand_buffers - buffer structure for read/write
287 * @ecccalc: buffer for calculated ecc 293 * @ecccalc: buffer for calculated ecc
288 * @ecccode: buffer for ecc read from flash 294 * @ecccode: buffer for ecc read from flash
289 * @oobwbuf: buffer for write oob data
290 * @databuf: buffer for data - dynamically sized 295 * @databuf: buffer for data - dynamically sized
291 * @oobrbuf: buffer to read oob data
292 * 296 *
293 * Do not change the order of buffers. databuf and oobrbuf must be in 297 * Do not change the order of buffers. databuf and oobrbuf must be in
294 * consecutive order. 298 * consecutive order.
@@ -296,9 +300,7 @@ struct nand_ecc_ctrl {
296struct nand_buffers { 300struct nand_buffers {
297 uint8_t ecccalc[NAND_MAX_OOBSIZE]; 301 uint8_t ecccalc[NAND_MAX_OOBSIZE];
298 uint8_t ecccode[NAND_MAX_OOBSIZE]; 302 uint8_t ecccode[NAND_MAX_OOBSIZE];
299 uint8_t oobwbuf[NAND_MAX_OOBSIZE]; 303 uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
300 uint8_t databuf[NAND_MAX_PAGESIZE];
301 uint8_t oobrbuf[NAND_MAX_OOBSIZE];
302}; 304};
303 305
304/** 306/**
@@ -345,6 +347,7 @@ struct nand_buffers {
345 * @chipsize: [INTERN] the size of one chip for multichip arrays 347 * @chipsize: [INTERN] the size of one chip for multichip arrays
346 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 348 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
347 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf 349 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf
350 * @subpagesize: [INTERN] holds the subpagesize
348 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 351 * @ecclayout: [REPLACEABLE] the default ecc placement scheme
349 * @bbt: [INTERN] bad block table pointer 352 * @bbt: [INTERN] bad block table pointer
350 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup 353 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
@@ -392,6 +395,8 @@ struct nand_chip {
392 unsigned long chipsize; 395 unsigned long chipsize;
393 int pagemask; 396 int pagemask;
394 int pagebuf; 397 int pagebuf;
398 int subpagesize;
399 uint8_t cellinfo;
395 int badblockpos; 400 int badblockpos;
396 401
397 nand_state_t state; 402 nand_state_t state;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 6f045b586e76..f775a7af3890 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -13,6 +13,7 @@
13#define __LINUX_MTD_ONENAND_H 13#define __LINUX_MTD_ONENAND_H
14 14
15#include <linux/spinlock.h> 15#include <linux/spinlock.h>
16#include <linux/completion.h>
16#include <linux/mtd/onenand_regs.h> 17#include <linux/mtd/onenand_regs.h>
17#include <linux/mtd/bbm.h> 18#include <linux/mtd/bbm.h>
18 19
@@ -33,7 +34,6 @@ typedef enum {
33 FL_WRITING, 34 FL_WRITING,
34 FL_ERASING, 35 FL_ERASING,
35 FL_SYNCING, 36 FL_SYNCING,
36 FL_UNLOCKING,
37 FL_LOCKING, 37 FL_LOCKING,
38 FL_RESETING, 38 FL_RESETING,
39 FL_OTPING, 39 FL_OTPING,
@@ -88,6 +88,7 @@ struct onenand_bufferram {
88 * operation is in progress 88 * operation is in progress
89 * @state: [INTERN] the current state of the OneNAND device 89 * @state: [INTERN] the current state of the OneNAND device
90 * @page_buf: data buffer 90 * @page_buf: data buffer
91 * @subpagesize: [INTERN] holds the subpagesize
91 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 92 * @ecclayout: [REPLACEABLE] the default ecc placement scheme
92 * @bbm: [REPLACEABLE] pointer to Bad Block Management 93 * @bbm: [REPLACEABLE] pointer to Bad Block Management
93 * @priv: [OPTIONAL] pointer to private chip date 94 * @priv: [OPTIONAL] pointer to private chip date
@@ -120,11 +121,15 @@ struct onenand_chip {
120 int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); 121 int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
121 int (*scan_bbt)(struct mtd_info *mtd); 122 int (*scan_bbt)(struct mtd_info *mtd);
122 123
124 struct completion complete;
125 int irq;
126
123 spinlock_t chip_lock; 127 spinlock_t chip_lock;
124 wait_queue_head_t wq; 128 wait_queue_head_t wq;
125 onenand_state_t state; 129 onenand_state_t state;
126 unsigned char *page_buf; 130 unsigned char *page_buf;
127 131
132 int subpagesize;
128 struct nand_ecclayout *ecclayout; 133 struct nand_ecclayout *ecclayout;
129 134
130 void *bbm; 135 void *bbm;
@@ -138,6 +143,7 @@ struct onenand_chip {
138#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) 143#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
139#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) 144#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
140#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) 145#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
146#define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
141 147
142#define ONENAND_GET_SYS_CFG1(this) \ 148#define ONENAND_GET_SYS_CFG1(this) \
143 (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) 149 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index 9e409fe6ded6..e31c8f5d4271 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -179,6 +179,7 @@
179 * ECC Status Reigser FF00h (R) 179 * ECC Status Reigser FF00h (R)
180 */ 180 */
181#define ONENAND_ECC_1BIT (1 << 0) 181#define ONENAND_ECC_1BIT (1 << 0)
182#define ONENAND_ECC_1BIT_ALL (0x5555)
182#define ONENAND_ECC_2BIT (1 << 1) 183#define ONENAND_ECC_2BIT (1 << 1)
183#define ONENAND_ECC_2BIT_ALL (0xAAAA) 184#define ONENAND_ECC_2BIT_ALL (0xAAAA)
184 185