diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-02-26 14:04:15 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-02-26 14:06:24 -0500 |
commit | a7790532f5b7358c33a6b1834dc2b318de209f31 (patch) | |
tree | 0ceb9e24b3f54cb5c8453fb5a218e2a94a0f1cce /drivers/mtd | |
parent | 2764fb4244cc1bc08df3667924ca4a972e90ac70 (diff) | |
parent | 60b341b778cc2929df16c0a504c91621b3c6a4ad (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
The SmartMedia FTL code depends on new kfifo bits from 2.6.33
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/maps/Kconfig | 17 | ||||
-rw-r--r-- | drivers/mtd/maps/pismo.c | 320 | ||||
-rw-r--r-- | drivers/mtd/maps/pxa2xx-flash.c | 13 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/excite_nandflash.c | 248 | ||||
-rw-r--r-- | drivers/mtd/tests/mtd_readtest.c | 6 | ||||
-rw-r--r-- | drivers/mtd/tests/mtd_speedtest.c | 7 | ||||
-rw-r--r-- | drivers/mtd/tests/mtd_stresstest.c | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/cdev.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 15 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 1 |
13 files changed, 373 insertions, 271 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 4c364d44ad59..2de0cc823d60 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -549,4 +549,21 @@ config MTD_VMU | |||
549 | To build this as a module select M here, the module will be called | 549 | To build this as a module select M here, the module will be called |
550 | vmu-flash. | 550 | vmu-flash. |
551 | 551 | ||
552 | config MTD_PISMO | ||
553 | tristate "MTD discovery driver for PISMO modules" | ||
554 | depends on I2C | ||
555 | depends on ARCH_VERSATILE | ||
556 | help | ||
557 | This driver allows for discovery of PISMO modules - see | ||
558 | <http://www.pismoworld.org/>. These are small modules containing | ||
559 | up to five memory devices (eg, SRAM, flash, DOC) described by an | ||
560 | I2C EEPROM. | ||
561 | |||
562 | This driver does not create any MTD maps itself; instead it | ||
563 | creates MTD physmap and MTD SRAM platform devices. If you | ||
564 | enable this option, you should consider enabling MTD_PHYSMAP | ||
565 | and/or MTD_PLATRAM according to the devices on your module. | ||
566 | |||
567 | When built as a module, it will be called pismo.ko | ||
568 | |||
552 | endmenu | 569 | endmenu |
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c new file mode 100644 index 000000000000..c48cad271f5d --- /dev/null +++ b/drivers/mtd/maps/pismo.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* | ||
2 | * PISMO memory driver - http://www.pismoworld.org/ | ||
3 | * | ||
4 | * For ARM Realview and Versatile platforms | ||
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. | ||
9 | */ | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/mtd/physmap.h> | ||
17 | #include <linux/mtd/plat-ram.h> | ||
18 | #include <linux/mtd/pismo.h> | ||
19 | |||
20 | #define PISMO_NUM_CS 5 | ||
21 | |||
22 | struct pismo_cs_block { | ||
23 | u8 type; | ||
24 | u8 width; | ||
25 | __le16 access; | ||
26 | __le32 size; | ||
27 | u32 reserved[2]; | ||
28 | char device[32]; | ||
29 | } __packed; | ||
30 | |||
31 | struct pismo_eeprom { | ||
32 | struct pismo_cs_block cs[PISMO_NUM_CS]; | ||
33 | char board[15]; | ||
34 | u8 sum; | ||
35 | } __packed; | ||
36 | |||
37 | struct pismo_mem { | ||
38 | phys_addr_t base; | ||
39 | u32 size; | ||
40 | u16 access; | ||
41 | u8 width; | ||
42 | u8 type; | ||
43 | }; | ||
44 | |||
45 | struct pismo_data { | ||
46 | struct i2c_client *client; | ||
47 | void (*vpp)(void *, int); | ||
48 | void *vpp_data; | ||
49 | struct platform_device *dev[PISMO_NUM_CS]; | ||
50 | }; | ||
51 | |||
52 | /* FIXME: set_vpp could do with a better calling convention */ | ||
53 | static struct pismo_data *vpp_pismo; | ||
54 | static DEFINE_MUTEX(pismo_mutex); | ||
55 | |||
56 | static int pismo_setvpp_probe_fix(struct pismo_data *pismo) | ||
57 | { | ||
58 | mutex_lock(&pismo_mutex); | ||
59 | if (vpp_pismo) { | ||
60 | mutex_unlock(&pismo_mutex); | ||
61 | kfree(pismo); | ||
62 | return -EBUSY; | ||
63 | } | ||
64 | vpp_pismo = pismo; | ||
65 | mutex_unlock(&pismo_mutex); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void pismo_setvpp_remove_fix(struct pismo_data *pismo) | ||
70 | { | ||
71 | mutex_lock(&pismo_mutex); | ||
72 | if (vpp_pismo == pismo) | ||
73 | vpp_pismo = NULL; | ||
74 | mutex_unlock(&pismo_mutex); | ||
75 | } | ||
76 | |||
77 | static void pismo_set_vpp(struct map_info *map, int on) | ||
78 | { | ||
79 | struct pismo_data *pismo = vpp_pismo; | ||
80 | |||
81 | pismo->vpp(pismo->vpp_data, on); | ||
82 | } | ||
83 | /* end of hack */ | ||
84 | |||
85 | |||
86 | static unsigned int __devinit pismo_width_to_bytes(unsigned int width) | ||
87 | { | ||
88 | width &= 15; | ||
89 | if (width > 2) | ||
90 | return 0; | ||
91 | return 1 << width; | ||
92 | } | ||
93 | |||
94 | static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, | ||
95 | u8 addr, size_t size) | ||
96 | { | ||
97 | int ret; | ||
98 | struct i2c_msg msg[] = { | ||
99 | { | ||
100 | .addr = client->addr, | ||
101 | .len = sizeof(addr), | ||
102 | .buf = &addr, | ||
103 | }, { | ||
104 | .addr = client->addr, | ||
105 | .flags = I2C_M_RD, | ||
106 | .len = size, | ||
107 | .buf = buf, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
112 | |||
113 | return ret == ARRAY_SIZE(msg) ? size : -EIO; | ||
114 | } | ||
115 | |||
116 | static int __devinit pismo_add_device(struct pismo_data *pismo, int i, | ||
117 | struct pismo_mem *region, const char *name, void *pdata, size_t psize) | ||
118 | { | ||
119 | struct platform_device *dev; | ||
120 | struct resource res = { }; | ||
121 | phys_addr_t base = region.base; | ||
122 | int ret; | ||
123 | |||
124 | if (base == ~0) | ||
125 | return -ENXIO; | ||
126 | |||
127 | res.start = base; | ||
128 | res.end = base + region->size - 1; | ||
129 | res.flags = IORESOURCE_MEM; | ||
130 | |||
131 | dev = platform_device_alloc(name, i); | ||
132 | if (!dev) | ||
133 | return -ENOMEM; | ||
134 | dev->dev.parent = &pismo->client->dev; | ||
135 | |||
136 | do { | ||
137 | ret = platform_device_add_resources(dev, &res, 1); | ||
138 | if (ret) | ||
139 | break; | ||
140 | |||
141 | ret = platform_device_add_data(dev, pdata, psize); | ||
142 | if (ret) | ||
143 | break; | ||
144 | |||
145 | ret = platform_device_add(dev); | ||
146 | if (ret) | ||
147 | break; | ||
148 | |||
149 | pismo->dev[i] = dev; | ||
150 | return 0; | ||
151 | } while (0); | ||
152 | |||
153 | platform_device_put(dev); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, | ||
158 | struct pismo_mem *region) | ||
159 | { | ||
160 | struct physmap_flash_data data = { | ||
161 | .width = region->width, | ||
162 | }; | ||
163 | |||
164 | if (pismo->vpp) | ||
165 | data.set_vpp = pismo_set_vpp; | ||
166 | |||
167 | return pismo_add_device(pismo, i, region, "physmap-flash", | ||
168 | &data, sizeof(data)); | ||
169 | } | ||
170 | |||
171 | static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, | ||
172 | struct pismo_mem *region) | ||
173 | { | ||
174 | struct platdata_mtd_ram data = { | ||
175 | .bankwidth = region->width, | ||
176 | }; | ||
177 | |||
178 | return pismo_add_device(pismo, i, region, "mtd-ram", | ||
179 | &data, sizeof(data)); | ||
180 | } | ||
181 | |||
182 | static void __devinit pismo_add_one(struct pismo_data *pismo, int i, | ||
183 | const struct pismo_cs_block *cs, phys_addr_t base) | ||
184 | { | ||
185 | struct device *dev = &pismo->client->dev; | ||
186 | struct pismo_mem region; | ||
187 | |||
188 | region.base = base; | ||
189 | region.type = cs->type; | ||
190 | region.width = pismo_width_to_bytes(cs->width); | ||
191 | region.access = le16_to_cpu(cs->access); | ||
192 | region.size = le32_to_cpu(cs->size); | ||
193 | |||
194 | if (region.width == 0) { | ||
195 | dev_err(dev, "cs%u: bad width: %02x, ignoring\n", i, cs->width); | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * FIXME: may need to the platforms memory controller here, but at | ||
201 | * the moment we assume that it has already been correctly setup. | ||
202 | * The memory controller can also tell us the base address as well. | ||
203 | */ | ||
204 | |||
205 | dev_info(dev, "cs%u: %.32s: type %02x access %u00ps size %uK\n", | ||
206 | i, cs->device, region.type, region.access, region.size / 1024); | ||
207 | |||
208 | switch (region.type) { | ||
209 | case 0: | ||
210 | break; | ||
211 | case 1: | ||
212 | /* static DOC */ | ||
213 | break; | ||
214 | case 2: | ||
215 | /* static NOR */ | ||
216 | pismo_add_nor(pismo, i, ®ion); | ||
217 | break; | ||
218 | case 3: | ||
219 | /* static RAM */ | ||
220 | pismo_add_sram(pismo, i, ®ion); | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static int __devexit pismo_remove(struct i2c_client *client) | ||
226 | { | ||
227 | struct pismo_data *pismo = i2c_get_clientdata(client); | ||
228 | int i; | ||
229 | |||
230 | for (i = 0; i < ARRAY_SIZE(pismo->dev); i++) | ||
231 | platform_device_unregister(pismo->dev[i]); | ||
232 | |||
233 | /* FIXME: set_vpp needs saner arguments */ | ||
234 | pismo_setvpp_remove_fix(pismo); | ||
235 | |||
236 | kfree(pismo); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int __devinit pismo_probe(struct i2c_client *client, | ||
242 | const struct i2c_device_id *id) | ||
243 | { | ||
244 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
245 | struct pismo_pdata *pdata = client->dev.platform_data; | ||
246 | struct pismo_eeprom eeprom; | ||
247 | struct pismo_data *pismo; | ||
248 | int ret, i; | ||
249 | |||
250 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
251 | dev_err(&client->dev, "functionality mismatch\n"); | ||
252 | return -EIO; | ||
253 | } | ||
254 | |||
255 | pismo = kzalloc(sizeof(*pismo), GFP_KERNEL); | ||
256 | if (!pismo) | ||
257 | return -ENOMEM; | ||
258 | |||
259 | /* FIXME: set_vpp needs saner arguments */ | ||
260 | ret = pismo_setvpp_probe_fix(pismo); | ||
261 | if (ret) | ||
262 | return ret; | ||
263 | |||
264 | pismo->client = client; | ||
265 | if (pdata) { | ||
266 | pismo->vpp = pdata->set_vpp; | ||
267 | pismo->vpp_data = pdata->vpp_data; | ||
268 | } | ||
269 | i2c_set_clientdata(client, pismo); | ||
270 | |||
271 | ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom)); | ||
272 | if (ret < 0) { | ||
273 | dev_err(&client->dev, "error reading EEPROM: %d\n", ret); | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | dev_info(&client->dev, "%.15s board found\n", eeprom.board); | ||
278 | |||
279 | for (i = 0; i < ARRAY_SIZE(eeprom.cs); i++) | ||
280 | if (eeprom.cs[i].type != 0xff) | ||
281 | pismo_add_one(pismo, i, &eeprom.cs[i], | ||
282 | pdata->cs_addrs[i]); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static const struct i2c_device_id pismo_id[] = { | ||
288 | { "pismo" }, | ||
289 | { }, | ||
290 | }; | ||
291 | MODULE_DEVICE_TABLE(i2c, pismo_id); | ||
292 | |||
293 | static struct i2c_driver pismo_driver = { | ||
294 | .driver = { | ||
295 | .name = "pismo", | ||
296 | .owner = THIS_MODULE, | ||
297 | }, | ||
298 | .probe = pismo_probe, | ||
299 | .remove = __devexit_p(pismo_remove), | ||
300 | .id_table = pismo_id, | ||
301 | }; | ||
302 | |||
303 | static int __init pismo_init(void) | ||
304 | { | ||
305 | BUILD_BUG_ON(sizeof(struct pismo_cs_block) != 48); | ||
306 | BUILD_BUG_ON(sizeof(struct pismo_eeprom) != 256); | ||
307 | |||
308 | return i2c_add_driver(&pismo_driver); | ||
309 | } | ||
310 | module_init(pismo_init); | ||
311 | |||
312 | static void __exit pismo_exit(void) | ||
313 | { | ||
314 | i2c_del_driver(&pismo_driver); | ||
315 | } | ||
316 | module_exit(pismo_exit); | ||
317 | |||
318 | MODULE_AUTHOR("Russell King <linux@arm.linux.org.uk>"); | ||
319 | MODULE_DESCRIPTION("PISMO memory driver"); | ||
320 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 74fa075c838a..b13f6417b5b2 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
@@ -20,14 +20,23 @@ | |||
20 | 20 | ||
21 | #include <asm/io.h> | 21 | #include <asm/io.h> |
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | #include <asm/cacheflush.h> | ||
24 | 23 | ||
25 | #include <asm/mach/flash.h> | 24 | #include <asm/mach/flash.h> |
26 | 25 | ||
26 | #define CACHELINESIZE 32 | ||
27 | |||
27 | static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, | 28 | static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, |
28 | ssize_t len) | 29 | ssize_t len) |
29 | { | 30 | { |
30 | flush_ioremap_region(map->phys, map->cached, from, len); | 31 | unsigned long start = (unsigned long)map->cached + from; |
32 | unsigned long end = start + len; | ||
33 | |||
34 | start &= ~(CACHELINESIZE - 1); | ||
35 | while (start < end) { | ||
36 | /* invalidate D cache line */ | ||
37 | asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)); | ||
38 | start += CACHELINESIZE; | ||
39 | } | ||
31 | } | 40 | } |
32 | 41 | ||
33 | struct pxa2xx_flash_info { | 42 | struct pxa2xx_flash_info { |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c89aaab15712..7a67218e86fc 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -289,14 +289,6 @@ config MTD_NAND_SHARPSL | |||
289 | tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" | 289 | tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" |
290 | depends on ARCH_PXA | 290 | depends on ARCH_PXA |
291 | 291 | ||
292 | config MTD_NAND_BASLER_EXCITE | ||
293 | tristate "Support for NAND Flash on Basler eXcite" | ||
294 | depends on BASLER_EXCITE | ||
295 | help | ||
296 | This enables the driver for the NAND flash device found on the | ||
297 | Basler eXcite Smart Camera. If built as a module, the driver | ||
298 | will be named excite_nandflash. | ||
299 | |||
300 | config MTD_NAND_CAFE | 292 | config MTD_NAND_CAFE |
301 | tristate "NAND support for OLPC CAFÉ chip" | 293 | tristate "NAND support for OLPC CAFÉ chip" |
302 | depends on PCI | 294 | depends on PCI |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index d9257961a6ee..f39d0b6ed42c 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -27,7 +27,6 @@ obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o | |||
27 | obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o | 27 | obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o |
28 | obj-$(CONFIG_MTD_NAND_OMAP2) += omap2.o | 28 | obj-$(CONFIG_MTD_NAND_OMAP2) += omap2.o |
29 | obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o | 29 | obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o |
30 | obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o | ||
31 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o | 30 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o |
32 | obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o | 31 | obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o |
33 | obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o | 32 | obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o |
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c deleted file mode 100644 index af6a6a5399e1..000000000000 --- a/drivers/mtd/nand/excite_nandflash.c +++ /dev/null | |||
@@ -1,248 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 - 2007 by Basler Vision Technologies AG | ||
3 | * Author: Thomas Koeller <thomas.koeller.qbaslerweb.com> | ||
4 | * Original code by Thies Moeller <thies.moeller@baslerweb.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/ioport.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/err.h> | ||
30 | |||
31 | #include <linux/mtd/mtd.h> | ||
32 | #include <linux/mtd/nand.h> | ||
33 | #include <linux/mtd/nand_ecc.h> | ||
34 | #include <linux/mtd/partitions.h> | ||
35 | |||
36 | #include <asm/io.h> | ||
37 | #include <asm/rm9k-ocd.h> | ||
38 | |||
39 | #include <excite_nandflash.h> | ||
40 | |||
41 | #define EXCITE_NANDFLASH_VERSION "0.1" | ||
42 | |||
43 | /* I/O register offsets */ | ||
44 | #define EXCITE_NANDFLASH_DATA_BYTE 0x00 | ||
45 | #define EXCITE_NANDFLASH_STATUS_BYTE 0x0c | ||
46 | #define EXCITE_NANDFLASH_ADDR_BYTE 0x10 | ||
47 | #define EXCITE_NANDFLASH_CMD_BYTE 0x14 | ||
48 | |||
49 | /* prefix for debug output */ | ||
50 | static const char module_id[] = "excite_nandflash"; | ||
51 | |||
52 | /* | ||
53 | * partition definition | ||
54 | */ | ||
55 | static const struct mtd_partition partition_info[] = { | ||
56 | { | ||
57 | .name = "eXcite RootFS", | ||
58 | .offset = 0, | ||
59 | .size = MTDPART_SIZ_FULL | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | static inline const struct resource * | ||
64 | excite_nand_get_resource(struct platform_device *d, unsigned long flags, | ||
65 | const char *basename) | ||
66 | { | ||
67 | char buf[80]; | ||
68 | |||
69 | if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf) | ||
70 | return NULL; | ||
71 | return platform_get_resource_byname(d, flags, buf); | ||
72 | } | ||
73 | |||
74 | static inline void __iomem * | ||
75 | excite_nand_map_regs(struct platform_device *d, const char *basename) | ||
76 | { | ||
77 | void *result = NULL; | ||
78 | const struct resource *const r = | ||
79 | excite_nand_get_resource(d, IORESOURCE_MEM, basename); | ||
80 | |||
81 | if (r) | ||
82 | result = ioremap_nocache(r->start, r->end + 1 - r->start); | ||
83 | return result; | ||
84 | } | ||
85 | |||
86 | /* controller and mtd information */ | ||
87 | struct excite_nand_drvdata { | ||
88 | struct mtd_info board_mtd; | ||
89 | struct nand_chip board_chip; | ||
90 | void __iomem *regs; | ||
91 | void __iomem *tgt; | ||
92 | }; | ||
93 | |||
94 | /* Control function */ | ||
95 | static void excite_nand_control(struct mtd_info *mtd, int cmd, | ||
96 | unsigned int ctrl) | ||
97 | { | ||
98 | struct excite_nand_drvdata * const d = | ||
99 | container_of(mtd, struct excite_nand_drvdata, board_mtd); | ||
100 | |||
101 | switch (ctrl) { | ||
102 | case NAND_CTRL_CHANGE | NAND_CTRL_CLE: | ||
103 | d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE; | ||
104 | break; | ||
105 | case NAND_CTRL_CHANGE | NAND_CTRL_ALE: | ||
106 | d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE; | ||
107 | break; | ||
108 | case NAND_CTRL_CHANGE | NAND_NCE: | ||
109 | d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE; | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | if (cmd != NAND_CMD_NONE) | ||
114 | __raw_writeb(cmd, d->tgt); | ||
115 | } | ||
116 | |||
117 | /* Return 0 if flash is busy, 1 if ready */ | ||
118 | static int excite_nand_devready(struct mtd_info *mtd) | ||
119 | { | ||
120 | struct excite_nand_drvdata * const drvdata = | ||
121 | container_of(mtd, struct excite_nand_drvdata, board_mtd); | ||
122 | |||
123 | return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Called by device layer to remove the driver. | ||
128 | * The binding to the mtd and all allocated | ||
129 | * resources are released. | ||
130 | */ | ||
131 | static int __devexit excite_nand_remove(struct platform_device *dev) | ||
132 | { | ||
133 | struct excite_nand_drvdata * const this = platform_get_drvdata(dev); | ||
134 | |||
135 | platform_set_drvdata(dev, NULL); | ||
136 | |||
137 | if (unlikely(!this)) { | ||
138 | printk(KERN_ERR "%s: called %s without private data!!", | ||
139 | module_id, __func__); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | /* first thing we need to do is release our mtd | ||
144 | * then go through freeing the resource used | ||
145 | */ | ||
146 | nand_release(&this->board_mtd); | ||
147 | |||
148 | /* free the common resources */ | ||
149 | iounmap(this->regs); | ||
150 | kfree(this); | ||
151 | |||
152 | DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * Called by device layer when it finds a device matching | ||
158 | * one our driver can handle. This code checks to see if | ||
159 | * it can allocate all necessary resources then calls the | ||
160 | * nand layer to look for devices. | ||
161 | */ | ||
162 | static int __init excite_nand_probe(struct platform_device *pdev) | ||
163 | { | ||
164 | struct excite_nand_drvdata *drvdata; /* private driver data */ | ||
165 | struct nand_chip *board_chip; /* private flash chip data */ | ||
166 | struct mtd_info *board_mtd; /* mtd info for this board */ | ||
167 | int scan_res; | ||
168 | |||
169 | drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); | ||
170 | if (unlikely(!drvdata)) { | ||
171 | printk(KERN_ERR "%s: no memory for drvdata\n", | ||
172 | module_id); | ||
173 | return -ENOMEM; | ||
174 | } | ||
175 | |||
176 | /* bind private data into driver */ | ||
177 | platform_set_drvdata(pdev, drvdata); | ||
178 | |||
179 | /* allocate and map the resource */ | ||
180 | drvdata->regs = | ||
181 | excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS); | ||
182 | |||
183 | if (unlikely(!drvdata->regs)) { | ||
184 | printk(KERN_ERR "%s: cannot reserve register region\n", | ||
185 | module_id); | ||
186 | kfree(drvdata); | ||
187 | return -ENXIO; | ||
188 | } | ||
189 | |||
190 | drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE; | ||
191 | |||
192 | /* initialise our chip */ | ||
193 | board_chip = &drvdata->board_chip; | ||
194 | board_chip->IO_ADDR_R = board_chip->IO_ADDR_W = | ||
195 | drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE; | ||
196 | board_chip->cmd_ctrl = excite_nand_control; | ||
197 | board_chip->dev_ready = excite_nand_devready; | ||
198 | board_chip->chip_delay = 25; | ||
199 | board_chip->ecc.mode = NAND_ECC_SOFT; | ||
200 | |||
201 | /* link chip to mtd */ | ||
202 | board_mtd = &drvdata->board_mtd; | ||
203 | board_mtd->priv = board_chip; | ||
204 | |||
205 | DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id); | ||
206 | scan_res = nand_scan(&drvdata->board_mtd, 1); | ||
207 | |||
208 | if (likely(!scan_res)) { | ||
209 | DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id); | ||
210 | add_mtd_partitions(&drvdata->board_mtd, partition_info, | ||
211 | ARRAY_SIZE(partition_info)); | ||
212 | } else { | ||
213 | iounmap(drvdata->regs); | ||
214 | kfree(drvdata); | ||
215 | printk(KERN_ERR "%s: device scan failed\n", module_id); | ||
216 | return -EIO; | ||
217 | } | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static struct platform_driver excite_nand_driver = { | ||
222 | .driver = { | ||
223 | .name = "excite_nand", | ||
224 | .owner = THIS_MODULE, | ||
225 | }, | ||
226 | .probe = excite_nand_probe, | ||
227 | .remove = __devexit_p(excite_nand_remove) | ||
228 | }; | ||
229 | |||
230 | static int __init excite_nand_init(void) | ||
231 | { | ||
232 | pr_info("Basler eXcite nand flash driver Version " | ||
233 | EXCITE_NANDFLASH_VERSION "\n"); | ||
234 | return platform_driver_register(&excite_nand_driver); | ||
235 | } | ||
236 | |||
237 | static void __exit excite_nand_exit(void) | ||
238 | { | ||
239 | platform_driver_unregister(&excite_nand_driver); | ||
240 | } | ||
241 | |||
242 | module_init(excite_nand_init); | ||
243 | module_exit(excite_nand_exit); | ||
244 | |||
245 | MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>"); | ||
246 | MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver"); | ||
247 | MODULE_LICENSE("GPL"); | ||
248 | MODULE_VERSION(EXCITE_NANDFLASH_VERSION) | ||
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c index 79fc4530987b..25c5dd03a837 100644 --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/mtd_readtest.c | |||
@@ -147,6 +147,10 @@ static int scan_for_bad_eraseblocks(void) | |||
147 | } | 147 | } |
148 | memset(bbt, 0 , ebcnt); | 148 | memset(bbt, 0 , ebcnt); |
149 | 149 | ||
150 | /* NOR flash does not implement block_isbad */ | ||
151 | if (mtd->block_isbad == NULL) | ||
152 | return 0; | ||
153 | |||
150 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 154 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); |
151 | for (i = 0; i < ebcnt; ++i) { | 155 | for (i = 0; i < ebcnt; ++i) { |
152 | bbt[i] = is_block_bad(i) ? 1 : 0; | 156 | bbt[i] = is_block_bad(i) ? 1 : 0; |
@@ -184,7 +188,7 @@ static int __init mtd_readtest_init(void) | |||
184 | tmp = mtd->size; | 188 | tmp = mtd->size; |
185 | do_div(tmp, mtd->erasesize); | 189 | do_div(tmp, mtd->erasesize); |
186 | ebcnt = tmp; | 190 | ebcnt = tmp; |
187 | pgcnt = mtd->erasesize / mtd->writesize; | 191 | pgcnt = mtd->erasesize / pgsize; |
188 | 192 | ||
189 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 193 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " |
190 | "page size %u, count of eraseblocks %u, pages per " | 194 | "page size %u, count of eraseblocks %u, pages per " |
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 141363a7e805..7fbb51d4eabe 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c | |||
@@ -301,6 +301,10 @@ static int scan_for_bad_eraseblocks(void) | |||
301 | } | 301 | } |
302 | memset(bbt, 0 , ebcnt); | 302 | memset(bbt, 0 , ebcnt); |
303 | 303 | ||
304 | /* NOR flash does not implement block_isbad */ | ||
305 | if (mtd->block_isbad == NULL) | ||
306 | goto out; | ||
307 | |||
304 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 308 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); |
305 | for (i = 0; i < ebcnt; ++i) { | 309 | for (i = 0; i < ebcnt; ++i) { |
306 | bbt[i] = is_block_bad(i) ? 1 : 0; | 310 | bbt[i] = is_block_bad(i) ? 1 : 0; |
@@ -309,6 +313,7 @@ static int scan_for_bad_eraseblocks(void) | |||
309 | cond_resched(); | 313 | cond_resched(); |
310 | } | 314 | } |
311 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 315 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); |
316 | out: | ||
312 | goodebcnt = ebcnt - bad; | 317 | goodebcnt = ebcnt - bad; |
313 | return 0; | 318 | return 0; |
314 | } | 319 | } |
@@ -340,7 +345,7 @@ static int __init mtd_speedtest_init(void) | |||
340 | tmp = mtd->size; | 345 | tmp = mtd->size; |
341 | do_div(tmp, mtd->erasesize); | 346 | do_div(tmp, mtd->erasesize); |
342 | ebcnt = tmp; | 347 | ebcnt = tmp; |
343 | pgcnt = mtd->erasesize / mtd->writesize; | 348 | pgcnt = mtd->erasesize / pgsize; |
344 | 349 | ||
345 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 350 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " |
346 | "page size %u, count of eraseblocks %u, pages per " | 351 | "page size %u, count of eraseblocks %u, pages per " |
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c index 63920476b57a..a99d3cd737d8 100644 --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/mtd_stresstest.c | |||
@@ -227,6 +227,10 @@ static int scan_for_bad_eraseblocks(void) | |||
227 | } | 227 | } |
228 | memset(bbt, 0 , ebcnt); | 228 | memset(bbt, 0 , ebcnt); |
229 | 229 | ||
230 | /* NOR flash does not implement block_isbad */ | ||
231 | if (mtd->block_isbad == NULL) | ||
232 | return 0; | ||
233 | |||
230 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 234 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); |
231 | for (i = 0; i < ebcnt; ++i) { | 235 | for (i = 0; i < ebcnt; ++i) { |
232 | bbt[i] = is_block_bad(i) ? 1 : 0; | 236 | bbt[i] = is_block_bad(i) ? 1 : 0; |
@@ -265,7 +269,7 @@ static int __init mtd_stresstest_init(void) | |||
265 | tmp = mtd->size; | 269 | tmp = mtd->size; |
266 | do_div(tmp, mtd->erasesize); | 270 | do_div(tmp, mtd->erasesize); |
267 | ebcnt = tmp; | 271 | ebcnt = tmp; |
268 | pgcnt = mtd->erasesize / mtd->writesize; | 272 | pgcnt = mtd->erasesize / pgsize; |
269 | 273 | ||
270 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 274 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " |
271 | "page size %u, count of eraseblocks %u, pages per " | 275 | "page size %u, count of eraseblocks %u, pages per " |
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index f237ddbb2713..111ea41c4ecd 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
@@ -853,7 +853,6 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd, | |||
853 | break; | 853 | break; |
854 | } | 854 | } |
855 | 855 | ||
856 | req.name[req.name_len] = '\0'; | ||
857 | err = verify_mkvol_req(ubi, &req); | 856 | err = verify_mkvol_req(ubi, &req); |
858 | if (err) | 857 | if (err) |
859 | break; | 858 | break; |
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 277786ebaa2c..1361574e2b00 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c | |||
@@ -291,8 +291,7 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm); | |||
291 | */ | 291 | */ |
292 | struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) | 292 | struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) |
293 | { | 293 | { |
294 | int error, ubi_num, vol_id; | 294 | int error, ubi_num, vol_id, mod; |
295 | struct ubi_volume_desc *ret; | ||
296 | struct inode *inode; | 295 | struct inode *inode; |
297 | struct path path; | 296 | struct path path; |
298 | 297 | ||
@@ -306,16 +305,16 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) | |||
306 | return ERR_PTR(error); | 305 | return ERR_PTR(error); |
307 | 306 | ||
308 | inode = path.dentry->d_inode; | 307 | inode = path.dentry->d_inode; |
308 | mod = inode->i_mode; | ||
309 | ubi_num = ubi_major2num(imajor(inode)); | 309 | ubi_num = ubi_major2num(imajor(inode)); |
310 | vol_id = iminor(inode) - 1; | 310 | vol_id = iminor(inode) - 1; |
311 | path_put(&path); | ||
311 | 312 | ||
313 | if (!S_ISCHR(mod)) | ||
314 | return ERR_PTR(-EINVAL); | ||
312 | if (vol_id >= 0 && ubi_num >= 0) | 315 | if (vol_id >= 0 && ubi_num >= 0) |
313 | ret = ubi_open_volume(ubi_num, vol_id, mode); | 316 | return ubi_open_volume(ubi_num, vol_id, mode); |
314 | else | 317 | return ERR_PTR(-ENODEV); |
315 | ret = ERR_PTR(-ENODEV); | ||
316 | |||
317 | path_put(&path); | ||
318 | return ret; | ||
319 | } | 318 | } |
320 | EXPORT_SYMBOL_GPL(ubi_open_volume_path); | 319 | EXPORT_SYMBOL_GPL(ubi_open_volume_path); |
321 | 320 | ||
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index c1d7b880c795..425bf5a3edd4 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c | |||
@@ -155,6 +155,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, | |||
155 | if (err) | 155 | if (err) |
156 | return err; | 156 | return err; |
157 | vol->updating = 0; | 157 | vol->updating = 0; |
158 | return 0; | ||
158 | } | 159 | } |
159 | 160 | ||
160 | vol->upd_buf = vmalloc(ubi->leb_size); | 161 | vol->upd_buf = vmalloc(ubi->leb_size); |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 1afc61e7455d..40044028d682 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
@@ -566,6 +566,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
566 | vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs); | 566 | vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs); |
567 | vol->alignment = be32_to_cpu(vtbl[i].alignment); | 567 | vol->alignment = be32_to_cpu(vtbl[i].alignment); |
568 | vol->data_pad = be32_to_cpu(vtbl[i].data_pad); | 568 | vol->data_pad = be32_to_cpu(vtbl[i].data_pad); |
569 | vol->upd_marker = vtbl[i].upd_marker; | ||
569 | vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ? | 570 | vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ? |
570 | UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; | 571 | UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; |
571 | vol->name_len = be16_to_cpu(vtbl[i].name_len); | 572 | vol->name_len = be16_to_cpu(vtbl[i].name_len); |