aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/testcases/tests-phandle.dtsi37
-rw-r--r--arch/arm/boot/dts/testcases/tests.dtsi1
-rw-r--r--arch/arm/boot/dts/versatile-pb.dts2
-rw-r--r--drivers/of/Kconfig9
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/selftest.c139
6 files changed, 189 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
new file mode 100644
index 000000000000..ec0c4e6212c9
--- /dev/null
+++ b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
@@ -0,0 +1,37 @@
1
2/ {
3 testcase-data {
4 phandle-tests {
5 provider0: provider0 {
6 #phandle-cells = <0>;
7 };
8
9 provider1: provider1 {
10 #phandle-cells = <1>;
11 };
12
13 provider2: provider2 {
14 #phandle-cells = <2>;
15 };
16
17 provider3: provider3 {
18 #phandle-cells = <3>;
19 };
20
21 consumer-a {
22 phandle-list = <&provider1 1>,
23 <&provider2 2 0>,
24 <0>,
25 <&provider3 4 4 3>,
26 <&provider2 5 100>,
27 <&provider0>,
28 <&provider1 7>;
29 phandle-list-names = "first", "second", "third";
30
31 phandle-list-bad-phandle = <12345678 0 0>;
32 phandle-list-bad-args = <&provider2 1 0>,
33 <&provider3 0>;
34 };
35 };
36 };
37};
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
new file mode 100644
index 000000000000..a7c5067622e8
--- /dev/null
+++ b/arch/arm/boot/dts/testcases/tests.dtsi
@@ -0,0 +1 @@
/include/ "tests-phandle.dtsi"
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 8a614e398004..166461073b78 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -46,3 +46,5 @@
46 }; 46 };
47 }; 47 };
48}; 48};
49
50/include/ "testcases/tests.dtsi"
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index cac63c9f49ae..268163dd71c7 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -15,6 +15,15 @@ config PROC_DEVICETREE
15 an image of the device tree that the kernel copies from Open 15 an image of the device tree that the kernel copies from Open
16 Firmware or other boot firmware. If unsure, say Y here. 16 Firmware or other boot firmware. If unsure, say Y here.
17 17
18config OF_SELFTEST
19 bool "Device Tree Runtime self tests"
20 help
21 This option builds in test cases for the device tree infrastructure
22 that are executed one at boot time, and the results dumped to the
23 console.
24
25 If unsure, say N here, but this option is safe to enable.
26
18config OF_FLATTREE 27config OF_FLATTREE
19 bool 28 bool
20 select DTC 29 select DTC
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index dccb1176be57..a73f5a51ff4c 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
8obj-$(CONFIG_OF_I2C) += of_i2c.o 8obj-$(CONFIG_OF_I2C) += of_i2c.o
9obj-$(CONFIG_OF_NET) += of_net.o 9obj-$(CONFIG_OF_NET) += of_net.o
10obj-$(CONFIG_OF_SPI) += of_spi.o 10obj-$(CONFIG_OF_SPI) += of_spi.o
11obj-$(CONFIG_OF_SELFTEST) += selftest.o
11obj-$(CONFIG_OF_MDIO) += of_mdio.o 12obj-$(CONFIG_OF_MDIO) += of_mdio.o
12obj-$(CONFIG_OF_PCI) += of_pci.o 13obj-$(CONFIG_OF_PCI) += of_pci.o
13obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o 14obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
new file mode 100644
index 000000000000..9d2b4803a9d6
--- /dev/null
+++ b/drivers/of/selftest.c
@@ -0,0 +1,139 @@
1/*
2 * Self tests for device tree subsystem
3 */
4
5#define pr_fmt(fmt) "### %s(): " fmt, __func__
6
7#include <linux/clk.h>
8#include <linux/err.h>
9#include <linux/errno.h>
10#include <linux/module.h>
11#include <linux/of.h>
12#include <linux/list.h>
13#include <linux/mutex.h>
14#include <linux/slab.h>
15#include <linux/device.h>
16
17static bool selftest_passed = true;
18#define selftest(result, fmt, ...) { \
19 selftest_passed &= (result); \
20 if (!(result)) \
21 pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
22}
23
24static void __init of_selftest_parse_phandle_with_args(void)
25{
26 struct device_node *np;
27 struct of_phandle_args args;
28 int rc, i;
29 bool passed_all = true;
30
31 pr_info("start\n");
32 np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
33 if (!np) {
34 pr_err("missing testcase data\n");
35 return;
36 }
37
38 for (i = 0; i < 7; i++) {
39 bool passed = true;
40 rc = of_parse_phandle_with_args(np, "phandle-list",
41 "#phandle-cells", i, &args);
42
43 /* Test the values from tests-phandle.dtsi */
44 switch (i) {
45 case 0:
46 passed &= !rc;
47 passed &= (args.args_count == 1);
48 passed &= (args.args[0] == (i + 1));
49 break;
50 case 1:
51 passed &= !rc;
52 passed &= (args.args_count == 2);
53 passed &= (args.args[0] == (i + 1));
54 passed &= (args.args[1] == 0);
55 break;
56 case 2:
57 passed &= (rc == -ENOENT);
58 break;
59 case 3:
60 passed &= !rc;
61 passed &= (args.args_count == 3);
62 passed &= (args.args[0] == (i + 1));
63 passed &= (args.args[1] == 4);
64 passed &= (args.args[2] == 3);
65 break;
66 case 4:
67 passed &= !rc;
68 passed &= (args.args_count == 2);
69 passed &= (args.args[0] == (i + 1));
70 passed &= (args.args[1] == 100);
71 break;
72 case 5:
73 passed &= !rc;
74 passed &= (args.args_count == 0);
75 break;
76 case 6:
77 passed &= !rc;
78 passed &= (args.args_count == 1);
79 passed &= (args.args[0] == (i + 1));
80 break;
81 case 7:
82 passed &= (rc == -EINVAL);
83 break;
84 default:
85 passed = false;
86 }
87
88 if (!passed) {
89 int j;
90 pr_err("index %i - data error on node %s rc=%i regs=[",
91 i, args.np->full_name, rc);
92 for (j = 0; j < args.args_count; j++)
93 printk(" %i", args.args[j]);
94 printk(" ]\n");
95
96 passed_all = false;
97 }
98 }
99
100 /* Check for missing list property */
101 rc = of_parse_phandle_with_args(np, "phandle-list-missing",
102 "#phandle-cells", 0, &args);
103 passed_all &= (rc == -EINVAL);
104
105 /* Check for missing cells property */
106 rc = of_parse_phandle_with_args(np, "phandle-list",
107 "#phandle-cells-missing", 0, &args);
108 passed_all &= (rc == -EINVAL);
109
110 /* Check for bad phandle in list */
111 rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
112 "#phandle-cells", 0, &args);
113 passed_all &= (rc == -EINVAL);
114
115 /* Check for incorrectly formed argument list */
116 rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
117 "#phandle-cells", 1, &args);
118 passed_all &= (rc == -EINVAL);
119
120 pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
121}
122
123static int __init of_selftest(void)
124{
125 struct device_node *np;
126
127 np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
128 if (!np) {
129 pr_info("No testcase data in device tree; not running tests\n");
130 return 0;
131 }
132 of_node_put(np);
133
134 pr_info("start of selftest - you will see error messages\n");
135 of_selftest_parse_phandle_with_args();
136 pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
137 return 0;
138}
139late_initcall(of_selftest);