in imx/imx-scu.c [260:343]
static int imx_scu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct imx_sc_ipc *sc_ipc;
struct imx_sc_chan *sc_chan;
struct mbox_client *cl;
char *chan_name;
struct of_phandle_args args;
int num_channel;
int ret;
int i;
sc_ipc = devm_kzalloc(dev, sizeof(*sc_ipc), GFP_KERNEL);
if (!sc_ipc)
return -ENOMEM;
ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
"#mbox-cells", 0, &args);
if (ret)
return ret;
sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
for (i = 0; i < num_channel; i++) {
if (i < num_channel / 2)
chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
else
chan_name = kasprintf(GFP_KERNEL, "rx%d",
i - num_channel / 2);
if (!chan_name)
return -ENOMEM;
sc_chan = &sc_ipc->chans[i];
cl = &sc_chan->cl;
cl->dev = dev;
cl->tx_block = false;
cl->knows_txdone = true;
cl->rx_callback = imx_scu_rx_callback;
if (!sc_ipc->fast_ipc) {
/* Initial tx_done completion as "done" */
cl->tx_done = imx_scu_tx_done;
init_completion(&sc_chan->tx_done);
complete(&sc_chan->tx_done);
}
sc_chan->sc_ipc = sc_ipc;
sc_chan->idx = i % (num_channel / 2);
sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
if (IS_ERR(sc_chan->ch)) {
ret = PTR_ERR(sc_chan->ch);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to request mbox chan %s ret %d\n",
chan_name, ret);
kfree(chan_name);
return ret;
}
dev_dbg(dev, "request mbox chan %s\n", chan_name);
/* chan_name is not used anymore by framework */
kfree(chan_name);
}
sc_ipc->dev = dev;
mutex_init(&sc_ipc->lock);
init_completion(&sc_ipc->done);
imx_sc_ipc_handle = sc_ipc;
ret = imx_scu_soc_init(dev);
if (ret)
dev_warn(dev, "failed to initialize SoC info: %d\n", ret);
ret = imx_scu_enable_general_irq_channel(dev);
if (ret)
dev_warn(dev,
"failed to enable general irq channel: %d\n", ret);
dev_info(dev, "NXP i.MX SCU Initialized\n");
return devm_of_platform_populate(dev);
}