diff options
author | Simon Glass <sjg@chromium.org> | 2014-02-26 15:59:21 -0700 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2014-03-04 12:15:29 -0500 |
commit | 2e7d35d2a60339cfa54e26a07326bc75e1060bb3 (patch) | |
tree | 0c49d6f7fb9bdaf9cb2b553e6cbd839c7c837ed5 /test/dm/test-fdt.c | |
parent | 1ce60176799ae04d508b14e9caa7f3bd3a170f0f (diff) | |
download | u-boot-imx-2e7d35d2a60339cfa54e26a07326bc75e1060bb3.zip u-boot-imx-2e7d35d2a60339cfa54e26a07326bc75e1060bb3.tar.gz u-boot-imx-2e7d35d2a60339cfa54e26a07326bc75e1060bb3.tar.bz2 |
dm: Add basic tests
Add some tests of driver model functionality. Coverage includes:
- basic init
- binding of drivers to devices using platform_data
- automatic probing of devices when referenced
- availability of platform data to devices
- lifecycle from bind to probe to remove to unbind
- renumbering within a uclass when devices are probed/removed
- calling driver-defined operations
- deactivation of drivers when removed
- memory leak across creation and destruction of drivers/uclasses
- uclass init/destroy methods
- automatic probe/remove of children/parents when needed
This function is enabled for sandbox, using CONFIG_DM_TEST.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'test/dm/test-fdt.c')
-rw-r--r-- | test/dm/test-fdt.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c new file mode 100644 index 0000000..e1d982f --- /dev/null +++ b/test/dm/test-fdt.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <malloc.h> +#include <asm/io.h> +#include <dm/test.h> +#include <dm/root.h> +#include <dm/ut.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int testfdt_drv_ping(struct device *dev, int pingval, int *pingret) +{ + const struct dm_test_pdata *pdata = dev->platdata; + struct dm_test_priv *priv = dev_get_priv(dev); + + *pingret = pingval + pdata->ping_add; + priv->ping_total += *pingret; + + return 0; +} + +static const struct test_ops test_ops = { + .ping = testfdt_drv_ping, +}; + +static int testfdt_ofdata_to_platdata(struct device *dev) +{ + struct dm_test_pdata *pdata = dev_get_platdata(dev); + + pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "ping-add", -1); + pdata->base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); + + return 0; +} + +static int testfdt_drv_probe(struct device *dev) +{ + struct dm_test_priv *priv = dev_get_priv(dev); + + priv->ping_total += DM_TEST_START_TOTAL; + + return 0; +} + +static const struct device_id testfdt_ids[] = { + { + .compatible = "denx,u-boot-fdt-test", + .data = DM_TEST_TYPE_FIRST }, + { + .compatible = "google,another-fdt-test", + .data = DM_TEST_TYPE_SECOND }, + { } +}; + +U_BOOT_DRIVER(testfdt_drv) = { + .name = "testfdt_drv", + .of_match = testfdt_ids, + .id = UCLASS_TEST_FDT, + .ofdata_to_platdata = testfdt_ofdata_to_platdata, + .probe = testfdt_drv_probe, + .ops = &test_ops, + .priv_auto_alloc_size = sizeof(struct dm_test_priv), + .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), +}; + +/* From here is the testfdt uclass code */ +int testfdt_ping(struct device *dev, int pingval, int *pingret) +{ + const struct test_ops *ops = device_get_ops(dev); + + if (!ops->ping) + return -ENOSYS; + + return ops->ping(dev, pingval, pingret); +} + +UCLASS_DRIVER(testfdt) = { + .name = "testfdt", + .id = UCLASS_TEST_FDT, +}; + +/* Test that FDT-based binding works correctly */ +static int dm_test_fdt(struct dm_test_state *dms) +{ + const int num_drivers = 3; + struct device *dev; + struct uclass *uc; + int ret; + int i; + + ret = dm_scan_fdt(gd->fdt_blob); + ut_assert(!ret); + + ret = uclass_get(UCLASS_TEST_FDT, &uc); + ut_assert(!ret); + + /* These are num_drivers compatible root-level device tree nodes */ + ut_asserteq(num_drivers, list_count_items(&uc->dev_head)); + + /* Each should have no platdata / priv */ + for (i = 0; i < num_drivers; i++) { + ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev); + ut_assert(!ret); + ut_assert(!dev_get_priv(dev)); + ut_assert(!dev->platdata); + } + + /* + * Now check that the ping adds are what we expect. This is using the + * ping-add property in each node. + */ + for (i = 0; i < num_drivers; i++) { + uint32_t base; + + ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev); + ut_assert(!ret); + + /* + * Get the 'reg' property, which tells us what the ping add + * should be. We don't use the platdata because we want + * to test the code that sets that up (testfdt_drv_probe()). + */ + base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); + debug("dev=%d, base=%d: %s\n", i, base, + fdt_get_name(gd->fdt_blob, dev->of_offset, NULL)); + + ut_assert(!dm_check_operations(dms, dev, base, + dev_get_priv(dev))); + } + + return 0; +} +DM_TEST(dm_test_fdt, 0); |