|
27 | 27 | #include <linux/slab.h> |
28 | 28 | #include <linux/mtd/mtd.h> |
29 | 29 | #include <asm/div64.h> |
| 30 | +#include <linux/platform_device.h> |
| 31 | +#include <linux/of_address.h> |
| 32 | +#include <linux/of.h> |
30 | 33 |
|
31 | 34 | struct phram_mtd_list { |
32 | 35 | struct mtd_info mtd; |
@@ -89,8 +92,10 @@ static void unregister_devices(void) |
89 | 92 | } |
90 | 93 | } |
91 | 94 |
|
92 | | -static int register_device(char *name, phys_addr_t start, size_t len, uint32_t erasesize) |
| 95 | +static int register_device(struct platform_device *pdev, const char *name, |
| 96 | + phys_addr_t start, size_t len, uint32_t erasesize) |
93 | 97 | { |
| 98 | + struct device_node *np = pdev ? pdev->dev.of_node : NULL; |
94 | 99 | struct phram_mtd_list *new; |
95 | 100 | int ret = -ENOMEM; |
96 | 101 |
|
@@ -119,13 +124,19 @@ static int register_device(char *name, phys_addr_t start, size_t len, uint32_t e |
119 | 124 | new->mtd.erasesize = erasesize; |
120 | 125 | new->mtd.writesize = 1; |
121 | 126 |
|
| 127 | + mtd_set_of_node(&new->mtd, np); |
| 128 | + |
122 | 129 | ret = -EAGAIN; |
123 | 130 | if (mtd_device_register(&new->mtd, NULL, 0)) { |
124 | 131 | pr_err("Failed to register new device\n"); |
125 | 132 | goto out2; |
126 | 133 | } |
127 | 134 |
|
128 | | - list_add_tail(&new->list, &phram_list); |
| 135 | + if (pdev) |
| 136 | + platform_set_drvdata(pdev, new); |
| 137 | + else |
| 138 | + list_add_tail(&new->list, &phram_list); |
| 139 | + |
129 | 140 | return 0; |
130 | 141 |
|
131 | 142 | out2: |
@@ -278,7 +289,7 @@ static int phram_setup(const char *val) |
278 | 289 | goto error; |
279 | 290 | } |
280 | 291 |
|
281 | | - ret = register_device(name, start, len, (uint32_t)erasesize); |
| 292 | + ret = register_device(NULL, name, start, len, (uint32_t)erasesize); |
282 | 293 | if (ret) |
283 | 294 | goto error; |
284 | 295 |
|
@@ -325,23 +336,71 @@ static int phram_param_call(const char *val, const struct kernel_param *kp) |
325 | 336 | module_param_call(phram, phram_param_call, NULL, NULL, 0200); |
326 | 337 | MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>[,<erasesize>]\""); |
327 | 338 |
|
| 339 | +#ifdef CONFIG_OF |
| 340 | +static const struct of_device_id phram_of_match[] = { |
| 341 | + { .compatible = "phram" }, |
| 342 | + {} |
| 343 | +}; |
| 344 | +MODULE_DEVICE_TABLE(of, phram_of_match); |
| 345 | +#endif |
| 346 | + |
| 347 | +static int phram_probe(struct platform_device *pdev) |
| 348 | +{ |
| 349 | + struct resource *res; |
| 350 | + |
| 351 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 352 | + if (!res) |
| 353 | + return -ENOMEM; |
| 354 | + |
| 355 | + /* mtd_set_of_node() reads name from "label" */ |
| 356 | + return register_device(pdev, NULL, res->start, resource_size(res), |
| 357 | + PAGE_SIZE); |
| 358 | +} |
| 359 | + |
| 360 | +static int phram_remove(struct platform_device *pdev) |
| 361 | +{ |
| 362 | + struct phram_mtd_list *phram = platform_get_drvdata(pdev); |
| 363 | + |
| 364 | + mtd_device_unregister(&phram->mtd); |
| 365 | + iounmap(phram->mtd.priv); |
| 366 | + kfree(phram); |
| 367 | + |
| 368 | + return 0; |
| 369 | +} |
| 370 | + |
| 371 | +static struct platform_driver phram_driver = { |
| 372 | + .probe = phram_probe, |
| 373 | + .remove = phram_remove, |
| 374 | + .driver = { |
| 375 | + .name = "phram", |
| 376 | + .of_match_table = of_match_ptr(phram_of_match), |
| 377 | + }, |
| 378 | +}; |
328 | 379 |
|
329 | 380 | static int __init init_phram(void) |
330 | 381 | { |
331 | | - int ret = 0; |
| 382 | + int ret; |
| 383 | + |
| 384 | + ret = platform_driver_register(&phram_driver); |
| 385 | + if (ret) |
| 386 | + return ret; |
332 | 387 |
|
333 | 388 | #ifndef MODULE |
334 | 389 | if (phram_paramline[0]) |
335 | 390 | ret = phram_setup(phram_paramline); |
336 | 391 | phram_init_called = 1; |
337 | 392 | #endif |
338 | 393 |
|
| 394 | + if (ret) |
| 395 | + platform_driver_unregister(&phram_driver); |
| 396 | + |
339 | 397 | return ret; |
340 | 398 | } |
341 | 399 |
|
342 | 400 | static void __exit cleanup_phram(void) |
343 | 401 | { |
344 | 402 | unregister_devices(); |
| 403 | + platform_driver_unregister(&phram_driver); |
345 | 404 | } |
346 | 405 |
|
347 | 406 | module_init(init_phram); |
|
0 commit comments