mtk-rpmsg-mailbox.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (c) 2019 MediaTek Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/of.h>
  15. #include <linux/slab.h>
  16. #include <linux/errno.h>
  17. #include <linux/mailbox_controller.h>
  18. #include <linux/mailbox_client.h>
  19. #include <linux/mailbox/mtk-rpmsg-mailbox.h>
  20. #include "../misc/mediatek/include/mt-plat/mtk-mbox.h"
  21. static struct mtk_mbox_chan *to_mtk_mbox_chan(struct mbox_chan *chan)
  22. {
  23. if (!chan || !chan->con_priv)
  24. return NULL;
  25. return (struct mtk_mbox_chan *)chan->con_priv;
  26. }
  27. int mtk_mbox_send_ipi(struct mtk_mbox_chan *mchan, void *data)
  28. {
  29. struct mtk_mbox_device *mbdev;
  30. struct mtk_ipi_msg *msg;
  31. unsigned int status;
  32. int ret;
  33. if (WARN_ON(!data)) {
  34. pr_notice("mbox fw:%u warning\n", mchan->mbox);
  35. return -EINVAL;
  36. }
  37. mbdev = mchan->mbdev;
  38. msg = (struct mtk_ipi_msg *)data;
  39. status = mtk_mbox_check_send_irq(mbdev, mchan->mbox,
  40. mchan->send_pin_index);
  41. if (status != 0) {
  42. mchan->ipimsg = data;
  43. return -EBUSY;
  44. }
  45. ret = mtk_mbox_write_hd(mbdev, mchan->mbox, mchan->send_slot, msg);
  46. if (ret != MBOX_DONE)
  47. return -EIO;
  48. /*
  49. * Ensure that all writes to SRAM are committed before sending the
  50. * interrupt to mbox.
  51. */
  52. mb();
  53. ret = mtk_mbox_trigger_irq(mbdev, mchan->mbox,
  54. 0x1 << mchan->send_pin_index);
  55. if (ret != MBOX_DONE)
  56. pr_notice("mbox fw:%u irq fail\n", mchan->mbox);
  57. return ret;
  58. }
  59. bool mtk_mbox_tx_done(struct mtk_mbox_chan *mchan)
  60. {
  61. struct mtk_mbox_device *mbdev;
  62. struct mbox_chan *chan;
  63. unsigned int status;
  64. unsigned long flags;
  65. chan = mchan->chan;
  66. mbdev = mchan->mbdev;
  67. spin_lock_irqsave(&chan->lock, flags);
  68. status = mtk_mbox_check_send_irq(mbdev, mchan->mbox,
  69. mchan->send_pin_index);
  70. spin_unlock_irqrestore(&chan->lock, flags);
  71. return status ? false : true;
  72. }
  73. int mtk_mbox_start(struct mtk_mbox_chan *mchan)
  74. {
  75. return 0;
  76. }
  77. void mtk_mbox_down(struct mtk_mbox_chan *mchan)
  78. {
  79. }
  80. int mtk_mbox_send_data(struct mbox_chan *chan, void *data)
  81. {
  82. struct mtk_mbox_chan *mchan = to_mtk_mbox_chan(chan);
  83. if (mchan)
  84. return mchan->ops->mtk_send_ipi(mchan, data);
  85. return false;
  86. }
  87. bool mtk_mbox_last_tx_done(struct mbox_chan *chan)
  88. {
  89. struct mtk_mbox_chan *mchan = to_mtk_mbox_chan(chan);
  90. if (mchan)
  91. return mchan->ops->mtk_tx_done(mchan);
  92. return false;
  93. }
  94. int mtk_mbox_startup(struct mbox_chan *chan)
  95. {
  96. struct mtk_mbox_chan *mchan = to_mtk_mbox_chan(chan);
  97. if (mchan)
  98. return mchan->ops->mtk_startup(mchan);
  99. return 0;
  100. }
  101. void mtk_mbox_shutdown(struct mbox_chan *chan)
  102. {
  103. struct mtk_mbox_chan *mchan = to_mtk_mbox_chan(chan);
  104. if (mchan)
  105. mchan->ops->mtk_shutdown(mchan);
  106. }
  107. static const struct mbox_chan_ops mtk_ipi_mbox_chan_ops = {
  108. .send_data = mtk_mbox_send_data,
  109. .last_tx_done = mtk_mbox_last_tx_done,
  110. .startup = mtk_mbox_startup,
  111. .shutdown = mtk_mbox_shutdown,
  112. };
  113. static struct mtk_mbox_operations mtk_mbox_ops = {
  114. .mtk_send_ipi = mtk_mbox_send_ipi,
  115. .mtk_tx_done = mtk_mbox_tx_done,
  116. .mtk_startup = mtk_mbox_start,
  117. .mtk_shutdown = mtk_mbox_down,
  118. };
  119. static struct mbox_chan *mtk_rpmsg_mbox_xlate(struct mbox_controller *mbox,
  120. const struct of_phandle_args *sp)
  121. {
  122. int chan_id = sp->args[0];
  123. if (chan_id >= mbox->num_chans)
  124. return ERR_PTR(-EINVAL);
  125. return &mbox->chans[chan_id];
  126. }
  127. int mtk_mbox_chan_create(struct mbox_controller *mboxctrl,
  128. struct mtk_mbox_device *mbdev, int num)
  129. {
  130. struct mtk_mbox_chan *mchan;
  131. struct mtk_mbox_pin_send *msend;
  132. struct mbox_chan *chan;
  133. unsigned int i, j, count;
  134. mchan = kcalloc(num, sizeof(struct mtk_mbox_chan), GFP_KERNEL);
  135. if (!mchan)
  136. return -ENOMEM;
  137. chan = kcalloc(num, sizeof(struct mbox_chan), GFP_KERNEL);
  138. if (!chan) {
  139. kfree(mchan);
  140. return -ENOMEM;
  141. }
  142. count = mbdev->send_count;
  143. for (i = 0; i < num; i++) {
  144. chan[i].con_priv = &mchan[i];
  145. mchan[i].chan = &chan[i];
  146. mchan[i].mbdev = mbdev;
  147. mchan[i].ops = &mtk_mbox_ops;
  148. for (j = 0; j < count; j++) {
  149. msend = &(mbdev->pin_send_table[j]);
  150. if (i == msend->chan_id) {
  151. mchan[i].mbox = msend->mbox;
  152. mchan[i].send_slot = msend->offset;
  153. mchan[i].send_slot_size = msend->msg_size;
  154. mchan[i].send_pin_index = msend->pin_index;
  155. mchan[i].send_pin_offset = j;
  156. }
  157. }
  158. }
  159. mboxctrl->ops = &mtk_ipi_mbox_chan_ops;
  160. mboxctrl->chans = chan;
  161. mboxctrl->of_xlate = mtk_rpmsg_mbox_xlate;
  162. return 0;
  163. }