irq-msc01.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * Copyright (c) 2004 MIPS Inc
  5. * Author: [email protected]
  6. *
  7. * Copyright (C) 2004, 06 Ralf Baechle <[email protected]>
  8. */
  9. #include <linux/interrupt.h>
  10. #include <linux/kernel.h>
  11. #include <linux/sched.h>
  12. #include <linux/kernel_stat.h>
  13. #include <asm/io.h>
  14. #include <asm/irq.h>
  15. #include <asm/msc01_ic.h>
  16. #include <asm/traps.h>
  17. static unsigned long _icctrl_msc;
  18. #define MSC01_IC_REG_BASE _icctrl_msc
  19. #define MSCIC_WRITE(reg, data) do { *(volatile u32 *)(reg) = data; } while (0)
  20. #define MSCIC_READ(reg, data) do { data = *(volatile u32 *)(reg); } while (0)
  21. static unsigned int irq_base;
  22. /* mask off an interrupt */
  23. static inline void mask_msc_irq(struct irq_data *d)
  24. {
  25. unsigned int irq = d->irq;
  26. if (irq < (irq_base + 32))
  27. MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
  28. else
  29. MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32));
  30. }
  31. /* unmask an interrupt */
  32. static inline void unmask_msc_irq(struct irq_data *d)
  33. {
  34. unsigned int irq = d->irq;
  35. if (irq < (irq_base + 32))
  36. MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
  37. else
  38. MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32));
  39. }
  40. /*
  41. * Masks and ACKs an IRQ
  42. */
  43. static void level_mask_and_ack_msc_irq(struct irq_data *d)
  44. {
  45. mask_msc_irq(d);
  46. if (!cpu_has_veic)
  47. MSCIC_WRITE(MSC01_IC_EOI, 0);
  48. }
  49. /*
  50. * Masks and ACKs an IRQ
  51. */
  52. static void edge_mask_and_ack_msc_irq(struct irq_data *d)
  53. {
  54. unsigned int irq = d->irq;
  55. mask_msc_irq(d);
  56. if (!cpu_has_veic)
  57. MSCIC_WRITE(MSC01_IC_EOI, 0);
  58. else {
  59. u32 r;
  60. MSCIC_READ(MSC01_IC_SUP+irq*8, r);
  61. MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
  62. MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
  63. }
  64. }
  65. /*
  66. * Interrupt handler for interrupts coming from SOC-it.
  67. */
  68. void ll_msc_irq(void)
  69. {
  70. unsigned int irq;
  71. /* read the interrupt vector register */
  72. MSCIC_READ(MSC01_IC_VEC, irq);
  73. if (irq < 64)
  74. do_IRQ(irq + irq_base);
  75. else {
  76. /* Ignore spurious interrupt */
  77. }
  78. }
  79. static void msc_bind_eic_interrupt(int irq, int set)
  80. {
  81. MSCIC_WRITE(MSC01_IC_RAMW,
  82. (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
  83. }
  84. static struct irq_chip msc_levelirq_type = {
  85. .name = "SOC-it-Level",
  86. .irq_ack = level_mask_and_ack_msc_irq,
  87. .irq_mask = mask_msc_irq,
  88. .irq_mask_ack = level_mask_and_ack_msc_irq,
  89. .irq_unmask = unmask_msc_irq,
  90. .irq_eoi = unmask_msc_irq,
  91. };
  92. static struct irq_chip msc_edgeirq_type = {
  93. .name = "SOC-it-Edge",
  94. .irq_ack = edge_mask_and_ack_msc_irq,
  95. .irq_mask = mask_msc_irq,
  96. .irq_mask_ack = edge_mask_and_ack_msc_irq,
  97. .irq_unmask = unmask_msc_irq,
  98. .irq_eoi = unmask_msc_irq,
  99. };
  100. void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
  101. {
  102. _icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
  103. /* Reset interrupt controller - initialises all registers to 0 */
  104. MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
  105. board_bind_eic_interrupt = &msc_bind_eic_interrupt;
  106. for (; nirq > 0; nirq--, imp++) {
  107. int n = imp->im_irq;
  108. switch (imp->im_type) {
  109. case MSC01_IRQ_EDGE:
  110. irq_set_chip_and_handler_name(irqbase + n,
  111. &msc_edgeirq_type,
  112. handle_edge_irq,
  113. "edge");
  114. if (cpu_has_veic)
  115. MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
  116. else
  117. MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
  118. break;
  119. case MSC01_IRQ_LEVEL:
  120. irq_set_chip_and_handler_name(irqbase + n,
  121. &msc_levelirq_type,
  122. handle_level_irq,
  123. "level");
  124. if (cpu_has_veic)
  125. MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
  126. else
  127. MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
  128. }
  129. }
  130. irq_base = irqbase;
  131. MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT); /* Enable interrupt generation */
  132. }