irq-pic32-evic.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Cristian Birsan <cristian.birsan@microchip.com>
  3. * Joshua Henderson <joshua.henderson@microchip.com>
  4. * Copyright (C) 2016 Microchip Technology Inc. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or (at your
  9. * option) any later version.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/irqdomain.h>
  15. #include <linux/of_address.h>
  16. #include <linux/slab.h>
  17. #include <linux/io.h>
  18. #include <linux/irqchip.h>
  19. #include <linux/irq.h>
  20. #include <asm/irq.h>
  21. #include <asm/traps.h>
  22. #include <asm/mach-pic32/pic32.h>
  23. #define REG_INTCON 0x0000
  24. #define REG_INTSTAT 0x0020
  25. #define REG_IFS_OFFSET 0x0040
  26. #define REG_IEC_OFFSET 0x00C0
  27. #define REG_IPC_OFFSET 0x0140
  28. #define REG_OFF_OFFSET 0x0540
  29. #define MAJPRI_MASK 0x07
  30. #define SUBPRI_MASK 0x03
  31. #define PRIORITY_MASK 0x1F
  32. #define PIC32_INT_PRI(pri, subpri) \
  33. ((((pri) & MAJPRI_MASK) << 2) | ((subpri) & SUBPRI_MASK))
  34. struct evic_chip_data {
  35. u32 irq_types[NR_IRQS];
  36. u32 ext_irqs[8];
  37. };
  38. static struct irq_domain *evic_irq_domain;
  39. static void __iomem *evic_base;
  40. asmlinkage void __weak plat_irq_dispatch(void)
  41. {
  42. unsigned int irq, hwirq;
  43. hwirq = readl(evic_base + REG_INTSTAT) & 0xFF;
  44. irq = irq_linear_revmap(evic_irq_domain, hwirq);
  45. do_IRQ(irq);
  46. }
  47. static struct evic_chip_data *irqd_to_priv(struct irq_data *data)
  48. {
  49. return (struct evic_chip_data *)data->domain->host_data;
  50. }
  51. static int pic32_set_ext_polarity(int bit, u32 type)
  52. {
  53. /*
  54. * External interrupts can be either edge rising or edge falling,
  55. * but not both.
  56. */
  57. switch (type) {
  58. case IRQ_TYPE_EDGE_RISING:
  59. writel(BIT(bit), evic_base + PIC32_SET(REG_INTCON));
  60. break;
  61. case IRQ_TYPE_EDGE_FALLING:
  62. writel(BIT(bit), evic_base + PIC32_CLR(REG_INTCON));
  63. break;
  64. default:
  65. return -EINVAL;
  66. }
  67. return 0;
  68. }
  69. static int pic32_set_type_edge(struct irq_data *data,
  70. unsigned int flow_type)
  71. {
  72. struct evic_chip_data *priv = irqd_to_priv(data);
  73. int ret;
  74. int i;
  75. if (!(flow_type & IRQ_TYPE_EDGE_BOTH))
  76. return -EBADR;
  77. /* set polarity for external interrupts only */
  78. for (i = 0; i < ARRAY_SIZE(priv->ext_irqs); i++) {
  79. if (priv->ext_irqs[i] == data->hwirq) {
  80. ret = pic32_set_ext_polarity(i, flow_type);
  81. if (ret)
  82. return ret;
  83. }
  84. }
  85. irqd_set_trigger_type(data, flow_type);
  86. return IRQ_SET_MASK_OK;
  87. }
  88. static void pic32_bind_evic_interrupt(int irq, int set)
  89. {
  90. writel(set, evic_base + REG_OFF_OFFSET + irq * 4);
  91. }
  92. static void pic32_set_irq_priority(int irq, int priority)
  93. {
  94. u32 reg, shift;
  95. reg = irq / 4;
  96. shift = (irq % 4) * 8;
  97. writel(PRIORITY_MASK << shift,
  98. evic_base + PIC32_CLR(REG_IPC_OFFSET + reg * 0x10));
  99. writel(priority << shift,
  100. evic_base + PIC32_SET(REG_IPC_OFFSET + reg * 0x10));
  101. }
  102. #define IRQ_REG_MASK(_hwirq, _reg, _mask) \
  103. do { \
  104. _reg = _hwirq / 32; \
  105. _mask = 1 << (_hwirq % 32); \
  106. } while (0)
  107. static int pic32_irq_domain_map(struct irq_domain *d, unsigned int virq,
  108. irq_hw_number_t hw)
  109. {
  110. struct evic_chip_data *priv = d->host_data;
  111. struct irq_data *data;
  112. int ret;
  113. u32 iecclr, ifsclr;
  114. u32 reg, mask;
  115. ret = irq_map_generic_chip(d, virq, hw);
  116. if (ret)
  117. return ret;
  118. /*
  119. * Piggyback on xlate function to move to an alternate chip as necessary
  120. * at time of mapping instead of allowing the flow handler/chip to be
  121. * changed later. This requires all interrupts to be configured through
  122. * DT.
  123. */
  124. if (priv->irq_types[hw] & IRQ_TYPE_SENSE_MASK) {
  125. data = irq_domain_get_irq_data(d, virq);
  126. irqd_set_trigger_type(data, priv->irq_types[hw]);
  127. irq_setup_alt_chip(data, priv->irq_types[hw]);
  128. }
  129. IRQ_REG_MASK(hw, reg, mask);
  130. iecclr = PIC32_CLR(REG_IEC_OFFSET + reg * 0x10);
  131. ifsclr = PIC32_CLR(REG_IFS_OFFSET + reg * 0x10);
  132. /* mask and clear flag */
  133. writel(mask, evic_base + iecclr);
  134. writel(mask, evic_base + ifsclr);
  135. /* default priority is required */
  136. pic32_set_irq_priority(hw, PIC32_INT_PRI(2, 0));
  137. return ret;
  138. }
  139. int pic32_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
  140. const u32 *intspec, unsigned int intsize,
  141. irq_hw_number_t *out_hwirq, unsigned int *out_type)
  142. {
  143. struct evic_chip_data *priv = d->host_data;
  144. if (WARN_ON(intsize < 2))
  145. return -EINVAL;
  146. if (WARN_ON(intspec[0] >= NR_IRQS))
  147. return -EINVAL;
  148. *out_hwirq = intspec[0];
  149. *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
  150. priv->irq_types[intspec[0]] = intspec[1] & IRQ_TYPE_SENSE_MASK;
  151. return 0;
  152. }
  153. static const struct irq_domain_ops pic32_irq_domain_ops = {
  154. .map = pic32_irq_domain_map,
  155. .xlate = pic32_irq_domain_xlate,
  156. };
  157. static void __init pic32_ext_irq_of_init(struct irq_domain *domain)
  158. {
  159. struct device_node *node = irq_domain_get_of_node(domain);
  160. struct evic_chip_data *priv = domain->host_data;
  161. struct property *prop;
  162. const __le32 *p;
  163. u32 hwirq;
  164. int i = 0;
  165. const char *pname = "microchip,external-irqs";
  166. of_property_for_each_u32(node, pname, prop, p, hwirq) {
  167. if (i >= ARRAY_SIZE(priv->ext_irqs)) {
  168. pr_warn("More than %d external irq, skip rest\n",
  169. ARRAY_SIZE(priv->ext_irqs));
  170. break;
  171. }
  172. priv->ext_irqs[i] = hwirq;
  173. i++;
  174. }
  175. }
  176. static int __init pic32_of_init(struct device_node *node,
  177. struct device_node *parent)
  178. {
  179. struct irq_chip_generic *gc;
  180. struct evic_chip_data *priv;
  181. unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
  182. int nchips, ret;
  183. int i;
  184. nchips = DIV_ROUND_UP(NR_IRQS, 32);
  185. evic_base = of_iomap(node, 0);
  186. if (!evic_base)
  187. return -ENOMEM;
  188. priv = kcalloc(nchips, sizeof(*priv), GFP_KERNEL);
  189. if (!priv) {
  190. ret = -ENOMEM;
  191. goto err_iounmap;
  192. }
  193. evic_irq_domain = irq_domain_add_linear(node, nchips * 32,
  194. &pic32_irq_domain_ops,
  195. priv);
  196. if (!evic_irq_domain) {
  197. ret = -ENOMEM;
  198. goto err_free_priv;
  199. }
  200. /*
  201. * The PIC32 EVIC has a linear list of irqs and the type of each
  202. * irq is determined by the hardware peripheral the EVIC is arbitrating.
  203. * These irq types are defined in the datasheet as "persistent" and
  204. * "non-persistent" which are mapped here to level and edge
  205. * respectively. To manage the different flow handler requirements of
  206. * each irq type, different chip_types are used.
  207. */
  208. ret = irq_alloc_domain_generic_chips(evic_irq_domain, 32, 2,
  209. "evic-level", handle_level_irq,
  210. clr, 0, 0);
  211. if (ret)
  212. goto err_domain_remove;
  213. board_bind_eic_interrupt = &pic32_bind_evic_interrupt;
  214. for (i = 0; i < nchips; i++) {
  215. u32 ifsclr = PIC32_CLR(REG_IFS_OFFSET + (i * 0x10));
  216. u32 iec = REG_IEC_OFFSET + (i * 0x10);
  217. gc = irq_get_domain_generic_chip(evic_irq_domain, i * 32);
  218. gc->reg_base = evic_base;
  219. gc->unused = 0;
  220. /*
  221. * Level/persistent interrupts have a special requirement that
  222. * the condition generating the interrupt be cleared before the
  223. * interrupt flag (ifs) can be cleared. chip.irq_eoi is used to
  224. * complete the interrupt with an ack.
  225. */
  226. gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
  227. gc->chip_types[0].handler = handle_fasteoi_irq;
  228. gc->chip_types[0].regs.ack = ifsclr;
  229. gc->chip_types[0].regs.mask = iec;
  230. gc->chip_types[0].chip.name = "evic-level";
  231. gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit;
  232. gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
  233. gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
  234. gc->chip_types[0].chip.flags = IRQCHIP_SKIP_SET_WAKE;
  235. /* Edge interrupts */
  236. gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
  237. gc->chip_types[1].handler = handle_edge_irq;
  238. gc->chip_types[1].regs.ack = ifsclr;
  239. gc->chip_types[1].regs.mask = iec;
  240. gc->chip_types[1].chip.name = "evic-edge";
  241. gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit;
  242. gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit;
  243. gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit;
  244. gc->chip_types[1].chip.irq_set_type = pic32_set_type_edge;
  245. gc->chip_types[1].chip.flags = IRQCHIP_SKIP_SET_WAKE;
  246. gc->private = &priv[i];
  247. }
  248. irq_set_default_host(evic_irq_domain);
  249. /*
  250. * External interrupts have software configurable edge polarity. These
  251. * interrupts are defined in DT allowing polarity to be configured only
  252. * for these interrupts when requested.
  253. */
  254. pic32_ext_irq_of_init(evic_irq_domain);
  255. return 0;
  256. err_domain_remove:
  257. irq_domain_remove(evic_irq_domain);
  258. err_free_priv:
  259. kfree(priv);
  260. err_iounmap:
  261. iounmap(evic_base);
  262. return ret;
  263. }
  264. IRQCHIP_DECLARE(pic32_evic, "microchip,pic32mzda-evic", pic32_of_init);