hi6220-mailbox.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Hisilicon's Hi6220 mailbox driver
  4. *
  5. * Copyright (c) 2015 HiSilicon Limited.
  6. * Copyright (c) 2015 Linaro Limited.
  7. *
  8. * Author: Leo Yan <leo.yan@linaro.org>
  9. */
  10. #include <linux/device.h>
  11. #include <linux/err.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/io.h>
  14. #include <linux/kfifo.h>
  15. #include <linux/mailbox_controller.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/slab.h>
  20. #define MBOX_CHAN_MAX 32
  21. #define MBOX_TX 0x1
  22. /* Mailbox message length: 8 words */
  23. #define MBOX_MSG_LEN 8
  24. /* Mailbox Registers */
  25. #define MBOX_OFF(m) (0x40 * (m))
  26. #define MBOX_MODE_REG(m) (MBOX_OFF(m) + 0x0)
  27. #define MBOX_DATA_REG(m) (MBOX_OFF(m) + 0x4)
  28. #define MBOX_STATE_MASK (0xF << 4)
  29. #define MBOX_STATE_IDLE (0x1 << 4)
  30. #define MBOX_STATE_TX (0x2 << 4)
  31. #define MBOX_STATE_RX (0x4 << 4)
  32. #define MBOX_STATE_ACK (0x8 << 4)
  33. #define MBOX_ACK_CONFIG_MASK (0x1 << 0)
  34. #define MBOX_ACK_AUTOMATIC (0x1 << 0)
  35. #define MBOX_ACK_IRQ (0x0 << 0)
  36. /* IPC registers */
  37. #define ACK_INT_RAW_REG(i) ((i) + 0x400)
  38. #define ACK_INT_MSK_REG(i) ((i) + 0x404)
  39. #define ACK_INT_STAT_REG(i) ((i) + 0x408)
  40. #define ACK_INT_CLR_REG(i) ((i) + 0x40c)
  41. #define ACK_INT_ENA_REG(i) ((i) + 0x500)
  42. #define ACK_INT_DIS_REG(i) ((i) + 0x504)
  43. #define DST_INT_RAW_REG(i) ((i) + 0x420)
  44. struct hi6220_mbox_chan {
  45. /*
  46. * Description for channel's hardware info:
  47. * - direction: tx or rx
  48. * - dst irq: peer core's irq number
  49. * - ack irq: local irq number
  50. * - slot number
  51. */
  52. unsigned int dir, dst_irq, ack_irq;
  53. unsigned int slot;
  54. struct hi6220_mbox *parent;
  55. };
  56. struct hi6220_mbox {
  57. struct device *dev;
  58. int irq;
  59. /* flag of enabling tx's irq mode */
  60. bool tx_irq_mode;
  61. /* region for ipc event */
  62. void __iomem *ipc;
  63. /* region for mailbox */
  64. void __iomem *base;
  65. unsigned int chan_num;
  66. struct hi6220_mbox_chan *mchan;
  67. void *irq_map_chan[MBOX_CHAN_MAX];
  68. struct mbox_chan *chan;
  69. struct mbox_controller controller;
  70. };
  71. static void mbox_set_state(struct hi6220_mbox *mbox,
  72. unsigned int slot, u32 val)
  73. {
  74. u32 status;
  75. status = readl(mbox->base + MBOX_MODE_REG(slot));
  76. status = (status & ~MBOX_STATE_MASK) | val;
  77. writel(status, mbox->base + MBOX_MODE_REG(slot));
  78. }
  79. static void mbox_set_mode(struct hi6220_mbox *mbox,
  80. unsigned int slot, u32 val)
  81. {
  82. u32 mode;
  83. mode = readl(mbox->base + MBOX_MODE_REG(slot));
  84. mode = (mode & ~MBOX_ACK_CONFIG_MASK) | val;
  85. writel(mode, mbox->base + MBOX_MODE_REG(slot));
  86. }
  87. static bool hi6220_mbox_last_tx_done(struct mbox_chan *chan)
  88. {
  89. struct hi6220_mbox_chan *mchan = chan->con_priv;
  90. struct hi6220_mbox *mbox = mchan->parent;
  91. u32 state;
  92. /* Only set idle state for polling mode */
  93. BUG_ON(mbox->tx_irq_mode);
  94. state = readl(mbox->base + MBOX_MODE_REG(mchan->slot));
  95. return ((state & MBOX_STATE_MASK) == MBOX_STATE_IDLE);
  96. }
  97. static int hi6220_mbox_send_data(struct mbox_chan *chan, void *msg)
  98. {
  99. struct hi6220_mbox_chan *mchan = chan->con_priv;
  100. struct hi6220_mbox *mbox = mchan->parent;
  101. unsigned int slot = mchan->slot;
  102. u32 *buf = msg;
  103. int i;
  104. /* indicate as a TX channel */
  105. mchan->dir = MBOX_TX;
  106. mbox_set_state(mbox, slot, MBOX_STATE_TX);
  107. if (mbox->tx_irq_mode)
  108. mbox_set_mode(mbox, slot, MBOX_ACK_IRQ);
  109. else
  110. mbox_set_mode(mbox, slot, MBOX_ACK_AUTOMATIC);
  111. for (i = 0; i < MBOX_MSG_LEN; i++)
  112. writel(buf[i], mbox->base + MBOX_DATA_REG(slot) + i * 4);
  113. /* trigger remote request */
  114. writel(BIT(mchan->dst_irq), DST_INT_RAW_REG(mbox->ipc));
  115. return 0;
  116. }
  117. static irqreturn_t hi6220_mbox_interrupt(int irq, void *p)
  118. {
  119. struct hi6220_mbox *mbox = p;
  120. struct hi6220_mbox_chan *mchan;
  121. struct mbox_chan *chan;
  122. unsigned int state, intr_bit, i;
  123. u32 msg[MBOX_MSG_LEN];
  124. state = readl(ACK_INT_STAT_REG(mbox->ipc));
  125. if (!state) {
  126. dev_warn(mbox->dev, "%s: spurious interrupt\n",
  127. __func__);
  128. return IRQ_HANDLED;
  129. }
  130. while (state) {
  131. intr_bit = __ffs(state);
  132. state &= (state - 1);
  133. chan = mbox->irq_map_chan[intr_bit];
  134. if (!chan) {
  135. dev_warn(mbox->dev, "%s: unexpected irq vector %d\n",
  136. __func__, intr_bit);
  137. continue;
  138. }
  139. mchan = chan->con_priv;
  140. if (mchan->dir == MBOX_TX)
  141. mbox_chan_txdone(chan, 0);
  142. else {
  143. for (i = 0; i < MBOX_MSG_LEN; i++)
  144. msg[i] = readl(mbox->base +
  145. MBOX_DATA_REG(mchan->slot) + i * 4);
  146. mbox_chan_received_data(chan, (void *)msg);
  147. }
  148. /* clear IRQ source */
  149. writel(BIT(mchan->ack_irq), ACK_INT_CLR_REG(mbox->ipc));
  150. mbox_set_state(mbox, mchan->slot, MBOX_STATE_IDLE);
  151. }
  152. return IRQ_HANDLED;
  153. }
  154. static int hi6220_mbox_startup(struct mbox_chan *chan)
  155. {
  156. struct hi6220_mbox_chan *mchan = chan->con_priv;
  157. struct hi6220_mbox *mbox = mchan->parent;
  158. mchan->dir = 0;
  159. /* enable interrupt */
  160. writel(BIT(mchan->ack_irq), ACK_INT_ENA_REG(mbox->ipc));
  161. return 0;
  162. }
  163. static void hi6220_mbox_shutdown(struct mbox_chan *chan)
  164. {
  165. struct hi6220_mbox_chan *mchan = chan->con_priv;
  166. struct hi6220_mbox *mbox = mchan->parent;
  167. /* disable interrupt */
  168. writel(BIT(mchan->ack_irq), ACK_INT_DIS_REG(mbox->ipc));
  169. mbox->irq_map_chan[mchan->ack_irq] = NULL;
  170. }
  171. static const struct mbox_chan_ops hi6220_mbox_ops = {
  172. .send_data = hi6220_mbox_send_data,
  173. .startup = hi6220_mbox_startup,
  174. .shutdown = hi6220_mbox_shutdown,
  175. .last_tx_done = hi6220_mbox_last_tx_done,
  176. };
  177. static struct mbox_chan *hi6220_mbox_xlate(struct mbox_controller *controller,
  178. const struct of_phandle_args *spec)
  179. {
  180. struct hi6220_mbox *mbox = dev_get_drvdata(controller->dev);
  181. struct hi6220_mbox_chan *mchan;
  182. struct mbox_chan *chan;
  183. unsigned int i = spec->args[0];
  184. unsigned int dst_irq = spec->args[1];
  185. unsigned int ack_irq = spec->args[2];
  186. /* Bounds checking */
  187. if (i >= mbox->chan_num || dst_irq >= mbox->chan_num ||
  188. ack_irq >= mbox->chan_num) {
  189. dev_err(mbox->dev,
  190. "Invalid channel idx %d dst_irq %d ack_irq %d\n",
  191. i, dst_irq, ack_irq);
  192. return ERR_PTR(-EINVAL);
  193. }
  194. /* Is requested channel free? */
  195. chan = &mbox->chan[i];
  196. if (mbox->irq_map_chan[ack_irq] == (void *)chan) {
  197. dev_err(mbox->dev, "Channel in use\n");
  198. return ERR_PTR(-EBUSY);
  199. }
  200. mchan = chan->con_priv;
  201. mchan->dst_irq = dst_irq;
  202. mchan->ack_irq = ack_irq;
  203. mbox->irq_map_chan[ack_irq] = (void *)chan;
  204. return chan;
  205. }
  206. static const struct of_device_id hi6220_mbox_of_match[] = {
  207. { .compatible = "hisilicon,hi6220-mbox", },
  208. {},
  209. };
  210. MODULE_DEVICE_TABLE(of, hi6220_mbox_of_match);
  211. static int hi6220_mbox_probe(struct platform_device *pdev)
  212. {
  213. struct device_node *node = pdev->dev.of_node;
  214. struct device *dev = &pdev->dev;
  215. struct hi6220_mbox *mbox;
  216. int i, err;
  217. mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
  218. if (!mbox)
  219. return -ENOMEM;
  220. mbox->dev = dev;
  221. mbox->chan_num = MBOX_CHAN_MAX;
  222. mbox->mchan = devm_kcalloc(dev,
  223. mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL);
  224. if (!mbox->mchan)
  225. return -ENOMEM;
  226. mbox->chan = devm_kcalloc(dev,
  227. mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL);
  228. if (!mbox->chan)
  229. return -ENOMEM;
  230. mbox->irq = platform_get_irq(pdev, 0);
  231. if (mbox->irq < 0)
  232. return mbox->irq;
  233. mbox->ipc = devm_platform_ioremap_resource(pdev, 0);
  234. if (IS_ERR(mbox->ipc)) {
  235. dev_err(dev, "ioremap ipc failed\n");
  236. return PTR_ERR(mbox->ipc);
  237. }
  238. mbox->base = devm_platform_ioremap_resource(pdev, 1);
  239. if (IS_ERR(mbox->base)) {
  240. dev_err(dev, "ioremap buffer failed\n");
  241. return PTR_ERR(mbox->base);
  242. }
  243. err = devm_request_irq(dev, mbox->irq, hi6220_mbox_interrupt, 0,
  244. dev_name(dev), mbox);
  245. if (err) {
  246. dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
  247. err);
  248. return -ENODEV;
  249. }
  250. mbox->controller.dev = dev;
  251. mbox->controller.chans = &mbox->chan[0];
  252. mbox->controller.num_chans = mbox->chan_num;
  253. mbox->controller.ops = &hi6220_mbox_ops;
  254. mbox->controller.of_xlate = hi6220_mbox_xlate;
  255. for (i = 0; i < mbox->chan_num; i++) {
  256. mbox->chan[i].con_priv = &mbox->mchan[i];
  257. mbox->irq_map_chan[i] = NULL;
  258. mbox->mchan[i].parent = mbox;
  259. mbox->mchan[i].slot = i;
  260. }
  261. /* mask and clear all interrupt vectors */
  262. writel(0x0, ACK_INT_MSK_REG(mbox->ipc));
  263. writel(~0x0, ACK_INT_CLR_REG(mbox->ipc));
  264. /* use interrupt for tx's ack */
  265. mbox->tx_irq_mode = !of_property_read_bool(node, "hi6220,mbox-tx-noirq");
  266. if (mbox->tx_irq_mode)
  267. mbox->controller.txdone_irq = true;
  268. else {
  269. mbox->controller.txdone_poll = true;
  270. mbox->controller.txpoll_period = 5;
  271. }
  272. err = devm_mbox_controller_register(dev, &mbox->controller);
  273. if (err) {
  274. dev_err(dev, "Failed to register mailbox %d\n", err);
  275. return err;
  276. }
  277. platform_set_drvdata(pdev, mbox);
  278. dev_info(dev, "Mailbox enabled\n");
  279. return 0;
  280. }
  281. static struct platform_driver hi6220_mbox_driver = {
  282. .driver = {
  283. .name = "hi6220-mbox",
  284. .of_match_table = hi6220_mbox_of_match,
  285. },
  286. .probe = hi6220_mbox_probe,
  287. };
  288. static int __init hi6220_mbox_init(void)
  289. {
  290. return platform_driver_register(&hi6220_mbox_driver);
  291. }
  292. core_initcall(hi6220_mbox_init);
  293. static void __exit hi6220_mbox_exit(void)
  294. {
  295. platform_driver_unregister(&hi6220_mbox_driver);
  296. }
  297. module_exit(hi6220_mbox_exit);
  298. MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
  299. MODULE_DESCRIPTION("Hi6220 mailbox driver");
  300. MODULE_LICENSE("GPL v2");