Merge branch 'master' of git://git.denx.de/u-boot-mips
[platform/kernel/u-boot.git] / test / dm / test-fdt.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 Google, Inc
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <fdtdec.h>
10 #include <malloc.h>
11 #include <asm/io.h>
12 #include <dm/test.h>
13 #include <dm/root.h>
14 #include <dm/device-internal.h>
15 #include <dm/uclass-internal.h>
16 #include <dm/util.h>
17 #include <test/ut.h>
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
22 {
23         const struct dm_test_pdata *pdata = dev->platdata;
24         struct dm_test_priv *priv = dev_get_priv(dev);
25
26         *pingret = pingval + pdata->ping_add;
27         priv->ping_total += *pingret;
28
29         return 0;
30 }
31
32 static const struct test_ops test_ops = {
33         .ping = testfdt_drv_ping,
34 };
35
36 static int testfdt_ofdata_to_platdata(struct udevice *dev)
37 {
38         struct dm_test_pdata *pdata = dev_get_platdata(dev);
39
40         pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
41                                         "ping-add", -1);
42         pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
43                                       "ping-expect");
44
45         return 0;
46 }
47
48 static int testfdt_drv_probe(struct udevice *dev)
49 {
50         struct dm_test_priv *priv = dev_get_priv(dev);
51
52         priv->ping_total += DM_TEST_START_TOTAL;
53
54         /*
55          * If this device is on a bus, the uclass_flag will be set before
56          * calling this function. This is used by
57          * dm_test_bus_child_pre_probe_uclass().
58          */
59         priv->uclass_total += priv->uclass_flag;
60
61         return 0;
62 }
63
64 static const struct udevice_id testfdt_ids[] = {
65         {
66                 .compatible = "denx,u-boot-fdt-test",
67                 .data = DM_TEST_TYPE_FIRST },
68         {
69                 .compatible = "google,another-fdt-test",
70                 .data = DM_TEST_TYPE_SECOND },
71         { }
72 };
73
74 U_BOOT_DRIVER(testfdt_drv) = {
75         .name   = "testfdt_drv",
76         .of_match       = testfdt_ids,
77         .id     = UCLASS_TEST_FDT,
78         .ofdata_to_platdata = testfdt_ofdata_to_platdata,
79         .probe  = testfdt_drv_probe,
80         .ops    = &test_ops,
81         .priv_auto_alloc_size = sizeof(struct dm_test_priv),
82         .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
83 };
84
85 /* From here is the testfdt uclass code */
86 int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
87 {
88         const struct test_ops *ops = device_get_ops(dev);
89
90         if (!ops->ping)
91                 return -ENOSYS;
92
93         return ops->ping(dev, pingval, pingret);
94 }
95
96 UCLASS_DRIVER(testfdt) = {
97         .name           = "testfdt",
98         .id             = UCLASS_TEST_FDT,
99         .flags          = DM_UC_FLAG_SEQ_ALIAS,
100 };
101
102 struct dm_testprobe_pdata {
103         int probe_err;
104 };
105
106 static int testprobe_drv_probe(struct udevice *dev)
107 {
108         struct dm_testprobe_pdata *pdata = dev_get_platdata(dev);
109
110         return pdata->probe_err;
111 }
112
113 static const struct udevice_id testprobe_ids[] = {
114         { .compatible = "denx,u-boot-probe-test" },
115         { }
116 };
117
118 U_BOOT_DRIVER(testprobe_drv) = {
119         .name   = "testprobe_drv",
120         .of_match       = testprobe_ids,
121         .id     = UCLASS_TEST_PROBE,
122         .probe  = testprobe_drv_probe,
123         .platdata_auto_alloc_size       = sizeof(struct dm_testprobe_pdata),
124 };
125
126 UCLASS_DRIVER(testprobe) = {
127         .name           = "testprobe",
128         .id             = UCLASS_TEST_PROBE,
129         .flags          = DM_UC_FLAG_SEQ_ALIAS,
130 };
131
132 int dm_check_devices(struct unit_test_state *uts, int num_devices)
133 {
134         struct udevice *dev;
135         int ret;
136         int i;
137
138         /*
139          * Now check that the ping adds are what we expect. This is using the
140          * ping-add property in each node.
141          */
142         for (i = 0; i < num_devices; i++) {
143                 uint32_t base;
144
145                 ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev);
146                 ut_assert(!ret);
147
148                 /*
149                  * Get the 'ping-expect' property, which tells us what the
150                  * ping add should be. We don't use the platdata because we
151                  * want to test the code that sets that up
152                  * (testfdt_drv_probe()).
153                  */
154                 base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
155                                        "ping-expect");
156                 debug("dev=%d, base=%d: %s\n", i, base,
157                       fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL));
158
159                 ut_assert(!dm_check_operations(uts, dev, base,
160                                                dev_get_priv(dev)));
161         }
162
163         return 0;
164 }
165
166 /* Test that FDT-based binding works correctly */
167 static int dm_test_fdt(struct unit_test_state *uts)
168 {
169         const int num_devices = 7;
170         struct udevice *dev;
171         struct uclass *uc;
172         int ret;
173         int i;
174
175         ret = dm_scan_fdt(gd->fdt_blob, false);
176         ut_assert(!ret);
177
178         ret = uclass_get(UCLASS_TEST_FDT, &uc);
179         ut_assert(!ret);
180
181         /* These are num_devices compatible root-level device tree nodes */
182         ut_asserteq(num_devices, list_count_items(&uc->dev_head));
183
184         /* Each should have platform data but no private data */
185         for (i = 0; i < num_devices; i++) {
186                 ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev);
187                 ut_assert(!ret);
188                 ut_assert(!dev_get_priv(dev));
189                 ut_assert(dev->platdata);
190         }
191
192         ut_assertok(dm_check_devices(uts, num_devices));
193
194         return 0;
195 }
196 DM_TEST(dm_test_fdt, 0);
197
198 static int dm_test_fdt_pre_reloc(struct unit_test_state *uts)
199 {
200         struct uclass *uc;
201         int ret;
202
203         ret = dm_scan_fdt(gd->fdt_blob, true);
204         ut_assert(!ret);
205
206         ret = uclass_get(UCLASS_TEST_FDT, &uc);
207         ut_assert(!ret);
208
209         /* These is only one pre-reloc device */
210         ut_asserteq(1, list_count_items(&uc->dev_head));
211
212         return 0;
213 }
214 DM_TEST(dm_test_fdt_pre_reloc, 0);
215
216 /* Test that sequence numbers are allocated properly */
217 static int dm_test_fdt_uclass_seq(struct unit_test_state *uts)
218 {
219         struct udevice *dev;
220
221         /* A few basic santiy tests */
222         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev));
223         ut_asserteq_str("b-test", dev->name);
224
225         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev));
226         ut_asserteq_str("a-test", dev->name);
227
228         ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5,
229                                                        true, &dev));
230         ut_asserteq_ptr(NULL, dev);
231
232         /* Test aliases */
233         ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev));
234         ut_asserteq_str("e-test", dev->name);
235
236         ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7,
237                                                        true, &dev));
238
239         /*
240          * Note that c-test nodes are not probed since it is not a top-level
241          * node
242          */
243         ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev));
244         ut_asserteq_str("b-test", dev->name);
245
246         /*
247          * d-test wants sequence number 3 also, but it can't have it because
248          * b-test gets it first.
249          */
250         ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev));
251         ut_asserteq_str("d-test", dev->name);
252
253         /* d-test actually gets 0 */
254         ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev));
255         ut_asserteq_str("d-test", dev->name);
256
257         /* initially no one wants seq 1 */
258         ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1,
259                                                       &dev));
260         ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
261         ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev));
262
263         /* But now that it is probed, we can find it */
264         ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev));
265         ut_asserteq_str("f-test", dev->name);
266
267         return 0;
268 }
269 DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
270
271 /* Test that we can find a device by device tree offset */
272 static int dm_test_fdt_offset(struct unit_test_state *uts)
273 {
274         const void *blob = gd->fdt_blob;
275         struct udevice *dev;
276         int node;
277
278         node = fdt_path_offset(blob, "/e-test");
279         ut_assert(node > 0);
280         ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node,
281                                                    &dev));
282         ut_asserteq_str("e-test", dev->name);
283
284         /* This node should not be bound */
285         node = fdt_path_offset(blob, "/junk");
286         ut_assert(node > 0);
287         ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT,
288                                                             node, &dev));
289
290         /* This is not a top level node so should not be probed */
291         node = fdt_path_offset(blob, "/some-bus/c-test@5");
292         ut_assert(node > 0);
293         ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT,
294                                                             node, &dev));
295
296         return 0;
297 }
298 DM_TEST(dm_test_fdt_offset,
299         DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
300
301 /**
302  * Test various error conditions with uclass_first_device() and
303  * uclass_next_device()
304  */
305 static int dm_test_first_next_device(struct unit_test_state *uts)
306 {
307         struct dm_testprobe_pdata *pdata;
308         struct udevice *dev, *parent = NULL;
309         int count;
310         int ret;
311
312         /* There should be 4 devices */
313         for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
314              dev;
315              ret = uclass_next_device(&dev)) {
316                 count++;
317                 parent = dev_get_parent(dev);
318                 }
319         ut_assertok(ret);
320         ut_asserteq(4, count);
321
322         /* Remove them and try again, with an error on the second one */
323         ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 1, &dev));
324         pdata = dev_get_platdata(dev);
325         pdata->probe_err = -ENOMEM;
326         device_remove(parent, DM_REMOVE_NORMAL);
327         ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev));
328         ut_asserteq(-ENOMEM, uclass_next_device(&dev));
329         ut_asserteq_ptr(dev, NULL);
330
331         /* Now an error on the first one */
332         ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev));
333         pdata = dev_get_platdata(dev);
334         pdata->probe_err = -ENOENT;
335         device_remove(parent, DM_REMOVE_NORMAL);
336         ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev));
337
338         return 0;
339 }
340 DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
341
342 /**
343  * check_devices() - Check return values and pointers
344  *
345  * This runs through a full sequence of uclass_first_device_check()...
346  * uclass_next_device_check() checking that the return values and devices
347  * are correct.
348  *
349  * @uts: Test state
350  * @devlist: List of expected devices
351  * @mask: Indicates which devices should return an error. Device n should
352  *        return error (-NOENT - n) if bit n is set, or no error (i.e. 0) if
353  *        bit n is clear.
354  */
355 static int check_devices(struct unit_test_state *uts,
356                          struct udevice *devlist[], int mask)
357 {
358         int expected_ret;
359         struct udevice *dev;
360         int i;
361
362         expected_ret = (mask & 1) ? -ENOENT : 0;
363         mask >>= 1;
364         ut_asserteq(expected_ret,
365                     uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
366         for (i = 0; i < 4; i++) {
367                 ut_asserteq_ptr(devlist[i], dev);
368                 expected_ret = (mask & 1) ? -ENOENT - (i + 1) : 0;
369                 mask >>= 1;
370                 ut_asserteq(expected_ret, uclass_next_device_check(&dev));
371         }
372         ut_asserteq_ptr(NULL, dev);
373
374         return 0;
375 }
376
377 /* Test uclass_first_device_check() and uclass_next_device_check() */
378 static int dm_test_first_next_ok_device(struct unit_test_state *uts)
379 {
380         struct dm_testprobe_pdata *pdata;
381         struct udevice *dev, *parent = NULL, *devlist[4];
382         int count;
383         int ret;
384
385         /* There should be 4 devices */
386         count = 0;
387         for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev);
388              dev;
389              ret = uclass_next_device_check(&dev)) {
390                 ut_assertok(ret);
391                 devlist[count++] = dev;
392                 parent = dev_get_parent(dev);
393                 }
394         ut_asserteq(4, count);
395         ut_assertok(uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
396         ut_assertok(check_devices(uts, devlist, 0));
397
398         /* Remove them and try again, with an error on the second one */
399         pdata = dev_get_platdata(devlist[1]);
400         pdata->probe_err = -ENOENT - 1;
401         device_remove(parent, DM_REMOVE_NORMAL);
402         ut_assertok(check_devices(uts, devlist, 1 << 1));
403
404         /* Now an error on the first one */
405         pdata = dev_get_platdata(devlist[0]);
406         pdata->probe_err = -ENOENT - 0;
407         device_remove(parent, DM_REMOVE_NORMAL);
408         ut_assertok(check_devices(uts, devlist, 3 << 0));
409
410         /* Now errors on all */
411         pdata = dev_get_platdata(devlist[2]);
412         pdata->probe_err = -ENOENT - 2;
413         pdata = dev_get_platdata(devlist[3]);
414         pdata->probe_err = -ENOENT - 3;
415         device_remove(parent, DM_REMOVE_NORMAL);
416         ut_assertok(check_devices(uts, devlist, 0xf << 0));
417
418         return 0;
419 }
420 DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
421
422 static const struct udevice_id fdt_dummy_ids[] = {
423         { .compatible = "denx,u-boot-fdt-dummy", },
424         { }
425 };
426
427 UCLASS_DRIVER(fdt_dummy) = {
428         .name           = "fdt-dummy",
429         .id             = UCLASS_TEST_DUMMY,
430         .flags          = DM_UC_FLAG_SEQ_ALIAS,
431 };
432
433 U_BOOT_DRIVER(fdt_dummy_drv) = {
434         .name   = "fdt_dummy_drv",
435         .of_match       = fdt_dummy_ids,
436         .id     = UCLASS_TEST_DUMMY,
437 };
438
439 static int dm_test_fdt_translation(struct unit_test_state *uts)
440 {
441         struct udevice *dev;
442
443         /* Some simple translations */
444         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
445         ut_asserteq_str("dev@0,0", dev->name);
446         ut_asserteq(0x8000, dev_read_addr(dev));
447
448         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 1, true, &dev));
449         ut_asserteq_str("dev@1,100", dev->name);
450         ut_asserteq(0x9000, dev_read_addr(dev));
451
452         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 2, true, &dev));
453         ut_asserteq_str("dev@2,200", dev->name);
454         ut_asserteq(0xA000, dev_read_addr(dev));
455
456         /* No translation for busses with #size-cells == 0 */
457         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 3, true, &dev));
458         ut_asserteq_str("dev@42", dev->name);
459         ut_asserteq(0x42, dev_read_addr(dev));
460
461         return 0;
462 }
463 DM_TEST(dm_test_fdt_translation, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
464
465 /* Test devfdt_remap_addr_index() */
466 static int dm_test_fdt_remap_addr_flat(struct unit_test_state *uts)
467 {
468         struct udevice *dev;
469         fdt_addr_t addr;
470         void *paddr;
471
472         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
473
474         addr = devfdt_get_addr(dev);
475         ut_asserteq(0x8000, addr);
476
477         paddr = map_physmem(addr, 0, MAP_NOCACHE);
478         ut_assertnonnull(paddr);
479         ut_asserteq_ptr(paddr, devfdt_remap_addr(dev));
480
481         return 0;
482 }
483 DM_TEST(dm_test_fdt_remap_addr_flat,
484         DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
485
486 /* Test dev_remap_addr_index() */
487 static int dm_test_fdt_remap_addr_live(struct unit_test_state *uts)
488 {
489         struct udevice *dev;
490         fdt_addr_t addr;
491         void *paddr;
492
493         ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev));
494
495         addr = dev_read_addr(dev);
496         ut_asserteq(0x8000, addr);
497
498         paddr = map_physmem(addr, 0, MAP_NOCACHE);
499         ut_assertnonnull(paddr);
500         ut_asserteq_ptr(paddr, dev_remap_addr(dev));
501
502         return 0;
503 }
504 DM_TEST(dm_test_fdt_remap_addr_live,
505         DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);