Home | History | Annotate | Download | only in dm
      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);
    506