diff options
Diffstat (limited to 'drivers/mtd/maps/sa1100-flash.c')
| -rw-r--r-- | drivers/mtd/maps/sa1100-flash.c | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 6a8e0caf9fdc..c81bec7b14d5 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c | |||
| @@ -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 | ||
| 136 | struct sa_info { | 136 | struct 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 | ||
| 143 | static void sa1100_set_vpp(struct map_info *map, int on) | 144 | static 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 | ||
| 149 | static void sa1100_destroy_subdev(struct sa_subdev_info *subdev) | 150 | static 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 | ||
| 226 | static void sa1100_destroy(struct sa_info *info) | 227 | static 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 | ||
| 247 | static struct sa_info *__init | 255 | static struct sa_info *__init |
| 248 | 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) |
| 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 }; | |||
| 346 | static int __init sa1100_mtd_probe(struct device *dev) | 360 | static 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,8 +413,11 @@ static int __init sa1100_mtd_probe(struct device *dev) | |||
| 397 | static int __exit sa1100_mtd_remove(struct device *dev) | 413 | static 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 | ||
| @@ -421,9 +440,17 @@ static int sa1100_mtd_resume(struct device *dev) | |||
| 421 | info->mtd->resume(info->mtd); | 440 | info->mtd->resume(info->mtd); |
| 422 | return 0; | 441 | return 0; |
| 423 | } | 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 | } | ||
| 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 | ||
| 429 | static struct device_driver sa1100_mtd_driver = { | 456 | static 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 | ||
| 438 | static int __init sa1100_mtd_init(void) | 466 | static int __init sa1100_mtd_init(void) |
