irq-metag.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Meta internal (HWSTATMETA) interrupt code.
  3. *
  4. * Copyright (C) 2011-2012 Imagination Technologies Ltd.
  5. *
  6. * This code is based on the code in SoC/common/irq.c and SoC/comet/irq.c
  7. * The code base could be generalised/merged as a lot of the functionality is
  8. * similar. Until this is done, we try to keep the code simple here.
  9. */
  10. #include <linux/interrupt.h>
  11. #include <linux/io.h>
  12. #include <linux/irqdomain.h>
  13. #include <asm/irq.h>
  14. #include <asm/hwthread.h>
  15. #define PERF0VECINT 0x04820580
  16. #define PERF1VECINT 0x04820588
  17. #define PERF0TRIG_OFFSET 16
  18. #define PERF1TRIG_OFFSET 17
  19. /**
  20. * struct metag_internal_irq_priv - private meta internal interrupt data
  21. * @domain: IRQ domain for all internal Meta IRQs (HWSTATMETA)
  22. * @unmasked: Record of unmasked IRQs
  23. */
  24. struct metag_internal_irq_priv {
  25. struct irq_domain *domain;
  26. unsigned long unmasked;
  27. };
  28. /* Private data for the one and only internal interrupt controller */
  29. static struct metag_internal_irq_priv metag_internal_irq_priv;
  30. static unsigned int metag_internal_irq_startup(struct irq_data *data);
  31. static void metag_internal_irq_shutdown(struct irq_data *data);
  32. static void metag_internal_irq_ack(struct irq_data *data);
  33. static void metag_internal_irq_mask(struct irq_data *data);
  34. static void metag_internal_irq_unmask(struct irq_data *data);
  35. #ifdef CONFIG_SMP
  36. static int metag_internal_irq_set_affinity(struct irq_data *data,
  37. const struct cpumask *cpumask, bool force);
  38. #endif
  39. static struct irq_chip internal_irq_edge_chip = {
  40. .name = "HWSTATMETA-IRQ",
  41. .irq_startup = metag_internal_irq_startup,
  42. .irq_shutdown = metag_internal_irq_shutdown,
  43. .irq_ack = metag_internal_irq_ack,
  44. .irq_mask = metag_internal_irq_mask,
  45. .irq_unmask = metag_internal_irq_unmask,
  46. #ifdef CONFIG_SMP
  47. .irq_set_affinity = metag_internal_irq_set_affinity,
  48. #endif
  49. };
  50. /*
  51. * metag_hwvec_addr - get the address of *VECINT regs of irq
  52. *
  53. * This function is a table of supported triggers on HWSTATMETA
  54. * Could do with a structure, but better keep it simple. Changes
  55. * in this code should be rare.
  56. */
  57. static inline void __iomem *metag_hwvec_addr(irq_hw_number_t hw)
  58. {
  59. void __iomem *addr;
  60. switch (hw) {
  61. case PERF0TRIG_OFFSET:
  62. addr = (void __iomem *)PERF0VECINT;
  63. break;
  64. case PERF1TRIG_OFFSET:
  65. addr = (void __iomem *)PERF1VECINT;
  66. break;
  67. default:
  68. addr = NULL;
  69. break;
  70. }
  71. return addr;
  72. }
  73. /*
  74. * metag_internal_startup - setup an internal irq
  75. * @irq: the irq to startup
  76. *
  77. * Multiplex interrupts for @irq onto TR1. Clear any pending
  78. * interrupts.
  79. */
  80. static unsigned int metag_internal_irq_startup(struct irq_data *data)
  81. {
  82. /* Clear (toggle) the bit in HWSTATMETA for our interrupt. */
  83. metag_internal_irq_ack(data);
  84. /* Enable the interrupt by unmasking it */
  85. metag_internal_irq_unmask(data);
  86. return 0;
  87. }
  88. /*
  89. * metag_internal_irq_shutdown - turn off the irq
  90. * @irq: the irq number to turn off
  91. *
  92. * Mask @irq and clear any pending interrupts.
  93. * Stop muxing @irq onto TR1.
  94. */
  95. static void metag_internal_irq_shutdown(struct irq_data *data)
  96. {
  97. /* Disable the IRQ at the core by masking it. */
  98. metag_internal_irq_mask(data);
  99. /* Clear (toggle) the bit in HWSTATMETA for our interrupt. */
  100. metag_internal_irq_ack(data);
  101. }
  102. /*
  103. * metag_internal_irq_ack - acknowledge irq
  104. * @irq: the irq to ack
  105. */
  106. static void metag_internal_irq_ack(struct irq_data *data)
  107. {
  108. irq_hw_number_t hw = data->hwirq;
  109. unsigned int bit = 1 << hw;
  110. if (metag_in32(HWSTATMETA) & bit)
  111. metag_out32(bit, HWSTATMETA);
  112. }
  113. /**
  114. * metag_internal_irq_mask() - mask an internal irq by unvectoring
  115. * @data: data for the internal irq to mask
  116. *
  117. * HWSTATMETA has no mask register. Instead the IRQ is unvectored from the core
  118. * and retriggered if necessary later.
  119. */
  120. static void metag_internal_irq_mask(struct irq_data *data)
  121. {
  122. struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
  123. irq_hw_number_t hw = data->hwirq;
  124. void __iomem *vec_addr = metag_hwvec_addr(hw);
  125. clear_bit(hw, &priv->unmasked);
  126. /* there is no interrupt mask, so unvector the interrupt */
  127. metag_out32(0, vec_addr);
  128. }
  129. /**
  130. * meta_intc_unmask_edge_irq_nomask() - unmask an edge irq by revectoring
  131. * @data: data for the internal irq to unmask
  132. *
  133. * HWSTATMETA has no mask register. Instead the IRQ is revectored back to the
  134. * core and retriggered if necessary.
  135. */
  136. static void metag_internal_irq_unmask(struct irq_data *data)
  137. {
  138. struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
  139. irq_hw_number_t hw = data->hwirq;
  140. unsigned int bit = 1 << hw;
  141. void __iomem *vec_addr = metag_hwvec_addr(hw);
  142. unsigned int thread = hard_processor_id();
  143. set_bit(hw, &priv->unmasked);
  144. /* there is no interrupt mask, so revector the interrupt */
  145. metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)), vec_addr);
  146. /*
  147. * Re-trigger interrupt
  148. *
  149. * Writing a 1 toggles, and a 0->1 transition triggers. We only
  150. * retrigger if the status bit is already set, which means we
  151. * need to clear it first. Retriggering is fundamentally racy
  152. * because if the interrupt fires again after we clear it we
  153. * could end up clearing it again and the interrupt handler
  154. * thinking it hasn't fired. Therefore we need to keep trying to
  155. * retrigger until the bit is set.
  156. */
  157. if (metag_in32(HWSTATMETA) & bit) {
  158. metag_out32(bit, HWSTATMETA);
  159. while (!(metag_in32(HWSTATMETA) & bit))
  160. metag_out32(bit, HWSTATMETA);
  161. }
  162. }
  163. #ifdef CONFIG_SMP
  164. /*
  165. * metag_internal_irq_set_affinity - set the affinity for an interrupt
  166. */
  167. static int metag_internal_irq_set_affinity(struct irq_data *data,
  168. const struct cpumask *cpumask, bool force)
  169. {
  170. unsigned int cpu, thread;
  171. irq_hw_number_t hw = data->hwirq;
  172. /*
  173. * Wire up this interrupt from *VECINT to the Meta core.
  174. *
  175. * Note that we can't wire up *VECINT to interrupt more than
  176. * one cpu (the interrupt code doesn't support it), so we just
  177. * pick the first cpu we find in 'cpumask'.
  178. */
  179. cpu = cpumask_any_and(cpumask, cpu_online_mask);
  180. thread = cpu_2_hwthread_id[cpu];
  181. metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)),
  182. metag_hwvec_addr(hw));
  183. return 0;
  184. }
  185. #endif
  186. /*
  187. * metag_internal_irq_demux - irq de-multiplexer
  188. * @irq: the interrupt number
  189. * @desc: the interrupt description structure for this irq
  190. *
  191. * The cpu receives an interrupt on TR1 when an interrupt has
  192. * occurred. It is this function's job to demux this irq and
  193. * figure out exactly which trigger needs servicing.
  194. */
  195. static void metag_internal_irq_demux(struct irq_desc *desc)
  196. {
  197. struct metag_internal_irq_priv *priv = irq_desc_get_handler_data(desc);
  198. irq_hw_number_t hw;
  199. unsigned int irq_no;
  200. u32 status;
  201. recalculate:
  202. status = metag_in32(HWSTATMETA) & priv->unmasked;
  203. for (hw = 0; status != 0; status >>= 1, ++hw) {
  204. if (status & 0x1) {
  205. /*
  206. * Map the hardware IRQ number to a virtual Linux IRQ
  207. * number.
  208. */
  209. irq_no = irq_linear_revmap(priv->domain, hw);
  210. /*
  211. * Only fire off interrupts that are
  212. * registered to be handled by the kernel.
  213. * Other interrupts are probably being
  214. * handled by other Meta hardware threads.
  215. */
  216. generic_handle_irq(irq_no);
  217. /*
  218. * The handler may have re-enabled interrupts
  219. * which could have caused a nested invocation
  220. * of this code and make the copy of the
  221. * status register we are using invalid.
  222. */
  223. goto recalculate;
  224. }
  225. }
  226. }
  227. /**
  228. * internal_irq_map() - Map an internal meta IRQ to a virtual IRQ number.
  229. * @hw: Number of the internal IRQ. Must be in range.
  230. *
  231. * Returns: The virtual IRQ number of the Meta internal IRQ specified by
  232. * @hw.
  233. */
  234. int internal_irq_map(unsigned int hw)
  235. {
  236. struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
  237. if (!priv->domain)
  238. return -ENODEV;
  239. return irq_create_mapping(priv->domain, hw);
  240. }
  241. /**
  242. * metag_internal_irq_init_cpu - regsister with the Meta cpu
  243. * @cpu: the CPU to register on
  244. *
  245. * Configure @cpu's TR1 irq so that we can demux irqs.
  246. */
  247. static void metag_internal_irq_init_cpu(struct metag_internal_irq_priv *priv,
  248. int cpu)
  249. {
  250. unsigned int thread = cpu_2_hwthread_id[cpu];
  251. unsigned int signum = TBID_SIGNUM_TR1(thread);
  252. int irq = tbisig_map(signum);
  253. /* Register the multiplexed IRQ handler */
  254. irq_set_chained_handler_and_data(irq, metag_internal_irq_demux, priv);
  255. irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
  256. }
  257. /**
  258. * metag_internal_intc_map() - map an internal irq
  259. * @d: irq domain of internal trigger block
  260. * @irq: virtual irq number
  261. * @hw: hardware irq number within internal trigger block
  262. *
  263. * This sets up a virtual irq for a specified hardware interrupt. The irq chip
  264. * and handler is configured.
  265. */
  266. static int metag_internal_intc_map(struct irq_domain *d, unsigned int irq,
  267. irq_hw_number_t hw)
  268. {
  269. /* only register interrupt if it is mapped */
  270. if (!metag_hwvec_addr(hw))
  271. return -EINVAL;
  272. irq_set_chip_and_handler(irq, &internal_irq_edge_chip,
  273. handle_edge_irq);
  274. return 0;
  275. }
  276. static const struct irq_domain_ops metag_internal_intc_domain_ops = {
  277. .map = metag_internal_intc_map,
  278. };
  279. /**
  280. * metag_internal_irq_register - register internal IRQs
  281. *
  282. * Register the irq chip and handler function for all internal IRQs
  283. */
  284. int __init init_internal_IRQ(void)
  285. {
  286. struct metag_internal_irq_priv *priv = &metag_internal_irq_priv;
  287. unsigned int cpu;
  288. /* Set up an IRQ domain */
  289. priv->domain = irq_domain_add_linear(NULL, 32,
  290. &metag_internal_intc_domain_ops,
  291. priv);
  292. if (unlikely(!priv->domain)) {
  293. pr_err("meta-internal-intc: cannot add IRQ domain\n");
  294. return -ENOMEM;
  295. }
  296. /* Setup TR1 for all cpus. */
  297. for_each_possible_cpu(cpu)
  298. metag_internal_irq_init_cpu(priv, cpu);
  299. return 0;
  300. };