aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/maps
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps')
-rw-r--r--drivers/mtd/maps/Kconfig13
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/bfin-async-flash.c5
-rw-r--r--drivers/mtd/maps/integrator-flash.c226
-rw-r--r--drivers/mtd/maps/physmap.c40
-rw-r--r--drivers/mtd/maps/physmap_of.c199
-rw-r--r--drivers/mtd/maps/pmcmsp-ramroot.c104
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c22
-rw-r--r--drivers/mtd/maps/rbtx4939-flash.c23
-rw-r--r--drivers/mtd/maps/sa1100-flash.c23
-rw-r--r--drivers/mtd/maps/uclinux.c16
11 files changed, 323 insertions, 349 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 82923bd2d9c5..0b98654d8eed 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -105,15 +105,6 @@ config MSP_FLASH_MAP_LIMIT
105 default "0x02000000" 105 default "0x02000000"
106 depends on MSP_FLASH_MAP_LIMIT_32M 106 depends on MSP_FLASH_MAP_LIMIT_32M
107 107
108config MTD_PMC_MSP_RAMROOT
109 tristate "Embedded RAM block device for root on PMC-Sierra MSP"
110 depends on PMC_MSP_EMBEDDED_ROOTFS && \
111 (MTD_BLOCK || MTD_BLOCK_RO) && \
112 MTD_RAM
113 help
114 This provides support for the embedded root file system
115 on PMC MSP devices. This memory is mapped as a MTD block device.
116
117config MTD_SUN_UFLASH 108config MTD_SUN_UFLASH
118 tristate "Sun Microsystems userflash support" 109 tristate "Sun Microsystems userflash support"
119 depends on SPARC && MTD_CFI && PCI 110 depends on SPARC && MTD_CFI && PCI
@@ -270,7 +261,7 @@ config MTD_ALCHEMY
270 261
271config MTD_DILNETPC 262config MTD_DILNETPC
272 tristate "CFI Flash device mapped on DIL/Net PC" 263 tristate "CFI Flash device mapped on DIL/Net PC"
273 depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT 264 depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
274 help 265 help
275 MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP". 266 MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
276 For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm> 267 For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
@@ -501,7 +492,7 @@ config MTD_BFIN_ASYNC
501 If compiled as a module, it will be called bfin-async-flash. 492 If compiled as a module, it will be called bfin-async-flash.
502 493
503config MTD_UCLINUX 494config MTD_UCLINUX
504 tristate "Generic uClinux RAM/ROM filesystem support" 495 bool "Generic uClinux RAM/ROM filesystem support"
505 depends on MTD_PARTITIONS && MTD_RAM && !MMU 496 depends on MTD_PARTITIONS && MTD_RAM && !MMU
506 help 497 help
507 Map driver to support image based filesystems for uClinux. 498 Map driver to support image based filesystems for uClinux.
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 2dbc1bec8488..8bae7f9850c0 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
25obj-$(CONFIG_MTD_PHYSMAP) += physmap.o 25obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
26obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o 26obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
27obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o 27obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
28obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o
29obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o 28obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
30obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o 29obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
31obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o 30obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 576611f605db..365c77b1b871 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -40,6 +40,9 @@ struct async_state {
40 uint32_t flash_ambctl0, flash_ambctl1; 40 uint32_t flash_ambctl0, flash_ambctl1;
41 uint32_t save_ambctl0, save_ambctl1; 41 uint32_t save_ambctl0, save_ambctl1;
42 unsigned long irq_flags; 42 unsigned long irq_flags;
43#ifdef CONFIG_MTD_PARTITIONS
44 struct mtd_partition *parts;
45#endif
43}; 46};
44 47
45static void switch_to_flash(struct async_state *state) 48static void switch_to_flash(struct async_state *state)
@@ -170,6 +173,7 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
170 if (ret > 0) { 173 if (ret > 0) {
171 pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n"); 174 pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
172 add_mtd_partitions(state->mtd, pdata->parts, ret); 175 add_mtd_partitions(state->mtd, pdata->parts, ret);
176 state->parts = pdata->parts;
173 177
174 } else if (pdata->nr_parts) { 178 } else if (pdata->nr_parts) {
175 pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n"); 179 pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
@@ -193,6 +197,7 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
193 gpio_free(state->enet_flash_pin); 197 gpio_free(state->enet_flash_pin);
194#ifdef CONFIG_MTD_PARTITIONS 198#ifdef CONFIG_MTD_PARTITIONS
195 del_mtd_partitions(state->mtd); 199 del_mtd_partitions(state->mtd);
200 kfree(state->parts);
196#endif 201#endif
197 map_destroy(state->mtd); 202 map_destroy(state->mtd);
198 kfree(state); 203 kfree(state);
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index c9681a339a59..b08a798ee254 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -36,27 +36,33 @@
36#include <linux/mtd/mtd.h> 36#include <linux/mtd/mtd.h>
37#include <linux/mtd/map.h> 37#include <linux/mtd/map.h>
38#include <linux/mtd/partitions.h> 38#include <linux/mtd/partitions.h>
39#include <linux/mtd/concat.h>
39 40
40#include <asm/mach/flash.h> 41#include <asm/mach/flash.h>
41#include <mach/hardware.h> 42#include <mach/hardware.h>
42#include <asm/system.h> 43#include <asm/system.h>
43 44
44#ifdef CONFIG_ARCH_P720T 45#define SUBDEV_NAME_SIZE (BUS_ID_SIZE + 2)
45#define FLASH_BASE (0x04000000)
46#define FLASH_SIZE (64*1024*1024)
47#endif
48 46
49struct armflash_info { 47struct armflash_subdev_info {
48 char name[SUBDEV_NAME_SIZE];
49 struct mtd_info *mtd;
50 struct map_info map;
50 struct flash_platform_data *plat; 51 struct flash_platform_data *plat;
52};
53
54struct armflash_info {
51 struct resource *res; 55 struct resource *res;
52 struct mtd_partition *parts; 56 struct mtd_partition *parts;
53 struct mtd_info *mtd; 57 struct mtd_info *mtd;
54 struct map_info map; 58 int nr_subdev;
59 struct armflash_subdev_info subdev[0];
55}; 60};
56 61
57static void armflash_set_vpp(struct map_info *map, int on) 62static void armflash_set_vpp(struct map_info *map, int on)
58{ 63{
59 struct armflash_info *info = container_of(map, struct armflash_info, map); 64 struct armflash_subdev_info *info =
65 container_of(map, struct armflash_subdev_info, map);
60 66
61 if (info->plat && info->plat->set_vpp) 67 if (info->plat && info->plat->set_vpp)
62 info->plat->set_vpp(on); 68 info->plat->set_vpp(on);
@@ -64,32 +70,17 @@ static void armflash_set_vpp(struct map_info *map, int on)
64 70
65static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL }; 71static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
66 72
67static int armflash_probe(struct platform_device *dev) 73static int armflash_subdev_probe(struct armflash_subdev_info *subdev,
74 struct resource *res)
68{ 75{
69 struct flash_platform_data *plat = dev->dev.platform_data; 76 struct flash_platform_data *plat = subdev->plat;
70 struct resource *res = dev->resource; 77 resource_size_t size = res->end - res->start + 1;
71 unsigned int size = res->end - res->start + 1;
72 struct armflash_info *info;
73 int err;
74 void __iomem *base; 78 void __iomem *base;
79 int err = 0;
75 80
76 info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL); 81 if (!request_mem_region(res->start, size, subdev->name)) {
77 if (!info) {
78 err = -ENOMEM;
79 goto out;
80 }
81
82 info->plat = plat;
83 if (plat && plat->init) {
84 err = plat->init();
85 if (err)
86 goto no_resource;
87 }
88
89 info->res = request_mem_region(res->start, size, "armflash");
90 if (!info->res) {
91 err = -EBUSY; 82 err = -EBUSY;
92 goto no_resource; 83 goto out;
93 } 84 }
94 85
95 base = ioremap(res->start, size); 86 base = ioremap(res->start, size);
@@ -101,27 +92,132 @@ static int armflash_probe(struct platform_device *dev)
101 /* 92 /*
102 * look for CFI based flash parts fitted to this board 93 * look for CFI based flash parts fitted to this board
103 */ 94 */
104 info->map.size = size; 95 subdev->map.size = size;
105 info->map.bankwidth = plat->width; 96 subdev->map.bankwidth = plat->width;
106 info->map.phys = res->start; 97 subdev->map.phys = res->start;
107 info->map.virt = base; 98 subdev->map.virt = base;
108 info->map.name = dev_name(&dev->dev); 99 subdev->map.name = subdev->name;
109 info->map.set_vpp = armflash_set_vpp; 100 subdev->map.set_vpp = armflash_set_vpp;
110 101
111 simple_map_init(&info->map); 102 simple_map_init(&subdev->map);
112 103
113 /* 104 /*
114 * Also, the CFI layer automatically works out what size 105 * Also, the CFI layer automatically works out what size
115 * of chips we have, and does the necessary identification 106 * of chips we have, and does the necessary identification
116 * for us automatically. 107 * for us automatically.
117 */ 108 */
118 info->mtd = do_map_probe(plat->map_name, &info->map); 109 subdev->mtd = do_map_probe(plat->map_name, &subdev->map);
119 if (!info->mtd) { 110 if (!subdev->mtd) {
120 err = -ENXIO; 111 err = -ENXIO;
121 goto no_device; 112 goto no_device;
122 } 113 }
123 114
124 info->mtd->owner = THIS_MODULE; 115 subdev->mtd->owner = THIS_MODULE;
116
117 /* Successful? */
118 if (err == 0)
119 return err;
120
121 if (subdev->mtd)
122 map_destroy(subdev->mtd);
123 no_device:
124 iounmap(base);
125 no_mem:
126 release_mem_region(res->start, size);
127 out:
128 return err;
129}
130
131static void armflash_subdev_remove(struct armflash_subdev_info *subdev)
132{
133 if (subdev->mtd)
134 map_destroy(subdev->mtd);
135 if (subdev->map.virt)
136 iounmap(subdev->map.virt);
137 release_mem_region(subdev->map.phys, subdev->map.size);
138}
139
140static int armflash_probe(struct platform_device *dev)
141{
142 struct flash_platform_data *plat = dev->dev.platform_data;
143 unsigned int size;
144 struct armflash_info *info;
145 int i, nr, err;
146
147 /* Count the number of devices */
148 for (nr = 0; ; nr++)
149 if (!platform_get_resource(dev, IORESOURCE_MEM, nr))
150 break;
151 if (nr == 0) {
152 err = -ENODEV;
153 goto out;
154 }
155
156 size = sizeof(struct armflash_info) +
157 sizeof(struct armflash_subdev_info) * nr;
158 info = kzalloc(size, GFP_KERNEL);
159 if (!info) {
160 err = -ENOMEM;
161 goto out;
162 }
163
164 if (plat && plat->init) {
165 err = plat->init();
166 if (err)
167 goto no_resource;
168 }
169
170 for (i = 0; i < nr; i++) {
171 struct armflash_subdev_info *subdev = &info->subdev[i];
172 struct resource *res;
173
174 res = platform_get_resource(dev, IORESOURCE_MEM, i);
175 if (!res)
176 break;
177
178 if (nr == 1)
179 /* No MTD concatenation, just use the default name */
180 snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s",
181 dev_name(&dev->dev));
182 else
183 snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s-%d",
184 dev_name(&dev->dev), i);
185 subdev->plat = plat;
186
187 err = armflash_subdev_probe(subdev, res);
188 if (err)
189 break;
190 }
191 info->nr_subdev = i;
192
193 if (err)
194 goto subdev_err;
195
196 if (info->nr_subdev == 1)
197 info->mtd = info->subdev[0].mtd;
198 else if (info->nr_subdev > 1) {
199#ifdef CONFIG_MTD_CONCAT
200 struct mtd_info *cdev[info->nr_subdev];
201
202 /*
203 * We detected multiple devices. Concatenate them together.
204 */
205 for (i = 0; i < info->nr_subdev; i++)
206 cdev[i] = info->subdev[i].mtd;
207
208 info->mtd = mtd_concat_create(cdev, info->nr_subdev,
209 dev_name(&dev->dev));
210 if (info->mtd == NULL)
211 err = -ENXIO;
212#else
213 printk(KERN_ERR "armflash: multiple devices found but "
214 "MTD concat support disabled.\n");
215 err = -ENXIO;
216#endif
217 }
218
219 if (err < 0)
220 goto cleanup;
125 221
126 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0); 222 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
127 if (err > 0) { 223 if (err > 0) {
@@ -131,28 +227,30 @@ static int armflash_probe(struct platform_device *dev)
131 "mtd partition registration failed: %d\n", err); 227 "mtd partition registration failed: %d\n", err);
132 } 228 }
133 229
134 if (err == 0) 230 if (err == 0) {
135 platform_set_drvdata(dev, info); 231 platform_set_drvdata(dev, info);
232 return err;
233 }
136 234
137 /* 235 /*
138 * If we got an error, free all resources. 236 * We got an error, free all resources.
139 */ 237 */
140 if (err < 0) { 238 cleanup:
141 if (info->mtd) { 239 if (info->mtd) {
142 del_mtd_partitions(info->mtd); 240 del_mtd_partitions(info->mtd);
143 map_destroy(info->mtd); 241#ifdef CONFIG_MTD_CONCAT
144 } 242 if (info->mtd != info->subdev[0].mtd)
145 kfree(info->parts); 243 mtd_concat_destroy(info->mtd);
146 244#endif
147 no_device:
148 iounmap(base);
149 no_mem:
150 release_mem_region(res->start, size);
151 no_resource:
152 if (plat && plat->exit)
153 plat->exit();
154 kfree(info);
155 } 245 }
246 kfree(info->parts);
247 subdev_err:
248 for (i = info->nr_subdev - 1; i >= 0; i--)
249 armflash_subdev_remove(&info->subdev[i]);
250 no_resource:
251 if (plat && plat->exit)
252 plat->exit();
253 kfree(info);
156 out: 254 out:
157 return err; 255 return err;
158} 256}
@@ -160,22 +258,26 @@ static int armflash_probe(struct platform_device *dev)
160static int armflash_remove(struct platform_device *dev) 258static int armflash_remove(struct platform_device *dev)
161{ 259{
162 struct armflash_info *info = platform_get_drvdata(dev); 260 struct armflash_info *info = platform_get_drvdata(dev);
261 struct flash_platform_data *plat = dev->dev.platform_data;
262 int i;
163 263
164 platform_set_drvdata(dev, NULL); 264 platform_set_drvdata(dev, NULL);
165 265
166 if (info) { 266 if (info) {
167 if (info->mtd) { 267 if (info->mtd) {
168 del_mtd_partitions(info->mtd); 268 del_mtd_partitions(info->mtd);
169 map_destroy(info->mtd); 269#ifdef CONFIG_MTD_CONCAT
270 if (info->mtd != info->subdev[0].mtd)
271 mtd_concat_destroy(info->mtd);
272#endif
170 } 273 }
171 kfree(info->parts); 274 kfree(info->parts);
172 275
173 iounmap(info->map.virt); 276 for (i = info->nr_subdev - 1; i >= 0; i--)
174 release_resource(info->res); 277 armflash_subdev_remove(&info->subdev[i]);
175 kfree(info->res);
176 278
177 if (info->plat && info->plat->exit) 279 if (plat && plat->exit)
178 info->plat->exit(); 280 plat->exit();
179 281
180 kfree(info); 282 kfree(info);
181 } 283 }
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 29a901157352..380648e9051a 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -195,42 +195,6 @@ err_out:
195} 195}
196 196
197#ifdef CONFIG_PM 197#ifdef CONFIG_PM
198static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state)
199{
200 struct physmap_flash_info *info = platform_get_drvdata(dev);
201 int ret = 0;
202 int i;
203
204 for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
205 if (info->mtd[i]->suspend) {
206 ret = info->mtd[i]->suspend(info->mtd[i]);
207 if (ret)
208 goto fail;
209 }
210
211 return 0;
212fail:
213 for (--i; i >= 0; --i)
214 if (info->mtd[i]->suspend) {
215 BUG_ON(!info->mtd[i]->resume);
216 info->mtd[i]->resume(info->mtd[i]);
217 }
218
219 return ret;
220}
221
222static int physmap_flash_resume(struct platform_device *dev)
223{
224 struct physmap_flash_info *info = platform_get_drvdata(dev);
225 int i;
226
227 for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
228 if (info->mtd[i]->resume)
229 info->mtd[i]->resume(info->mtd[i]);
230
231 return 0;
232}
233
234static void physmap_flash_shutdown(struct platform_device *dev) 198static void physmap_flash_shutdown(struct platform_device *dev)
235{ 199{
236 struct physmap_flash_info *info = platform_get_drvdata(dev); 200 struct physmap_flash_info *info = platform_get_drvdata(dev);
@@ -242,16 +206,12 @@ static void physmap_flash_shutdown(struct platform_device *dev)
242 info->mtd[i]->resume(info->mtd[i]); 206 info->mtd[i]->resume(info->mtd[i]);
243} 207}
244#else 208#else
245#define physmap_flash_suspend NULL
246#define physmap_flash_resume NULL
247#define physmap_flash_shutdown NULL 209#define physmap_flash_shutdown NULL
248#endif 210#endif
249 211
250static struct platform_driver physmap_flash_driver = { 212static struct platform_driver physmap_flash_driver = {
251 .probe = physmap_flash_probe, 213 .probe = physmap_flash_probe,
252 .remove = physmap_flash_remove, 214 .remove = physmap_flash_remove,
253 .suspend = physmap_flash_suspend,
254 .resume = physmap_flash_resume,
255 .shutdown = physmap_flash_shutdown, 215 .shutdown = physmap_flash_shutdown,
256 .driver = { 216 .driver = {
257 .name = "physmap-flash", 217 .name = "physmap-flash",
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index c83a60fada53..39d357b2eb47 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -20,16 +20,23 @@
20#include <linux/mtd/mtd.h> 20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h> 21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h> 22#include <linux/mtd/partitions.h>
23#include <linux/mtd/concat.h>
23#include <linux/of.h> 24#include <linux/of.h>
24#include <linux/of_platform.h> 25#include <linux/of_platform.h>
25 26
27struct of_flash_list {
28 struct mtd_info *mtd;
29 struct map_info map;
30 struct resource *res;
31};
32
26struct of_flash { 33struct of_flash {
27 struct mtd_info *mtd; 34 struct mtd_info *cmtd;
28 struct map_info map;
29 struct resource *res;
30#ifdef CONFIG_MTD_PARTITIONS 35#ifdef CONFIG_MTD_PARTITIONS
31 struct mtd_partition *parts; 36 struct mtd_partition *parts;
32#endif 37#endif
38 int list_size; /* number of elements in of_flash_list */
39 struct of_flash_list list[0];
33}; 40};
34 41
35#ifdef CONFIG_MTD_PARTITIONS 42#ifdef CONFIG_MTD_PARTITIONS
@@ -88,30 +95,44 @@ static int parse_obsolete_partitions(struct of_device *dev,
88static int of_flash_remove(struct of_device *dev) 95static int of_flash_remove(struct of_device *dev)
89{ 96{
90 struct of_flash *info; 97 struct of_flash *info;
98 int i;
91 99
92 info = dev_get_drvdata(&dev->dev); 100 info = dev_get_drvdata(&dev->dev);
93 if (!info) 101 if (!info)
94 return 0; 102 return 0;
95 dev_set_drvdata(&dev->dev, NULL); 103 dev_set_drvdata(&dev->dev, NULL);
96 104
97 if (info->mtd) { 105#ifdef CONFIG_MTD_CONCAT
106 if (info->cmtd != info->list[0].mtd) {
107 del_mtd_device(info->cmtd);
108 mtd_concat_destroy(info->cmtd);
109 }
110#endif
111
112 if (info->cmtd) {
98 if (OF_FLASH_PARTS(info)) { 113 if (OF_FLASH_PARTS(info)) {
99 del_mtd_partitions(info->mtd); 114 del_mtd_partitions(info->cmtd);
100 kfree(OF_FLASH_PARTS(info)); 115 kfree(OF_FLASH_PARTS(info));
101 } else { 116 } else {
102 del_mtd_device(info->mtd); 117 del_mtd_device(info->cmtd);
103 } 118 }
104 map_destroy(info->mtd);
105 } 119 }
106 120
107 if (info->map.virt) 121 for (i = 0; i < info->list_size; i++) {
108 iounmap(info->map.virt); 122 if (info->list[i].mtd)
123 map_destroy(info->list[i].mtd);
109 124
110 if (info->res) { 125 if (info->list[i].map.virt)
111 release_resource(info->res); 126 iounmap(info->list[i].map.virt);
112 kfree(info->res); 127
128 if (info->list[i].res) {
129 release_resource(info->list[i].res);
130 kfree(info->list[i].res);
131 }
113 } 132 }
114 133
134 kfree(info);
135
115 return 0; 136 return 0;
116} 137}
117 138
@@ -164,68 +185,130 @@ static int __devinit of_flash_probe(struct of_device *dev,
164 const char *probe_type = match->data; 185 const char *probe_type = match->data;
165 const u32 *width; 186 const u32 *width;
166 int err; 187 int err;
167 188 int i;
168 err = -ENXIO; 189 int count;
169 if (of_address_to_resource(dp, 0, &res)) { 190 const u32 *p;
170 dev_err(&dev->dev, "Can't get IO address from device tree\n"); 191 int reg_tuple_size;
192 struct mtd_info **mtd_list = NULL;
193
194 reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
195
196 /*
197 * Get number of "reg" tuples. Scan for MTD devices on area's
198 * described by each "reg" region. This makes it possible (including
199 * the concat support) to support the Intel P30 48F4400 chips which
200 * consists internally of 2 non-identical NOR chips on one die.
201 */
202 p = of_get_property(dp, "reg", &count);
203 if (count % reg_tuple_size != 0) {
204 dev_err(&dev->dev, "Malformed reg property on %s\n",
205 dev->node->full_name);
206 err = -EINVAL;
171 goto err_out; 207 goto err_out;
172 } 208 }
173 209 count /= reg_tuple_size;
174 dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
175 (unsigned long long)res.start, (unsigned long long)res.end);
176 210
177 err = -ENOMEM; 211 err = -ENOMEM;
178 info = kzalloc(sizeof(*info), GFP_KERNEL); 212 info = kzalloc(sizeof(struct of_flash) +
213 sizeof(struct of_flash_list) * count, GFP_KERNEL);
214 if (!info)
215 goto err_out;
216
217 mtd_list = kzalloc(sizeof(struct mtd_info) * count, GFP_KERNEL);
179 if (!info) 218 if (!info)
180 goto err_out; 219 goto err_out;
181 220
182 dev_set_drvdata(&dev->dev, info); 221 dev_set_drvdata(&dev->dev, info);
183 222
184 err = -EBUSY; 223 for (i = 0; i < count; i++) {
185 info->res = request_mem_region(res.start, res.end - res.start + 1, 224 err = -ENXIO;
186 dev_name(&dev->dev)); 225 if (of_address_to_resource(dp, i, &res)) {
187 if (!info->res) 226 dev_err(&dev->dev, "Can't get IO address from device"
188 goto err_out; 227 " tree\n");
228 goto err_out;
229 }
189 230
190 err = -ENXIO; 231 dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
191 width = of_get_property(dp, "bank-width", NULL); 232 (unsigned long long)res.start,
192 if (!width) { 233 (unsigned long long)res.end);
193 dev_err(&dev->dev, "Can't get bank width from device tree\n"); 234
194 goto err_out; 235 err = -EBUSY;
195 } 236 info->list[i].res = request_mem_region(res.start, res.end -
237 res.start + 1,
238 dev_name(&dev->dev));
239 if (!info->list[i].res)
240 goto err_out;
241
242 err = -ENXIO;
243 width = of_get_property(dp, "bank-width", NULL);
244 if (!width) {
245 dev_err(&dev->dev, "Can't get bank width from device"
246 " tree\n");
247 goto err_out;
248 }
196 249
197 info->map.name = dev_name(&dev->dev); 250 info->list[i].map.name = dev_name(&dev->dev);
198 info->map.phys = res.start; 251 info->list[i].map.phys = res.start;
199 info->map.size = res.end - res.start + 1; 252 info->list[i].map.size = res.end - res.start + 1;
200 info->map.bankwidth = *width; 253 info->list[i].map.bankwidth = *width;
254
255 err = -ENOMEM;
256 info->list[i].map.virt = ioremap(info->list[i].map.phys,
257 info->list[i].map.size);
258 if (!info->list[i].map.virt) {
259 dev_err(&dev->dev, "Failed to ioremap() flash"
260 " region\n");
261 goto err_out;
262 }
201 263
202 err = -ENOMEM; 264 simple_map_init(&info->list[i].map);
203 info->map.virt = ioremap(info->map.phys, info->map.size);
204 if (!info->map.virt) {
205 dev_err(&dev->dev, "Failed to ioremap() flash region\n");
206 goto err_out;
207 }
208 265
209 simple_map_init(&info->map); 266 if (probe_type) {
267 info->list[i].mtd = do_map_probe(probe_type,
268 &info->list[i].map);
269 } else {
270 info->list[i].mtd = obsolete_probe(dev,
271 &info->list[i].map);
272 }
273 mtd_list[i] = info->list[i].mtd;
210 274
211 if (probe_type) 275 err = -ENXIO;
212 info->mtd = do_map_probe(probe_type, &info->map); 276 if (!info->list[i].mtd) {
213 else 277 dev_err(&dev->dev, "do_map_probe() failed\n");
214 info->mtd = obsolete_probe(dev, &info->map); 278 goto err_out;
279 } else {
280 info->list_size++;
281 }
282 info->list[i].mtd->owner = THIS_MODULE;
283 info->list[i].mtd->dev.parent = &dev->dev;
284 }
215 285
216 err = -ENXIO; 286 err = 0;
217 if (!info->mtd) { 287 if (info->list_size == 1) {
218 dev_err(&dev->dev, "do_map_probe() failed\n"); 288 info->cmtd = info->list[0].mtd;
219 goto err_out; 289 } else if (info->list_size > 1) {
290 /*
291 * We detected multiple devices. Concatenate them together.
292 */
293#ifdef CONFIG_MTD_CONCAT
294 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
295 dev_name(&dev->dev));
296 if (info->cmtd == NULL)
297 err = -ENXIO;
298#else
299 printk(KERN_ERR "physmap_of: multiple devices "
300 "found but MTD concat support disabled.\n");
301 err = -ENXIO;
302#endif
220 } 303 }
221 info->mtd->owner = THIS_MODULE; 304 if (err)
222 info->mtd->dev.parent = &dev->dev; 305 goto err_out;
223 306
224#ifdef CONFIG_MTD_PARTITIONS 307#ifdef CONFIG_MTD_PARTITIONS
225 /* First look for RedBoot table or partitions on the command 308 /* First look for RedBoot table or partitions on the command
226 * line, these take precedence over device tree information */ 309 * line, these take precedence over device tree information */
227 err = parse_mtd_partitions(info->mtd, part_probe_types, 310 err = parse_mtd_partitions(info->cmtd, part_probe_types,
228 &info->parts, 0); 311 &info->parts, 0);
229 if (err < 0) 312 if (err < 0)
230 return err; 313 return err;
231 314
@@ -244,15 +327,19 @@ static int __devinit of_flash_probe(struct of_device *dev,
244 } 327 }
245 328
246 if (err > 0) 329 if (err > 0)
247 add_mtd_partitions(info->mtd, info->parts, err); 330 add_mtd_partitions(info->cmtd, info->parts, err);
248 else 331 else
249#endif 332#endif
250 add_mtd_device(info->mtd); 333 add_mtd_device(info->cmtd);
334
335 kfree(mtd_list);
251 336
252 return 0; 337 return 0;
253 338
254err_out: 339err_out:
340 kfree(mtd_list);
255 of_flash_remove(dev); 341 of_flash_remove(dev);
342
256 return err; 343 return err;
257} 344}
258 345
diff --git a/drivers/mtd/maps/pmcmsp-ramroot.c b/drivers/mtd/maps/pmcmsp-ramroot.c
deleted file mode 100644
index 30de5c0c09a9..000000000000
--- a/drivers/mtd/maps/pmcmsp-ramroot.c
+++ /dev/null
@@ -1,104 +0,0 @@
1/*
2 * Mapping of the rootfs in a physical region of memory
3 *
4 * Copyright (C) 2005-2007 PMC-Sierra Inc.
5 * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#include <linux/module.h>
29#include <linux/types.h>
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/slab.h>
33#include <linux/fs.h>
34#include <linux/root_dev.h>
35#include <linux/mtd/mtd.h>
36#include <linux/mtd/map.h>
37
38#include <asm/io.h>
39
40#include <msp_prom.h>
41
42static struct mtd_info *rr_mtd;
43
44struct map_info rr_map = {
45 .name = "ramroot",
46 .bankwidth = 4,
47};
48
49static int __init init_rrmap(void)
50{
51 void *ramroot_start;
52 unsigned long ramroot_size;
53
54 /* Check for supported rootfs types */
55 if (get_ramroot(&ramroot_start, &ramroot_size)) {
56 rr_map.phys = CPHYSADDR(ramroot_start);
57 rr_map.size = ramroot_size;
58
59 printk(KERN_NOTICE
60 "PMC embedded root device: 0x%08lx @ 0x%08lx\n",
61 rr_map.size, (unsigned long)rr_map.phys);
62 } else {
63 printk(KERN_ERR
64 "init_rrmap: no supported embedded rootfs detected!\n");
65 return -ENXIO;
66 }
67
68 /* Map rootfs to I/O space for block device driver */
69 rr_map.virt = ioremap(rr_map.phys, rr_map.size);
70 if (!rr_map.virt) {
71 printk(KERN_ERR "Failed to ioremap\n");
72 return -EIO;
73 }
74
75 simple_map_init(&rr_map);
76
77 rr_mtd = do_map_probe("map_ram", &rr_map);
78 if (rr_mtd) {
79 rr_mtd->owner = THIS_MODULE;
80
81 add_mtd_device(rr_mtd);
82
83 return 0;
84 }
85
86 iounmap(rr_map.virt);
87 return -ENXIO;
88}
89
90static void __exit cleanup_rrmap(void)
91{
92 del_mtd_device(rr_mtd);
93 map_destroy(rr_mtd);
94
95 iounmap(rr_map.virt);
96 rr_map.virt = NULL;
97}
98
99MODULE_AUTHOR("PMC-Sierra, Inc");
100MODULE_DESCRIPTION("MTD map driver for embedded PMC-Sierra MSP filesystem");
101MODULE_LICENSE("GPL");
102
103module_init(init_rrmap);
104module_exit(cleanup_rrmap);
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 572d32fdf38a..643aa06b599e 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -140,24 +140,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
140} 140}
141 141
142#ifdef CONFIG_PM 142#ifdef CONFIG_PM
143static int pxa2xx_flash_suspend(struct platform_device *dev, pm_message_t state)
144{
145 struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
146 int ret = 0;
147
148 if (info->mtd && info->mtd->suspend)
149 ret = info->mtd->suspend(info->mtd);
150 return ret;
151}
152
153static int pxa2xx_flash_resume(struct platform_device *dev)
154{
155 struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
156
157 if (info->mtd && info->mtd->resume)
158 info->mtd->resume(info->mtd);
159 return 0;
160}
161static void pxa2xx_flash_shutdown(struct platform_device *dev) 143static void pxa2xx_flash_shutdown(struct platform_device *dev)
162{ 144{
163 struct pxa2xx_flash_info *info = platform_get_drvdata(dev); 145 struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
@@ -166,8 +148,6 @@ static void pxa2xx_flash_shutdown(struct platform_device *dev)
166 info->mtd->resume(info->mtd); 148 info->mtd->resume(info->mtd);
167} 149}
168#else 150#else
169#define pxa2xx_flash_suspend NULL
170#define pxa2xx_flash_resume NULL
171#define pxa2xx_flash_shutdown NULL 151#define pxa2xx_flash_shutdown NULL
172#endif 152#endif
173 153
@@ -178,8 +158,6 @@ static struct platform_driver pxa2xx_flash_driver = {
178 }, 158 },
179 .probe = pxa2xx_flash_probe, 159 .probe = pxa2xx_flash_probe,
180 .remove = __devexit_p(pxa2xx_flash_remove), 160 .remove = __devexit_p(pxa2xx_flash_remove),
181 .suspend = pxa2xx_flash_suspend,
182 .resume = pxa2xx_flash_resume,
183 .shutdown = pxa2xx_flash_shutdown, 161 .shutdown = pxa2xx_flash_shutdown,
184}; 162};
185 163
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index d39f0adac846..83ed64512c5e 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -145,25 +145,6 @@ err_out:
145} 145}
146 146
147#ifdef CONFIG_PM 147#ifdef CONFIG_PM
148static int rbtx4939_flash_suspend(struct platform_device *dev,
149 pm_message_t state)
150{
151 struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
152
153 if (info->mtd->suspend)
154 return info->mtd->suspend(info->mtd);
155 return 0;
156}
157
158static int rbtx4939_flash_resume(struct platform_device *dev)
159{
160 struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
161
162 if (info->mtd->resume)
163 info->mtd->resume(info->mtd);
164 return 0;
165}
166
167static void rbtx4939_flash_shutdown(struct platform_device *dev) 148static void rbtx4939_flash_shutdown(struct platform_device *dev)
168{ 149{
169 struct rbtx4939_flash_info *info = platform_get_drvdata(dev); 150 struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
@@ -173,16 +154,12 @@ static void rbtx4939_flash_shutdown(struct platform_device *dev)
173 info->mtd->resume(info->mtd); 154 info->mtd->resume(info->mtd);
174} 155}
175#else 156#else
176#define rbtx4939_flash_suspend NULL
177#define rbtx4939_flash_resume NULL
178#define rbtx4939_flash_shutdown NULL 157#define rbtx4939_flash_shutdown NULL
179#endif 158#endif
180 159
181static struct platform_driver rbtx4939_flash_driver = { 160static struct platform_driver rbtx4939_flash_driver = {
182 .probe = rbtx4939_flash_probe, 161 .probe = rbtx4939_flash_probe,
183 .remove = rbtx4939_flash_remove, 162 .remove = rbtx4939_flash_remove,
184 .suspend = rbtx4939_flash_suspend,
185 .resume = rbtx4939_flash_resume,
186 .shutdown = rbtx4939_flash_shutdown, 163 .shutdown = rbtx4939_flash_shutdown,
187 .driver = { 164 .driver = {
188 .name = "rbtx4939-flash", 165 .name = "rbtx4939-flash",
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 05e9362dc7f0..c6210f5118d1 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -415,25 +415,6 @@ static int __exit sa1100_mtd_remove(struct platform_device *pdev)
415} 415}
416 416
417#ifdef CONFIG_PM 417#ifdef CONFIG_PM
418static int sa1100_mtd_suspend(struct platform_device *dev, pm_message_t state)
419{
420 struct sa_info *info = platform_get_drvdata(dev);
421 int ret = 0;
422
423 if (info)
424 ret = info->mtd->suspend(info->mtd);
425
426 return ret;
427}
428
429static int sa1100_mtd_resume(struct platform_device *dev)
430{
431 struct sa_info *info = platform_get_drvdata(dev);
432 if (info)
433 info->mtd->resume(info->mtd);
434 return 0;
435}
436
437static void sa1100_mtd_shutdown(struct platform_device *dev) 418static void sa1100_mtd_shutdown(struct platform_device *dev)
438{ 419{
439 struct sa_info *info = platform_get_drvdata(dev); 420 struct sa_info *info = platform_get_drvdata(dev);
@@ -441,16 +422,12 @@ static void sa1100_mtd_shutdown(struct platform_device *dev)
441 info->mtd->resume(info->mtd); 422 info->mtd->resume(info->mtd);
442} 423}
443#else 424#else
444#define sa1100_mtd_suspend NULL
445#define sa1100_mtd_resume NULL
446#define sa1100_mtd_shutdown NULL 425#define sa1100_mtd_shutdown NULL
447#endif 426#endif
448 427
449static struct platform_driver sa1100_mtd_driver = { 428static struct platform_driver sa1100_mtd_driver = {
450 .probe = sa1100_mtd_probe, 429 .probe = sa1100_mtd_probe,
451 .remove = __exit_p(sa1100_mtd_remove), 430 .remove = __exit_p(sa1100_mtd_remove),
452 .suspend = sa1100_mtd_suspend,
453 .resume = sa1100_mtd_resume,
454 .shutdown = sa1100_mtd_shutdown, 431 .shutdown = sa1100_mtd_shutdown,
455 .driver = { 432 .driver = {
456 .name = "sa1100-mtd", 433 .name = "sa1100-mtd",
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 81756e397711..d4314fb88212 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -22,15 +22,19 @@
22 22
23/****************************************************************************/ 23/****************************************************************************/
24 24
25extern char _ebss;
26
25struct map_info uclinux_ram_map = { 27struct map_info uclinux_ram_map = {
26 .name = "RAM", 28 .name = "RAM",
29 .phys = (unsigned long)&_ebss,
30 .size = 0,
27}; 31};
28 32
29struct mtd_info *uclinux_ram_mtdinfo; 33static struct mtd_info *uclinux_ram_mtdinfo;
30 34
31/****************************************************************************/ 35/****************************************************************************/
32 36
33struct mtd_partition uclinux_romfs[] = { 37static struct mtd_partition uclinux_romfs[] = {
34 { .name = "ROMfs" } 38 { .name = "ROMfs" }
35}; 39};
36 40
@@ -38,7 +42,7 @@ struct mtd_partition uclinux_romfs[] = {
38 42
39/****************************************************************************/ 43/****************************************************************************/
40 44
41int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len, 45static int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
42 size_t *retlen, void **virt, resource_size_t *phys) 46 size_t *retlen, void **virt, resource_size_t *phys)
43{ 47{
44 struct map_info *map = mtd->priv; 48 struct map_info *map = mtd->priv;
@@ -55,12 +59,10 @@ static int __init uclinux_mtd_init(void)
55{ 59{
56 struct mtd_info *mtd; 60 struct mtd_info *mtd;
57 struct map_info *mapp; 61 struct map_info *mapp;
58 extern char _ebss;
59 unsigned long addr = (unsigned long) &_ebss;
60 62
61 mapp = &uclinux_ram_map; 63 mapp = &uclinux_ram_map;
62 mapp->phys = addr; 64 if (!mapp->size)
63 mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8)))); 65 mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(mapp->phys + 8))));
64 mapp->bankwidth = 4; 66 mapp->bankwidth = 4;
65 67
66 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", 68 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",