/** * of_platform_device_create_pdata - Alloc, initialize and register an of_device * @np: pointer to node to create device for * @bus_id: name to assign device * @platform_data: pointer to populate platform_data pointer with * @parent: Linux device model parent device. * * Returns pointer to created platform device, or NULL if a device was not * registered. Unavailable devices will not get registered. */ static struct platform_device *of_platform_device_create_pdata( struct device_node *np, const char *bus_id, void *platform_data, struct device *parent) { struct platform_device *dev; if (!of_device_is_available(np) || of_node_test_and_set_flag(np, OF_POPULATED)) return NULL; dev = of_device_alloc(np, bus_id, parent); if (!dev) goto err_clear_flag; dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data; of_dma_configure(&dev->dev, dev->dev.of_node); of_msi_configure(&dev->dev, dev->dev.of_node); if (of_device_add(dev) != 0) { of_dma_deconfigure(&dev->dev); platform_device_put(dev); goto err_clear_flag; } return dev; err_clear_flag: of_node_clear_flag(np, OF_POPULATED); return NULL; }
static int __init hidma_mgmt_of_populate_channels(struct device_node *np) { struct platform_device *pdev_parent = of_find_device_by_node(np); struct platform_device_info pdevinfo; struct of_phandle_args out_irq; struct device_node *child; struct resource *res; const __be32 *cell; int ret = 0, size, i, num; u64 addr, addr_size; for_each_available_child_of_node(np, child) { struct resource *res_iter; struct platform_device *new_pdev; cell = of_get_property(child, "reg", &size); if (!cell) { ret = -EINVAL; goto out; } size /= sizeof(*cell); num = size / (of_n_addr_cells(child) + of_n_size_cells(child)) + 1; /* allocate a resource array */ res = kcalloc(num, sizeof(*res), GFP_KERNEL); if (!res) { ret = -ENOMEM; goto out; } /* read each reg value */ i = 0; res_iter = res; while (i < size) { addr = of_read_number(&cell[i], of_n_addr_cells(child)); i += of_n_addr_cells(child); addr_size = of_read_number(&cell[i], of_n_size_cells(child)); i += of_n_size_cells(child); res_iter->start = addr; res_iter->end = res_iter->start + addr_size - 1; res_iter->flags = IORESOURCE_MEM; res_iter++; } ret = of_irq_parse_one(child, 0, &out_irq); if (ret) goto out; res_iter->start = irq_create_of_mapping(&out_irq); res_iter->name = "hidma event irq"; res_iter->flags = IORESOURCE_IRQ; memset(&pdevinfo, 0, sizeof(pdevinfo)); pdevinfo.fwnode = &child->fwnode; pdevinfo.parent = pdev_parent ? &pdev_parent->dev : NULL; pdevinfo.name = child->name; pdevinfo.id = object_counter++; pdevinfo.res = res; pdevinfo.num_res = num; pdevinfo.data = NULL; pdevinfo.size_data = 0; pdevinfo.dma_mask = DMA_BIT_MASK(64); new_pdev = platform_device_register_full(&pdevinfo); if (IS_ERR(new_pdev)) { ret = PTR_ERR(new_pdev); goto out; } of_node_get(child); new_pdev->dev.of_node = child; of_dma_configure(&new_pdev->dev, child); /* * It is assumed that calling of_msi_configure is safe on * platforms with or without MSI support. */ of_msi_configure(&new_pdev->dev, child); of_node_put(child); kfree(res); res = NULL; } out: kfree(res); return ret; }