static int pru_rproc_probe()

in pru_rproc.c [766:855]


static int pru_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct platform_device *ppdev = to_platform_device(dev->parent);
	struct pru_rproc *pru;
	const char *fw_name;
	struct rproc *rproc = NULL;
	struct resource *res;
	int i, ret;
	const struct pru_private_data *data;
	const char *mem_names[PRU_IOMEM_MAX] = { "iram", "control", "debug" };

	data = of_device_get_match_data(&pdev->dev);
	if (!data)
		return -ENODEV;

	ret = of_property_read_string(np, "firmware-name", &fw_name);
	if (ret) {
		dev_err(dev, "unable to retrieve firmware-name %d\n", ret);
		return ret;
	}

	rproc = devm_rproc_alloc(dev, pdev->name, &pru_rproc_ops, fw_name,
				 sizeof(*pru));
	if (!rproc) {
		dev_err(dev, "rproc_alloc failed\n");
		return -ENOMEM;
	}
	/* use a custom load function to deal with PRU-specific quirks */
	rproc->ops->load = pru_rproc_load_elf_segments;

	/* use a custom parse function to deal with PRU-specific resources */
	rproc->ops->parse_fw = pru_rproc_parse_fw;

	/* error recovery is not supported for PRUs */
	rproc->recovery_disabled = true;

	/*
	 * rproc_add will auto-boot the processor normally, but this is not
	 * desired with PRU client driven boot-flow methodology. A PRU
	 * application/client driver will boot the corresponding PRU
	 * remote-processor as part of its state machine either through the
	 * remoteproc sysfs interface or through the equivalent kernel API.
	 */
	rproc->auto_boot = false;

	pru = rproc->priv;
	pru->dev = dev;
	pru->data = data;
	pru->pruss = platform_get_drvdata(ppdev);
	pru->rproc = rproc;
	pru->fw_name = fw_name;

	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						   mem_names[i]);
		pru->mem_regions[i].va = devm_ioremap_resource(dev, res);
		if (IS_ERR(pru->mem_regions[i].va)) {
			dev_err(dev, "failed to parse and map memory resource %d %s\n",
				i, mem_names[i]);
			ret = PTR_ERR(pru->mem_regions[i].va);
			return ret;
		}
		pru->mem_regions[i].pa = res->start;
		pru->mem_regions[i].size = resource_size(res);

		dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
			mem_names[i], &pru->mem_regions[i].pa,
			pru->mem_regions[i].size, pru->mem_regions[i].va);
	}

	ret = pru_rproc_set_id(pru);
	if (ret < 0)
		return ret;

	platform_set_drvdata(pdev, rproc);

	ret = devm_rproc_add(dev, pru->rproc);
	if (ret) {
		dev_err(dev, "rproc_add failed: %d\n", ret);
		return ret;
	}

	pru_rproc_create_debug_entries(rproc);

	dev_dbg(dev, "PRU rproc node %pOF probed successfully\n", np);

	return 0;
}