Lines Matching +full:mbox +full:- +full:rx
1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/arm-smccc.h>
17 #include <linux/mailbox/zynqmp-ipi-message.h>
56 #define IPI_MB_CHNL_RX 1 /* IPI mailbox RX channel */
75 * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel
99 * struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox
105 * @mbox: mailbox Controller
106 * @mchans: array for channels, tx channel and rx channel.
113 struct mbox_controller mbox;
119 * struct zynqmp_ipi_pdata - Description of z ZynqMP IPI agent platform data.
144 .name = "zynqmp-ipi-mbox",
151 struct zynqmp_ipi_pdata *pdata = ipi_mbox->pdata;
154 a1 = pdata->local_id;
155 a2 = ipi_mbox->remote_id;
156 if (pdata->method == USE_SMC)
163 * zynqmp_ipi_interrupt - Interrupt handler for IPI notification
168 * Return: -EINVAL if there is no instance
170 * IRQ_HANDLED if the rx interrupt was successfully handled.
186 for (i = 0; i < pdata->num_mboxes; i++) {
187 ipi_mbox = &pdata->ipi_mboxes[i];
188 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
189 chan = &ipi_mbox->mbox.chans[IPI_MB_CHNL_RX];
193 if (mchan->is_opened) {
194 msg = mchan->rx_buf;
196 msg->len = mchan->req_buf_size;
197 memcpy_fromio(msg->data, mchan->req_buf,
198 msg->len);
217 * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.
221 * Return: 'true' if there is pending rx data, 'false' if there is none.
225 struct device *dev = chan->mbox->dev;
227 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
241 if (mchan->chan_type == IPI_MB_CHNL_TX) {
250 /* RX channel, check if there is message arrived. */
257 * zynqmp_ipi_last_tx_done - See if the last tx message is sent
265 struct device *dev = chan->mbox->dev;
267 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
277 if (mchan->chan_type == IPI_MB_CHNL_TX) {
289 /* Always true for the response message in RX channel */
294 * zynqmp_ipi_send_data - Send data
303 struct device *dev = chan->mbox->dev;
305 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
312 return -EINVAL;
315 if (mchan->chan_type == IPI_MB_CHNL_TX) {
317 if (msg && msg->len > mchan->req_buf_size && mchan->req_buf) {
319 mchan->chan_type, (unsigned int)msg->len,
320 mchan->req_buf_size);
321 return -EINVAL;
323 if (msg && msg->len && mchan->req_buf)
324 memcpy_toio(mchan->req_buf, msg->data, msg->len);
330 if (msg && msg->len > mchan->resp_buf_size && mchan->resp_buf) {
332 mchan->chan_type, (unsigned int)msg->len,
333 mchan->resp_buf_size);
334 return -EINVAL;
336 if (msg && msg->len && mchan->resp_buf)
337 memcpy_toio(mchan->resp_buf, msg->data, msg->len);
346 * zynqmp_ipi_startup - Startup the IPI channel
354 struct device *dev = chan->mbox->dev;
356 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
362 if (mchan->is_opened)
366 nchan_type = (mchan->chan_type + 1) % 2;
367 if (!ipi_mbox->mchans[nchan_type].is_opened) {
379 /* If it is RX channel, enable the IPI notification interrupt */
380 if (mchan->chan_type == IPI_MB_CHNL_RX) {
384 mchan->is_opened = 1;
390 * zynqmp_ipi_shutdown - Shutdown the IPI channel
396 struct device *dev = chan->mbox->dev;
398 struct zynqmp_ipi_mchan *mchan = chan->con_priv;
403 if (!mchan->is_opened)
406 /* If it is RX channel, disable notification interrupt */
407 chan_type = mchan->chan_type;
414 if (!ipi_mbox->mchans[chan_type].is_opened) {
419 mchan->is_opened = 0;
432 * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel
434 * @mbox: mailbox controller pointer
439 static struct mbox_chan *zynqmp_ipi_of_xlate(struct mbox_controller *mbox,
443 struct device *dev = mbox->dev;
446 /* Only supports TX and RX channels */
447 chan_type = p->args[0];
451 return ERR_PTR(-EINVAL);
453 chan = &mbox->chans[chan_type];
458 * zynqmp_ipi_mbox_get_buf_res - Get buffer resource from the IPI dev node
460 * @node: IPI mbox device child node
472 index = of_property_match_string(node, "reg-names", name);
476 return -EINVAL;
479 return -ENODEV;
483 * zynqmp_ipi_mbox_dev_release() - release the existence of a ipi mbox dev
496 * zynqmp_ipi_mbox_probe - probe IPI mailbox resource from device node
507 struct mbox_controller *mbox;
511 dev = ipi_mbox->pdata->dev;
513 ipi_mbox->dev.parent = dev;
514 ipi_mbox->dev.release = NULL;
515 ipi_mbox->dev.of_node = node;
516 dev_set_name(&ipi_mbox->dev, "%s", of_node_full_name(node));
517 dev_set_drvdata(&ipi_mbox->dev, ipi_mbox);
518 ipi_mbox->dev.release = zynqmp_ipi_mbox_dev_release;
519 ipi_mbox->dev.driver = &zynqmp_ipi_mbox_driver;
520 ret = device_register(&ipi_mbox->dev);
522 dev_err(dev, "Failed to register ipi mbox dev.\n");
523 put_device(&ipi_mbox->dev);
526 mdev = &ipi_mbox->dev;
529 ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id);
535 ret = ipi_mbox->setup_ipi_fn(ipi_mbox, node);
541 mbox = &ipi_mbox->mbox;
542 mbox->dev = mdev;
543 mbox->ops = &zynqmp_ipi_chan_ops;
544 mbox->num_chans = 2;
545 mbox->txdone_irq = false;
546 mbox->txdone_poll = true;
547 mbox->txpoll_period = tx_poll_period;
548 mbox->of_xlate = zynqmp_ipi_of_xlate;
551 return -ENOMEM;
552 mbox->chans = chans;
553 chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
554 chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
555 ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;
556 ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;
557 ret = devm_mbox_controller_register(mdev, mbox);
563 "Registered ZynqMP IPI mbox with TX/RX channels.\n");
568 * zynqmp_ipi_setup - set up IPI Buffers for classic flow
580 * This will be invoked with compatible string "xlnx,zynqmp-ipi-mailbox".
593 mdev = &ipi_mbox->dev;
595 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
599 mchan->req_buf_size = resource_size(&res);
600 mchan->req_buf = devm_ioremap(mdev, res.start,
601 mchan->req_buf_size);
602 if (!mchan->req_buf) {
604 return -ENOMEM;
606 } else if (ret != -ENODEV) {
614 mchan->resp_buf_size = resource_size(&res);
615 mchan->resp_buf = devm_ioremap(mdev, res.start,
616 mchan->resp_buf_size);
617 if (!mchan->resp_buf) {
619 return -ENOMEM;
621 } else if (ret != -ENODEV) {
625 mchan->rx_buf = devm_kzalloc(mdev,
626 mchan->resp_buf_size +
629 if (!mchan->rx_buf)
630 return -ENOMEM;
632 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
636 mchan->req_buf_size = resource_size(&res);
637 mchan->req_buf = devm_ioremap(mdev, res.start,
638 mchan->req_buf_size);
639 if (!mchan->req_buf) {
641 return -ENOMEM;
643 } else if (ret != -ENODEV) {
651 mchan->resp_buf_size = resource_size(&res);
652 mchan->resp_buf = devm_ioremap(mdev, res.start,
653 mchan->resp_buf_size);
654 if (!mchan->resp_buf) {
656 return -ENOMEM;
658 } else if (ret != -ENODEV) {
662 mchan->rx_buf = devm_kzalloc(mdev,
663 mchan->resp_buf_size +
666 if (!mchan->rx_buf)
667 return -ENOMEM;
673 * versal_ipi_setup - Set up IPIs to support mixed usage of
690 tx_mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
691 rx_mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];
693 mdev = &ipi_mbox->dev;
720 return -EINVAL;
723 tx_mchan->req_buf = devm_ioremap(mdev,
726 if (!tx_mchan->req_buf) {
728 return -ENOMEM;
731 tx_mchan->resp_buf = devm_ioremap(mdev,
734 if (!tx_mchan->resp_buf) {
736 return -ENOMEM;
739 rx_mchan->req_buf = devm_ioremap(mdev,
742 if (!rx_mchan->req_buf) {
744 return -ENOMEM;
747 rx_mchan->resp_buf = devm_ioremap(mdev,
750 if (!rx_mchan->resp_buf) {
752 return -ENOMEM;
755 tx_mchan->resp_buf_size = IPI_BUF_SIZE;
756 tx_mchan->req_buf_size = IPI_BUF_SIZE;
757 tx_mchan->rx_buf = devm_kzalloc(mdev, IPI_BUF_SIZE +
760 if (!tx_mchan->rx_buf)
761 return -ENOMEM;
763 rx_mchan->resp_buf_size = IPI_BUF_SIZE;
764 rx_mchan->req_buf_size = IPI_BUF_SIZE;
765 rx_mchan->rx_buf = devm_kzalloc(mdev, IPI_BUF_SIZE +
768 if (!rx_mchan->rx_buf)
769 return -ENOMEM;
781 enable_percpu_irq(pdata->virq_sgi, IRQ_TYPE_NONE);
792 disable_percpu_irq(pdata->virq_sgi);
803 disable_percpu_irq(pdata->virq_sgi);
823 struct device *dev = &pdev->dev;
826 interrupt_parent = of_irq_find_parent(dev->of_node);
828 dev_err(&pdev->dev, "Failed to find property for Interrupt parent\n");
829 return -EINVAL;
837 sgi_fwspec.fwnode = domain->fwnode;
847 pdata->virq_sgi = irq_create_fwspec_mapping(&sgi_fwspec);
852 ret = request_percpu_irq(pdata->virq_sgi, zynqmp_sgi_interrupt, pdev->name,
856 irq_dispose_mapping(pdata->virq_sgi);
860 irq_set_status_flags(pdata->virq_sgi, IRQ_PER_CPU);
862 /* Setup function for the CPU hot-plug cases */
875 irq_clear_status_flags(pdata->virq_sgi, IRQ_PER_CPU);
876 free_percpu_irq(pdata->virq_sgi, &per_cpu_pdata);
877 irq_dispose_mapping(pdata->virq_sgi);
881 * zynqmp_ipi_free_mboxes - Free IPI mailboxes devices
890 if (pdata->irq < MAX_SGI)
893 i = pdata->num_mboxes;
894 for (; i >= 0; i--) {
895 ipi_mbox = &pdata->ipi_mboxes[i];
896 if (ipi_mbox->dev.parent) {
897 mbox_controller_unregister(&ipi_mbox->mbox);
898 if (device_is_registered(&ipi_mbox->dev))
899 device_unregister(&ipi_mbox->dev);
906 struct device *dev = &pdev->dev;
907 struct device_node *nc, *np = pdev->dev.of_node;
910 struct zynqmp_ipi_mbox *mbox;
911 int num_mboxes, ret = -EINVAL;
917 return -EINVAL;
923 return -ENOMEM;
924 pdata->dev = dev;
927 ret = of_property_read_u32(np, "xlnx,ipi-id", &pdata->local_id);
933 ipi_fn = (setup_ipi_fn)device_get_match_data(&pdev->dev);
936 "Mbox Compatible String is missing IPI Setup fn.\n");
937 return -ENODEV;
940 pdata->num_mboxes = num_mboxes;
942 mbox = pdata->ipi_mboxes;
944 mbox->pdata = pdata;
945 mbox->setup_ipi_fn = ipi_fn;
947 ret = zynqmp_ipi_mbox_probe(mbox, nc);
951 ret = -EINVAL;
954 mbox++;
969 pdata->irq = ret;
970 ret = xlnx_mbox_init_sgi(pdev, pdata->irq, pdata);
978 pdata->irq = ret;
979 ret = devm_request_irq(dev, pdata->irq, zynqmp_ipi_interrupt,
985 pdata->irq);
1006 { .compatible = "xlnx,zynqmp-ipi-mailbox",
1009 { .compatible = "xlnx,versal-ipi-mailbox",
1020 .name = "zynqmp-ipi",