aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/maps/sa1100-flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps/sa1100-flash.c')
-rw-r--r--drivers/mtd/maps/sa1100-flash.c78
1 files changed, 53 insertions, 25 deletions
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 52385705da09..c8d0da19d897 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -13,7 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/device.h> 16#include <linux/platform_device.h>
17#include <linux/err.h> 17#include <linux/err.h>
18 18
19#include <linux/mtd/mtd.h> 19#include <linux/mtd/mtd.h>
@@ -21,7 +21,7 @@
21#include <linux/mtd/partitions.h> 21#include <linux/mtd/partitions.h>
22#include <linux/mtd/concat.h> 22#include <linux/mtd/concat.h>
23 23
24#include <asm/mach-types.h> 24#include <asm/hardware.h>
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/sizes.h> 26#include <asm/sizes.h>
27#include <asm/mach/flash.h> 27#include <asm/mach/flash.h>
@@ -130,20 +130,21 @@ struct sa_subdev_info {
130 char name[16]; 130 char name[16];
131 struct map_info map; 131 struct map_info map;
132 struct mtd_info *mtd; 132 struct mtd_info *mtd;
133 struct flash_platform_data *data; 133 struct flash_platform_data *plat;
134}; 134};
135 135
136struct sa_info { 136struct sa_info {
137 struct mtd_partition *parts; 137 struct mtd_partition *parts;
138 struct mtd_info *mtd; 138 struct mtd_info *mtd;
139 int num_subdev; 139 int num_subdev;
140 unsigned int nr_parts;
140 struct sa_subdev_info subdev[0]; 141 struct sa_subdev_info subdev[0];
141}; 142};
142 143
143static void sa1100_set_vpp(struct map_info *map, int on) 144static void sa1100_set_vpp(struct map_info *map, int on)
144{ 145{
145 struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map); 146 struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
146 subdev->data->set_vpp(on); 147 subdev->plat->set_vpp(on);
147} 148}
148 149
149static void sa1100_destroy_subdev(struct sa_subdev_info *subdev) 150static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
@@ -187,7 +188,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
187 goto out; 188 goto out;
188 } 189 }
189 190
190 if (subdev->data->set_vpp) 191 if (subdev->plat->set_vpp)
191 subdev->map.set_vpp = sa1100_set_vpp; 192 subdev->map.set_vpp = sa1100_set_vpp;
192 193
193 subdev->map.phys = phys; 194 subdev->map.phys = phys;
@@ -204,7 +205,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
204 * Now let's probe for the actual flash. Do it here since 205 * Now let's probe for the actual flash. Do it here since
205 * specific machine settings might have been set above. 206 * specific machine settings might have been set above.
206 */ 207 */
207 subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map); 208 subdev->mtd = do_map_probe(subdev->plat->map_name, &subdev->map);
208 if (subdev->mtd == NULL) { 209 if (subdev->mtd == NULL) {
209 ret = -ENXIO; 210 ret = -ENXIO;
210 goto err; 211 goto err;
@@ -223,13 +224,17 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
223 return ret; 224 return ret;
224} 225}
225 226
226static void sa1100_destroy(struct sa_info *info) 227static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *plat)
227{ 228{
228 int i; 229 int i;
229 230
230 if (info->mtd) { 231 if (info->mtd) {
231 del_mtd_partitions(info->mtd); 232 if (info->nr_parts == 0)
232 233 del_mtd_device(info->mtd);
234#ifdef CONFIG_MTD_PARTITIONS
235 else
236 del_mtd_partitions(info->mtd);
237#endif
233#ifdef CONFIG_MTD_CONCAT 238#ifdef CONFIG_MTD_CONCAT
234 if (info->mtd != info->subdev[0].mtd) 239 if (info->mtd != info->subdev[0].mtd)
235 mtd_concat_destroy(info->mtd); 240 mtd_concat_destroy(info->mtd);
@@ -242,10 +247,13 @@ static void sa1100_destroy(struct sa_info *info)
242 for (i = info->num_subdev - 1; i >= 0; i--) 247 for (i = info->num_subdev - 1; i >= 0; i--)
243 sa1100_destroy_subdev(&info->subdev[i]); 248 sa1100_destroy_subdev(&info->subdev[i]);
244 kfree(info); 249 kfree(info);
250
251 if (plat->exit)
252 plat->exit();
245} 253}
246 254
247static struct sa_info *__init 255static struct sa_info *__init
248sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash) 256sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
249{ 257{
250 struct sa_info *info; 258 struct sa_info *info;
251 int nr, size, i, ret = 0; 259 int nr, size, i, ret = 0;
@@ -275,6 +283,12 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
275 283
276 memset(info, 0, size); 284 memset(info, 0, size);
277 285
286 if (plat->init) {
287 ret = plat->init();
288 if (ret)
289 goto err;
290 }
291
278 /* 292 /*
279 * Claim and then map the memory regions. 293 * Claim and then map the memory regions.
280 */ 294 */
@@ -287,8 +301,8 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
287 break; 301 break;
288 302
289 subdev->map.name = subdev->name; 303 subdev->map.name = subdev->name;
290 sprintf(subdev->name, "sa1100-%d", i); 304 sprintf(subdev->name, "%s-%d", plat->name, i);
291 subdev->data = flash; 305 subdev->plat = plat;
292 306
293 ret = sa1100_probe_subdev(subdev, res); 307 ret = sa1100_probe_subdev(subdev, res);
294 if (ret) 308 if (ret)
@@ -309,7 +323,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
309 * otherwise fail. Either way, it'll be called "sa1100". 323 * otherwise fail. Either way, it'll be called "sa1100".
310 */ 324 */
311 if (info->num_subdev == 1) { 325 if (info->num_subdev == 1) {
312 strcpy(info->subdev[0].name, "sa1100"); 326 strcpy(info->subdev[0].name, plat->name);
313 info->mtd = info->subdev[0].mtd; 327 info->mtd = info->subdev[0].mtd;
314 ret = 0; 328 ret = 0;
315 } else if (info->num_subdev > 1) { 329 } else if (info->num_subdev > 1) {
@@ -322,7 +336,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
322 cdev[i] = info->subdev[i].mtd; 336 cdev[i] = info->subdev[i].mtd;
323 337
324 info->mtd = mtd_concat_create(cdev, info->num_subdev, 338 info->mtd = mtd_concat_create(cdev, info->num_subdev,
325 "sa1100"); 339 plat->name);
326 if (info->mtd == NULL) 340 if (info->mtd == NULL)
327 ret = -ENXIO; 341 ret = -ENXIO;
328#else 342#else
@@ -336,7 +350,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
336 return info; 350 return info;
337 351
338 err: 352 err:
339 sa1100_destroy(info); 353 sa1100_destroy(info, plat);
340 out: 354 out:
341 return ERR_PTR(ret); 355 return ERR_PTR(ret);
342} 356}
@@ -346,16 +360,16 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
346static int __init sa1100_mtd_probe(struct device *dev) 360static int __init sa1100_mtd_probe(struct device *dev)
347{ 361{
348 struct platform_device *pdev = to_platform_device(dev); 362 struct platform_device *pdev = to_platform_device(dev);
349 struct flash_platform_data *flash = pdev->dev.platform_data; 363 struct flash_platform_data *plat = pdev->dev.platform_data;
350 struct mtd_partition *parts; 364 struct mtd_partition *parts;
351 const char *part_type = NULL; 365 const char *part_type = NULL;
352 struct sa_info *info; 366 struct sa_info *info;
353 int err, nr_parts = 0; 367 int err, nr_parts = 0;
354 368
355 if (!flash) 369 if (!plat)
356 return -ENODEV; 370 return -ENODEV;
357 371
358 info = sa1100_setup_mtd(pdev, flash); 372 info = sa1100_setup_mtd(pdev, plat);
359 if (IS_ERR(info)) { 373 if (IS_ERR(info)) {
360 err = PTR_ERR(info); 374 err = PTR_ERR(info);
361 goto out; 375 goto out;
@@ -372,8 +386,8 @@ static int __init sa1100_mtd_probe(struct device *dev)
372 } else 386 } else
373#endif 387#endif
374 { 388 {
375 parts = flash->parts; 389 parts = plat->parts;
376 nr_parts = flash->nr_parts; 390 nr_parts = plat->nr_parts;
377 part_type = "static"; 391 part_type = "static";
378 } 392 }
379 393
@@ -387,6 +401,8 @@ static int __init sa1100_mtd_probe(struct device *dev)
387 add_mtd_partitions(info->mtd, parts, nr_parts); 401 add_mtd_partitions(info->mtd, parts, nr_parts);
388 } 402 }
389 403
404 info->nr_parts = nr_parts;
405
390 dev_set_drvdata(dev, info); 406 dev_set_drvdata(dev, info);
391 err = 0; 407 err = 0;
392 408
@@ -397,33 +413,44 @@ static int __init sa1100_mtd_probe(struct device *dev)
397static int __exit sa1100_mtd_remove(struct device *dev) 413static int __exit sa1100_mtd_remove(struct device *dev)
398{ 414{
399 struct sa_info *info = dev_get_drvdata(dev); 415 struct sa_info *info = dev_get_drvdata(dev);
416 struct flash_platform_data *plat = dev->platform_data;
417
400 dev_set_drvdata(dev, NULL); 418 dev_set_drvdata(dev, NULL);
401 sa1100_destroy(info); 419 sa1100_destroy(info, plat);
420
402 return 0; 421 return 0;
403} 422}
404 423
405#ifdef CONFIG_PM 424#ifdef CONFIG_PM
406static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level) 425static int sa1100_mtd_suspend(struct device *dev, pm_message_t state)
407{ 426{
408 struct sa_info *info = dev_get_drvdata(dev); 427 struct sa_info *info = dev_get_drvdata(dev);
409 int ret = 0; 428 int ret = 0;
410 429
411 if (info && level == SUSPEND_SAVE_STATE) 430 if (info)
412 ret = info->mtd->suspend(info->mtd); 431 ret = info->mtd->suspend(info->mtd);
413 432
414 return ret; 433 return ret;
415} 434}
416 435
417static int sa1100_mtd_resume(struct device *dev, u32 level) 436static int sa1100_mtd_resume(struct device *dev)
418{ 437{
419 struct sa_info *info = dev_get_drvdata(dev); 438 struct sa_info *info = dev_get_drvdata(dev);
420 if (info && level == RESUME_RESTORE_STATE) 439 if (info)
421 info->mtd->resume(info->mtd); 440 info->mtd->resume(info->mtd);
422 return 0; 441 return 0;
423} 442}
443
444static void sa1100_mtd_shutdown(struct device *dev)
445{
446 struct sa_info *info = dev_get_drvdata(dev);
447 if (info && info->mtd->suspend(info->mtd) == 0)
448 info->mtd->resume(info->mtd);
449}
424#else 450#else
425#define sa1100_mtd_suspend NULL 451#define sa1100_mtd_suspend NULL
426#define sa1100_mtd_resume NULL 452#define sa1100_mtd_resume NULL
453#define sa1100_mtd_shutdown NULL
427#endif 454#endif
428 455
429static struct device_driver sa1100_mtd_driver = { 456static struct device_driver sa1100_mtd_driver = {
@@ -433,6 +460,7 @@ static struct device_driver sa1100_mtd_driver = {
433 .remove = __exit_p(sa1100_mtd_remove), 460 .remove = __exit_p(sa1100_mtd_remove),
434 .suspend = sa1100_mtd_suspend, 461 .suspend = sa1100_mtd_suspend,
435 .resume = sa1100_mtd_resume, 462 .resume = sa1100_mtd_resume,
463 .shutdown = sa1100_mtd_shutdown,
436}; 464};
437 465
438static int __init sa1100_mtd_init(void) 466static int __init sa1100_mtd_init(void)