aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 16:45:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 16:45:22 -0500
commit7b3480f8b701170c046e1ed362946f5f0d005e13 (patch)
treebd25e05b4f35699689b485480dddf24f840f80af /drivers/mtd
parent1c8106528aa6bf16b3f457de80df1cf7462a49a4 (diff)
parentb60ef99c1164a8ad346cf41f9e71acfffb6d25a6 (diff)
Merge tag 'for-linus-3.3' of git://git.infradead.org/mtd-2.6
MTD pull for 3.3 * tag 'for-linus-3.3' of git://git.infradead.org/mtd-2.6: (113 commits) mtd: Fix dependency for MTD_DOC200x mtd: do not use mtd->block_markbad directly logfs: do not use 'mtd->block_isbad' directly mtd: introduce mtd_can_have_bb helper mtd: do not use mtd->suspend and mtd->resume directly mtd: do not use mtd->lock, unlock and is_locked directly mtd: do not use mtd->sync directly mtd: harmonize mtd_writev usage mtd: do not use mtd->lock_user_prot_reg directly mtd: mtd->write_user_prot_reg directly mtd: do not use mtd->read_*_prot_reg directly mtd: do not use mtd->get_*_prot_info directly mtd: do not use mtd->read_oob directly mtd: mtdoops: do not use mtd->panic_write directly romfs: do not use mtd->get_unmapped_area directly mtd: do not use mtd->get_unmapped_area directly mtd: do use mtd->point directly mtd: introduce mtd_has_oob helper mtd: mtdcore: export symbols cleanup mtd: clean-up the default_mtd_writev function ... Fix up trivial edit/remove conflict in drivers/staging/spectra/lld_mtd.c
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/Kconfig8
-rw-r--r--drivers/mtd/Makefile1
-rw-r--r--drivers/mtd/afs.c4
-rw-r--r--drivers/mtd/ar7part.c15
-rw-r--r--drivers/mtd/bcm63xxpart.c222
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c13
-rw-r--r--drivers/mtd/devices/Kconfig12
-rw-r--r--drivers/mtd/devices/block2mtd.c2
-rw-r--r--drivers/mtd/devices/doc2000.c9
-rw-r--r--drivers/mtd/devices/doc2001.c8
-rw-r--r--drivers/mtd/devices/doc2001plus.c9
-rw-r--r--drivers/mtd/devices/docg3.c1441
-rw-r--r--drivers/mtd/devices/docg3.h65
-rw-r--r--drivers/mtd/devices/docprobe.c7
-rw-r--r--drivers/mtd/devices/m25p80.c1
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c1
-rw-r--r--drivers/mtd/devices/sst25l.c3
-rw-r--r--drivers/mtd/ftl.c81
-rw-r--r--drivers/mtd/inftlcore.c25
-rw-r--r--drivers/mtd/inftlmount.c19
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c7
-rw-r--r--drivers/mtd/maps/Kconfig9
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/bcm963xx-flash.c277
-rw-r--r--drivers/mtd/maps/bfin-async-flash.c12
-rw-r--r--drivers/mtd/maps/gpio-addr-flash.c12
-rw-r--r--drivers/mtd/maps/ixp2000.c12
-rw-r--r--drivers/mtd/maps/ixp4xx.c14
-rw-r--r--drivers/mtd/maps/lantiq-flash.c6
-rw-r--r--drivers/mtd/maps/latch-addr-flash.c12
-rw-r--r--drivers/mtd/maps/physmap.c10
-rw-r--r--drivers/mtd/maps/physmap_of.c13
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c17
-rw-r--r--drivers/mtd/maps/rbtx4939-flash.c18
-rw-r--r--drivers/mtd/maps/sa1100-flash.c17
-rw-r--r--drivers/mtd/maps/scb2_flash.c3
-rw-r--r--drivers/mtd/maps/sun_uflash.c13
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
-rw-r--r--drivers/mtd/mtdblock.c21
-rw-r--r--drivers/mtd/mtdblock_ro.c4
-rw-r--r--drivers/mtd/mtdchar.c203
-rw-r--r--drivers/mtd/mtdconcat.c53
-rw-r--r--drivers/mtd/mtdcore.c126
-rw-r--r--drivers/mtd/mtdoops.c44
-rw-r--r--drivers/mtd/mtdpart.c63
-rw-r--r--drivers/mtd/mtdswap.c29
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/ams-delta.c12
-rw-r--r--drivers/mtd/nand/bcm_umi_nand.c13
-rw-r--r--drivers/mtd/nand/davinci_nand.c4
-rw-r--r--drivers/mtd/nand/diskonchip.c4
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c75
-rw-r--r--drivers/mtd/nand/fsl_upm.c12
-rw-r--r--drivers/mtd/nand/gpio.c115
-rw-r--r--drivers/mtd/nand/jz4740_nand.c12
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c14
-rw-r--r--drivers/mtd/nand/nand_base.c7
-rw-r--r--drivers/mtd/nand/nand_bbt.c14
-rw-r--r--drivers/mtd/nand/nand_ids.c4
-rw-r--r--drivers/mtd/nand/nandsim.c2
-rw-r--r--drivers/mtd/nand/ndfc.c13
-rw-r--r--drivers/mtd/nand/nomadik_nand.c18
-rw-r--r--drivers/mtd/nand/nuc900_nand.c13
-rw-r--r--drivers/mtd/nand/omap2.c15
-rw-r--r--drivers/mtd/nand/pasemi_nand.c12
-rw-r--r--drivers/mtd/nand/plat_nand.c13
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c16
-rw-r--r--drivers/mtd/nand/sharpsl.c12
-rw-r--r--drivers/mtd/nand/sm_common.c2
-rw-r--r--drivers/mtd/nand/socrates_nand.c13
-rw-r--r--drivers/mtd/nand/tmio_nand.c13
-rw-r--r--drivers/mtd/nand/txx9ndfmc.c6
-rw-r--r--drivers/mtd/nftlcore.c25
-rw-r--r--drivers/mtd/nftlmount.c13
-rw-r--r--drivers/mtd/onenand/generic.c16
-rw-r--r--drivers/mtd/onenand/onenand_base.c3
-rw-r--r--drivers/mtd/onenand/samsung.c13
-rw-r--r--drivers/mtd/redboot.c12
-rw-r--r--drivers/mtd/rfd_ftl.c46
-rw-r--r--drivers/mtd/sm_ftl.c12
-rw-r--r--drivers/mtd/ssfdc.c12
-rw-r--r--drivers/mtd/tests/mtd_oobtest.c28
-rw-r--r--drivers/mtd/tests/mtd_pagetest.c57
-rw-r--r--drivers/mtd/tests/mtd_readtest.c11
-rw-r--r--drivers/mtd/tests/mtd_speedtest.c37
-rw-r--r--drivers/mtd/tests/mtd_stresstest.c22
-rw-r--r--drivers/mtd/tests/mtd_subpagetest.c32
-rw-r--r--drivers/mtd/tests/mtd_torturetest.c15
-rw-r--r--drivers/mtd/ubi/build.c2
-rw-r--r--drivers/mtd/ubi/debug.c2
-rw-r--r--drivers/mtd/ubi/io.c19
-rw-r--r--drivers/mtd/ubi/kapi.c4
92 files changed, 2263 insertions, 1499 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 318a869286a..1be62184140 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -140,6 +140,14 @@ config MTD_AR7_PARTS
140 ---help--- 140 ---help---
141 TI AR7 partitioning support 141 TI AR7 partitioning support
142 142
143config MTD_BCM63XX_PARTS
144 tristate "BCM63XX CFE partitioning support"
145 depends on BCM63XX
146 select CRC32
147 help
148 This provides partions parsing for BCM63xx devices with CFE
149 bootloaders.
150
143comment "User Modules And Translation Layers" 151comment "User Modules And Translation Layers"
144 152
145config MTD_CHAR 153config MTD_CHAR
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 9aaac3ac89f..f90135429dc 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
11obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o 11obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
12obj-$(CONFIG_MTD_AFS_PARTS) += afs.o 12obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
13obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o 13obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
14obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
14 15
15# 'Users' - code which presents functionality to userspace. 16# 'Users' - code which presents functionality to userspace.
16obj-$(CONFIG_MTD_CHAR) += mtdchar.o 17obj-$(CONFIG_MTD_CHAR) += mtdchar.o
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index 89a02f6f65d..5a3942bf109 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -75,7 +75,7 @@ afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
75 size_t sz; 75 size_t sz;
76 int ret; 76 int ret;
77 77
78 ret = mtd->read(mtd, ptr, sizeof(fs), &sz, (u_char *) &fs); 78 ret = mtd_read(mtd, ptr, sizeof(fs), &sz, (u_char *)&fs);
79 if (ret >= 0 && sz != sizeof(fs)) 79 if (ret >= 0 && sz != sizeof(fs))
80 ret = -EINVAL; 80 ret = -EINVAL;
81 81
@@ -132,7 +132,7 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
132 int ret, i; 132 int ret, i;
133 133
134 memset(iis, 0, sizeof(*iis)); 134 memset(iis, 0, sizeof(*iis));
135 ret = mtd->read(mtd, ptr, sizeof(*iis), &sz, (u_char *) iis); 135 ret = mtd_read(mtd, ptr, sizeof(*iis), &sz, (u_char *)iis);
136 if (ret < 0) 136 if (ret < 0)
137 goto failed; 137 goto failed;
138 138
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
index f40ea454755..94539312995 100644
--- a/drivers/mtd/ar7part.c
+++ b/drivers/mtd/ar7part.c
@@ -73,8 +73,8 @@ static int create_mtd_partitions(struct mtd_info *master,
73 73
74 do { /* Try 10 blocks starting from master->erasesize */ 74 do { /* Try 10 blocks starting from master->erasesize */
75 offset = pre_size; 75 offset = pre_size;
76 master->read(master, offset, 76 mtd_read(master, offset, sizeof(header), &len,
77 sizeof(header), &len, (uint8_t *)&header); 77 (uint8_t *)&header);
78 if (!strncmp((char *)&header, "TIENV0.8", 8)) 78 if (!strncmp((char *)&header, "TIENV0.8", 8))
79 ar7_parts[1].offset = pre_size; 79 ar7_parts[1].offset = pre_size;
80 if (header.checksum == LOADER_MAGIC1) 80 if (header.checksum == LOADER_MAGIC1)
@@ -95,16 +95,16 @@ static int create_mtd_partitions(struct mtd_info *master,
95 case LOADER_MAGIC1: 95 case LOADER_MAGIC1:
96 while (header.length) { 96 while (header.length) {
97 offset += sizeof(header) + header.length; 97 offset += sizeof(header) + header.length;
98 master->read(master, offset, sizeof(header), 98 mtd_read(master, offset, sizeof(header), &len,
99 &len, (uint8_t *)&header); 99 (uint8_t *)&header);
100 } 100 }
101 root_offset = offset + sizeof(header) + 4; 101 root_offset = offset + sizeof(header) + 4;
102 break; 102 break;
103 case LOADER_MAGIC2: 103 case LOADER_MAGIC2:
104 while (header.length) { 104 while (header.length) {
105 offset += sizeof(header) + header.length; 105 offset += sizeof(header) + header.length;
106 master->read(master, offset, sizeof(header), 106 mtd_read(master, offset, sizeof(header), &len,
107 &len, (uint8_t *)&header); 107 (uint8_t *)&header);
108 } 108 }
109 root_offset = offset + sizeof(header) + 4 + 0xff; 109 root_offset = offset + sizeof(header) + 4 + 0xff;
110 root_offset &= ~(uint32_t)0xff; 110 root_offset &= ~(uint32_t)0xff;
@@ -114,8 +114,7 @@ static int create_mtd_partitions(struct mtd_info *master,
114 break; 114 break;
115 } 115 }
116 116
117 master->read(master, root_offset, 117 mtd_read(master, root_offset, sizeof(header), &len, (u8 *)&header);
118 sizeof(header), &len, (u8 *)&header);
119 if (header.checksum != SQUASHFS_MAGIC) { 118 if (header.checksum != SQUASHFS_MAGIC) {
120 root_offset += master->erasesize - 1; 119 root_offset += master->erasesize - 1;
121 root_offset &= ~(master->erasesize - 1); 120 root_offset &= ~(master->erasesize - 1);
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
new file mode 100644
index 00000000000..608321ee056
--- /dev/null
+++ b/drivers/mtd/bcm63xxpart.c
@@ -0,0 +1,222 @@
1/*
2 * BCM63XX CFE image tag parser
3 *
4 * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org>
5 * Mike Albon <malbon@openwrt.org>
6 * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
7 * Copyright © 2011 Jonas Gorski <jonas.gorski@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/crc32.h>
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/slab.h>
31#include <linux/vmalloc.h>
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/partitions.h>
34
35#include <asm/mach-bcm63xx/bcm963xx_tag.h>
36#include <asm/mach-bcm63xx/board_bcm963xx.h>
37
38#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
39
40#define BCM63XX_MIN_CFE_SIZE 0x10000 /* always at least 64KiB */
41#define BCM63XX_MIN_NVRAM_SIZE 0x10000 /* always at least 64KiB */
42
43#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
44
45static int bcm63xx_detect_cfe(struct mtd_info *master)
46{
47 char buf[9];
48 int ret;
49 size_t retlen;
50
51 ret = mtd_read(master, BCM963XX_CFE_VERSION_OFFSET, 5, &retlen,
52 (void *)buf);
53 buf[retlen] = 0;
54
55 if (ret)
56 return ret;
57
58 if (strncmp("cfe-v", buf, 5) == 0)
59 return 0;
60
61 /* very old CFE's do not have the cfe-v string, so check for magic */
62 ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
63 (void *)buf);
64 buf[retlen] = 0;
65
66 return strncmp("CFE1CFE1", buf, 8);
67}
68
69static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
70 struct mtd_partition **pparts,
71 struct mtd_part_parser_data *data)
72{
73 /* CFE, NVRAM and global Linux are always present */
74 int nrparts = 3, curpart = 0;
75 struct bcm_tag *buf;
76 struct mtd_partition *parts;
77 int ret;
78 size_t retlen;
79 unsigned int rootfsaddr, kerneladdr, spareaddr;
80 unsigned int rootfslen, kernellen, sparelen, totallen;
81 unsigned int cfelen, nvramlen;
82 int namelen = 0;
83 int i;
84 u32 computed_crc;
85
86 if (bcm63xx_detect_cfe(master))
87 return -EINVAL;
88
89 cfelen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_CFE_SIZE);
90 nvramlen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_NVRAM_SIZE);
91
92 /* Allocate memory for buffer */
93 buf = vmalloc(sizeof(struct bcm_tag));
94 if (!buf)
95 return -ENOMEM;
96
97 /* Get the tag */
98 ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen,
99 (void *)buf);
100
101 if (retlen != sizeof(struct bcm_tag)) {
102 vfree(buf);
103 return -EIO;
104 }
105
106 computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
107 offsetof(struct bcm_tag, header_crc));
108 if (computed_crc == buf->header_crc) {
109 char *boardid = &(buf->board_id[0]);
110 char *tagversion = &(buf->tag_version[0]);
111
112 sscanf(buf->kernel_address, "%u", &kerneladdr);
113 sscanf(buf->kernel_length, "%u", &kernellen);
114 sscanf(buf->total_length, "%u", &totallen);
115
116 pr_info("CFE boot tag found with version %s and board type %s\n",
117 tagversion, boardid);
118
119 kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
120 rootfsaddr = kerneladdr + kernellen;
121 spareaddr = roundup(totallen, master->erasesize) + cfelen;
122 sparelen = master->size - spareaddr - nvramlen;
123 rootfslen = spareaddr - rootfsaddr;
124 } else {
125 pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
126 buf->header_crc, computed_crc);
127 kernellen = 0;
128 rootfslen = 0;
129 rootfsaddr = 0;
130 spareaddr = cfelen;
131 sparelen = master->size - cfelen - nvramlen;
132 }
133
134 /* Determine number of partitions */
135 namelen = 8;
136 if (rootfslen > 0) {
137 nrparts++;
138 namelen += 6;
139 }
140 if (kernellen > 0) {
141 nrparts++;
142 namelen += 6;
143 }
144
145 /* Ask kernel for more memory */
146 parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
147 if (!parts) {
148 vfree(buf);
149 return -ENOMEM;
150 }
151
152 /* Start building partition list */
153 parts[curpart].name = "CFE";
154 parts[curpart].offset = 0;
155 parts[curpart].size = cfelen;
156 curpart++;
157
158 if (kernellen > 0) {
159 parts[curpart].name = "kernel";
160 parts[curpart].offset = kerneladdr;
161 parts[curpart].size = kernellen;
162 curpart++;
163 }
164
165 if (rootfslen > 0) {
166 parts[curpart].name = "rootfs";
167 parts[curpart].offset = rootfsaddr;
168 parts[curpart].size = rootfslen;
169 if (sparelen > 0)
170 parts[curpart].size += sparelen;
171 curpart++;
172 }
173
174 parts[curpart].name = "nvram";
175 parts[curpart].offset = master->size - nvramlen;
176 parts[curpart].size = nvramlen;
177
178 /* Global partition "linux" to make easy firmware upgrade */
179 curpart++;
180 parts[curpart].name = "linux";
181 parts[curpart].offset = cfelen;
182 parts[curpart].size = master->size - cfelen - nvramlen;
183
184 for (i = 0; i < nrparts; i++)
185 pr_info("Partition %d is %s offset %lx and length %lx\n", i,
186 parts[i].name, (long unsigned int)(parts[i].offset),
187 (long unsigned int)(parts[i].size));
188
189 pr_info("Spare partition is offset %x and length %x\n", spareaddr,
190 sparelen);
191
192 *pparts = parts;
193 vfree(buf);
194
195 return nrparts;
196};
197
198static struct mtd_part_parser bcm63xx_cfe_parser = {
199 .owner = THIS_MODULE,
200 .parse_fn = bcm63xx_parse_cfe_partitions,
201 .name = "bcm63xxpart",
202};
203
204static int __init bcm63xx_cfe_parser_init(void)
205{
206 return register_mtd_parser(&bcm63xx_cfe_parser);
207}
208
209static void __exit bcm63xx_cfe_parser_exit(void)
210{
211 deregister_mtd_parser(&bcm63xx_cfe_parser);
212}
213
214module_init(bcm63xx_cfe_parser_init);
215module_exit(bcm63xx_cfe_parser_exit);
216
217MODULE_LICENSE("GPL");
218MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>");
219MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
220MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>");
221MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com");
222MODULE_DESCRIPTION("MTD partitioning for BCM63XX CFE bootloaders");
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index 179814a95f3..85e80180b65 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -139,8 +139,9 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
139 } 139 }
140 140
141 /* Do some byteswapping if necessary */ 141 /* Do some byteswapping if necessary */
142 extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); 142 extp->FeatureSupport = cfi32_to_cpu(map, extp->FeatureSupport);
143 extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); 143 extp->BlkStatusRegMask = cfi32_to_cpu(map,
144 extp->BlkStatusRegMask);
144 145
145#ifdef DEBUG_CFI_FEATURES 146#ifdef DEBUG_CFI_FEATURES
146 /* Tell the user about it in lots of lovely detail */ 147 /* Tell the user about it in lots of lovely detail */
@@ -698,7 +699,8 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
698 continue; 699 continue;
699 } 700 }
700 memcpy(buffer+buflen, elem_base, ECCBUF_SIZE-buflen); 701 memcpy(buffer+buflen, elem_base, ECCBUF_SIZE-buflen);
701 ret = mtd->write(mtd, to, ECCBUF_SIZE, &thislen, buffer); 702 ret = mtd_write(mtd, to, ECCBUF_SIZE, &thislen,
703 buffer);
702 totlen += thislen; 704 totlen += thislen;
703 if (ret || thislen != ECCBUF_SIZE) 705 if (ret || thislen != ECCBUF_SIZE)
704 goto write_error; 706 goto write_error;
@@ -707,7 +709,8 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
707 to += ECCBUF_SIZE; 709 to += ECCBUF_SIZE;
708 } 710 }
709 if (ECCBUF_DIV(elem_len)) { /* write clean aligned data */ 711 if (ECCBUF_DIV(elem_len)) { /* write clean aligned data */
710 ret = mtd->write(mtd, to, ECCBUF_DIV(elem_len), &thislen, elem_base); 712 ret = mtd_write(mtd, to, ECCBUF_DIV(elem_len),
713 &thislen, elem_base);
711 totlen += thislen; 714 totlen += thislen;
712 if (ret || thislen != ECCBUF_DIV(elem_len)) 715 if (ret || thislen != ECCBUF_DIV(elem_len))
713 goto write_error; 716 goto write_error;
@@ -721,7 +724,7 @@ cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
721 } 724 }
722 if (buflen) { /* flush last page, even if not full */ 725 if (buflen) { /* flush last page, even if not full */
723 /* This is sometimes intended behaviour, really */ 726 /* This is sometimes intended behaviour, really */
724 ret = mtd->write(mtd, to, buflen, &thislen, buffer); 727 ret = mtd_write(mtd, to, buflen, &thislen, buffer);
725 totlen += thislen; 728 totlen += thislen;
726 if (ret || thislen != ECCBUF_SIZE) 729 if (ret || thislen != ECCBUF_SIZE)
727 goto write_error; 730 goto write_error;
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 283d887f782..37b05c3f279 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -191,6 +191,7 @@ comment "Disk-On-Chip Device Drivers"
191 191
192config MTD_DOC2000 192config MTD_DOC2000
193 tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)" 193 tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)"
194 depends on MTD_NAND
194 select MTD_DOCPROBE 195 select MTD_DOCPROBE
195 select MTD_NAND_IDS 196 select MTD_NAND_IDS
196 ---help--- 197 ---help---
@@ -213,6 +214,7 @@ config MTD_DOC2000
213 214
214config MTD_DOC2001 215config MTD_DOC2001
215 tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)" 216 tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)"
217 depends on MTD_NAND
216 select MTD_DOCPROBE 218 select MTD_DOCPROBE
217 select MTD_NAND_IDS 219 select MTD_NAND_IDS
218 ---help--- 220 ---help---
@@ -234,6 +236,7 @@ config MTD_DOC2001
234 236
235config MTD_DOC2001PLUS 237config MTD_DOC2001PLUS
236 tristate "M-Systems Disk-On-Chip Millennium Plus" 238 tristate "M-Systems Disk-On-Chip Millennium Plus"
239 depends on MTD_NAND
237 select MTD_DOCPROBE 240 select MTD_DOCPROBE
238 select MTD_NAND_IDS 241 select MTD_NAND_IDS
239 ---help--- 242 ---help---
@@ -251,6 +254,8 @@ config MTD_DOC2001PLUS
251 254
252config MTD_DOCG3 255config MTD_DOCG3
253 tristate "M-Systems Disk-On-Chip G3" 256 tristate "M-Systems Disk-On-Chip G3"
257 select BCH
258 select BCH_CONST_PARAMS
254 ---help--- 259 ---help---
255 This provides an MTD device driver for the M-Systems DiskOnChip 260 This provides an MTD device driver for the M-Systems DiskOnChip
256 G3 devices. 261 G3 devices.
@@ -259,6 +264,13 @@ config MTD_DOCG3
259 M-Systems and now Sandisk. The support is very experimental, 264 M-Systems and now Sandisk. The support is very experimental,
260 and doesn't give access to any write operations. 265 and doesn't give access to any write operations.
261 266
267if MTD_DOCG3
268config BCH_CONST_M
269 default 14
270config BCH_CONST_T
271 default 4
272endif
273
262config MTD_DOCPROBE 274config MTD_DOCPROBE
263 tristate 275 tristate
264 select MTD_DOCECC 276 select MTD_DOCECC
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index ebeabc727f7..e7e46d1e746 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -287,7 +287,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
287 dev->mtd.flags = MTD_CAP_RAM; 287 dev->mtd.flags = MTD_CAP_RAM;
288 dev->mtd.erase = block2mtd_erase; 288 dev->mtd.erase = block2mtd_erase;
289 dev->mtd.write = block2mtd_write; 289 dev->mtd.write = block2mtd_write;
290 dev->mtd.writev = default_mtd_writev; 290 dev->mtd.writev = mtd_writev;
291 dev->mtd.sync = block2mtd_sync; 291 dev->mtd.sync = block2mtd_sync;
292 dev->mtd.read = block2mtd_read; 292 dev->mtd.read = block2mtd_read;
293 dev->mtd.priv = dev; 293 dev->mtd.priv = dev;
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index e9fad915121..b1cdf647901 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -562,23 +562,14 @@ void DoC2k_init(struct mtd_info *mtd)
562 562
563 mtd->type = MTD_NANDFLASH; 563 mtd->type = MTD_NANDFLASH;
564 mtd->flags = MTD_CAP_NANDFLASH; 564 mtd->flags = MTD_CAP_NANDFLASH;
565 mtd->size = 0;
566 mtd->erasesize = 0;
567 mtd->writesize = 512; 565 mtd->writesize = 512;
568 mtd->oobsize = 16; 566 mtd->oobsize = 16;
569 mtd->owner = THIS_MODULE; 567 mtd->owner = THIS_MODULE;
570 mtd->erase = doc_erase; 568 mtd->erase = doc_erase;
571 mtd->point = NULL;
572 mtd->unpoint = NULL;
573 mtd->read = doc_read; 569 mtd->read = doc_read;
574 mtd->write = doc_write; 570 mtd->write = doc_write;
575 mtd->read_oob = doc_read_oob; 571 mtd->read_oob = doc_read_oob;
576 mtd->write_oob = doc_write_oob; 572 mtd->write_oob = doc_write_oob;
577 mtd->sync = NULL;
578
579 this->totlen = 0;
580 this->numchips = 0;
581
582 this->curfloor = -1; 573 this->curfloor = -1;
583 this->curchip = -1; 574 this->curchip = -1;
584 mutex_init(&this->lock); 575 mutex_init(&this->lock);
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index a3f7a27499b..7543b98f46c 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -343,25 +343,17 @@ void DoCMil_init(struct mtd_info *mtd)
343 343
344 mtd->type = MTD_NANDFLASH; 344 mtd->type = MTD_NANDFLASH;
345 mtd->flags = MTD_CAP_NANDFLASH; 345 mtd->flags = MTD_CAP_NANDFLASH;
346 mtd->size = 0;
347 346
348 /* FIXME: erase size is not always 8KiB */ 347 /* FIXME: erase size is not always 8KiB */
349 mtd->erasesize = 0x2000; 348 mtd->erasesize = 0x2000;
350
351 mtd->writesize = 512; 349 mtd->writesize = 512;
352 mtd->oobsize = 16; 350 mtd->oobsize = 16;
353 mtd->owner = THIS_MODULE; 351 mtd->owner = THIS_MODULE;
354 mtd->erase = doc_erase; 352 mtd->erase = doc_erase;
355 mtd->point = NULL;
356 mtd->unpoint = NULL;
357 mtd->read = doc_read; 353 mtd->read = doc_read;
358 mtd->write = doc_write; 354 mtd->write = doc_write;
359 mtd->read_oob = doc_read_oob; 355 mtd->read_oob = doc_read_oob;
360 mtd->write_oob = doc_write_oob; 356 mtd->write_oob = doc_write_oob;
361 mtd->sync = NULL;
362
363 this->totlen = 0;
364 this->numchips = 0;
365 this->curfloor = -1; 357 this->curfloor = -1;
366 this->curchip = -1; 358 this->curchip = -1;
367 359
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 99351bc3e0e..177510d0e7e 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -467,23 +467,14 @@ void DoCMilPlus_init(struct mtd_info *mtd)
467 467
468 mtd->type = MTD_NANDFLASH; 468 mtd->type = MTD_NANDFLASH;
469 mtd->flags = MTD_CAP_NANDFLASH; 469 mtd->flags = MTD_CAP_NANDFLASH;
470 mtd->size = 0;
471
472 mtd->erasesize = 0;
473 mtd->writesize = 512; 470 mtd->writesize = 512;
474 mtd->oobsize = 16; 471 mtd->oobsize = 16;
475 mtd->owner = THIS_MODULE; 472 mtd->owner = THIS_MODULE;
476 mtd->erase = doc_erase; 473 mtd->erase = doc_erase;
477 mtd->point = NULL;
478 mtd->unpoint = NULL;
479 mtd->read = doc_read; 474 mtd->read = doc_read;
480 mtd->write = doc_write; 475 mtd->write = doc_write;
481 mtd->read_oob = doc_read_oob; 476 mtd->read_oob = doc_read_oob;
482 mtd->write_oob = doc_write_oob; 477 mtd->write_oob = doc_write_oob;
483 mtd->sync = NULL;
484
485 this->totlen = 0;
486 this->numchips = 0;
487 this->curfloor = -1; 478 this->curfloor = -1;
488 this->curchip = -1; 479 this->curchip = -1;
489 480
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index bdcf5df982e..ad11ef0a81f 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -29,6 +29,9 @@
29#include <linux/delay.h> 29#include <linux/delay.h>
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/bitmap.h>
33#include <linux/bitrev.h>
34#include <linux/bch.h>
32 35
33#include <linux/debugfs.h> 36#include <linux/debugfs.h>
34#include <linux/seq_file.h> 37#include <linux/seq_file.h>
@@ -41,11 +44,7 @@
41 * 44 *
42 * As no specification is available from M-Systems/Sandisk, this drivers lacks 45 * As no specification is available from M-Systems/Sandisk, this drivers lacks
43 * several functions available on the chip, as : 46 * several functions available on the chip, as :
44 * - block erase
45 * - page write
46 * - IPL write 47 * - IPL write
47 * - ECC fixing (lack of BCH algorith understanding)
48 * - powerdown / powerup
49 * 48 *
50 * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and 49 * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and
51 * the driver assumes a 16bits data bus. 50 * the driver assumes a 16bits data bus.
@@ -53,8 +52,7 @@
53 * DocG3 relies on 2 ECC algorithms, which are handled in hardware : 52 * DocG3 relies on 2 ECC algorithms, which are handled in hardware :
54 * - a 1 byte Hamming code stored in the OOB for each page 53 * - a 1 byte Hamming code stored in the OOB for each page
55 * - a 7 bytes BCH code stored in the OOB for each page 54 * - a 7 bytes BCH code stored in the OOB for each page
56 * The BCH part is only used for check purpose, no correction is available as 55 * The BCH ECC is :
57 * some information is missing. What is known is that :
58 * - BCH is in GF(2^14) 56 * - BCH is in GF(2^14)
59 * - BCH is over data of 520 bytes (512 page + 7 page_info bytes 57 * - BCH is over data of 520 bytes (512 page + 7 page_info bytes
60 * + 1 hamming byte) 58 * + 1 hamming byte)
@@ -63,6 +61,30 @@
63 * 61 *
64 */ 62 */
65 63
64static unsigned int reliable_mode;
65module_param(reliable_mode, uint, 0);
66MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, "
67 "2=reliable) : MLC normal operations are in normal mode");
68
69/**
70 * struct docg3_oobinfo - DiskOnChip G3 OOB layout
71 * @eccbytes: 8 bytes are used (1 for Hamming ECC, 7 for BCH ECC)
72 * @eccpos: ecc positions (byte 7 is Hamming ECC, byte 8-14 are BCH ECC)
73 * @oobfree: free pageinfo bytes (byte 0 until byte 6, byte 15
74 * @oobavail: 8 available bytes remaining after ECC toll
75 */
76static struct nand_ecclayout docg3_oobinfo = {
77 .eccbytes = 8,
78 .eccpos = {7, 8, 9, 10, 11, 12, 13, 14},
79 .oobfree = {{0, 7}, {15, 1} },
80 .oobavail = 8,
81};
82
83/**
84 * struct docg3_bch - BCH engine
85 */
86static struct bch_control *docg3_bch;
87
66static inline u8 doc_readb(struct docg3 *docg3, u16 reg) 88static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
67{ 89{
68 u8 val = readb(docg3->base + reg); 90 u8 val = readb(docg3->base + reg);
@@ -82,7 +104,7 @@ static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
82static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) 104static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg)
83{ 105{
84 writeb(val, docg3->base + reg); 106 writeb(val, docg3->base + reg);
85 trace_docg3_io(1, 16, reg, val); 107 trace_docg3_io(1, 8, reg, val);
86} 108}
87 109
88static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) 110static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg)
@@ -143,7 +165,7 @@ static void doc_delay(struct docg3 *docg3, int nbNOPs)
143{ 165{
144 int i; 166 int i;
145 167
146 doc_dbg("NOP x %d\n", nbNOPs); 168 doc_vdbg("NOP x %d\n", nbNOPs);
147 for (i = 0; i < nbNOPs; i++) 169 for (i = 0; i < nbNOPs; i++)
148 doc_writeb(docg3, 0, DOC_NOP); 170 doc_writeb(docg3, 0, DOC_NOP);
149} 171}
@@ -196,8 +218,8 @@ static int doc_reset_seq(struct docg3 *docg3)
196/** 218/**
197 * doc_read_data_area - Read data from data area 219 * doc_read_data_area - Read data from data area
198 * @docg3: the device 220 * @docg3: the device
199 * @buf: the buffer to fill in 221 * @buf: the buffer to fill in (might be NULL is dummy reads)
200 * @len: the lenght to read 222 * @len: the length to read
201 * @first: first time read, DOC_READADDRESS should be set 223 * @first: first time read, DOC_READADDRESS should be set
202 * 224 *
203 * Reads bytes from flash data. Handles the single byte / even bytes reads. 225 * Reads bytes from flash data. Handles the single byte / even bytes reads.
@@ -218,8 +240,10 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
218 dst16 = buf; 240 dst16 = buf;
219 for (i = 0; i < len4; i += 2) { 241 for (i = 0; i < len4; i += 2) {
220 data16 = doc_readw(docg3, DOC_IOSPACE_DATA); 242 data16 = doc_readw(docg3, DOC_IOSPACE_DATA);
221 *dst16 = data16; 243 if (dst16) {
222 dst16++; 244 *dst16 = data16;
245 dst16++;
246 }
223 } 247 }
224 248
225 if (cdr) { 249 if (cdr) {
@@ -229,26 +253,84 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
229 dst8 = (u8 *)dst16; 253 dst8 = (u8 *)dst16;
230 for (i = 0; i < cdr; i++) { 254 for (i = 0; i < cdr; i++) {
231 data8 = doc_readb(docg3, DOC_IOSPACE_DATA); 255 data8 = doc_readb(docg3, DOC_IOSPACE_DATA);
232 *dst8 = data8; 256 if (dst8) {
233 dst8++; 257 *dst8 = data8;
258 dst8++;
259 }
234 } 260 }
235 } 261 }
236} 262}
237 263
238/** 264/**
239 * doc_set_data_mode - Sets the flash to reliable data mode 265 * doc_write_data_area - Write data into data area
266 * @docg3: the device
267 * @buf: the buffer to get input bytes from
268 * @len: the length to write
269 *
270 * Writes bytes into flash data. Handles the single byte / even bytes writes.
271 */
272static void doc_write_data_area(struct docg3 *docg3, const void *buf, int len)
273{
274 int i, cdr, len4;
275 u16 *src16;
276 u8 *src8;
277
278 doc_dbg("doc_write_data_area(buf=%p, len=%d)\n", buf, len);
279 cdr = len & 0x3;
280 len4 = len - cdr;
281
282 doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS);
283 src16 = (u16 *)buf;
284 for (i = 0; i < len4; i += 2) {
285 doc_writew(docg3, *src16, DOC_IOSPACE_DATA);
286 src16++;
287 }
288
289 src8 = (u8 *)src16;
290 for (i = 0; i < cdr; i++) {
291 doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE,
292 DOC_READADDRESS);
293 doc_writeb(docg3, *src8, DOC_IOSPACE_DATA);
294 src8++;
295 }
296}
297
298/**
299 * doc_set_data_mode - Sets the flash to normal or reliable data mode
240 * @docg3: the device 300 * @docg3: the device
241 * 301 *
242 * The reliable data mode is a bit slower than the fast mode, but less errors 302 * The reliable data mode is a bit slower than the fast mode, but less errors
243 * occur. Entering the reliable mode cannot be done without entering the fast 303 * occur. Entering the reliable mode cannot be done without entering the fast
244 * mode first. 304 * mode first.
305 *
306 * In reliable mode, pages 2*n and 2*n+1 are clones. Writing to page 0 of blocks
307 * (4,5) make the hardware write also to page 1 of blocks blocks(4,5). Reading
308 * from page 0 of blocks (4,5) or from page 1 of blocks (4,5) gives the same
309 * result, which is a logical and between bytes from page 0 and page 1 (which is
310 * consistent with the fact that writing to a page is _clearing_ bits of that
311 * page).
245 */ 312 */
246static void doc_set_reliable_mode(struct docg3 *docg3) 313static void doc_set_reliable_mode(struct docg3 *docg3)
247{ 314{
248 doc_dbg("doc_set_reliable_mode()\n"); 315 static char *strmode[] = { "normal", "fast", "reliable", "invalid" };
249 doc_flash_sequence(docg3, DOC_SEQ_SET_MODE); 316
250 doc_flash_command(docg3, DOC_CMD_FAST_MODE); 317 doc_dbg("doc_set_reliable_mode(%s)\n", strmode[docg3->reliable]);
251 doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE); 318 switch (docg3->reliable) {
319 case 0:
320 break;
321 case 1:
322 doc_flash_sequence(docg3, DOC_SEQ_SET_FASTMODE);
323 doc_flash_command(docg3, DOC_CMD_FAST_MODE);
324 break;
325 case 2:
326 doc_flash_sequence(docg3, DOC_SEQ_SET_RELIABLEMODE);
327 doc_flash_command(docg3, DOC_CMD_FAST_MODE);
328 doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE);
329 break;
330 default:
331 doc_err("doc_set_reliable_mode(): invalid mode\n");
332 break;
333 }
252 doc_delay(docg3, 2); 334 doc_delay(docg3, 2);
253} 335}
254 336
@@ -325,6 +407,37 @@ static int doc_set_extra_page_mode(struct docg3 *docg3)
325} 407}
326 408
327/** 409/**
410 * doc_setup_addr_sector - Setup blocks/page/ofs address for one plane
411 * @docg3: the device
412 * @sector: the sector
413 */
414static void doc_setup_addr_sector(struct docg3 *docg3, int sector)
415{
416 doc_delay(docg3, 1);
417 doc_flash_address(docg3, sector & 0xff);
418 doc_flash_address(docg3, (sector >> 8) & 0xff);
419 doc_flash_address(docg3, (sector >> 16) & 0xff);
420 doc_delay(docg3, 1);
421}
422
423/**
424 * doc_setup_writeaddr_sector - Setup blocks/page/ofs address for one plane
425 * @docg3: the device
426 * @sector: the sector
427 * @ofs: the offset in the page, between 0 and (512 + 16 + 512)
428 */
429static void doc_setup_writeaddr_sector(struct docg3 *docg3, int sector, int ofs)
430{
431 ofs = ofs >> 2;
432 doc_delay(docg3, 1);
433 doc_flash_address(docg3, ofs & 0xff);
434 doc_flash_address(docg3, sector & 0xff);
435 doc_flash_address(docg3, (sector >> 8) & 0xff);
436 doc_flash_address(docg3, (sector >> 16) & 0xff);
437 doc_delay(docg3, 1);
438}
439
440/**
328 * doc_seek - Set both flash planes to the specified block, page for reading 441 * doc_seek - Set both flash planes to the specified block, page for reading
329 * @docg3: the device 442 * @docg3: the device
330 * @block0: the first plane block index 443 * @block0: the first plane block index
@@ -360,34 +473,80 @@ static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page,
360 if (ret) 473 if (ret)
361 goto out; 474 goto out;
362 475
363 sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
364 doc_flash_sequence(docg3, DOC_SEQ_READ); 476 doc_flash_sequence(docg3, DOC_SEQ_READ);
477 sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
365 doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); 478 doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
366 doc_delay(docg3, 1); 479 doc_setup_addr_sector(docg3, sector);
367 doc_flash_address(docg3, sector & 0xff);
368 doc_flash_address(docg3, (sector >> 8) & 0xff);
369 doc_flash_address(docg3, (sector >> 16) & 0xff);
370 doc_delay(docg3, 1);
371 480
372 sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); 481 sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
373 doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); 482 doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
483 doc_setup_addr_sector(docg3, sector);
374 doc_delay(docg3, 1); 484 doc_delay(docg3, 1);
375 doc_flash_address(docg3, sector & 0xff); 485
376 doc_flash_address(docg3, (sector >> 8) & 0xff); 486out:
377 doc_flash_address(docg3, (sector >> 16) & 0xff); 487 return ret;
488}
489
490/**
491 * doc_write_seek - Set both flash planes to the specified block, page for writing
492 * @docg3: the device
493 * @block0: the first plane block index
494 * @block1: the second plane block index
495 * @page: the page index within the block
496 * @ofs: offset in page to write
497 *
498 * Programs the flash even and odd planes to the specific block and page.
499 * Alternatively, programs the flash to the wear area of the specified page.
500 */
501static int doc_write_seek(struct docg3 *docg3, int block0, int block1, int page,
502 int ofs)
503{
504 int ret = 0, sector;
505
506 doc_dbg("doc_write_seek(blocks=(%d,%d), page=%d, ofs=%d)\n",
507 block0, block1, page, ofs);
508
509 doc_set_reliable_mode(docg3);
510
511 if (ofs < 2 * DOC_LAYOUT_PAGE_SIZE) {
512 doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1);
513 doc_flash_command(docg3, DOC_CMD_READ_PLANE1);
514 doc_delay(docg3, 2);
515 } else {
516 doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2);
517 doc_flash_command(docg3, DOC_CMD_READ_PLANE2);
518 doc_delay(docg3, 2);
519 }
520
521 doc_flash_sequence(docg3, DOC_SEQ_PAGE_SETUP);
522 doc_flash_command(docg3, DOC_CMD_PROG_CYCLE1);
523
524 sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
525 doc_setup_writeaddr_sector(docg3, sector, ofs);
526
527 doc_flash_command(docg3, DOC_CMD_PROG_CYCLE3);
378 doc_delay(docg3, 2); 528 doc_delay(docg3, 2);
529 ret = doc_wait_ready(docg3);
530 if (ret)
531 goto out;
532
533 doc_flash_command(docg3, DOC_CMD_PROG_CYCLE1);
534 sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
535 doc_setup_writeaddr_sector(docg3, sector, ofs);
536 doc_delay(docg3, 1);
379 537
380out: 538out:
381 return ret; 539 return ret;
382} 540}
383 541
542
384/** 543/**
385 * doc_read_page_ecc_init - Initialize hardware ECC engine 544 * doc_read_page_ecc_init - Initialize hardware ECC engine
386 * @docg3: the device 545 * @docg3: the device
387 * @len: the number of bytes covered by the ECC (BCH covered) 546 * @len: the number of bytes covered by the ECC (BCH covered)
388 * 547 *
389 * The function does initialize the hardware ECC engine to compute the Hamming 548 * The function does initialize the hardware ECC engine to compute the Hamming
390 * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes). 549 * ECC (on 1 byte) and the BCH hardware ECC (on 7 bytes).
391 * 550 *
392 * Return 0 if succeeded, -EIO on error 551 * Return 0 if succeeded, -EIO on error
393 */ 552 */
@@ -403,6 +562,106 @@ static int doc_read_page_ecc_init(struct docg3 *docg3, int len)
403} 562}
404 563
405/** 564/**
565 * doc_write_page_ecc_init - Initialize hardware BCH ECC engine
566 * @docg3: the device
567 * @len: the number of bytes covered by the ECC (BCH covered)
568 *
569 * The function does initialize the hardware ECC engine to compute the Hamming
570 * ECC (on 1 byte) and the BCH hardware ECC (on 7 bytes).
571 *
572 * Return 0 if succeeded, -EIO on error
573 */
574static int doc_write_page_ecc_init(struct docg3 *docg3, int len)
575{
576 doc_writew(docg3, DOC_ECCCONF0_WRITE_MODE
577 | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE
578 | (len & DOC_ECCCONF0_DATA_BYTES_MASK),
579 DOC_ECCCONF0);
580 doc_delay(docg3, 4);
581 doc_register_readb(docg3, DOC_FLASHCONTROL);
582 return doc_wait_ready(docg3);
583}
584
585/**
586 * doc_ecc_disable - Disable Hamming and BCH ECC hardware calculator
587 * @docg3: the device
588 *
589 * Disables the hardware ECC generator and checker, for unchecked reads (as when
590 * reading OOB only or write status byte).
591 */
592static void doc_ecc_disable(struct docg3 *docg3)
593{
594 doc_writew(docg3, DOC_ECCCONF0_READ_MODE, DOC_ECCCONF0);
595 doc_delay(docg3, 4);
596}
597
598/**
599 * doc_hamming_ecc_init - Initialize hardware Hamming ECC engine
600 * @docg3: the device
601 * @nb_bytes: the number of bytes covered by the ECC (Hamming covered)
602 *
603 * This function programs the ECC hardware to compute the hamming code on the
604 * last provided N bytes to the hardware generator.
605 */
606static void doc_hamming_ecc_init(struct docg3 *docg3, int nb_bytes)
607{
608 u8 ecc_conf1;
609
610 ecc_conf1 = doc_register_readb(docg3, DOC_ECCCONF1);
611 ecc_conf1 &= ~DOC_ECCCONF1_HAMMING_BITS_MASK;
612 ecc_conf1 |= (nb_bytes & DOC_ECCCONF1_HAMMING_BITS_MASK);
613 doc_writeb(docg3, ecc_conf1, DOC_ECCCONF1);
614}
615
616/**
617 * doc_ecc_bch_fix_data - Fix if need be read data from flash
618 * @docg3: the device
619 * @buf: the buffer of read data (512 + 7 + 1 bytes)
620 * @hwecc: the hardware calculated ECC.
621 * It's in fact recv_ecc ^ calc_ecc, where recv_ecc was read from OOB
622 * area data, and calc_ecc the ECC calculated by the hardware generator.
623 *
624 * Checks if the received data matches the ECC, and if an error is detected,
625 * tries to fix the bit flips (at most 4) in the buffer buf. As the docg3
626 * understands the (data, ecc, syndroms) in an inverted order in comparison to
627 * the BCH library, the function reverses the order of bits (ie. bit7 and bit0,
628 * bit6 and bit 1, ...) for all ECC data.
629 *
630 * The hardware ecc unit produces oob_ecc ^ calc_ecc. The kernel's bch
631 * algorithm is used to decode this. However the hw operates on page
632 * data in a bit order that is the reverse of that of the bch alg,
633 * requiring that the bits be reversed on the result. Thanks to Ivan
634 * Djelic for his analysis.
635 *
636 * Returns number of fixed bits (0, 1, 2, 3, 4) or -EBADMSG if too many bit
637 * errors were detected and cannot be fixed.
638 */
639static int doc_ecc_bch_fix_data(struct docg3 *docg3, void *buf, u8 *hwecc)
640{
641 u8 ecc[DOC_ECC_BCH_SIZE];
642 int errorpos[DOC_ECC_BCH_T], i, numerrs;
643
644 for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
645 ecc[i] = bitrev8(hwecc[i]);
646 numerrs = decode_bch(docg3_bch, NULL, DOC_ECC_BCH_COVERED_BYTES,
647 NULL, ecc, NULL, errorpos);
648 BUG_ON(numerrs == -EINVAL);
649 if (numerrs < 0)
650 goto out;
651
652 for (i = 0; i < numerrs; i++)
653 errorpos[i] = (errorpos[i] & ~7) | (7 - (errorpos[i] & 7));
654 for (i = 0; i < numerrs; i++)
655 if (errorpos[i] < DOC_ECC_BCH_COVERED_BYTES*8)
656 /* error is located in data, correct it */
657 change_bit(errorpos[i], buf);
658out:
659 doc_dbg("doc_ecc_bch_fix_data: flipped %d bits\n", numerrs);
660 return numerrs;
661}
662
663
664/**
406 * doc_read_page_prepare - Prepares reading data from a flash page 665 * doc_read_page_prepare - Prepares reading data from a flash page
407 * @docg3: the device 666 * @docg3: the device
408 * @block0: the first plane block index on flash memory 667 * @block0: the first plane block index on flash memory
@@ -488,16 +747,40 @@ static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
488} 747}
489 748
490/** 749/**
491 * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms 750 * doc_write_page_putbytes - Writes bytes into a prepared page
751 * @docg3: the device
752 * @len: the number of bytes to be written
753 * @buf: the buffer of input bytes
754 *
755 */
756static void doc_write_page_putbytes(struct docg3 *docg3, int len,
757 const u_char *buf)
758{
759 doc_write_data_area(docg3, buf, len);
760 doc_delay(docg3, 2);
761}
762
763/**
764 * doc_get_bch_hw_ecc - Get hardware calculated BCH ECC
492 * @docg3: the device 765 * @docg3: the device
493 * @syns: the array of 7 integers where the syndroms will be stored 766 * @hwecc: the array of 7 integers where the hardware ecc will be stored
494 */ 767 */
495static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns) 768static void doc_get_bch_hw_ecc(struct docg3 *docg3, u8 *hwecc)
496{ 769{
497 int i; 770 int i;
498 771
499 for (i = 0; i < DOC_ECC_BCH_SIZE; i++) 772 for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
500 syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i)); 773 hwecc[i] = doc_register_readb(docg3, DOC_BCH_HW_ECC(i));
774}
775
776/**
777 * doc_page_finish - Ends reading/writing of a flash page
778 * @docg3: the device
779 */
780static void doc_page_finish(struct docg3 *docg3)
781{
782 doc_writeb(docg3, 0, DOC_DATAEND);
783 doc_delay(docg3, 2);
501} 784}
502 785
503/** 786/**
@@ -510,8 +793,7 @@ static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns)
510 */ 793 */
511static void doc_read_page_finish(struct docg3 *docg3) 794static void doc_read_page_finish(struct docg3 *docg3)
512{ 795{
513 doc_writeb(docg3, 0, DOC_DATAEND); 796 doc_page_finish(docg3);
514 doc_delay(docg3, 2);
515 doc_set_device_id(docg3, 0); 797 doc_set_device_id(docg3, 0);
516} 798}
517 799
@@ -523,18 +805,29 @@ static void doc_read_page_finish(struct docg3 *docg3)
523 * @block1: second plane block index calculated 805 * @block1: second plane block index calculated
524 * @page: page calculated 806 * @page: page calculated
525 * @ofs: offset in page 807 * @ofs: offset in page
808 * @reliable: 0 if docg3 in normal mode, 1 if docg3 in fast mode, 2 if docg3 in
809 * reliable mode.
810 *
811 * The calculation is based on the reliable/normal mode. In normal mode, the 64
812 * pages of a block are available. In reliable mode, as pages 2*n and 2*n+1 are
813 * clones, only 32 pages per block are available.
526 */ 814 */
527static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, 815static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
528 int *ofs) 816 int *ofs, int reliable)
529{ 817{
530 uint sector; 818 uint sector, pages_biblock;
819
820 pages_biblock = DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES;
821 if (reliable == 1 || reliable == 2)
822 pages_biblock /= 2;
531 823
532 sector = from / DOC_LAYOUT_PAGE_SIZE; 824 sector = from / DOC_LAYOUT_PAGE_SIZE;
533 *block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES) 825 *block0 = sector / pages_biblock * DOC_LAYOUT_NBPLANES;
534 * DOC_LAYOUT_NBPLANES;
535 *block1 = *block0 + 1; 826 *block1 = *block0 + 1;
536 *page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES); 827 *page = sector % pages_biblock;
537 *page /= DOC_LAYOUT_NBPLANES; 828 *page /= DOC_LAYOUT_NBPLANES;
829 if (reliable == 1 || reliable == 2)
830 *page *= 2;
538 if (sector % 2) 831 if (sector % 2)
539 *ofs = DOC_LAYOUT_PAGE_OOB_SIZE; 832 *ofs = DOC_LAYOUT_PAGE_OOB_SIZE;
540 else 833 else
@@ -542,99 +835,124 @@ static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
542} 835}
543 836
544/** 837/**
545 * doc_read - Read bytes from flash 838 * doc_read_oob - Read out of band bytes from flash
546 * @mtd: the device 839 * @mtd: the device
547 * @from: the offset from first block and first page, in bytes, aligned on page 840 * @from: the offset from first block and first page, in bytes, aligned on page
548 * size 841 * size
549 * @len: the number of bytes to read (must be a multiple of 4) 842 * @ops: the mtd oob structure
550 * @retlen: the number of bytes actually read
551 * @buf: the filled in buffer
552 * 843 *
553 * Reads flash memory pages. This function does not read the OOB chunk, but only 844 * Reads flash memory OOB area of pages.
554 * the page data.
555 * 845 *
556 * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured 846 * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
557 */ 847 */
558static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, 848static int doc_read_oob(struct mtd_info *mtd, loff_t from,
559 size_t *retlen, u_char *buf) 849 struct mtd_oob_ops *ops)
560{ 850{
561 struct docg3 *docg3 = mtd->priv; 851 struct docg3 *docg3 = mtd->priv;
562 int block0, block1, page, readlen, ret, ofs = 0; 852 int block0, block1, page, ret, ofs = 0;
563 int syn[DOC_ECC_BCH_SIZE], eccconf1; 853 u8 *oobbuf = ops->oobbuf;
564 u8 oob[DOC_LAYOUT_OOB_SIZE]; 854 u8 *buf = ops->datbuf;
855 size_t len, ooblen, nbdata, nboob;
856 u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1;
857
858 if (buf)
859 len = ops->len;
860 else
861 len = 0;
862 if (oobbuf)
863 ooblen = ops->ooblen;
864 else
865 ooblen = 0;
866
867 if (oobbuf && ops->mode == MTD_OPS_PLACE_OOB)
868 oobbuf += ops->ooboffs;
869
870 doc_dbg("doc_read_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n",
871 from, ops->mode, buf, len, oobbuf, ooblen);
872 if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % DOC_LAYOUT_OOB_SIZE) ||
873 (from % DOC_LAYOUT_PAGE_SIZE))
874 return -EINVAL;
565 875
566 ret = -EINVAL; 876 ret = -EINVAL;
567 doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf); 877 calc_block_sector(from + len, &block0, &block1, &page, &ofs,
568 if (from % DOC_LAYOUT_PAGE_SIZE) 878 docg3->reliable);
569 goto err;
570 if (len % 4)
571 goto err;
572 calc_block_sector(from, &block0, &block1, &page, &ofs);
573 if (block1 > docg3->max_block) 879 if (block1 > docg3->max_block)
574 goto err; 880 goto err;
575 881
576 *retlen = 0; 882 ops->oobretlen = 0;
883 ops->retlen = 0;
577 ret = 0; 884 ret = 0;
578 readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); 885 while (!ret && (len > 0 || ooblen > 0)) {
579 while (!ret && len > 0) { 886 calc_block_sector(from, &block0, &block1, &page, &ofs,
580 readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); 887 docg3->reliable);
888 nbdata = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
889 nboob = min_t(size_t, ooblen, (size_t)DOC_LAYOUT_OOB_SIZE);
581 ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); 890 ret = doc_read_page_prepare(docg3, block0, block1, page, ofs);
582 if (ret < 0) 891 if (ret < 0)
583 goto err; 892 goto err;
584 ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES); 893 ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES);
585 if (ret < 0) 894 if (ret < 0)
586 goto err_in_read; 895 goto err_in_read;
587 ret = doc_read_page_getbytes(docg3, readlen, buf, 1); 896 ret = doc_read_page_getbytes(docg3, nbdata, buf, 1);
588 if (ret < readlen) 897 if (ret < nbdata)
589 goto err_in_read; 898 goto err_in_read;
590 ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, 899 doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE - nbdata,
591 oob, 0); 900 NULL, 0);
592 if (ret < DOC_LAYOUT_OOB_SIZE) 901 ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0);
902 if (ret < nboob)
593 goto err_in_read; 903 goto err_in_read;
904 doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob,
905 NULL, 0);
594 906
595 *retlen += readlen; 907 doc_get_bch_hw_ecc(docg3, hwecc);
596 buf += readlen;
597 len -= readlen;
598
599 ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE;
600 if (ofs == 0)
601 page += 2;
602 if (page > DOC_ADDR_PAGE_MASK) {
603 page = 0;
604 block0 += 2;
605 block1 += 2;
606 }
607
608 /*
609 * There should be a BCH bitstream fixing algorithm here ...
610 * By now, a page read failure is triggered by BCH error
611 */
612 doc_get_hw_bch_syndroms(docg3, syn);
613 eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); 908 eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
614 909
615 doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 910 if (nboob >= DOC_LAYOUT_OOB_SIZE) {
616 oob[0], oob[1], oob[2], oob[3], oob[4], 911 doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
617 oob[5], oob[6]); 912 oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3],
618 doc_dbg("OOB - HAMMING: %02x\n", oob[7]); 913 oobbuf[4], oobbuf[5], oobbuf[6]);
619 doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 914 doc_dbg("OOB - HAMMING: %02x\n", oobbuf[7]);
620 oob[8], oob[9], oob[10], oob[11], oob[12], 915 doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
621 oob[13], oob[14]); 916 oobbuf[8], oobbuf[9], oobbuf[10], oobbuf[11],
622 doc_dbg("OOB - UNUSED: %02x\n", oob[15]); 917 oobbuf[12], oobbuf[13], oobbuf[14]);
918 doc_dbg("OOB - UNUSED: %02x\n", oobbuf[15]);
919 }
623 doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1); 920 doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
624 doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 921 doc_dbg("ECC HW_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
625 syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]); 922 hwecc[0], hwecc[1], hwecc[2], hwecc[3], hwecc[4],
626 923 hwecc[5], hwecc[6]);
627 ret = -EBADMSG; 924
628 if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) { 925 ret = -EIO;
629 if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) 926 if (is_prot_seq_error(docg3))
630 goto err_in_read; 927 goto err_in_read;
631 if (is_prot_seq_error(docg3)) 928 ret = 0;
632 goto err_in_read; 929 if ((block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) &&
930 (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) &&
931 (eccconf1 & DOC_ECCCONF1_PAGE_IS_WRITTEN) &&
932 (ops->mode != MTD_OPS_RAW) &&
933 (nbdata == DOC_LAYOUT_PAGE_SIZE)) {
934 ret = doc_ecc_bch_fix_data(docg3, buf, hwecc);
935 if (ret < 0) {
936 mtd->ecc_stats.failed++;
937 ret = -EBADMSG;
938 }
939 if (ret > 0) {
940 mtd->ecc_stats.corrected += ret;
941 ret = -EUCLEAN;
942 }
633 } 943 }
944
634 doc_read_page_finish(docg3); 945 doc_read_page_finish(docg3);
946 ops->retlen += nbdata;
947 ops->oobretlen += nboob;
948 buf += nbdata;
949 oobbuf += nboob;
950 len -= nbdata;
951 ooblen -= nboob;
952 from += DOC_LAYOUT_PAGE_SIZE;
635 } 953 }
636 954
637 return 0; 955 return ret;
638err_in_read: 956err_in_read:
639 doc_read_page_finish(docg3); 957 doc_read_page_finish(docg3);
640err: 958err:
@@ -642,54 +960,33 @@ err:
642} 960}
643 961
644/** 962/**
645 * doc_read_oob - Read out of band bytes from flash 963 * doc_read - Read bytes from flash
646 * @mtd: the device 964 * @mtd: the device
647 * @from: the offset from first block and first page, in bytes, aligned on page 965 * @from: the offset from first block and first page, in bytes, aligned on page
648 * size 966 * size
649 * @ops: the mtd oob structure 967 * @len: the number of bytes to read (must be a multiple of 4)
968 * @retlen: the number of bytes actually read
969 * @buf: the filled in buffer
650 * 970 *
651 * Reads flash memory OOB area of pages. 971 * Reads flash memory pages. This function does not read the OOB chunk, but only
972 * the page data.
652 * 973 *
653 * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured 974 * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
654 */ 975 */
655static int doc_read_oob(struct mtd_info *mtd, loff_t from, 976static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
656 struct mtd_oob_ops *ops) 977 size_t *retlen, u_char *buf)
657{ 978{
658 struct docg3 *docg3 = mtd->priv; 979 struct mtd_oob_ops ops;
659 int block0, block1, page, ofs, ret; 980 size_t ret;
660 u8 *buf = ops->oobbuf;
661 size_t len = ops->ooblen;
662
663 doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len);
664 if (len != DOC_LAYOUT_OOB_SIZE)
665 return -EINVAL;
666
667 switch (ops->mode) {
668 case MTD_OPS_PLACE_OOB:
669 buf += ops->ooboffs;
670 break;
671 default:
672 break;
673 }
674 981
675 calc_block_sector(from, &block0, &block1, &page, &ofs); 982 memset(&ops, 0, sizeof(ops));
676 if (block1 > docg3->max_block) 983 ops.datbuf = buf;
677 return -EINVAL; 984 ops.len = len;
678 985 ops.mode = MTD_OPS_AUTO_OOB;
679 ret = doc_read_page_prepare(docg3, block0, block1, page,
680 ofs + DOC_LAYOUT_PAGE_SIZE);
681 if (!ret)
682 ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE);
683 if (!ret)
684 ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
685 buf, 1);
686 doc_read_page_finish(docg3);
687 986
688 if (ret > 0) 987 ret = doc_read_oob(mtd, from, &ops);
689 ops->oobretlen = ret; 988 *retlen = ops.retlen;
690 else 989 return ret;
691 ops->oobretlen = 0;
692 return (ret > 0) ? 0 : ret;
693} 990}
694 991
695static int doc_reload_bbt(struct docg3 *docg3) 992static int doc_reload_bbt(struct docg3 *docg3)
@@ -726,7 +1023,8 @@ static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
726 struct docg3 *docg3 = mtd->priv; 1023 struct docg3 *docg3 = mtd->priv;
727 int block0, block1, page, ofs, is_good; 1024 int block0, block1, page, ofs, is_good;
728 1025
729 calc_block_sector(from, &block0, &block1, &page, &ofs); 1026 calc_block_sector(from, &block0, &block1, &page, &ofs,
1027 docg3->reliable);
730 doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n", 1028 doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n",
731 from, block0, block1, page, ofs); 1029 from, block0, block1, page, ofs);
732 1030
@@ -739,6 +1037,7 @@ static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
739 return !is_good; 1037 return !is_good;
740} 1038}
741 1039
1040#if 0
742/** 1041/**
743 * doc_get_erase_count - Get block erase count 1042 * doc_get_erase_count - Get block erase count
744 * @docg3: the device 1043 * @docg3: the device
@@ -758,7 +1057,7 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from)
758 doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf); 1057 doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf);
759 if (from % DOC_LAYOUT_PAGE_SIZE) 1058 if (from % DOC_LAYOUT_PAGE_SIZE)
760 return -EINVAL; 1059 return -EINVAL;
761 calc_block_sector(from, &block0, &block1, &page, &ofs); 1060 calc_block_sector(from, &block0, &block1, &page, &ofs, docg3->reliable);
762 if (block1 > docg3->max_block) 1061 if (block1 > docg3->max_block)
763 return -EINVAL; 1062 return -EINVAL;
764 1063
@@ -780,6 +1079,558 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from)
780 1079
781 return max(plane1_erase_count, plane2_erase_count); 1080 return max(plane1_erase_count, plane2_erase_count);
782} 1081}
1082#endif
1083
1084/**
1085 * doc_get_op_status - get erase/write operation status
1086 * @docg3: the device
1087 *
1088 * Queries the status from the chip, and returns it
1089 *
1090 * Returns the status (bits DOC_PLANES_STATUS_*)
1091 */
1092static int doc_get_op_status(struct docg3 *docg3)
1093{
1094 u8 status;
1095
1096 doc_flash_sequence(docg3, DOC_SEQ_PLANES_STATUS);
1097 doc_flash_command(docg3, DOC_CMD_PLANES_STATUS);
1098 doc_delay(docg3, 5);
1099
1100 doc_ecc_disable(docg3);
1101 doc_read_data_area(docg3, &status, 1, 1);
1102 return status;
1103}
1104
1105/**
1106 * doc_write_erase_wait_status - wait for write or erase completion
1107 * @docg3: the device
1108 *
1109 * Wait for the chip to be ready again after erase or write operation, and check
1110 * erase/write status.
1111 *
1112 * Returns 0 if erase successfull, -EIO if erase/write issue, -ETIMEOUT if
1113 * timeout
1114 */
1115static int doc_write_erase_wait_status(struct docg3 *docg3)
1116{
1117 int status, ret = 0;
1118
1119 if (!doc_is_ready(docg3))
1120 usleep_range(3000, 3000);
1121 if (!doc_is_ready(docg3)) {
1122 doc_dbg("Timeout reached and the chip is still not ready\n");
1123 ret = -EAGAIN;
1124 goto out;
1125 }
1126
1127 status = doc_get_op_status(docg3);
1128 if (status & DOC_PLANES_STATUS_FAIL) {
1129 doc_dbg("Erase/Write failed on (a) plane(s), status = %x\n",
1130 status);
1131 ret = -EIO;
1132 }
1133
1134out:
1135 doc_page_finish(docg3);
1136 return ret;
1137}
1138
1139/**
1140 * doc_erase_block - Erase a couple of blocks
1141 * @docg3: the device
1142 * @block0: the first block to erase (leftmost plane)
1143 * @block1: the second block to erase (rightmost plane)
1144 *
1145 * Erase both blocks, and return operation status
1146 *
1147 * Returns 0 if erase successful, -EIO if erase issue, -ETIMEOUT if chip not
1148 * ready for too long
1149 */
1150static int doc_erase_block(struct docg3 *docg3, int block0, int block1)
1151{
1152 int ret, sector;
1153
1154 doc_dbg("doc_erase_block(blocks=(%d,%d))\n", block0, block1);
1155 ret = doc_reset_seq(docg3);
1156 if (ret)
1157 return -EIO;
1158
1159 doc_set_reliable_mode(docg3);
1160 doc_flash_sequence(docg3, DOC_SEQ_ERASE);
1161
1162 sector = block0 << DOC_ADDR_BLOCK_SHIFT;
1163 doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
1164 doc_setup_addr_sector(docg3, sector);
1165 sector = block1 << DOC_ADDR_BLOCK_SHIFT;
1166 doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
1167 doc_setup_addr_sector(docg3, sector);
1168 doc_delay(docg3, 1);
1169
1170 doc_flash_command(docg3, DOC_CMD_ERASECYCLE2);
1171 doc_delay(docg3, 2);
1172
1173 if (is_prot_seq_error(docg3)) {
1174 doc_err("Erase blocks %d,%d error\n", block0, block1);
1175 return -EIO;
1176 }
1177
1178 return doc_write_erase_wait_status(docg3);
1179}
1180
1181/**
1182 * doc_erase - Erase a portion of the chip
1183 * @mtd: the device
1184 * @info: the erase info
1185 *
1186 * Erase a bunch of contiguous blocks, by pairs, as a "mtd" page of 1024 is
1187 * split into 2 pages of 512 bytes on 2 contiguous blocks.
1188 *
1189 * Returns 0 if erase successful, -EINVAL if adressing error, -EIO if erase
1190 * issue
1191 */
1192static int doc_erase(struct mtd_info *mtd, struct erase_info *info)
1193{
1194 struct docg3 *docg3 = mtd->priv;
1195 uint64_t len;
1196 int block0, block1, page, ret, ofs = 0;
1197
1198 doc_dbg("doc_erase(from=%lld, len=%lld\n", info->addr, info->len);
1199 doc_set_device_id(docg3, docg3->device_id);
1200
1201 info->state = MTD_ERASE_PENDING;
1202 calc_block_sector(info->addr + info->len, &block0, &block1, &page,
1203 &ofs, docg3->reliable);
1204 ret = -EINVAL;
1205 if (block1 > docg3->max_block || page || ofs)
1206 goto reset_err;
1207
1208 ret = 0;
1209 calc_block_sector(info->addr, &block0, &block1, &page, &ofs,
1210 docg3->reliable);
1211 doc_set_reliable_mode(docg3);
1212 for (len = info->len; !ret && len > 0; len -= mtd->erasesize) {
1213 info->state = MTD_ERASING;
1214 ret = doc_erase_block(docg3, block0, block1);
1215 block0 += 2;
1216 block1 += 2;
1217 }
1218
1219 if (ret)
1220 goto reset_err;
1221
1222 info->state = MTD_ERASE_DONE;
1223 return 0;
1224
1225reset_err:
1226 info->state = MTD_ERASE_FAILED;
1227 return ret;
1228}
1229
1230/**
1231 * doc_write_page - Write a single page to the chip
1232 * @docg3: the device
1233 * @to: the offset from first block and first page, in bytes, aligned on page
1234 * size
1235 * @buf: buffer to get bytes from
1236 * @oob: buffer to get out of band bytes from (can be NULL if no OOB should be
1237 * written)
1238 * @autoecc: if 0, all 16 bytes from OOB are taken, regardless of HW Hamming or
1239 * BCH computations. If 1, only bytes 0-7 and byte 15 are taken,
1240 * remaining ones are filled with hardware Hamming and BCH
1241 * computations. Its value is not meaningfull is oob == NULL.
1242 *
1243 * Write one full page (ie. 1 page split on two planes), of 512 bytes, with the
1244 * OOB data. The OOB ECC is automatically computed by the hardware Hamming and
1245 * BCH generator if autoecc is not null.
1246 *
1247 * Returns 0 if write successful, -EIO if write error, -EAGAIN if timeout
1248 */
1249static int doc_write_page(struct docg3 *docg3, loff_t to, const u_char *buf,
1250 const u_char *oob, int autoecc)
1251{
1252 int block0, block1, page, ret, ofs = 0;
1253 u8 hwecc[DOC_ECC_BCH_SIZE], hamming;
1254
1255 doc_dbg("doc_write_page(to=%lld)\n", to);
1256 calc_block_sector(to, &block0, &block1, &page, &ofs, docg3->reliable);
1257
1258 doc_set_device_id(docg3, docg3->device_id);
1259 ret = doc_reset_seq(docg3);
1260 if (ret)
1261 goto err;
1262
1263 /* Program the flash address block and page */
1264 ret = doc_write_seek(docg3, block0, block1, page, ofs);
1265 if (ret)
1266 goto err;
1267
1268 doc_write_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES);
1269 doc_delay(docg3, 2);
1270 doc_write_page_putbytes(docg3, DOC_LAYOUT_PAGE_SIZE, buf);
1271
1272 if (oob && autoecc) {
1273 doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ, oob);
1274 doc_delay(docg3, 2);
1275 oob += DOC_LAYOUT_OOB_UNUSED_OFS;
1276
1277 hamming = doc_register_readb(docg3, DOC_HAMMINGPARITY);
1278 doc_delay(docg3, 2);
1279 doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_HAMMING_SZ,
1280 &hamming);
1281 doc_delay(docg3, 2);
1282
1283 doc_get_bch_hw_ecc(docg3, hwecc);
1284 doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_BCH_SZ, hwecc);
1285 doc_delay(docg3, 2);
1286
1287 doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_UNUSED_SZ, oob);
1288 }
1289 if (oob && !autoecc)
1290 doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_SIZE, oob);
1291
1292 doc_delay(docg3, 2);
1293 doc_page_finish(docg3);
1294 doc_delay(docg3, 2);
1295 doc_flash_command(docg3, DOC_CMD_PROG_CYCLE2);
1296 doc_delay(docg3, 2);
1297
1298 /*
1299 * The wait status will perform another doc_page_finish() call, but that
1300 * seems to please the docg3, so leave it.
1301 */
1302 ret = doc_write_erase_wait_status(docg3);
1303 return ret;
1304err:
1305 doc_read_page_finish(docg3);
1306 return ret;
1307}
1308
1309/**
1310 * doc_guess_autoecc - Guess autoecc mode from mbd_oob_ops
1311 * @ops: the oob operations
1312 *
1313 * Returns 0 or 1 if success, -EINVAL if invalid oob mode
1314 */
1315static int doc_guess_autoecc(struct mtd_oob_ops *ops)
1316{
1317 int autoecc;
1318
1319 switch (ops->mode) {
1320 case MTD_OPS_PLACE_OOB:
1321 case MTD_OPS_AUTO_OOB:
1322 autoecc = 1;
1323 break;
1324 case MTD_OPS_RAW:
1325 autoecc = 0;
1326 break;
1327 default:
1328 autoecc = -EINVAL;
1329 }
1330 return autoecc;
1331}
1332
1333/**
1334 * doc_fill_autooob - Fill a 16 bytes OOB from 8 non-ECC bytes
1335 * @dst: the target 16 bytes OOB buffer
1336 * @oobsrc: the source 8 bytes non-ECC OOB buffer
1337 *
1338 */
1339static void doc_fill_autooob(u8 *dst, u8 *oobsrc)
1340{
1341 memcpy(dst, oobsrc, DOC_LAYOUT_OOB_PAGEINFO_SZ);
1342 dst[DOC_LAYOUT_OOB_UNUSED_OFS] = oobsrc[DOC_LAYOUT_OOB_PAGEINFO_SZ];
1343}
1344
1345/**
1346 * doc_backup_oob - Backup OOB into docg3 structure
1347 * @docg3: the device
1348 * @to: the page offset in the chip
1349 * @ops: the OOB size and buffer
1350 *
1351 * As the docg3 should write a page with its OOB in one pass, and some userland
1352 * applications do write_oob() to setup the OOB and then write(), store the OOB
1353 * into a temporary storage. This is very dangerous, as 2 concurrent
1354 * applications could store an OOB, and then write their pages (which will
1355 * result into one having its OOB corrupted).
1356 *
1357 * The only reliable way would be for userland to call doc_write_oob() with both
1358 * the page data _and_ the OOB area.
1359 *
1360 * Returns 0 if success, -EINVAL if ops content invalid
1361 */
1362static int doc_backup_oob(struct docg3 *docg3, loff_t to,
1363 struct mtd_oob_ops *ops)
1364{
1365 int ooblen = ops->ooblen, autoecc;
1366
1367 if (ooblen != DOC_LAYOUT_OOB_SIZE)
1368 return -EINVAL;
1369 autoecc = doc_guess_autoecc(ops);
1370 if (autoecc < 0)
1371 return autoecc;
1372
1373 docg3->oob_write_ofs = to;
1374 docg3->oob_autoecc = autoecc;
1375 if (ops->mode == MTD_OPS_AUTO_OOB) {
1376 doc_fill_autooob(docg3->oob_write_buf, ops->oobbuf);
1377 ops->oobretlen = 8;
1378 } else {
1379 memcpy(docg3->oob_write_buf, ops->oobbuf, DOC_LAYOUT_OOB_SIZE);
1380 ops->oobretlen = DOC_LAYOUT_OOB_SIZE;
1381 }
1382 return 0;
1383}
1384
1385/**
1386 * doc_write_oob - Write out of band bytes to flash
1387 * @mtd: the device
1388 * @ofs: the offset from first block and first page, in bytes, aligned on page
1389 * size
1390 * @ops: the mtd oob structure
1391 *
1392 * Either write OOB data into a temporary buffer, for the subsequent write
1393 * page. The provided OOB should be 16 bytes long. If a data buffer is provided
1394 * as well, issue the page write.
1395 * Or provide data without OOB, and then a all zeroed OOB will be used (ECC will
1396 * still be filled in if asked for).
1397 *
1398 * Returns 0 is successfull, EINVAL if length is not 14 bytes
1399 */
1400static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
1401 struct mtd_oob_ops *ops)
1402{
1403 struct docg3 *docg3 = mtd->priv;
1404 int block0, block1, page, ret, pofs = 0, autoecc, oobdelta;
1405 u8 *oobbuf = ops->oobbuf;
1406 u8 *buf = ops->datbuf;
1407 size_t len, ooblen;
1408 u8 oob[DOC_LAYOUT_OOB_SIZE];
1409
1410 if (buf)
1411 len = ops->len;
1412 else
1413 len = 0;
1414 if (oobbuf)
1415 ooblen = ops->ooblen;
1416 else
1417 ooblen = 0;
1418
1419 if (oobbuf && ops->mode == MTD_OPS_PLACE_OOB)
1420 oobbuf += ops->ooboffs;
1421
1422 doc_dbg("doc_write_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n",
1423 ofs, ops->mode, buf, len, oobbuf, ooblen);
1424 switch (ops->mode) {
1425 case MTD_OPS_PLACE_OOB:
1426 case MTD_OPS_RAW:
1427 oobdelta = mtd->oobsize;
1428 break;
1429 case MTD_OPS_AUTO_OOB:
1430 oobdelta = mtd->ecclayout->oobavail;
1431 break;
1432 default:
1433 oobdelta = 0;
1434 }
1435 if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % oobdelta) ||
1436 (ofs % DOC_LAYOUT_PAGE_SIZE))
1437 return -EINVAL;
1438 if (len && ooblen &&
1439 (len / DOC_LAYOUT_PAGE_SIZE) != (ooblen / oobdelta))
1440 return -EINVAL;
1441
1442 ret = -EINVAL;
1443 calc_block_sector(ofs + len, &block0, &block1, &page, &pofs,
1444 docg3->reliable);
1445 if (block1 > docg3->max_block)
1446 goto err;
1447
1448 ops->oobretlen = 0;
1449 ops->retlen = 0;
1450 ret = 0;
1451 if (len == 0 && ooblen == 0)
1452 return -EINVAL;
1453 if (len == 0 && ooblen > 0)
1454 return doc_backup_oob(docg3, ofs, ops);
1455
1456 autoecc = doc_guess_autoecc(ops);
1457 if (autoecc < 0)
1458 return autoecc;
1459
1460 while (!ret && len > 0) {
1461 memset(oob, 0, sizeof(oob));
1462 if (ofs == docg3->oob_write_ofs)
1463 memcpy(oob, docg3->oob_write_buf, DOC_LAYOUT_OOB_SIZE);
1464 else if (ooblen > 0 && ops->mode == MTD_OPS_AUTO_OOB)
1465 doc_fill_autooob(oob, oobbuf);
1466 else if (ooblen > 0)
1467 memcpy(oob, oobbuf, DOC_LAYOUT_OOB_SIZE);
1468 ret = doc_write_page(docg3, ofs, buf, oob, autoecc);
1469
1470 ofs += DOC_LAYOUT_PAGE_SIZE;
1471 len -= DOC_LAYOUT_PAGE_SIZE;
1472 buf += DOC_LAYOUT_PAGE_SIZE;
1473 if (ooblen) {
1474 oobbuf += oobdelta;
1475 ooblen -= oobdelta;
1476 ops->oobretlen += oobdelta;
1477 }
1478 ops->retlen += DOC_LAYOUT_PAGE_SIZE;
1479 }
1480err:
1481 doc_set_device_id(docg3, 0);
1482 return ret;
1483}
1484
1485/**
1486 * doc_write - Write a buffer to the chip
1487 * @mtd: the device
1488 * @to: the offset from first block and first page, in bytes, aligned on page
1489 * size
1490 * @len: the number of bytes to write (must be a full page size, ie. 512)
1491 * @retlen: the number of bytes actually written (0 or 512)
1492 * @buf: the buffer to get bytes from
1493 *
1494 * Writes data to the chip.
1495 *
1496 * Returns 0 if write successful, -EIO if write error
1497 */
1498static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
1499 size_t *retlen, const u_char *buf)
1500{
1501 struct docg3 *docg3 = mtd->priv;
1502 int ret;
1503 struct mtd_oob_ops ops;
1504
1505 doc_dbg("doc_write(to=%lld, len=%zu)\n", to, len);
1506 ops.datbuf = (char *)buf;
1507 ops.len = len;
1508 ops.mode = MTD_OPS_PLACE_OOB;
1509 ops.oobbuf = NULL;
1510 ops.ooblen = 0;
1511 ops.ooboffs = 0;
1512
1513 ret = doc_write_oob(mtd, to, &ops);
1514 *retlen = ops.retlen;
1515 return ret;
1516}
1517
1518static struct docg3 *sysfs_dev2docg3(struct device *dev,
1519 struct device_attribute *attr)
1520{
1521 int floor;
1522 struct platform_device *pdev = to_platform_device(dev);
1523 struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
1524
1525 floor = attr->attr.name[1] - '0';
1526 if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
1527 return NULL;
1528 else
1529 return docg3_floors[floor]->priv;
1530}
1531
1532static ssize_t dps0_is_key_locked(struct device *dev,
1533 struct device_attribute *attr, char *buf)
1534{
1535 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1536 int dps0;
1537
1538 doc_set_device_id(docg3, docg3->device_id);
1539 dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
1540 doc_set_device_id(docg3, 0);
1541
1542 return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK));
1543}
1544
1545static ssize_t dps1_is_key_locked(struct device *dev,
1546 struct device_attribute *attr, char *buf)
1547{
1548 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1549 int dps1;
1550
1551 doc_set_device_id(docg3, docg3->device_id);
1552 dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
1553 doc_set_device_id(docg3, 0);
1554
1555 return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK));
1556}
1557
1558static ssize_t dps0_insert_key(struct device *dev,
1559 struct device_attribute *attr,
1560 const char *buf, size_t count)
1561{
1562 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1563 int i;
1564
1565 if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
1566 return -EINVAL;
1567
1568 doc_set_device_id(docg3, docg3->device_id);
1569 for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
1570 doc_writeb(docg3, buf[i], DOC_DPS0_KEY);
1571 doc_set_device_id(docg3, 0);
1572 return count;
1573}
1574
1575static ssize_t dps1_insert_key(struct device *dev,
1576 struct device_attribute *attr,
1577 const char *buf, size_t count)
1578{
1579 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1580 int i;
1581
1582 if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
1583 return -EINVAL;
1584
1585 doc_set_device_id(docg3, docg3->device_id);
1586 for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
1587 doc_writeb(docg3, buf[i], DOC_DPS1_KEY);
1588 doc_set_device_id(docg3, 0);
1589 return count;
1590}
1591
1592#define FLOOR_SYSFS(id) { \
1593 __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
1594 __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
1595 __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
1596 __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
1597}
1598
1599static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
1600 FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3)
1601};
1602
1603static int doc_register_sysfs(struct platform_device *pdev,
1604 struct mtd_info **floors)
1605{
1606 int ret = 0, floor, i = 0;
1607 struct device *dev = &pdev->dev;
1608
1609 for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
1610 floor++)
1611 for (i = 0; !ret && i < 4; i++)
1612 ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
1613 if (!ret)
1614 return 0;
1615 do {
1616 while (--i >= 0)
1617 device_remove_file(dev, &doc_sys_attrs[floor][i]);
1618 i = 4;
1619 } while (--floor >= 0);
1620 return ret;
1621}
1622
1623static void doc_unregister_sysfs(struct platform_device *pdev,
1624 struct mtd_info **floors)
1625{
1626 struct device *dev = &pdev->dev;
1627 int floor, i;
1628
1629 for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
1630 floor++)
1631 for (i = 0; i < 4; i++)
1632 device_remove_file(dev, &doc_sys_attrs[floor][i]);
1633}
783 1634
784/* 1635/*
785 * Debug sysfs entries 1636 * Debug sysfs entries
@@ -852,13 +1703,15 @@ static int dbg_protection_show(struct seq_file *s, void *p)
852{ 1703{
853 struct docg3 *docg3 = (struct docg3 *)s->private; 1704 struct docg3 *docg3 = (struct docg3 *)s->private;
854 int pos = 0; 1705 int pos = 0;
855 int protect = doc_register_readb(docg3, DOC_PROTECTION); 1706 int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high;
856 int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); 1707
857 int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW); 1708 protect = doc_register_readb(docg3, DOC_PROTECTION);
858 int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH); 1709 dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
859 int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); 1710 dps0_low = doc_register_readw(docg3, DOC_DPS0_ADDRLOW);
860 int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW); 1711 dps0_high = doc_register_readw(docg3, DOC_DPS0_ADDRHIGH);
861 int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH); 1712 dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
1713 dps1_low = doc_register_readw(docg3, DOC_DPS1_ADDRLOW);
1714 dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH);
862 1715
863 pos += seq_printf(s, "Protection = 0x%02x (", 1716 pos += seq_printf(s, "Protection = 0x%02x (",
864 protect); 1717 protect);
@@ -947,52 +1800,54 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
947 1800
948 cfg = doc_register_readb(docg3, DOC_CONFIGURATION); 1801 cfg = doc_register_readb(docg3, DOC_CONFIGURATION);
949 docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0); 1802 docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0);
1803 docg3->reliable = reliable_mode;
950 1804
951 switch (chip_id) { 1805 switch (chip_id) {
952 case DOC_CHIPID_G3: 1806 case DOC_CHIPID_G3:
953 mtd->name = "DiskOnChip G3"; 1807 mtd->name = kasprintf(GFP_KERNEL, "DiskOnChip G3 floor %d",
1808 docg3->device_id);
954 docg3->max_block = 2047; 1809 docg3->max_block = 2047;
955 break; 1810 break;
956 } 1811 }
957 mtd->type = MTD_NANDFLASH; 1812 mtd->type = MTD_NANDFLASH;
958 /* 1813 mtd->flags = MTD_CAP_NANDFLASH;
959 * Once write methods are added, the correct flags will be set.
960 * mtd->flags = MTD_CAP_NANDFLASH;
961 */
962 mtd->flags = MTD_CAP_ROM;
963 mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE; 1814 mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE;
1815 if (docg3->reliable == 2)
1816 mtd->size /= 2;
964 mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; 1817 mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
1818 if (docg3->reliable == 2)
1819 mtd->erasesize /= 2;
965 mtd->writesize = DOC_LAYOUT_PAGE_SIZE; 1820 mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
966 mtd->oobsize = DOC_LAYOUT_OOB_SIZE; 1821 mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
967 mtd->owner = THIS_MODULE; 1822 mtd->owner = THIS_MODULE;
968 mtd->erase = NULL; 1823 mtd->erase = doc_erase;
969 mtd->point = NULL;
970 mtd->unpoint = NULL;
971 mtd->read = doc_read; 1824 mtd->read = doc_read;
972 mtd->write = NULL; 1825 mtd->write = doc_write;
973 mtd->read_oob = doc_read_oob; 1826 mtd->read_oob = doc_read_oob;
974 mtd->write_oob = NULL; 1827 mtd->write_oob = doc_write_oob;
975 mtd->sync = NULL;
976 mtd->block_isbad = doc_block_isbad; 1828 mtd->block_isbad = doc_block_isbad;
1829 mtd->ecclayout = &docg3_oobinfo;
977} 1830}
978 1831
979/** 1832/**
980 * doc_probe - Probe the IO space for a DiskOnChip G3 chip 1833 * doc_probe_device - Check if a device is available
981 * @pdev: platform device 1834 * @base: the io space where the device is probed
1835 * @floor: the floor of the probed device
1836 * @dev: the device
982 * 1837 *
983 * Probes for a G3 chip at the specified IO space in the platform data 1838 * Checks whether a device at the specified IO range, and floor is available.
984 * ressources.
985 * 1839 *
986 * Returns 0 on success, -ENOMEM, -ENXIO on error 1840 * Returns a mtd_info struct if there is a device, ENODEV if none found, ENOMEM
1841 * if a memory allocation failed. If floor 0 is checked, a reset of the ASIC is
1842 * launched.
987 */ 1843 */
988static int __init docg3_probe(struct platform_device *pdev) 1844static struct mtd_info *doc_probe_device(void __iomem *base, int floor,
1845 struct device *dev)
989{ 1846{
990 struct device *dev = &pdev->dev;
991 struct docg3 *docg3;
992 struct mtd_info *mtd;
993 struct resource *ress;
994 int ret, bbt_nbpages; 1847 int ret, bbt_nbpages;
995 u16 chip_id, chip_id_inv; 1848 u16 chip_id, chip_id_inv;
1849 struct docg3 *docg3;
1850 struct mtd_info *mtd;
996 1851
997 ret = -ENOMEM; 1852 ret = -ENOMEM;
998 docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL); 1853 docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL);
@@ -1002,69 +1857,218 @@ static int __init docg3_probe(struct platform_device *pdev)
1002 if (!mtd) 1857 if (!mtd)
1003 goto nomem2; 1858 goto nomem2;
1004 mtd->priv = docg3; 1859 mtd->priv = docg3;
1860 bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
1861 8 * DOC_LAYOUT_PAGE_SIZE);
1862 docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
1863 if (!docg3->bbt)
1864 goto nomem3;
1005 1865
1006 ret = -ENXIO; 1866 docg3->dev = dev;
1007 ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1867 docg3->device_id = floor;
1008 if (!ress) { 1868 docg3->base = base;
1009 dev_err(dev, "No I/O memory resource defined\n");
1010 goto noress;
1011 }
1012 docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE);
1013
1014 docg3->dev = &pdev->dev;
1015 docg3->device_id = 0;
1016 doc_set_device_id(docg3, docg3->device_id); 1869 doc_set_device_id(docg3, docg3->device_id);
1017 doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); 1870 if (!floor)
1871 doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
1018 doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL); 1872 doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL);
1019 1873
1020 chip_id = doc_register_readw(docg3, DOC_CHIPID); 1874 chip_id = doc_register_readw(docg3, DOC_CHIPID);
1021 chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV); 1875 chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV);
1022 1876
1023 ret = -ENODEV; 1877 ret = 0;
1024 if (chip_id != (u16)(~chip_id_inv)) { 1878 if (chip_id != (u16)(~chip_id_inv)) {
1025 doc_info("No device found at IO addr %p\n", 1879 goto nomem3;
1026 (void *)ress->start);
1027 goto nochipfound;
1028 } 1880 }
1029 1881
1030 switch (chip_id) { 1882 switch (chip_id) {
1031 case DOC_CHIPID_G3: 1883 case DOC_CHIPID_G3:
1032 doc_info("Found a G3 DiskOnChip at addr %p\n", 1884 doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n",
1033 (void *)ress->start); 1885 base, floor);
1034 break; 1886 break;
1035 default: 1887 default:
1036 doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); 1888 doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
1037 goto nochipfound; 1889 goto nomem3;
1038 } 1890 }
1039 1891
1040 doc_set_driver_info(chip_id, mtd); 1892 doc_set_driver_info(chip_id, mtd);
1041 platform_set_drvdata(pdev, mtd);
1042 1893
1043 ret = -ENOMEM; 1894 doc_hamming_ecc_init(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ);
1044 bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
1045 8 * DOC_LAYOUT_PAGE_SIZE);
1046 docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
1047 if (!docg3->bbt)
1048 goto nochipfound;
1049 doc_reload_bbt(docg3); 1895 doc_reload_bbt(docg3);
1896 return mtd;
1050 1897
1051 ret = mtd_device_parse_register(mtd, part_probes, 1898nomem3:
1052 NULL, NULL, 0); 1899 kfree(mtd);
1053 if (ret) 1900nomem2:
1054 goto register_error; 1901 kfree(docg3);
1902nomem1:
1903 return ERR_PTR(ret);
1904}
1055 1905
1056 doc_dbg_register(docg3); 1906/**
1057 return 0; 1907 * doc_release_device - Release a docg3 floor
1908 * @mtd: the device
1909 */
1910static void doc_release_device(struct mtd_info *mtd)
1911{
1912 struct docg3 *docg3 = mtd->priv;
1058 1913
1059register_error: 1914 mtd_device_unregister(mtd);
1060 kfree(docg3->bbt); 1915 kfree(docg3->bbt);
1061nochipfound: 1916 kfree(docg3);
1062 iounmap(docg3->base); 1917 kfree(mtd->name);
1063noress:
1064 kfree(mtd); 1918 kfree(mtd);
1919}
1920
1921/**
1922 * docg3_resume - Awakens docg3 floor
1923 * @pdev: platfrom device
1924 *
1925 * Returns 0 (always successfull)
1926 */
1927static int docg3_resume(struct platform_device *pdev)
1928{
1929 int i;
1930 struct mtd_info **docg3_floors, *mtd;
1931 struct docg3 *docg3;
1932
1933 docg3_floors = platform_get_drvdata(pdev);
1934 mtd = docg3_floors[0];
1935 docg3 = mtd->priv;
1936
1937 doc_dbg("docg3_resume()\n");
1938 for (i = 0; i < 12; i++)
1939 doc_readb(docg3, DOC_IOSPACE_IPL);
1940 return 0;
1941}
1942
1943/**
1944 * docg3_suspend - Put in low power mode the docg3 floor
1945 * @pdev: platform device
1946 * @state: power state
1947 *
1948 * Shuts off most of docg3 circuitery to lower power consumption.
1949 *
1950 * Returns 0 if suspend succeeded, -EIO if chip refused suspend
1951 */
1952static int docg3_suspend(struct platform_device *pdev, pm_message_t state)
1953{
1954 int floor, i;
1955 struct mtd_info **docg3_floors, *mtd;
1956 struct docg3 *docg3;
1957 u8 ctrl, pwr_down;
1958
1959 docg3_floors = platform_get_drvdata(pdev);
1960 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
1961 mtd = docg3_floors[floor];
1962 if (!mtd)
1963 continue;
1964 docg3 = mtd->priv;
1965
1966 doc_writeb(docg3, floor, DOC_DEVICESELECT);
1967 ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
1968 ctrl &= ~DOC_CTRL_VIOLATION & ~DOC_CTRL_CE;
1969 doc_writeb(docg3, ctrl, DOC_FLASHCONTROL);
1970
1971 for (i = 0; i < 10; i++) {
1972 usleep_range(3000, 4000);
1973 pwr_down = doc_register_readb(docg3, DOC_POWERMODE);
1974 if (pwr_down & DOC_POWERDOWN_READY)
1975 break;
1976 }
1977 if (pwr_down & DOC_POWERDOWN_READY) {
1978 doc_dbg("docg3_suspend(): floor %d powerdown ok\n",
1979 floor);
1980 } else {
1981 doc_err("docg3_suspend(): floor %d powerdown failed\n",
1982 floor);
1983 return -EIO;
1984 }
1985 }
1986
1987 mtd = docg3_floors[0];
1988 docg3 = mtd->priv;
1989 doc_set_asic_mode(docg3, DOC_ASICMODE_POWERDOWN);
1990 return 0;
1991}
1992
1993/**
1994 * doc_probe - Probe the IO space for a DiskOnChip G3 chip
1995 * @pdev: platform device
1996 *
1997 * Probes for a G3 chip at the specified IO space in the platform data
1998 * ressources. The floor 0 must be available.
1999 *
2000 * Returns 0 on success, -ENOMEM, -ENXIO on error
2001 */
2002static int __init docg3_probe(struct platform_device *pdev)
2003{
2004 struct device *dev = &pdev->dev;
2005 struct mtd_info *mtd;
2006 struct resource *ress;
2007 void __iomem *base;
2008 int ret, floor, found = 0;
2009 struct mtd_info **docg3_floors;
2010
2011 ret = -ENXIO;
2012 ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2013 if (!ress) {
2014 dev_err(dev, "No I/O memory resource defined\n");
2015 goto noress;
2016 }
2017 base = ioremap(ress->start, DOC_IOSPACE_SIZE);
2018
2019 ret = -ENOMEM;
2020 docg3_floors = kzalloc(sizeof(*docg3_floors) * DOC_MAX_NBFLOORS,
2021 GFP_KERNEL);
2022 if (!docg3_floors)
2023 goto nomem1;
2024 docg3_bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T,
2025 DOC_ECC_BCH_PRIMPOLY);
2026 if (!docg3_bch)
2027 goto nomem2;
2028
2029 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
2030 mtd = doc_probe_device(base, floor, dev);
2031 if (IS_ERR(mtd)) {
2032 ret = PTR_ERR(mtd);
2033 goto err_probe;
2034 }
2035 if (!mtd) {
2036 if (floor == 0)
2037 goto notfound;
2038 else
2039 continue;
2040 }
2041 docg3_floors[floor] = mtd;
2042 ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL,
2043 0);
2044 if (ret)
2045 goto err_probe;
2046 found++;
2047 }
2048
2049 ret = doc_register_sysfs(pdev, docg3_floors);
2050 if (ret)
2051 goto err_probe;
2052 if (!found)
2053 goto notfound;
2054
2055 platform_set_drvdata(pdev, docg3_floors);
2056 doc_dbg_register(docg3_floors[0]->priv);
2057 return 0;
2058
2059notfound:
2060 ret = -ENODEV;
2061 dev_info(dev, "No supported DiskOnChip found\n");
2062err_probe:
2063 free_bch(docg3_bch);
2064 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
2065 if (docg3_floors[floor])
2066 doc_release_device(docg3_floors[floor]);
1065nomem2: 2067nomem2:
1066 kfree(docg3); 2068 kfree(docg3_floors);
1067nomem1: 2069nomem1:
2070 iounmap(base);
2071noress:
1068 return ret; 2072 return ret;
1069} 2073}
1070 2074
@@ -1076,15 +2080,20 @@ nomem1:
1076 */ 2080 */
1077static int __exit docg3_release(struct platform_device *pdev) 2081static int __exit docg3_release(struct platform_device *pdev)
1078{ 2082{
1079 struct mtd_info *mtd = platform_get_drvdata(pdev); 2083 struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
1080 struct docg3 *docg3 = mtd->priv; 2084 struct docg3 *docg3 = docg3_floors[0]->priv;
2085 void __iomem *base = docg3->base;
2086 int floor;
1081 2087
2088 doc_unregister_sysfs(pdev, docg3_floors);
1082 doc_dbg_unregister(docg3); 2089 doc_dbg_unregister(docg3);
1083 mtd_device_unregister(mtd); 2090 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
1084 iounmap(docg3->base); 2091 if (docg3_floors[floor])
1085 kfree(docg3->bbt); 2092 doc_release_device(docg3_floors[floor]);
1086 kfree(docg3); 2093
1087 kfree(mtd); 2094 kfree(docg3_floors);
2095 free_bch(docg3_bch);
2096 iounmap(base);
1088 return 0; 2097 return 0;
1089} 2098}
1090 2099
@@ -1093,6 +2102,8 @@ static struct platform_driver g3_driver = {
1093 .name = "docg3", 2102 .name = "docg3",
1094 .owner = THIS_MODULE, 2103 .owner = THIS_MODULE,
1095 }, 2104 },
2105 .suspend = docg3_suspend,
2106 .resume = docg3_resume,
1096 .remove = __exit_p(docg3_release), 2107 .remove = __exit_p(docg3_release),
1097}; 2108};
1098 2109
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
index 0d407be2459..db0da436b49 100644
--- a/drivers/mtd/devices/docg3.h
+++ b/drivers/mtd/devices/docg3.h
@@ -51,10 +51,19 @@
51#define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2) 51#define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2)
52#define DOC_LAYOUT_BLOCK_SIZE \ 52#define DOC_LAYOUT_BLOCK_SIZE \
53 (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE) 53 (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE)
54
55/*
56 * ECC related constants
57 */
58#define DOC_ECC_BCH_M 14
59#define DOC_ECC_BCH_T 4
60#define DOC_ECC_BCH_PRIMPOLY 0x4443
54#define DOC_ECC_BCH_SIZE 7 61#define DOC_ECC_BCH_SIZE 7
55#define DOC_ECC_BCH_COVERED_BYTES \ 62#define DOC_ECC_BCH_COVERED_BYTES \
56 (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \ 63 (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \
57 DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ) 64 DOC_LAYOUT_OOB_HAMMING_SZ)
65#define DOC_ECC_BCH_TOTAL_BYTES \
66 (DOC_ECC_BCH_COVERED_BYTES + DOC_LAYOUT_OOB_BCH_SZ)
58 67
59/* 68/*
60 * Blocks distribution 69 * Blocks distribution
@@ -80,6 +89,7 @@
80 89
81#define DOC_CHIPID_G3 0x200 90#define DOC_CHIPID_G3 0x200
82#define DOC_ERASE_MARK 0xaa 91#define DOC_ERASE_MARK 0xaa
92#define DOC_MAX_NBFLOORS 4
83/* 93/*
84 * Flash registers 94 * Flash registers
85 */ 95 */
@@ -105,9 +115,11 @@
105#define DOC_ECCCONF1 0x1042 115#define DOC_ECCCONF1 0x1042
106#define DOC_ECCPRESET 0x1044 116#define DOC_ECCPRESET 0x1044
107#define DOC_HAMMINGPARITY 0x1046 117#define DOC_HAMMINGPARITY 0x1046
108#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 1)) 118#define DOC_BCH_HW_ECC(idx) (0x1048 + idx)
109 119
110#define DOC_PROTECTION 0x1056 120#define DOC_PROTECTION 0x1056
121#define DOC_DPS0_KEY 0x105c
122#define DOC_DPS1_KEY 0x105e
111#define DOC_DPS0_ADDRLOW 0x1060 123#define DOC_DPS0_ADDRLOW 0x1060
112#define DOC_DPS0_ADDRHIGH 0x1062 124#define DOC_DPS0_ADDRHIGH 0x1062
113#define DOC_DPS1_ADDRLOW 0x1064 125#define DOC_DPS1_ADDRLOW 0x1064
@@ -117,6 +129,7 @@
117 129
118#define DOC_ASICMODECONFIRM 0x1072 130#define DOC_ASICMODECONFIRM 0x1072
119#define DOC_CHIPID_INV 0x1074 131#define DOC_CHIPID_INV 0x1074
132#define DOC_POWERMODE 0x107c
120 133
121/* 134/*
122 * Flash sequences 135 * Flash sequences
@@ -124,11 +137,14 @@
124 */ 137 */
125#define DOC_SEQ_RESET 0x00 138#define DOC_SEQ_RESET 0x00
126#define DOC_SEQ_PAGE_SIZE_532 0x03 139#define DOC_SEQ_PAGE_SIZE_532 0x03
127#define DOC_SEQ_SET_MODE 0x09 140#define DOC_SEQ_SET_FASTMODE 0x05
141#define DOC_SEQ_SET_RELIABLEMODE 0x09
128#define DOC_SEQ_READ 0x12 142#define DOC_SEQ_READ 0x12
129#define DOC_SEQ_SET_PLANE1 0x0e 143#define DOC_SEQ_SET_PLANE1 0x0e
130#define DOC_SEQ_SET_PLANE2 0x10 144#define DOC_SEQ_SET_PLANE2 0x10
131#define DOC_SEQ_PAGE_SETUP 0x1d 145#define DOC_SEQ_PAGE_SETUP 0x1d
146#define DOC_SEQ_ERASE 0x27
147#define DOC_SEQ_PLANES_STATUS 0x31
132 148
133/* 149/*
134 * Flash commands 150 * Flash commands
@@ -143,7 +159,10 @@
143#define DOC_CMD_PROG_BLOCK_ADDR 0x60 159#define DOC_CMD_PROG_BLOCK_ADDR 0x60
144#define DOC_CMD_PROG_CYCLE1 0x80 160#define DOC_CMD_PROG_CYCLE1 0x80
145#define DOC_CMD_PROG_CYCLE2 0x10 161#define DOC_CMD_PROG_CYCLE2 0x10
162#define DOC_CMD_PROG_CYCLE3 0x11
146#define DOC_CMD_ERASECYCLE2 0xd0 163#define DOC_CMD_ERASECYCLE2 0xd0
164#define DOC_CMD_READ_STATUS 0x70
165#define DOC_CMD_PLANES_STATUS 0x71
147 166
148#define DOC_CMD_RELIABLE_MODE 0x22 167#define DOC_CMD_RELIABLE_MODE 0x22
149#define DOC_CMD_FAST_MODE 0xa2 168#define DOC_CMD_FAST_MODE 0xa2
@@ -174,6 +193,7 @@
174/* 193/*
175 * Flash register : DOC_ECCCONF0 194 * Flash register : DOC_ECCCONF0
176 */ 195 */
196#define DOC_ECCCONF0_WRITE_MODE 0x0000
177#define DOC_ECCCONF0_READ_MODE 0x8000 197#define DOC_ECCCONF0_READ_MODE 0x8000
178#define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000 198#define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000
179#define DOC_ECCCONF0_HAMMING_ENABLE 0x1000 199#define DOC_ECCCONF0_HAMMING_ENABLE 0x1000
@@ -185,7 +205,7 @@
185 */ 205 */
186#define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80 206#define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80
187#define DOC_ECCCONF1_UNKOWN1 0x40 207#define DOC_ECCCONF1_UNKOWN1 0x40
188#define DOC_ECCCONF1_UNKOWN2 0x20 208#define DOC_ECCCONF1_PAGE_IS_WRITTEN 0x20
189#define DOC_ECCCONF1_UNKOWN3 0x10 209#define DOC_ECCCONF1_UNKOWN3 0x10
190#define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f 210#define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f
191 211
@@ -223,13 +243,46 @@
223#define DOC_READADDR_ONE_BYTE 0x4000 243#define DOC_READADDR_ONE_BYTE 0x4000
224#define DOC_READADDR_ADDR_MASK 0x1fff 244#define DOC_READADDR_ADDR_MASK 0x1fff
225 245
246/*
247 * Flash register : DOC_POWERMODE
248 */
249#define DOC_POWERDOWN_READY 0x80
250
251/*
252 * Status of erase and write operation
253 */
254#define DOC_PLANES_STATUS_FAIL 0x01
255#define DOC_PLANES_STATUS_PLANE0_KO 0x02
256#define DOC_PLANES_STATUS_PLANE1_KO 0x04
257
258/*
259 * DPS key management
260 *
261 * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
262 * across block boundaries, and define whether these blocks can be read or
263 * written.
264 * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
265 * page 0 of blocks (4,5) for DPS1.
266 */
267#define DOC_LAYOUT_DPS_KEY_LENGTH 8
268
226/** 269/**
227 * struct docg3 - DiskOnChip driver private data 270 * struct docg3 - DiskOnChip driver private data
228 * @dev: the device currently under control 271 * @dev: the device currently under control
229 * @base: mapped IO space 272 * @base: mapped IO space
230 * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3) 273 * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
231 * @if_cfg: if true, reads are on 16bits, else reads are on 8bits 274 * @if_cfg: if true, reads are on 16bits, else reads are on 8bits
275
276 * @reliable: if 0, docg3 in normal mode, if 1 docg3 in fast mode, if 2 in
277 * reliable mode
278 * Fast mode implies more errors than normal mode.
279 * Reliable mode implies that page 2*n and 2*n+1 are clones.
232 * @bbt: bad block table cache 280 * @bbt: bad block table cache
281 * @oob_write_ofs: offset of the MTD where this OOB should belong (ie. in next
282 * page_write)
283 * @oob_autoecc: if 1, use only bytes 0-7, 15, and fill the others with HW ECC
284 * if 0, use all the 16 bytes.
285 * @oob_write_buf: prepared OOB for next page_write
233 * @debugfs_root: debugfs root node 286 * @debugfs_root: debugfs root node
234 */ 287 */
235struct docg3 { 288struct docg3 {
@@ -237,8 +290,12 @@ struct docg3 {
237 void __iomem *base; 290 void __iomem *base;
238 unsigned int device_id:4; 291 unsigned int device_id:4;
239 unsigned int if_cfg:1; 292 unsigned int if_cfg:1;
293 unsigned int reliable:2;
240 int max_block; 294 int max_block;
241 u8 *bbt; 295 u8 *bbt;
296 loff_t oob_write_ofs;
297 int oob_autoecc;
298 u8 oob_write_buf[DOC_LAYOUT_OOB_SIZE];
242 struct dentry *debugfs_root; 299 struct dentry *debugfs_root;
243}; 300};
244 301
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 45116bb3029..706b847b46b 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -241,8 +241,7 @@ static void __init DoC_Probe(unsigned long physadr)
241 return; 241 return;
242 } 242 }
243 docfound = 1; 243 docfound = 1;
244 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); 244 mtd = kzalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
245
246 if (!mtd) { 245 if (!mtd) {
247 printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n"); 246 printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n");
248 iounmap(docptr); 247 iounmap(docptr);
@@ -250,10 +249,6 @@ static void __init DoC_Probe(unsigned long physadr)
250 } 249 }
251 250
252 this = (struct DiskOnChip *)(&mtd[1]); 251 this = (struct DiskOnChip *)(&mtd[1]);
253
254 memset((char *)mtd,0, sizeof(struct mtd_info));
255 memset((char *)this, 0, sizeof(struct DiskOnChip));
256
257 mtd->priv = this; 252 mtd->priv = this;
258 this->virtadr = docptr; 253 this->virtadr = docptr;
259 this->physadr = physadr; 254 this->physadr = physadr;
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 884904d3f9d..7c60dddbefc 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -992,7 +992,6 @@ static int __devexit m25p_remove(struct spi_device *spi)
992static struct spi_driver m25p80_driver = { 992static struct spi_driver m25p80_driver = {
993 .driver = { 993 .driver = {
994 .name = "m25p80", 994 .name = "m25p80",
995 .bus = &spi_bus_type,
996 .owner = THIS_MODULE, 995 .owner = THIS_MODULE,
997 }, 996 },
998 .id_table = m25p_ids, 997 .id_table = m25p_ids,
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index d75c7af18a6..236057ead0d 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -936,7 +936,6 @@ static int __devexit dataflash_remove(struct spi_device *spi)
936static struct spi_driver dataflash_driver = { 936static struct spi_driver dataflash_driver = {
937 .driver = { 937 .driver = {
938 .name = "mtd_dataflash", 938 .name = "mtd_dataflash",
939 .bus = &spi_bus_type,
940 .owner = THIS_MODULE, 939 .owner = THIS_MODULE,
941 .of_match_table = dataflash_dt_ids, 940 .of_match_table = dataflash_dt_ids,
942 }, 941 },
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index d38ef3bffe8..5fc198350b9 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -378,7 +378,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
378 struct flash_info *flash_info; 378 struct flash_info *flash_info;
379 struct sst25l_flash *flash; 379 struct sst25l_flash *flash;
380 struct flash_platform_data *data; 380 struct flash_platform_data *data;
381 int ret, i; 381 int ret;
382 382
383 flash_info = sst25l_match_device(spi); 383 flash_info = sst25l_match_device(spi);
384 if (!flash_info) 384 if (!flash_info)
@@ -444,7 +444,6 @@ static int __devexit sst25l_remove(struct spi_device *spi)
444static struct spi_driver sst25l_driver = { 444static struct spi_driver sst25l_driver = {
445 .driver = { 445 .driver = {
446 .name = "sst25l", 446 .name = "sst25l",
447 .bus = &spi_bus_type,
448 .owner = THIS_MODULE, 447 .owner = THIS_MODULE,
449 }, 448 },
450 .probe = sst25l_probe, 449 .probe = sst25l_probe,
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index c7382bb686c..19d637266fc 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -168,8 +168,8 @@ static int scan_header(partition_t *part)
168 (offset + sizeof(header)) < max_offset; 168 (offset + sizeof(header)) < max_offset;
169 offset += part->mbd.mtd->erasesize ? : 0x2000) { 169 offset += part->mbd.mtd->erasesize ? : 0x2000) {
170 170
171 err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, 171 err = mtd_read(part->mbd.mtd, offset, sizeof(header), &ret,
172 (unsigned char *)&header); 172 (unsigned char *)&header);
173 173
174 if (err) 174 if (err)
175 return err; 175 return err;
@@ -224,8 +224,8 @@ static int build_maps(partition_t *part)
224 for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) { 224 for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {
225 offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN)) 225 offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))
226 << part->header.EraseUnitSize); 226 << part->header.EraseUnitSize);
227 ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, 227 ret = mtd_read(part->mbd.mtd, offset, sizeof(header), &retval,
228 (unsigned char *)&header); 228 (unsigned char *)&header);
229 229
230 if (ret) 230 if (ret)
231 goto out_XferInfo; 231 goto out_XferInfo;
@@ -289,9 +289,9 @@ static int build_maps(partition_t *part)
289 part->EUNInfo[i].Deleted = 0; 289 part->EUNInfo[i].Deleted = 0;
290 offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset); 290 offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
291 291
292 ret = part->mbd.mtd->read(part->mbd.mtd, offset, 292 ret = mtd_read(part->mbd.mtd, offset,
293 part->BlocksPerUnit * sizeof(uint32_t), &retval, 293 part->BlocksPerUnit * sizeof(uint32_t), &retval,
294 (unsigned char *)part->bam_cache); 294 (unsigned char *)part->bam_cache);
295 295
296 if (ret) 296 if (ret)
297 goto out_bam_cache; 297 goto out_bam_cache;
@@ -355,7 +355,7 @@ static int erase_xfer(partition_t *part,
355 erase->len = 1 << part->header.EraseUnitSize; 355 erase->len = 1 << part->header.EraseUnitSize;
356 erase->priv = (u_long)part; 356 erase->priv = (u_long)part;
357 357
358 ret = part->mbd.mtd->erase(part->mbd.mtd, erase); 358 ret = mtd_erase(part->mbd.mtd, erase);
359 359
360 if (!ret) 360 if (!ret)
361 xfer->EraseCount++; 361 xfer->EraseCount++;
@@ -422,8 +422,8 @@ static int prepare_xfer(partition_t *part, int i)
422 header.LogicalEUN = cpu_to_le16(0xffff); 422 header.LogicalEUN = cpu_to_le16(0xffff);
423 header.EraseCount = cpu_to_le32(xfer->EraseCount); 423 header.EraseCount = cpu_to_le32(xfer->EraseCount);
424 424
425 ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset, sizeof(header), 425 ret = mtd_write(part->mbd.mtd, xfer->Offset, sizeof(header), &retlen,
426 &retlen, (u_char *)&header); 426 (u_char *)&header);
427 427
428 if (ret) { 428 if (ret) {
429 return ret; 429 return ret;
@@ -438,8 +438,8 @@ static int prepare_xfer(partition_t *part, int i)
438 438
439 for (i = 0; i < nbam; i++, offset += sizeof(uint32_t)) { 439 for (i = 0; i < nbam; i++, offset += sizeof(uint32_t)) {
440 440
441 ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t), 441 ret = mtd_write(part->mbd.mtd, offset, sizeof(uint32_t), &retlen,
442 &retlen, (u_char *)&ctl); 442 (u_char *)&ctl);
443 443
444 if (ret) 444 if (ret)
445 return ret; 445 return ret;
@@ -485,9 +485,9 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
485 485
486 offset = eun->Offset + le32_to_cpu(part->header.BAMOffset); 486 offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
487 487
488 ret = part->mbd.mtd->read(part->mbd.mtd, offset, 488 ret = mtd_read(part->mbd.mtd, offset,
489 part->BlocksPerUnit * sizeof(uint32_t), 489 part->BlocksPerUnit * sizeof(uint32_t), &retlen,
490 &retlen, (u_char *) (part->bam_cache)); 490 (u_char *)(part->bam_cache));
491 491
492 /* mark the cache bad, in case we get an error later */ 492 /* mark the cache bad, in case we get an error later */
493 part->bam_index = 0xffff; 493 part->bam_index = 0xffff;
@@ -503,8 +503,8 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
503 offset = xfer->Offset + 20; /* Bad! */ 503 offset = xfer->Offset + 20; /* Bad! */
504 unit = cpu_to_le16(0x7fff); 504 unit = cpu_to_le16(0x7fff);
505 505
506 ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint16_t), 506 ret = mtd_write(part->mbd.mtd, offset, sizeof(uint16_t), &retlen,
507 &retlen, (u_char *) &unit); 507 (u_char *)&unit);
508 508
509 if (ret) { 509 if (ret) {
510 printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n"); 510 printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");
@@ -523,16 +523,16 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
523 break; 523 break;
524 case BLOCK_DATA: 524 case BLOCK_DATA:
525 case BLOCK_REPLACEMENT: 525 case BLOCK_REPLACEMENT:
526 ret = part->mbd.mtd->read(part->mbd.mtd, src, SECTOR_SIZE, 526 ret = mtd_read(part->mbd.mtd, src, SECTOR_SIZE, &retlen,
527 &retlen, (u_char *) buf); 527 (u_char *)buf);
528 if (ret) { 528 if (ret) {
529 printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n"); 529 printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n");
530 return ret; 530 return ret;
531 } 531 }
532 532
533 533
534 ret = part->mbd.mtd->write(part->mbd.mtd, dest, SECTOR_SIZE, 534 ret = mtd_write(part->mbd.mtd, dest, SECTOR_SIZE, &retlen,
535 &retlen, (u_char *) buf); 535 (u_char *)buf);
536 if (ret) { 536 if (ret) {
537 printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n"); 537 printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n");
538 return ret; 538 return ret;
@@ -550,9 +550,11 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
550 } 550 }
551 551
552 /* Write the BAM to the transfer unit */ 552 /* Write the BAM to the transfer unit */
553 ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), 553 ret = mtd_write(part->mbd.mtd,
554 part->BlocksPerUnit * sizeof(int32_t), &retlen, 554 xfer->Offset + le32_to_cpu(part->header.BAMOffset),
555 (u_char *)part->bam_cache); 555 part->BlocksPerUnit * sizeof(int32_t),
556 &retlen,
557 (u_char *)part->bam_cache);
556 if (ret) { 558 if (ret) {
557 printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n"); 559 printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");
558 return ret; 560 return ret;
@@ -560,8 +562,8 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
560 562
561 563
562 /* All clear? Then update the LogicalEUN again */ 564 /* All clear? Then update the LogicalEUN again */
563 ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(uint16_t), 565 ret = mtd_write(part->mbd.mtd, xfer->Offset + 20, sizeof(uint16_t),
564 &retlen, (u_char *)&srcunitswap); 566 &retlen, (u_char *)&srcunitswap);
565 567
566 if (ret) { 568 if (ret) {
567 printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n"); 569 printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");
@@ -648,8 +650,7 @@ static int reclaim_block(partition_t *part)
648 if (queued) { 650 if (queued) {
649 pr_debug("ftl_cs: waiting for transfer " 651 pr_debug("ftl_cs: waiting for transfer "
650 "unit to be prepared...\n"); 652 "unit to be prepared...\n");
651 if (part->mbd.mtd->sync) 653 mtd_sync(part->mbd.mtd);
652 part->mbd.mtd->sync(part->mbd.mtd);
653 } else { 654 } else {
654 static int ne = 0; 655 static int ne = 0;
655 if (++ne < 5) 656 if (++ne < 5)
@@ -747,10 +748,11 @@ static uint32_t find_free(partition_t *part)
747 /* Invalidate cache */ 748 /* Invalidate cache */
748 part->bam_index = 0xffff; 749 part->bam_index = 0xffff;
749 750
750 ret = part->mbd.mtd->read(part->mbd.mtd, 751 ret = mtd_read(part->mbd.mtd,
751 part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset), 752 part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
752 part->BlocksPerUnit * sizeof(uint32_t), 753 part->BlocksPerUnit * sizeof(uint32_t),
753 &retlen, (u_char *) (part->bam_cache)); 754 &retlen,
755 (u_char *)(part->bam_cache));
754 756
755 if (ret) { 757 if (ret) {
756 printk(KERN_WARNING"ftl: Error reading BAM in find_free\n"); 758 printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");
@@ -810,8 +812,8 @@ static int ftl_read(partition_t *part, caddr_t buffer,
810 else { 812 else {
811 offset = (part->EUNInfo[log_addr / bsize].Offset 813 offset = (part->EUNInfo[log_addr / bsize].Offset
812 + (log_addr % bsize)); 814 + (log_addr % bsize));
813 ret = part->mbd.mtd->read(part->mbd.mtd, offset, SECTOR_SIZE, 815 ret = mtd_read(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,
814 &retlen, (u_char *) buffer); 816 (u_char *)buffer);
815 817
816 if (ret) { 818 if (ret) {
817 printk(KERN_WARNING "Error reading MTD device in ftl_read()\n"); 819 printk(KERN_WARNING "Error reading MTD device in ftl_read()\n");
@@ -849,8 +851,8 @@ static int set_bam_entry(partition_t *part, uint32_t log_addr,
849 le32_to_cpu(part->header.BAMOffset)); 851 le32_to_cpu(part->header.BAMOffset));
850 852
851#ifdef PSYCHO_DEBUG 853#ifdef PSYCHO_DEBUG
852 ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(uint32_t), 854 ret = mtd_read(part->mbd.mtd, offset, sizeof(uint32_t), &retlen,
853 &retlen, (u_char *)&old_addr); 855 (u_char *)&old_addr);
854 if (ret) { 856 if (ret) {
855 printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret); 857 printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret);
856 return ret; 858 return ret;
@@ -886,8 +888,8 @@ static int set_bam_entry(partition_t *part, uint32_t log_addr,
886#endif 888#endif
887 part->bam_cache[blk] = le_virt_addr; 889 part->bam_cache[blk] = le_virt_addr;
888 } 890 }
889 ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t), 891 ret = mtd_write(part->mbd.mtd, offset, sizeof(uint32_t), &retlen,
890 &retlen, (u_char *)&le_virt_addr); 892 (u_char *)&le_virt_addr);
891 893
892 if (ret) { 894 if (ret) {
893 printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n"); 895 printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n");
@@ -946,8 +948,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
946 part->EUNInfo[part->bam_index].Deleted++; 948 part->EUNInfo[part->bam_index].Deleted++;
947 offset = (part->EUNInfo[part->bam_index].Offset + 949 offset = (part->EUNInfo[part->bam_index].Offset +
948 blk * SECTOR_SIZE); 950 blk * SECTOR_SIZE);
949 ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, 951 ret = mtd_write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, buffer);
950 buffer);
951 952
952 if (ret) { 953 if (ret) {
953 printk(KERN_NOTICE "ftl_cs: block write failed!\n"); 954 printk(KERN_NOTICE "ftl_cs: block write failed!\n");
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index dd034efd187..28646c95cfb 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -158,7 +158,7 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
158 ops.oobbuf = buf; 158 ops.oobbuf = buf;
159 ops.datbuf = NULL; 159 ops.datbuf = NULL;
160 160
161 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 161 res = mtd_read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
162 *retlen = ops.oobretlen; 162 *retlen = ops.oobretlen;
163 return res; 163 return res;
164} 164}
@@ -178,7 +178,7 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
178 ops.oobbuf = buf; 178 ops.oobbuf = buf;
179 ops.datbuf = NULL; 179 ops.datbuf = NULL;
180 180
181 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 181 res = mtd_write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
182 *retlen = ops.oobretlen; 182 *retlen = ops.oobretlen;
183 return res; 183 return res;
184} 184}
@@ -199,7 +199,7 @@ static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
199 ops.datbuf = buf; 199 ops.datbuf = buf;
200 ops.len = len; 200 ops.len = len;
201 201
202 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 202 res = mtd_write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
203 *retlen = ops.retlen; 203 *retlen = ops.retlen;
204 return res; 204 return res;
205} 205}
@@ -343,14 +343,17 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
343 if (BlockMap[block] == BLOCK_NIL) 343 if (BlockMap[block] == BLOCK_NIL)
344 continue; 344 continue;
345 345
346 ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) + 346 ret = mtd_read(mtd,
347 (block * SECTORSIZE), SECTORSIZE, &retlen, 347 (inftl->EraseSize * BlockMap[block]) + (block * SECTORSIZE),
348 movebuf); 348 SECTORSIZE,
349 &retlen,
350 movebuf);
349 if (ret < 0 && !mtd_is_bitflip(ret)) { 351 if (ret < 0 && !mtd_is_bitflip(ret)) {
350 ret = mtd->read(mtd, 352 ret = mtd_read(mtd,
351 (inftl->EraseSize * BlockMap[block]) + 353 (inftl->EraseSize * BlockMap[block]) + (block * SECTORSIZE),
352 (block * SECTORSIZE), SECTORSIZE, 354 SECTORSIZE,
353 &retlen, movebuf); 355 &retlen,
356 movebuf);
354 if (ret != -EIO) 357 if (ret != -EIO)
355 pr_debug("INFTL: error went away on retry?\n"); 358 pr_debug("INFTL: error went away on retry?\n");
356 } 359 }
@@ -914,7 +917,7 @@ foundit:
914 } else { 917 } else {
915 size_t retlen; 918 size_t retlen;
916 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; 919 loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
917 int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer); 920 int ret = mtd_read(mtd, ptr, SECTORSIZE, &retlen, buffer);
918 921
919 /* Handle corrected bit flips gracefully */ 922 /* Handle corrected bit flips gracefully */
920 if (ret < 0 && !mtd_is_bitflip(ret)) 923 if (ret < 0 && !mtd_is_bitflip(ret))
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 2ff601f816c..4adc0374fb6 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -73,8 +73,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
73 * Check for BNAND header first. Then whinge if it's found 73 * Check for BNAND header first. Then whinge if it's found
74 * but later checks fail. 74 * but later checks fail.
75 */ 75 */
76 ret = mtd->read(mtd, block * inftl->EraseSize, 76 ret = mtd_read(mtd, block * inftl->EraseSize, SECTORSIZE,
77 SECTORSIZE, &retlen, buf); 77 &retlen, buf);
78 /* We ignore ret in case the ECC of the MediaHeader is invalid 78 /* We ignore ret in case the ECC of the MediaHeader is invalid
79 (which is apparently acceptable) */ 79 (which is apparently acceptable) */
80 if (retlen != SECTORSIZE) { 80 if (retlen != SECTORSIZE) {
@@ -118,8 +118,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
118 memcpy(mh, buf, sizeof(struct INFTLMediaHeader)); 118 memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
119 119
120 /* Read the spare media header at offset 4096 */ 120 /* Read the spare media header at offset 4096 */
121 mtd->read(mtd, block * inftl->EraseSize + 4096, 121 mtd_read(mtd, block * inftl->EraseSize + 4096, SECTORSIZE,
122 SECTORSIZE, &retlen, buf); 122 &retlen, buf);
123 if (retlen != SECTORSIZE) { 123 if (retlen != SECTORSIZE) {
124 printk(KERN_WARNING "INFTL: Unable to read spare " 124 printk(KERN_WARNING "INFTL: Unable to read spare "
125 "Media Header\n"); 125 "Media Header\n");
@@ -220,7 +220,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
220 */ 220 */
221 instr->addr = ip->Reserved0 * inftl->EraseSize; 221 instr->addr = ip->Reserved0 * inftl->EraseSize;
222 instr->len = inftl->EraseSize; 222 instr->len = inftl->EraseSize;
223 mtd->erase(mtd, instr); 223 mtd_erase(mtd, instr);
224 } 224 }
225 if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) { 225 if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
226 printk(KERN_WARNING "INFTL: Media Header " 226 printk(KERN_WARNING "INFTL: Media Header "
@@ -306,7 +306,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
306 /* If any of the physical eraseblocks are bad, don't 306 /* If any of the physical eraseblocks are bad, don't
307 use the unit. */ 307 use the unit. */
308 for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) { 308 for (physblock = 0; physblock < inftl->EraseSize; physblock += inftl->mbd.mtd->erasesize) {
309 if (inftl->mbd.mtd->block_isbad(inftl->mbd.mtd, i * inftl->EraseSize + physblock)) 309 if (mtd_block_isbad(inftl->mbd.mtd,
310 i * inftl->EraseSize + physblock))
310 inftl->PUtable[i] = BLOCK_RESERVED; 311 inftl->PUtable[i] = BLOCK_RESERVED;
311 } 312 }
312 } 313 }
@@ -342,7 +343,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
342 int i; 343 int i;
343 344
344 for (i = 0; i < len; i += SECTORSIZE) { 345 for (i = 0; i < len; i += SECTORSIZE) {
345 if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf)) 346 if (mtd_read(mtd, address, SECTORSIZE, &retlen, buf))
346 return -1; 347 return -1;
347 if (memcmpb(buf, 0xff, SECTORSIZE) != 0) 348 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
348 return -1; 349 return -1;
@@ -393,7 +394,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
393 mark only the failed block in the bbt. */ 394 mark only the failed block in the bbt. */
394 for (physblock = 0; physblock < inftl->EraseSize; 395 for (physblock = 0; physblock < inftl->EraseSize;
395 physblock += instr->len, instr->addr += instr->len) { 396 physblock += instr->len, instr->addr += instr->len) {
396 mtd->erase(inftl->mbd.mtd, instr); 397 mtd_erase(inftl->mbd.mtd, instr);
397 398
398 if (instr->state == MTD_ERASE_FAILED) { 399 if (instr->state == MTD_ERASE_FAILED) {
399 printk(KERN_WARNING "INFTL: error while formatting block %d\n", 400 printk(KERN_WARNING "INFTL: error while formatting block %d\n",
@@ -423,7 +424,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
423fail: 424fail:
424 /* could not format, update the bad block table (caller is responsible 425 /* could not format, update the bad block table (caller is responsible
425 for setting the PUtable to BLOCK_RESERVED on failure) */ 426 for setting the PUtable to BLOCK_RESERVED on failure) */
426 inftl->mbd.mtd->block_markbad(inftl->mbd.mtd, instr->addr); 427 mtd_block_markbad(inftl->mbd.mtd, instr->addr);
427 return -1; 428 return -1;
428} 429}
429 430
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index 1dca31d9a8b..536bbceaeaa 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -70,19 +70,12 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
70 mtd->erase = lpddr_erase; 70 mtd->erase = lpddr_erase;
71 mtd->write = lpddr_write_buffers; 71 mtd->write = lpddr_write_buffers;
72 mtd->writev = lpddr_writev; 72 mtd->writev = lpddr_writev;
73 mtd->read_oob = NULL;
74 mtd->write_oob = NULL;
75 mtd->sync = NULL;
76 mtd->lock = lpddr_lock; 73 mtd->lock = lpddr_lock;
77 mtd->unlock = lpddr_unlock; 74 mtd->unlock = lpddr_unlock;
78 mtd->suspend = NULL;
79 mtd->resume = NULL;
80 if (map_is_linear(map)) { 75 if (map_is_linear(map)) {
81 mtd->point = lpddr_point; 76 mtd->point = lpddr_point;
82 mtd->unpoint = lpddr_unpoint; 77 mtd->unpoint = lpddr_unpoint;
83 } 78 }
84 mtd->block_isbad = NULL;
85 mtd->block_markbad = NULL;
86 mtd->size = 1 << lpddr->qinfo->DevSizeShift; 79 mtd->size = 1 << lpddr->qinfo->DevSizeShift;
87 mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift; 80 mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift;
88 mtd->writesize = 1 << lpddr->qinfo->BufSizeShift; 81 mtd->writesize = 1 << lpddr->qinfo->BufSizeShift;
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 8e0c4bf9f7f..6c5c431c64a 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -242,15 +242,6 @@ config MTD_NETtel
242 help 242 help
243 Support for flash chips on NETtel/SecureEdge/SnapGear boards. 243 Support for flash chips on NETtel/SecureEdge/SnapGear boards.
244 244
245config MTD_BCM963XX
246 tristate "Map driver for Broadcom BCM963xx boards"
247 depends on BCM63XX
248 select MTD_MAP_BANK_WIDTH_2
249 select MTD_CFI_I1
250 help
251 Support for parsing CFE image tag and creating MTD partitions on
252 Broadcom BCM63xx boards.
253
254config MTD_LANTIQ 245config MTD_LANTIQ
255 tristate "Lantiq SoC NOR support" 246 tristate "Lantiq SoC NOR support"
256 depends on LANTIQ 247 depends on LANTIQ
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 45dcb8b14f2..68a9a91d344 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -55,6 +55,5 @@ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o
55obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o 55obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
56obj-$(CONFIG_MTD_VMU) += vmu-flash.o 56obj-$(CONFIG_MTD_VMU) += vmu-flash.o
57obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o 57obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
58obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o
59obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o 58obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o
60obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o 59obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c
deleted file mode 100644
index 736ca10ca9f..00000000000
--- a/drivers/mtd/maps/bcm963xx-flash.c
+++ /dev/null
@@ -1,277 +0,0 @@
1/*
2 * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org>
3 * Mike Albon <malbon@openwrt.org>
4 * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/module.h>
25#include <linux/mtd/map.h>
26#include <linux/mtd/mtd.h>
27#include <linux/mtd/partitions.h>
28#include <linux/vmalloc.h>
29#include <linux/platform_device.h>
30#include <linux/io.h>
31
32#include <asm/mach-bcm63xx/bcm963xx_tag.h>
33
34#define BCM63XX_BUSWIDTH 2 /* Buswidth */
35#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
36
37#define PFX KBUILD_MODNAME ": "
38
39static struct mtd_partition *parsed_parts;
40
41static struct mtd_info *bcm963xx_mtd_info;
42
43static struct map_info bcm963xx_map = {
44 .name = "bcm963xx",
45 .bankwidth = BCM63XX_BUSWIDTH,
46};
47
48static int parse_cfe_partitions(struct mtd_info *master,
49 struct mtd_partition **pparts)
50{
51 /* CFE, NVRAM and global Linux are always present */
52 int nrparts = 3, curpart = 0;
53 struct bcm_tag *buf;
54 struct mtd_partition *parts;
55 int ret;
56 size_t retlen;
57 unsigned int rootfsaddr, kerneladdr, spareaddr;
58 unsigned int rootfslen, kernellen, sparelen, totallen;
59 int namelen = 0;
60 int i;
61 char *boardid;
62 char *tagversion;
63
64 /* Allocate memory for buffer */
65 buf = vmalloc(sizeof(struct bcm_tag));
66 if (!buf)
67 return -ENOMEM;
68
69 /* Get the tag */
70 ret = master->read(master, master->erasesize, sizeof(struct bcm_tag),
71 &retlen, (void *)buf);
72 if (retlen != sizeof(struct bcm_tag)) {
73 vfree(buf);
74 return -EIO;
75 }
76
77 sscanf(buf->kernel_address, "%u", &kerneladdr);
78 sscanf(buf->kernel_length, "%u", &kernellen);
79 sscanf(buf->total_length, "%u", &totallen);
80 tagversion = &(buf->tag_version[0]);
81 boardid = &(buf->board_id[0]);
82
83 printk(KERN_INFO PFX "CFE boot tag found with version %s "
84 "and board type %s\n", tagversion, boardid);
85
86 kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
87 rootfsaddr = kerneladdr + kernellen;
88 spareaddr = roundup(totallen, master->erasesize) + master->erasesize;
89 sparelen = master->size - spareaddr - master->erasesize;
90 rootfslen = spareaddr - rootfsaddr;
91
92 /* Determine number of partitions */
93 namelen = 8;
94 if (rootfslen > 0) {
95 nrparts++;
96 namelen += 6;
97 };
98 if (kernellen > 0) {
99 nrparts++;
100 namelen += 6;
101 };
102
103 /* Ask kernel for more memory */
104 parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
105 if (!parts) {
106 vfree(buf);
107 return -ENOMEM;
108 };
109
110 /* Start building partition list */
111 parts[curpart].name = "CFE";
112 parts[curpart].offset = 0;
113 parts[curpart].size = master->erasesize;
114 curpart++;
115
116 if (kernellen > 0) {
117 parts[curpart].name = "kernel";
118 parts[curpart].offset = kerneladdr;
119 parts[curpart].size = kernellen;
120 curpart++;
121 };
122
123 if (rootfslen > 0) {
124 parts[curpart].name = "rootfs";
125 parts[curpart].offset = rootfsaddr;
126 parts[curpart].size = rootfslen;
127 if (sparelen > 0)
128 parts[curpart].size += sparelen;
129 curpart++;
130 };
131
132 parts[curpart].name = "nvram";
133 parts[curpart].offset = master->size - master->erasesize;
134 parts[curpart].size = master->erasesize;
135
136 /* Global partition "linux" to make easy firmware upgrade */
137 curpart++;
138 parts[curpart].name = "linux";
139 parts[curpart].offset = parts[0].size;
140 parts[curpart].size = master->size - parts[0].size - parts[3].size;
141
142 for (i = 0; i < nrparts; i++)
143 printk(KERN_INFO PFX "Partition %d is %s offset %lx and "
144 "length %lx\n", i, parts[i].name,
145 (long unsigned int)(parts[i].offset),
146 (long unsigned int)(parts[i].size));
147
148 printk(KERN_INFO PFX "Spare partition is %x offset and length %x\n",
149 spareaddr, sparelen);
150 *pparts = parts;
151 vfree(buf);
152
153 return nrparts;
154};
155
156static int bcm963xx_detect_cfe(struct mtd_info *master)
157{
158 int idoffset = 0x4e0;
159 static char idstring[8] = "CFE1CFE1";
160 char buf[9];
161 int ret;
162 size_t retlen;
163
164 ret = master->read(master, idoffset, 8, &retlen, (void *)buf);
165 buf[retlen] = 0;
166 printk(KERN_INFO PFX "Read Signature value of %s\n", buf);
167
168 return strncmp(idstring, buf, 8);
169}
170
171static int bcm963xx_probe(struct platform_device *pdev)
172{
173 int err = 0;
174 int parsed_nr_parts = 0;
175 char *part_type;
176 struct resource *r;
177
178 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
179 if (!r) {
180 dev_err(&pdev->dev, "no resource supplied\n");
181 return -ENODEV;
182 }
183
184 bcm963xx_map.phys = r->start;
185 bcm963xx_map.size = resource_size(r);
186 bcm963xx_map.virt = ioremap(r->start, resource_size(r));
187 if (!bcm963xx_map.virt) {
188 dev_err(&pdev->dev, "failed to ioremap\n");
189 return -EIO;
190 }
191
192 dev_info(&pdev->dev, "0x%08lx at 0x%08x\n",
193 bcm963xx_map.size, bcm963xx_map.phys);
194
195 simple_map_init(&bcm963xx_map);
196
197 bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
198 if (!bcm963xx_mtd_info) {
199 dev_err(&pdev->dev, "failed to probe using CFI\n");
200 bcm963xx_mtd_info = do_map_probe("jedec_probe", &bcm963xx_map);
201 if (bcm963xx_mtd_info)
202 goto probe_ok;
203 dev_err(&pdev->dev, "failed to probe using JEDEC\n");
204 err = -EIO;
205 goto err_probe;
206 }
207
208probe_ok:
209 bcm963xx_mtd_info->owner = THIS_MODULE;
210
211 /* This is mutually exclusive */
212 if (bcm963xx_detect_cfe(bcm963xx_mtd_info) == 0) {
213 dev_info(&pdev->dev, "CFE bootloader detected\n");
214 if (parsed_nr_parts == 0) {
215 int ret = parse_cfe_partitions(bcm963xx_mtd_info,
216 &parsed_parts);
217 if (ret > 0) {
218 part_type = "CFE";
219 parsed_nr_parts = ret;
220 }
221 }
222 } else {
223 dev_info(&pdev->dev, "unsupported bootloader\n");
224 err = -ENODEV;
225 goto err_probe;
226 }
227
228 return mtd_device_register(bcm963xx_mtd_info, parsed_parts,
229 parsed_nr_parts);
230
231err_probe:
232 iounmap(bcm963xx_map.virt);
233 return err;
234}
235
236static int bcm963xx_remove(struct platform_device *pdev)
237{
238 if (bcm963xx_mtd_info) {
239 mtd_device_unregister(bcm963xx_mtd_info);
240 map_destroy(bcm963xx_mtd_info);
241 }
242
243 if (bcm963xx_map.virt) {
244 iounmap(bcm963xx_map.virt);
245 bcm963xx_map.virt = 0;
246 }
247
248 return 0;
249}
250
251static struct platform_driver bcm63xx_mtd_dev = {
252 .probe = bcm963xx_probe,
253 .remove = bcm963xx_remove,
254 .driver = {
255 .name = "bcm963xx-flash",
256 .owner = THIS_MODULE,
257 },
258};
259
260static int __init bcm963xx_mtd_init(void)
261{
262 return platform_driver_register(&bcm63xx_mtd_dev);
263}
264
265static void __exit bcm963xx_mtd_exit(void)
266{
267 platform_driver_unregister(&bcm63xx_mtd_dev);
268}
269
270module_init(bcm963xx_mtd_init);
271module_exit(bcm963xx_mtd_exit);
272
273MODULE_LICENSE("GPL");
274MODULE_DESCRIPTION("Broadcom BCM63xx MTD driver for CFE and RedBoot");
275MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>");
276MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
277MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>");
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 6d6b2b5674e..650126c361f 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -190,17 +190,7 @@ static struct platform_driver bfin_flash_driver = {
190 }, 190 },
191}; 191};
192 192
193static int __init bfin_flash_init(void) 193module_platform_driver(bfin_flash_driver);
194{
195 return platform_driver_register(&bfin_flash_driver);
196}
197module_init(bfin_flash_init);
198
199static void __exit bfin_flash_exit(void)
200{
201 platform_driver_unregister(&bfin_flash_driver);
202}
203module_exit(bfin_flash_exit);
204 194
205MODULE_LICENSE("GPL"); 195MODULE_LICENSE("GPL");
206MODULE_DESCRIPTION("MTD map driver for Blackfins with flash/ethernet on same async bank"); 196MODULE_DESCRIPTION("MTD map driver for Blackfins with flash/ethernet on same async bank");
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 1ec66f031c5..33cce895859 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -279,17 +279,7 @@ static struct platform_driver gpio_flash_driver = {
279 }, 279 },
280}; 280};
281 281
282static int __init gpio_flash_init(void) 282module_platform_driver(gpio_flash_driver);
283{
284 return platform_driver_register(&gpio_flash_driver);
285}
286module_init(gpio_flash_init);
287
288static void __exit gpio_flash_exit(void)
289{
290 platform_driver_unregister(&gpio_flash_driver);
291}
292module_exit(gpio_flash_exit);
293 283
294MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); 284MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
295MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios"); 285MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios");
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 437fcd2f352..fc7d4d0d9a4 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -246,18 +246,8 @@ static struct platform_driver ixp2000_flash_driver = {
246 }, 246 },
247}; 247};
248 248
249static int __init ixp2000_flash_init(void) 249module_platform_driver(ixp2000_flash_driver);
250{
251 return platform_driver_register(&ixp2000_flash_driver);
252}
253
254static void __exit ixp2000_flash_exit(void)
255{
256 platform_driver_unregister(&ixp2000_flash_driver);
257}
258 250
259module_init(ixp2000_flash_init);
260module_exit(ixp2000_flash_exit);
261MODULE_LICENSE("GPL"); 251MODULE_LICENSE("GPL");
262MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); 252MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
263MODULE_ALIAS("platform:IXP2000-Flash"); 253MODULE_ALIAS("platform:IXP2000-Flash");
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 30409015a3d..8b5410162d7 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -270,19 +270,7 @@ static struct platform_driver ixp4xx_flash_driver = {
270 }, 270 },
271}; 271};
272 272
273static int __init ixp4xx_flash_init(void) 273module_platform_driver(ixp4xx_flash_driver);
274{
275 return platform_driver_register(&ixp4xx_flash_driver);
276}
277
278static void __exit ixp4xx_flash_exit(void)
279{
280 platform_driver_unregister(&ixp4xx_flash_driver);
281}
282
283
284module_init(ixp4xx_flash_init);
285module_exit(ixp4xx_flash_exit);
286 274
287MODULE_LICENSE("GPL"); 275MODULE_LICENSE("GPL");
288MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); 276MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index 4f10e27ada5..7b889de9477 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -159,7 +159,7 @@ ltq_mtd_probe(struct platform_device *pdev)
159 if (!ltq_mtd->mtd) { 159 if (!ltq_mtd->mtd) {
160 dev_err(&pdev->dev, "probing failed\n"); 160 dev_err(&pdev->dev, "probing failed\n");
161 err = -ENXIO; 161 err = -ENXIO;
162 goto err_unmap; 162 goto err_free;
163 } 163 }
164 164
165 ltq_mtd->mtd->owner = THIS_MODULE; 165 ltq_mtd->mtd->owner = THIS_MODULE;
@@ -179,8 +179,6 @@ ltq_mtd_probe(struct platform_device *pdev)
179 179
180err_destroy: 180err_destroy:
181 map_destroy(ltq_mtd->mtd); 181 map_destroy(ltq_mtd->mtd);
182err_unmap:
183 iounmap(ltq_mtd->map->virt);
184err_free: 182err_free:
185 kfree(ltq_mtd->map); 183 kfree(ltq_mtd->map);
186err_out: 184err_out:
@@ -198,8 +196,6 @@ ltq_mtd_remove(struct platform_device *pdev)
198 mtd_device_unregister(ltq_mtd->mtd); 196 mtd_device_unregister(ltq_mtd->mtd);
199 map_destroy(ltq_mtd->mtd); 197 map_destroy(ltq_mtd->mtd);
200 } 198 }
201 if (ltq_mtd->map->virt)
202 iounmap(ltq_mtd->map->virt);
203 kfree(ltq_mtd->map); 199 kfree(ltq_mtd->map);
204 kfree(ltq_mtd); 200 kfree(ltq_mtd);
205 } 201 }
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index 119baa7d747..8fed58e3a4a 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -223,17 +223,7 @@ static struct platform_driver latch_addr_flash_driver = {
223 }, 223 },
224}; 224};
225 225
226static int __init latch_addr_flash_init(void) 226module_platform_driver(latch_addr_flash_driver);
227{
228 return platform_driver_register(&latch_addr_flash_driver);
229}
230module_init(latch_addr_flash_init);
231
232static void __exit latch_addr_flash_exit(void)
233{
234 platform_driver_unregister(&latch_addr_flash_driver);
235}
236module_exit(latch_addr_flash_exit);
237 227
238MODULE_AUTHOR("David Griego <dgriego@mvista.com>"); 228MODULE_AUTHOR("David Griego <dgriego@mvista.com>");
239MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper " 229MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 66e8200079c..abc562653b3 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -85,6 +85,7 @@ static int physmap_flash_probe(struct platform_device *dev)
85 struct physmap_flash_data *physmap_data; 85 struct physmap_flash_data *physmap_data;
86 struct physmap_flash_info *info; 86 struct physmap_flash_info *info;
87 const char **probe_type; 87 const char **probe_type;
88 const char **part_types;
88 int err = 0; 89 int err = 0;
89 int i; 90 int i;
90 int devices_found = 0; 91 int devices_found = 0;
@@ -171,7 +172,9 @@ static int physmap_flash_probe(struct platform_device *dev)
171 if (err) 172 if (err)
172 goto err_out; 173 goto err_out;
173 174
174 mtd_device_parse_register(info->cmtd, part_probe_types, 0, 175 part_types = physmap_data->part_probe_types ? : part_probe_types;
176
177 mtd_device_parse_register(info->cmtd, part_types, 0,
175 physmap_data->parts, physmap_data->nr_parts); 178 physmap_data->parts, physmap_data->nr_parts);
176 return 0; 179 return 0;
177 180
@@ -187,9 +190,8 @@ static void physmap_flash_shutdown(struct platform_device *dev)
187 int i; 190 int i;
188 191
189 for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++) 192 for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
190 if (info->mtd[i]->suspend && info->mtd[i]->resume) 193 if (mtd_suspend(info->mtd[i]) == 0)
191 if (info->mtd[i]->suspend(info->mtd[i]) == 0) 194 mtd_resume(info->mtd[i]);
192 info->mtd[i]->resume(info->mtd[i]);
193} 195}
194#else 196#else
195#define physmap_flash_shutdown NULL 197#define physmap_flash_shutdown NULL
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 7d65f9d3e69..2e6fb6831d5 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -338,18 +338,7 @@ static struct platform_driver of_flash_driver = {
338 .remove = of_flash_remove, 338 .remove = of_flash_remove,
339}; 339};
340 340
341static int __init of_flash_init(void) 341module_platform_driver(of_flash_driver);
342{
343 return platform_driver_register(&of_flash_driver);
344}
345
346static void __exit of_flash_exit(void)
347{
348 platform_driver_unregister(&of_flash_driver);
349}
350
351module_init(of_flash_init);
352module_exit(of_flash_exit);
353 342
354MODULE_LICENSE("GPL"); 343MODULE_LICENSE("GPL");
355MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>"); 344MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 2a25b6789af..436d121185b 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -125,8 +125,8 @@ static void pxa2xx_flash_shutdown(struct platform_device *dev)
125{ 125{
126 struct pxa2xx_flash_info *info = platform_get_drvdata(dev); 126 struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
127 127
128 if (info && info->mtd->suspend(info->mtd) == 0) 128 if (info && mtd_suspend(info->mtd) == 0)
129 info->mtd->resume(info->mtd); 129 mtd_resume(info->mtd);
130} 130}
131#else 131#else
132#define pxa2xx_flash_shutdown NULL 132#define pxa2xx_flash_shutdown NULL
@@ -142,18 +142,7 @@ static struct platform_driver pxa2xx_flash_driver = {
142 .shutdown = pxa2xx_flash_shutdown, 142 .shutdown = pxa2xx_flash_shutdown,
143}; 143};
144 144
145static int __init init_pxa2xx_flash(void) 145module_platform_driver(pxa2xx_flash_driver);
146{
147 return platform_driver_register(&pxa2xx_flash_driver);
148}
149
150static void __exit cleanup_pxa2xx_flash(void)
151{
152 platform_driver_unregister(&pxa2xx_flash_driver);
153}
154
155module_init(init_pxa2xx_flash);
156module_exit(cleanup_pxa2xx_flash);
157 146
158MODULE_LICENSE("GPL"); 147MODULE_LICENSE("GPL");
159MODULE_AUTHOR("Nicolas Pitre <nico@fluxnic.net>"); 148MODULE_AUTHOR("Nicolas Pitre <nico@fluxnic.net>");
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 0237f197fd1..3da63fc6f16 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -119,9 +119,8 @@ static void rbtx4939_flash_shutdown(struct platform_device *dev)
119{ 119{
120 struct rbtx4939_flash_info *info = platform_get_drvdata(dev); 120 struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
121 121
122 if (info->mtd->suspend && info->mtd->resume) 122 if (mtd_suspend(info->mtd) == 0)
123 if (info->mtd->suspend(info->mtd) == 0) 123 mtd_resume(info->mtd);
124 info->mtd->resume(info->mtd);
125} 124}
126#else 125#else
127#define rbtx4939_flash_shutdown NULL 126#define rbtx4939_flash_shutdown NULL
@@ -137,18 +136,7 @@ static struct platform_driver rbtx4939_flash_driver = {
137 }, 136 },
138}; 137};
139 138
140static int __init rbtx4939_flash_init(void) 139module_platform_driver(rbtx4939_flash_driver);
141{
142 return platform_driver_register(&rbtx4939_flash_driver);
143}
144
145static void __exit rbtx4939_flash_exit(void)
146{
147 platform_driver_unregister(&rbtx4939_flash_driver);
148}
149
150module_init(rbtx4939_flash_init);
151module_exit(rbtx4939_flash_exit);
152 140
153MODULE_LICENSE("GPL"); 141MODULE_LICENSE("GPL");
154MODULE_DESCRIPTION("RBTX4939 MTD map driver"); 142MODULE_DESCRIPTION("RBTX4939 MTD map driver");
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index fa9c0a9670c..50282199770 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -377,8 +377,8 @@ static int __exit sa1100_mtd_remove(struct platform_device *pdev)
377static void sa1100_mtd_shutdown(struct platform_device *dev) 377static void sa1100_mtd_shutdown(struct platform_device *dev)
378{ 378{
379 struct sa_info *info = platform_get_drvdata(dev); 379 struct sa_info *info = platform_get_drvdata(dev);
380 if (info && info->mtd->suspend(info->mtd) == 0) 380 if (info && mtd_suspend(info->mtd) == 0)
381 info->mtd->resume(info->mtd); 381 mtd_resume(info->mtd);
382} 382}
383#else 383#else
384#define sa1100_mtd_shutdown NULL 384#define sa1100_mtd_shutdown NULL
@@ -394,18 +394,7 @@ static struct platform_driver sa1100_mtd_driver = {
394 }, 394 },
395}; 395};
396 396
397static int __init sa1100_mtd_init(void) 397module_platform_driver(sa1100_mtd_driver);
398{
399 return platform_driver_register(&sa1100_mtd_driver);
400}
401
402static void __exit sa1100_mtd_exit(void)
403{
404 platform_driver_unregister(&sa1100_mtd_driver);
405}
406
407module_init(sa1100_mtd_init);
408module_exit(sa1100_mtd_exit);
409 398
410MODULE_AUTHOR("Nicolas Pitre"); 399MODULE_AUTHOR("Nicolas Pitre");
411MODULE_DESCRIPTION("SA1100 CFI map driver"); 400MODULE_DESCRIPTION("SA1100 CFI map driver");
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
index d88c8426bb0..934a72c8007 100644
--- a/drivers/mtd/maps/scb2_flash.c
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -204,8 +204,7 @@ scb2_flash_remove(struct pci_dev *dev)
204 return; 204 return;
205 205
206 /* disable flash writes */ 206 /* disable flash writes */
207 if (scb2_mtd->lock) 207 mtd_lock(scb2_mtd, 0, scb2_mtd->size);
208 scb2_mtd->lock(scb2_mtd, 0, scb2_mtd->size);
209 208
210 mtd_device_unregister(scb2_mtd); 209 mtd_device_unregister(scb2_mtd);
211 map_destroy(scb2_mtd); 210 map_destroy(scb2_mtd);
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 2d66234f57c..175e537b444 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -158,15 +158,4 @@ static struct platform_driver uflash_driver = {
158 .remove = __devexit_p(uflash_remove), 158 .remove = __devexit_p(uflash_remove),
159}; 159};
160 160
161static int __init uflash_init(void) 161module_platform_driver(uflash_driver);
162{
163 return platform_driver_register(&uflash_driver);
164}
165
166static void __exit uflash_exit(void)
167{
168 platform_driver_unregister(&uflash_driver);
169}
170
171module_init(uflash_init);
172module_exit(uflash_exit);
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index ed8b5e744b1..424ca5f93c6 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -215,7 +215,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
215 215
216 mutex_lock(&dev->lock); 216 mutex_lock(&dev->lock);
217 217
218 if (dev->open++) 218 if (dev->open)
219 goto unlock; 219 goto unlock;
220 220
221 kref_get(&dev->ref); 221 kref_get(&dev->ref);
@@ -235,6 +235,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
235 goto error_release; 235 goto error_release;
236 236
237unlock: 237unlock:
238 dev->open++;
238 mutex_unlock(&dev->lock); 239 mutex_unlock(&dev->lock);
239 blktrans_dev_put(dev); 240 blktrans_dev_put(dev);
240 return ret; 241 return ret;
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 7c1dc908a17..af6591237b9 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -85,7 +85,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos,
85 set_current_state(TASK_INTERRUPTIBLE); 85 set_current_state(TASK_INTERRUPTIBLE);
86 add_wait_queue(&wait_q, &wait); 86 add_wait_queue(&wait_q, &wait);
87 87
88 ret = mtd->erase(mtd, &erase); 88 ret = mtd_erase(mtd, &erase);
89 if (ret) { 89 if (ret) {
90 set_current_state(TASK_RUNNING); 90 set_current_state(TASK_RUNNING);
91 remove_wait_queue(&wait_q, &wait); 91 remove_wait_queue(&wait_q, &wait);
@@ -102,7 +102,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos,
102 * Next, write the data to flash. 102 * Next, write the data to flash.
103 */ 103 */
104 104
105 ret = mtd->write(mtd, pos, len, &retlen, buf); 105 ret = mtd_write(mtd, pos, len, &retlen, buf);
106 if (ret) 106 if (ret)
107 return ret; 107 return ret;
108 if (retlen != len) 108 if (retlen != len)
@@ -152,7 +152,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
152 mtd->name, pos, len); 152 mtd->name, pos, len);
153 153
154 if (!sect_size) 154 if (!sect_size)
155 return mtd->write(mtd, pos, len, &retlen, buf); 155 return mtd_write(mtd, pos, len, &retlen, buf);
156 156
157 while (len > 0) { 157 while (len > 0) {
158 unsigned long sect_start = (pos/sect_size)*sect_size; 158 unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -184,8 +184,8 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
184 mtdblk->cache_offset != sect_start) { 184 mtdblk->cache_offset != sect_start) {
185 /* fill the cache with the current sector */ 185 /* fill the cache with the current sector */
186 mtdblk->cache_state = STATE_EMPTY; 186 mtdblk->cache_state = STATE_EMPTY;
187 ret = mtd->read(mtd, sect_start, sect_size, 187 ret = mtd_read(mtd, sect_start, sect_size,
188 &retlen, mtdblk->cache_data); 188 &retlen, mtdblk->cache_data);
189 if (ret) 189 if (ret)
190 return ret; 190 return ret;
191 if (retlen != sect_size) 191 if (retlen != sect_size)
@@ -222,7 +222,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
222 mtd->name, pos, len); 222 mtd->name, pos, len);
223 223
224 if (!sect_size) 224 if (!sect_size)
225 return mtd->read(mtd, pos, len, &retlen, buf); 225 return mtd_read(mtd, pos, len, &retlen, buf);
226 226
227 while (len > 0) { 227 while (len > 0) {
228 unsigned long sect_start = (pos/sect_size)*sect_size; 228 unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -241,7 +241,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
241 mtdblk->cache_offset == sect_start) { 241 mtdblk->cache_offset == sect_start) {
242 memcpy (buf, mtdblk->cache_data + offset, size); 242 memcpy (buf, mtdblk->cache_data + offset, size);
243 } else { 243 } else {
244 ret = mtd->read(mtd, pos, size, &retlen, buf); 244 ret = mtd_read(mtd, pos, size, &retlen, buf);
245 if (ret) 245 if (ret)
246 return ret; 246 return ret;
247 if (retlen != size) 247 if (retlen != size)
@@ -322,8 +322,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
322 322
323 if (!--mtdblk->count) { 323 if (!--mtdblk->count) {
324 /* It was the last usage. Free the cache */ 324 /* It was the last usage. Free the cache */
325 if (mbd->mtd->sync) 325 mtd_sync(mbd->mtd);
326 mbd->mtd->sync(mbd->mtd);
327 vfree(mtdblk->cache_data); 326 vfree(mtdblk->cache_data);
328 } 327 }
329 328
@@ -341,9 +340,7 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev)
341 mutex_lock(&mtdblk->cache_mutex); 340 mutex_lock(&mtdblk->cache_mutex);
342 write_cached_data(mtdblk); 341 write_cached_data(mtdblk);
343 mutex_unlock(&mtdblk->cache_mutex); 342 mutex_unlock(&mtdblk->cache_mutex);
344 343 mtd_sync(dev->mtd);
345 if (dev->mtd->sync)
346 dev->mtd->sync(dev->mtd);
347 return 0; 344 return 0;
348} 345}
349 346
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index 0470a6e8630..92759a9d298 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -30,7 +30,7 @@ static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
30{ 30{
31 size_t retlen; 31 size_t retlen;
32 32
33 if (dev->mtd->read(dev->mtd, (block * 512), 512, &retlen, buf)) 33 if (mtd_read(dev->mtd, (block * 512), 512, &retlen, buf))
34 return 1; 34 return 1;
35 return 0; 35 return 0;
36} 36}
@@ -40,7 +40,7 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
40{ 40{
41 size_t retlen; 41 size_t retlen;
42 42
43 if (dev->mtd->write(dev->mtd, (block * 512), 512, &retlen, buf)) 43 if (mtd_write(dev->mtd, (block * 512), 512, &retlen, buf))
44 return 1; 44 return 1;
45 return 0; 45 return 0;
46} 46}
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index e7dc732ddab..50c6a1e7f67 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -51,7 +51,7 @@ struct mtd_file_info {
51 enum mtd_file_modes mode; 51 enum mtd_file_modes mode;
52}; 52};
53 53
54static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) 54static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig)
55{ 55{
56 struct mtd_file_info *mfi = file->private_data; 56 struct mtd_file_info *mfi = file->private_data;
57 struct mtd_info *mtd = mfi->mtd; 57 struct mtd_info *mtd = mfi->mtd;
@@ -77,7 +77,7 @@ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
77 77
78 78
79 79
80static int mtd_open(struct inode *inode, struct file *file) 80static int mtdchar_open(struct inode *inode, struct file *file)
81{ 81{
82 int minor = iminor(inode); 82 int minor = iminor(inode);
83 int devnum = minor >> 1; 83 int devnum = minor >> 1;
@@ -142,11 +142,11 @@ static int mtd_open(struct inode *inode, struct file *file)
142out: 142out:
143 mutex_unlock(&mtd_mutex); 143 mutex_unlock(&mtd_mutex);
144 return ret; 144 return ret;
145} /* mtd_open */ 145} /* mtdchar_open */
146 146
147/*====================================================================*/ 147/*====================================================================*/
148 148
149static int mtd_close(struct inode *inode, struct file *file) 149static int mtdchar_close(struct inode *inode, struct file *file)
150{ 150{
151 struct mtd_file_info *mfi = file->private_data; 151 struct mtd_file_info *mfi = file->private_data;
152 struct mtd_info *mtd = mfi->mtd; 152 struct mtd_info *mtd = mfi->mtd;
@@ -154,8 +154,8 @@ static int mtd_close(struct inode *inode, struct file *file)
154 pr_debug("MTD_close\n"); 154 pr_debug("MTD_close\n");
155 155
156 /* Only sync if opened RW */ 156 /* Only sync if opened RW */
157 if ((file->f_mode & FMODE_WRITE) && mtd->sync) 157 if ((file->f_mode & FMODE_WRITE))
158 mtd->sync(mtd); 158 mtd_sync(mtd);
159 159
160 iput(mfi->ino); 160 iput(mfi->ino);
161 161
@@ -164,7 +164,7 @@ static int mtd_close(struct inode *inode, struct file *file)
164 kfree(mfi); 164 kfree(mfi);
165 165
166 return 0; 166 return 0;
167} /* mtd_close */ 167} /* mtdchar_close */
168 168
169/* Back in June 2001, dwmw2 wrote: 169/* Back in June 2001, dwmw2 wrote:
170 * 170 *
@@ -184,11 +184,12 @@ static int mtd_close(struct inode *inode, struct file *file)
184 * alignment requirements are not met in the NAND subdriver. 184 * alignment requirements are not met in the NAND subdriver.
185 */ 185 */
186 186
187static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) 187static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
188 loff_t *ppos)
188{ 189{
189 struct mtd_file_info *mfi = file->private_data; 190 struct mtd_file_info *mfi = file->private_data;
190 struct mtd_info *mtd = mfi->mtd; 191 struct mtd_info *mtd = mfi->mtd;
191 size_t retlen=0; 192 size_t retlen;
192 size_t total_retlen=0; 193 size_t total_retlen=0;
193 int ret=0; 194 int ret=0;
194 int len; 195 int len;
@@ -212,10 +213,12 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
212 213
213 switch (mfi->mode) { 214 switch (mfi->mode) {
214 case MTD_FILE_MODE_OTP_FACTORY: 215 case MTD_FILE_MODE_OTP_FACTORY:
215 ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); 216 ret = mtd_read_fact_prot_reg(mtd, *ppos, len,
217 &retlen, kbuf);
216 break; 218 break;
217 case MTD_FILE_MODE_OTP_USER: 219 case MTD_FILE_MODE_OTP_USER:
218 ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); 220 ret = mtd_read_user_prot_reg(mtd, *ppos, len,
221 &retlen, kbuf);
219 break; 222 break;
220 case MTD_FILE_MODE_RAW: 223 case MTD_FILE_MODE_RAW:
221 { 224 {
@@ -226,12 +229,12 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
226 ops.oobbuf = NULL; 229 ops.oobbuf = NULL;
227 ops.len = len; 230 ops.len = len;
228 231
229 ret = mtd->read_oob(mtd, *ppos, &ops); 232 ret = mtd_read_oob(mtd, *ppos, &ops);
230 retlen = ops.retlen; 233 retlen = ops.retlen;
231 break; 234 break;
232 } 235 }
233 default: 236 default:
234 ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); 237 ret = mtd_read(mtd, *ppos, len, &retlen, kbuf);
235 } 238 }
236 /* Nand returns -EBADMSG on ECC errors, but it returns 239 /* Nand returns -EBADMSG on ECC errors, but it returns
237 * the data. For our userspace tools it is important 240 * the data. For our userspace tools it is important
@@ -265,9 +268,10 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
265 268
266 kfree(kbuf); 269 kfree(kbuf);
267 return total_retlen; 270 return total_retlen;
268} /* mtd_read */ 271} /* mtdchar_read */
269 272
270static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) 273static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t count,
274 loff_t *ppos)
271{ 275{
272 struct mtd_file_info *mfi = file->private_data; 276 struct mtd_file_info *mfi = file->private_data;
273 struct mtd_info *mtd = mfi->mtd; 277 struct mtd_info *mtd = mfi->mtd;
@@ -306,11 +310,8 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
306 ret = -EROFS; 310 ret = -EROFS;
307 break; 311 break;
308 case MTD_FILE_MODE_OTP_USER: 312 case MTD_FILE_MODE_OTP_USER:
309 if (!mtd->write_user_prot_reg) { 313 ret = mtd_write_user_prot_reg(mtd, *ppos, len,
310 ret = -EOPNOTSUPP; 314 &retlen, kbuf);
311 break;
312 }
313 ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
314 break; 315 break;
315 316
316 case MTD_FILE_MODE_RAW: 317 case MTD_FILE_MODE_RAW:
@@ -323,13 +324,13 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
323 ops.ooboffs = 0; 324 ops.ooboffs = 0;
324 ops.len = len; 325 ops.len = len;
325 326
326 ret = mtd->write_oob(mtd, *ppos, &ops); 327 ret = mtd_write_oob(mtd, *ppos, &ops);
327 retlen = ops.retlen; 328 retlen = ops.retlen;
328 break; 329 break;
329 } 330 }
330 331
331 default: 332 default:
332 ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf); 333 ret = mtd_write(mtd, *ppos, len, &retlen, kbuf);
333 } 334 }
334 if (!ret) { 335 if (!ret) {
335 *ppos += retlen; 336 *ppos += retlen;
@@ -345,7 +346,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
345 346
346 kfree(kbuf); 347 kfree(kbuf);
347 return total_retlen; 348 return total_retlen;
348} /* mtd_write */ 349} /* mtdchar_write */
349 350
350/*====================================================================== 351/*======================================================================
351 352
@@ -361,20 +362,22 @@ static void mtdchar_erase_callback (struct erase_info *instr)
361static int otp_select_filemode(struct mtd_file_info *mfi, int mode) 362static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
362{ 363{
363 struct mtd_info *mtd = mfi->mtd; 364 struct mtd_info *mtd = mfi->mtd;
365 size_t retlen;
364 int ret = 0; 366 int ret = 0;
365 367
368 /*
369 * Make a fake call to mtd_read_fact_prot_reg() to check if OTP
370 * operations are supported.
371 */
372 if (mtd_read_fact_prot_reg(mtd, -1, -1, &retlen, NULL) == -EOPNOTSUPP)
373 return -EOPNOTSUPP;
374
366 switch (mode) { 375 switch (mode) {
367 case MTD_OTP_FACTORY: 376 case MTD_OTP_FACTORY:
368 if (!mtd->read_fact_prot_reg) 377 mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
369 ret = -EOPNOTSUPP;
370 else
371 mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
372 break; 378 break;
373 case MTD_OTP_USER: 379 case MTD_OTP_USER:
374 if (!mtd->read_fact_prot_reg) 380 mfi->mode = MTD_FILE_MODE_OTP_USER;
375 ret = -EOPNOTSUPP;
376 else
377 mfi->mode = MTD_FILE_MODE_OTP_USER;
378 break; 381 break;
379 default: 382 default:
380 ret = -EINVAL; 383 ret = -EINVAL;
@@ -387,7 +390,7 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
387# define otp_select_filemode(f,m) -EOPNOTSUPP 390# define otp_select_filemode(f,m) -EOPNOTSUPP
388#endif 391#endif
389 392
390static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, 393static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
391 uint64_t start, uint32_t length, void __user *ptr, 394 uint64_t start, uint32_t length, void __user *ptr,
392 uint32_t __user *retp) 395 uint32_t __user *retp)
393{ 396{
@@ -424,7 +427,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
424 return PTR_ERR(ops.oobbuf); 427 return PTR_ERR(ops.oobbuf);
425 428
426 start &= ~((uint64_t)mtd->writesize - 1); 429 start &= ~((uint64_t)mtd->writesize - 1);
427 ret = mtd->write_oob(mtd, start, &ops); 430 ret = mtd_write_oob(mtd, start, &ops);
428 431
429 if (ops.oobretlen > 0xFFFFFFFFU) 432 if (ops.oobretlen > 0xFFFFFFFFU)
430 ret = -EOVERFLOW; 433 ret = -EOVERFLOW;
@@ -436,7 +439,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
436 return ret; 439 return ret;
437} 440}
438 441
439static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, 442static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
440 uint64_t start, uint32_t length, void __user *ptr, 443 uint64_t start, uint32_t length, void __user *ptr,
441 uint32_t __user *retp) 444 uint32_t __user *retp)
442{ 445{
@@ -447,13 +450,8 @@ static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,
447 if (length > 4096) 450 if (length > 4096)
448 return -EINVAL; 451 return -EINVAL;
449 452
450 if (!mtd->read_oob) 453 if (!access_ok(VERIFY_WRITE, ptr, length))
451 ret = -EOPNOTSUPP; 454 return -EFAULT;
452 else
453 ret = access_ok(VERIFY_WRITE, ptr,
454 length) ? 0 : -EFAULT;
455 if (ret)
456 return ret;
457 455
458 ops.ooblen = length; 456 ops.ooblen = length;
459 ops.ooboffs = start & (mtd->writesize - 1); 457 ops.ooboffs = start & (mtd->writesize - 1);
@@ -469,7 +467,7 @@ static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,
469 return -ENOMEM; 467 return -ENOMEM;
470 468
471 start &= ~((uint64_t)mtd->writesize - 1); 469 start &= ~((uint64_t)mtd->writesize - 1);
472 ret = mtd->read_oob(mtd, start, &ops); 470 ret = mtd_read_oob(mtd, start, &ops);
473 471
474 if (put_user(ops.oobretlen, retp)) 472 if (put_user(ops.oobretlen, retp))
475 ret = -EFAULT; 473 ret = -EFAULT;
@@ -530,7 +528,7 @@ static int shrink_ecclayout(const struct nand_ecclayout *from,
530 return 0; 528 return 0;
531} 529}
532 530
533static int mtd_blkpg_ioctl(struct mtd_info *mtd, 531static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
534 struct blkpg_ioctl_arg __user *arg) 532 struct blkpg_ioctl_arg __user *arg)
535{ 533{
536 struct blkpg_ioctl_arg a; 534 struct blkpg_ioctl_arg a;
@@ -566,7 +564,7 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd,
566 } 564 }
567} 565}
568 566
569static int mtd_write_ioctl(struct mtd_info *mtd, 567static int mtdchar_write_ioctl(struct mtd_info *mtd,
570 struct mtd_write_req __user *argp) 568 struct mtd_write_req __user *argp)
571{ 569{
572 struct mtd_write_req req; 570 struct mtd_write_req req;
@@ -607,7 +605,7 @@ static int mtd_write_ioctl(struct mtd_info *mtd,
607 ops.oobbuf = NULL; 605 ops.oobbuf = NULL;
608 } 606 }
609 607
610 ret = mtd->write_oob(mtd, (loff_t)req.start, &ops); 608 ret = mtd_write_oob(mtd, (loff_t)req.start, &ops);
611 609
612 kfree(ops.datbuf); 610 kfree(ops.datbuf);
613 kfree(ops.oobbuf); 611 kfree(ops.oobbuf);
@@ -615,7 +613,7 @@ static int mtd_write_ioctl(struct mtd_info *mtd,
615 return ret; 613 return ret;
616} 614}
617 615
618static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) 616static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
619{ 617{
620 struct mtd_file_info *mfi = file->private_data; 618 struct mtd_file_info *mfi = file->private_data;
621 struct mtd_info *mtd = mfi->mtd; 619 struct mtd_info *mtd = mfi->mtd;
@@ -729,7 +727,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
729 wq_head is no longer there when the 727 wq_head is no longer there when the
730 callback routine tries to wake us up. 728 callback routine tries to wake us up.
731 */ 729 */
732 ret = mtd->erase(mtd, erase); 730 ret = mtd_erase(mtd, erase);
733 if (!ret) { 731 if (!ret) {
734 set_current_state(TASK_UNINTERRUPTIBLE); 732 set_current_state(TASK_UNINTERRUPTIBLE);
735 add_wait_queue(&waitq, &wait); 733 add_wait_queue(&waitq, &wait);
@@ -755,7 +753,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
755 if (copy_from_user(&buf, argp, sizeof(buf))) 753 if (copy_from_user(&buf, argp, sizeof(buf)))
756 ret = -EFAULT; 754 ret = -EFAULT;
757 else 755 else
758 ret = mtd_do_writeoob(file, mtd, buf.start, buf.length, 756 ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
759 buf.ptr, &buf_user->length); 757 buf.ptr, &buf_user->length);
760 break; 758 break;
761 } 759 }
@@ -769,7 +767,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
769 if (copy_from_user(&buf, argp, sizeof(buf))) 767 if (copy_from_user(&buf, argp, sizeof(buf)))
770 ret = -EFAULT; 768 ret = -EFAULT;
771 else 769 else
772 ret = mtd_do_readoob(file, mtd, buf.start, buf.length, 770 ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
773 buf.ptr, &buf_user->start); 771 buf.ptr, &buf_user->start);
774 break; 772 break;
775 } 773 }
@@ -782,7 +780,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
782 if (copy_from_user(&buf, argp, sizeof(buf))) 780 if (copy_from_user(&buf, argp, sizeof(buf)))
783 ret = -EFAULT; 781 ret = -EFAULT;
784 else 782 else
785 ret = mtd_do_writeoob(file, mtd, buf.start, buf.length, 783 ret = mtdchar_writeoob(file, mtd, buf.start, buf.length,
786 (void __user *)(uintptr_t)buf.usr_ptr, 784 (void __user *)(uintptr_t)buf.usr_ptr,
787 &buf_user->length); 785 &buf_user->length);
788 break; 786 break;
@@ -796,7 +794,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
796 if (copy_from_user(&buf, argp, sizeof(buf))) 794 if (copy_from_user(&buf, argp, sizeof(buf)))
797 ret = -EFAULT; 795 ret = -EFAULT;
798 else 796 else
799 ret = mtd_do_readoob(file, mtd, buf.start, buf.length, 797 ret = mtdchar_readoob(file, mtd, buf.start, buf.length,
800 (void __user *)(uintptr_t)buf.usr_ptr, 798 (void __user *)(uintptr_t)buf.usr_ptr,
801 &buf_user->length); 799 &buf_user->length);
802 break; 800 break;
@@ -804,7 +802,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
804 802
805 case MEMWRITE: 803 case MEMWRITE:
806 { 804 {
807 ret = mtd_write_ioctl(mtd, 805 ret = mtdchar_write_ioctl(mtd,
808 (struct mtd_write_req __user *)arg); 806 (struct mtd_write_req __user *)arg);
809 break; 807 break;
810 } 808 }
@@ -816,10 +814,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
816 if (copy_from_user(&einfo, argp, sizeof(einfo))) 814 if (copy_from_user(&einfo, argp, sizeof(einfo)))
817 return -EFAULT; 815 return -EFAULT;
818 816
819 if (!mtd->lock) 817 ret = mtd_lock(mtd, einfo.start, einfo.length);
820 ret = -EOPNOTSUPP;
821 else
822 ret = mtd->lock(mtd, einfo.start, einfo.length);
823 break; 818 break;
824 } 819 }
825 820
@@ -830,10 +825,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
830 if (copy_from_user(&einfo, argp, sizeof(einfo))) 825 if (copy_from_user(&einfo, argp, sizeof(einfo)))
831 return -EFAULT; 826 return -EFAULT;
832 827
833 if (!mtd->unlock) 828 ret = mtd_unlock(mtd, einfo.start, einfo.length);
834 ret = -EOPNOTSUPP;
835 else
836 ret = mtd->unlock(mtd, einfo.start, einfo.length);
837 break; 829 break;
838 } 830 }
839 831
@@ -844,10 +836,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
844 if (copy_from_user(&einfo, argp, sizeof(einfo))) 836 if (copy_from_user(&einfo, argp, sizeof(einfo)))
845 return -EFAULT; 837 return -EFAULT;
846 838
847 if (!mtd->is_locked) 839 ret = mtd_is_locked(mtd, einfo.start, einfo.length);
848 ret = -EOPNOTSUPP;
849 else
850 ret = mtd->is_locked(mtd, einfo.start, einfo.length);
851 break; 840 break;
852 } 841 }
853 842
@@ -878,10 +867,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
878 867
879 if (copy_from_user(&offs, argp, sizeof(loff_t))) 868 if (copy_from_user(&offs, argp, sizeof(loff_t)))
880 return -EFAULT; 869 return -EFAULT;
881 if (!mtd->block_isbad) 870 return mtd_block_isbad(mtd, offs);
882 ret = -EOPNOTSUPP;
883 else
884 return mtd->block_isbad(mtd, offs);
885 break; 871 break;
886 } 872 }
887 873
@@ -891,10 +877,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
891 877
892 if (copy_from_user(&offs, argp, sizeof(loff_t))) 878 if (copy_from_user(&offs, argp, sizeof(loff_t)))
893 return -EFAULT; 879 return -EFAULT;
894 if (!mtd->block_markbad) 880 return mtd_block_markbad(mtd, offs);
895 ret = -EOPNOTSUPP;
896 else
897 return mtd->block_markbad(mtd, offs);
898 break; 881 break;
899 } 882 }
900 883
@@ -919,17 +902,15 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
919 struct otp_info *buf = kmalloc(4096, GFP_KERNEL); 902 struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
920 if (!buf) 903 if (!buf)
921 return -ENOMEM; 904 return -ENOMEM;
922 ret = -EOPNOTSUPP;
923 switch (mfi->mode) { 905 switch (mfi->mode) {
924 case MTD_FILE_MODE_OTP_FACTORY: 906 case MTD_FILE_MODE_OTP_FACTORY:
925 if (mtd->get_fact_prot_info) 907 ret = mtd_get_fact_prot_info(mtd, buf, 4096);
926 ret = mtd->get_fact_prot_info(mtd, buf, 4096);
927 break; 908 break;
928 case MTD_FILE_MODE_OTP_USER: 909 case MTD_FILE_MODE_OTP_USER:
929 if (mtd->get_user_prot_info) 910 ret = mtd_get_user_prot_info(mtd, buf, 4096);
930 ret = mtd->get_user_prot_info(mtd, buf, 4096);
931 break; 911 break;
932 default: 912 default:
913 ret = -EINVAL;
933 break; 914 break;
934 } 915 }
935 if (ret >= 0) { 916 if (ret >= 0) {
@@ -953,9 +934,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
953 return -EINVAL; 934 return -EINVAL;
954 if (copy_from_user(&oinfo, argp, sizeof(oinfo))) 935 if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
955 return -EFAULT; 936 return -EFAULT;
956 if (!mtd->lock_user_prot_reg) 937 ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
957 return -EOPNOTSUPP;
958 ret = mtd->lock_user_prot_reg(mtd, oinfo.start, oinfo.length);
959 break; 938 break;
960 } 939 }
961#endif 940#endif
@@ -999,7 +978,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
999 break; 978 break;
1000 979
1001 case MTD_FILE_MODE_RAW: 980 case MTD_FILE_MODE_RAW:
1002 if (!mtd->read_oob || !mtd->write_oob) 981 if (!mtd_has_oob(mtd))
1003 return -EOPNOTSUPP; 982 return -EOPNOTSUPP;
1004 mfi->mode = arg; 983 mfi->mode = arg;
1005 984
@@ -1014,7 +993,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
1014 993
1015 case BLKPG: 994 case BLKPG:
1016 { 995 {
1017 ret = mtd_blkpg_ioctl(mtd, 996 ret = mtdchar_blkpg_ioctl(mtd,
1018 (struct blkpg_ioctl_arg __user *)arg); 997 (struct blkpg_ioctl_arg __user *)arg);
1019 break; 998 break;
1020 } 999 }
@@ -1033,12 +1012,12 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
1033 return ret; 1012 return ret;
1034} /* memory_ioctl */ 1013} /* memory_ioctl */
1035 1014
1036static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) 1015static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
1037{ 1016{
1038 int ret; 1017 int ret;
1039 1018
1040 mutex_lock(&mtd_mutex); 1019 mutex_lock(&mtd_mutex);
1041 ret = mtd_ioctl(file, cmd, arg); 1020 ret = mtdchar_ioctl(file, cmd, arg);
1042 mutex_unlock(&mtd_mutex); 1021 mutex_unlock(&mtd_mutex);
1043 1022
1044 return ret; 1023 return ret;
@@ -1055,7 +1034,7 @@ struct mtd_oob_buf32 {
1055#define MEMWRITEOOB32 _IOWR('M', 3, struct mtd_oob_buf32) 1034#define MEMWRITEOOB32 _IOWR('M', 3, struct mtd_oob_buf32)
1056#define MEMREADOOB32 _IOWR('M', 4, struct mtd_oob_buf32) 1035#define MEMREADOOB32 _IOWR('M', 4, struct mtd_oob_buf32)
1057 1036
1058static long mtd_compat_ioctl(struct file *file, unsigned int cmd, 1037static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
1059 unsigned long arg) 1038 unsigned long arg)
1060{ 1039{
1061 struct mtd_file_info *mfi = file->private_data; 1040 struct mtd_file_info *mfi = file->private_data;
@@ -1074,7 +1053,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
1074 if (copy_from_user(&buf, argp, sizeof(buf))) 1053 if (copy_from_user(&buf, argp, sizeof(buf)))
1075 ret = -EFAULT; 1054 ret = -EFAULT;
1076 else 1055 else
1077 ret = mtd_do_writeoob(file, mtd, buf.start, 1056 ret = mtdchar_writeoob(file, mtd, buf.start,
1078 buf.length, compat_ptr(buf.ptr), 1057 buf.length, compat_ptr(buf.ptr),
1079 &buf_user->length); 1058 &buf_user->length);
1080 break; 1059 break;
@@ -1089,13 +1068,13 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
1089 if (copy_from_user(&buf, argp, sizeof(buf))) 1068 if (copy_from_user(&buf, argp, sizeof(buf)))
1090 ret = -EFAULT; 1069 ret = -EFAULT;
1091 else 1070 else
1092 ret = mtd_do_readoob(file, mtd, buf.start, 1071 ret = mtdchar_readoob(file, mtd, buf.start,
1093 buf.length, compat_ptr(buf.ptr), 1072 buf.length, compat_ptr(buf.ptr),
1094 &buf_user->start); 1073 &buf_user->start);
1095 break; 1074 break;
1096 } 1075 }
1097 default: 1076 default:
1098 ret = mtd_ioctl(file, cmd, (unsigned long)argp); 1077 ret = mtdchar_ioctl(file, cmd, (unsigned long)argp);
1099 } 1078 }
1100 1079
1101 mutex_unlock(&mtd_mutex); 1080 mutex_unlock(&mtd_mutex);
@@ -1111,7 +1090,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
1111 * mappings) 1090 * mappings)
1112 */ 1091 */
1113#ifndef CONFIG_MMU 1092#ifndef CONFIG_MMU
1114static unsigned long mtd_get_unmapped_area(struct file *file, 1093static unsigned long mtdchar_get_unmapped_area(struct file *file,
1115 unsigned long addr, 1094 unsigned long addr,
1116 unsigned long len, 1095 unsigned long len,
1117 unsigned long pgoff, 1096 unsigned long pgoff,
@@ -1119,32 +1098,28 @@ static unsigned long mtd_get_unmapped_area(struct file *file,
1119{ 1098{
1120 struct mtd_file_info *mfi = file->private_data; 1099 struct mtd_file_info *mfi = file->private_data;
1121 struct mtd_info *mtd = mfi->mtd; 1100 struct mtd_info *mtd = mfi->mtd;
1101 unsigned long offset;
1102 int ret;
1122 1103
1123 if (mtd->get_unmapped_area) { 1104 if (addr != 0)
1124 unsigned long offset; 1105 return (unsigned long) -EINVAL;
1125
1126 if (addr != 0)
1127 return (unsigned long) -EINVAL;
1128
1129 if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
1130 return (unsigned long) -EINVAL;
1131 1106
1132 offset = pgoff << PAGE_SHIFT; 1107 if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
1133 if (offset > mtd->size - len) 1108 return (unsigned long) -EINVAL;
1134 return (unsigned long) -EINVAL;
1135 1109
1136 return mtd->get_unmapped_area(mtd, len, offset, flags); 1110 offset = pgoff << PAGE_SHIFT;
1137 } 1111 if (offset > mtd->size - len)
1112 return (unsigned long) -EINVAL;
1138 1113
1139 /* can't map directly */ 1114 ret = mtd_get_unmapped_area(mtd, len, offset, flags);
1140 return (unsigned long) -ENOSYS; 1115 return ret == -EOPNOTSUPP ? -ENOSYS : ret;
1141} 1116}
1142#endif 1117#endif
1143 1118
1144/* 1119/*
1145 * set up a mapping for shared memory segments 1120 * set up a mapping for shared memory segments
1146 */ 1121 */
1147static int mtd_mmap(struct file *file, struct vm_area_struct *vma) 1122static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
1148{ 1123{
1149#ifdef CONFIG_MMU 1124#ifdef CONFIG_MMU
1150 struct mtd_file_info *mfi = file->private_data; 1125 struct mtd_file_info *mfi = file->private_data;
@@ -1185,18 +1160,18 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma)
1185 1160
1186static const struct file_operations mtd_fops = { 1161static const struct file_operations mtd_fops = {
1187 .owner = THIS_MODULE, 1162 .owner = THIS_MODULE,
1188 .llseek = mtd_lseek, 1163 .llseek = mtdchar_lseek,
1189 .read = mtd_read, 1164 .read = mtdchar_read,
1190 .write = mtd_write, 1165 .write = mtdchar_write,
1191 .unlocked_ioctl = mtd_unlocked_ioctl, 1166 .unlocked_ioctl = mtdchar_unlocked_ioctl,
1192#ifdef CONFIG_COMPAT 1167#ifdef CONFIG_COMPAT
1193 .compat_ioctl = mtd_compat_ioctl, 1168 .compat_ioctl = mtdchar_compat_ioctl,
1194#endif 1169#endif
1195 .open = mtd_open, 1170 .open = mtdchar_open,
1196 .release = mtd_close, 1171 .release = mtdchar_close,
1197 .mmap = mtd_mmap, 1172 .mmap = mtdchar_mmap,
1198#ifndef CONFIG_MMU 1173#ifndef CONFIG_MMU
1199 .get_unmapped_area = mtd_get_unmapped_area, 1174 .get_unmapped_area = mtdchar_get_unmapped_area,
1200#endif 1175#endif
1201}; 1176};
1202 1177
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 6df4d4d4eb9..1ed5103b219 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -91,7 +91,7 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
91 /* Entire transaction goes into this subdev */ 91 /* Entire transaction goes into this subdev */
92 size = len; 92 size = len;
93 93
94 err = subdev->read(subdev, from, size, &retsize, buf); 94 err = mtd_read(subdev, from, size, &retsize, buf);
95 95
96 /* Save information about bitflips! */ 96 /* Save information about bitflips! */
97 if (unlikely(err)) { 97 if (unlikely(err)) {
@@ -148,7 +148,7 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len,
148 if (!(subdev->flags & MTD_WRITEABLE)) 148 if (!(subdev->flags & MTD_WRITEABLE))
149 err = -EROFS; 149 err = -EROFS;
150 else 150 else
151 err = subdev->write(subdev, to, size, &retsize, buf); 151 err = mtd_write(subdev, to, size, &retsize, buf);
152 152
153 if (err) 153 if (err)
154 break; 154 break;
@@ -227,8 +227,9 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
227 if (!(subdev->flags & MTD_WRITEABLE)) 227 if (!(subdev->flags & MTD_WRITEABLE))
228 err = -EROFS; 228 err = -EROFS;
229 else 229 else
230 err = subdev->writev(subdev, &vecs_copy[entry_low], 230 err = mtd_writev(subdev, &vecs_copy[entry_low],
231 entry_high - entry_low + 1, to, &retsize); 231 entry_high - entry_low + 1, to,
232 &retsize);
232 233
233 vecs_copy[entry_high].iov_len = old_iov_len - size; 234 vecs_copy[entry_high].iov_len = old_iov_len - size;
234 vecs_copy[entry_high].iov_base += size; 235 vecs_copy[entry_high].iov_base += size;
@@ -273,7 +274,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
273 if (from + devops.len > subdev->size) 274 if (from + devops.len > subdev->size)
274 devops.len = subdev->size - from; 275 devops.len = subdev->size - from;
275 276
276 err = subdev->read_oob(subdev, from, &devops); 277 err = mtd_read_oob(subdev, from, &devops);
277 ops->retlen += devops.retlen; 278 ops->retlen += devops.retlen;
278 ops->oobretlen += devops.oobretlen; 279 ops->oobretlen += devops.oobretlen;
279 280
@@ -333,7 +334,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
333 if (to + devops.len > subdev->size) 334 if (to + devops.len > subdev->size)
334 devops.len = subdev->size - to; 335 devops.len = subdev->size - to;
335 336
336 err = subdev->write_oob(subdev, to, &devops); 337 err = mtd_write_oob(subdev, to, &devops);
337 ops->retlen += devops.oobretlen; 338 ops->retlen += devops.oobretlen;
338 if (err) 339 if (err)
339 return err; 340 return err;
@@ -379,7 +380,7 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
379 * FIXME: Allow INTERRUPTIBLE. Which means 380 * FIXME: Allow INTERRUPTIBLE. Which means
380 * not having the wait_queue head on the stack. 381 * not having the wait_queue head on the stack.
381 */ 382 */
382 err = mtd->erase(mtd, erase); 383 err = mtd_erase(mtd, erase);
383 if (!err) { 384 if (!err) {
384 set_current_state(TASK_UNINTERRUPTIBLE); 385 set_current_state(TASK_UNINTERRUPTIBLE);
385 add_wait_queue(&waitq, &wait); 386 add_wait_queue(&waitq, &wait);
@@ -554,12 +555,9 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
554 else 555 else
555 size = len; 556 size = len;
556 557
557 if (subdev->lock) { 558 err = mtd_lock(subdev, ofs, size);
558 err = subdev->lock(subdev, ofs, size); 559 if (err)
559 if (err) 560 break;
560 break;
561 } else
562 err = -EOPNOTSUPP;
563 561
564 len -= size; 562 len -= size;
565 if (len == 0) 563 if (len == 0)
@@ -594,12 +592,9 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
594 else 592 else
595 size = len; 593 size = len;
596 594
597 if (subdev->unlock) { 595 err = mtd_unlock(subdev, ofs, size);
598 err = subdev->unlock(subdev, ofs, size); 596 if (err)
599 if (err) 597 break;
600 break;
601 } else
602 err = -EOPNOTSUPP;
603 598
604 len -= size; 599 len -= size;
605 if (len == 0) 600 if (len == 0)
@@ -619,7 +614,7 @@ static void concat_sync(struct mtd_info *mtd)
619 614
620 for (i = 0; i < concat->num_subdev; i++) { 615 for (i = 0; i < concat->num_subdev; i++) {
621 struct mtd_info *subdev = concat->subdev[i]; 616 struct mtd_info *subdev = concat->subdev[i];
622 subdev->sync(subdev); 617 mtd_sync(subdev);
623 } 618 }
624} 619}
625 620
@@ -630,7 +625,7 @@ static int concat_suspend(struct mtd_info *mtd)
630 625
631 for (i = 0; i < concat->num_subdev; i++) { 626 for (i = 0; i < concat->num_subdev; i++) {
632 struct mtd_info *subdev = concat->subdev[i]; 627 struct mtd_info *subdev = concat->subdev[i];
633 if ((rc = subdev->suspend(subdev)) < 0) 628 if ((rc = mtd_suspend(subdev)) < 0)
634 return rc; 629 return rc;
635 } 630 }
636 return rc; 631 return rc;
@@ -643,7 +638,7 @@ static void concat_resume(struct mtd_info *mtd)
643 638
644 for (i = 0; i < concat->num_subdev; i++) { 639 for (i = 0; i < concat->num_subdev; i++) {
645 struct mtd_info *subdev = concat->subdev[i]; 640 struct mtd_info *subdev = concat->subdev[i];
646 subdev->resume(subdev); 641 mtd_resume(subdev);
647 } 642 }
648} 643}
649 644
@@ -652,7 +647,7 @@ static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
652 struct mtd_concat *concat = CONCAT(mtd); 647 struct mtd_concat *concat = CONCAT(mtd);
653 int i, res = 0; 648 int i, res = 0;
654 649
655 if (!concat->subdev[0]->block_isbad) 650 if (!mtd_can_have_bb(concat->subdev[0]))
656 return res; 651 return res;
657 652
658 if (ofs > mtd->size) 653 if (ofs > mtd->size)
@@ -666,7 +661,7 @@ static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
666 continue; 661 continue;
667 } 662 }
668 663
669 res = subdev->block_isbad(subdev, ofs); 664 res = mtd_block_isbad(subdev, ofs);
670 break; 665 break;
671 } 666 }
672 667
@@ -678,7 +673,7 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
678 struct mtd_concat *concat = CONCAT(mtd); 673 struct mtd_concat *concat = CONCAT(mtd);
679 int i, err = -EINVAL; 674 int i, err = -EINVAL;
680 675
681 if (!concat->subdev[0]->block_markbad) 676 if (!mtd_can_have_bb(concat->subdev[0]))
682 return 0; 677 return 0;
683 678
684 if (ofs > mtd->size) 679 if (ofs > mtd->size)
@@ -692,7 +687,7 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
692 continue; 687 continue;
693 } 688 }
694 689
695 err = subdev->block_markbad(subdev, ofs); 690 err = mtd_block_markbad(subdev, ofs);
696 if (!err) 691 if (!err)
697 mtd->ecc_stats.badblocks++; 692 mtd->ecc_stats.badblocks++;
698 break; 693 break;
@@ -725,11 +720,7 @@ static unsigned long concat_get_unmapped_area(struct mtd_info *mtd,
725 if (offset + len > subdev->size) 720 if (offset + len > subdev->size)
726 return (unsigned long) -EINVAL; 721 return (unsigned long) -EINVAL;
727 722
728 if (subdev->get_unmapped_area) 723 return mtd_get_unmapped_area(subdev, len, offset, flags);
729 return subdev->get_unmapped_area(subdev, len, offset,
730 flags);
731
732 break;
733 } 724 }
734 725
735 return (unsigned long) -ENOSYS; 726 return (unsigned long) -ENOSYS;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index b01993ea260..6ae9ca01388 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -107,7 +107,8 @@ static LIST_HEAD(mtd_notifiers);
107 */ 107 */
108static void mtd_release(struct device *dev) 108static void mtd_release(struct device *dev)
109{ 109{
110 dev_t index = MTD_DEVT(dev_to_mtd(dev)->index); 110 struct mtd_info *mtd = dev_get_drvdata(dev);
111 dev_t index = MTD_DEVT(mtd->index);
111 112
112 /* remove /dev/mtdXro node if needed */ 113 /* remove /dev/mtdXro node if needed */
113 if (index) 114 if (index)
@@ -116,27 +117,24 @@ static void mtd_release(struct device *dev)
116 117
117static int mtd_cls_suspend(struct device *dev, pm_message_t state) 118static int mtd_cls_suspend(struct device *dev, pm_message_t state)
118{ 119{
119 struct mtd_info *mtd = dev_to_mtd(dev); 120 struct mtd_info *mtd = dev_get_drvdata(dev);
120 121
121 if (mtd && mtd->suspend) 122 return mtd_suspend(mtd);
122 return mtd->suspend(mtd);
123 else
124 return 0;
125} 123}
126 124
127static int mtd_cls_resume(struct device *dev) 125static int mtd_cls_resume(struct device *dev)
128{ 126{
129 struct mtd_info *mtd = dev_to_mtd(dev); 127 struct mtd_info *mtd = dev_get_drvdata(dev);
130 128
131 if (mtd && mtd->resume) 129 if (mtd && mtd->resume)
132 mtd->resume(mtd); 130 mtd_resume(mtd);
133 return 0; 131 return 0;
134} 132}
135 133
136static ssize_t mtd_type_show(struct device *dev, 134static ssize_t mtd_type_show(struct device *dev,
137 struct device_attribute *attr, char *buf) 135 struct device_attribute *attr, char *buf)
138{ 136{
139 struct mtd_info *mtd = dev_to_mtd(dev); 137 struct mtd_info *mtd = dev_get_drvdata(dev);
140 char *type; 138 char *type;
141 139
142 switch (mtd->type) { 140 switch (mtd->type) {
@@ -172,7 +170,7 @@ static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL);
172static ssize_t mtd_flags_show(struct device *dev, 170static ssize_t mtd_flags_show(struct device *dev,
173 struct device_attribute *attr, char *buf) 171 struct device_attribute *attr, char *buf)
174{ 172{
175 struct mtd_info *mtd = dev_to_mtd(dev); 173 struct mtd_info *mtd = dev_get_drvdata(dev);
176 174
177 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags); 175 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
178 176
@@ -182,7 +180,7 @@ static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
182static ssize_t mtd_size_show(struct device *dev, 180static ssize_t mtd_size_show(struct device *dev,
183 struct device_attribute *attr, char *buf) 181 struct device_attribute *attr, char *buf)
184{ 182{
185 struct mtd_info *mtd = dev_to_mtd(dev); 183 struct mtd_info *mtd = dev_get_drvdata(dev);
186 184
187 return snprintf(buf, PAGE_SIZE, "%llu\n", 185 return snprintf(buf, PAGE_SIZE, "%llu\n",
188 (unsigned long long)mtd->size); 186 (unsigned long long)mtd->size);
@@ -193,7 +191,7 @@ static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
193static ssize_t mtd_erasesize_show(struct device *dev, 191static ssize_t mtd_erasesize_show(struct device *dev,
194 struct device_attribute *attr, char *buf) 192 struct device_attribute *attr, char *buf)
195{ 193{
196 struct mtd_info *mtd = dev_to_mtd(dev); 194 struct mtd_info *mtd = dev_get_drvdata(dev);
197 195
198 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize); 196 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
199 197
@@ -203,7 +201,7 @@ static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
203static ssize_t mtd_writesize_show(struct device *dev, 201static ssize_t mtd_writesize_show(struct device *dev,
204 struct device_attribute *attr, char *buf) 202 struct device_attribute *attr, char *buf)
205{ 203{
206 struct mtd_info *mtd = dev_to_mtd(dev); 204 struct mtd_info *mtd = dev_get_drvdata(dev);
207 205
208 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize); 206 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
209 207
@@ -213,7 +211,7 @@ static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
213static ssize_t mtd_subpagesize_show(struct device *dev, 211static ssize_t mtd_subpagesize_show(struct device *dev,
214 struct device_attribute *attr, char *buf) 212 struct device_attribute *attr, char *buf)
215{ 213{
216 struct mtd_info *mtd = dev_to_mtd(dev); 214 struct mtd_info *mtd = dev_get_drvdata(dev);
217 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; 215 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
218 216
219 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); 217 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
@@ -224,7 +222,7 @@ static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
224static ssize_t mtd_oobsize_show(struct device *dev, 222static ssize_t mtd_oobsize_show(struct device *dev,
225 struct device_attribute *attr, char *buf) 223 struct device_attribute *attr, char *buf)
226{ 224{
227 struct mtd_info *mtd = dev_to_mtd(dev); 225 struct mtd_info *mtd = dev_get_drvdata(dev);
228 226
229 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize); 227 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize);
230 228
@@ -234,7 +232,7 @@ static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
234static ssize_t mtd_numeraseregions_show(struct device *dev, 232static ssize_t mtd_numeraseregions_show(struct device *dev,
235 struct device_attribute *attr, char *buf) 233 struct device_attribute *attr, char *buf)
236{ 234{
237 struct mtd_info *mtd = dev_to_mtd(dev); 235 struct mtd_info *mtd = dev_get_drvdata(dev);
238 236
239 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions); 237 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
240 238
@@ -245,7 +243,7 @@ static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
245static ssize_t mtd_name_show(struct device *dev, 243static ssize_t mtd_name_show(struct device *dev,
246 struct device_attribute *attr, char *buf) 244 struct device_attribute *attr, char *buf)
247{ 245{
248 struct mtd_info *mtd = dev_to_mtd(dev); 246 struct mtd_info *mtd = dev_get_drvdata(dev);
249 247
250 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name); 248 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
251 249
@@ -338,9 +336,9 @@ int add_mtd_device(struct mtd_info *mtd)
338 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; 336 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
339 337
340 /* Some chips always power up locked. Unlock them now */ 338 /* Some chips always power up locked. Unlock them now */
341 if ((mtd->flags & MTD_WRITEABLE) 339 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) {
342 && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) { 340 error = mtd_unlock(mtd, 0, mtd->size);
343 if (mtd->unlock(mtd, 0, mtd->size)) 341 if (error && error != -EOPNOTSUPP)
344 printk(KERN_WARNING 342 printk(KERN_WARNING
345 "%s: unlock failed, writes may not work\n", 343 "%s: unlock failed, writes may not work\n",
346 mtd->name); 344 mtd->name);
@@ -516,7 +514,6 @@ EXPORT_SYMBOL_GPL(mtd_device_unregister);
516 * or removal of MTD devices. Causes the 'add' callback to be immediately 514 * or removal of MTD devices. Causes the 'add' callback to be immediately
517 * invoked for each MTD device currently present in the system. 515 * invoked for each MTD device currently present in the system.
518 */ 516 */
519
520void register_mtd_user (struct mtd_notifier *new) 517void register_mtd_user (struct mtd_notifier *new)
521{ 518{
522 struct mtd_info *mtd; 519 struct mtd_info *mtd;
@@ -532,6 +529,7 @@ void register_mtd_user (struct mtd_notifier *new)
532 529
533 mutex_unlock(&mtd_table_mutex); 530 mutex_unlock(&mtd_table_mutex);
534} 531}
532EXPORT_SYMBOL_GPL(register_mtd_user);
535 533
536/** 534/**
537 * unregister_mtd_user - unregister a 'user' of MTD devices. 535 * unregister_mtd_user - unregister a 'user' of MTD devices.
@@ -542,7 +540,6 @@ void register_mtd_user (struct mtd_notifier *new)
542 * 'remove' callback to be immediately invoked for each MTD device 540 * 'remove' callback to be immediately invoked for each MTD device
543 * currently present in the system. 541 * currently present in the system.
544 */ 542 */
545
546int unregister_mtd_user (struct mtd_notifier *old) 543int unregister_mtd_user (struct mtd_notifier *old)
547{ 544{
548 struct mtd_info *mtd; 545 struct mtd_info *mtd;
@@ -558,7 +555,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
558 mutex_unlock(&mtd_table_mutex); 555 mutex_unlock(&mtd_table_mutex);
559 return 0; 556 return 0;
560} 557}
561 558EXPORT_SYMBOL_GPL(unregister_mtd_user);
562 559
563/** 560/**
564 * get_mtd_device - obtain a validated handle for an MTD device 561 * get_mtd_device - obtain a validated handle for an MTD device
@@ -571,7 +568,6 @@ int unregister_mtd_user (struct mtd_notifier *old)
571 * both, return the num'th driver only if its address matches. Return 568 * both, return the num'th driver only if its address matches. Return
572 * error code if not. 569 * error code if not.
573 */ 570 */
574
575struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 571struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
576{ 572{
577 struct mtd_info *ret = NULL, *other; 573 struct mtd_info *ret = NULL, *other;
@@ -604,6 +600,7 @@ out:
604 mutex_unlock(&mtd_table_mutex); 600 mutex_unlock(&mtd_table_mutex);
605 return ret; 601 return ret;
606} 602}
603EXPORT_SYMBOL_GPL(get_mtd_device);
607 604
608 605
609int __get_mtd_device(struct mtd_info *mtd) 606int __get_mtd_device(struct mtd_info *mtd)
@@ -624,6 +621,7 @@ int __get_mtd_device(struct mtd_info *mtd)
624 mtd->usecount++; 621 mtd->usecount++;
625 return 0; 622 return 0;
626} 623}
624EXPORT_SYMBOL_GPL(__get_mtd_device);
627 625
628/** 626/**
629 * get_mtd_device_nm - obtain a validated handle for an MTD device by 627 * get_mtd_device_nm - obtain a validated handle for an MTD device by
@@ -633,7 +631,6 @@ int __get_mtd_device(struct mtd_info *mtd)
633 * This function returns MTD device description structure in case of 631 * This function returns MTD device description structure in case of
634 * success and an error code in case of failure. 632 * success and an error code in case of failure.
635 */ 633 */
636
637struct mtd_info *get_mtd_device_nm(const char *name) 634struct mtd_info *get_mtd_device_nm(const char *name)
638{ 635{
639 int err = -ENODEV; 636 int err = -ENODEV;
@@ -662,6 +659,7 @@ out_unlock:
662 mutex_unlock(&mtd_table_mutex); 659 mutex_unlock(&mtd_table_mutex);
663 return ERR_PTR(err); 660 return ERR_PTR(err);
664} 661}
662EXPORT_SYMBOL_GPL(get_mtd_device_nm);
665 663
666void put_mtd_device(struct mtd_info *mtd) 664void put_mtd_device(struct mtd_info *mtd)
667{ 665{
@@ -670,6 +668,7 @@ void put_mtd_device(struct mtd_info *mtd)
670 mutex_unlock(&mtd_table_mutex); 668 mutex_unlock(&mtd_table_mutex);
671 669
672} 670}
671EXPORT_SYMBOL_GPL(put_mtd_device);
673 672
674void __put_mtd_device(struct mtd_info *mtd) 673void __put_mtd_device(struct mtd_info *mtd)
675{ 674{
@@ -681,39 +680,65 @@ void __put_mtd_device(struct mtd_info *mtd)
681 680
682 module_put(mtd->owner); 681 module_put(mtd->owner);
683} 682}
683EXPORT_SYMBOL_GPL(__put_mtd_device);
684 684
685/* default_mtd_writev - default mtd writev method for MTD devices that 685/*
686 * don't implement their own 686 * default_mtd_writev - the default writev method
687 * @mtd: mtd device description object pointer
688 * @vecs: the vectors to write
689 * @count: count of vectors in @vecs
690 * @to: the MTD device offset to write to
691 * @retlen: on exit contains the count of bytes written to the MTD device.
692 *
693 * This function returns zero in case of success and a negative error code in
694 * case of failure.
687 */ 695 */
688 696static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
689int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 697 unsigned long count, loff_t to, size_t *retlen)
690 unsigned long count, loff_t to, size_t *retlen)
691{ 698{
692 unsigned long i; 699 unsigned long i;
693 size_t totlen = 0, thislen; 700 size_t totlen = 0, thislen;
694 int ret = 0; 701 int ret = 0;
695 702
696 if(!mtd->write) { 703 for (i = 0; i < count; i++) {
697 ret = -EROFS; 704 if (!vecs[i].iov_len)
698 } else { 705 continue;
699 for (i=0; i<count; i++) { 706 ret = mtd_write(mtd, to, vecs[i].iov_len, &thislen,
700 if (!vecs[i].iov_len) 707 vecs[i].iov_base);
701 continue; 708 totlen += thislen;
702 ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); 709 if (ret || thislen != vecs[i].iov_len)
703 totlen += thislen; 710 break;
704 if (ret || thislen != vecs[i].iov_len) 711 to += vecs[i].iov_len;
705 break;
706 to += vecs[i].iov_len;
707 }
708 } 712 }
709 if (retlen) 713 *retlen = totlen;
710 *retlen = totlen;
711 return ret; 714 return ret;
712} 715}
713 716
717/*
718 * mtd_writev - the vector-based MTD write method
719 * @mtd: mtd device description object pointer
720 * @vecs: the vectors to write
721 * @count: count of vectors in @vecs
722 * @to: the MTD device offset to write to
723 * @retlen: on exit contains the count of bytes written to the MTD device.
724 *
725 * This function returns zero in case of success and a negative error code in
726 * case of failure.
727 */
728int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
729 unsigned long count, loff_t to, size_t *retlen)
730{
731 *retlen = 0;
732 if (!mtd->writev)
733 return default_mtd_writev(mtd, vecs, count, to, retlen);
734 return mtd->writev(mtd, vecs, count, to, retlen);
735}
736EXPORT_SYMBOL_GPL(mtd_writev);
737
714/** 738/**
715 * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size 739 * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size
716 * @size: A pointer to the ideal or maximum size of the allocation. Points 740 * @mtd: mtd device description object pointer
741 * @size: a pointer to the ideal or maximum size of the allocation, points
717 * to the actual allocation size on success. 742 * to the actual allocation size on success.
718 * 743 *
719 * This routine attempts to allocate a contiguous kernel buffer up to 744 * This routine attempts to allocate a contiguous kernel buffer up to
@@ -758,15 +783,6 @@ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
758 */ 783 */
759 return kmalloc(*size, GFP_KERNEL); 784 return kmalloc(*size, GFP_KERNEL);
760} 785}
761
762EXPORT_SYMBOL_GPL(get_mtd_device);
763EXPORT_SYMBOL_GPL(get_mtd_device_nm);
764EXPORT_SYMBOL_GPL(__get_mtd_device);
765EXPORT_SYMBOL_GPL(put_mtd_device);
766EXPORT_SYMBOL_GPL(__put_mtd_device);
767EXPORT_SYMBOL_GPL(register_mtd_user);
768EXPORT_SYMBOL_GPL(unregister_mtd_user);
769EXPORT_SYMBOL_GPL(default_mtd_writev);
770EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to); 786EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
771 787
772#ifdef CONFIG_PROC_FS 788#ifdef CONFIG_PROC_FS
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index 1e2fa623670..db8e8272d69 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -112,7 +112,7 @@ static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
112 set_current_state(TASK_INTERRUPTIBLE); 112 set_current_state(TASK_INTERRUPTIBLE);
113 add_wait_queue(&wait_q, &wait); 113 add_wait_queue(&wait_q, &wait);
114 114
115 ret = mtd->erase(mtd, &erase); 115 ret = mtd_erase(mtd, &erase);
116 if (ret) { 116 if (ret) {
117 set_current_state(TASK_RUNNING); 117 set_current_state(TASK_RUNNING);
118 remove_wait_queue(&wait_q, &wait); 118 remove_wait_queue(&wait_q, &wait);
@@ -169,8 +169,8 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
169 cxt->nextpage = 0; 169 cxt->nextpage = 0;
170 } 170 }
171 171
172 while (mtd->block_isbad) { 172 while (mtd_can_have_bb(mtd)) {
173 ret = mtd->block_isbad(mtd, cxt->nextpage * record_size); 173 ret = mtd_block_isbad(mtd, cxt->nextpage * record_size);
174 if (!ret) 174 if (!ret)
175 break; 175 break;
176 if (ret < 0) { 176 if (ret < 0) {
@@ -199,8 +199,8 @@ badblock:
199 return; 199 return;
200 } 200 }
201 201
202 if (mtd->block_markbad && ret == -EIO) { 202 if (mtd_can_have_bb(mtd) && ret == -EIO) {
203 ret = mtd->block_markbad(mtd, cxt->nextpage * record_size); 203 ret = mtd_block_markbad(mtd, cxt->nextpage * record_size);
204 if (ret < 0) { 204 if (ret < 0) {
205 printk(KERN_ERR "mtdoops: block_markbad failed, aborting\n"); 205 printk(KERN_ERR "mtdoops: block_markbad failed, aborting\n");
206 return; 206 return;
@@ -221,12 +221,16 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic)
221 hdr[0] = cxt->nextcount; 221 hdr[0] = cxt->nextcount;
222 hdr[1] = MTDOOPS_KERNMSG_MAGIC; 222 hdr[1] = MTDOOPS_KERNMSG_MAGIC;
223 223
224 if (panic) 224 if (panic) {
225 ret = mtd->panic_write(mtd, cxt->nextpage * record_size, 225 ret = mtd_panic_write(mtd, cxt->nextpage * record_size,
226 record_size, &retlen, cxt->oops_buf); 226 record_size, &retlen, cxt->oops_buf);
227 else 227 if (ret == -EOPNOTSUPP) {
228 ret = mtd->write(mtd, cxt->nextpage * record_size, 228 printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
229 record_size, &retlen, cxt->oops_buf); 229 return;
230 }
231 } else
232 ret = mtd_write(mtd, cxt->nextpage * record_size,
233 record_size, &retlen, cxt->oops_buf);
230 234
231 if (retlen != record_size || ret < 0) 235 if (retlen != record_size || ret < 0)
232 printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n", 236 printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n",
@@ -253,10 +257,13 @@ static void find_next_position(struct mtdoops_context *cxt)
253 size_t retlen; 257 size_t retlen;
254 258
255 for (page = 0; page < cxt->oops_pages; page++) { 259 for (page = 0; page < cxt->oops_pages; page++) {
260 if (mtd_can_have_bb(mtd) &&
261 mtd_block_isbad(mtd, page * record_size))
262 continue;
256 /* Assume the page is used */ 263 /* Assume the page is used */
257 mark_page_used(cxt, page); 264 mark_page_used(cxt, page);
258 ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE, 265 ret = mtd_read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
259 &retlen, (u_char *) &count[0]); 266 &retlen, (u_char *)&count[0]);
260 if (retlen != MTDOOPS_HEADER_SIZE || 267 if (retlen != MTDOOPS_HEADER_SIZE ||
261 (ret < 0 && !mtd_is_bitflip(ret))) { 268 (ret < 0 && !mtd_is_bitflip(ret))) {
262 printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n", 269 printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
@@ -327,13 +334,8 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper,
327 memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); 334 memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
328 335
329 /* Panics must be written immediately */ 336 /* Panics must be written immediately */
330 if (reason != KMSG_DUMP_OOPS) { 337 if (reason != KMSG_DUMP_OOPS)
331 if (!cxt->mtd->panic_write) 338 mtdoops_write(cxt, 1);
332 printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
333 else
334 mtdoops_write(cxt, 1);
335 return;
336 }
337 339
338 /* For other cases, schedule work to write it "nicely" */ 340 /* For other cases, schedule work to write it "nicely" */
339 schedule_work(&cxt->work_write); 341 schedule_work(&cxt->work_write);
@@ -369,7 +371,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
369 371
370 /* oops_page_used is a bit field */ 372 /* oops_page_used is a bit field */
371 cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages, 373 cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages,
372 BITS_PER_LONG)); 374 BITS_PER_LONG) * sizeof(unsigned long));
373 if (!cxt->oops_page_used) { 375 if (!cxt->oops_page_used) {
374 printk(KERN_ERR "mtdoops: could not allocate page array\n"); 376 printk(KERN_ERR "mtdoops: could not allocate page array\n");
375 return; 377 return;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index a0bd2de4752..a3d44c3416b 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -70,8 +70,7 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
70 len = 0; 70 len = 0;
71 else if (from + len > mtd->size) 71 else if (from + len > mtd->size)
72 len = mtd->size - from; 72 len = mtd->size - from;
73 res = part->master->read(part->master, from + part->offset, 73 res = mtd_read(part->master, from + part->offset, len, retlen, buf);
74 len, retlen, buf);
75 if (unlikely(res)) { 74 if (unlikely(res)) {
76 if (mtd_is_bitflip(res)) 75 if (mtd_is_bitflip(res))
77 mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; 76 mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
@@ -89,15 +88,15 @@ static int part_point(struct mtd_info *mtd, loff_t from, size_t len,
89 len = 0; 88 len = 0;
90 else if (from + len > mtd->size) 89 else if (from + len > mtd->size)
91 len = mtd->size - from; 90 len = mtd->size - from;
92 return part->master->point (part->master, from + part->offset, 91 return mtd_point(part->master, from + part->offset, len, retlen,
93 len, retlen, virt, phys); 92 virt, phys);
94} 93}
95 94
96static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 95static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
97{ 96{
98 struct mtd_part *part = PART(mtd); 97 struct mtd_part *part = PART(mtd);
99 98
100 part->master->unpoint(part->master, from + part->offset, len); 99 mtd_unpoint(part->master, from + part->offset, len);
101} 100}
102 101
103static unsigned long part_get_unmapped_area(struct mtd_info *mtd, 102static unsigned long part_get_unmapped_area(struct mtd_info *mtd,
@@ -108,8 +107,7 @@ static unsigned long part_get_unmapped_area(struct mtd_info *mtd,
108 struct mtd_part *part = PART(mtd); 107 struct mtd_part *part = PART(mtd);
109 108
110 offset += part->offset; 109 offset += part->offset;
111 return part->master->get_unmapped_area(part->master, len, offset, 110 return mtd_get_unmapped_area(part->master, len, offset, flags);
112 flags);
113} 111}
114 112
115static int part_read_oob(struct mtd_info *mtd, loff_t from, 113static int part_read_oob(struct mtd_info *mtd, loff_t from,
@@ -140,7 +138,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
140 return -EINVAL; 138 return -EINVAL;
141 } 139 }
142 140
143 res = part->master->read_oob(part->master, from + part->offset, ops); 141 res = mtd_read_oob(part->master, from + part->offset, ops);
144 if (unlikely(res)) { 142 if (unlikely(res)) {
145 if (mtd_is_bitflip(res)) 143 if (mtd_is_bitflip(res))
146 mtd->ecc_stats.corrected++; 144 mtd->ecc_stats.corrected++;
@@ -154,30 +152,28 @@ static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
154 size_t len, size_t *retlen, u_char *buf) 152 size_t len, size_t *retlen, u_char *buf)
155{ 153{
156 struct mtd_part *part = PART(mtd); 154 struct mtd_part *part = PART(mtd);
157 return part->master->read_user_prot_reg(part->master, from, 155 return mtd_read_user_prot_reg(part->master, from, len, retlen, buf);
158 len, retlen, buf);
159} 156}
160 157
161static int part_get_user_prot_info(struct mtd_info *mtd, 158static int part_get_user_prot_info(struct mtd_info *mtd,
162 struct otp_info *buf, size_t len) 159 struct otp_info *buf, size_t len)
163{ 160{
164 struct mtd_part *part = PART(mtd); 161 struct mtd_part *part = PART(mtd);
165 return part->master->get_user_prot_info(part->master, buf, len); 162 return mtd_get_user_prot_info(part->master, buf, len);
166} 163}
167 164
168static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, 165static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
169 size_t len, size_t *retlen, u_char *buf) 166 size_t len, size_t *retlen, u_char *buf)
170{ 167{
171 struct mtd_part *part = PART(mtd); 168 struct mtd_part *part = PART(mtd);
172 return part->master->read_fact_prot_reg(part->master, from, 169 return mtd_read_fact_prot_reg(part->master, from, len, retlen, buf);
173 len, retlen, buf);
174} 170}
175 171
176static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, 172static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,
177 size_t len) 173 size_t len)
178{ 174{
179 struct mtd_part *part = PART(mtd); 175 struct mtd_part *part = PART(mtd);
180 return part->master->get_fact_prot_info(part->master, buf, len); 176 return mtd_get_fact_prot_info(part->master, buf, len);
181} 177}
182 178
183static int part_write(struct mtd_info *mtd, loff_t to, size_t len, 179static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
@@ -190,8 +186,7 @@ static int part_write(struct mtd_info *mtd, loff_t to, size_t len,
190 len = 0; 186 len = 0;
191 else if (to + len > mtd->size) 187 else if (to + len > mtd->size)
192 len = mtd->size - to; 188 len = mtd->size - to;
193 return part->master->write(part->master, to + part->offset, 189 return mtd_write(part->master, to + part->offset, len, retlen, buf);
194 len, retlen, buf);
195} 190}
196 191
197static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len, 192static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
@@ -204,8 +199,8 @@ static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
204 len = 0; 199 len = 0;
205 else if (to + len > mtd->size) 200 else if (to + len > mtd->size)
206 len = mtd->size - to; 201 len = mtd->size - to;
207 return part->master->panic_write(part->master, to + part->offset, 202 return mtd_panic_write(part->master, to + part->offset, len, retlen,
208 len, retlen, buf); 203 buf);
209} 204}
210 205
211static int part_write_oob(struct mtd_info *mtd, loff_t to, 206static int part_write_oob(struct mtd_info *mtd, loff_t to,
@@ -220,22 +215,21 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
220 return -EINVAL; 215 return -EINVAL;
221 if (ops->datbuf && to + ops->len > mtd->size) 216 if (ops->datbuf && to + ops->len > mtd->size)
222 return -EINVAL; 217 return -EINVAL;
223 return part->master->write_oob(part->master, to + part->offset, ops); 218 return mtd_write_oob(part->master, to + part->offset, ops);
224} 219}
225 220
226static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, 221static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
227 size_t len, size_t *retlen, u_char *buf) 222 size_t len, size_t *retlen, u_char *buf)
228{ 223{
229 struct mtd_part *part = PART(mtd); 224 struct mtd_part *part = PART(mtd);
230 return part->master->write_user_prot_reg(part->master, from, 225 return mtd_write_user_prot_reg(part->master, from, len, retlen, buf);
231 len, retlen, buf);
232} 226}
233 227
234static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, 228static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
235 size_t len) 229 size_t len)
236{ 230{
237 struct mtd_part *part = PART(mtd); 231 struct mtd_part *part = PART(mtd);
238 return part->master->lock_user_prot_reg(part->master, from, len); 232 return mtd_lock_user_prot_reg(part->master, from, len);
239} 233}
240 234
241static int part_writev(struct mtd_info *mtd, const struct kvec *vecs, 235static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
@@ -244,8 +238,8 @@ static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
244 struct mtd_part *part = PART(mtd); 238 struct mtd_part *part = PART(mtd);
245 if (!(mtd->flags & MTD_WRITEABLE)) 239 if (!(mtd->flags & MTD_WRITEABLE))
246 return -EROFS; 240 return -EROFS;
247 return part->master->writev(part->master, vecs, count, 241 return mtd_writev(part->master, vecs, count, to + part->offset,
248 to + part->offset, retlen); 242 retlen);
249} 243}
250 244
251static int part_erase(struct mtd_info *mtd, struct erase_info *instr) 245static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
@@ -257,7 +251,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
257 if (instr->addr >= mtd->size) 251 if (instr->addr >= mtd->size)
258 return -EINVAL; 252 return -EINVAL;
259 instr->addr += part->offset; 253 instr->addr += part->offset;
260 ret = part->master->erase(part->master, instr); 254 ret = mtd_erase(part->master, instr);
261 if (ret) { 255 if (ret) {
262 if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) 256 if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
263 instr->fail_addr -= part->offset; 257 instr->fail_addr -= part->offset;
@@ -285,7 +279,7 @@ static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
285 struct mtd_part *part = PART(mtd); 279 struct mtd_part *part = PART(mtd);
286 if ((len + ofs) > mtd->size) 280 if ((len + ofs) > mtd->size)
287 return -EINVAL; 281 return -EINVAL;
288 return part->master->lock(part->master, ofs + part->offset, len); 282 return mtd_lock(part->master, ofs + part->offset, len);
289} 283}
290 284
291static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 285static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
@@ -293,7 +287,7 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
293 struct mtd_part *part = PART(mtd); 287 struct mtd_part *part = PART(mtd);
294 if ((len + ofs) > mtd->size) 288 if ((len + ofs) > mtd->size)
295 return -EINVAL; 289 return -EINVAL;
296 return part->master->unlock(part->master, ofs + part->offset, len); 290 return mtd_unlock(part->master, ofs + part->offset, len);
297} 291}
298 292
299static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) 293static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
@@ -301,25 +295,25 @@ static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
301 struct mtd_part *part = PART(mtd); 295 struct mtd_part *part = PART(mtd);
302 if ((len + ofs) > mtd->size) 296 if ((len + ofs) > mtd->size)
303 return -EINVAL; 297 return -EINVAL;
304 return part->master->is_locked(part->master, ofs + part->offset, len); 298 return mtd_is_locked(part->master, ofs + part->offset, len);
305} 299}
306 300
307static void part_sync(struct mtd_info *mtd) 301static void part_sync(struct mtd_info *mtd)
308{ 302{
309 struct mtd_part *part = PART(mtd); 303 struct mtd_part *part = PART(mtd);
310 part->master->sync(part->master); 304 mtd_sync(part->master);
311} 305}
312 306
313static int part_suspend(struct mtd_info *mtd) 307static int part_suspend(struct mtd_info *mtd)
314{ 308{
315 struct mtd_part *part = PART(mtd); 309 struct mtd_part *part = PART(mtd);
316 return part->master->suspend(part->master); 310 return mtd_suspend(part->master);
317} 311}
318 312
319static void part_resume(struct mtd_info *mtd) 313static void part_resume(struct mtd_info *mtd)
320{ 314{
321 struct mtd_part *part = PART(mtd); 315 struct mtd_part *part = PART(mtd);
322 part->master->resume(part->master); 316 mtd_resume(part->master);
323} 317}
324 318
325static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) 319static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
@@ -328,7 +322,7 @@ static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
328 if (ofs >= mtd->size) 322 if (ofs >= mtd->size)
329 return -EINVAL; 323 return -EINVAL;
330 ofs += part->offset; 324 ofs += part->offset;
331 return part->master->block_isbad(part->master, ofs); 325 return mtd_block_isbad(part->master, ofs);
332} 326}
333 327
334static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) 328static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
@@ -341,7 +335,7 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
341 if (ofs >= mtd->size) 335 if (ofs >= mtd->size)
342 return -EINVAL; 336 return -EINVAL;
343 ofs += part->offset; 337 ofs += part->offset;
344 res = part->master->block_markbad(part->master, ofs); 338 res = mtd_block_markbad(part->master, ofs);
345 if (!res) 339 if (!res)
346 mtd->ecc_stats.badblocks++; 340 mtd->ecc_stats.badblocks++;
347 return res; 341 return res;
@@ -559,8 +553,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
559 uint64_t offs = 0; 553 uint64_t offs = 0;
560 554
561 while (offs < slave->mtd.size) { 555 while (offs < slave->mtd.size) {
562 if (master->block_isbad(master, 556 if (mtd_block_isbad(master, offs + slave->offset))
563 offs + slave->offset))
564 slave->mtd.ecc_stats.badblocks++; 557 slave->mtd.ecc_stats.badblocks++;
565 offs += slave->mtd.erasesize; 558 offs += slave->mtd.erasesize;
566 } 559 }
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c
index bd9590c723e..c92f0f6bc13 100644
--- a/drivers/mtd/mtdswap.c
+++ b/drivers/mtd/mtdswap.c
@@ -274,12 +274,12 @@ static int mtdswap_handle_badblock(struct mtdswap_dev *d, struct swap_eb *eb)
274 eb->root = NULL; 274 eb->root = NULL;
275 275
276 /* badblocks not supported */ 276 /* badblocks not supported */
277 if (!d->mtd->block_markbad) 277 if (!mtd_can_have_bb(d->mtd))
278 return 1; 278 return 1;
279 279
280 offset = mtdswap_eb_offset(d, eb); 280 offset = mtdswap_eb_offset(d, eb);
281 dev_warn(d->dev, "Marking bad block at %08llx\n", offset); 281 dev_warn(d->dev, "Marking bad block at %08llx\n", offset);
282 ret = d->mtd->block_markbad(d->mtd, offset); 282 ret = mtd_block_markbad(d->mtd, offset);
283 283
284 if (ret) { 284 if (ret) {
285 dev_warn(d->dev, "Mark block bad failed for block at %08llx " 285 dev_warn(d->dev, "Mark block bad failed for block at %08llx "
@@ -312,7 +312,7 @@ static int mtdswap_handle_write_error(struct mtdswap_dev *d, struct swap_eb *eb)
312static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from, 312static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from,
313 struct mtd_oob_ops *ops) 313 struct mtd_oob_ops *ops)
314{ 314{
315 int ret = d->mtd->read_oob(d->mtd, from, ops); 315 int ret = mtd_read_oob(d->mtd, from, ops);
316 316
317 if (mtd_is_bitflip(ret)) 317 if (mtd_is_bitflip(ret))
318 return ret; 318 return ret;
@@ -343,7 +343,7 @@ static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)
343 offset = mtdswap_eb_offset(d, eb); 343 offset = mtdswap_eb_offset(d, eb);
344 344
345 /* Check first if the block is bad. */ 345 /* Check first if the block is bad. */
346 if (d->mtd->block_isbad && d->mtd->block_isbad(d->mtd, offset)) 346 if (mtd_can_have_bb(d->mtd) && mtd_block_isbad(d->mtd, offset))
347 return MTDSWAP_SCANNED_BAD; 347 return MTDSWAP_SCANNED_BAD;
348 348
349 ops.ooblen = 2 * d->mtd->ecclayout->oobavail; 349 ops.ooblen = 2 * d->mtd->ecclayout->oobavail;
@@ -403,7 +403,7 @@ static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,
403 offset = mtdswap_eb_offset(d, eb) + d->mtd->writesize; 403 offset = mtdswap_eb_offset(d, eb) + d->mtd->writesize;
404 } 404 }
405 405
406 ret = d->mtd->write_oob(d->mtd, offset , &ops); 406 ret = mtd_write_oob(d->mtd, offset, &ops);
407 407
408 if (ret) { 408 if (ret) {
409 dev_warn(d->dev, "Write OOB failed for block at %08llx " 409 dev_warn(d->dev, "Write OOB failed for block at %08llx "
@@ -567,7 +567,7 @@ retry:
567 erase.len = mtd->erasesize; 567 erase.len = mtd->erasesize;
568 erase.priv = (u_long)&wq; 568 erase.priv = (u_long)&wq;
569 569
570 ret = mtd->erase(mtd, &erase); 570 ret = mtd_erase(mtd, &erase);
571 if (ret) { 571 if (ret) {
572 if (retries++ < MTDSWAP_ERASE_RETRIES) { 572 if (retries++ < MTDSWAP_ERASE_RETRIES) {
573 dev_warn(d->dev, 573 dev_warn(d->dev,
@@ -689,7 +689,7 @@ retry:
689 return ret; 689 return ret;
690 690
691 writepos = (loff_t)*bp << PAGE_SHIFT; 691 writepos = (loff_t)*bp << PAGE_SHIFT;
692 ret = mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf); 692 ret = mtd_write(mtd, writepos, PAGE_SIZE, &retlen, buf);
693 if (ret == -EIO || mtd_is_eccerr(ret)) { 693 if (ret == -EIO || mtd_is_eccerr(ret)) {
694 d->curr_write_pos--; 694 d->curr_write_pos--;
695 eb->active_count--; 695 eb->active_count--;
@@ -736,7 +736,7 @@ static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock,
736 retries = 0; 736 retries = 0;
737 737
738retry: 738retry:
739 ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf); 739 ret = mtd_read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf);
740 740
741 if (ret < 0 && !mtd_is_bitflip(ret)) { 741 if (ret < 0 && !mtd_is_bitflip(ret)) {
742 oldeb = d->eb_data + oldblock / d->pages_per_eblk; 742 oldeb = d->eb_data + oldblock / d->pages_per_eblk;
@@ -946,7 +946,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d,
946 patt = mtdswap_test_patt(test + i); 946 patt = mtdswap_test_patt(test + i);
947 memset(d->page_buf, patt, mtd->writesize); 947 memset(d->page_buf, patt, mtd->writesize);
948 memset(d->oob_buf, patt, mtd->ecclayout->oobavail); 948 memset(d->oob_buf, patt, mtd->ecclayout->oobavail);
949 ret = mtd->write_oob(mtd, pos, &ops); 949 ret = mtd_write_oob(mtd, pos, &ops);
950 if (ret) 950 if (ret)
951 goto error; 951 goto error;
952 952
@@ -955,7 +955,7 @@ static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d,
955 955
956 pos = base; 956 pos = base;
957 for (i = 0; i < mtd_pages; i++) { 957 for (i = 0; i < mtd_pages; i++) {
958 ret = mtd->read_oob(mtd, pos, &ops); 958 ret = mtd_read_oob(mtd, pos, &ops);
959 if (ret) 959 if (ret)
960 goto error; 960 goto error;
961 961
@@ -1047,8 +1047,7 @@ static int mtdswap_flush(struct mtd_blktrans_dev *dev)
1047{ 1047{
1048 struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev); 1048 struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
1049 1049
1050 if (d->mtd->sync) 1050 mtd_sync(d->mtd);
1051 d->mtd->sync(d->mtd);
1052 return 0; 1051 return 0;
1053} 1052}
1054 1053
@@ -1059,9 +1058,9 @@ static unsigned int mtdswap_badblocks(struct mtd_info *mtd, uint64_t size)
1059 1058
1060 badcnt = 0; 1059 badcnt = 0;
1061 1060
1062 if (mtd->block_isbad) 1061 if (mtd_can_have_bb(mtd))
1063 for (offset = 0; offset < size; offset += mtd->erasesize) 1062 for (offset = 0; offset < size; offset += mtd->erasesize)
1064 if (mtd->block_isbad(mtd, offset)) 1063 if (mtd_block_isbad(mtd, offset))
1065 badcnt++; 1064 badcnt++;
1066 1065
1067 return badcnt; 1066 return badcnt;
@@ -1161,7 +1160,7 @@ static int mtdswap_readsect(struct mtd_blktrans_dev *dev,
1161 retries = 0; 1160 retries = 0;
1162 1161
1163retry: 1162retry:
1164 ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf); 1163 ret = mtd_read(mtd, readpos, PAGE_SIZE, &retlen, buf);
1165 1164
1166 d->mtd_read_count++; 1165 d->mtd_read_count++;
1167 if (mtd_is_bitflip(ret)) { 1166 if (mtd_is_bitflip(ret)) {
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index dd0279249bf..31b034b7eba 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -110,7 +110,7 @@ config MTD_NAND_AMS_DELTA
110 110
111config MTD_NAND_OMAP2 111config MTD_NAND_OMAP2
112 tristate "NAND Flash device on OMAP2, OMAP3 and OMAP4" 112 tristate "NAND Flash device on OMAP2, OMAP3 and OMAP4"
113 depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4) 113 depends on ARCH_OMAP2PLUS
114 help 114 help
115 Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 115 Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4
116 platforms. 116 platforms.
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 9e6b498c9be..3197e9764fc 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -280,17 +280,7 @@ static struct platform_driver ams_delta_nand_driver = {
280 }, 280 },
281}; 281};
282 282
283static int __init ams_delta_nand_init(void) 283module_platform_driver(ams_delta_nand_driver);
284{
285 return platform_driver_register(&ams_delta_nand_driver);
286}
287module_init(ams_delta_nand_init);
288
289static void __exit ams_delta_nand_exit(void)
290{
291 platform_driver_unregister(&ams_delta_nand_driver);
292}
293module_exit(ams_delta_nand_exit);
294 284
295MODULE_LICENSE("GPL"); 285MODULE_LICENSE("GPL");
296MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); 286MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index 46b58d67284..50387fd4009 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -546,18 +546,7 @@ static struct platform_driver nand_driver = {
546 .resume = bcm_umi_nand_resume, 546 .resume = bcm_umi_nand_resume,
547}; 547};
548 548
549static int __init nand_init(void) 549module_platform_driver(nand_driver);
550{
551 return platform_driver_register(&nand_driver);
552}
553
554static void __exit nand_exit(void)
555{
556 platform_driver_unregister(&nand_driver);
557}
558
559module_init(nand_init);
560module_exit(nand_exit);
561 550
562MODULE_LICENSE("GPL"); 551MODULE_LICENSE("GPL");
563MODULE_AUTHOR("Broadcom"); 552MODULE_AUTHOR("Broadcom");
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index c153e1f77f9..6e566156956 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -675,7 +675,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
675 675
676 davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val); 676 davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
677 677
678 ret = davinci_aemif_setup_timing(info->timing, info->base, 678 ret = 0;
679 if (info->timing)
680 ret = davinci_aemif_setup_timing(info->timing, info->base,
679 info->core_chipsel); 681 info->core_chipsel);
680 if (ret < 0) { 682 if (ret < 0) {
681 dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); 683 dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 5780dbab611..df921e7a496 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1072,7 +1072,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
1072 size_t retlen; 1072 size_t retlen;
1073 1073
1074 for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { 1074 for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
1075 ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); 1075 ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf);
1076 if (retlen != mtd->writesize) 1076 if (retlen != mtd->writesize)
1077 continue; 1077 continue;
1078 if (ret) { 1078 if (ret) {
@@ -1097,7 +1097,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
1097 /* Only one mediaheader was found. We want buf to contain a 1097 /* Only one mediaheader was found. We want buf to contain a
1098 mediaheader on return, so we'll have to re-read the one we found. */ 1098 mediaheader on return, so we'll have to re-read the one we found. */
1099 offs = doc->mh0_page << this->page_shift; 1099 offs = doc->mh0_page << this->page_shift;
1100 ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); 1100 ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf);
1101 if (retlen != mtd->writesize) { 1101 if (retlen != mtd->writesize) {
1102 /* Insanity. Give up. */ 1102 /* Insanity. Give up. */
1103 printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); 1103 printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index eedd8ee2c9a..7195ee6efe1 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -166,15 +166,22 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
166 166
167 elbc_fcm_ctrl->page = page_addr; 167 elbc_fcm_ctrl->page = page_addr;
168 168
169 out_be32(&lbc->fbar,
170 page_addr >> (chip->phys_erase_shift - chip->page_shift));
171
172 if (priv->page_size) { 169 if (priv->page_size) {
170 /*
171 * large page size chip : FPAR[PI] save the lowest 6 bits,
172 * FBAR[BLK] save the other bits.
173 */
174 out_be32(&lbc->fbar, page_addr >> 6);
173 out_be32(&lbc->fpar, 175 out_be32(&lbc->fpar,
174 ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | 176 ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
175 (oob ? FPAR_LP_MS : 0) | column); 177 (oob ? FPAR_LP_MS : 0) | column);
176 buf_num = (page_addr & 1) << 2; 178 buf_num = (page_addr & 1) << 2;
177 } else { 179 } else {
180 /*
181 * small page size chip : FPAR[PI] save the lowest 5 bits,
182 * FBAR[BLK] save the other bits.
183 */
184 out_be32(&lbc->fbar, page_addr >> 5);
178 out_be32(&lbc->fpar, 185 out_be32(&lbc->fpar,
179 ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | 186 ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
180 (oob ? FPAR_SP_MS : 0) | column); 187 (oob ? FPAR_SP_MS : 0) | column);
@@ -349,20 +356,22 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
349 fsl_elbc_run_command(mtd); 356 fsl_elbc_run_command(mtd);
350 return; 357 return;
351 358
352 /* READID must read all 5 possible bytes while CEB is active */
353 case NAND_CMD_READID: 359 case NAND_CMD_READID:
354 dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); 360 case NAND_CMD_PARAM:
361 dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command);
355 362
356 out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | 363 out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
357 (FIR_OP_UA << FIR_OP1_SHIFT) | 364 (FIR_OP_UA << FIR_OP1_SHIFT) |
358 (FIR_OP_RBW << FIR_OP2_SHIFT)); 365 (FIR_OP_RBW << FIR_OP2_SHIFT));
359 out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); 366 out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
360 /* nand_get_flash_type() reads 8 bytes of entire ID string */ 367 /*
361 out_be32(&lbc->fbcr, 8); 368 * although currently it's 8 bytes for READID, we always read
362 elbc_fcm_ctrl->read_bytes = 8; 369 * the maximum 256 bytes(for PARAM)
370 */
371 out_be32(&lbc->fbcr, 256);
372 elbc_fcm_ctrl->read_bytes = 256;
363 elbc_fcm_ctrl->use_mdr = 1; 373 elbc_fcm_ctrl->use_mdr = 1;
364 elbc_fcm_ctrl->mdr = 0; 374 elbc_fcm_ctrl->mdr = column;
365
366 set_addr(mtd, 0, 0, 0); 375 set_addr(mtd, 0, 0, 0);
367 fsl_elbc_run_command(mtd); 376 fsl_elbc_run_command(mtd);
368 return; 377 return;
@@ -407,9 +416,17 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
407 page_addr, column); 416 page_addr, column);
408 417
409 elbc_fcm_ctrl->column = column; 418 elbc_fcm_ctrl->column = column;
410 elbc_fcm_ctrl->oob = 0;
411 elbc_fcm_ctrl->use_mdr = 1; 419 elbc_fcm_ctrl->use_mdr = 1;
412 420
421 if (column >= mtd->writesize) {
422 /* OOB area */
423 column -= mtd->writesize;
424 elbc_fcm_ctrl->oob = 1;
425 } else {
426 WARN_ON(column != 0);
427 elbc_fcm_ctrl->oob = 0;
428 }
429
413 fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | 430 fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
414 (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | 431 (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
415 (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT); 432 (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
@@ -434,16 +451,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
434 (FIR_OP_CW1 << FIR_OP6_SHIFT) | 451 (FIR_OP_CW1 << FIR_OP6_SHIFT) |
435 (FIR_OP_RS << FIR_OP7_SHIFT)); 452 (FIR_OP_RS << FIR_OP7_SHIFT));
436 453
437 if (column >= mtd->writesize) { 454 if (elbc_fcm_ctrl->oob)
438 /* OOB area --> READOOB */ 455 /* OOB area --> READOOB */
439 column -= mtd->writesize;
440 fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; 456 fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
441 elbc_fcm_ctrl->oob = 1; 457 else
442 } else {
443 WARN_ON(column != 0);
444 /* First 256 bytes --> READ0 */ 458 /* First 256 bytes --> READ0 */
445 fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; 459 fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
446 }
447 } 460 }
448 461
449 out_be32(&lbc->fcr, fcr); 462 out_be32(&lbc->fcr, fcr);
@@ -463,7 +476,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
463 */ 476 */
464 if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || 477 if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
465 elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) 478 elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
466 out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); 479 out_be32(&lbc->fbcr,
480 elbc_fcm_ctrl->index - elbc_fcm_ctrl->column);
467 else 481 else
468 out_be32(&lbc->fbcr, 0); 482 out_be32(&lbc->fbcr, 0);
469 483
@@ -659,9 +673,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
659 if (chip->pagemask & 0xff000000) 673 if (chip->pagemask & 0xff000000)
660 al++; 674 al++;
661 675
662 /* add to ECCM mode set in fsl_elbc_init */ 676 priv->fmr |= al << FMR_AL_SHIFT;
663 priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */
664 (al << FMR_AL_SHIFT);
665 677
666 dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", 678 dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
667 chip->numchips); 679 chip->numchips);
@@ -764,8 +776,10 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
764 priv->mtd.priv = chip; 776 priv->mtd.priv = chip;
765 priv->mtd.owner = THIS_MODULE; 777 priv->mtd.owner = THIS_MODULE;
766 778
767 /* Set the ECCM according to the settings in bootloader.*/ 779 /* set timeout to maximum */
768 priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM; 780 priv->fmr = 15 << FMR_CWTO_SHIFT;
781 if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS)
782 priv->fmr |= FMR_ECCM;
769 783
770 /* fill in nand_chip structure */ 784 /* fill in nand_chip structure */
771 /* set up function call table */ 785 /* set up function call table */
@@ -971,18 +985,7 @@ static struct platform_driver fsl_elbc_nand_driver = {
971 .remove = fsl_elbc_nand_remove, 985 .remove = fsl_elbc_nand_remove,
972}; 986};
973 987
974static int __init fsl_elbc_nand_init(void) 988module_platform_driver(fsl_elbc_nand_driver);
975{
976 return platform_driver_register(&fsl_elbc_nand_driver);
977}
978
979static void __exit fsl_elbc_nand_exit(void)
980{
981 platform_driver_unregister(&fsl_elbc_nand_driver);
982}
983
984module_init(fsl_elbc_nand_init);
985module_exit(fsl_elbc_nand_exit);
986 989
987MODULE_LICENSE("GPL"); 990MODULE_LICENSE("GPL");
988MODULE_AUTHOR("Freescale"); 991MODULE_AUTHOR("Freescale");
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index b4f3cc9f32f..45df542b9c6 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -353,17 +353,7 @@ static struct platform_driver of_fun_driver = {
353 .remove = __devexit_p(fun_remove), 353 .remove = __devexit_p(fun_remove),
354}; 354};
355 355
356static int __init fun_module_init(void) 356module_platform_driver(of_fun_driver);
357{
358 return platform_driver_register(&of_fun_driver);
359}
360module_init(fun_module_init);
361
362static void __exit fun_module_exit(void)
363{
364 platform_driver_unregister(&of_fun_driver);
365}
366module_exit(fun_module_exit);
367 357
368MODULE_LICENSE("GPL"); 358MODULE_LICENSE("GPL");
369MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); 359MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 2c2060b2800..27000a5f5f4 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -27,6 +27,9 @@
27#include <linux/mtd/nand.h> 27#include <linux/mtd/nand.h>
28#include <linux/mtd/partitions.h> 28#include <linux/mtd/partitions.h>
29#include <linux/mtd/nand-gpio.h> 29#include <linux/mtd/nand-gpio.h>
30#include <linux/of.h>
31#include <linux/of_address.h>
32#include <linux/of_gpio.h>
30 33
31struct gpiomtd { 34struct gpiomtd {
32 void __iomem *io_sync; 35 void __iomem *io_sync;
@@ -171,6 +174,96 @@ static int gpio_nand_devready(struct mtd_info *mtd)
171 return gpio_get_value(gpiomtd->plat.gpio_rdy); 174 return gpio_get_value(gpiomtd->plat.gpio_rdy);
172} 175}
173 176
177#ifdef CONFIG_OF
178static const struct of_device_id gpio_nand_id_table[] = {
179 { .compatible = "gpio-control-nand" },
180 {}
181};
182MODULE_DEVICE_TABLE(of, gpio_nand_id_table);
183
184static int gpio_nand_get_config_of(const struct device *dev,
185 struct gpio_nand_platdata *plat)
186{
187 u32 val;
188
189 if (!of_property_read_u32(dev->of_node, "bank-width", &val)) {
190 if (val == 2) {
191 plat->options |= NAND_BUSWIDTH_16;
192 } else if (val != 1) {
193 dev_err(dev, "invalid bank-width %u\n", val);
194 return -EINVAL;
195 }
196 }
197
198 plat->gpio_rdy = of_get_gpio(dev->of_node, 0);
199 plat->gpio_nce = of_get_gpio(dev->of_node, 1);
200 plat->gpio_ale = of_get_gpio(dev->of_node, 2);
201 plat->gpio_cle = of_get_gpio(dev->of_node, 3);
202 plat->gpio_nwp = of_get_gpio(dev->of_node, 4);
203
204 if (!of_property_read_u32(dev->of_node, "chip-delay", &val))
205 plat->chip_delay = val;
206
207 return 0;
208}
209
210static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev)
211{
212 struct resource *r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
213 u64 addr;
214
215 if (!r || of_property_read_u64(pdev->dev.of_node,
216 "gpio-control-nand,io-sync-reg", &addr))
217 return NULL;
218
219 r->start = addr;
220 r->end = r->start + 0x3;
221 r->flags = IORESOURCE_MEM;
222
223 return r;
224}
225#else /* CONFIG_OF */
226#define gpio_nand_id_table NULL
227static inline int gpio_nand_get_config_of(const struct device *dev,
228 struct gpio_nand_platdata *plat)
229{
230 return -ENOSYS;
231}
232
233static inline struct resource *
234gpio_nand_get_io_sync_of(struct platform_device *pdev)
235{
236 return NULL;
237}
238#endif /* CONFIG_OF */
239
240static inline int gpio_nand_get_config(const struct device *dev,
241 struct gpio_nand_platdata *plat)
242{
243 int ret = gpio_nand_get_config_of(dev, plat);
244
245 if (!ret)
246 return ret;
247
248 if (dev->platform_data) {
249 memcpy(plat, dev->platform_data, sizeof(*plat));
250 return 0;
251 }
252
253 return -EINVAL;
254}
255
256static inline struct resource *
257gpio_nand_get_io_sync(struct platform_device *pdev)
258{
259 struct resource *r = gpio_nand_get_io_sync_of(pdev);
260
261 if (r)
262 return r;
263
264 return platform_get_resource(pdev, IORESOURCE_MEM, 1);
265}
266
174static int __devexit gpio_nand_remove(struct platform_device *dev) 267static int __devexit gpio_nand_remove(struct platform_device *dev)
175{ 268{
176 struct gpiomtd *gpiomtd = platform_get_drvdata(dev); 269 struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
@@ -178,7 +271,7 @@ static int __devexit gpio_nand_remove(struct platform_device *dev)
178 271
179 nand_release(&gpiomtd->mtd_info); 272 nand_release(&gpiomtd->mtd_info);
180 273
181 res = platform_get_resource(dev, IORESOURCE_MEM, 1); 274 res = gpio_nand_get_io_sync(dev);
182 iounmap(gpiomtd->io_sync); 275 iounmap(gpiomtd->io_sync);
183 if (res) 276 if (res)
184 release_mem_region(res->start, resource_size(res)); 277 release_mem_region(res->start, resource_size(res));
@@ -226,9 +319,10 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
226 struct gpiomtd *gpiomtd; 319 struct gpiomtd *gpiomtd;
227 struct nand_chip *this; 320 struct nand_chip *this;
228 struct resource *res0, *res1; 321 struct resource *res0, *res1;
229 int ret; 322 struct mtd_part_parser_data ppdata = {};
323 int ret = 0;
230 324
231 if (!dev->dev.platform_data) 325 if (!dev->dev.of_node && !dev->dev.platform_data)
232 return -EINVAL; 326 return -EINVAL;
233 327
234 res0 = platform_get_resource(dev, IORESOURCE_MEM, 0); 328 res0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
@@ -248,7 +342,7 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
248 goto err_map; 342 goto err_map;
249 } 343 }
250 344
251 res1 = platform_get_resource(dev, IORESOURCE_MEM, 1); 345 res1 = gpio_nand_get_io_sync(dev);
252 if (res1) { 346 if (res1) {
253 gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret); 347 gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret);
254 if (!gpiomtd->io_sync) { 348 if (!gpiomtd->io_sync) {
@@ -257,7 +351,9 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
257 } 351 }
258 } 352 }
259 353
260 memcpy(&gpiomtd->plat, dev->dev.platform_data, sizeof(gpiomtd->plat)); 354 ret = gpio_nand_get_config(&dev->dev, &gpiomtd->plat);
355 if (ret)
356 goto err_nce;
261 357
262 ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE"); 358 ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE");
263 if (ret) 359 if (ret)
@@ -316,8 +412,12 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
316 gpiomtd->plat.adjust_parts(&gpiomtd->plat, 412 gpiomtd->plat.adjust_parts(&gpiomtd->plat,
317 gpiomtd->mtd_info.size); 413 gpiomtd->mtd_info.size);
318 414
319 mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts, 415 ppdata.of_node = dev->dev.of_node;
320 gpiomtd->plat.num_parts); 416 ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata,
417 gpiomtd->plat.parts,
418 gpiomtd->plat.num_parts);
419 if (ret)
420 goto err_wp;
321 platform_set_drvdata(dev, gpiomtd); 421 platform_set_drvdata(dev, gpiomtd);
322 422
323 return 0; 423 return 0;
@@ -352,6 +452,7 @@ static struct platform_driver gpio_nand_driver = {
352 .remove = gpio_nand_remove, 452 .remove = gpio_nand_remove,
353 .driver = { 453 .driver = {
354 .name = "gpio-nand", 454 .name = "gpio-nand",
455 .of_match_table = gpio_nand_id_table,
355 }, 456 },
356}; 457};
357 458
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index e2664073a89..ac3b9f255e0 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -423,17 +423,7 @@ static struct platform_driver jz_nand_driver = {
423 }, 423 },
424}; 424};
425 425
426static int __init jz_nand_init(void) 426module_platform_driver(jz_nand_driver);
427{
428 return platform_driver_register(&jz_nand_driver);
429}
430module_init(jz_nand_init);
431
432static void __exit jz_nand_exit(void)
433{
434 platform_driver_unregister(&jz_nand_driver);
435}
436module_exit(jz_nand_exit);
437 427
438MODULE_LICENSE("GPL"); 428MODULE_LICENSE("GPL");
439MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 429MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 5ede6470634..c240cf1af96 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -879,19 +879,7 @@ static struct platform_driver mpc5121_nfc_driver = {
879 }, 879 },
880}; 880};
881 881
882static int __init mpc5121_nfc_init(void) 882module_platform_driver(mpc5121_nfc_driver);
883{
884 return platform_driver_register(&mpc5121_nfc_driver);
885}
886
887module_init(mpc5121_nfc_init);
888
889static void __exit mpc5121_nfc_cleanup(void)
890{
891 platform_driver_unregister(&mpc5121_nfc_driver);
892}
893
894module_exit(mpc5121_nfc_cleanup);
895 883
896MODULE_AUTHOR("Freescale Semiconductor, Inc."); 884MODULE_AUTHOR("Freescale Semiconductor, Inc.");
897MODULE_DESCRIPTION("MPC5121 NAND MTD driver"); 885MODULE_DESCRIPTION("MPC5121 NAND MTD driver");
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 3ed9c5e4d34..35b4565050f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3132,8 +3132,8 @@ ident_done:
3132 * Bad block marker is stored in the last page of each block 3132 * Bad block marker is stored in the last page of each block
3133 * on Samsung and Hynix MLC devices; stored in first two pages 3133 * on Samsung and Hynix MLC devices; stored in first two pages
3134 * of each block on Micron devices with 2KiB pages and on 3134 * of each block on Micron devices with 2KiB pages and on
3135 * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan 3135 * SLC Samsung, Hynix, Toshiba, AMD/Spansion, and Macronix.
3136 * only the first page. 3136 * All others scan only the first page.
3137 */ 3137 */
3138 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && 3138 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
3139 (*maf_id == NAND_MFR_SAMSUNG || 3139 (*maf_id == NAND_MFR_SAMSUNG ||
@@ -3143,7 +3143,8 @@ ident_done:
3143 (*maf_id == NAND_MFR_SAMSUNG || 3143 (*maf_id == NAND_MFR_SAMSUNG ||
3144 *maf_id == NAND_MFR_HYNIX || 3144 *maf_id == NAND_MFR_HYNIX ||
3145 *maf_id == NAND_MFR_TOSHIBA || 3145 *maf_id == NAND_MFR_TOSHIBA ||
3146 *maf_id == NAND_MFR_AMD)) || 3146 *maf_id == NAND_MFR_AMD ||
3147 *maf_id == NAND_MFR_MACRONIX)) ||
3147 (mtd->writesize == 2048 && 3148 (mtd->writesize == 2048 &&
3148 *maf_id == NAND_MFR_MICRON)) 3149 *maf_id == NAND_MFR_MICRON))
3149 chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; 3150 chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 69148ae3bf5..20a112f591f 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -201,7 +201,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
201 from += marker_len; 201 from += marker_len;
202 marker_len = 0; 202 marker_len = 0;
203 } 203 }
204 res = mtd->read(mtd, from, len, &retlen, buf); 204 res = mtd_read(mtd, from, len, &retlen, buf);
205 if (res < 0) { 205 if (res < 0) {
206 if (mtd_is_eccerr(res)) { 206 if (mtd_is_eccerr(res)) {
207 pr_info("nand_bbt: ECC error in BBT at " 207 pr_info("nand_bbt: ECC error in BBT at "
@@ -298,7 +298,7 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
298 if (td->options & NAND_BBT_VERSION) 298 if (td->options & NAND_BBT_VERSION)
299 len++; 299 len++;
300 300
301 return mtd->read(mtd, offs, len, &retlen, buf); 301 return mtd_read(mtd, offs, len, &retlen, buf);
302} 302}
303 303
304/* Scan read raw data from flash */ 304/* Scan read raw data from flash */
@@ -317,7 +317,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
317 ops.len = min(len, (size_t)mtd->writesize); 317 ops.len = min(len, (size_t)mtd->writesize);
318 ops.oobbuf = buf + ops.len; 318 ops.oobbuf = buf + ops.len;
319 319
320 res = mtd->read_oob(mtd, offs, &ops); 320 res = mtd_read_oob(mtd, offs, &ops);
321 321
322 if (res) 322 if (res)
323 return res; 323 return res;
@@ -350,7 +350,7 @@ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
350 ops.oobbuf = oob; 350 ops.oobbuf = oob;
351 ops.len = len; 351 ops.len = len;
352 352
353 return mtd->write_oob(mtd, offs, &ops); 353 return mtd_write_oob(mtd, offs, &ops);
354} 354}
355 355
356static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) 356static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
@@ -434,7 +434,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
434 * Read the full oob until read_oob is fixed to handle single 434 * Read the full oob until read_oob is fixed to handle single
435 * byte reads for 16 bit buswidth. 435 * byte reads for 16 bit buswidth.
436 */ 436 */
437 ret = mtd->read_oob(mtd, offs, &ops); 437 ret = mtd_read_oob(mtd, offs, &ops);
438 /* Ignore ECC errors when checking for BBM */ 438 /* Ignore ECC errors when checking for BBM */
439 if (ret && !mtd_is_bitflip_or_eccerr(ret)) 439 if (ret && !mtd_is_bitflip_or_eccerr(ret))
440 return ret; 440 return ret;
@@ -756,7 +756,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
756 /* Make it block aligned */ 756 /* Make it block aligned */
757 to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1)); 757 to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1));
758 len = 1 << this->bbt_erase_shift; 758 len = 1 << this->bbt_erase_shift;
759 res = mtd->read(mtd, to, len, &retlen, buf); 759 res = mtd_read(mtd, to, len, &retlen, buf);
760 if (res < 0) { 760 if (res < 0) {
761 if (retlen != len) { 761 if (retlen != len) {
762 pr_info("nand_bbt: error reading block " 762 pr_info("nand_bbt: error reading block "
@@ -769,7 +769,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
769 /* Read oob data */ 769 /* Read oob data */
770 ops.ooblen = (len >> this->page_shift) * mtd->oobsize; 770 ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
771 ops.oobbuf = &buf[len]; 771 ops.oobbuf = &buf[len];
772 res = mtd->read_oob(mtd, to + mtd->writesize, &ops); 772 res = mtd_read_oob(mtd, to + mtd->writesize, &ops);
773 if (res < 0 || ops.oobretlen != ops.ooblen) 773 if (res < 0 || ops.oobretlen != ops.ooblen)
774 goto outerr; 774 goto outerr;
775 775
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 00cf1b0d605..af4fe8ca7b5 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -73,11 +73,12 @@ struct nand_flash_dev nand_flash_ids[] = {
73#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) 73#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR)
74#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) 74#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
75 75
76 /*512 Megabit */ 76 /* 512 Megabit */
77 {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, 77 {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS},
78 {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS}, 78 {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS},
79 {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, 79 {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS},
80 {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS}, 80 {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS},
81 {"NAND 64MiB 3,3V 8-bit", 0xF0, 0, 64, 0, LP_OPTIONS},
81 {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, 82 {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16},
82 {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16}, 83 {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16},
83 {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, 84 {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16},
@@ -176,6 +177,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
176 {NAND_MFR_HYNIX, "Hynix"}, 177 {NAND_MFR_HYNIX, "Hynix"},
177 {NAND_MFR_MICRON, "Micron"}, 178 {NAND_MFR_MICRON, "Micron"},
178 {NAND_MFR_AMD, "AMD"}, 179 {NAND_MFR_AMD, "AMD"},
180 {NAND_MFR_MACRONIX, "Macronix"},
179 {0x0, "Unknown"} 181 {0x0, "Unknown"}
180}; 182};
181 183
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 34c03be7730..261f478f8cc 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -737,7 +737,7 @@ static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd)
737 return -EINVAL; 737 return -EINVAL;
738 } 738 }
739 offset = erase_block_no * ns->geom.secsz; 739 offset = erase_block_no * ns->geom.secsz;
740 if (mtd->block_markbad(mtd, offset)) { 740 if (mtd_block_markbad(mtd, offset)) {
741 NS_ERR("invalid badblocks.\n"); 741 NS_ERR("invalid badblocks.\n");
742 return -EINVAL; 742 return -EINVAL;
743 } 743 }
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index f8aacf48ecd..ec688548c88 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -294,18 +294,7 @@ static struct platform_driver ndfc_driver = {
294 .remove = __devexit_p(ndfc_remove), 294 .remove = __devexit_p(ndfc_remove),
295}; 295};
296 296
297static int __init ndfc_nand_init(void) 297module_platform_driver(ndfc_driver);
298{
299 return platform_driver_register(&ndfc_driver);
300}
301
302static void __exit ndfc_nand_exit(void)
303{
304 platform_driver_unregister(&ndfc_driver);
305}
306
307module_init(ndfc_nand_init);
308module_exit(ndfc_nand_exit);
309 298
310MODULE_LICENSE("GPL"); 299MODULE_LICENSE("GPL");
311MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); 300MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
index b463ecfb4c1..a86aa812ca1 100644
--- a/drivers/mtd/nand/nomadik_nand.c
+++ b/drivers/mtd/nand/nomadik_nand.c
@@ -201,7 +201,7 @@ static int nomadik_nand_suspend(struct device *dev)
201 struct nomadik_nand_host *host = dev_get_drvdata(dev); 201 struct nomadik_nand_host *host = dev_get_drvdata(dev);
202 int ret = 0; 202 int ret = 0;
203 if (host) 203 if (host)
204 ret = host->mtd.suspend(&host->mtd); 204 ret = mtd_suspend(&host->mtd);
205 return ret; 205 return ret;
206} 206}
207 207
@@ -209,7 +209,7 @@ static int nomadik_nand_resume(struct device *dev)
209{ 209{
210 struct nomadik_nand_host *host = dev_get_drvdata(dev); 210 struct nomadik_nand_host *host = dev_get_drvdata(dev);
211 if (host) 211 if (host)
212 host->mtd.resume(&host->mtd); 212 mtd_resume(&host->mtd);
213 return 0; 213 return 0;
214} 214}
215 215
@@ -228,19 +228,7 @@ static struct platform_driver nomadik_nand_driver = {
228 }, 228 },
229}; 229};
230 230
231static int __init nand_nomadik_init(void) 231module_platform_driver(nomadik_nand_driver);
232{
233 pr_info("Nomadik NAND driver\n");
234 return platform_driver_register(&nomadik_nand_driver);
235}
236
237static void __exit nand_nomadik_exit(void)
238{
239 platform_driver_unregister(&nomadik_nand_driver);
240}
241
242module_init(nand_nomadik_init);
243module_exit(nand_nomadik_exit);
244 232
245MODULE_LICENSE("GPL"); 233MODULE_LICENSE("GPL");
246MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)"); 234MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)");
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index fa8faedfad6..8febe46e110 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -364,18 +364,7 @@ static struct platform_driver nuc900_nand_driver = {
364 }, 364 },
365}; 365};
366 366
367static int __init nuc900_nand_init(void) 367module_platform_driver(nuc900_nand_driver);
368{
369 return platform_driver_register(&nuc900_nand_driver);
370}
371
372static void __exit nuc900_nand_exit(void)
373{
374 platform_driver_unregister(&nuc900_nand_driver);
375}
376
377module_init(nuc900_nand_init);
378module_exit(nuc900_nand_exit);
379 368
380MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); 369MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
381MODULE_DESCRIPTION("w90p910/NUC9xx nand driver!"); 370MODULE_DESCRIPTION("w90p910/NUC9xx nand driver!");
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index f745f00f316..b3a883e2a22 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1145,20 +1145,7 @@ static struct platform_driver omap_nand_driver = {
1145 }, 1145 },
1146}; 1146};
1147 1147
1148static int __init omap_nand_init(void) 1148module_platform_driver(omap_nand_driver);
1149{
1150 pr_info("%s driver initializing\n", DRIVER_NAME);
1151
1152 return platform_driver_register(&omap_nand_driver);
1153}
1154
1155static void __exit omap_nand_exit(void)
1156{
1157 platform_driver_unregister(&omap_nand_driver);
1158}
1159
1160module_init(omap_nand_init);
1161module_exit(omap_nand_exit);
1162 1149
1163MODULE_ALIAS("platform:" DRIVER_NAME); 1150MODULE_ALIAS("platform:" DRIVER_NAME);
1164MODULE_LICENSE("GPL"); 1151MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index a97264ececd..974dbf8251c 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -230,17 +230,7 @@ static struct platform_driver pasemi_nand_driver =
230 .remove = pasemi_nand_remove, 230 .remove = pasemi_nand_remove,
231}; 231};
232 232
233static int __init pasemi_nand_init(void) 233module_platform_driver(pasemi_nand_driver);
234{
235 return platform_driver_register(&pasemi_nand_driver);
236}
237module_init(pasemi_nand_init);
238
239static void __exit pasemi_nand_exit(void)
240{
241 platform_driver_unregister(&pasemi_nand_driver);
242}
243module_exit(pasemi_nand_exit);
244 234
245MODULE_LICENSE("GPL"); 235MODULE_LICENSE("GPL");
246MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); 236MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index ea8e1234e0e..7f2da695335 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -148,18 +148,7 @@ static struct platform_driver plat_nand_driver = {
148 }, 148 },
149}; 149};
150 150
151static int __init plat_nand_init(void) 151module_platform_driver(plat_nand_driver);
152{
153 return platform_driver_register(&plat_nand_driver);
154}
155
156static void __exit plat_nand_exit(void)
157{
158 platform_driver_unregister(&plat_nand_driver);
159}
160
161module_init(plat_nand_init);
162module_exit(plat_nand_exit);
163 152
164MODULE_LICENSE("GPL"); 153MODULE_LICENSE("GPL");
165MODULE_AUTHOR("Vitaly Wool"); 154MODULE_AUTHOR("Vitaly Wool");
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 9eb7f879969..8544d6bf50a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1258,7 +1258,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
1258 1258
1259 for (cs = 0; cs < pdata->num_cs; cs++) { 1259 for (cs = 0; cs < pdata->num_cs; cs++) {
1260 mtd = info->host[cs]->mtd; 1260 mtd = info->host[cs]->mtd;
1261 mtd->suspend(mtd); 1261 mtd_suspend(mtd);
1262 } 1262 }
1263 1263
1264 return 0; 1264 return 0;
@@ -1291,7 +1291,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
1291 nand_writel(info, NDSR, NDSR_MASK); 1291 nand_writel(info, NDSR, NDSR_MASK);
1292 for (cs = 0; cs < pdata->num_cs; cs++) { 1292 for (cs = 0; cs < pdata->num_cs; cs++) {
1293 mtd = info->host[cs]->mtd; 1293 mtd = info->host[cs]->mtd;
1294 mtd->resume(mtd); 1294 mtd_resume(mtd);
1295 } 1295 }
1296 1296
1297 return 0; 1297 return 0;
@@ -1311,17 +1311,7 @@ static struct platform_driver pxa3xx_nand_driver = {
1311 .resume = pxa3xx_nand_resume, 1311 .resume = pxa3xx_nand_resume,
1312}; 1312};
1313 1313
1314static int __init pxa3xx_nand_init(void) 1314module_platform_driver(pxa3xx_nand_driver);
1315{
1316 return platform_driver_register(&pxa3xx_nand_driver);
1317}
1318module_init(pxa3xx_nand_init);
1319
1320static void __exit pxa3xx_nand_exit(void)
1321{
1322 platform_driver_unregister(&pxa3xx_nand_driver);
1323}
1324module_exit(pxa3xx_nand_exit);
1325 1315
1326MODULE_LICENSE("GPL"); 1316MODULE_LICENSE("GPL");
1327MODULE_DESCRIPTION("PXA3xx NAND controller driver"); 1317MODULE_DESCRIPTION("PXA3xx NAND controller driver");
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 619d2a50478..b175c0fd8b9 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -230,17 +230,7 @@ static struct platform_driver sharpsl_nand_driver = {
230 .remove = __devexit_p(sharpsl_nand_remove), 230 .remove = __devexit_p(sharpsl_nand_remove),
231}; 231};
232 232
233static int __init sharpsl_nand_init(void) 233module_platform_driver(sharpsl_nand_driver);
234{
235 return platform_driver_register(&sharpsl_nand_driver);
236}
237module_init(sharpsl_nand_init);
238
239static void __exit sharpsl_nand_exit(void)
240{
241 platform_driver_unregister(&sharpsl_nand_driver);
242}
243module_exit(sharpsl_nand_exit);
244 234
245MODULE_LICENSE("GPL"); 235MODULE_LICENSE("GPL");
246MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); 236MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c
index 32ae5af7444..774c3c26671 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/sm_common.c
@@ -55,7 +55,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
55 ops.datbuf = NULL; 55 ops.datbuf = NULL;
56 56
57 57
58 ret = mtd->write_oob(mtd, ofs, &ops); 58 ret = mtd_write_oob(mtd, ofs, &ops);
59 if (ret < 0 || ops.oobretlen != SM_OOB_SIZE) { 59 if (ret < 0 || ops.oobretlen != SM_OOB_SIZE) {
60 printk(KERN_NOTICE 60 printk(KERN_NOTICE
61 "sm_common: can't mark sector at %i as bad\n", 61 "sm_common: can't mark sector at %i as bad\n",
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 0fb24f9c232..e02b08bcf0c 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -273,18 +273,7 @@ static struct platform_driver socrates_nand_driver = {
273 .remove = __devexit_p(socrates_nand_remove), 273 .remove = __devexit_p(socrates_nand_remove),
274}; 274};
275 275
276static int __init socrates_nand_init(void) 276module_platform_driver(socrates_nand_driver);
277{
278 return platform_driver_register(&socrates_nand_driver);
279}
280
281static void __exit socrates_nand_exit(void)
282{
283 platform_driver_unregister(&socrates_nand_driver);
284}
285
286module_init(socrates_nand_init);
287module_exit(socrates_nand_exit);
288 277
289MODULE_LICENSE("GPL"); 278MODULE_LICENSE("GPL");
290MODULE_AUTHOR("Ilya Yanok"); 279MODULE_AUTHOR("Ilya Yanok");
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index beebd95f769..6caa0cd9d6a 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -533,18 +533,7 @@ static struct platform_driver tmio_driver = {
533 .resume = tmio_resume, 533 .resume = tmio_resume,
534}; 534};
535 535
536static int __init tmio_init(void) 536module_platform_driver(tmio_driver);
537{
538 return platform_driver_register(&tmio_driver);
539}
540
541static void __exit tmio_exit(void)
542{
543 platform_driver_unregister(&tmio_driver);
544}
545
546module_init(tmio_init);
547module_exit(tmio_exit);
548 537
549MODULE_LICENSE("GPL v2"); 538MODULE_LICENSE("GPL v2");
550MODULE_AUTHOR("Ian Molton, Dirk Opfer, Chris Humbert, Dmitry Baryshkov"); 539MODULE_AUTHOR("Ian Molton, Dirk Opfer, Chris Humbert, Dmitry Baryshkov");
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index ace46fdaef5..c7c4f1d11c7 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -298,11 +298,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
298 drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL); 298 drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL);
299 if (!drvdata) 299 if (!drvdata)
300 return -ENOMEM; 300 return -ENOMEM;
301 if (!devm_request_mem_region(&dev->dev, res->start, 301 drvdata->base = devm_request_and_ioremap(&dev->dev, res);
302 resource_size(res), dev_name(&dev->dev)))
303 return -EBUSY;
304 drvdata->base = devm_ioremap(&dev->dev, res->start,
305 resource_size(res));
306 if (!drvdata->base) 302 if (!drvdata->base)
307 return -EBUSY; 303 return -EBUSY;
308 304
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index cda77b562ad..a75382aff5f 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -56,7 +56,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
56 if (memcmp(mtd->name, "DiskOnChip", 10)) 56 if (memcmp(mtd->name, "DiskOnChip", 10))
57 return; 57 return;
58 58
59 if (!mtd->block_isbad) { 59 if (!mtd_can_have_bb(mtd)) {
60 printk(KERN_ERR 60 printk(KERN_ERR
61"NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n" 61"NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
62"Please use the new diskonchip driver under the NAND subsystem.\n"); 62"Please use the new diskonchip driver under the NAND subsystem.\n");
@@ -153,7 +153,7 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
153 ops.oobbuf = buf; 153 ops.oobbuf = buf;
154 ops.datbuf = NULL; 154 ops.datbuf = NULL;
155 155
156 res = mtd->read_oob(mtd, offs & ~mask, &ops); 156 res = mtd_read_oob(mtd, offs & ~mask, &ops);
157 *retlen = ops.oobretlen; 157 *retlen = ops.oobretlen;
158 return res; 158 return res;
159} 159}
@@ -174,7 +174,7 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
174 ops.oobbuf = buf; 174 ops.oobbuf = buf;
175 ops.datbuf = NULL; 175 ops.datbuf = NULL;
176 176
177 res = mtd->write_oob(mtd, offs & ~mask, &ops); 177 res = mtd_write_oob(mtd, offs & ~mask, &ops);
178 *retlen = ops.oobretlen; 178 *retlen = ops.oobretlen;
179 return res; 179 return res;
180} 180}
@@ -198,7 +198,7 @@ static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
198 ops.datbuf = buf; 198 ops.datbuf = buf;
199 ops.len = len; 199 ops.len = len;
200 200
201 res = mtd->write_oob(mtd, offs & ~mask, &ops); 201 res = mtd_write_oob(mtd, offs & ~mask, &ops);
202 *retlen = ops.retlen; 202 *retlen = ops.retlen;
203 return res; 203 return res;
204} 204}
@@ -423,12 +423,17 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
423 if (BlockMap[block] == BLOCK_NIL) 423 if (BlockMap[block] == BLOCK_NIL)
424 continue; 424 continue;
425 425
426 ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), 426 ret = mtd_read(mtd,
427 512, &retlen, movebuf); 427 (nftl->EraseSize * BlockMap[block]) + (block * 512),
428 512,
429 &retlen,
430 movebuf);
428 if (ret < 0 && !mtd_is_bitflip(ret)) { 431 if (ret < 0 && !mtd_is_bitflip(ret)) {
429 ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) 432 ret = mtd_read(mtd,
430 + (block * 512), 512, &retlen, 433 (nftl->EraseSize * BlockMap[block]) + (block * 512),
431 movebuf); 434 512,
435 &retlen,
436 movebuf);
432 if (ret != -EIO) 437 if (ret != -EIO)
433 printk("Error went away on retry.\n"); 438 printk("Error went away on retry.\n");
434 } 439 }
@@ -771,7 +776,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
771 } else { 776 } else {
772 loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; 777 loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
773 size_t retlen; 778 size_t retlen;
774 int res = mtd->read(mtd, ptr, 512, &retlen, buffer); 779 int res = mtd_read(mtd, ptr, 512, &retlen, buffer);
775 780
776 if (res < 0 && !mtd_is_bitflip(res)) 781 if (res < 0 && !mtd_is_bitflip(res))
777 return -EIO; 782 return -EIO;
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index ac4092591ae..51b9d6af307 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -63,8 +63,8 @@ static int find_boot_record(struct NFTLrecord *nftl)
63 63
64 /* Check for ANAND header first. Then can whinge if it's found but later 64 /* Check for ANAND header first. Then can whinge if it's found but later
65 checks fail */ 65 checks fail */
66 ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, 66 ret = mtd_read(mtd, block * nftl->EraseSize, SECTORSIZE,
67 &retlen, buf); 67 &retlen, buf);
68 /* We ignore ret in case the ECC of the MediaHeader is invalid 68 /* We ignore ret in case the ECC of the MediaHeader is invalid
69 (which is apparently acceptable) */ 69 (which is apparently acceptable) */
70 if (retlen != SECTORSIZE) { 70 if (retlen != SECTORSIZE) {
@@ -242,7 +242,8 @@ The new DiskOnChip driver already scanned the bad block table. Just query it.
242 if (buf[i & (SECTORSIZE - 1)] != 0xff) 242 if (buf[i & (SECTORSIZE - 1)] != 0xff)
243 nftl->ReplUnitTable[i] = BLOCK_RESERVED; 243 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
244#endif 244#endif
245 if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize)) 245 if (mtd_block_isbad(nftl->mbd.mtd,
246 i * nftl->EraseSize))
246 nftl->ReplUnitTable[i] = BLOCK_RESERVED; 247 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
247 } 248 }
248 249
@@ -274,7 +275,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int
274 int i; 275 int i;
275 276
276 for (i = 0; i < len; i += SECTORSIZE) { 277 for (i = 0; i < len; i += SECTORSIZE) {
277 if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf)) 278 if (mtd_read(mtd, address, SECTORSIZE, &retlen, buf))
278 return -1; 279 return -1;
279 if (memcmpb(buf, 0xff, SECTORSIZE) != 0) 280 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
280 return -1; 281 return -1;
@@ -326,7 +327,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
326 instr->mtd = nftl->mbd.mtd; 327 instr->mtd = nftl->mbd.mtd;
327 instr->addr = block * nftl->EraseSize; 328 instr->addr = block * nftl->EraseSize;
328 instr->len = nftl->EraseSize; 329 instr->len = nftl->EraseSize;
329 mtd->erase(mtd, instr); 330 mtd_erase(mtd, instr);
330 331
331 if (instr->state == MTD_ERASE_FAILED) { 332 if (instr->state == MTD_ERASE_FAILED) {
332 printk("Error while formatting block %d\n", block); 333 printk("Error while formatting block %d\n", block);
@@ -355,7 +356,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
355fail: 356fail:
356 /* could not format, update the bad block table (caller is responsible 357 /* could not format, update the bad block table (caller is responsible
357 for setting the ReplUnitTable to BLOCK_RESERVED on failure) */ 358 for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
358 nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr); 359 mtd_block_markbad(nftl->mbd.mtd, instr->addr);
359 return -1; 360 return -1;
360} 361}
361 362
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 7813095264a..0ccd5bff254 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -115,21 +115,9 @@ static struct platform_driver generic_onenand_driver = {
115 .remove = __devexit_p(generic_onenand_remove), 115 .remove = __devexit_p(generic_onenand_remove),
116}; 116};
117 117
118MODULE_ALIAS("platform:" DRIVER_NAME); 118module_platform_driver(generic_onenand_driver);
119
120static int __init generic_onenand_init(void)
121{
122 return platform_driver_register(&generic_onenand_driver);
123}
124
125static void __exit generic_onenand_exit(void)
126{
127 platform_driver_unregister(&generic_onenand_driver);
128}
129
130module_init(generic_onenand_init);
131module_exit(generic_onenand_exit);
132 119
133MODULE_LICENSE("GPL"); 120MODULE_LICENSE("GPL");
134MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); 121MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
135MODULE_DESCRIPTION("Glue layer for OneNAND flash on generic boards"); 122MODULE_DESCRIPTION("Glue layer for OneNAND flash on generic boards");
123MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index a8394730b4b..a061bc163da 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -2633,7 +2633,6 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
2633 */ 2633 */
2634static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) 2634static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
2635{ 2635{
2636 struct onenand_chip *this = mtd->priv;
2637 int ret; 2636 int ret;
2638 2637
2639 ret = onenand_block_isbad(mtd, ofs); 2638 ret = onenand_block_isbad(mtd, ofs);
@@ -2645,7 +2644,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
2645 } 2644 }
2646 2645
2647 onenand_get_device(mtd, FL_WRITING); 2646 onenand_get_device(mtd, FL_WRITING);
2648 ret = this->block_markbad(mtd, ofs); 2647 ret = mtd_block_markbad(mtd, ofs);
2649 onenand_release_device(mtd); 2648 onenand_release_device(mtd);
2650 return ret; 2649 return ret;
2651} 2650}
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 5474547eafc..fa1ee43f735 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -1133,18 +1133,7 @@ static struct platform_driver s3c_onenand_driver = {
1133 .remove = __devexit_p(s3c_onenand_remove), 1133 .remove = __devexit_p(s3c_onenand_remove),
1134}; 1134};
1135 1135
1136static int __init s3c_onenand_init(void) 1136module_platform_driver(s3c_onenand_driver);
1137{
1138 return platform_driver_register(&s3c_onenand_driver);
1139}
1140
1141static void __exit s3c_onenand_exit(void)
1142{
1143 platform_driver_unregister(&s3c_onenand_driver);
1144}
1145
1146module_init(s3c_onenand_init);
1147module_exit(s3c_onenand_exit);
1148 1137
1149MODULE_LICENSE("GPL"); 1138MODULE_LICENSE("GPL");
1150MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); 1139MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index e366b1d84ea..48970c14bef 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -78,8 +78,8 @@ static int parse_redboot_partitions(struct mtd_info *master,
78 78
79 if ( directory < 0 ) { 79 if ( directory < 0 ) {
80 offset = master->size + directory * master->erasesize; 80 offset = master->size + directory * master->erasesize;
81 while (master->block_isbad && 81 while (mtd_can_have_bb(master) &&
82 master->block_isbad(master, offset)) { 82 mtd_block_isbad(master, offset)) {
83 if (!offset) { 83 if (!offset) {
84 nogood: 84 nogood:
85 printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n"); 85 printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n");
@@ -89,8 +89,8 @@ static int parse_redboot_partitions(struct mtd_info *master,
89 } 89 }
90 } else { 90 } else {
91 offset = directory * master->erasesize; 91 offset = directory * master->erasesize;
92 while (master->block_isbad && 92 while (mtd_can_have_bb(master) &&
93 master->block_isbad(master, offset)) { 93 mtd_block_isbad(master, offset)) {
94 offset += master->erasesize; 94 offset += master->erasesize;
95 if (offset == master->size) 95 if (offset == master->size)
96 goto nogood; 96 goto nogood;
@@ -104,8 +104,8 @@ static int parse_redboot_partitions(struct mtd_info *master,
104 printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n", 104 printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n",
105 master->name, offset); 105 master->name, offset);
106 106
107 ret = master->read(master, offset, 107 ret = mtd_read(master, offset, master->erasesize, &retlen,
108 master->erasesize, &retlen, (void *)buf); 108 (void *)buf);
109 109
110 if (ret) 110 if (ret)
111 goto out; 111 goto out;
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 73ae217a425..233b946e5d6 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -200,9 +200,9 @@ static int scan_header(struct partition *part)
200 part->sector_map[i] = -1; 200 part->sector_map[i] = -1;
201 201
202 for (i=0, blocks_found=0; i<part->total_blocks; i++) { 202 for (i=0, blocks_found=0; i<part->total_blocks; i++) {
203 rc = part->mbd.mtd->read(part->mbd.mtd, 203 rc = mtd_read(part->mbd.mtd, i * part->block_size,
204 i * part->block_size, part->header_size, 204 part->header_size, &retlen,
205 &retlen, (u_char*)part->header_cache); 205 (u_char *)part->header_cache);
206 206
207 if (!rc && retlen != part->header_size) 207 if (!rc && retlen != part->header_size)
208 rc = -EIO; 208 rc = -EIO;
@@ -250,8 +250,8 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b
250 250
251 addr = part->sector_map[sector]; 251 addr = part->sector_map[sector];
252 if (addr != -1) { 252 if (addr != -1) {
253 rc = part->mbd.mtd->read(part->mbd.mtd, addr, SECTOR_SIZE, 253 rc = mtd_read(part->mbd.mtd, addr, SECTOR_SIZE, &retlen,
254 &retlen, (u_char*)buf); 254 (u_char *)buf);
255 if (!rc && retlen != SECTOR_SIZE) 255 if (!rc && retlen != SECTOR_SIZE)
256 rc = -EIO; 256 rc = -EIO;
257 257
@@ -304,9 +304,8 @@ static void erase_callback(struct erase_info *erase)
304 part->blocks[i].used_sectors = 0; 304 part->blocks[i].used_sectors = 0;
305 part->blocks[i].erases++; 305 part->blocks[i].erases++;
306 306
307 rc = part->mbd.mtd->write(part->mbd.mtd, 307 rc = mtd_write(part->mbd.mtd, part->blocks[i].offset, sizeof(magic),
308 part->blocks[i].offset, sizeof(magic), &retlen, 308 &retlen, (u_char *)&magic);
309 (u_char*)&magic);
310 309
311 if (!rc && retlen != sizeof(magic)) 310 if (!rc && retlen != sizeof(magic))
312 rc = -EIO; 311 rc = -EIO;
@@ -342,7 +341,7 @@ static int erase_block(struct partition *part, int block)
342 part->blocks[block].state = BLOCK_ERASING; 341 part->blocks[block].state = BLOCK_ERASING;
343 part->blocks[block].free_sectors = 0; 342 part->blocks[block].free_sectors = 0;
344 343
345 rc = part->mbd.mtd->erase(part->mbd.mtd, erase); 344 rc = mtd_erase(part->mbd.mtd, erase);
346 345
347 if (rc) { 346 if (rc) {
348 printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' " 347 printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' "
@@ -372,9 +371,8 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
372 if (!map) 371 if (!map)
373 goto err2; 372 goto err2;
374 373
375 rc = part->mbd.mtd->read(part->mbd.mtd, 374 rc = mtd_read(part->mbd.mtd, part->blocks[block_no].offset,
376 part->blocks[block_no].offset, part->header_size, 375 part->header_size, &retlen, (u_char *)map);
377 &retlen, (u_char*)map);
378 376
379 if (!rc && retlen != part->header_size) 377 if (!rc && retlen != part->header_size)
380 rc = -EIO; 378 rc = -EIO;
@@ -413,8 +411,8 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
413 } 411 }
414 continue; 412 continue;
415 } 413 }
416 rc = part->mbd.mtd->read(part->mbd.mtd, addr, 414 rc = mtd_read(part->mbd.mtd, addr, SECTOR_SIZE, &retlen,
417 SECTOR_SIZE, &retlen, sector_data); 415 sector_data);
418 416
419 if (!rc && retlen != SECTOR_SIZE) 417 if (!rc && retlen != SECTOR_SIZE)
420 rc = -EIO; 418 rc = -EIO;
@@ -450,8 +448,7 @@ static int reclaim_block(struct partition *part, u_long *old_sector)
450 int rc; 448 int rc;
451 449
452 /* we have a race if sync doesn't exist */ 450 /* we have a race if sync doesn't exist */
453 if (part->mbd.mtd->sync) 451 mtd_sync(part->mbd.mtd);
454 part->mbd.mtd->sync(part->mbd.mtd);
455 452
456 score = 0x7fffffff; /* MAX_INT */ 453 score = 0x7fffffff; /* MAX_INT */
457 best_block = -1; 454 best_block = -1;
@@ -563,8 +560,9 @@ static int find_writable_block(struct partition *part, u_long *old_sector)
563 } 560 }
564 } 561 }
565 562
566 rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, 563 rc = mtd_read(part->mbd.mtd, part->blocks[block].offset,
567 part->header_size, &retlen, (u_char*)part->header_cache); 564 part->header_size, &retlen,
565 (u_char *)part->header_cache);
568 566
569 if (!rc && retlen != part->header_size) 567 if (!rc && retlen != part->header_size)
570 rc = -EIO; 568 rc = -EIO;
@@ -595,8 +593,8 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
595 593
596 addr = part->blocks[block].offset + 594 addr = part->blocks[block].offset +
597 (HEADER_MAP_OFFSET + offset) * sizeof(u16); 595 (HEADER_MAP_OFFSET + offset) * sizeof(u16);
598 rc = part->mbd.mtd->write(part->mbd.mtd, addr, 596 rc = mtd_write(part->mbd.mtd, addr, sizeof(del), &retlen,
599 sizeof(del), &retlen, (u_char*)&del); 597 (u_char *)&del);
600 598
601 if (!rc && retlen != sizeof(del)) 599 if (!rc && retlen != sizeof(del))
602 rc = -EIO; 600 rc = -EIO;
@@ -668,8 +666,8 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
668 666
669 addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + 667 addr = (i + part->header_sectors_per_block) * SECTOR_SIZE +
670 block->offset; 668 block->offset;
671 rc = part->mbd.mtd->write(part->mbd.mtd, 669 rc = mtd_write(part->mbd.mtd, addr, SECTOR_SIZE, &retlen,
672 addr, SECTOR_SIZE, &retlen, (u_char*)buf); 670 (u_char *)buf);
673 671
674 if (!rc && retlen != SECTOR_SIZE) 672 if (!rc && retlen != SECTOR_SIZE)
675 rc = -EIO; 673 rc = -EIO;
@@ -688,8 +686,8 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
688 part->header_cache[i + HEADER_MAP_OFFSET] = entry; 686 part->header_cache[i + HEADER_MAP_OFFSET] = entry;
689 687
690 addr = block->offset + (HEADER_MAP_OFFSET + i) * sizeof(u16); 688 addr = block->offset + (HEADER_MAP_OFFSET + i) * sizeof(u16);
691 rc = part->mbd.mtd->write(part->mbd.mtd, addr, 689 rc = mtd_write(part->mbd.mtd, addr, sizeof(entry), &retlen,
692 sizeof(entry), &retlen, (u_char*)&entry); 690 (u_char *)&entry);
693 691
694 if (!rc && retlen != sizeof(entry)) 692 if (!rc && retlen != sizeof(entry))
695 rc = -EIO; 693 rc = -EIO;
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index fddb714e323..072ed5970e2 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -25,7 +25,7 @@
25struct workqueue_struct *cache_flush_workqueue; 25struct workqueue_struct *cache_flush_workqueue;
26 26
27static int cache_timeout = 1000; 27static int cache_timeout = 1000;
28module_param(cache_timeout, bool, S_IRUGO); 28module_param(cache_timeout, int, S_IRUGO);
29MODULE_PARM_DESC(cache_timeout, 29MODULE_PARM_DESC(cache_timeout,
30 "Timeout (in ms) for cache flush (1000 ms default"); 30 "Timeout (in ms) for cache flush (1000 ms default");
31 31
@@ -278,7 +278,7 @@ again:
278 278
279 /* Unfortunately, oob read will _always_ succeed, 279 /* Unfortunately, oob read will _always_ succeed,
280 despite card removal..... */ 280 despite card removal..... */
281 ret = mtd->read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); 281 ret = mtd_read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
282 282
283 /* Test for unknown errors */ 283 /* Test for unknown errors */
284 if (ret != 0 && !mtd_is_bitflip_or_eccerr(ret)) { 284 if (ret != 0 && !mtd_is_bitflip_or_eccerr(ret)) {
@@ -343,7 +343,7 @@ static int sm_write_sector(struct sm_ftl *ftl,
343 ops.ooblen = SM_OOB_SIZE; 343 ops.ooblen = SM_OOB_SIZE;
344 ops.oobbuf = (void *)oob; 344 ops.oobbuf = (void *)oob;
345 345
346 ret = mtd->write_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); 346 ret = mtd_write_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops);
347 347
348 /* Now we assume that hardware will catch write bitflip errors */ 348 /* Now we assume that hardware will catch write bitflip errors */
349 /* If you are paranoid, use CONFIG_MTD_NAND_VERIFY_WRITE */ 349 /* If you are paranoid, use CONFIG_MTD_NAND_VERIFY_WRITE */
@@ -479,7 +479,7 @@ static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block,
479 return -EIO; 479 return -EIO;
480 } 480 }
481 481
482 if (mtd->erase(mtd, &erase)) { 482 if (mtd_erase(mtd, &erase)) {
483 sm_printk("erase of block %d in zone %d failed", 483 sm_printk("erase of block %d in zone %d failed",
484 block, zone_num); 484 block, zone_num);
485 goto error; 485 goto error;
@@ -645,8 +645,8 @@ int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd)
645 if (!ftl->smallpagenand && mtd->oobsize < SM_OOB_SIZE) 645 if (!ftl->smallpagenand && mtd->oobsize < SM_OOB_SIZE)
646 return -ENODEV; 646 return -ENODEV;
647 647
648 /* We use these functions for IO */ 648 /* We use OOB */
649 if (!mtd->read_oob || !mtd->write_oob) 649 if (!mtd_has_oob(mtd))
650 return -ENODEV; 650 return -ENODEV;
651 651
652 /* Find geometry information */ 652 /* Find geometry information */
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 976e3d28b96..ab2a52a039c 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -122,9 +122,9 @@ static int get_valid_cis_sector(struct mtd_info *mtd)
122 * is not SSFDC formatted 122 * is not SSFDC formatted
123 */ 123 */
124 for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) { 124 for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) {
125 if (!mtd->block_isbad(mtd, offset)) { 125 if (mtd_block_isbad(mtd, offset)) {
126 ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, 126 ret = mtd_read(mtd, offset, SECTOR_SIZE, &retlen,
127 sect_buf); 127 sect_buf);
128 128
129 /* CIS pattern match on the sector buffer */ 129 /* CIS pattern match on the sector buffer */
130 if (ret < 0 || retlen != SECTOR_SIZE) { 130 if (ret < 0 || retlen != SECTOR_SIZE) {
@@ -156,7 +156,7 @@ static int read_physical_sector(struct mtd_info *mtd, uint8_t *sect_buf,
156 size_t retlen; 156 size_t retlen;
157 loff_t offset = (loff_t)sect_no << SECTOR_SHIFT; 157 loff_t offset = (loff_t)sect_no << SECTOR_SHIFT;
158 158
159 ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, sect_buf); 159 ret = mtd_read(mtd, offset, SECTOR_SIZE, &retlen, sect_buf);
160 if (ret < 0 || retlen != SECTOR_SIZE) 160 if (ret < 0 || retlen != SECTOR_SIZE)
161 return -1; 161 return -1;
162 162
@@ -175,7 +175,7 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
175 ops.oobbuf = buf; 175 ops.oobbuf = buf;
176 ops.datbuf = NULL; 176 ops.datbuf = NULL;
177 177
178 ret = mtd->read_oob(mtd, offs, &ops); 178 ret = mtd_read_oob(mtd, offs, &ops);
179 if (ret < 0 || ops.oobretlen != OOB_SIZE) 179 if (ret < 0 || ops.oobretlen != OOB_SIZE)
180 return -1; 180 return -1;
181 181
@@ -255,7 +255,7 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc)
255 for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len; 255 for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len;
256 phys_block++) { 256 phys_block++) {
257 offset = (unsigned long)phys_block * ssfdc->erase_size; 257 offset = (unsigned long)phys_block * ssfdc->erase_size;
258 if (mtd->block_isbad(mtd, offset)) 258 if (mtd_block_isbad(mtd, offset))
259 continue; /* skip bad blocks */ 259 continue; /* skip bad blocks */
260 260
261 ret = read_raw_oob(mtd, offset, oob_buf); 261 ret = read_raw_oob(mtd, offset, oob_buf);
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
index 933f7e5f32d..ed9b62827f1 100644
--- a/drivers/mtd/tests/mtd_oobtest.c
+++ b/drivers/mtd/tests/mtd_oobtest.c
@@ -78,7 +78,7 @@ static int erase_eraseblock(int ebnum)
78 ei.addr = addr; 78 ei.addr = addr;
79 ei.len = mtd->erasesize; 79 ei.len = mtd->erasesize;
80 80
81 err = mtd->erase(mtd, &ei); 81 err = mtd_erase(mtd, &ei);
82 if (err) { 82 if (err) {
83 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 83 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
84 return err; 84 return err;
@@ -139,7 +139,7 @@ static int write_eraseblock(int ebnum)
139 ops.ooboffs = use_offset; 139 ops.ooboffs = use_offset;
140 ops.datbuf = NULL; 140 ops.datbuf = NULL;
141 ops.oobbuf = writebuf; 141 ops.oobbuf = writebuf;
142 err = mtd->write_oob(mtd, addr, &ops); 142 err = mtd_write_oob(mtd, addr, &ops);
143 if (err || ops.oobretlen != use_len) { 143 if (err || ops.oobretlen != use_len) {
144 printk(PRINT_PREF "error: writeoob failed at %#llx\n", 144 printk(PRINT_PREF "error: writeoob failed at %#llx\n",
145 (long long)addr); 145 (long long)addr);
@@ -192,7 +192,7 @@ static int verify_eraseblock(int ebnum)
192 ops.ooboffs = use_offset; 192 ops.ooboffs = use_offset;
193 ops.datbuf = NULL; 193 ops.datbuf = NULL;
194 ops.oobbuf = readbuf; 194 ops.oobbuf = readbuf;
195 err = mtd->read_oob(mtd, addr, &ops); 195 err = mtd_read_oob(mtd, addr, &ops);
196 if (err || ops.oobretlen != use_len) { 196 if (err || ops.oobretlen != use_len) {
197 printk(PRINT_PREF "error: readoob failed at %#llx\n", 197 printk(PRINT_PREF "error: readoob failed at %#llx\n",
198 (long long)addr); 198 (long long)addr);
@@ -219,7 +219,7 @@ static int verify_eraseblock(int ebnum)
219 ops.ooboffs = 0; 219 ops.ooboffs = 0;
220 ops.datbuf = NULL; 220 ops.datbuf = NULL;
221 ops.oobbuf = readbuf; 221 ops.oobbuf = readbuf;
222 err = mtd->read_oob(mtd, addr, &ops); 222 err = mtd_read_oob(mtd, addr, &ops);
223 if (err || ops.oobretlen != mtd->ecclayout->oobavail) { 223 if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
224 printk(PRINT_PREF "error: readoob failed at " 224 printk(PRINT_PREF "error: readoob failed at "
225 "%#llx\n", (long long)addr); 225 "%#llx\n", (long long)addr);
@@ -284,7 +284,7 @@ static int verify_eraseblock_in_one_go(int ebnum)
284 ops.ooboffs = 0; 284 ops.ooboffs = 0;
285 ops.datbuf = NULL; 285 ops.datbuf = NULL;
286 ops.oobbuf = readbuf; 286 ops.oobbuf = readbuf;
287 err = mtd->read_oob(mtd, addr, &ops); 287 err = mtd_read_oob(mtd, addr, &ops);
288 if (err || ops.oobretlen != len) { 288 if (err || ops.oobretlen != len) {
289 printk(PRINT_PREF "error: readoob failed at %#llx\n", 289 printk(PRINT_PREF "error: readoob failed at %#llx\n",
290 (long long)addr); 290 (long long)addr);
@@ -329,7 +329,7 @@ static int is_block_bad(int ebnum)
329 int ret; 329 int ret;
330 loff_t addr = ebnum * mtd->erasesize; 330 loff_t addr = ebnum * mtd->erasesize;
331 331
332 ret = mtd->block_isbad(mtd, addr); 332 ret = mtd_block_isbad(mtd, addr);
333 if (ret) 333 if (ret)
334 printk(PRINT_PREF "block %d is bad\n", ebnum); 334 printk(PRINT_PREF "block %d is bad\n", ebnum);
335 return ret; 335 return ret;
@@ -524,7 +524,7 @@ static int __init mtd_oobtest_init(void)
524 ops.oobbuf = writebuf; 524 ops.oobbuf = writebuf;
525 printk(PRINT_PREF "attempting to start write past end of OOB\n"); 525 printk(PRINT_PREF "attempting to start write past end of OOB\n");
526 printk(PRINT_PREF "an error is expected...\n"); 526 printk(PRINT_PREF "an error is expected...\n");
527 err = mtd->write_oob(mtd, addr0, &ops); 527 err = mtd_write_oob(mtd, addr0, &ops);
528 if (err) { 528 if (err) {
529 printk(PRINT_PREF "error occurred as expected\n"); 529 printk(PRINT_PREF "error occurred as expected\n");
530 err = 0; 530 err = 0;
@@ -544,7 +544,7 @@ static int __init mtd_oobtest_init(void)
544 ops.oobbuf = readbuf; 544 ops.oobbuf = readbuf;
545 printk(PRINT_PREF "attempting to start read past end of OOB\n"); 545 printk(PRINT_PREF "attempting to start read past end of OOB\n");
546 printk(PRINT_PREF "an error is expected...\n"); 546 printk(PRINT_PREF "an error is expected...\n");
547 err = mtd->read_oob(mtd, addr0, &ops); 547 err = mtd_read_oob(mtd, addr0, &ops);
548 if (err) { 548 if (err) {
549 printk(PRINT_PREF "error occurred as expected\n"); 549 printk(PRINT_PREF "error occurred as expected\n");
550 err = 0; 550 err = 0;
@@ -568,7 +568,7 @@ static int __init mtd_oobtest_init(void)
568 ops.oobbuf = writebuf; 568 ops.oobbuf = writebuf;
569 printk(PRINT_PREF "attempting to write past end of device\n"); 569 printk(PRINT_PREF "attempting to write past end of device\n");
570 printk(PRINT_PREF "an error is expected...\n"); 570 printk(PRINT_PREF "an error is expected...\n");
571 err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops); 571 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
572 if (err) { 572 if (err) {
573 printk(PRINT_PREF "error occurred as expected\n"); 573 printk(PRINT_PREF "error occurred as expected\n");
574 err = 0; 574 err = 0;
@@ -588,7 +588,7 @@ static int __init mtd_oobtest_init(void)
588 ops.oobbuf = readbuf; 588 ops.oobbuf = readbuf;
589 printk(PRINT_PREF "attempting to read past end of device\n"); 589 printk(PRINT_PREF "attempting to read past end of device\n");
590 printk(PRINT_PREF "an error is expected...\n"); 590 printk(PRINT_PREF "an error is expected...\n");
591 err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops); 591 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
592 if (err) { 592 if (err) {
593 printk(PRINT_PREF "error occurred as expected\n"); 593 printk(PRINT_PREF "error occurred as expected\n");
594 err = 0; 594 err = 0;
@@ -612,7 +612,7 @@ static int __init mtd_oobtest_init(void)
612 ops.oobbuf = writebuf; 612 ops.oobbuf = writebuf;
613 printk(PRINT_PREF "attempting to write past end of device\n"); 613 printk(PRINT_PREF "attempting to write past end of device\n");
614 printk(PRINT_PREF "an error is expected...\n"); 614 printk(PRINT_PREF "an error is expected...\n");
615 err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops); 615 err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
616 if (err) { 616 if (err) {
617 printk(PRINT_PREF "error occurred as expected\n"); 617 printk(PRINT_PREF "error occurred as expected\n");
618 err = 0; 618 err = 0;
@@ -632,7 +632,7 @@ static int __init mtd_oobtest_init(void)
632 ops.oobbuf = readbuf; 632 ops.oobbuf = readbuf;
633 printk(PRINT_PREF "attempting to read past end of device\n"); 633 printk(PRINT_PREF "attempting to read past end of device\n");
634 printk(PRINT_PREF "an error is expected...\n"); 634 printk(PRINT_PREF "an error is expected...\n");
635 err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops); 635 err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
636 if (err) { 636 if (err) {
637 printk(PRINT_PREF "error occurred as expected\n"); 637 printk(PRINT_PREF "error occurred as expected\n");
638 err = 0; 638 err = 0;
@@ -670,7 +670,7 @@ static int __init mtd_oobtest_init(void)
670 ops.ooboffs = 0; 670 ops.ooboffs = 0;
671 ops.datbuf = NULL; 671 ops.datbuf = NULL;
672 ops.oobbuf = writebuf; 672 ops.oobbuf = writebuf;
673 err = mtd->write_oob(mtd, addr, &ops); 673 err = mtd_write_oob(mtd, addr, &ops);
674 if (err) 674 if (err)
675 goto out; 675 goto out;
676 if (i % 256 == 0) 676 if (i % 256 == 0)
@@ -698,7 +698,7 @@ static int __init mtd_oobtest_init(void)
698 ops.ooboffs = 0; 698 ops.ooboffs = 0;
699 ops.datbuf = NULL; 699 ops.datbuf = NULL;
700 ops.oobbuf = readbuf; 700 ops.oobbuf = readbuf;
701 err = mtd->read_oob(mtd, addr, &ops); 701 err = mtd_read_oob(mtd, addr, &ops);
702 if (err) 702 if (err)
703 goto out; 703 goto out;
704 if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) { 704 if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
index afafb6935fd..252ddb092fb 100644
--- a/drivers/mtd/tests/mtd_pagetest.c
+++ b/drivers/mtd/tests/mtd_pagetest.c
@@ -77,7 +77,7 @@ static int erase_eraseblock(int ebnum)
77 ei.addr = addr; 77 ei.addr = addr;
78 ei.len = mtd->erasesize; 78 ei.len = mtd->erasesize;
79 79
80 err = mtd->erase(mtd, &ei); 80 err = mtd_erase(mtd, &ei);
81 if (err) { 81 if (err) {
82 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 82 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
83 return err; 83 return err;
@@ -95,12 +95,12 @@ static int erase_eraseblock(int ebnum)
95static int write_eraseblock(int ebnum) 95static int write_eraseblock(int ebnum)
96{ 96{
97 int err = 0; 97 int err = 0;
98 size_t written = 0; 98 size_t written;
99 loff_t addr = ebnum * mtd->erasesize; 99 loff_t addr = ebnum * mtd->erasesize;
100 100
101 set_random_data(writebuf, mtd->erasesize); 101 set_random_data(writebuf, mtd->erasesize);
102 cond_resched(); 102 cond_resched();
103 err = mtd->write(mtd, addr, mtd->erasesize, &written, writebuf); 103 err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
104 if (err || written != mtd->erasesize) 104 if (err || written != mtd->erasesize)
105 printk(PRINT_PREF "error: write failed at %#llx\n", 105 printk(PRINT_PREF "error: write failed at %#llx\n",
106 (long long)addr); 106 (long long)addr);
@@ -111,7 +111,7 @@ static int write_eraseblock(int ebnum)
111static int verify_eraseblock(int ebnum) 111static int verify_eraseblock(int ebnum)
112{ 112{
113 uint32_t j; 113 uint32_t j;
114 size_t read = 0; 114 size_t read;
115 int err = 0, i; 115 int err = 0, i;
116 loff_t addr0, addrn; 116 loff_t addr0, addrn;
117 loff_t addr = ebnum * mtd->erasesize; 117 loff_t addr = ebnum * mtd->erasesize;
@@ -127,7 +127,7 @@ static int verify_eraseblock(int ebnum)
127 set_random_data(writebuf, mtd->erasesize); 127 set_random_data(writebuf, mtd->erasesize);
128 for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { 128 for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
129 /* Do a read to set the internal dataRAMs to different data */ 129 /* Do a read to set the internal dataRAMs to different data */
130 err = mtd->read(mtd, addr0, bufsize, &read, twopages); 130 err = mtd_read(mtd, addr0, bufsize, &read, twopages);
131 if (mtd_is_bitflip(err)) 131 if (mtd_is_bitflip(err))
132 err = 0; 132 err = 0;
133 if (err || read != bufsize) { 133 if (err || read != bufsize) {
@@ -135,7 +135,7 @@ static int verify_eraseblock(int ebnum)
135 (long long)addr0); 135 (long long)addr0);
136 return err; 136 return err;
137 } 137 }
138 err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); 138 err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
139 if (mtd_is_bitflip(err)) 139 if (mtd_is_bitflip(err))
140 err = 0; 140 err = 0;
141 if (err || read != bufsize) { 141 if (err || read != bufsize) {
@@ -144,8 +144,7 @@ static int verify_eraseblock(int ebnum)
144 return err; 144 return err;
145 } 145 }
146 memset(twopages, 0, bufsize); 146 memset(twopages, 0, bufsize);
147 read = 0; 147 err = mtd_read(mtd, addr, bufsize, &read, twopages);
148 err = mtd->read(mtd, addr, bufsize, &read, twopages);
149 if (mtd_is_bitflip(err)) 148 if (mtd_is_bitflip(err))
150 err = 0; 149 err = 0;
151 if (err || read != bufsize) { 150 if (err || read != bufsize) {
@@ -163,7 +162,7 @@ static int verify_eraseblock(int ebnum)
163 if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) { 162 if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
164 unsigned long oldnext = next; 163 unsigned long oldnext = next;
165 /* Do a read to set the internal dataRAMs to different data */ 164 /* Do a read to set the internal dataRAMs to different data */
166 err = mtd->read(mtd, addr0, bufsize, &read, twopages); 165 err = mtd_read(mtd, addr0, bufsize, &read, twopages);
167 if (mtd_is_bitflip(err)) 166 if (mtd_is_bitflip(err))
168 err = 0; 167 err = 0;
169 if (err || read != bufsize) { 168 if (err || read != bufsize) {
@@ -171,7 +170,7 @@ static int verify_eraseblock(int ebnum)
171 (long long)addr0); 170 (long long)addr0);
172 return err; 171 return err;
173 } 172 }
174 err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages); 173 err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages);
175 if (mtd_is_bitflip(err)) 174 if (mtd_is_bitflip(err))
176 err = 0; 175 err = 0;
177 if (err || read != bufsize) { 176 if (err || read != bufsize) {
@@ -180,8 +179,7 @@ static int verify_eraseblock(int ebnum)
180 return err; 179 return err;
181 } 180 }
182 memset(twopages, 0, bufsize); 181 memset(twopages, 0, bufsize);
183 read = 0; 182 err = mtd_read(mtd, addr, bufsize, &read, twopages);
184 err = mtd->read(mtd, addr, bufsize, &read, twopages);
185 if (mtd_is_bitflip(err)) 183 if (mtd_is_bitflip(err))
186 err = 0; 184 err = 0;
187 if (err || read != bufsize) { 185 if (err || read != bufsize) {
@@ -203,7 +201,7 @@ static int verify_eraseblock(int ebnum)
203 201
204static int crosstest(void) 202static int crosstest(void)
205{ 203{
206 size_t read = 0; 204 size_t read;
207 int err = 0, i; 205 int err = 0, i;
208 loff_t addr, addr0, addrn; 206 loff_t addr, addr0, addrn;
209 unsigned char *pp1, *pp2, *pp3, *pp4; 207 unsigned char *pp1, *pp2, *pp3, *pp4;
@@ -228,9 +226,8 @@ static int crosstest(void)
228 addrn -= mtd->erasesize; 226 addrn -= mtd->erasesize;
229 227
230 /* Read 2nd-to-last page to pp1 */ 228 /* Read 2nd-to-last page to pp1 */
231 read = 0;
232 addr = addrn - pgsize - pgsize; 229 addr = addrn - pgsize - pgsize;
233 err = mtd->read(mtd, addr, pgsize, &read, pp1); 230 err = mtd_read(mtd, addr, pgsize, &read, pp1);
234 if (mtd_is_bitflip(err)) 231 if (mtd_is_bitflip(err))
235 err = 0; 232 err = 0;
236 if (err || read != pgsize) { 233 if (err || read != pgsize) {
@@ -241,9 +238,8 @@ static int crosstest(void)
241 } 238 }
242 239
243 /* Read 3rd-to-last page to pp1 */ 240 /* Read 3rd-to-last page to pp1 */
244 read = 0;
245 addr = addrn - pgsize - pgsize - pgsize; 241 addr = addrn - pgsize - pgsize - pgsize;
246 err = mtd->read(mtd, addr, pgsize, &read, pp1); 242 err = mtd_read(mtd, addr, pgsize, &read, pp1);
247 if (mtd_is_bitflip(err)) 243 if (mtd_is_bitflip(err))
248 err = 0; 244 err = 0;
249 if (err || read != pgsize) { 245 if (err || read != pgsize) {
@@ -254,10 +250,9 @@ static int crosstest(void)
254 } 250 }
255 251
256 /* Read first page to pp2 */ 252 /* Read first page to pp2 */
257 read = 0;
258 addr = addr0; 253 addr = addr0;
259 printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); 254 printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
260 err = mtd->read(mtd, addr, pgsize, &read, pp2); 255 err = mtd_read(mtd, addr, pgsize, &read, pp2);
261 if (mtd_is_bitflip(err)) 256 if (mtd_is_bitflip(err))
262 err = 0; 257 err = 0;
263 if (err || read != pgsize) { 258 if (err || read != pgsize) {
@@ -268,10 +263,9 @@ static int crosstest(void)
268 } 263 }
269 264
270 /* Read last page to pp3 */ 265 /* Read last page to pp3 */
271 read = 0;
272 addr = addrn - pgsize; 266 addr = addrn - pgsize;
273 printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); 267 printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
274 err = mtd->read(mtd, addr, pgsize, &read, pp3); 268 err = mtd_read(mtd, addr, pgsize, &read, pp3);
275 if (mtd_is_bitflip(err)) 269 if (mtd_is_bitflip(err))
276 err = 0; 270 err = 0;
277 if (err || read != pgsize) { 271 if (err || read != pgsize) {
@@ -282,10 +276,9 @@ static int crosstest(void)
282 } 276 }
283 277
284 /* Read first page again to pp4 */ 278 /* Read first page again to pp4 */
285 read = 0;
286 addr = addr0; 279 addr = addr0;
287 printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); 280 printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
288 err = mtd->read(mtd, addr, pgsize, &read, pp4); 281 err = mtd_read(mtd, addr, pgsize, &read, pp4);
289 if (mtd_is_bitflip(err)) 282 if (mtd_is_bitflip(err))
290 err = 0; 283 err = 0;
291 if (err || read != pgsize) { 284 if (err || read != pgsize) {
@@ -309,7 +302,7 @@ static int crosstest(void)
309 302
310static int erasecrosstest(void) 303static int erasecrosstest(void)
311{ 304{
312 size_t read = 0, written = 0; 305 size_t read, written;
313 int err = 0, i, ebnum, ebnum2; 306 int err = 0, i, ebnum, ebnum2;
314 loff_t addr0; 307 loff_t addr0;
315 char *readbuf = twopages; 308 char *readbuf = twopages;
@@ -335,7 +328,7 @@ static int erasecrosstest(void)
335 printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); 328 printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
336 set_random_data(writebuf, pgsize); 329 set_random_data(writebuf, pgsize);
337 strcpy(writebuf, "There is no data like this!"); 330 strcpy(writebuf, "There is no data like this!");
338 err = mtd->write(mtd, addr0, pgsize, &written, writebuf); 331 err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
339 if (err || written != pgsize) { 332 if (err || written != pgsize) {
340 printk(PRINT_PREF "error: write failed at %#llx\n", 333 printk(PRINT_PREF "error: write failed at %#llx\n",
341 (long long)addr0); 334 (long long)addr0);
@@ -344,7 +337,7 @@ static int erasecrosstest(void)
344 337
345 printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); 338 printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
346 memset(readbuf, 0, pgsize); 339 memset(readbuf, 0, pgsize);
347 err = mtd->read(mtd, addr0, pgsize, &read, readbuf); 340 err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
348 if (mtd_is_bitflip(err)) 341 if (mtd_is_bitflip(err))
349 err = 0; 342 err = 0;
350 if (err || read != pgsize) { 343 if (err || read != pgsize) {
@@ -368,7 +361,7 @@ static int erasecrosstest(void)
368 printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); 361 printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
369 set_random_data(writebuf, pgsize); 362 set_random_data(writebuf, pgsize);
370 strcpy(writebuf, "There is no data like this!"); 363 strcpy(writebuf, "There is no data like this!");
371 err = mtd->write(mtd, addr0, pgsize, &written, writebuf); 364 err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
372 if (err || written != pgsize) { 365 if (err || written != pgsize) {
373 printk(PRINT_PREF "error: write failed at %#llx\n", 366 printk(PRINT_PREF "error: write failed at %#llx\n",
374 (long long)addr0); 367 (long long)addr0);
@@ -382,7 +375,7 @@ static int erasecrosstest(void)
382 375
383 printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); 376 printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
384 memset(readbuf, 0, pgsize); 377 memset(readbuf, 0, pgsize);
385 err = mtd->read(mtd, addr0, pgsize, &read, readbuf); 378 err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
386 if (mtd_is_bitflip(err)) 379 if (mtd_is_bitflip(err))
387 err = 0; 380 err = 0;
388 if (err || read != pgsize) { 381 if (err || read != pgsize) {
@@ -405,7 +398,7 @@ static int erasecrosstest(void)
405 398
406static int erasetest(void) 399static int erasetest(void)
407{ 400{
408 size_t read = 0, written = 0; 401 size_t read, written;
409 int err = 0, i, ebnum, ok = 1; 402 int err = 0, i, ebnum, ok = 1;
410 loff_t addr0; 403 loff_t addr0;
411 404
@@ -425,7 +418,7 @@ static int erasetest(void)
425 418
426 printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); 419 printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
427 set_random_data(writebuf, pgsize); 420 set_random_data(writebuf, pgsize);
428 err = mtd->write(mtd, addr0, pgsize, &written, writebuf); 421 err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
429 if (err || written != pgsize) { 422 if (err || written != pgsize) {
430 printk(PRINT_PREF "error: write failed at %#llx\n", 423 printk(PRINT_PREF "error: write failed at %#llx\n",
431 (long long)addr0); 424 (long long)addr0);
@@ -438,7 +431,7 @@ static int erasetest(void)
438 return err; 431 return err;
439 432
440 printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); 433 printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
441 err = mtd->read(mtd, addr0, pgsize, &read, twopages); 434 err = mtd_read(mtd, addr0, pgsize, &read, twopages);
442 if (mtd_is_bitflip(err)) 435 if (mtd_is_bitflip(err))
443 err = 0; 436 err = 0;
444 if (err || read != pgsize) { 437 if (err || read != pgsize) {
@@ -469,7 +462,7 @@ static int is_block_bad(int ebnum)
469 loff_t addr = ebnum * mtd->erasesize; 462 loff_t addr = ebnum * mtd->erasesize;
470 int ret; 463 int ret;
471 464
472 ret = mtd->block_isbad(mtd, addr); 465 ret = mtd_block_isbad(mtd, addr);
473 if (ret) 466 if (ret)
474 printk(PRINT_PREF "block %d is bad\n", ebnum); 467 printk(PRINT_PREF "block %d is bad\n", ebnum);
475 return ret; 468 return ret;
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
index 550fe51225a..121aba189ce 100644
--- a/drivers/mtd/tests/mtd_readtest.c
+++ b/drivers/mtd/tests/mtd_readtest.c
@@ -44,7 +44,7 @@ static int pgcnt;
44 44
45static int read_eraseblock_by_page(int ebnum) 45static int read_eraseblock_by_page(int ebnum)
46{ 46{
47 size_t read = 0; 47 size_t read;
48 int i, ret, err = 0; 48 int i, ret, err = 0;
49 loff_t addr = ebnum * mtd->erasesize; 49 loff_t addr = ebnum * mtd->erasesize;
50 void *buf = iobuf; 50 void *buf = iobuf;
@@ -52,7 +52,7 @@ static int read_eraseblock_by_page(int ebnum)
52 52
53 for (i = 0; i < pgcnt; i++) { 53 for (i = 0; i < pgcnt; i++) {
54 memset(buf, 0 , pgcnt); 54 memset(buf, 0 , pgcnt);
55 ret = mtd->read(mtd, addr, pgsize, &read, buf); 55 ret = mtd_read(mtd, addr, pgsize, &read, buf);
56 if (ret == -EUCLEAN) 56 if (ret == -EUCLEAN)
57 ret = 0; 57 ret = 0;
58 if (ret || read != pgsize) { 58 if (ret || read != pgsize) {
@@ -74,7 +74,7 @@ static int read_eraseblock_by_page(int ebnum)
74 ops.ooboffs = 0; 74 ops.ooboffs = 0;
75 ops.datbuf = NULL; 75 ops.datbuf = NULL;
76 ops.oobbuf = oobbuf; 76 ops.oobbuf = oobbuf;
77 ret = mtd->read_oob(mtd, addr, &ops); 77 ret = mtd_read_oob(mtd, addr, &ops);
78 if ((ret && !mtd_is_bitflip(ret)) || 78 if ((ret && !mtd_is_bitflip(ret)) ||
79 ops.oobretlen != mtd->oobsize) { 79 ops.oobretlen != mtd->oobsize) {
80 printk(PRINT_PREF "error: read oob failed at " 80 printk(PRINT_PREF "error: read oob failed at "
@@ -132,7 +132,7 @@ static int is_block_bad(int ebnum)
132 loff_t addr = ebnum * mtd->erasesize; 132 loff_t addr = ebnum * mtd->erasesize;
133 int ret; 133 int ret;
134 134
135 ret = mtd->block_isbad(mtd, addr); 135 ret = mtd_block_isbad(mtd, addr);
136 if (ret) 136 if (ret)
137 printk(PRINT_PREF "block %d is bad\n", ebnum); 137 printk(PRINT_PREF "block %d is bad\n", ebnum);
138 return ret; 138 return ret;
@@ -148,8 +148,7 @@ static int scan_for_bad_eraseblocks(void)
148 return -ENOMEM; 148 return -ENOMEM;
149 } 149 }
150 150
151 /* NOR flash does not implement block_isbad */ 151 if (!mtd_can_have_bb(mtd))
152 if (mtd->block_isbad == NULL)
153 return 0; 152 return 0;
154 153
155 printk(PRINT_PREF "scanning for bad eraseblocks\n"); 154 printk(PRINT_PREF "scanning for bad eraseblocks\n");
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c
index 493b367bdd3..2aec4f3b72b 100644
--- a/drivers/mtd/tests/mtd_speedtest.c
+++ b/drivers/mtd/tests/mtd_speedtest.c
@@ -79,7 +79,7 @@ static int erase_eraseblock(int ebnum)
79 ei.addr = addr; 79 ei.addr = addr;
80 ei.len = mtd->erasesize; 80 ei.len = mtd->erasesize;
81 81
82 err = mtd->erase(mtd, &ei); 82 err = mtd_erase(mtd, &ei);
83 if (err) { 83 if (err) {
84 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 84 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
85 return err; 85 return err;
@@ -105,7 +105,7 @@ static int multiblock_erase(int ebnum, int blocks)
105 ei.addr = addr; 105 ei.addr = addr;
106 ei.len = mtd->erasesize * blocks; 106 ei.len = mtd->erasesize * blocks;
107 107
108 err = mtd->erase(mtd, &ei); 108 err = mtd_erase(mtd, &ei);
109 if (err) { 109 if (err) {
110 printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n", 110 printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n",
111 err, ebnum, blocks); 111 err, ebnum, blocks);
@@ -139,11 +139,11 @@ static int erase_whole_device(void)
139 139
140static int write_eraseblock(int ebnum) 140static int write_eraseblock(int ebnum)
141{ 141{
142 size_t written = 0; 142 size_t written;
143 int err = 0; 143 int err = 0;
144 loff_t addr = ebnum * mtd->erasesize; 144 loff_t addr = ebnum * mtd->erasesize;
145 145
146 err = mtd->write(mtd, addr, mtd->erasesize, &written, iobuf); 146 err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf);
147 if (err || written != mtd->erasesize) { 147 if (err || written != mtd->erasesize) {
148 printk(PRINT_PREF "error: write failed at %#llx\n", addr); 148 printk(PRINT_PREF "error: write failed at %#llx\n", addr);
149 if (!err) 149 if (!err)
@@ -155,13 +155,13 @@ static int write_eraseblock(int ebnum)
155 155
156static int write_eraseblock_by_page(int ebnum) 156static int write_eraseblock_by_page(int ebnum)
157{ 157{
158 size_t written = 0; 158 size_t written;
159 int i, err = 0; 159 int i, err = 0;
160 loff_t addr = ebnum * mtd->erasesize; 160 loff_t addr = ebnum * mtd->erasesize;
161 void *buf = iobuf; 161 void *buf = iobuf;
162 162
163 for (i = 0; i < pgcnt; i++) { 163 for (i = 0; i < pgcnt; i++) {
164 err = mtd->write(mtd, addr, pgsize, &written, buf); 164 err = mtd_write(mtd, addr, pgsize, &written, buf);
165 if (err || written != pgsize) { 165 if (err || written != pgsize) {
166 printk(PRINT_PREF "error: write failed at %#llx\n", 166 printk(PRINT_PREF "error: write failed at %#llx\n",
167 addr); 167 addr);
@@ -178,13 +178,13 @@ static int write_eraseblock_by_page(int ebnum)
178 178
179static int write_eraseblock_by_2pages(int ebnum) 179static int write_eraseblock_by_2pages(int ebnum)
180{ 180{
181 size_t written = 0, sz = pgsize * 2; 181 size_t written, sz = pgsize * 2;
182 int i, n = pgcnt / 2, err = 0; 182 int i, n = pgcnt / 2, err = 0;
183 loff_t addr = ebnum * mtd->erasesize; 183 loff_t addr = ebnum * mtd->erasesize;
184 void *buf = iobuf; 184 void *buf = iobuf;
185 185
186 for (i = 0; i < n; i++) { 186 for (i = 0; i < n; i++) {
187 err = mtd->write(mtd, addr, sz, &written, buf); 187 err = mtd_write(mtd, addr, sz, &written, buf);
188 if (err || written != sz) { 188 if (err || written != sz) {
189 printk(PRINT_PREF "error: write failed at %#llx\n", 189 printk(PRINT_PREF "error: write failed at %#llx\n",
190 addr); 190 addr);
@@ -196,7 +196,7 @@ static int write_eraseblock_by_2pages(int ebnum)
196 buf += sz; 196 buf += sz;
197 } 197 }
198 if (pgcnt % 2) { 198 if (pgcnt % 2) {
199 err = mtd->write(mtd, addr, pgsize, &written, buf); 199 err = mtd_write(mtd, addr, pgsize, &written, buf);
200 if (err || written != pgsize) { 200 if (err || written != pgsize) {
201 printk(PRINT_PREF "error: write failed at %#llx\n", 201 printk(PRINT_PREF "error: write failed at %#llx\n",
202 addr); 202 addr);
@@ -210,11 +210,11 @@ static int write_eraseblock_by_2pages(int ebnum)
210 210
211static int read_eraseblock(int ebnum) 211static int read_eraseblock(int ebnum)
212{ 212{
213 size_t read = 0; 213 size_t read;
214 int err = 0; 214 int err = 0;
215 loff_t addr = ebnum * mtd->erasesize; 215 loff_t addr = ebnum * mtd->erasesize;
216 216
217 err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf); 217 err = mtd_read(mtd, addr, mtd->erasesize, &read, iobuf);
218 /* Ignore corrected ECC errors */ 218 /* Ignore corrected ECC errors */
219 if (mtd_is_bitflip(err)) 219 if (mtd_is_bitflip(err))
220 err = 0; 220 err = 0;
@@ -229,13 +229,13 @@ static int read_eraseblock(int ebnum)
229 229
230static int read_eraseblock_by_page(int ebnum) 230static int read_eraseblock_by_page(int ebnum)
231{ 231{
232 size_t read = 0; 232 size_t read;
233 int i, err = 0; 233 int i, err = 0;
234 loff_t addr = ebnum * mtd->erasesize; 234 loff_t addr = ebnum * mtd->erasesize;
235 void *buf = iobuf; 235 void *buf = iobuf;
236 236
237 for (i = 0; i < pgcnt; i++) { 237 for (i = 0; i < pgcnt; i++) {
238 err = mtd->read(mtd, addr, pgsize, &read, buf); 238 err = mtd_read(mtd, addr, pgsize, &read, buf);
239 /* Ignore corrected ECC errors */ 239 /* Ignore corrected ECC errors */
240 if (mtd_is_bitflip(err)) 240 if (mtd_is_bitflip(err))
241 err = 0; 241 err = 0;
@@ -255,13 +255,13 @@ static int read_eraseblock_by_page(int ebnum)
255 255
256static int read_eraseblock_by_2pages(int ebnum) 256static int read_eraseblock_by_2pages(int ebnum)
257{ 257{
258 size_t read = 0, sz = pgsize * 2; 258 size_t read, sz = pgsize * 2;
259 int i, n = pgcnt / 2, err = 0; 259 int i, n = pgcnt / 2, err = 0;
260 loff_t addr = ebnum * mtd->erasesize; 260 loff_t addr = ebnum * mtd->erasesize;
261 void *buf = iobuf; 261 void *buf = iobuf;
262 262
263 for (i = 0; i < n; i++) { 263 for (i = 0; i < n; i++) {
264 err = mtd->read(mtd, addr, sz, &read, buf); 264 err = mtd_read(mtd, addr, sz, &read, buf);
265 /* Ignore corrected ECC errors */ 265 /* Ignore corrected ECC errors */
266 if (mtd_is_bitflip(err)) 266 if (mtd_is_bitflip(err))
267 err = 0; 267 err = 0;
@@ -276,7 +276,7 @@ static int read_eraseblock_by_2pages(int ebnum)
276 buf += sz; 276 buf += sz;
277 } 277 }
278 if (pgcnt % 2) { 278 if (pgcnt % 2) {
279 err = mtd->read(mtd, addr, pgsize, &read, buf); 279 err = mtd_read(mtd, addr, pgsize, &read, buf);
280 /* Ignore corrected ECC errors */ 280 /* Ignore corrected ECC errors */
281 if (mtd_is_bitflip(err)) 281 if (mtd_is_bitflip(err))
282 err = 0; 282 err = 0;
@@ -296,7 +296,7 @@ static int is_block_bad(int ebnum)
296 loff_t addr = ebnum * mtd->erasesize; 296 loff_t addr = ebnum * mtd->erasesize;
297 int ret; 297 int ret;
298 298
299 ret = mtd->block_isbad(mtd, addr); 299 ret = mtd_block_isbad(mtd, addr);
300 if (ret) 300 if (ret)
301 printk(PRINT_PREF "block %d is bad\n", ebnum); 301 printk(PRINT_PREF "block %d is bad\n", ebnum);
302 return ret; 302 return ret;
@@ -336,8 +336,7 @@ static int scan_for_bad_eraseblocks(void)
336 return -ENOMEM; 336 return -ENOMEM;
337 } 337 }
338 338
339 /* NOR flash does not implement block_isbad */ 339 if (!mtd_can_have_bb(mtd))
340 if (mtd->block_isbad == NULL)
341 goto out; 340 goto out;
342 341
343 printk(PRINT_PREF "scanning for bad eraseblocks\n"); 342 printk(PRINT_PREF "scanning for bad eraseblocks\n");
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
index 52ffd9120e0..7b33f22d0b5 100644
--- a/drivers/mtd/tests/mtd_stresstest.c
+++ b/drivers/mtd/tests/mtd_stresstest.c
@@ -112,7 +112,7 @@ static int erase_eraseblock(int ebnum)
112 ei.addr = addr; 112 ei.addr = addr;
113 ei.len = mtd->erasesize; 113 ei.len = mtd->erasesize;
114 114
115 err = mtd->erase(mtd, &ei); 115 err = mtd_erase(mtd, &ei);
116 if (unlikely(err)) { 116 if (unlikely(err)) {
117 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 117 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
118 return err; 118 return err;
@@ -132,7 +132,7 @@ static int is_block_bad(int ebnum)
132 loff_t addr = ebnum * mtd->erasesize; 132 loff_t addr = ebnum * mtd->erasesize;
133 int ret; 133 int ret;
134 134
135 ret = mtd->block_isbad(mtd, addr); 135 ret = mtd_block_isbad(mtd, addr);
136 if (ret) 136 if (ret)
137 printk(PRINT_PREF "block %d is bad\n", ebnum); 137 printk(PRINT_PREF "block %d is bad\n", ebnum);
138 return ret; 138 return ret;
@@ -140,7 +140,7 @@ static int is_block_bad(int ebnum)
140 140
141static int do_read(void) 141static int do_read(void)
142{ 142{
143 size_t read = 0; 143 size_t read;
144 int eb = rand_eb(); 144 int eb = rand_eb();
145 int offs = rand_offs(); 145 int offs = rand_offs();
146 int len = rand_len(offs), err; 146 int len = rand_len(offs), err;
@@ -153,7 +153,7 @@ static int do_read(void)
153 len = mtd->erasesize - offs; 153 len = mtd->erasesize - offs;
154 } 154 }
155 addr = eb * mtd->erasesize + offs; 155 addr = eb * mtd->erasesize + offs;
156 err = mtd->read(mtd, addr, len, &read, readbuf); 156 err = mtd_read(mtd, addr, len, &read, readbuf);
157 if (mtd_is_bitflip(err)) 157 if (mtd_is_bitflip(err))
158 err = 0; 158 err = 0;
159 if (unlikely(err || read != len)) { 159 if (unlikely(err || read != len)) {
@@ -169,7 +169,7 @@ static int do_read(void)
169static int do_write(void) 169static int do_write(void)
170{ 170{
171 int eb = rand_eb(), offs, err, len; 171 int eb = rand_eb(), offs, err, len;
172 size_t written = 0; 172 size_t written;
173 loff_t addr; 173 loff_t addr;
174 174
175 offs = offsets[eb]; 175 offs = offsets[eb];
@@ -192,7 +192,7 @@ static int do_write(void)
192 } 192 }
193 } 193 }
194 addr = eb * mtd->erasesize + offs; 194 addr = eb * mtd->erasesize + offs;
195 err = mtd->write(mtd, addr, len, &written, writebuf); 195 err = mtd_write(mtd, addr, len, &written, writebuf);
196 if (unlikely(err || written != len)) { 196 if (unlikely(err || written != len)) {
197 printk(PRINT_PREF "error: write failed at 0x%llx\n", 197 printk(PRINT_PREF "error: write failed at 0x%llx\n",
198 (long long)addr); 198 (long long)addr);
@@ -227,8 +227,7 @@ static int scan_for_bad_eraseblocks(void)
227 return -ENOMEM; 227 return -ENOMEM;
228 } 228 }
229 229
230 /* NOR flash does not implement block_isbad */ 230 if (!mtd_can_have_bb(mtd))
231 if (mtd->block_isbad == NULL)
232 return 0; 231 return 0;
233 232
234 printk(PRINT_PREF "scanning for bad eraseblocks\n"); 233 printk(PRINT_PREF "scanning for bad eraseblocks\n");
@@ -284,6 +283,12 @@ static int __init mtd_stresstest_init(void)
284 (unsigned long long)mtd->size, mtd->erasesize, 283 (unsigned long long)mtd->size, mtd->erasesize,
285 pgsize, ebcnt, pgcnt, mtd->oobsize); 284 pgsize, ebcnt, pgcnt, mtd->oobsize);
286 285
286 if (ebcnt < 2) {
287 printk(PRINT_PREF "error: need at least 2 eraseblocks\n");
288 err = -ENOSPC;
289 goto out_put_mtd;
290 }
291
287 /* Read or write up 2 eraseblocks at a time */ 292 /* Read or write up 2 eraseblocks at a time */
288 bufsize = mtd->erasesize * 2; 293 bufsize = mtd->erasesize * 2;
289 294
@@ -322,6 +327,7 @@ out:
322 kfree(bbt); 327 kfree(bbt);
323 vfree(writebuf); 328 vfree(writebuf);
324 vfree(readbuf); 329 vfree(readbuf);
330out_put_mtd:
325 put_mtd_device(mtd); 331 put_mtd_device(mtd);
326 if (err) 332 if (err)
327 printk(PRINT_PREF "error %d occurred\n", err); 333 printk(PRINT_PREF "error %d occurred\n", err);
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c
index 1a05bfac4ee..9667bf53528 100644
--- a/drivers/mtd/tests/mtd_subpagetest.c
+++ b/drivers/mtd/tests/mtd_subpagetest.c
@@ -80,7 +80,7 @@ static int erase_eraseblock(int ebnum)
80 ei.addr = addr; 80 ei.addr = addr;
81 ei.len = mtd->erasesize; 81 ei.len = mtd->erasesize;
82 82
83 err = mtd->erase(mtd, &ei); 83 err = mtd_erase(mtd, &ei);
84 if (err) { 84 if (err) {
85 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 85 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
86 return err; 86 return err;
@@ -115,12 +115,12 @@ static int erase_whole_device(void)
115 115
116static int write_eraseblock(int ebnum) 116static int write_eraseblock(int ebnum)
117{ 117{
118 size_t written = 0; 118 size_t written;
119 int err = 0; 119 int err = 0;
120 loff_t addr = ebnum * mtd->erasesize; 120 loff_t addr = ebnum * mtd->erasesize;
121 121
122 set_random_data(writebuf, subpgsize); 122 set_random_data(writebuf, subpgsize);
123 err = mtd->write(mtd, addr, subpgsize, &written, writebuf); 123 err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
124 if (unlikely(err || written != subpgsize)) { 124 if (unlikely(err || written != subpgsize)) {
125 printk(PRINT_PREF "error: write failed at %#llx\n", 125 printk(PRINT_PREF "error: write failed at %#llx\n",
126 (long long)addr); 126 (long long)addr);
@@ -134,7 +134,7 @@ static int write_eraseblock(int ebnum)
134 addr += subpgsize; 134 addr += subpgsize;
135 135
136 set_random_data(writebuf, subpgsize); 136 set_random_data(writebuf, subpgsize);
137 err = mtd->write(mtd, addr, subpgsize, &written, writebuf); 137 err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
138 if (unlikely(err || written != subpgsize)) { 138 if (unlikely(err || written != subpgsize)) {
139 printk(PRINT_PREF "error: write failed at %#llx\n", 139 printk(PRINT_PREF "error: write failed at %#llx\n",
140 (long long)addr); 140 (long long)addr);
@@ -150,7 +150,7 @@ static int write_eraseblock(int ebnum)
150 150
151static int write_eraseblock2(int ebnum) 151static int write_eraseblock2(int ebnum)
152{ 152{
153 size_t written = 0; 153 size_t written;
154 int err = 0, k; 154 int err = 0, k;
155 loff_t addr = ebnum * mtd->erasesize; 155 loff_t addr = ebnum * mtd->erasesize;
156 156
@@ -158,7 +158,7 @@ static int write_eraseblock2(int ebnum)
158 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize) 158 if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
159 break; 159 break;
160 set_random_data(writebuf, subpgsize * k); 160 set_random_data(writebuf, subpgsize * k);
161 err = mtd->write(mtd, addr, subpgsize * k, &written, writebuf); 161 err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
162 if (unlikely(err || written != subpgsize * k)) { 162 if (unlikely(err || written != subpgsize * k)) {
163 printk(PRINT_PREF "error: write failed at %#llx\n", 163 printk(PRINT_PREF "error: write failed at %#llx\n",
164 (long long)addr); 164 (long long)addr);
@@ -189,14 +189,13 @@ static void print_subpage(unsigned char *p)
189 189
190static int verify_eraseblock(int ebnum) 190static int verify_eraseblock(int ebnum)
191{ 191{
192 size_t read = 0; 192 size_t read;
193 int err = 0; 193 int err = 0;
194 loff_t addr = ebnum * mtd->erasesize; 194 loff_t addr = ebnum * mtd->erasesize;
195 195
196 set_random_data(writebuf, subpgsize); 196 set_random_data(writebuf, subpgsize);
197 clear_data(readbuf, subpgsize); 197 clear_data(readbuf, subpgsize);
198 read = 0; 198 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
199 err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
200 if (unlikely(err || read != subpgsize)) { 199 if (unlikely(err || read != subpgsize)) {
201 if (mtd_is_bitflip(err) && read == subpgsize) { 200 if (mtd_is_bitflip(err) && read == subpgsize) {
202 printk(PRINT_PREF "ECC correction at %#llx\n", 201 printk(PRINT_PREF "ECC correction at %#llx\n",
@@ -223,8 +222,7 @@ static int verify_eraseblock(int ebnum)
223 222
224 set_random_data(writebuf, subpgsize); 223 set_random_data(writebuf, subpgsize);
225 clear_data(readbuf, subpgsize); 224 clear_data(readbuf, subpgsize);
226 read = 0; 225 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
227 err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
228 if (unlikely(err || read != subpgsize)) { 226 if (unlikely(err || read != subpgsize)) {
229 if (mtd_is_bitflip(err) && read == subpgsize) { 227 if (mtd_is_bitflip(err) && read == subpgsize) {
230 printk(PRINT_PREF "ECC correction at %#llx\n", 228 printk(PRINT_PREF "ECC correction at %#llx\n",
@@ -252,7 +250,7 @@ static int verify_eraseblock(int ebnum)
252 250
253static int verify_eraseblock2(int ebnum) 251static int verify_eraseblock2(int ebnum)
254{ 252{
255 size_t read = 0; 253 size_t read;
256 int err = 0, k; 254 int err = 0, k;
257 loff_t addr = ebnum * mtd->erasesize; 255 loff_t addr = ebnum * mtd->erasesize;
258 256
@@ -261,8 +259,7 @@ static int verify_eraseblock2(int ebnum)
261 break; 259 break;
262 set_random_data(writebuf, subpgsize * k); 260 set_random_data(writebuf, subpgsize * k);
263 clear_data(readbuf, subpgsize * k); 261 clear_data(readbuf, subpgsize * k);
264 read = 0; 262 err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
265 err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf);
266 if (unlikely(err || read != subpgsize * k)) { 263 if (unlikely(err || read != subpgsize * k)) {
267 if (mtd_is_bitflip(err) && read == subpgsize * k) { 264 if (mtd_is_bitflip(err) && read == subpgsize * k) {
268 printk(PRINT_PREF "ECC correction at %#llx\n", 265 printk(PRINT_PREF "ECC correction at %#llx\n",
@@ -288,15 +285,14 @@ static int verify_eraseblock2(int ebnum)
288static int verify_eraseblock_ff(int ebnum) 285static int verify_eraseblock_ff(int ebnum)
289{ 286{
290 uint32_t j; 287 uint32_t j;
291 size_t read = 0; 288 size_t read;
292 int err = 0; 289 int err = 0;
293 loff_t addr = ebnum * mtd->erasesize; 290 loff_t addr = ebnum * mtd->erasesize;
294 291
295 memset(writebuf, 0xff, subpgsize); 292 memset(writebuf, 0xff, subpgsize);
296 for (j = 0; j < mtd->erasesize / subpgsize; ++j) { 293 for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
297 clear_data(readbuf, subpgsize); 294 clear_data(readbuf, subpgsize);
298 read = 0; 295 err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
299 err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
300 if (unlikely(err || read != subpgsize)) { 296 if (unlikely(err || read != subpgsize)) {
301 if (mtd_is_bitflip(err) && read == subpgsize) { 297 if (mtd_is_bitflip(err) && read == subpgsize) {
302 printk(PRINT_PREF "ECC correction at %#llx\n", 298 printk(PRINT_PREF "ECC correction at %#llx\n",
@@ -344,7 +340,7 @@ static int is_block_bad(int ebnum)
344 loff_t addr = ebnum * mtd->erasesize; 340 loff_t addr = ebnum * mtd->erasesize;
345 int ret; 341 int ret;
346 342
347 ret = mtd->block_isbad(mtd, addr); 343 ret = mtd_block_isbad(mtd, addr);
348 if (ret) 344 if (ret)
349 printk(PRINT_PREF "block %d is bad\n", ebnum); 345 printk(PRINT_PREF "block %d is bad\n", ebnum);
350 return ret; 346 return ret;
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c
index 03ab649a696..b65861bc7b8 100644
--- a/drivers/mtd/tests/mtd_torturetest.c
+++ b/drivers/mtd/tests/mtd_torturetest.c
@@ -105,7 +105,7 @@ static inline int erase_eraseblock(int ebnum)
105 ei.addr = addr; 105 ei.addr = addr;
106 ei.len = mtd->erasesize; 106 ei.len = mtd->erasesize;
107 107
108 err = mtd->erase(mtd, &ei); 108 err = mtd_erase(mtd, &ei);
109 if (err) { 109 if (err) {
110 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); 110 printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
111 return err; 111 return err;
@@ -127,7 +127,7 @@ static inline int erase_eraseblock(int ebnum)
127static inline int check_eraseblock(int ebnum, unsigned char *buf) 127static inline int check_eraseblock(int ebnum, unsigned char *buf)
128{ 128{
129 int err, retries = 0; 129 int err, retries = 0;
130 size_t read = 0; 130 size_t read;
131 loff_t addr = ebnum * mtd->erasesize; 131 loff_t addr = ebnum * mtd->erasesize;
132 size_t len = mtd->erasesize; 132 size_t len = mtd->erasesize;
133 133
@@ -137,7 +137,7 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf)
137 } 137 }
138 138
139retry: 139retry:
140 err = mtd->read(mtd, addr, len, &read, check_buf); 140 err = mtd_read(mtd, addr, len, &read, check_buf);
141 if (mtd_is_bitflip(err)) 141 if (mtd_is_bitflip(err))
142 printk(PRINT_PREF "single bit flip occurred at EB %d " 142 printk(PRINT_PREF "single bit flip occurred at EB %d "
143 "MTD reported that it was fixed.\n", ebnum); 143 "MTD reported that it was fixed.\n", ebnum);
@@ -181,7 +181,7 @@ retry:
181static inline int write_pattern(int ebnum, void *buf) 181static inline int write_pattern(int ebnum, void *buf)
182{ 182{
183 int err; 183 int err;
184 size_t written = 0; 184 size_t written;
185 loff_t addr = ebnum * mtd->erasesize; 185 loff_t addr = ebnum * mtd->erasesize;
186 size_t len = mtd->erasesize; 186 size_t len = mtd->erasesize;
187 187
@@ -189,7 +189,7 @@ static inline int write_pattern(int ebnum, void *buf)
189 addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; 189 addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
190 len = pgcnt * pgsize; 190 len = pgcnt * pgsize;
191 } 191 }
192 err = mtd->write(mtd, addr, len, &written, buf); 192 err = mtd_write(mtd, addr, len, &written, buf);
193 if (err) { 193 if (err) {
194 printk(PRINT_PREF "error %d while writing EB %d, written %zd" 194 printk(PRINT_PREF "error %d while writing EB %d, written %zd"
195 " bytes\n", err, ebnum, written); 195 " bytes\n", err, ebnum, written);
@@ -290,10 +290,9 @@ static int __init tort_init(void)
290 * Check if there is a bad eraseblock among those we are going to test. 290 * Check if there is a bad eraseblock among those we are going to test.
291 */ 291 */
292 memset(&bad_ebs[0], 0, sizeof(int) * ebcnt); 292 memset(&bad_ebs[0], 0, sizeof(int) * ebcnt);
293 if (mtd->block_isbad) { 293 if (mtd_can_have_bb(mtd)) {
294 for (i = eb; i < eb + ebcnt; i++) { 294 for (i = eb; i < eb + ebcnt; i++) {
295 err = mtd->block_isbad(mtd, 295 err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize);
296 (loff_t)i * mtd->erasesize);
297 296
298 if (err < 0) { 297 if (err < 0) {
299 printk(PRINT_PREF "block_isbad() returned %d " 298 printk(PRINT_PREF "block_isbad() returned %d "
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 6c3fb5ab20f..115749f20f9 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -664,7 +664,7 @@ static int io_init(struct ubi_device *ubi)
664 ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd); 664 ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
665 ubi->flash_size = ubi->mtd->size; 665 ubi->flash_size = ubi->mtd->size;
666 666
667 if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) 667 if (mtd_can_have_bb(ubi->mtd))
668 ubi->bad_allowed = 1; 668 ubi->bad_allowed = 1;
669 669
670 if (ubi->mtd->type == MTD_NORFLASH) { 670 if (ubi->mtd->type == MTD_NORFLASH) {
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index ab80c0debac..e2cdebf4084 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -216,7 +216,7 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
216 buf = vmalloc(len); 216 buf = vmalloc(len);
217 if (!buf) 217 if (!buf)
218 return; 218 return;
219 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); 219 err = mtd_read(ubi->mtd, addr, len, &read, buf);
220 if (err && err != -EUCLEAN) { 220 if (err && err != -EUCLEAN) {
221 ubi_err("error %d while reading %d bytes from PEB %d:%d, " 221 ubi_err("error %d while reading %d bytes from PEB %d:%d, "
222 "read %zd bytes", err, len, pnum, offset, read); 222 "read %zd bytes", err, len, pnum, offset, read);
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index f20b6f22f24..5cde4e5ca3e 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -170,7 +170,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
170 170
171 addr = (loff_t)pnum * ubi->peb_size + offset; 171 addr = (loff_t)pnum * ubi->peb_size + offset;
172retry: 172retry:
173 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); 173 err = mtd_read(ubi->mtd, addr, len, &read, buf);
174 if (err) { 174 if (err) {
175 const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : ""; 175 const char *errstr = mtd_is_eccerr(err) ? " (ECC error)" : "";
176 176
@@ -289,7 +289,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
289 } 289 }
290 290
291 addr = (loff_t)pnum * ubi->peb_size + offset; 291 addr = (loff_t)pnum * ubi->peb_size + offset;
292 err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); 292 err = mtd_write(ubi->mtd, addr, len, &written, buf);
293 if (err) { 293 if (err) {
294 ubi_err("error %d while writing %d bytes to PEB %d:%d, written " 294 ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
295 "%zd bytes", err, len, pnum, offset, written); 295 "%zd bytes", err, len, pnum, offset, written);
@@ -361,7 +361,7 @@ retry:
361 ei.callback = erase_callback; 361 ei.callback = erase_callback;
362 ei.priv = (unsigned long)&wq; 362 ei.priv = (unsigned long)&wq;
363 363
364 err = ubi->mtd->erase(ubi->mtd, &ei); 364 err = mtd_erase(ubi->mtd, &ei);
365 if (err) { 365 if (err) {
366 if (retries++ < UBI_IO_RETRIES) { 366 if (retries++ < UBI_IO_RETRIES) {
367 dbg_io("error %d while erasing PEB %d, retry", 367 dbg_io("error %d while erasing PEB %d, retry",
@@ -525,11 +525,10 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
525 * the header comment in scan.c for more information). 525 * the header comment in scan.c for more information).
526 */ 526 */
527 addr = (loff_t)pnum * ubi->peb_size; 527 addr = (loff_t)pnum * ubi->peb_size;
528 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); 528 err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
529 if (!err) { 529 if (!err) {
530 addr += ubi->vid_hdr_aloffset; 530 addr += ubi->vid_hdr_aloffset;
531 err = ubi->mtd->write(ubi->mtd, addr, 4, &written, 531 err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data);
532 (void *)&data);
533 if (!err) 532 if (!err)
534 return 0; 533 return 0;
535 } 534 }
@@ -635,7 +634,7 @@ int ubi_io_is_bad(const struct ubi_device *ubi, int pnum)
635 if (ubi->bad_allowed) { 634 if (ubi->bad_allowed) {
636 int ret; 635 int ret;
637 636
638 ret = mtd->block_isbad(mtd, (loff_t)pnum * ubi->peb_size); 637 ret = mtd_block_isbad(mtd, (loff_t)pnum * ubi->peb_size);
639 if (ret < 0) 638 if (ret < 0)
640 ubi_err("error %d while checking if PEB %d is bad", 639 ubi_err("error %d while checking if PEB %d is bad",
641 ret, pnum); 640 ret, pnum);
@@ -670,7 +669,7 @@ int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum)
670 if (!ubi->bad_allowed) 669 if (!ubi->bad_allowed)
671 return 0; 670 return 0;
672 671
673 err = mtd->block_markbad(mtd, (loff_t)pnum * ubi->peb_size); 672 err = mtd_block_markbad(mtd, (loff_t)pnum * ubi->peb_size);
674 if (err) 673 if (err)
675 ubi_err("cannot mark PEB %d bad, error %d", pnum, err); 674 ubi_err("cannot mark PEB %d bad, error %d", pnum, err);
676 return err; 675 return err;
@@ -1357,7 +1356,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
1357 return 0; 1356 return 0;
1358 } 1357 }
1359 1358
1360 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1); 1359 err = mtd_read(ubi->mtd, addr, len, &read, buf1);
1361 if (err && !mtd_is_bitflip(err)) 1360 if (err && !mtd_is_bitflip(err))
1362 goto out_free; 1361 goto out_free;
1363 1362
@@ -1421,7 +1420,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
1421 return 0; 1420 return 0;
1422 } 1421 }
1423 1422
1424 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); 1423 err = mtd_read(ubi->mtd, addr, len, &read, buf);
1425 if (err && !mtd_is_bitflip(err)) { 1424 if (err && !mtd_is_bitflip(err)) {
1426 ubi_err("error %d while reading %d bytes from PEB %d:%d, " 1425 ubi_err("error %d while reading %d bytes from PEB %d:%d, "
1427 "read %zd bytes", err, len, pnum, offset, read); 1426 "read %zd bytes", err, len, pnum, offset, read);
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 1a35fc5e3b4..9fdb35367fe 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -714,9 +714,7 @@ int ubi_sync(int ubi_num)
714 if (!ubi) 714 if (!ubi)
715 return -ENODEV; 715 return -ENODEV;
716 716
717 if (ubi->mtd->sync) 717 mtd_sync(ubi->mtd);
718 ubi->mtd->sync(ubi->mtd);
719
720 ubi_put_device(ubi); 718 ubi_put_device(ubi);
721 return 0; 719 return 0;
722} 720}