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

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/arm-smccc.h>
15 #include <linux/mailbox/zynqmp-ipi-message.h>
56 * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel
76 * struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox
82 * @mbox: mailbox Controller
90 struct mbox_controller mbox; member
95 * struct zynqmp_ipi_pdata - Description of z ZynqMP IPI agent platform data.
116 .name = "zynqmp-ipi-mbox",
123 struct zynqmp_ipi_pdata *pdata = ipi_mbox->pdata; in zynqmp_ipi_fw_call()
126 a1 = pdata->local_id; in zynqmp_ipi_fw_call()
127 a2 = ipi_mbox->remote_id; in zynqmp_ipi_fw_call()
128 if (pdata->method == USE_SMC) in zynqmp_ipi_fw_call()
135 * zynqmp_ipi_interrupt - Interrupt handler for IPI notification
140 * Return: -EINVAL if there is no instance
158 for (i = 0; i < pdata->num_mboxes; i++) { in zynqmp_ipi_interrupt()
159 ipi_mbox = &pdata->ipi_mboxes[i]; in zynqmp_ipi_interrupt()
160 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX]; in zynqmp_ipi_interrupt()
161 chan = &ipi_mbox->mbox.chans[IPI_MB_CHNL_RX]; in zynqmp_ipi_interrupt()
165 if (mchan->is_opened) { in zynqmp_ipi_interrupt()
166 msg = mchan->rx_buf; in zynqmp_ipi_interrupt()
167 msg->len = mchan->req_buf_size; in zynqmp_ipi_interrupt()
168 memcpy_fromio(msg->data, mchan->req_buf, in zynqmp_ipi_interrupt()
169 msg->len); in zynqmp_ipi_interrupt()
179 * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.
187 struct device *dev = chan->mbox->dev; in zynqmp_ipi_peek_data()
189 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_peek_data()
203 if (mchan->chan_type == IPI_MB_CHNL_TX) { in zynqmp_ipi_peek_data()
219 * zynqmp_ipi_last_tx_done - See if the last tx message is sent
227 struct device *dev = chan->mbox->dev; in zynqmp_ipi_last_tx_done()
229 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_last_tx_done()
239 if (mchan->chan_type == IPI_MB_CHNL_TX) { in zynqmp_ipi_last_tx_done()
256 * zynqmp_ipi_send_data - Send data
265 struct device *dev = chan->mbox->dev; in zynqmp_ipi_send_data()
267 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_send_data()
274 return -EINVAL; in zynqmp_ipi_send_data()
277 if (mchan->chan_type == IPI_MB_CHNL_TX) { in zynqmp_ipi_send_data()
279 if (msg && msg->len > mchan->req_buf_size) { in zynqmp_ipi_send_data()
281 mchan->chan_type, (unsigned int)msg->len, in zynqmp_ipi_send_data()
282 mchan->req_buf_size); in zynqmp_ipi_send_data()
283 return -EINVAL; in zynqmp_ipi_send_data()
285 if (msg && msg->len) in zynqmp_ipi_send_data()
286 memcpy_toio(mchan->req_buf, msg->data, msg->len); in zynqmp_ipi_send_data()
292 if (msg && msg->len > mchan->resp_buf_size) { in zynqmp_ipi_send_data()
294 mchan->chan_type, (unsigned int)msg->len, in zynqmp_ipi_send_data()
295 mchan->resp_buf_size); in zynqmp_ipi_send_data()
296 return -EINVAL; in zynqmp_ipi_send_data()
298 if (msg && msg->len) in zynqmp_ipi_send_data()
299 memcpy_toio(mchan->resp_buf, msg->data, msg->len); in zynqmp_ipi_send_data()
308 * zynqmp_ipi_startup - Startup the IPI channel
316 struct device *dev = chan->mbox->dev; in zynqmp_ipi_startup()
318 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_startup()
324 if (mchan->is_opened) in zynqmp_ipi_startup()
328 nchan_type = (mchan->chan_type + 1) % 2; in zynqmp_ipi_startup()
329 if (!ipi_mbox->mchans[nchan_type].is_opened) { in zynqmp_ipi_startup()
342 if (mchan->chan_type == IPI_MB_CHNL_RX) { in zynqmp_ipi_startup()
346 mchan->is_opened = 1; in zynqmp_ipi_startup()
352 * zynqmp_ipi_shutdown - Shutdown the IPI channel
358 struct device *dev = chan->mbox->dev; in zynqmp_ipi_shutdown()
360 struct zynqmp_ipi_mchan *mchan = chan->con_priv; in zynqmp_ipi_shutdown()
365 if (!mchan->is_opened) in zynqmp_ipi_shutdown()
369 chan_type = mchan->chan_type; in zynqmp_ipi_shutdown()
376 if (!ipi_mbox->mchans[chan_type].is_opened) { in zynqmp_ipi_shutdown()
381 mchan->is_opened = 0; in zynqmp_ipi_shutdown()
394 * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel
396 * @mbox: mailbox controller pointer
401 static struct mbox_chan *zynqmp_ipi_of_xlate(struct mbox_controller *mbox, in zynqmp_ipi_of_xlate() argument
405 struct device *dev = mbox->dev; in zynqmp_ipi_of_xlate()
409 chan_type = p->args[0]; in zynqmp_ipi_of_xlate()
413 return ERR_PTR(-EINVAL); in zynqmp_ipi_of_xlate()
415 chan = &mbox->chans[chan_type]; in zynqmp_ipi_of_xlate()
420 { .compatible = "xlnx,zynqmp-ipi-mailbox" },
426 * zynqmp_ipi_mbox_get_buf_res - Get buffer resource from the IPI dev node
428 * @node: IPI mbox device child node
429 * @name: name of the IPI buffer
435 const char *name, in zynqmp_ipi_mbox_get_buf_res() argument
440 index = of_property_match_string(node, "reg-names", name); in zynqmp_ipi_mbox_get_buf_res()
444 return -EINVAL; in zynqmp_ipi_mbox_get_buf_res()
447 return -ENODEV; in zynqmp_ipi_mbox_get_buf_res()
451 * zynqmp_ipi_mbox_dev_release() - release the existence of a ipi mbox dev
464 * zynqmp_ipi_mbox_probe - probe IPI mailbox resource from device node
476 struct mbox_controller *mbox; in zynqmp_ipi_mbox_probe() local
479 const char *name; in zynqmp_ipi_mbox_probe() local
482 dev = ipi_mbox->pdata->dev; in zynqmp_ipi_mbox_probe()
484 ipi_mbox->dev.parent = dev; in zynqmp_ipi_mbox_probe()
485 ipi_mbox->dev.release = NULL; in zynqmp_ipi_mbox_probe()
486 ipi_mbox->dev.of_node = node; in zynqmp_ipi_mbox_probe()
487 dev_set_name(&ipi_mbox->dev, "%s", of_node_full_name(node)); in zynqmp_ipi_mbox_probe()
488 dev_set_drvdata(&ipi_mbox->dev, ipi_mbox); in zynqmp_ipi_mbox_probe()
489 ipi_mbox->dev.release = zynqmp_ipi_mbox_dev_release; in zynqmp_ipi_mbox_probe()
490 ipi_mbox->dev.driver = &zynqmp_ipi_mbox_driver; in zynqmp_ipi_mbox_probe()
491 ret = device_register(&ipi_mbox->dev); in zynqmp_ipi_mbox_probe()
493 dev_err(dev, "Failed to register ipi mbox dev.\n"); in zynqmp_ipi_mbox_probe()
494 put_device(&ipi_mbox->dev); in zynqmp_ipi_mbox_probe()
497 mdev = &ipi_mbox->dev; in zynqmp_ipi_mbox_probe()
499 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX]; in zynqmp_ipi_mbox_probe()
500 name = "local_request_region"; in zynqmp_ipi_mbox_probe()
501 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res); in zynqmp_ipi_mbox_probe()
503 mchan->req_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
504 mchan->req_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
505 mchan->req_buf_size); in zynqmp_ipi_mbox_probe()
506 if (!mchan->req_buf) { in zynqmp_ipi_mbox_probe()
508 return -ENOMEM; in zynqmp_ipi_mbox_probe()
510 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
511 dev_err(mdev, "Unmatched resource %s, %d.\n", name, ret); in zynqmp_ipi_mbox_probe()
515 name = "remote_response_region"; in zynqmp_ipi_mbox_probe()
516 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res); in zynqmp_ipi_mbox_probe()
518 mchan->resp_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
519 mchan->resp_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
520 mchan->resp_buf_size); in zynqmp_ipi_mbox_probe()
521 if (!mchan->resp_buf) { in zynqmp_ipi_mbox_probe()
523 return -ENOMEM; in zynqmp_ipi_mbox_probe()
525 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
526 dev_err(mdev, "Unmatched resource %s.\n", name); in zynqmp_ipi_mbox_probe()
529 mchan->rx_buf = devm_kzalloc(mdev, in zynqmp_ipi_mbox_probe()
530 mchan->resp_buf_size + in zynqmp_ipi_mbox_probe()
533 if (!mchan->rx_buf) in zynqmp_ipi_mbox_probe()
534 return -ENOMEM; in zynqmp_ipi_mbox_probe()
536 mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX]; in zynqmp_ipi_mbox_probe()
537 name = "remote_request_region"; in zynqmp_ipi_mbox_probe()
538 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res); in zynqmp_ipi_mbox_probe()
540 mchan->req_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
541 mchan->req_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
542 mchan->req_buf_size); in zynqmp_ipi_mbox_probe()
543 if (!mchan->req_buf) { in zynqmp_ipi_mbox_probe()
545 return -ENOMEM; in zynqmp_ipi_mbox_probe()
547 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
548 dev_err(mdev, "Unmatched resource %s.\n", name); in zynqmp_ipi_mbox_probe()
552 name = "local_response_region"; in zynqmp_ipi_mbox_probe()
553 ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res); in zynqmp_ipi_mbox_probe()
555 mchan->resp_buf_size = resource_size(&res); in zynqmp_ipi_mbox_probe()
556 mchan->resp_buf = devm_ioremap(mdev, res.start, in zynqmp_ipi_mbox_probe()
557 mchan->resp_buf_size); in zynqmp_ipi_mbox_probe()
558 if (!mchan->resp_buf) { in zynqmp_ipi_mbox_probe()
560 return -ENOMEM; in zynqmp_ipi_mbox_probe()
562 } else if (ret != -ENODEV) { in zynqmp_ipi_mbox_probe()
563 dev_err(mdev, "Unmatched resource %s.\n", name); in zynqmp_ipi_mbox_probe()
566 mchan->rx_buf = devm_kzalloc(mdev, in zynqmp_ipi_mbox_probe()
567 mchan->resp_buf_size + in zynqmp_ipi_mbox_probe()
570 if (!mchan->rx_buf) in zynqmp_ipi_mbox_probe()
571 return -ENOMEM; in zynqmp_ipi_mbox_probe()
574 ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id); in zynqmp_ipi_mbox_probe()
580 mbox = &ipi_mbox->mbox; in zynqmp_ipi_mbox_probe()
581 mbox->dev = mdev; in zynqmp_ipi_mbox_probe()
582 mbox->ops = &zynqmp_ipi_chan_ops; in zynqmp_ipi_mbox_probe()
583 mbox->num_chans = 2; in zynqmp_ipi_mbox_probe()
584 mbox->txdone_irq = false; in zynqmp_ipi_mbox_probe()
585 mbox->txdone_poll = true; in zynqmp_ipi_mbox_probe()
586 mbox->txpoll_period = 5; in zynqmp_ipi_mbox_probe()
587 mbox->of_xlate = zynqmp_ipi_of_xlate; in zynqmp_ipi_mbox_probe()
590 return -ENOMEM; in zynqmp_ipi_mbox_probe()
591 mbox->chans = chans; in zynqmp_ipi_mbox_probe()
592 chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX]; in zynqmp_ipi_mbox_probe()
593 chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX]; in zynqmp_ipi_mbox_probe()
594 ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX; in zynqmp_ipi_mbox_probe()
595 ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX; in zynqmp_ipi_mbox_probe()
596 ret = devm_mbox_controller_register(mdev, mbox); in zynqmp_ipi_mbox_probe()
602 "Registered ZynqMP IPI mbox with TX/RX channels.\n"); in zynqmp_ipi_mbox_probe()
607 * zynqmp_ipi_free_mboxes - Free IPI mailboxes devices
616 i = pdata->num_mboxes; in zynqmp_ipi_free_mboxes()
617 for (; i >= 0; i--) { in zynqmp_ipi_free_mboxes()
618 ipi_mbox = &pdata->ipi_mboxes[i]; in zynqmp_ipi_free_mboxes()
619 if (ipi_mbox->dev.parent) { in zynqmp_ipi_free_mboxes()
620 mbox_controller_unregister(&ipi_mbox->mbox); in zynqmp_ipi_free_mboxes()
621 if (device_is_registered(&ipi_mbox->dev)) 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()
638 return -EINVAL; in zynqmp_ipi_probe()
644 return -ENOMEM; in zynqmp_ipi_probe()
645 pdata->dev = dev; in zynqmp_ipi_probe()
648 ret = of_property_read_u32(np, "xlnx,ipi-id", &pdata->local_id); in zynqmp_ipi_probe()
654 pdata->num_mboxes = num_mboxes; in zynqmp_ipi_probe()
656 mbox = pdata->ipi_mboxes; in zynqmp_ipi_probe()
658 mbox->pdata = pdata; in zynqmp_ipi_probe()
659 ret = zynqmp_ipi_mbox_probe(mbox, nc); in zynqmp_ipi_probe()
663 ret = -EINVAL; in zynqmp_ipi_probe()
666 mbox++; in zynqmp_ipi_probe()
674 pdata->irq = ret; in zynqmp_ipi_probe()
675 ret = devm_request_irq(dev, pdata->irq, zynqmp_ipi_interrupt, in zynqmp_ipi_probe()
679 pdata->irq); in zynqmp_ipi_probe()
705 .name = "zynqmp-ipi",