iop331-irq.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * linux/arch/arm/mach-iop3xx/iop331-irq.c
  3. *
  4. * Generic IOP331 IRQ handling functionality
  5. *
  6. * Author: Dave Jiang <dave.jiang@intel.com>
  7. * Copyright (C) 2003 Intel Corp.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. *
  14. */
  15. #include <linux/init.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/list.h>
  18. #include <asm/mach/irq.h>
  19. #include <asm/irq.h>
  20. #include <asm/hardware.h>
  21. #include <asm/mach-types.h>
  22. static u32 iop331_mask0 = 0;
  23. static u32 iop331_mask1 = 0;
  24. static inline void intctl_write0(u32 val)
  25. {
  26. // INTCTL0
  27. asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
  28. }
  29. static inline void intctl_write1(u32 val)
  30. {
  31. // INTCTL1
  32. asm volatile("mcr p6,0,%0,c1,c0,0"::"r" (val));
  33. }
  34. static inline void intstr_write0(u32 val)
  35. {
  36. // INTSTR0
  37. asm volatile("mcr p6,0,%0,c2,c0,0"::"r" (val));
  38. }
  39. static inline void intstr_write1(u32 val)
  40. {
  41. // INTSTR1
  42. asm volatile("mcr p6,0,%0,c3,c0,0"::"r" (val));
  43. }
  44. static void
  45. iop331_irq_mask1 (unsigned int irq)
  46. {
  47. iop331_mask0 &= ~(1 << (irq - IOP331_IRQ_OFS));
  48. intctl_write0(iop331_mask0);
  49. }
  50. static void
  51. iop331_irq_mask2 (unsigned int irq)
  52. {
  53. iop331_mask1 &= ~(1 << (irq - IOP331_IRQ_OFS - 32));
  54. intctl_write1(iop331_mask1);
  55. }
  56. static void
  57. iop331_irq_unmask1(unsigned int irq)
  58. {
  59. iop331_mask0 |= (1 << (irq - IOP331_IRQ_OFS));
  60. intctl_write0(iop331_mask0);
  61. }
  62. static void
  63. iop331_irq_unmask2(unsigned int irq)
  64. {
  65. iop331_mask1 |= (1 << (irq - IOP331_IRQ_OFS - 32));
  66. intctl_write1(iop331_mask1);
  67. }
  68. struct irqchip iop331_irqchip1 = {
  69. .ack = iop331_irq_mask1,
  70. .mask = iop331_irq_mask1,
  71. .unmask = iop331_irq_unmask1,
  72. };
  73. struct irqchip iop331_irqchip2 = {
  74. .ack = iop331_irq_mask2,
  75. .mask = iop331_irq_mask2,
  76. .unmask = iop331_irq_unmask2,
  77. };
  78. void __init iop331_init_irq(void)
  79. {
  80. unsigned int i, tmp;
  81. /* Enable access to coprocessor 6 for dealing with IRQs.
  82. * From RMK:
  83. * Basically, the Intel documentation here is poor. It appears that
  84. * you need to set the bit to be able to access the coprocessor from
  85. * SVC mode. Whether that allows access from user space or not is
  86. * unclear.
  87. */
  88. asm volatile (
  89. "mrc p15, 0, %0, c15, c1, 0\n\t"
  90. "orr %0, %0, %1\n\t"
  91. "mcr p15, 0, %0, c15, c1, 0\n\t"
  92. /* The action is delayed, so we have to do this: */
  93. "mrc p15, 0, %0, c15, c1, 0\n\t"
  94. "mov %0, %0\n\t"
  95. "sub pc, pc, #4"
  96. : "=r" (tmp) : "i" (1 << 6) );
  97. intctl_write0(0); // disable all interrupts
  98. intctl_write1(0);
  99. intstr_write0(0); // treat all as IRQ
  100. intstr_write1(0);
  101. if(machine_is_iq80331()) // all interrupts are inputs to chip
  102. *IOP331_PCIIRSR = 0x0f;
  103. for(i = IOP331_IRQ_OFS; i < NR_IOP331_IRQS; i++)
  104. {
  105. set_irq_chip(i, (i < 32) ? &iop331_irqchip1 : &iop331_irqchip2);
  106. set_irq_handler(i, do_level_IRQ);
  107. set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
  108. }
  109. }