]> git.karo-electronics.de Git - linux-beck.git/blob - drivers/of/selftest.c
OF: Utility helper functions for dynamic nodes
[linux-beck.git] / drivers / of / selftest.c
1 /*
2  * Self tests for device tree subsystem
3  */
4
5 #define pr_fmt(fmt) "### dt-test ### " fmt
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/of_irq.h>
13 #include <linux/of_platform.h>
14 #include <linux/list.h>
15 #include <linux/mutex.h>
16 #include <linux/slab.h>
17 #include <linux/device.h>
18
19 #include "of_private.h"
20
21 static struct selftest_results {
22         int passed;
23         int failed;
24 } selftest_results;
25
26 #define selftest(result, fmt, ...) { \
27         if (!(result)) { \
28                 selftest_results.failed++; \
29                 pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \
30         } else { \
31                 selftest_results.passed++; \
32                 pr_debug("pass %s():%i\n", __func__, __LINE__); \
33         } \
34 }
35
36 static void __init of_selftest_find_node_by_name(void)
37 {
38         struct device_node *np;
39
40         np = of_find_node_by_path("/testcase-data");
41         selftest(np && !strcmp("/testcase-data", np->full_name),
42                 "find /testcase-data failed\n");
43         of_node_put(np);
44
45         /* Test if trailing '/' works */
46         np = of_find_node_by_path("/testcase-data/");
47         selftest(!np, "trailing '/' on /testcase-data/ should fail\n");
48
49         np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
50         selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name),
51                 "find /testcase-data/phandle-tests/consumer-a failed\n");
52         of_node_put(np);
53
54         np = of_find_node_by_path("testcase-alias");
55         selftest(np && !strcmp("/testcase-data", np->full_name),
56                 "find testcase-alias failed\n");
57         of_node_put(np);
58
59         /* Test if trailing '/' works on aliases */
60         np = of_find_node_by_path("testcase-alias/");
61         selftest(!np, "trailing '/' on testcase-alias/ should fail\n");
62
63         np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a");
64         selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name),
65                 "find testcase-alias/phandle-tests/consumer-a failed\n");
66         of_node_put(np);
67
68         np = of_find_node_by_path("/testcase-data/missing-path");
69         selftest(!np, "non-existent path returned node %s\n", np->full_name);
70         of_node_put(np);
71
72         np = of_find_node_by_path("missing-alias");
73         selftest(!np, "non-existent alias returned node %s\n", np->full_name);
74         of_node_put(np);
75
76         np = of_find_node_by_path("testcase-alias/missing-path");
77         selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name);
78         of_node_put(np);
79 }
80
81 static void __init of_selftest_dynamic(void)
82 {
83         struct device_node *np;
84         struct property *prop;
85
86         np = of_find_node_by_path("/testcase-data");
87         if (!np) {
88                 pr_err("missing testcase data\n");
89                 return;
90         }
91
92         /* Array of 4 properties for the purpose of testing */
93         prop = kzalloc(sizeof(*prop) * 4, GFP_KERNEL);
94         if (!prop) {
95                 selftest(0, "kzalloc() failed\n");
96                 return;
97         }
98
99         /* Add a new property - should pass*/
100         prop->name = "new-property";
101         prop->value = "new-property-data";
102         prop->length = strlen(prop->value);
103         selftest(of_add_property(np, prop) == 0, "Adding a new property failed\n");
104
105         /* Try to add an existing property - should fail */
106         prop++;
107         prop->name = "new-property";
108         prop->value = "new-property-data-should-fail";
109         prop->length = strlen(prop->value);
110         selftest(of_add_property(np, prop) != 0,
111                  "Adding an existing property should have failed\n");
112
113         /* Try to modify an existing property - should pass */
114         prop->value = "modify-property-data-should-pass";
115         prop->length = strlen(prop->value);
116         selftest(of_update_property(np, prop) == 0,
117                  "Updating an existing property should have passed\n");
118
119         /* Try to modify non-existent property - should pass*/
120         prop++;
121         prop->name = "modify-property";
122         prop->value = "modify-missing-property-data-should-pass";
123         prop->length = strlen(prop->value);
124         selftest(of_update_property(np, prop) == 0,
125                  "Updating a missing property should have passed\n");
126
127         /* Remove property - should pass */
128         selftest(of_remove_property(np, prop) == 0,
129                  "Removing a property should have passed\n");
130
131         /* Adding very large property - should pass */
132         prop++;
133         prop->name = "large-property-PAGE_SIZEx8";
134         prop->length = PAGE_SIZE * 8;
135         prop->value = kzalloc(prop->length, GFP_KERNEL);
136         selftest(prop->value != NULL, "Unable to allocate large buffer\n");
137         if (prop->value)
138                 selftest(of_add_property(np, prop) == 0,
139                          "Adding a large property should have passed\n");
140 }
141
142 static void __init of_selftest_parse_phandle_with_args(void)
143 {
144         struct device_node *np;
145         struct of_phandle_args args;
146         int i, rc;
147
148         np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
149         if (!np) {
150                 pr_err("missing testcase data\n");
151                 return;
152         }
153
154         rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells");
155         selftest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc);
156
157         for (i = 0; i < 8; i++) {
158                 bool passed = true;
159                 rc = of_parse_phandle_with_args(np, "phandle-list",
160                                                 "#phandle-cells", i, &args);
161
162                 /* Test the values from tests-phandle.dtsi */
163                 switch (i) {
164                 case 0:
165                         passed &= !rc;
166                         passed &= (args.args_count == 1);
167                         passed &= (args.args[0] == (i + 1));
168                         break;
169                 case 1:
170                         passed &= !rc;
171                         passed &= (args.args_count == 2);
172                         passed &= (args.args[0] == (i + 1));
173                         passed &= (args.args[1] == 0);
174                         break;
175                 case 2:
176                         passed &= (rc == -ENOENT);
177                         break;
178                 case 3:
179                         passed &= !rc;
180                         passed &= (args.args_count == 3);
181                         passed &= (args.args[0] == (i + 1));
182                         passed &= (args.args[1] == 4);
183                         passed &= (args.args[2] == 3);
184                         break;
185                 case 4:
186                         passed &= !rc;
187                         passed &= (args.args_count == 2);
188                         passed &= (args.args[0] == (i + 1));
189                         passed &= (args.args[1] == 100);
190                         break;
191                 case 5:
192                         passed &= !rc;
193                         passed &= (args.args_count == 0);
194                         break;
195                 case 6:
196                         passed &= !rc;
197                         passed &= (args.args_count == 1);
198                         passed &= (args.args[0] == (i + 1));
199                         break;
200                 case 7:
201                         passed &= (rc == -ENOENT);
202                         break;
203                 default:
204                         passed = false;
205                 }
206
207                 selftest(passed, "index %i - data error on node %s rc=%i\n",
208                          i, args.np->full_name, rc);
209         }
210
211         /* Check for missing list property */
212         rc = of_parse_phandle_with_args(np, "phandle-list-missing",
213                                         "#phandle-cells", 0, &args);
214         selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc);
215         rc = of_count_phandle_with_args(np, "phandle-list-missing",
216                                         "#phandle-cells");
217         selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc);
218
219         /* Check for missing cells property */
220         rc = of_parse_phandle_with_args(np, "phandle-list",
221                                         "#phandle-cells-missing", 0, &args);
222         selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
223         rc = of_count_phandle_with_args(np, "phandle-list",
224                                         "#phandle-cells-missing");
225         selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
226
227         /* Check for bad phandle in list */
228         rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
229                                         "#phandle-cells", 0, &args);
230         selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
231         rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle",
232                                         "#phandle-cells");
233         selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
234
235         /* Check for incorrectly formed argument list */
236         rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
237                                         "#phandle-cells", 1, &args);
238         selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
239         rc = of_count_phandle_with_args(np, "phandle-list-bad-args",
240                                         "#phandle-cells");
241         selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
242 }
243
244 static void __init of_selftest_property_match_string(void)
245 {
246         struct device_node *np;
247         int rc;
248
249         np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
250         if (!np) {
251                 pr_err("No testcase data in device tree\n");
252                 return;
253         }
254
255         rc = of_property_match_string(np, "phandle-list-names", "first");
256         selftest(rc == 0, "first expected:0 got:%i\n", rc);
257         rc = of_property_match_string(np, "phandle-list-names", "second");
258         selftest(rc == 1, "second expected:0 got:%i\n", rc);
259         rc = of_property_match_string(np, "phandle-list-names", "third");
260         selftest(rc == 2, "third expected:0 got:%i\n", rc);
261         rc = of_property_match_string(np, "phandle-list-names", "fourth");
262         selftest(rc == -ENODATA, "unmatched string; rc=%i", rc);
263         rc = of_property_match_string(np, "missing-property", "blah");
264         selftest(rc == -EINVAL, "missing property; rc=%i", rc);
265         rc = of_property_match_string(np, "empty-property", "blah");
266         selftest(rc == -ENODATA, "empty property; rc=%i", rc);
267         rc = of_property_match_string(np, "unterminated-string", "blah");
268         selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
269 }
270
271 #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \
272                         (p1)->value && (p2)->value && \
273                         !memcmp((p1)->value, (p2)->value, (p1)->length) && \
274                         !strcmp((p1)->name, (p2)->name))
275 static void __init of_selftest_property_copy(void)
276 {
277 #ifdef CONFIG_OF_DYNAMIC
278         struct property p1 = { .name = "p1", .length = 0, .value = "" };
279         struct property p2 = { .name = "p2", .length = 5, .value = "abcd" };
280         struct property *new;
281
282         new = __of_prop_dup(&p1, GFP_KERNEL);
283         selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n");
284         kfree(new->value);
285         kfree(new->name);
286         kfree(new);
287
288         new = __of_prop_dup(&p2, GFP_KERNEL);
289         selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n");
290         kfree(new->value);
291         kfree(new->name);
292         kfree(new);
293 #endif
294 }
295
296 static void __init of_selftest_parse_interrupts(void)
297 {
298         struct device_node *np;
299         struct of_phandle_args args;
300         int i, rc;
301
302         np = of_find_node_by_path("/testcase-data/interrupts/interrupts0");
303         if (!np) {
304                 pr_err("missing testcase data\n");
305                 return;
306         }
307
308         for (i = 0; i < 4; i++) {
309                 bool passed = true;
310                 args.args_count = 0;
311                 rc = of_irq_parse_one(np, i, &args);
312
313                 passed &= !rc;
314                 passed &= (args.args_count == 1);
315                 passed &= (args.args[0] == (i + 1));
316
317                 selftest(passed, "index %i - data error on node %s rc=%i\n",
318                          i, args.np->full_name, rc);
319         }
320         of_node_put(np);
321
322         np = of_find_node_by_path("/testcase-data/interrupts/interrupts1");
323         if (!np) {
324                 pr_err("missing testcase data\n");
325                 return;
326         }
327
328         for (i = 0; i < 4; i++) {
329                 bool passed = true;
330                 args.args_count = 0;
331                 rc = of_irq_parse_one(np, i, &args);
332
333                 /* Test the values from tests-phandle.dtsi */
334                 switch (i) {
335                 case 0:
336                         passed &= !rc;
337                         passed &= (args.args_count == 1);
338                         passed &= (args.args[0] == 9);
339                         break;
340                 case 1:
341                         passed &= !rc;
342                         passed &= (args.args_count == 3);
343                         passed &= (args.args[0] == 10);
344                         passed &= (args.args[1] == 11);
345                         passed &= (args.args[2] == 12);
346                         break;
347                 case 2:
348                         passed &= !rc;
349                         passed &= (args.args_count == 2);
350                         passed &= (args.args[0] == 13);
351                         passed &= (args.args[1] == 14);
352                         break;
353                 case 3:
354                         passed &= !rc;
355                         passed &= (args.args_count == 2);
356                         passed &= (args.args[0] == 15);
357                         passed &= (args.args[1] == 16);
358                         break;
359                 default:
360                         passed = false;
361                 }
362                 selftest(passed, "index %i - data error on node %s rc=%i\n",
363                          i, args.np->full_name, rc);
364         }
365         of_node_put(np);
366 }
367
368 static void __init of_selftest_parse_interrupts_extended(void)
369 {
370         struct device_node *np;
371         struct of_phandle_args args;
372         int i, rc;
373
374         np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
375         if (!np) {
376                 pr_err("missing testcase data\n");
377                 return;
378         }
379
380         for (i = 0; i < 7; i++) {
381                 bool passed = true;
382                 rc = of_irq_parse_one(np, i, &args);
383
384                 /* Test the values from tests-phandle.dtsi */
385                 switch (i) {
386                 case 0:
387                         passed &= !rc;
388                         passed &= (args.args_count == 1);
389                         passed &= (args.args[0] == 1);
390                         break;
391                 case 1:
392                         passed &= !rc;
393                         passed &= (args.args_count == 3);
394                         passed &= (args.args[0] == 2);
395                         passed &= (args.args[1] == 3);
396                         passed &= (args.args[2] == 4);
397                         break;
398                 case 2:
399                         passed &= !rc;
400                         passed &= (args.args_count == 2);
401                         passed &= (args.args[0] == 5);
402                         passed &= (args.args[1] == 6);
403                         break;
404                 case 3:
405                         passed &= !rc;
406                         passed &= (args.args_count == 1);
407                         passed &= (args.args[0] == 9);
408                         break;
409                 case 4:
410                         passed &= !rc;
411                         passed &= (args.args_count == 3);
412                         passed &= (args.args[0] == 10);
413                         passed &= (args.args[1] == 11);
414                         passed &= (args.args[2] == 12);
415                         break;
416                 case 5:
417                         passed &= !rc;
418                         passed &= (args.args_count == 2);
419                         passed &= (args.args[0] == 13);
420                         passed &= (args.args[1] == 14);
421                         break;
422                 case 6:
423                         passed &= !rc;
424                         passed &= (args.args_count == 1);
425                         passed &= (args.args[0] == 15);
426                         break;
427                 default:
428                         passed = false;
429                 }
430
431                 selftest(passed, "index %i - data error on node %s rc=%i\n",
432                          i, args.np->full_name, rc);
433         }
434         of_node_put(np);
435 }
436
437 static struct of_device_id match_node_table[] = {
438         { .data = "A", .name = "name0", }, /* Name alone is lowest priority */
439         { .data = "B", .type = "type1", }, /* followed by type alone */
440
441         { .data = "Ca", .name = "name2", .type = "type1", }, /* followed by both together */
442         { .data = "Cb", .name = "name2", }, /* Only match when type doesn't match */
443         { .data = "Cc", .name = "name2", .type = "type2", },
444
445         { .data = "E", .compatible = "compat3" },
446         { .data = "G", .compatible = "compat2", },
447         { .data = "H", .compatible = "compat2", .name = "name5", },
448         { .data = "I", .compatible = "compat2", .type = "type1", },
449         { .data = "J", .compatible = "compat2", .type = "type1", .name = "name8", },
450         { .data = "K", .compatible = "compat2", .name = "name9", },
451         {}
452 };
453
454 static struct {
455         const char *path;
456         const char *data;
457 } match_node_tests[] = {
458         { .path = "/testcase-data/match-node/name0", .data = "A", },
459         { .path = "/testcase-data/match-node/name1", .data = "B", },
460         { .path = "/testcase-data/match-node/a/name2", .data = "Ca", },
461         { .path = "/testcase-data/match-node/b/name2", .data = "Cb", },
462         { .path = "/testcase-data/match-node/c/name2", .data = "Cc", },
463         { .path = "/testcase-data/match-node/name3", .data = "E", },
464         { .path = "/testcase-data/match-node/name4", .data = "G", },
465         { .path = "/testcase-data/match-node/name5", .data = "H", },
466         { .path = "/testcase-data/match-node/name6", .data = "G", },
467         { .path = "/testcase-data/match-node/name7", .data = "I", },
468         { .path = "/testcase-data/match-node/name8", .data = "J", },
469         { .path = "/testcase-data/match-node/name9", .data = "K", },
470 };
471
472 static void __init of_selftest_match_node(void)
473 {
474         struct device_node *np;
475         const struct of_device_id *match;
476         int i;
477
478         for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) {
479                 np = of_find_node_by_path(match_node_tests[i].path);
480                 if (!np) {
481                         selftest(0, "missing testcase node %s\n",
482                                 match_node_tests[i].path);
483                         continue;
484                 }
485
486                 match = of_match_node(match_node_table, np);
487                 if (!match) {
488                         selftest(0, "%s didn't match anything\n",
489                                 match_node_tests[i].path);
490                         continue;
491                 }
492
493                 if (strcmp(match->data, match_node_tests[i].data) != 0) {
494                         selftest(0, "%s got wrong match. expected %s, got %s\n",
495                                 match_node_tests[i].path, match_node_tests[i].data,
496                                 (const char *)match->data);
497                         continue;
498                 }
499                 selftest(1, "passed");
500         }
501 }
502
503 static void __init of_selftest_platform_populate(void)
504 {
505         int irq;
506         struct device_node *np, *child;
507         struct platform_device *pdev;
508         struct of_device_id match[] = {
509                 { .compatible = "test-device", },
510                 {}
511         };
512
513         np = of_find_node_by_path("/testcase-data");
514         of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
515
516         /* Test that a missing irq domain returns -EPROBE_DEFER */
517         np = of_find_node_by_path("/testcase-data/testcase-device1");
518         pdev = of_find_device_by_node(np);
519         selftest(pdev, "device 1 creation failed\n");
520
521         irq = platform_get_irq(pdev, 0);
522         selftest(irq == -EPROBE_DEFER, "device deferred probe failed - %d\n", irq);
523
524         /* Test that a parsing failure does not return -EPROBE_DEFER */
525         np = of_find_node_by_path("/testcase-data/testcase-device2");
526         pdev = of_find_device_by_node(np);
527         selftest(pdev, "device 2 creation failed\n");
528         irq = platform_get_irq(pdev, 0);
529         selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq);
530
531         np = of_find_node_by_path("/testcase-data/platform-tests");
532         if (!np) {
533                 pr_err("No testcase data in device tree\n");
534                 return;
535         }
536
537         for_each_child_of_node(np, child) {
538                 struct device_node *grandchild;
539                 of_platform_populate(child, match, NULL, NULL);
540                 for_each_child_of_node(child, grandchild)
541                         selftest(of_find_device_by_node(grandchild),
542                                  "Could not create device for node '%s'\n",
543                                  grandchild->name);
544         }
545 }
546
547 static int __init of_selftest(void)
548 {
549         struct device_node *np;
550
551         np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
552         if (!np) {
553                 pr_info("No testcase data in device tree; not running tests\n");
554                 return 0;
555         }
556         of_node_put(np);
557
558         pr_info("start of selftest - you will see error messages\n");
559         of_selftest_find_node_by_name();
560         of_selftest_dynamic();
561         of_selftest_parse_phandle_with_args();
562         of_selftest_property_match_string();
563         of_selftest_property_copy();
564         of_selftest_parse_interrupts();
565         of_selftest_parse_interrupts_extended();
566         of_selftest_match_node();
567         of_selftest_platform_populate();
568         pr_info("end of selftest - %i passed, %i failed\n",
569                 selftest_results.passed, selftest_results.failed);
570         return 0;
571 }
572 late_initcall(of_selftest);