Lines Matching +full:mbox +full:- +full:tx

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/arm-smccc.h>
15 #include <linux/mailbox/zynqmp-ipi-message.h>
54 #define IPI_MB_CHNL_TX 0 /* IPI mailbox TX channel */
58 * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel
78 * struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox
84 * @mbox: mailbox Controller
85 * @mchans: array for channels, tx channel and rx channel.
92 struct mbox_controller mbox; member
97 * struct zynqmp_ipi_pdata - Description of z ZynqMP IPI agent platform data.
118 .name = "zynqmp-ipi-mbox",
125 struct zynqmp_ipi_pdata *pdata = ipi_mbox->pdata; in zynqmp_ipi_fw_call()
128 a1 = pdata->local_id; in zynqmp_ipi_fw_call()
129 a2 = ipi_mbox->remote_id; in zynqmp_ipi_fw_call()
130 if (pdata->method == USE_SMC) in zynqmp_ipi_fw_call()
137 * zynqmp_ipi_interrupt - Interrupt handler for IPI notification
142 * Return: -EINVAL if there is no instance
160 for (i = 0; i < pdata->num_mboxes; i++) { in zynqmp_ipi_interrupt()
161 ipi_mbox = &pdata->ipi_mboxes[i]; in zynqmp_ipi_interrupt()
162 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX]; in zynqmp_ipi_interrupt()
163 chan = &ipi_mbox->mbox.chans[IPI_MB_CHNL_RX]; in zynqmp_ipi_interrupt()
167 if (mchan->is_opened) { in zynqmp_ipi_interrupt()
168 msg = mchan->rx_buf; in zynqmp_ipi_interrupt()
169 msg->len = mchan->req_buf_size; in zynqmp_ipi_interrupt()
170 memcpy_fromio(msg->data, mchan->req_buf, in zynqmp_ipi_interrupt()
171 msg->len); in zynqmp_ipi_interrupt()
181 * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.
189 struct device *dev = chan->mbox->dev; in zynqmp_ipi_peek_data()
191 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_peek_data()
205 if (mchan->chan_type == IPI_MB_CHNL_TX) { in zynqmp_ipi_peek_data()
206 /* TX channel, check if the message has been acked in zynqmp_ipi_peek_data()
221 * zynqmp_ipi_last_tx_done - See if the last tx message is sent
225 * Return: 'true' is no pending tx data, 'false' if there are any.
229 struct device *dev = chan->mbox->dev; in zynqmp_ipi_last_tx_done()
231 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_last_tx_done()
241 if (mchan->chan_type == IPI_MB_CHNL_TX) { in zynqmp_ipi_last_tx_done()
243 * by the remote in the TX channel in zynqmp_ipi_last_tx_done()
258 * zynqmp_ipi_send_data - Send data
267 struct device *dev = chan->mbox->dev; in zynqmp_ipi_send_data()
269 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_send_data()
276 return -EINVAL; in zynqmp_ipi_send_data()
279 if (mchan->chan_type == IPI_MB_CHNL_TX) { in zynqmp_ipi_send_data()
281 if (msg && msg->len > mchan->req_buf_size) { in zynqmp_ipi_send_data()
283 mchan->chan_type, (unsigned int)msg->len, in zynqmp_ipi_send_data()
284 mchan->req_buf_size); in zynqmp_ipi_send_data()
285 return -EINVAL; in zynqmp_ipi_send_data()
287 if (msg && msg->len) in zynqmp_ipi_send_data()
288 memcpy_toio(mchan->req_buf, msg->data, msg->len); in zynqmp_ipi_send_data()
294 if (msg && msg->len > mchan->resp_buf_size) { in zynqmp_ipi_send_data()
296 mchan->chan_type, (unsigned int)msg->len, in zynqmp_ipi_send_data()
297 mchan->resp_buf_size); in zynqmp_ipi_send_data()
298 return -EINVAL; in zynqmp_ipi_send_data()
300 if (msg && msg->len) in zynqmp_ipi_send_data()
301 memcpy_toio(mchan->resp_buf, msg->data, msg->len); in zynqmp_ipi_send_data()
310 * zynqmp_ipi_startup - Startup the IPI channel
318 struct device *dev = chan->mbox->dev; in zynqmp_ipi_startup()
320 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_startup()
326 if (mchan->is_opened) in zynqmp_ipi_startup()
330 nchan_type = (mchan->chan_type + 1) % 2; in zynqmp_ipi_startup()
331 if (!ipi_mbox->mchans[nchan_type].is_opened) { in zynqmp_ipi_startup()
344 if (mchan->chan_type == IPI_MB_CHNL_RX) { in zynqmp_ipi_startup()
348 mchan->is_opened = 1; in zynqmp_ipi_startup()
354 * zynqmp_ipi_shutdown - Shutdown the IPI channel
360 struct device *dev = chan->mbox->dev; in zynqmp_ipi_shutdown()
362 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_shutdown()
367 if (!mchan->is_opened) in zynqmp_ipi_shutdown()
371 chan_type = mchan->chan_type; in zynqmp_ipi_shutdown()
378 if (!ipi_mbox->mchans[chan_type].is_opened) { in zynqmp_ipi_shutdown()
383 mchan->is_opened = 0; in zynqmp_ipi_shutdown()
396 * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel
398 * @mbox: mailbox controller pointer
403 static struct mbox_chan *zynqmp_ipi_of_xlate(struct mbox_controller *mbox, in zynqmp_ipi_of_xlate() argument
407 struct device *dev = mbox->dev; in zynqmp_ipi_of_xlate()
410 /* Only supports TX and RX channels */ in zynqmp_ipi_of_xlate()
411 chan_type = p->args[0]; in zynqmp_ipi_of_xlate()
415 return ERR_PTR(-EINVAL); in zynqmp_ipi_of_xlate()
417 chan = &mbox->chans[chan_type]; in zynqmp_ipi_of_xlate()
422 { .compatible = "xlnx,zynqmp-ipi-mailbox" },
428 * zynqmp_ipi_mbox_get_buf_res - Get buffer resource from the IPI dev node
430 * @node: IPI mbox device child node
442 index = of_property_match_string(node, "reg-names", name); in zynqmp_ipi_mbox_get_buf_res()
446 return -EINVAL; in zynqmp_ipi_mbox_get_buf_res()
449 return -ENODEV; in zynqmp_ipi_mbox_get_buf_res()
453 * zynqmp_ipi_mbox_dev_release() - release the existence of a ipi mbox dev
466 * zynqmp_ipi_mbox_probe - probe IPI mailbox resource from device node
478 struct mbox_controller *mbox; in zynqmp_ipi_mbox_probe() local
484 dev = ipi_mbox->pdata->dev; in zynqmp_ipi_mbox_probe()
486 ipi_mbox->dev.parent = dev; in zynqmp_ipi_mbox_probe()
487 ipi_mbox->dev.release = NULL; in zynqmp_ipi_mbox_probe()
488 ipi_mbox->dev.of_node = node; in zynqmp_ipi_mbox_probe()
489 dev_set_name(&ipi_mbox->dev, "%s", of_node_full_name(node)); in zynqmp_ipi_mbox_probe()
490 dev_set_drvdata(&ipi_mbox->dev, ipi_mbox); in zynqmp_ipi_mbox_probe()
491 ipi_mbox->dev.release = zynqmp_ipi_mbox_dev_release; in zynqmp_ipi_mbox_probe()
492 ipi_mbox->dev.driver = &zynqmp_ipi_mbox_driver; in zynqmp_ipi_mbox_probe()
493 ret = device_register(&ipi_mbox->dev); in zynqmp_ipi_mbox_probe()
495 dev_err(dev, "Failed to register ipi mbox dev.\n"); in zynqmp_ipi_mbox_probe()
498 mdev = &ipi_mbox->dev; in zynqmp_ipi_mbox_probe()
500 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX]; in zynqmp_ipi_mbox_probe()
504 mchan->req_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
505 mchan->req_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
506 mchan->req_buf_size); in zynqmp_ipi_mbox_probe()
507 if (!mchan->req_buf) { in zynqmp_ipi_mbox_probe()
509 return -ENOMEM; in zynqmp_ipi_mbox_probe()
511 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
519 mchan->resp_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
520 mchan->resp_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
521 mchan->resp_buf_size); in zynqmp_ipi_mbox_probe()
522 if (!mchan->resp_buf) { in zynqmp_ipi_mbox_probe()
524 return -ENOMEM; in zynqmp_ipi_mbox_probe()
526 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
530 mchan->rx_buf = devm_kzalloc(mdev, in zynqmp_ipi_mbox_probe()
531 mchan->resp_buf_size + in zynqmp_ipi_mbox_probe()
534 if (!mchan->rx_buf) in zynqmp_ipi_mbox_probe()
535 return -ENOMEM; in zynqmp_ipi_mbox_probe()
537 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX]; in zynqmp_ipi_mbox_probe()
541 mchan->req_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
542 mchan->req_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
543 mchan->req_buf_size); in zynqmp_ipi_mbox_probe()
544 if (!mchan->req_buf) { in zynqmp_ipi_mbox_probe()
546 return -ENOMEM; in zynqmp_ipi_mbox_probe()
548 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
556 mchan->resp_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
557 mchan->resp_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
558 mchan->resp_buf_size); in zynqmp_ipi_mbox_probe()
559 if (!mchan->resp_buf) { in zynqmp_ipi_mbox_probe()
561 return -ENOMEM; in zynqmp_ipi_mbox_probe()
563 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
567 mchan->rx_buf = devm_kzalloc(mdev, in zynqmp_ipi_mbox_probe()
568 mchan->resp_buf_size + in zynqmp_ipi_mbox_probe()
571 if (!mchan->rx_buf) in zynqmp_ipi_mbox_probe()
572 return -ENOMEM; in zynqmp_ipi_mbox_probe()
575 ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id); in zynqmp_ipi_mbox_probe()
581 mbox = &ipi_mbox->mbox; in zynqmp_ipi_mbox_probe()
582 mbox->dev = mdev; in zynqmp_ipi_mbox_probe()
583 mbox->ops = &zynqmp_ipi_chan_ops; in zynqmp_ipi_mbox_probe()
584 mbox->num_chans = 2; in zynqmp_ipi_mbox_probe()
585 mbox->txdone_irq = false; in zynqmp_ipi_mbox_probe()
586 mbox->txdone_poll = true; in zynqmp_ipi_mbox_probe()
587 mbox->txpoll_period = 5; in zynqmp_ipi_mbox_probe()
588 mbox->of_xlate = zynqmp_ipi_of_xlate; in zynqmp_ipi_mbox_probe()
591 return -ENOMEM; in zynqmp_ipi_mbox_probe()
592 mbox->chans = chans; in zynqmp_ipi_mbox_probe()
593 chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX]; in zynqmp_ipi_mbox_probe()
594 chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX]; in zynqmp_ipi_mbox_probe()
595 ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX; in zynqmp_ipi_mbox_probe()
596 ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX; in zynqmp_ipi_mbox_probe()
597 ret = devm_mbox_controller_register(mdev, mbox); in zynqmp_ipi_mbox_probe()
603 "Registered ZynqMP IPI mbox with TX/RX channels.\n"); in zynqmp_ipi_mbox_probe()
608 * zynqmp_ipi_free_mboxes - Free IPI mailboxes devices
617 i = pdata->num_mboxes; in zynqmp_ipi_free_mboxes()
618 for (; i >= 0; i--) { in zynqmp_ipi_free_mboxes()
619 ipi_mbox = &pdata->ipi_mboxes[i]; in zynqmp_ipi_free_mboxes()
620 if (ipi_mbox->dev.parent) { in zynqmp_ipi_free_mboxes()
621 mbox_controller_unregister(&ipi_mbox->mbox); in zynqmp_ipi_free_mboxes()
622 device_unregister(&ipi_mbox->dev); in zynqmp_ipi_free_mboxes()
629 struct device *dev = &pdev->dev; in zynqmp_ipi_probe()
630 struct device_node *nc, *np = pdev->dev.of_node; in zynqmp_ipi_probe()
632 struct zynqmp_ipi_mbox *mbox; in zynqmp_ipi_probe() local
633 int num_mboxes, ret = -EINVAL; in zynqmp_ipi_probe()
636 pdata = devm_kzalloc(dev, sizeof(*pdata) + (num_mboxes * sizeof(*mbox)), in zynqmp_ipi_probe()
639 return -ENOMEM; in zynqmp_ipi_probe()
640 pdata->dev = dev; in zynqmp_ipi_probe()
643 ret = of_property_read_u32(np, "xlnx,ipi-id", &pdata->local_id); in zynqmp_ipi_probe()
649 pdata->num_mboxes = num_mboxes; in zynqmp_ipi_probe()
650 pdata->ipi_mboxes = (struct zynqmp_ipi_mbox *) in zynqmp_ipi_probe()
653 mbox = pdata->ipi_mboxes; in zynqmp_ipi_probe()
655 mbox->pdata = pdata; in zynqmp_ipi_probe()
656 ret = zynqmp_ipi_mbox_probe(mbox, nc); in zynqmp_ipi_probe()
660 ret = -EINVAL; in zynqmp_ipi_probe()
663 mbox++; in zynqmp_ipi_probe()
671 pdata->irq = ret; in zynqmp_ipi_probe()
672 ret = devm_request_irq(dev, pdata->irq, zynqmp_ipi_interrupt, in zynqmp_ipi_probe()
676 pdata->irq); in zynqmp_ipi_probe()
702 .name = "zynqmp-ipi",