| // SPDX-License-Identifier: GPL-2.0+ | |
| /* | |
| * Copyright (c) 2014 Google, Inc | |
| */ | |
| #include <dm.h> | |
| #include <dm/test.h> | |
| #include <asm/global_data.h> | |
| /* Records the last testbus device that was removed */ | |
| static struct udevice *testbus_removed; | |
| struct udevice *testbus_get_clear_removed(void) | |
| { | |
| struct udevice *removed = testbus_removed; | |
| testbus_removed = NULL; | |
| return removed; | |
| } | |
| static int testbus_drv_probe(struct udevice *dev) | |
| { | |
| if (!CONFIG_IS_ENABLED(OF_PLATDATA)) { | |
| int ret; | |
| ret = dm_scan_fdt_dev(dev); | |
| if (ret) | |
| return ret; | |
| } | |
| return 0; | |
| } | |
| static int testbus_child_post_bind(struct udevice *dev) | |
| { | |
| struct dm_test_parent_plat *plat; | |
| plat = dev_get_parent_plat(dev); | |
| plat->bind_flag = 1; | |
| plat->uclass_bind_flag = 2; | |
| return 0; | |
| } | |
| static int testbus_child_pre_probe(struct udevice *dev) | |
| { | |
| struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); | |
| parent_data->flag += TEST_FLAG_CHILD_PROBED; | |
| return 0; | |
| } | |
| static int testbus_child_pre_probe_uclass(struct udevice *dev) | |
| { | |
| struct dm_test_priv *priv = dev_get_priv(dev); | |
| priv->uclass_flag++; | |
| return 0; | |
| } | |
| static int testbus_child_post_probe_uclass(struct udevice *dev) | |
| { | |
| struct dm_test_priv *priv = dev_get_priv(dev); | |
| priv->uclass_postp++; | |
| return 0; | |
| } | |
| static int testbus_child_post_remove(struct udevice *dev) | |
| { | |
| struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); | |
| parent_data->flag += TEST_FLAG_CHILD_REMOVED; | |
| testbus_removed = dev; | |
| return 0; | |
| } | |
| static const struct udevice_id testbus_ids[] = { | |
| { .compatible = "denx,u-boot-test-bus", .data = DM_TEST_TYPE_FIRST }, | |
| { } | |
| }; | |
| U_BOOT_DRIVER(denx_u_boot_test_bus) = { | |
| .name = "testbus_drv", | |
| .of_match = testbus_ids, | |
| .id = UCLASS_TEST_BUS, | |
| .probe = testbus_drv_probe, | |
| .child_post_bind = testbus_child_post_bind, | |
| .priv_auto = sizeof(struct dm_test_priv), | |
| .plat_auto = sizeof(struct dm_test_pdata), | |
| .per_child_auto = sizeof(struct dm_test_parent_data), | |
| .per_child_plat_auto = sizeof(struct dm_test_parent_plat), | |
| .child_pre_probe = testbus_child_pre_probe, | |
| .child_post_remove = testbus_child_post_remove, | |
| DM_HEADER(<test.h>) | |
| }; | |
| UCLASS_DRIVER(testbus) = { | |
| .name = "testbus", | |
| .id = UCLASS_TEST_BUS, | |
| .flags = DM_UC_FLAG_SEQ_ALIAS, | |
| .child_pre_probe = testbus_child_pre_probe_uclass, | |
| .child_post_probe = testbus_child_post_probe_uclass, | |
| .per_device_auto = sizeof(struct dm_test_uclass_priv), | |
| /* Note: this is for dtoc testing as well as tags*/ | |
| .per_device_plat_auto = sizeof(struct dm_test_uclass_plat), | |
| }; | |
| static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret) | |
| { | |
| const struct dm_test_pdata *pdata = dev_get_plat(dev); | |
| 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_of_to_plat(struct udevice *dev) | |
| { | |
| struct dm_test_pdata *pdata = dev_get_plat(dev); | |
| pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), | |
| "ping-add", -1); | |
| pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), | |
| "ping-expect"); | |
| return 0; | |
| } | |
| static int testfdt_drv_probe(struct udevice *dev) | |
| { | |
| struct dm_test_priv *priv = dev_get_priv(dev); | |
| priv->ping_total += DM_TEST_START_TOTAL; | |
| /* | |
| * If this device is on a bus, the uclass_flag will be set before | |
| * calling this function. In the meantime the uclass_postp is | |
| * initlized to a value -1. These are used respectively by | |
| * dm_test_bus_child_pre_probe_uclass() and | |
| * dm_test_bus_child_post_probe_uclass(). | |
| */ | |
| priv->uclass_total += priv->uclass_flag; | |
| priv->uclass_postp = -1; | |
| return 0; | |
| } | |
| static const struct udevice_id testfdt_ids[] = { | |
| { .compatible = "denx,u-boot-fdt-test", .data = DM_TEST_TYPE_FIRST }, | |
| { .compatible = "google,another-fdt-test", .data = DM_TEST_TYPE_SECOND }, | |
| { } | |
| }; | |
| DM_DRIVER_ALIAS(denx_u_boot_fdt_test, google_another_fdt_test) | |
| U_BOOT_DRIVER(denx_u_boot_fdt_test) = { | |
| .name = "testfdt_drv", | |
| .of_match = testfdt_ids, | |
| .id = UCLASS_TEST_FDT, | |
| .of_to_plat = testfdt_of_to_plat, | |
| .probe = testfdt_drv_probe, | |
| .ops = &test_ops, | |
| .priv_auto = sizeof(struct dm_test_priv), | |
| .plat_auto = sizeof(struct dm_test_pdata), | |
| }; | |
| static const struct udevice_id testfdt1_ids[] = { | |
| { .compatible = "denx,u-boot-fdt-test1", .data = DM_TEST_TYPE_FIRST }, | |
| { } | |
| }; | |
| U_BOOT_DRIVER(testfdt1_drv) = { | |
| .name = "testfdt1_drv", | |
| .of_match = testfdt1_ids, | |
| .id = UCLASS_TEST_FDT, | |
| .of_to_plat = testfdt_of_to_plat, | |
| .probe = testfdt_drv_probe, | |
| .ops = &test_ops, | |
| .priv_auto = sizeof(struct dm_test_priv), | |
| .plat_auto = sizeof(struct dm_test_pdata), | |
| .flags = DM_FLAG_PRE_RELOC, | |
| }; | |
| /* From here is the testfdt uclass code */ | |
| int testfdt_ping(struct udevice *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, | |
| .flags = DM_UC_FLAG_SEQ_ALIAS, | |
| .priv_auto = sizeof(struct dm_test_uc_priv), | |
| }; | |
| static const struct udevice_id testfdtm_ids[] = { | |
| { .compatible = "denx,u-boot-fdtm-test" }, | |
| { } | |
| }; | |
| U_BOOT_DRIVER(testfdtm_drv) = { | |
| .name = "testfdtm_drv", | |
| .of_match = testfdtm_ids, | |
| .id = UCLASS_TEST_FDT_MANUAL, | |
| }; | |
| UCLASS_DRIVER(testfdtm) = { | |
| .name = "testfdtm", | |
| .id = UCLASS_TEST_FDT_MANUAL, | |
| .flags = DM_UC_FLAG_SEQ_ALIAS | DM_UC_FLAG_NO_AUTO_SEQ, | |
| }; |