in zynqmp-ipi-mailbox.c [473:605]
static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,
struct device_node *node)
{
struct zynqmp_ipi_mchan *mchan;
struct mbox_chan *chans;
struct mbox_controller *mbox;
struct resource res;
struct device *dev, *mdev;
const char *name;
int ret;
dev = ipi_mbox->pdata->dev;
/* Initialize dev for IPI mailbox */
ipi_mbox->dev.parent = dev;
ipi_mbox->dev.release = NULL;
ipi_mbox->dev.of_node = node;
dev_set_name(&ipi_mbox->dev, "%s", of_node_full_name(node));
dev_set_drvdata(&ipi_mbox->dev, ipi_mbox);
ipi_mbox->dev.release = zynqmp_ipi_mbox_dev_release;
ipi_mbox->dev.driver = &zynqmp_ipi_mbox_driver;
ret = device_register(&ipi_mbox->dev);
if (ret) {
dev_err(dev, "Failed to register ipi mbox dev.\n");
return ret;
}
mdev = &ipi_mbox->dev;
mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
name = "local_request_region";
ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
if (!ret) {
mchan->req_buf_size = resource_size(&res);
mchan->req_buf = devm_ioremap(mdev, res.start,
mchan->req_buf_size);
if (!mchan->req_buf) {
dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
return -ENOMEM;
}
} else if (ret != -ENODEV) {
dev_err(mdev, "Unmatched resource %s, %d.\n", name, ret);
return ret;
}
name = "remote_response_region";
ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
if (!ret) {
mchan->resp_buf_size = resource_size(&res);
mchan->resp_buf = devm_ioremap(mdev, res.start,
mchan->resp_buf_size);
if (!mchan->resp_buf) {
dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
return -ENOMEM;
}
} else if (ret != -ENODEV) {
dev_err(mdev, "Unmatched resource %s.\n", name);
return ret;
}
mchan->rx_buf = devm_kzalloc(mdev,
mchan->resp_buf_size +
sizeof(struct zynqmp_ipi_message),
GFP_KERNEL);
if (!mchan->rx_buf)
return -ENOMEM;
mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
name = "remote_request_region";
ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
if (!ret) {
mchan->req_buf_size = resource_size(&res);
mchan->req_buf = devm_ioremap(mdev, res.start,
mchan->req_buf_size);
if (!mchan->req_buf) {
dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
return -ENOMEM;
}
} else if (ret != -ENODEV) {
dev_err(mdev, "Unmatched resource %s.\n", name);
return ret;
}
name = "local_response_region";
ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
if (!ret) {
mchan->resp_buf_size = resource_size(&res);
mchan->resp_buf = devm_ioremap(mdev, res.start,
mchan->resp_buf_size);
if (!mchan->resp_buf) {
dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
return -ENOMEM;
}
} else if (ret != -ENODEV) {
dev_err(mdev, "Unmatched resource %s.\n", name);
return ret;
}
mchan->rx_buf = devm_kzalloc(mdev,
mchan->resp_buf_size +
sizeof(struct zynqmp_ipi_message),
GFP_KERNEL);
if (!mchan->rx_buf)
return -ENOMEM;
/* Get the IPI remote agent ID */
ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id);
if (ret < 0) {
dev_err(dev, "No IPI remote ID is specified.\n");
return ret;
}
mbox = &ipi_mbox->mbox;
mbox->dev = mdev;
mbox->ops = &zynqmp_ipi_chan_ops;
mbox->num_chans = 2;
mbox->txdone_irq = false;
mbox->txdone_poll = true;
mbox->txpoll_period = 5;
mbox->of_xlate = zynqmp_ipi_of_xlate;
chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL);
if (!chans)
return -ENOMEM;
mbox->chans = chans;
chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;
ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;
ret = devm_mbox_controller_register(mdev, mbox);
if (ret)
dev_err(mdev,
"Failed to register mbox_controller(%d)\n", ret);
else
dev_info(mdev,
"Registered ZynqMP IPI mbox with TX/RX channels.\n");
return ret;
}