diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/base.c | 14 | ||||
-rw-r--r-- | drivers/of/fdt.c | 2 | ||||
-rw-r--r-- | drivers/of/irq.c | 28 | ||||
-rw-r--r-- | drivers/of/platform.c | 4 | ||||
-rw-r--r-- | drivers/of/selftest.c | 32 | ||||
-rw-r--r-- | drivers/of/testcase-data/tests-interrupts.dtsi | 13 |
6 files changed, 83 insertions, 10 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index f72d19b7e5d2..32e969d95319 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -1828,17 +1828,17 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1828 | next = &(*next)->next; | 1828 | next = &(*next)->next; |
1829 | } | 1829 | } |
1830 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1830 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1831 | if (rc) | 1831 | if (!found) |
1832 | return rc; | 1832 | return -ENODEV; |
1833 | |||
1834 | /* At early boot, bail out and defer setup to of_init() */ | ||
1835 | if (!of_kset) | ||
1836 | return found ? 0 : -ENODEV; | ||
1833 | 1837 | ||
1834 | /* Update the sysfs attribute */ | 1838 | /* Update the sysfs attribute */ |
1835 | if (oldprop) | 1839 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); |
1836 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | ||
1837 | __of_add_property_sysfs(np, newprop); | 1840 | __of_add_property_sysfs(np, newprop); |
1838 | 1841 | ||
1839 | if (!found) | ||
1840 | return -ENODEV; | ||
1841 | |||
1842 | return 0; | 1842 | return 0; |
1843 | } | 1843 | } |
1844 | 1844 | ||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index fa16a912a927..7a2ef7bb8022 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -491,7 +491,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, | |||
491 | * in /reserved-memory matches the values supported by the current implementation, | 491 | * in /reserved-memory matches the values supported by the current implementation, |
492 | * also check if ranges property has been provided | 492 | * also check if ranges property has been provided |
493 | */ | 493 | */ |
494 | static int __reserved_mem_check_root(unsigned long node) | 494 | static int __init __reserved_mem_check_root(unsigned long node) |
495 | { | 495 | { |
496 | __be32 *prop; | 496 | __be32 *prop; |
497 | 497 | ||
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9bcf2cf19357..5aeb89411350 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
@@ -364,7 +364,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) | |||
364 | 364 | ||
365 | memset(r, 0, sizeof(*r)); | 365 | memset(r, 0, sizeof(*r)); |
366 | /* | 366 | /* |
367 | * Get optional "interrupts-names" property to add a name | 367 | * Get optional "interrupt-names" property to add a name |
368 | * to the resource. | 368 | * to the resource. |
369 | */ | 369 | */ |
370 | of_property_read_string_index(dev, "interrupt-names", index, | 370 | of_property_read_string_index(dev, "interrupt-names", index, |
@@ -380,6 +380,32 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) | |||
380 | EXPORT_SYMBOL_GPL(of_irq_to_resource); | 380 | EXPORT_SYMBOL_GPL(of_irq_to_resource); |
381 | 381 | ||
382 | /** | 382 | /** |
383 | * of_irq_get - Decode a node's IRQ and return it as a Linux irq number | ||
384 | * @dev: pointer to device tree node | ||
385 | * @index: zero-based index of the irq | ||
386 | * | ||
387 | * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain | ||
388 | * is not yet created. | ||
389 | * | ||
390 | */ | ||
391 | int of_irq_get(struct device_node *dev, int index) | ||
392 | { | ||
393 | int rc; | ||
394 | struct of_phandle_args oirq; | ||
395 | struct irq_domain *domain; | ||
396 | |||
397 | rc = of_irq_parse_one(dev, index, &oirq); | ||
398 | if (rc) | ||
399 | return rc; | ||
400 | |||
401 | domain = irq_find_host(oirq.np); | ||
402 | if (!domain) | ||
403 | return -EPROBE_DEFER; | ||
404 | |||
405 | return irq_create_of_mapping(&oirq); | ||
406 | } | ||
407 | |||
408 | /** | ||
383 | * of_irq_count - Count the number of IRQs a node uses | 409 | * of_irq_count - Count the number of IRQs a node uses |
384 | * @dev: pointer to device tree node | 410 | * @dev: pointer to device tree node |
385 | */ | 411 | */ |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 404d1daebefa..bd47fbc53dc9 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
168 | rc = of_address_to_resource(np, i, res); | 168 | rc = of_address_to_resource(np, i, res); |
169 | WARN_ON(rc); | 169 | WARN_ON(rc); |
170 | } | 170 | } |
171 | WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); | 171 | if (of_irq_to_resource_table(np, res, num_irq) != num_irq) |
172 | pr_debug("not all legacy IRQ resources mapped for %s\n", | ||
173 | np->name); | ||
172 | } | 174 | } |
173 | 175 | ||
174 | dev->dev.of_node = of_node_get(np); | 176 | dev->dev.of_node = of_node_get(np); |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index ae4450070503..fe70b86bcffb 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
12 | #include <linux/of_irq.h> | 12 | #include <linux/of_irq.h> |
13 | #include <linux/of_platform.h> | ||
13 | #include <linux/list.h> | 14 | #include <linux/list.h> |
14 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
@@ -427,6 +428,36 @@ static void __init of_selftest_match_node(void) | |||
427 | } | 428 | } |
428 | } | 429 | } |
429 | 430 | ||
431 | static void __init of_selftest_platform_populate(void) | ||
432 | { | ||
433 | int irq; | ||
434 | struct device_node *np; | ||
435 | struct platform_device *pdev; | ||
436 | |||
437 | np = of_find_node_by_path("/testcase-data"); | ||
438 | of_platform_populate(np, of_default_bus_match_table, NULL, NULL); | ||
439 | |||
440 | /* Test that a missing irq domain returns -EPROBE_DEFER */ | ||
441 | np = of_find_node_by_path("/testcase-data/testcase-device1"); | ||
442 | pdev = of_find_device_by_node(np); | ||
443 | if (!pdev) | ||
444 | selftest(0, "device 1 creation failed\n"); | ||
445 | irq = platform_get_irq(pdev, 0); | ||
446 | if (irq != -EPROBE_DEFER) | ||
447 | selftest(0, "device deferred probe failed - %d\n", irq); | ||
448 | |||
449 | /* Test that a parsing failure does not return -EPROBE_DEFER */ | ||
450 | np = of_find_node_by_path("/testcase-data/testcase-device2"); | ||
451 | pdev = of_find_device_by_node(np); | ||
452 | if (!pdev) | ||
453 | selftest(0, "device 2 creation failed\n"); | ||
454 | irq = platform_get_irq(pdev, 0); | ||
455 | if (irq >= 0 || irq == -EPROBE_DEFER) | ||
456 | selftest(0, "device parsing error failed - %d\n", irq); | ||
457 | |||
458 | selftest(1, "passed"); | ||
459 | } | ||
460 | |||
430 | static int __init of_selftest(void) | 461 | static int __init of_selftest(void) |
431 | { | 462 | { |
432 | struct device_node *np; | 463 | struct device_node *np; |
@@ -445,6 +476,7 @@ static int __init of_selftest(void) | |||
445 | of_selftest_parse_interrupts(); | 476 | of_selftest_parse_interrupts(); |
446 | of_selftest_parse_interrupts_extended(); | 477 | of_selftest_parse_interrupts_extended(); |
447 | of_selftest_match_node(); | 478 | of_selftest_match_node(); |
479 | of_selftest_platform_populate(); | ||
448 | pr_info("end of selftest - %i passed, %i failed\n", | 480 | pr_info("end of selftest - %i passed, %i failed\n", |
449 | selftest_results.passed, selftest_results.failed); | 481 | selftest_results.passed, selftest_results.failed); |
450 | return 0; | 482 | return 0; |
diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi index c843720bd3e5..da4695f60351 100644 --- a/drivers/of/testcase-data/tests-interrupts.dtsi +++ b/drivers/of/testcase-data/tests-interrupts.dtsi | |||
@@ -54,5 +54,18 @@ | |||
54 | <&test_intmap1 1 2>; | 54 | <&test_intmap1 1 2>; |
55 | }; | 55 | }; |
56 | }; | 56 | }; |
57 | |||
58 | testcase-device1 { | ||
59 | compatible = "testcase-device"; | ||
60 | interrupt-parent = <&test_intc0>; | ||
61 | interrupts = <1>; | ||
62 | }; | ||
63 | |||
64 | testcase-device2 { | ||
65 | compatible = "testcase-device"; | ||
66 | interrupt-parent = <&test_intc2>; | ||
67 | interrupts = <1>; /* invalid specifier - too short */ | ||
68 | }; | ||
57 | }; | 69 | }; |
70 | |||
58 | }; | 71 | }; |