irq_srm.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /*
  2. * Handle interrupts from the SRM, assuming no additional weirdness.
  3. */
  4. #include <linux/init.h>
  5. #include <linux/sched.h>
  6. #include <linux/irq.h>
  7. #include "proto.h"
  8. #include "irq_impl.h"
  9. /*
  10. * Is the palcode SMP safe? In other words: can we call cserve_ena/dis
  11. * at the same time in multiple CPUs? To be safe I added a spinlock
  12. * but it can be removed trivially if the palcode is robust against smp.
  13. */
  14. DEFINE_SPINLOCK(srm_irq_lock);
  15. static inline void
  16. srm_enable_irq(unsigned int irq)
  17. {
  18. spin_lock(&srm_irq_lock);
  19. cserve_ena(irq - 16);
  20. spin_unlock(&srm_irq_lock);
  21. }
  22. static void
  23. srm_disable_irq(unsigned int irq)
  24. {
  25. spin_lock(&srm_irq_lock);
  26. cserve_dis(irq - 16);
  27. spin_unlock(&srm_irq_lock);
  28. }
  29. static unsigned int
  30. srm_startup_irq(unsigned int irq)
  31. {
  32. srm_enable_irq(irq);
  33. return 0;
  34. }
  35. static void
  36. srm_end_irq(unsigned int irq)
  37. {
  38. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  39. srm_enable_irq(irq);
  40. }
  41. /* Handle interrupts from the SRM, assuming no additional weirdness. */
  42. static struct hw_interrupt_type srm_irq_type = {
  43. .typename = "SRM",
  44. .startup = srm_startup_irq,
  45. .shutdown = srm_disable_irq,
  46. .enable = srm_enable_irq,
  47. .disable = srm_disable_irq,
  48. .ack = srm_disable_irq,
  49. .end = srm_end_irq,
  50. };
  51. void __init
  52. init_srm_irqs(long max, unsigned long ignore_mask)
  53. {
  54. long i;
  55. if (NR_IRQS <= 16)
  56. return;
  57. for (i = 16; i < max; ++i) {
  58. if (i < 64 && ((ignore_mask >> i) & 1))
  59. continue;
  60. irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
  61. irq_desc[i].chip = &srm_irq_type;
  62. }
  63. }
  64. void
  65. srm_device_interrupt(unsigned long vector)
  66. {
  67. int irq = (vector - 0x800) >> 4;
  68. handle_irq(irq);
  69. }