armada-37xx-rwtm-mailbox.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * rWTM BIU Mailbox driver for Armada 37xx
  4. *
  5. * Author: Marek Behun <marek.behun@nic.cz>
  6. */
  7. #include <linux/device.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/io.h>
  10. #include <linux/kernel.h>
  11. #include <linux/mailbox_controller.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/armada-37xx-rwtm-mailbox.h>
  16. #define DRIVER_NAME "armada-37xx-rwtm-mailbox"
  17. /* relative to rWTM BIU Mailbox Registers */
  18. #define RWTM_MBOX_PARAM(i) (0x0 + ((i) << 2))
  19. #define RWTM_MBOX_COMMAND 0x40
  20. #define RWTM_MBOX_RETURN_STATUS 0x80
  21. #define RWTM_MBOX_STATUS(i) (0x84 + ((i) << 2))
  22. #define RWTM_MBOX_FIFO_STATUS 0xc4
  23. #define FIFO_STS_RDY 0x100
  24. #define FIFO_STS_CNTR_MASK 0x7
  25. #define FIFO_STS_CNTR_MAX 4
  26. #define RWTM_HOST_INT_RESET 0xc8
  27. #define RWTM_HOST_INT_MASK 0xcc
  28. #define SP_CMD_COMPLETE BIT(0)
  29. #define SP_CMD_QUEUE_FULL_ACCESS BIT(17)
  30. #define SP_CMD_QUEUE_FULL BIT(18)
  31. struct a37xx_mbox {
  32. struct device *dev;
  33. struct mbox_controller controller;
  34. void __iomem *base;
  35. int irq;
  36. };
  37. static void a37xx_mbox_receive(struct mbox_chan *chan)
  38. {
  39. struct a37xx_mbox *mbox = chan->con_priv;
  40. struct armada_37xx_rwtm_rx_msg rx_msg;
  41. int i;
  42. rx_msg.retval = readl(mbox->base + RWTM_MBOX_RETURN_STATUS);
  43. for (i = 0; i < 16; ++i)
  44. rx_msg.status[i] = readl(mbox->base + RWTM_MBOX_STATUS(i));
  45. mbox_chan_received_data(chan, &rx_msg);
  46. }
  47. static irqreturn_t a37xx_mbox_irq_handler(int irq, void *data)
  48. {
  49. struct mbox_chan *chan = data;
  50. struct a37xx_mbox *mbox = chan->con_priv;
  51. u32 reg;
  52. reg = readl(mbox->base + RWTM_HOST_INT_RESET);
  53. if (reg & SP_CMD_COMPLETE)
  54. a37xx_mbox_receive(chan);
  55. if (reg & (SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL))
  56. dev_err(mbox->dev, "Secure processor command queue full\n");
  57. writel(reg, mbox->base + RWTM_HOST_INT_RESET);
  58. if (reg)
  59. mbox_chan_txdone(chan, 0);
  60. return reg ? IRQ_HANDLED : IRQ_NONE;
  61. }
  62. static int a37xx_mbox_send_data(struct mbox_chan *chan, void *data)
  63. {
  64. struct a37xx_mbox *mbox = chan->con_priv;
  65. struct armada_37xx_rwtm_tx_msg *msg = data;
  66. int i;
  67. u32 reg;
  68. if (!data)
  69. return -EINVAL;
  70. reg = readl(mbox->base + RWTM_MBOX_FIFO_STATUS);
  71. if (!(reg & FIFO_STS_RDY))
  72. dev_warn(mbox->dev, "Secure processor not ready\n");
  73. if ((reg & FIFO_STS_CNTR_MASK) >= FIFO_STS_CNTR_MAX) {
  74. dev_err(mbox->dev, "Secure processor command queue full\n");
  75. return -EBUSY;
  76. }
  77. for (i = 0; i < 16; ++i)
  78. writel(msg->args[i], mbox->base + RWTM_MBOX_PARAM(i));
  79. writel(msg->command, mbox->base + RWTM_MBOX_COMMAND);
  80. return 0;
  81. }
  82. static int a37xx_mbox_startup(struct mbox_chan *chan)
  83. {
  84. struct a37xx_mbox *mbox = chan->con_priv;
  85. u32 reg;
  86. int ret;
  87. ret = devm_request_irq(mbox->dev, mbox->irq, a37xx_mbox_irq_handler, 0,
  88. DRIVER_NAME, chan);
  89. if (ret < 0) {
  90. dev_err(mbox->dev, "Cannot request irq\n");
  91. return ret;
  92. }
  93. /* enable IRQ generation */
  94. reg = readl(mbox->base + RWTM_HOST_INT_MASK);
  95. reg &= ~(SP_CMD_COMPLETE | SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL);
  96. writel(reg, mbox->base + RWTM_HOST_INT_MASK);
  97. return 0;
  98. }
  99. static void a37xx_mbox_shutdown(struct mbox_chan *chan)
  100. {
  101. u32 reg;
  102. struct a37xx_mbox *mbox = chan->con_priv;
  103. /* disable interrupt generation */
  104. reg = readl(mbox->base + RWTM_HOST_INT_MASK);
  105. reg |= SP_CMD_COMPLETE | SP_CMD_QUEUE_FULL_ACCESS | SP_CMD_QUEUE_FULL;
  106. writel(reg, mbox->base + RWTM_HOST_INT_MASK);
  107. devm_free_irq(mbox->dev, mbox->irq, chan);
  108. }
  109. static const struct mbox_chan_ops a37xx_mbox_ops = {
  110. .send_data = a37xx_mbox_send_data,
  111. .startup = a37xx_mbox_startup,
  112. .shutdown = a37xx_mbox_shutdown,
  113. };
  114. static int armada_37xx_mbox_probe(struct platform_device *pdev)
  115. {
  116. struct a37xx_mbox *mbox;
  117. struct mbox_chan *chans;
  118. int ret;
  119. mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
  120. if (!mbox)
  121. return -ENOMEM;
  122. /* Allocated one channel */
  123. chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
  124. if (!chans)
  125. return -ENOMEM;
  126. mbox->base = devm_platform_ioremap_resource(pdev, 0);
  127. if (IS_ERR(mbox->base))
  128. return PTR_ERR(mbox->base);
  129. mbox->irq = platform_get_irq(pdev, 0);
  130. if (mbox->irq < 0)
  131. return mbox->irq;
  132. mbox->dev = &pdev->dev;
  133. /* Hardware supports only one channel. */
  134. chans[0].con_priv = mbox;
  135. mbox->controller.dev = mbox->dev;
  136. mbox->controller.num_chans = 1;
  137. mbox->controller.chans = chans;
  138. mbox->controller.ops = &a37xx_mbox_ops;
  139. mbox->controller.txdone_irq = true;
  140. ret = devm_mbox_controller_register(mbox->dev, &mbox->controller);
  141. if (ret) {
  142. dev_err(&pdev->dev, "Could not register mailbox controller\n");
  143. return ret;
  144. }
  145. platform_set_drvdata(pdev, mbox);
  146. return ret;
  147. }
  148. static const struct of_device_id armada_37xx_mbox_match[] = {
  149. { .compatible = "marvell,armada-3700-rwtm-mailbox" },
  150. { },
  151. };
  152. MODULE_DEVICE_TABLE(of, armada_37xx_mbox_match);
  153. static struct platform_driver armada_37xx_mbox_driver = {
  154. .probe = armada_37xx_mbox_probe,
  155. .driver = {
  156. .name = DRIVER_NAME,
  157. .of_match_table = armada_37xx_mbox_match,
  158. },
  159. };
  160. module_platform_driver(armada_37xx_mbox_driver);
  161. MODULE_LICENSE("GPL v2");
  162. MODULE_DESCRIPTION("rWTM BIU Mailbox driver for Armada 37xx");
  163. MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");