in ti-msgmgr.c [346:398]
static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data)
{
struct device *dev = chan->mbox->dev;
struct ti_msgmgr_inst *inst = dev_get_drvdata(dev);
const struct ti_msgmgr_desc *desc;
struct ti_queue_inst *qinst = chan->con_priv;
int num_words, trail_bytes;
struct ti_msgmgr_message *message = data;
void __iomem *data_reg;
u32 *word_data;
if (WARN_ON(!inst)) {
dev_err(dev, "no platform drv data??\n");
return -EINVAL;
}
desc = inst->desc;
if (ti_msgmgr_queue_is_error(desc, qinst)) {
dev_err(dev, "Error on channel %s\n", qinst->name);
return false;
}
if (desc->max_message_size < message->len) {
dev_err(dev, "Queue %s message length %zu > max %d\n",
qinst->name, message->len, desc->max_message_size);
return -EINVAL;
}
/* NOTE: Constraints similar to rx path exists here as well */
for (data_reg = qinst->queue_buff_start,
num_words = message->len / sizeof(u32),
word_data = (u32 *)message->buf;
num_words; num_words--, data_reg += sizeof(u32), word_data++)
writel(*word_data, data_reg);
trail_bytes = message->len % sizeof(u32);
if (trail_bytes) {
u32 data_trail = *word_data;
/* Ensure all unused data is 0 */
data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes));
writel(data_trail, data_reg);
data_reg++;
}
/*
* 'data_reg' indicates next register to write. If we did not already
* write on tx complete reg(last reg), we must do so for transmit
*/
if (data_reg <= qinst->queue_buff_end)
writel(0, qinst->queue_buff_end);
return 0;
}