bast-irq.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // Copyright 2003-2005 Simtec Electronics
  4. // Ben Dooks <[email protected]>
  5. //
  6. // http://www.simtec.co.uk/products/EB2410ITX/
  7. #include <linux/init.h>
  8. #include <linux/module.h>
  9. #include <linux/ioport.h>
  10. #include <linux/device.h>
  11. #include <linux/io.h>
  12. #include <asm/irq.h>
  13. #include <asm/mach-types.h>
  14. #include <asm/mach/irq.h>
  15. #include "regs-irq.h"
  16. #include "irqs.h"
  17. #include "bast.h"
  18. #define irqdbf(x...)
  19. #define irqdbf2(x...)
  20. /* handle PC104 ISA interrupts from the system CPLD */
  21. /* table of ISA irq nos to the relevant mask... zero means
  22. * the irq is not implemented
  23. */
  24. static const unsigned char bast_pc104_irqmasks[] = {
  25. 0, /* 0 */
  26. 0, /* 1 */
  27. 0, /* 2 */
  28. 1, /* 3 */
  29. 0, /* 4 */
  30. 2, /* 5 */
  31. 0, /* 6 */
  32. 4, /* 7 */
  33. 0, /* 8 */
  34. 0, /* 9 */
  35. 8, /* 10 */
  36. 0, /* 11 */
  37. 0, /* 12 */
  38. 0, /* 13 */
  39. 0, /* 14 */
  40. 0, /* 15 */
  41. };
  42. static const unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 };
  43. static void
  44. bast_pc104_mask(struct irq_data *data)
  45. {
  46. unsigned long temp;
  47. temp = __raw_readb(BAST_VA_PC104_IRQMASK);
  48. temp &= ~bast_pc104_irqmasks[data->irq];
  49. __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
  50. }
  51. static void
  52. bast_pc104_maskack(struct irq_data *data)
  53. {
  54. struct irq_desc *desc = irq_to_desc(BAST_IRQ_ISA);
  55. bast_pc104_mask(data);
  56. desc->irq_data.chip->irq_ack(&desc->irq_data);
  57. }
  58. static void
  59. bast_pc104_unmask(struct irq_data *data)
  60. {
  61. unsigned long temp;
  62. temp = __raw_readb(BAST_VA_PC104_IRQMASK);
  63. temp |= bast_pc104_irqmasks[data->irq];
  64. __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
  65. }
  66. static struct irq_chip bast_pc104_chip = {
  67. .irq_mask = bast_pc104_mask,
  68. .irq_unmask = bast_pc104_unmask,
  69. .irq_ack = bast_pc104_maskack
  70. };
  71. static void bast_irq_pc104_demux(struct irq_desc *desc)
  72. {
  73. unsigned int stat;
  74. unsigned int irqno;
  75. int i;
  76. stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
  77. if (unlikely(stat == 0)) {
  78. /* ack if we get an irq with nothing (ie, startup) */
  79. desc->irq_data.chip->irq_ack(&desc->irq_data);
  80. } else {
  81. /* handle the IRQ */
  82. for (i = 0; stat != 0; i++, stat >>= 1) {
  83. if (stat & 1) {
  84. irqno = bast_pc104_irqs[i];
  85. generic_handle_irq(irqno);
  86. }
  87. }
  88. }
  89. }
  90. static __init int bast_irq_init(void)
  91. {
  92. unsigned int i;
  93. if (machine_is_bast()) {
  94. printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n");
  95. /* zap all the IRQs */
  96. __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
  97. irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux);
  98. /* register our IRQs */
  99. for (i = 0; i < 4; i++) {
  100. unsigned int irqno = bast_pc104_irqs[i];
  101. irq_set_chip_and_handler(irqno, &bast_pc104_chip,
  102. handle_level_irq);
  103. irq_clear_status_flags(irqno, IRQ_NOREQUEST);
  104. }
  105. }
  106. return 0;
  107. }
  108. arch_initcall(bast_irq_init);