/* Test that we can iterate through children */ static int dm_test_bus_children_iterators(struct unit_test_state *uts) { struct udevice *bus, *dev, *child; /* Walk through the children one by one */ ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); ut_assertok(device_find_first_child(bus, &dev)); ut_asserteq_str("c-test@5", dev->name); ut_assertok(device_find_next_child(&dev)); ut_asserteq_str("c-test@0", dev->name); ut_assertok(device_find_next_child(&dev)); ut_asserteq_str("c-test@1", dev->name); ut_assertok(device_find_next_child(&dev)); ut_asserteq_ptr(dev, NULL); /* Move to the next child without using device_find_first_child() */ ut_assertok(device_find_child_by_seq(bus, 5, true, &dev)); ut_asserteq_str("c-test@5", dev->name); ut_assertok(device_find_next_child(&dev)); ut_asserteq_str("c-test@0", dev->name); /* Try a device with no children */ ut_assertok(device_find_first_child(dev, &child)); ut_asserteq_ptr(child, NULL); return 0; }
/* * Test that the bus' uclass' child_pre_probe() is called before the * device's probe() method */ static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) { struct udevice *bus, *dev; int child_count; /* * See testfdt_drv_probe() which effectively checks that the uclass * flag is set before that method is called */ ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); for (device_find_first_child(bus, &dev), child_count = 0; dev; device_find_next_child(&dev)) { struct dm_test_priv *priv = dev_get_priv(dev); /* Check that things happened in the right order */ ut_asserteq_ptr(NULL, priv); ut_assertok(device_probe(dev)); priv = dev_get_priv(dev); ut_assert(priv != NULL); ut_asserteq(1, priv->uclass_flag); ut_asserteq(1, priv->uclass_total); child_count++; } ut_asserteq(3, child_count); return 0; }
static int qemu_cpu_fixup(void) { int ret; int cpu_num; int cpu_online; struct udevice *dev, *pdev; struct cpu_platdata *plat; char *cpu; /* first we need to find '/cpus' */ for (device_find_first_child(dm_root(), &pdev); pdev; device_find_next_child(&pdev)) { if (!strcmp(pdev->name, "cpus")) break; } if (!pdev) { printf("unable to find cpus device\n"); return -ENODEV; } /* calculate cpus that are already bound */ cpu_num = 0; for (uclass_find_first_device(UCLASS_CPU, &dev); dev; uclass_find_next_device(&dev)) { cpu_num++; } /* get actual cpu number */ cpu_online = qemu_fwcfg_online_cpus(); if (cpu_online < 0) { printf("unable to get online cpu number: %d\n", cpu_online); return cpu_online; } /* bind addtional cpus */ dev = NULL; for (; cpu_num < cpu_online; cpu_num++) { /* * allocate device name here as device_bind_driver() does * not copy device name, 8 bytes are enough for * sizeof("cpu@") + 3 digits cpu number + '\0' */ cpu = malloc(8); if (!cpu) { printf("unable to allocate device name\n"); return -ENOMEM; } sprintf(cpu, "cpu@%d", cpu_num); ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev); if (ret) { printf("binding cpu@%d failed: %d\n", cpu_num, ret); return ret; } plat = dev_get_parent_platdata(dev); plat->cpu_id = cpu_num; } return 0; }
int i2c_get_chip(struct udevice *bus, uint chip_addr, struct udevice **devp) { struct udevice *dev; debug("%s: Searching bus '%s' for address %02x: ", __func__, bus->name, chip_addr); for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { struct dm_i2c_chip store; struct dm_i2c_chip *chip = dev_get_parentdata(dev); int ret; if (!chip) { chip = &store; i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, chip); } if (chip->chip_addr == chip_addr) { ret = device_probe(dev); debug("found, ret=%d\n", ret); if (ret) return ret; *devp = dev; return 0; } } debug("not found\n"); return i2c_bind_driver(bus, chip_addr, devp); }
/* Test if bus childs got probed propperly*/ static int dm_test_spmi_probe(struct unit_test_state *uts) { const char *name = "spmi@0"; struct udevice *bus, *dev; ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus)); /* Check bus name */ ut_asserteq_str(name, bus->name); /* Check that it has some devices */ ut_asserteq(device_has_children(bus), true); ut_assertok(device_find_first_child(bus, &dev)); /* There should be at least one child */ ut_assertnonnull(dev); /* Check that only PMICs are connected to the bus */ while (dev) { ut_asserteq(device_get_uclass_id(dev), UCLASS_PMIC); device_find_next_child(&dev); } return 0; }
int axi_sandbox_get_emul(struct udevice *bus, ulong address, enum axi_size_t size, struct udevice **emulp) { struct udevice *dev; u32 reg[2]; uint offset; switch (size) { case AXI_SIZE_8: offset = 1; break; case AXI_SIZE_16: offset = 2; break; case AXI_SIZE_32: offset = 4; break; default: debug("%s: Unknown AXI transfer size '%d'", bus->name, size); offset = 0; } /* * Note: device_find_* don't activate the devices; they're activated * as-needed below. */ for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { int ret; ret = dev_read_u32_array(dev, "reg", reg, ARRAY_SIZE(reg)); if (ret) { debug("%s: Could not read 'reg' property of %s\n", bus->name, dev->name); continue; } /* * Does the transfer's address fall into this device's address * space? */ if (address >= reg[0] && address <= reg[0] + reg[1] - offset) { /* If yes, activate it... */ if (device_probe(dev)) { debug("%s: Could not activate %s\n", bus->name, dev->name); return -ENODEV; } /* ...and return it */ *emulp = dev; return 0; } } return -ENODEV; }
int cros_ec_probe(struct udevice *dev) { struct ec_state *ec = dev->priv; struct cros_ec_dev *cdev = dev->uclass_priv; const void *blob = gd->fdt_blob; struct udevice *keyb_dev; int node; int err; memcpy(ec, &s_state, sizeof(*ec)); err = cros_ec_decode_ec_flash(blob, dev_of_offset(dev), &ec->ec_config); if (err) return err; node = -1; for (device_find_first_child(dev, &keyb_dev); keyb_dev; device_find_next_child(&keyb_dev)) { if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) { node = dev_of_offset(keyb_dev); break; } } if (node < 0) { debug("%s: No cros_ec keyboard found\n", __func__); } else if (keyscan_read_fdt_matrix(ec, blob, node)) { debug("%s: Could not read key matrix\n", __func__); return -1; } /* If we loaded EC data, check that the length matches */ if (ec->flash_data && ec->flash_data_len != ec->ec_config.flash.length) { printf("EC data length is %x, expected %x, discarding data\n", ec->flash_data_len, ec->ec_config.flash.length); os_free(ec->flash_data); ec->flash_data = NULL; } /* Otherwise allocate the memory */ if (!ec->flash_data) { ec->flash_data_len = ec->ec_config.flash.length; ec->flash_data = os_malloc(ec->flash_data_len); if (!ec->flash_data) return -ENOMEM; } cdev->dev = dev; g_state = ec; return cros_ec_register(dev); }
int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp) { struct udevice *dev; for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { struct dm_spi_slave_platdata *plat; plat = dev_get_parent_platdata(dev); debug("%s: plat=%p, cs=%d\n", __func__, plat, plat->cs); if (plat->cs == cs) { *devp = dev; return 0; } } return -ENODEV; }
int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) { struct udevice *child; int ret; ret = pinctrl_generic_set_state_subnode(dev, config); if (ret) return ret; for (device_find_first_child(config, &child); child; device_find_next_child(&child)) { ret = pinctrl_generic_set_state_subnode(dev, child); if (ret) return ret; } return 0; }
/* Test that the child post_bind method is called */ static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts) { struct dm_test_parent_platdata *plat; struct udevice *bus, *dev; int child_count; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); for (device_find_first_child(bus, &dev), child_count = 0; dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(2, plat->uclass_bind_flag); child_count++; } ut_asserteq(3, child_count); return 0; }
static void pciinfo(struct udevice *bus, bool short_listing) { struct udevice *dev; pciinfo_header(bus->seq, short_listing); for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) { struct pci_child_platdata *pplat; pplat = dev_get_parent_platdata(dev); if (short_listing) { printf("%02x.%02x.%02x ", bus->seq, PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); pci_header_show_brief(dev); } else { printf("\nFound PCI device %02x.%02x.%02x:\n", bus->seq, PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); pci_header_show(dev); } } }
static int test_bus_parent_platdata(struct unit_test_state *uts) { struct dm_test_parent_platdata *plat; struct udevice *bus, *dev; int child_count; /* Check that the bus has no children */ ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); device_find_first_child(bus, &dev); ut_asserteq_ptr(NULL, dev); ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); for (device_find_first_child(bus, &dev), child_count = 0; dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); /* * Check that it is not affected by the device being * probed/removed */ plat->count++; ut_asserteq(1, plat->count); device_probe(dev); device_remove(dev); ut_asserteq_ptr(plat, dev_get_parent_platdata(dev)); ut_asserteq(1, plat->count); ut_assertok(device_probe(dev)); child_count++; } ut_asserteq(3, child_count); /* Removing the bus should also have no effect (it is still bound) */ device_remove(bus); for (device_find_first_child(bus, &dev), child_count = 0; dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(1, plat->count); child_count++; } ut_asserteq(3, child_count); /* Unbind all the children */ do { device_find_first_child(bus, &dev); if (dev) device_unbind(dev); } while (dev); /* Now the child platdata should be removed and re-added */ device_probe(bus); for (device_find_first_child(bus, &dev), child_count = 0; dev; device_find_next_child(&dev)) { /* Check that platform data is allocated */ plat = dev_get_parent_platdata(dev); ut_assert(plat != NULL); ut_asserteq(0, plat->count); child_count++; } ut_asserteq(3, child_count); return 0; }