in zynqmp-ipi-mailbox.c [265:307]
static int zynqmp_ipi_send_data(struct mbox_chan *chan, void *data)
{
struct device *dev = chan->mbox->dev;
struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);
struct zynqmp_ipi_mchan *mchan = chan->con_priv;
struct zynqmp_ipi_message *msg = data;
u64 arg0;
struct arm_smccc_res res;
if (WARN_ON(!ipi_mbox)) {
dev_err(dev, "no platform drv data??\n");
return -EINVAL;
}
if (mchan->chan_type == IPI_MB_CHNL_TX) {
/* Send request message */
if (msg && msg->len > mchan->req_buf_size) {
dev_err(dev, "channel %d message length %u > max %lu\n",
mchan->chan_type, (unsigned int)msg->len,
mchan->req_buf_size);
return -EINVAL;
}
if (msg && msg->len)
memcpy_toio(mchan->req_buf, msg->data, msg->len);
/* Kick IPI mailbox to send message */
arg0 = SMC_IPI_MAILBOX_NOTIFY;
zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);
} else {
/* Send response message */
if (msg && msg->len > mchan->resp_buf_size) {
dev_err(dev, "channel %d message length %u > max %lu\n",
mchan->chan_type, (unsigned int)msg->len,
mchan->resp_buf_size);
return -EINVAL;
}
if (msg && msg->len)
memcpy_toio(mchan->resp_buf, msg->data, msg->len);
arg0 = SMC_IPI_MAILBOX_ACK;
zynqmp_ipi_fw_call(ipi_mbox, arg0, IPI_SMC_ACK_EIRQ_MASK,
&res);
}
return 0;
}