|
34 | 34 | #include <linux/slab.h>
|
35 | 35 | #include <linux/compiler.h>
|
36 | 36 | #include <linux/pstore_ram.h>
|
| 37 | +#include <linux/of.h> |
| 38 | +#include <linux/of_address.h> |
37 | 39 |
|
38 | 40 | #define RAMOOPS_KERNMSG_HDR "===="
|
39 | 41 | #define MIN_MEM_SIZE 4096UL
|
@@ -458,15 +460,98 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
|
458 | 460 | return 0;
|
459 | 461 | }
|
460 | 462 |
|
| 463 | +static int ramoops_parse_dt_size(struct platform_device *pdev, |
| 464 | + const char *propname, u32 *value) |
| 465 | +{ |
| 466 | + u32 val32 = 0; |
| 467 | + int ret; |
| 468 | + |
| 469 | + ret = of_property_read_u32(pdev->dev.of_node, propname, &val32); |
| 470 | + if (ret < 0 && ret != -EINVAL) { |
| 471 | + dev_err(&pdev->dev, "failed to parse property %s: %d\n", |
| 472 | + propname, ret); |
| 473 | + return ret; |
| 474 | + } |
| 475 | + |
| 476 | + if (val32 > INT_MAX) { |
| 477 | + dev_err(&pdev->dev, "%s %u > INT_MAX\n", propname, val32); |
| 478 | + return -EOVERFLOW; |
| 479 | + } |
| 480 | + |
| 481 | + *value = val32; |
| 482 | + return 0; |
| 483 | +} |
| 484 | + |
| 485 | +static int ramoops_parse_dt(struct platform_device *pdev, |
| 486 | + struct ramoops_platform_data *pdata) |
| 487 | +{ |
| 488 | + struct device_node *of_node = pdev->dev.of_node; |
| 489 | + struct device_node *mem_region; |
| 490 | + struct resource res; |
| 491 | + u32 value; |
| 492 | + int ret; |
| 493 | + |
| 494 | + dev_dbg(&pdev->dev, "using Device Tree\n"); |
| 495 | + |
| 496 | + mem_region = of_parse_phandle(of_node, "memory-region", 0); |
| 497 | + if (!mem_region) { |
| 498 | + dev_err(&pdev->dev, "no memory-region phandle\n"); |
| 499 | + return -ENODEV; |
| 500 | + } |
| 501 | + |
| 502 | + ret = of_address_to_resource(mem_region, 0, &res); |
| 503 | + of_node_put(mem_region); |
| 504 | + if (ret) { |
| 505 | + dev_err(&pdev->dev, |
| 506 | + "failed to translate memory-region to resource: %d\n", |
| 507 | + ret); |
| 508 | + return ret; |
| 509 | + } |
| 510 | + |
| 511 | + pdata->mem_size = resource_size(&res); |
| 512 | + pdata->mem_address = res.start; |
| 513 | + pdata->mem_type = of_property_read_bool(of_node, "unbuffered"); |
| 514 | + pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops"); |
| 515 | + |
| 516 | +#define parse_size(name, field) { \ |
| 517 | + ret = ramoops_parse_dt_size(pdev, name, &value); \ |
| 518 | + if (ret < 0) \ |
| 519 | + return ret; \ |
| 520 | + field = value; \ |
| 521 | + } |
| 522 | + |
| 523 | + parse_size("record-size", pdata->record_size); |
| 524 | + parse_size("console-size", pdata->console_size); |
| 525 | + parse_size("ftrace-size", pdata->ftrace_size); |
| 526 | + parse_size("pmsg-size", pdata->pmsg_size); |
| 527 | + parse_size("ecc-size", pdata->ecc_info.ecc_size); |
| 528 | + |
| 529 | +#undef parse_size |
| 530 | + |
| 531 | + return 0; |
| 532 | +} |
| 533 | + |
461 | 534 | static int ramoops_probe(struct platform_device *pdev)
|
462 | 535 | {
|
463 | 536 | struct device *dev = &pdev->dev;
|
464 |
| - struct ramoops_platform_data *pdata = pdev->dev.platform_data; |
| 537 | + struct ramoops_platform_data *pdata = dev->platform_data; |
465 | 538 | struct ramoops_context *cxt = &oops_cxt;
|
466 | 539 | size_t dump_mem_sz;
|
467 | 540 | phys_addr_t paddr;
|
468 | 541 | int err = -EINVAL;
|
469 | 542 |
|
| 543 | + if (dev_of_node(dev) && !pdata) { |
| 544 | + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| 545 | + if (!pdata) { |
| 546 | + err = -ENOMEM; |
| 547 | + goto fail_out; |
| 548 | + } |
| 549 | + |
| 550 | + err = ramoops_parse_dt(pdev, pdata); |
| 551 | + if (err < 0) |
| 552 | + goto fail_out; |
| 553 | + } |
| 554 | + |
470 | 555 | /* Only a single ramoops area allowed at a time, so fail extra
|
471 | 556 | * probes.
|
472 | 557 | */
|
@@ -596,11 +681,17 @@ static int ramoops_remove(struct platform_device *pdev)
|
596 | 681 | return 0;
|
597 | 682 | }
|
598 | 683 |
|
| 684 | +static const struct of_device_id dt_match[] = { |
| 685 | + { .compatible = "ramoops" }, |
| 686 | + {} |
| 687 | +}; |
| 688 | + |
599 | 689 | static struct platform_driver ramoops_driver = {
|
600 | 690 | .probe = ramoops_probe,
|
601 | 691 | .remove = ramoops_remove,
|
602 | 692 | .driver = {
|
603 |
| - .name = "ramoops", |
| 693 | + .name = "ramoops", |
| 694 | + .of_match_table = dt_match, |
604 | 695 | },
|
605 | 696 | };
|
606 | 697 |
|
|
0 commit comments