int usb_emul_control(struct udevice *emul, struct usb_device *udev, unsigned long pipe, void *buffer, int length, struct devrequest *setup) { struct dm_usb_ops *ops = usb_get_emul_ops(emul); struct usb_dev_platdata *plat; int ret; /* We permit getting the descriptor before we are probed */ plat = dev_get_parent_platdata(emul); if (!ops->control) return -ENOSYS; debug("%s: dev=%s\n", __func__, emul->name); if (pipe == usb_rcvctrlpipe(udev, 0)) { switch (setup->request) { case USB_REQ_GET_DESCRIPTOR: { return usb_emul_get_descriptor(plat, setup->value, buffer, length); } default: ret = device_probe(emul); if (ret) return ret; return ops->control(emul, udev, pipe, buffer, length, setup); } } else if (pipe == usb_snddefctrl(udev)) { switch (setup->request) { case USB_REQ_SET_ADDRESS: debug(" ** set address %s %d\n", emul->name, setup->value); plat->devnum = setup->value; return 0; default: debug("requestsend =%x\n", setup->request); break; } } else if (pipe == usb_sndctrlpipe(udev, 0)) { switch (setup->request) { case USB_REQ_SET_CONFIGURATION: plat->configno = setup->value; return 0; default: ret = device_probe(emul); if (ret) return ret; return ops->control(emul, udev, pipe, buffer, length, setup); } } debug("pipe=%lx\n", pipe); return -EIO; }
/* Test that we can bind, probe, remove, unbind a driver */ static int dm_test_lifecycle(struct unit_test_state *uts) { struct dm_test_state *dms = uts->priv; int op_count[DM_TEST_OP_COUNT]; struct udevice *dev, *test_dev; int pingret; int ret; memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, &dev)); ut_assert(dev); ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] == op_count[DM_TEST_OP_BIND] + 1); ut_assert(!dev->priv); /* Probe the device - it should fail allocating private data */ dms->force_fail_alloc = 1; ret = device_probe(dev); ut_assert(ret == -ENOMEM); ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] == op_count[DM_TEST_OP_PROBE] + 1); ut_assert(!dev->priv); /* Try again without the alloc failure */ dms->force_fail_alloc = 0; ut_assertok(device_probe(dev)); ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] == op_count[DM_TEST_OP_PROBE] + 2); ut_assert(dev->priv); /* This should be device 3 in the uclass */ ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); ut_assert(dev == test_dev); /* Try ping */ ut_assertok(test_ping(dev, 100, &pingret)); ut_assert(pingret == 102); /* Now remove device 3 */ ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); ut_assertok(device_remove(dev)); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); ut_assertok(device_unbind(dev)); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); return 0; }
static void serial_find_console_or_panic(void) { #ifdef CONFIG_OF_CONTROL int node; /* Check for a chosen console */ node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); if (node < 0) node = fdtdec_get_alias_node(gd->fdt_blob, "console"); if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) return; /* * If the console is not marked to be bound before relocation, bind * it anyway. */ if (node > 0 && !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { if (!device_probe(cur_dev)) return; cur_dev = NULL; } #endif /* * Failing that, get the device with sequence number 0, or in extremis * just the first serial device we can find. But we insist on having * a console (even if it is silent). */ if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) && (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) panic("No serial driver found"); }
static void vtpci_probe_and_attach_child(struct vtpci_softc *sc) { device_t dev, child; dev = sc->vtpci_dev; child = sc->vtpci_child_dev; if (child == NULL) return; if (device_get_state(child) != DS_NOTPRESENT) return; if (device_probe(child) != 0) return; vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER); if (device_attach(child) != 0) { vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED); vtpci_reset(sc); vtpci_release_child_resources(sc); /* Reset status for future attempt. */ vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_ACK); } else { vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER_OK); VIRTIO_ATTACH_COMPLETED(child); } }
/* Test that the bus ops are called when a child is probed/removed */ static int dm_test_bus_parent_ops(struct dm_test_state *dms) { struct dm_test_parent_data *parent_data; struct udevice *bus, *dev; struct uclass *uc; test_state = dms; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); ut_assertok(device_probe(dev)); parent_data = dev_get_parentdata(dev); ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); } uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; parent_data = dev_get_parentdata(dev); ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); ut_assertok(device_remove(dev)); ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); ut_asserteq_ptr(dms->removed, dev); } test_state = NULL; return 0; }
int __weak soc_clk_dump(void) { #if defined(CONFIG_DM) && defined(CONFIG_CLK) struct udevice *dev; struct uclass *uc; struct clk clk; int ret; /* Device addresses start at 1 */ ret = uclass_get(UCLASS_CLK, &uc); if (ret) return ret; uclass_foreach_dev(dev, uc) { memset(&clk, 0, sizeof(clk)); ret = device_probe(dev); if (ret) { printf("%-30.30s : ? Hz\n", dev->name); continue; } ret = clk_request(dev, &clk); if (ret) { printf("%-30.30s : ? Hz\n", dev->name); continue; } printf("%-30.30s : %lu Hz\n", dev->name, clk_get_rate(&clk)); clk_free(&clk); }
/* * 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; }
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); }
static int syscon_probe_by_ofnode(ofnode node, struct udevice **devp) { struct udevice *dev, *parent; int ret; /* found node with "syscon" compatible, not bounded to SYSCON UCLASS */ if (!ofnode_device_is_compatible(node, "syscon")) { dev_dbg(dev, "invalid compatible for syscon device\n"); return -EINVAL; } /* bound to driver with same ofnode or to root if not found */ if (device_find_global_by_ofnode(node, &parent)) parent = dm_root(); /* force bound to syscon class */ ret = device_bind_driver_to_node(parent, "syscon", ofnode_get_name(node), node, &dev); if (ret) { dev_dbg(dev, "unable to bound syscon device\n"); return ret; } ret = device_probe(dev); if (ret) { dev_dbg(dev, "unable to probe syscon device\n"); return ret; } *devp = dev; return 0; }
int dm_init(void) { int ret; if (gd->dm_root) { dm_warn("Virtual root driver already exists!\n"); return -EINVAL; } INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); #if defined(CONFIG_NEEDS_MANUAL_RELOC) fix_drivers(); fix_uclass(); #endif ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); if (ret) return ret; #if CONFIG_IS_ENABLED(OF_CONTROL) DM_ROOT_NON_CONST->of_offset = 0; #endif ret = device_probe(DM_ROOT_NON_CONST); if (ret) return ret; return 0; }
/* * Find the udevice that either has the name passed in as devname or has an * alias named devname. */ struct udevice *eth_get_dev_by_name(const char *devname) { int seq = -1; char *endp = NULL; const char *startp = NULL; struct udevice *it; struct uclass *uc; int len = strlen("eth"); /* Must be longer than 3 to be an alias */ if (!strncmp(devname, "eth", len) && strlen(devname) > len) { startp = devname + len; seq = simple_strtoul(startp, &endp, 10); } uclass_get(UCLASS_ETH, &uc); uclass_foreach_dev(it, uc) { /* * We need the seq to be valid, so try to probe it. * If the probe fails, the seq will not match since it will be * -1 instead of what we are looking for. * We don't care about errors from probe here. Either they won't * match an alias or it will match a literal name and we'll pick * up the error when we try to probe again in eth_set_dev(). */ if (device_probe(it)) continue; /* Check for the name or the sequence number to match */ if (strcmp(it->name, devname) == 0 || (endp > startp && it->seq == seq)) return it; } return NULL; }
/* Test that the bus can store data about each child */ static int test_bus_parent_data(struct unit_test_state *uts) { struct dm_test_parent_data *parent_data; struct udevice *bus, *dev; struct uclass *uc; int value; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); /* Check that parent data is allocated */ ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_assertok(device_get_child_by_seq(bus, 0, &dev)); parent_data = dev_get_parent_priv(dev); ut_assert(NULL != parent_data); /* Check that it starts at 0 and goes away when device is removed */ parent_data->sum += 5; ut_asserteq(5, parent_data->sum); device_remove(dev); ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); /* Check that we can do this twice */ ut_assertok(device_get_child_by_seq(bus, 0, &dev)); parent_data = dev_get_parent_priv(dev); ut_assert(NULL != parent_data); parent_data->sum += 5; ut_asserteq(5, parent_data->sum); /* Add parent data to all children */ ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); value = 5; uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) { ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); continue; } ut_assertok(device_probe(dev)); parent_data = dev_get_parent_priv(dev); parent_data->sum = value; value += 5; } /* Check it is still there */ value = 5; uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; parent_data = dev_get_parent_priv(dev); ut_asserteq(value, parent_data->sum); value += 5; } return 0; }
/** * connman_device_register: * @device: device structure * * Register device with the system */ int connman_device_register(struct connman_device *device) { __connman_storage_load_device(device); device->offlinemode = __connman_profile_get_offlinemode(); return device_probe(device); }
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; }
/* * Typically this will just store a device pointer. * In case it was not probed, we will attempt to do so. * dev may be NULL to unset the active device. */ void eth_set_dev(struct udevice *dev) { if (dev && !device_active(dev)) { eth_errno = device_probe(dev); if (eth_errno) dev = NULL; } eth_get_uclass_priv()->current = dev; }
int mp_init_cpu(struct udevice *cpu, void *unused) { /* * Multiple APs are brought up simultaneously and they may get the same * seq num in the uclass_resolve_seq() during device_probe(). To avoid * this, set req_seq to the reg number in the device tree in advance. */ cpu->req_seq = fdtdec_get_int(gd->fdt_blob, cpu->of_offset, "reg", -1); return device_probe(cpu); }
/** * _rproc_probe_dev() - iteration helper to probe a rproc device * @dev: device to probe * @uc_pdata: uclass data allocated for the device * @data: unused * * Return: 0 if all ok, else appropriate error value. */ static int _rproc_probe_dev(struct udevice *dev, struct dm_rproc_uclass_pdata *uc_pdata, const void *data) { int ret; ret = device_probe(dev); if (ret) debug("%s: Failed to initialize - %d\n", dev->name, ret); return ret; }
/* * Create a block device for a handle * * @handle handle * @interface block io protocol * @return 0 = success */ static int efi_bl_bind(efi_handle_t handle, void *interface) { struct udevice *bdev, *parent = dm_root(); int ret, devnum; char *name; struct efi_object *obj = efi_search_obj(handle); struct efi_block_io *io = interface; int disks; struct efi_blk_priv *priv; EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io); if (!obj) return -ENOENT; devnum = blk_find_max_devnum(IF_TYPE_EFI); if (devnum == -ENODEV) devnum = 0; else if (devnum < 0) return devnum; name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */ if (!name) return -ENOMEM; sprintf(name, "efiblk#%d", devnum); /* Create driver model udevice for the EFI block io device */ ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI, devnum, io->media->block_size, (lbaint_t)io->media->last_block, &bdev); if (ret) return ret; if (!bdev) return -ENOENT; /* Allocate priv */ ret = device_probe(bdev); if (ret) return ret; EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name); priv = bdev->priv; priv->handle = handle; priv->io = interface; ret = blk_prepare_device(bdev); /* Create handles for the partions of the block device */ disks = efi_bl_bind_partitions(handle, bdev); EFI_PRINT("Found %d partitions\n", disks); return 0; }
int usb_emul_bulk(struct udevice *emul, struct usb_device *udev, unsigned long pipe, void *buffer, int length) { struct dm_usb_ops *ops = usb_get_emul_ops(emul); int ret; /* We permit getting the descriptor before we are probed */ if (!ops->bulk) return -ENOSYS; debug("%s: dev=%s\n", __func__, emul->name); ret = device_probe(emul); if (ret) return ret; return ops->bulk(emul, udev, pipe, buffer, length); }
int mp_init_cpu(struct udevice *cpu, void *unused) { struct cpu_platdata *plat = dev_get_parent_platdata(cpu); /* * Multiple APs are brought up simultaneously and they may get the same * seq num in the uclass_resolve_seq() during device_probe(). To avoid * this, set req_seq to the reg number in the device tree in advance. */ cpu->req_seq = fdtdec_get_int(gd->fdt_blob, dev_of_offset(cpu), "reg", -1); plat->ucode_version = microcode_read_rev(); plat->device_id = gd->arch.x86_device; return device_probe(cpu); }
static void serial_find_console_or_panic(void) { struct udevice *dev; #ifdef CONFIG_OF_CONTROL int node; /* Check for a chosen console */ node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); if (node < 0) node = fdt_path_offset(gd->fdt_blob, "console"); if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) { gd->cur_serial_dev = dev; return; } /* * If the console is not marked to be bound before relocation, bind * it anyway. */ if (node > 0 && !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) { if (!device_probe(dev)) { gd->cur_serial_dev = dev; return; } } #endif /* * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!). * * Failing that, get the device with sequence number 0, or in extremis * just the first serial device we can find. But we insist on having * a console (even if it is silent). */ #ifdef CONFIG_CONS_INDEX #define INDEX (CONFIG_CONS_INDEX - 1) #else #define INDEX 0 #endif if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) && uclass_get_device(UCLASS_SERIAL, INDEX, &dev) && (uclass_first_device(UCLASS_SERIAL, &dev) || !dev)) panic("No serial driver found"); #undef INDEX gd->cur_serial_dev = dev; }
/** * This test case is trying to test the following scenario: * - All ethernet devices are not probed * - "ethaddr" for all ethernet devices are not set * - "ethact" is set to a valid ethernet device name * * With Sandbox default test configuration, all ethernet devices are * probed after power-up, so we have to manually create such scenario: * - Remove all ethernet devices * - Remove all "ethaddr" environment variables * - Set "ethact" to the first ethernet device * * Do a ping test to see if anything goes wrong. */ static int dm_test_eth_act(struct unit_test_state *uts) { struct udevice *dev[DM_TEST_ETH_NUM]; const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000", "sbe5", "eth@10004000"}; const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr", "eth3addr", "eth1addr"}; char ethaddr[DM_TEST_ETH_NUM][18]; int i; memset(ethaddr, '\0', sizeof(ethaddr)); net_ping_ip = string_to_ip("1.1.2.2"); /* Prepare the test scenario */ for (i = 0; i < DM_TEST_ETH_NUM; i++) { ut_assertok(uclass_find_device_by_name(UCLASS_ETH, ethname[i], &dev[i])); ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL)); /* Invalidate MAC address */ strncpy(ethaddr[i], env_get(addrname[i]), 17); /* Must disable access protection for ethaddr before clearing */ env_set(".flags", addrname[i]); env_set(addrname[i], NULL); } /* Set ethact to "eth@10002000" */ env_set("ethact", ethname[0]); /* Segment fault might happen if something is wrong */ ut_asserteq(-ENODEV, net_loop(PING)); for (i = 0; i < DM_TEST_ETH_NUM; i++) { /* Restore the env */ env_set(".flags", addrname[i]); env_set(addrname[i], ethaddr[i]); /* Probe the device again */ ut_assertok(device_probe(dev[i])); } env_set(".flags", NULL); env_set("ethact", NULL); return 0; }
int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp) { struct udevice *dev; struct uclass *uc; int ret; *devp = NULL; ret = uclass_get(UCLASS_SYSCON, &uc); if (ret) return ret; uclass_foreach_dev(dev, uc) { if (dev->driver_data == driver_data) { *devp = dev; return device_probe(dev); } } return -ENODEV; }
static int serial_check_stdout(const void *blob, struct udevice **devp) { int node; /* Check for a chosen console */ node = fdtdec_get_chosen_node(blob, "stdout-path"); if (node < 0) { const char *str, *p, *name; /* * Deal with things like * stdout-path = "serial0:115200n8"; * * We need to look up the alias and then follow it to the * correct node. */ str = fdtdec_get_chosen_prop(blob, "stdout-path"); if (str) { p = strchr(str, ':'); name = fdt_get_alias_namelen(blob, str, p ? p - str : strlen(str)); if (name) node = fdt_path_offset(blob, name); } } if (node < 0) node = fdt_path_offset(blob, "console"); if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp)) return 0; /* * If the console is not marked to be bound before relocation, bind it * anyway. */ if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), devp)) { if (!device_probe(*devp)) return 0; } return -ENODEV; }
int notrace dm_timer_init(void) { __maybe_unused const void *blob = gd->fdt_blob; struct udevice *dev = NULL; int node = -ENOENT; int ret; if (gd->timer) return 0; #if !CONFIG_IS_ENABLED(OF_PLATDATA) /* Check for a chosen timer to be used for tick */ node = fdtdec_get_chosen_node(blob, "tick-timer"); #endif if (node < 0) { /* No chosen timer, trying first available timer */ ret = uclass_first_device_err(UCLASS_TIMER, &dev); if (ret) return ret; } else { if (uclass_get_device_by_of_offset(UCLASS_TIMER, node, &dev)) { /* * If the timer is not marked to be bound before * relocation, bind it anyway. */ if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), &dev)) { ret = device_probe(dev); if (ret) return ret; } } } if (dev) { gd->timer = dev; return 0; } return -ENODEV; }
int scsi_scan_dev(struct udevice *dev, bool verbose) { struct scsi_platdata *uc_plat; /* scsi controller platdata */ int ret; int i; int lun; /* probe SCSI controller driver */ ret = device_probe(dev); if (ret) return ret; /* Get controller platdata */ uc_plat = dev_get_uclass_platdata(dev); for (i = 0; i < uc_plat->max_id; i++) for (lun = 0; lun < uc_plat->max_lun; lun++) do_scsi_scan_one(dev, i, lun, verbose); return 0; }
int dm_init(void) { int ret; if (gd->dm_root) { dm_warn("Virtual root driver already exists!\n"); return -EINVAL; } INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); if (ret) return ret; #ifdef CONFIG_OF_CONTROL DM_ROOT_NON_CONST->of_offset = 0; #endif ret = device_probe(DM_ROOT_NON_CONST); if (ret) return ret; return 0; }
int blk_get_device(int if_type, int devnum, struct udevice **devp) { struct uclass *uc; struct udevice *dev; int ret; ret = uclass_get(UCLASS_BLK, &uc); if (ret) return ret; uclass_foreach_dev(dev, uc) { struct blk_desc *desc = dev_get_uclass_platdata(dev); debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, if_type, devnum, dev->name, desc->if_type, desc->devnum); if (desc->if_type == if_type && desc->devnum == devnum) { *devp = dev; return device_probe(dev); } } return -ENODEV; }
static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len, struct udevice **devp) { struct dm_i2c_chip *chip; char name[30], *str; struct udevice *dev; int ret; snprintf(name, sizeof(name), "generic_%x", chip_addr); str = strdup(name); if (!str) return -ENOMEM; ret = device_bind_driver(bus, "i2c_generic_chip_drv", str, &dev); debug("%s: device_bind_driver: ret=%d\n", __func__, ret); if (ret) goto err_bind; /* Tell the device what we know about it */ chip = dev_get_parent_platdata(dev); chip->chip_addr = chip_addr; chip->offset_len = offset_len; ret = device_probe(dev); debug("%s: device_probe: ret=%d\n", __func__, ret); if (ret) goto err_probe; *devp = dev; return 0; err_probe: /* * If the device failed to probe, unbind it. There is nothing there * on the bus so we don't want to leave it lying around */ device_unbind(dev); err_bind: free(str); return ret; }
static int dm_test_children(struct unit_test_state *uts) { struct dm_test_state *dms = uts->priv; struct udevice *top[NODE_COUNT]; struct udevice *child[NODE_COUNT]; struct udevice *grandchild[NODE_COUNT]; struct udevice *dev; int total; int ret; int i; /* We don't care about the numbering for this test */ dms->skip_post_probe = 1; ut_assert(NODE_COUNT > 5); /* First create 10 top-level children */ ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top)); /* Now a few have their own children */ ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); ut_assertok(create_children(uts, top[5], NODE_COUNT, 5, child)); /* And grandchildren */ for (i = 0; i < NODE_COUNT; i++) ut_assertok(create_children(uts, child[i], NODE_COUNT, 50 * i, i == 2 ? grandchild : NULL)); /* Check total number of devices */ total = NODE_COUNT * (3 + NODE_COUNT); ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]); /* Try probing one of the grandchildren */ ut_assertok(uclass_get_device(UCLASS_TEST, NODE_COUNT * 3 + 2 * NODE_COUNT, &dev)); ut_asserteq_ptr(grandchild[0], dev); /* * This should have probed the child and top node also, for a total * of 3 nodes. */ ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PROBE]); /* Probe the other grandchildren */ for (i = 1; i < NODE_COUNT; i++) ut_assertok(device_probe(grandchild[i])); ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]); /* Probe everything */ for (ret = uclass_first_device(UCLASS_TEST, &dev); dev; ret = uclass_next_device(&dev)) ; ut_assertok(ret); ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]); /* Remove a top-level child and check that the children are removed */ ut_assertok(device_remove(top[2])); ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_REMOVE]); dm_testdrv_op_count[DM_TEST_OP_REMOVE] = 0; /* Try one with grandchildren */ ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); ut_asserteq_ptr(dev, top[5]); ut_assertok(device_remove(dev)); ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), dm_testdrv_op_count[DM_TEST_OP_REMOVE]); /* Try the same with unbind */ ut_assertok(device_unbind(top[2])); ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); dm_testdrv_op_count[DM_TEST_OP_UNBIND] = 0; /* Try one with grandchildren */ ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); ut_asserteq_ptr(dev, top[6]); ut_assertok(device_unbind(top[5])); ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), dm_testdrv_op_count[DM_TEST_OP_UNBIND]); return 0; }