ints.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/delay.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/irq.h>
  5. #include <linux/kernel.h>
  6. #include <linux/sched.h>
  7. #include <linux/sched/debug.h>
  8. #include <linux/types.h>
  9. #include <linux/ioport.h>
  10. #include <asm/hwtest.h>
  11. #include <asm/irq.h>
  12. #include <asm/irq_regs.h>
  13. #include <asm/processor.h>
  14. #include <asm/virt.h>
  15. #define GFPIC_REG_IRQ_PENDING 0x04
  16. #define GFPIC_REG_IRQ_DISABLE_ALL 0x08
  17. #define GFPIC_REG_IRQ_DISABLE 0x0c
  18. #define GFPIC_REG_IRQ_ENABLE 0x10
  19. static struct resource picres[6];
  20. static const char *picname[6] = {
  21. "goldfish_pic.0",
  22. "goldfish_pic.1",
  23. "goldfish_pic.2",
  24. "goldfish_pic.3",
  25. "goldfish_pic.4",
  26. "goldfish_pic.5"
  27. };
  28. /*
  29. * 6 goldfish-pic for CPU IRQ #1 to IRQ #6
  30. * CPU IRQ #1 -> PIC #1
  31. * IRQ #1 to IRQ #31 -> unused
  32. * IRQ #32 -> goldfish-tty
  33. * CPU IRQ #2 -> PIC #2
  34. * IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
  35. * CPU IRQ #3 -> PIC #3
  36. * IRQ #1 to IRQ #32 -> virtio-mmio from 33 to 64
  37. * CPU IRQ #4 -> PIC #4
  38. * IRQ #1 to IRQ #32 -> virtio-mmio from 65 to 96
  39. * CPU IRQ #5 -> PIC #5
  40. * IRQ #1 to IRQ #32 -> virtio-mmio from 97 to 128
  41. * CPU IRQ #6 -> PIC #6
  42. * IRQ #1 -> goldfish-timer
  43. * IRQ #2 -> goldfish-rtc
  44. * IRQ #3 to IRQ #32 -> unused
  45. * CPU IRQ #7 -> NMI
  46. */
  47. static u32 gfpic_read(int pic, int reg)
  48. {
  49. void __iomem *base = (void __iomem *)(virt_bi_data.pic.mmio +
  50. pic * 0x1000);
  51. return ioread32be(base + reg);
  52. }
  53. static void gfpic_write(u32 value, int pic, int reg)
  54. {
  55. void __iomem *base = (void __iomem *)(virt_bi_data.pic.mmio +
  56. pic * 0x1000);
  57. iowrite32be(value, base + reg);
  58. }
  59. #define GF_PIC(irq) ((irq - IRQ_USER) / 32)
  60. #define GF_IRQ(irq) ((irq - IRQ_USER) % 32)
  61. static void virt_irq_enable(struct irq_data *data)
  62. {
  63. gfpic_write(BIT(GF_IRQ(data->irq)), GF_PIC(data->irq),
  64. GFPIC_REG_IRQ_ENABLE);
  65. }
  66. static void virt_irq_disable(struct irq_data *data)
  67. {
  68. gfpic_write(BIT(GF_IRQ(data->irq)), GF_PIC(data->irq),
  69. GFPIC_REG_IRQ_DISABLE);
  70. }
  71. static unsigned int virt_irq_startup(struct irq_data *data)
  72. {
  73. virt_irq_enable(data);
  74. return 0;
  75. }
  76. static irqreturn_t virt_nmi_handler(int irq, void *dev_id)
  77. {
  78. static int in_nmi;
  79. if (READ_ONCE(in_nmi))
  80. return IRQ_HANDLED;
  81. WRITE_ONCE(in_nmi, 1);
  82. pr_warn("Non-Maskable Interrupt\n");
  83. show_registers(get_irq_regs());
  84. WRITE_ONCE(in_nmi, 0);
  85. return IRQ_HANDLED;
  86. }
  87. static struct irq_chip virt_irq_chip = {
  88. .name = "virt",
  89. .irq_enable = virt_irq_enable,
  90. .irq_disable = virt_irq_disable,
  91. .irq_startup = virt_irq_startup,
  92. .irq_shutdown = virt_irq_disable,
  93. };
  94. static void goldfish_pic_irq(struct irq_desc *desc)
  95. {
  96. u32 irq_pending;
  97. unsigned int irq_num;
  98. unsigned int pic = desc->irq_data.irq - 1;
  99. irq_pending = gfpic_read(pic, GFPIC_REG_IRQ_PENDING);
  100. irq_num = IRQ_USER + pic * 32;
  101. do {
  102. if (irq_pending & 1)
  103. generic_handle_irq(irq_num);
  104. ++irq_num;
  105. irq_pending >>= 1;
  106. } while (irq_pending);
  107. }
  108. void __init virt_init_IRQ(void)
  109. {
  110. unsigned int i;
  111. m68k_setup_irq_controller(&virt_irq_chip, handle_simple_irq, IRQ_USER,
  112. NUM_VIRT_SOURCES - IRQ_USER);
  113. for (i = 0; i < 6; i++) {
  114. picres[i] = (struct resource)
  115. DEFINE_RES_MEM_NAMED(virt_bi_data.pic.mmio + i * 0x1000,
  116. 0x1000, picname[i]);
  117. if (request_resource(&iomem_resource, &picres[i])) {
  118. pr_err("Cannot allocate %s resource\n", picname[i]);
  119. return;
  120. }
  121. irq_set_chained_handler(virt_bi_data.pic.irq + i,
  122. goldfish_pic_irq);
  123. }
  124. if (request_irq(IRQ_AUTO_7, virt_nmi_handler, 0, "NMI",
  125. virt_nmi_handler))
  126. pr_err("Couldn't register NMI\n");
  127. }