hi6220-mailbox.c 8.9 KB

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