i8259.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * i8259 interrupt controller driver.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. */
  9. #undef DEBUG
  10. #include <linux/init.h>
  11. #include <linux/ioport.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/kernel.h>
  14. #include <linux/delay.h>
  15. #include <asm/io.h>
  16. #include <asm/i8259.h>
  17. #include <asm/prom.h>
  18. static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */
  19. static unsigned char cached_8259[2] = { 0xff, 0xff };
  20. #define cached_A1 (cached_8259[0])
  21. #define cached_21 (cached_8259[1])
  22. static DEFINE_SPINLOCK(i8259_lock);
  23. static struct irq_host *i8259_host;
  24. /*
  25. * Acknowledge the IRQ using either the PCI host bridge's interrupt
  26. * acknowledge feature or poll. How i8259_init() is called determines
  27. * which is called. It should be noted that polling is broken on some
  28. * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
  29. */
  30. unsigned int i8259_irq(void)
  31. {
  32. int irq;
  33. int lock = 0;
  34. /* Either int-ack or poll for the IRQ */
  35. if (pci_intack)
  36. irq = readb(pci_intack);
  37. else {
  38. spin_lock(&i8259_lock);
  39. lock = 1;
  40. /* Perform an interrupt acknowledge cycle on controller 1. */
  41. outb(0x0C, 0x20); /* prepare for poll */
  42. irq = inb(0x20) & 7;
  43. if (irq == 2 ) {
  44. /*
  45. * Interrupt is cascaded so perform interrupt
  46. * acknowledge on controller 2.
  47. */
  48. outb(0x0C, 0xA0); /* prepare for poll */
  49. irq = (inb(0xA0) & 7) + 8;
  50. }
  51. }
  52. if (irq == 7) {
  53. /*
  54. * This may be a spurious interrupt.
  55. *
  56. * Read the interrupt status register (ISR). If the most
  57. * significant bit is not set then there is no valid
  58. * interrupt.
  59. */
  60. if (!pci_intack)
  61. outb(0x0B, 0x20); /* ISR register */
  62. if(~inb(0x20) & 0x80)
  63. irq = NO_IRQ;
  64. } else if (irq == 0xff)
  65. irq = NO_IRQ;
  66. if (lock)
  67. spin_unlock(&i8259_lock);
  68. return irq;
  69. }
  70. static void i8259_mask_and_ack_irq(unsigned int irq_nr)
  71. {
  72. unsigned long flags;
  73. spin_lock_irqsave(&i8259_lock, flags);
  74. if (irq_nr > 7) {
  75. cached_A1 |= 1 << (irq_nr-8);
  76. inb(0xA1); /* DUMMY */
  77. outb(cached_A1, 0xA1);
  78. outb(0x20, 0xA0); /* Non-specific EOI */
  79. outb(0x20, 0x20); /* Non-specific EOI to cascade */
  80. } else {
  81. cached_21 |= 1 << irq_nr;
  82. inb(0x21); /* DUMMY */
  83. outb(cached_21, 0x21);
  84. outb(0x20, 0x20); /* Non-specific EOI */
  85. }
  86. spin_unlock_irqrestore(&i8259_lock, flags);
  87. }
  88. static void i8259_set_irq_mask(int irq_nr)
  89. {
  90. outb(cached_A1,0xA1);
  91. outb(cached_21,0x21);
  92. }
  93. static void i8259_mask_irq(unsigned int irq_nr)
  94. {
  95. unsigned long flags;
  96. pr_debug("i8259_mask_irq(%d)\n", irq_nr);
  97. spin_lock_irqsave(&i8259_lock, flags);
  98. if (irq_nr < 8)
  99. cached_21 |= 1 << irq_nr;
  100. else
  101. cached_A1 |= 1 << (irq_nr-8);
  102. i8259_set_irq_mask(irq_nr);
  103. spin_unlock_irqrestore(&i8259_lock, flags);
  104. }
  105. static void i8259_unmask_irq(unsigned int irq_nr)
  106. {
  107. unsigned long flags;
  108. pr_debug("i8259_unmask_irq(%d)\n", irq_nr);
  109. spin_lock_irqsave(&i8259_lock, flags);
  110. if (irq_nr < 8)
  111. cached_21 &= ~(1 << irq_nr);
  112. else
  113. cached_A1 &= ~(1 << (irq_nr-8));
  114. i8259_set_irq_mask(irq_nr);
  115. spin_unlock_irqrestore(&i8259_lock, flags);
  116. }
  117. static struct irq_chip i8259_pic = {
  118. .typename = " i8259 ",
  119. .mask = i8259_mask_irq,
  120. .disable = i8259_mask_irq,
  121. .unmask = i8259_unmask_irq,
  122. .mask_ack = i8259_mask_and_ack_irq,
  123. };
  124. static struct resource pic1_iores = {
  125. .name = "8259 (master)",
  126. .start = 0x20,
  127. .end = 0x21,
  128. .flags = IORESOURCE_BUSY,
  129. };
  130. static struct resource pic2_iores = {
  131. .name = "8259 (slave)",
  132. .start = 0xa0,
  133. .end = 0xa1,
  134. .flags = IORESOURCE_BUSY,
  135. };
  136. static struct resource pic_edgectrl_iores = {
  137. .name = "8259 edge control",
  138. .start = 0x4d0,
  139. .end = 0x4d1,
  140. .flags = IORESOURCE_BUSY,
  141. };
  142. static int i8259_host_match(struct irq_host *h, struct device_node *node)
  143. {
  144. return h->of_node == NULL || h->of_node == node;
  145. }
  146. static int i8259_host_map(struct irq_host *h, unsigned int virq,
  147. irq_hw_number_t hw)
  148. {
  149. pr_debug("i8259_host_map(%d, 0x%lx)\n", virq, hw);
  150. /* We block the internal cascade */
  151. if (hw == 2)
  152. get_irq_desc(virq)->status |= IRQ_NOREQUEST;
  153. /* We use the level handler only for now, we might want to
  154. * be more cautious here but that works for now
  155. */
  156. get_irq_desc(virq)->status |= IRQ_LEVEL;
  157. set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq);
  158. return 0;
  159. }
  160. static void i8259_host_unmap(struct irq_host *h, unsigned int virq)
  161. {
  162. /* Make sure irq is masked in hardware */
  163. i8259_mask_irq(virq);
  164. /* remove chip and handler */
  165. set_irq_chip_and_handler(virq, NULL, NULL);
  166. /* Make sure it's completed */
  167. synchronize_irq(virq);
  168. }
  169. static int i8259_host_xlate(struct irq_host *h, struct device_node *ct,
  170. u32 *intspec, unsigned int intsize,
  171. irq_hw_number_t *out_hwirq, unsigned int *out_flags)
  172. {
  173. static unsigned char map_isa_senses[4] = {
  174. IRQ_TYPE_LEVEL_LOW,
  175. IRQ_TYPE_LEVEL_HIGH,
  176. IRQ_TYPE_EDGE_FALLING,
  177. IRQ_TYPE_EDGE_RISING,
  178. };
  179. *out_hwirq = intspec[0];
  180. if (intsize > 1 && intspec[1] < 4)
  181. *out_flags = map_isa_senses[intspec[1]];
  182. else
  183. *out_flags = IRQ_TYPE_NONE;
  184. return 0;
  185. }
  186. static struct irq_host_ops i8259_host_ops = {
  187. .match = i8259_host_match,
  188. .map = i8259_host_map,
  189. .unmap = i8259_host_unmap,
  190. .xlate = i8259_host_xlate,
  191. };
  192. struct irq_host *i8259_get_host(void)
  193. {
  194. return i8259_host;
  195. }
  196. /**
  197. * i8259_init - Initialize the legacy controller
  198. * @node: device node of the legacy PIC (can be NULL, but then, it will match
  199. * all interrupts, so beware)
  200. * @intack_addr: PCI interrupt acknowledge (real) address which will return
  201. * the active irq from the 8259
  202. */
  203. void i8259_init(struct device_node *node, unsigned long intack_addr)
  204. {
  205. unsigned long flags;
  206. /* initialize the controller */
  207. spin_lock_irqsave(&i8259_lock, flags);
  208. /* Mask all first */
  209. outb(0xff, 0xA1);
  210. outb(0xff, 0x21);
  211. /* init master interrupt controller */
  212. outb(0x11, 0x20); /* Start init sequence */
  213. outb(0x00, 0x21); /* Vector base */
  214. outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
  215. outb(0x01, 0x21); /* Select 8086 mode */
  216. /* init slave interrupt controller */
  217. outb(0x11, 0xA0); /* Start init sequence */
  218. outb(0x08, 0xA1); /* Vector base */
  219. outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
  220. outb(0x01, 0xA1); /* Select 8086 mode */
  221. /* That thing is slow */
  222. udelay(100);
  223. /* always read ISR */
  224. outb(0x0B, 0x20);
  225. outb(0x0B, 0xA0);
  226. /* Unmask the internal cascade */
  227. cached_21 &= ~(1 << 2);
  228. /* Set interrupt masks */
  229. outb(cached_A1, 0xA1);
  230. outb(cached_21, 0x21);
  231. spin_unlock_irqrestore(&i8259_lock, flags);
  232. /* create a legacy host */
  233. i8259_host = irq_alloc_host(node, IRQ_HOST_MAP_LEGACY,
  234. 0, &i8259_host_ops, 0);
  235. if (i8259_host == NULL) {
  236. printk(KERN_ERR "i8259: failed to allocate irq host !\n");
  237. return;
  238. }
  239. /* reserve our resources */
  240. /* XXX should we continue doing that ? it seems to cause problems
  241. * with further requesting of PCI IO resources for that range...
  242. * need to look into it.
  243. */
  244. request_resource(&ioport_resource, &pic1_iores);
  245. request_resource(&ioport_resource, &pic2_iores);
  246. request_resource(&ioport_resource, &pic_edgectrl_iores);
  247. if (intack_addr != 0)
  248. pci_intack = ioremap(intack_addr, 1);
  249. printk(KERN_INFO "i8259 legacy interrupt controller initialized\n");
  250. }