mpic_msgr.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
  3. *
  4. * Some ideas based on un-pushed work done by Vivek Mahajan, Jason Jin, and
  5. * Mingkai Hu from Freescale Semiconductor, Inc.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; version 2 of the
  10. * License.
  11. *
  12. */
  13. #include <linux/list.h>
  14. #include <linux/of_platform.h>
  15. #include <linux/errno.h>
  16. #include <asm/prom.h>
  17. #include <asm/hw_irq.h>
  18. #include <asm/ppc-pci.h>
  19. #include <asm/mpic_msgr.h>
  20. #define MPIC_MSGR_REGISTERS_PER_BLOCK 4
  21. #define MPIC_MSGR_STRIDE 0x10
  22. #define MPIC_MSGR_MER_OFFSET 0x100
  23. #define MSGR_INUSE 0
  24. #define MSGR_FREE 1
  25. static struct mpic_msgr **mpic_msgrs;
  26. static unsigned int mpic_msgr_count;
  27. static DEFINE_RAW_SPINLOCK(msgrs_lock);
  28. static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
  29. {
  30. out_be32(msgr->mer, value);
  31. }
  32. static inline u32 _mpic_msgr_mer_read(struct mpic_msgr *msgr)
  33. {
  34. return in_be32(msgr->mer);
  35. }
  36. static inline void _mpic_msgr_disable(struct mpic_msgr *msgr)
  37. {
  38. u32 mer = _mpic_msgr_mer_read(msgr);
  39. _mpic_msgr_mer_write(msgr, mer & ~(1 << msgr->num));
  40. }
  41. struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
  42. {
  43. unsigned long flags;
  44. struct mpic_msgr *msgr;
  45. /* Assume busy until proven otherwise. */
  46. msgr = ERR_PTR(-EBUSY);
  47. if (reg_num >= mpic_msgr_count)
  48. return ERR_PTR(-ENODEV);
  49. raw_spin_lock_irqsave(&msgrs_lock, flags);
  50. msgr = mpic_msgrs[reg_num];
  51. if (msgr->in_use == MSGR_FREE)
  52. msgr->in_use = MSGR_INUSE;
  53. raw_spin_unlock_irqrestore(&msgrs_lock, flags);
  54. return msgr;
  55. }
  56. EXPORT_SYMBOL_GPL(mpic_msgr_get);
  57. void mpic_msgr_put(struct mpic_msgr *msgr)
  58. {
  59. unsigned long flags;
  60. raw_spin_lock_irqsave(&msgr->lock, flags);
  61. msgr->in_use = MSGR_FREE;
  62. _mpic_msgr_disable(msgr);
  63. raw_spin_unlock_irqrestore(&msgr->lock, flags);
  64. }
  65. EXPORT_SYMBOL_GPL(mpic_msgr_put);
  66. void mpic_msgr_enable(struct mpic_msgr *msgr)
  67. {
  68. unsigned long flags;
  69. u32 mer;
  70. raw_spin_lock_irqsave(&msgr->lock, flags);
  71. mer = _mpic_msgr_mer_read(msgr);
  72. _mpic_msgr_mer_write(msgr, mer | (1 << msgr->num));
  73. raw_spin_unlock_irqrestore(&msgr->lock, flags);
  74. }
  75. EXPORT_SYMBOL_GPL(mpic_msgr_enable);
  76. void mpic_msgr_disable(struct mpic_msgr *msgr)
  77. {
  78. unsigned long flags;
  79. raw_spin_lock_irqsave(&msgr->lock, flags);
  80. _mpic_msgr_disable(msgr);
  81. raw_spin_unlock_irqrestore(&msgr->lock, flags);
  82. }
  83. EXPORT_SYMBOL_GPL(mpic_msgr_disable);
  84. /* The following three functions are used to compute the order and number of
  85. * the message register blocks. They are clearly very inefficent. However,
  86. * they are called *only* a few times during device initialization.
  87. */
  88. static unsigned int mpic_msgr_number_of_blocks(void)
  89. {
  90. unsigned int count;
  91. struct device_node *aliases;
  92. count = 0;
  93. aliases = of_find_node_by_name(NULL, "aliases");
  94. if (aliases) {
  95. char buf[32];
  96. for (;;) {
  97. snprintf(buf, sizeof(buf), "mpic-msgr-block%d", count);
  98. if (!of_find_property(aliases, buf, NULL))
  99. break;
  100. count += 1;
  101. }
  102. }
  103. return count;
  104. }
  105. static unsigned int mpic_msgr_number_of_registers(void)
  106. {
  107. return mpic_msgr_number_of_blocks() * MPIC_MSGR_REGISTERS_PER_BLOCK;
  108. }
  109. static int mpic_msgr_block_number(struct device_node *node)
  110. {
  111. struct device_node *aliases;
  112. unsigned int index, number_of_blocks;
  113. char buf[64];
  114. number_of_blocks = mpic_msgr_number_of_blocks();
  115. aliases = of_find_node_by_name(NULL, "aliases");
  116. if (!aliases)
  117. return -1;
  118. for (index = 0; index < number_of_blocks; ++index) {
  119. struct property *prop;
  120. snprintf(buf, sizeof(buf), "mpic-msgr-block%d", index);
  121. prop = of_find_property(aliases, buf, NULL);
  122. if (node == of_find_node_by_path(prop->value))
  123. break;
  124. }
  125. return index == number_of_blocks ? -1 : index;
  126. }
  127. /* The probe function for a single message register block.
  128. */
  129. static __devinit int mpic_msgr_probe(struct platform_device *dev)
  130. {
  131. void __iomem *msgr_block_addr;
  132. int block_number;
  133. struct resource rsrc;
  134. unsigned int i;
  135. unsigned int irq_index;
  136. struct device_node *np = dev->dev.of_node;
  137. unsigned int receive_mask;
  138. const unsigned int *prop;
  139. if (!np) {
  140. dev_err(&dev->dev, "Device OF-Node is NULL");
  141. return -EFAULT;
  142. }
  143. /* Allocate the message register array upon the first device
  144. * registered.
  145. */
  146. if (!mpic_msgrs) {
  147. mpic_msgr_count = mpic_msgr_number_of_registers();
  148. dev_info(&dev->dev, "Found %d message registers\n",
  149. mpic_msgr_count);
  150. mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count,
  151. GFP_KERNEL);
  152. if (!mpic_msgrs) {
  153. dev_err(&dev->dev,
  154. "No memory for message register blocks\n");
  155. return -ENOMEM;
  156. }
  157. }
  158. dev_info(&dev->dev, "Of-device full name %s\n", np->full_name);
  159. /* IO map the message register block. */
  160. of_address_to_resource(np, 0, &rsrc);
  161. msgr_block_addr = ioremap(rsrc.start, rsrc.end - rsrc.start);
  162. if (!msgr_block_addr) {
  163. dev_err(&dev->dev, "Failed to iomap MPIC message registers");
  164. return -EFAULT;
  165. }
  166. /* Ensure the block has a defined order. */
  167. block_number = mpic_msgr_block_number(np);
  168. if (block_number < 0) {
  169. dev_err(&dev->dev,
  170. "Failed to find message register block alias\n");
  171. return -ENODEV;
  172. }
  173. dev_info(&dev->dev, "Setting up message register block %d\n",
  174. block_number);
  175. /* Grab the receive mask which specifies what registers can receive
  176. * interrupts.
  177. */
  178. prop = of_get_property(np, "mpic-msgr-receive-mask", NULL);
  179. receive_mask = (prop) ? *prop : 0xF;
  180. /* Build up the appropriate message register data structures. */
  181. for (i = 0, irq_index = 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i) {
  182. struct mpic_msgr *msgr;
  183. unsigned int reg_number;
  184. msgr = kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL);
  185. if (!msgr) {
  186. dev_err(&dev->dev, "No memory for message register\n");
  187. return -ENOMEM;
  188. }
  189. reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
  190. msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
  191. msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
  192. msgr->in_use = MSGR_FREE;
  193. msgr->num = i;
  194. raw_spin_lock_init(&msgr->lock);
  195. if (receive_mask & (1 << i)) {
  196. struct resource irq;
  197. if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) {
  198. dev_err(&dev->dev,
  199. "Missing interrupt specifier");
  200. kfree(msgr);
  201. return -EFAULT;
  202. }
  203. msgr->irq = irq.start;
  204. irq_index += 1;
  205. } else {
  206. msgr->irq = NO_IRQ;
  207. }
  208. mpic_msgrs[reg_number] = msgr;
  209. mpic_msgr_disable(msgr);
  210. dev_info(&dev->dev, "Register %d initialized: irq %d\n",
  211. reg_number, msgr->irq);
  212. }
  213. return 0;
  214. }
  215. static const struct of_device_id mpic_msgr_ids[] = {
  216. {
  217. .compatible = "fsl,mpic-v3.1-msgr",
  218. .data = NULL,
  219. },
  220. {}
  221. };
  222. static struct platform_driver mpic_msgr_driver = {
  223. .driver = {
  224. .name = "mpic-msgr",
  225. .owner = THIS_MODULE,
  226. .of_match_table = mpic_msgr_ids,
  227. },
  228. .probe = mpic_msgr_probe,
  229. };
  230. static __init int mpic_msgr_init(void)
  231. {
  232. return platform_driver_register(&mpic_msgr_driver);
  233. }
  234. subsys_initcall(mpic_msgr_init);