static int keystone_rproc_probe()

in keystone_remoteproc.c [361:477]


static int keystone_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct keystone_rproc *ksproc;
	struct rproc *rproc;
	int dsp_id;
	char *fw_name = NULL;
	char *template = "keystone-dsp%d-fw";
	int name_len = 0;
	int ret = 0;

	if (!np) {
		dev_err(dev, "only DT-based devices are supported\n");
		return -ENODEV;
	}

	dsp_id = of_alias_get_id(np, "rproc");
	if (dsp_id < 0) {
		dev_warn(dev, "device does not have an alias id\n");
		return dsp_id;
	}

	/* construct a custom default fw name - subject to change in future */
	name_len = strlen(template); /* assuming a single digit alias */
	fw_name = devm_kzalloc(dev, name_len, GFP_KERNEL);
	if (!fw_name)
		return -ENOMEM;
	snprintf(fw_name, name_len, template, dsp_id);

	rproc = rproc_alloc(dev, dev_name(dev), &keystone_rproc_ops, fw_name,
			    sizeof(*ksproc));
	if (!rproc)
		return -ENOMEM;

	rproc->has_iommu = false;
	ksproc = rproc->priv;
	ksproc->rproc = rproc;
	ksproc->dev = dev;

	ret = keystone_rproc_of_get_dev_syscon(pdev, ksproc);
	if (ret)
		goto free_rproc;

	ksproc->reset = devm_reset_control_get_exclusive(dev, NULL);
	if (IS_ERR(ksproc->reset)) {
		ret = PTR_ERR(ksproc->reset);
		goto free_rproc;
	}

	/* enable clock for accessing DSP internal memories */
	pm_runtime_enable(dev);
	ret = pm_runtime_get_sync(dev);
	if (ret < 0) {
		dev_err(dev, "failed to enable clock, status = %d\n", ret);
		pm_runtime_put_noidle(dev);
		goto disable_rpm;
	}

	ret = keystone_rproc_of_get_memories(pdev, ksproc);
	if (ret)
		goto disable_clk;

	ksproc->irq_ring = platform_get_irq_byname(pdev, "vring");
	if (ksproc->irq_ring < 0) {
		ret = ksproc->irq_ring;
		goto disable_clk;
	}

	ksproc->irq_fault = platform_get_irq_byname(pdev, "exception");
	if (ksproc->irq_fault < 0) {
		ret = ksproc->irq_fault;
		goto disable_clk;
	}

	ksproc->kick_gpio = of_get_named_gpio_flags(np, "kick-gpios", 0, NULL);
	if (ksproc->kick_gpio < 0) {
		ret = ksproc->kick_gpio;
		dev_err(dev, "failed to get gpio for virtio kicks, status = %d\n",
			ret);
		goto disable_clk;
	}

	if (of_reserved_mem_device_init(dev))
		dev_warn(dev, "device does not have specific CMA pool\n");

	/* ensure the DSP is in reset before loading firmware */
	ret = reset_control_status(ksproc->reset);
	if (ret < 0) {
		dev_err(dev, "failed to get reset status, status = %d\n", ret);
		goto release_mem;
	} else if (ret == 0) {
		WARN(1, "device is not in reset\n");
		keystone_rproc_dsp_reset(ksproc);
	}

	ret = rproc_add(rproc);
	if (ret) {
		dev_err(dev, "failed to add register device with remoteproc core, status = %d\n",
			ret);
		goto release_mem;
	}

	platform_set_drvdata(pdev, ksproc);

	return 0;

release_mem:
	of_reserved_mem_device_release(dev);
disable_clk:
	pm_runtime_put_sync(dev);
disable_rpm:
	pm_runtime_disable(dev);
free_rproc:
	rproc_free(rproc);
	return ret;
}