static int st_rproc_probe()

in st_remoteproc.c [338:446]


static int st_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct of_device_id *match;
	struct st_rproc *ddata;
	struct device_node *np = dev->of_node;
	struct rproc *rproc;
	struct mbox_chan *chan;
	int enabled;
	int ret, i;

	match = of_match_device(st_rproc_match, dev);
	if (!match || !match->data) {
		dev_err(dev, "No device match found\n");
		return -ENODEV;
	}

	rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
	if (!rproc)
		return -ENOMEM;

	rproc->has_iommu = false;
	ddata = rproc->priv;
	ddata->config = (struct st_rproc_config *)match->data;

	platform_set_drvdata(pdev, rproc);

	ret = st_rproc_parse_dt(pdev);
	if (ret)
		goto free_rproc;

	enabled = st_rproc_state(pdev);
	if (enabled < 0) {
		ret = enabled;
		goto free_clk;
	}

	if (enabled) {
		atomic_inc(&rproc->power);
		rproc->state = RPROC_RUNNING;
	} else {
		clk_set_rate(ddata->clk, ddata->clk_rate);
	}

	if (of_get_property(np, "mbox-names", NULL)) {
		ddata->mbox_client_vq0.dev		= dev;
		ddata->mbox_client_vq0.tx_done		= NULL;
		ddata->mbox_client_vq0.tx_block	= false;
		ddata->mbox_client_vq0.knows_txdone	= false;
		ddata->mbox_client_vq0.rx_callback	= st_rproc_mbox_callback_vq0;

		ddata->mbox_client_vq1.dev		= dev;
		ddata->mbox_client_vq1.tx_done		= NULL;
		ddata->mbox_client_vq1.tx_block	= false;
		ddata->mbox_client_vq1.knows_txdone	= false;
		ddata->mbox_client_vq1.rx_callback	= st_rproc_mbox_callback_vq1;

		/*
		 * To control a co-processor without IPC mechanism.
		 * This driver can be used without mbox and rpmsg.
		 */
		chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx");
		if (IS_ERR(chan)) {
			dev_err(&rproc->dev, "failed to request mbox chan 0\n");
			ret = PTR_ERR(chan);
			goto free_clk;
		}
		ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan;

		chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx");
		if (IS_ERR(chan)) {
			dev_err(&rproc->dev, "failed to request mbox chan 0\n");
			ret = PTR_ERR(chan);
			goto free_mbox;
		}
		ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan;

		chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx");
		if (IS_ERR(chan)) {
			dev_err(&rproc->dev, "failed to request mbox chan 1\n");
			ret = PTR_ERR(chan);
			goto free_mbox;
		}
		ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan;

		chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx");
		if (IS_ERR(chan)) {
			dev_err(&rproc->dev, "failed to request mbox chan 1\n");
			ret = PTR_ERR(chan);
			goto free_mbox;
		}
		ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan;
	}

	ret = rproc_add(rproc);
	if (ret)
		goto free_mbox;

	return 0;

free_mbox:
	for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
		mbox_free_channel(ddata->mbox_chan[i]);
free_clk:
	clk_unprepare(ddata->clk);
free_rproc:
	rproc_free(rproc);
	return ret;
}