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;
}