Beispiel #1
0
/**
 * 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;
}
Beispiel #2
0
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;
}