irq.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. */
  9. #include <linux/interrupt.h>
  10. #include <linux/irq.h>
  11. #include <asm/irq_cpu.h>
  12. #include <loongson1.h>
  13. #include <irq.h>
  14. #define LS1X_INTC_REG(n, x) \
  15. ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x)))
  16. #define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0)
  17. #define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4)
  18. #define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8)
  19. #define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc)
  20. #define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10)
  21. #define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14)
  22. static void ls1x_irq_ack(struct irq_data *d)
  23. {
  24. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  25. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  26. __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
  27. | (1 << bit), LS1X_INTC_INTCLR(n));
  28. }
  29. static void ls1x_irq_mask(struct irq_data *d)
  30. {
  31. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  32. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  33. __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  34. & ~(1 << bit), LS1X_INTC_INTIEN(n));
  35. }
  36. static void ls1x_irq_mask_ack(struct irq_data *d)
  37. {
  38. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  39. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  40. __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  41. & ~(1 << bit), LS1X_INTC_INTIEN(n));
  42. __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
  43. | (1 << bit), LS1X_INTC_INTCLR(n));
  44. }
  45. static void ls1x_irq_unmask(struct irq_data *d)
  46. {
  47. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  48. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  49. __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  50. | (1 << bit), LS1X_INTC_INTIEN(n));
  51. }
  52. static struct irq_chip ls1x_irq_chip = {
  53. .name = "LS1X-INTC",
  54. .irq_ack = ls1x_irq_ack,
  55. .irq_mask = ls1x_irq_mask,
  56. .irq_mask_ack = ls1x_irq_mask_ack,
  57. .irq_unmask = ls1x_irq_unmask,
  58. };
  59. static void ls1x_irq_dispatch(int n)
  60. {
  61. u32 int_status, irq;
  62. /* Get pending sources, masked by current enables */
  63. int_status = __raw_readl(LS1X_INTC_INTISR(n)) &
  64. __raw_readl(LS1X_INTC_INTIEN(n));
  65. if (int_status) {
  66. irq = LS1X_IRQ(n, __ffs(int_status));
  67. do_IRQ(irq);
  68. }
  69. }
  70. asmlinkage void plat_irq_dispatch(void)
  71. {
  72. unsigned int pending;
  73. pending = read_c0_cause() & read_c0_status() & ST0_IM;
  74. if (pending & CAUSEF_IP7)
  75. do_IRQ(TIMER_IRQ);
  76. else if (pending & CAUSEF_IP2)
  77. ls1x_irq_dispatch(0); /* INT0 */
  78. else if (pending & CAUSEF_IP3)
  79. ls1x_irq_dispatch(1); /* INT1 */
  80. else if (pending & CAUSEF_IP4)
  81. ls1x_irq_dispatch(2); /* INT2 */
  82. else if (pending & CAUSEF_IP5)
  83. ls1x_irq_dispatch(3); /* INT3 */
  84. else if (pending & CAUSEF_IP6)
  85. ls1x_irq_dispatch(4); /* INT4 */
  86. else
  87. spurious_interrupt();
  88. }
  89. struct irqaction cascade_irqaction = {
  90. .handler = no_action,
  91. .name = "cascade",
  92. .flags = IRQF_NO_THREAD,
  93. };
  94. static void __init ls1x_irq_init(int base)
  95. {
  96. int n;
  97. /* Disable interrupts and clear pending,
  98. * setup all IRQs as high level triggered
  99. */
  100. for (n = 0; n < 4; n++) {
  101. __raw_writel(0x0, LS1X_INTC_INTIEN(n));
  102. __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n));
  103. __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n));
  104. /* set DMA0, DMA1 and DMA2 to edge trigger */
  105. __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n));
  106. }
  107. for (n = base; n < LS1X_IRQS; n++) {
  108. irq_set_chip_and_handler(n, &ls1x_irq_chip,
  109. handle_level_irq);
  110. }
  111. setup_irq(INT0_IRQ, &cascade_irqaction);
  112. setup_irq(INT1_IRQ, &cascade_irqaction);
  113. setup_irq(INT2_IRQ, &cascade_irqaction);
  114. setup_irq(INT3_IRQ, &cascade_irqaction);
  115. }
  116. void __init arch_init_irq(void)
  117. {
  118. mips_cpu_irq_init();
  119. ls1x_irq_init(LS1X_IRQ_BASE);
  120. }