Lines Matching +full:mbox +full:- +full:name

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