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