irq.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * linux/arch/arm/mach-pxa/irq.c
  3. *
  4. * Generic PXA IRQ handling
  5. *
  6. * Author: Nicolas Pitre
  7. * Created: Jun 15, 2001
  8. * Copyright: MontaVista Software Inc.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/module.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/sysdev.h>
  18. #include <mach/hardware.h>
  19. #include <asm/irq.h>
  20. #include <asm/mach/irq.h>
  21. #include <mach/pxa-regs.h>
  22. #include "generic.h"
  23. #define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
  24. #define _ICMR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
  25. #define _ICLR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
  26. /*
  27. * This is for peripheral IRQs internal to the PXA chip.
  28. */
  29. static int pxa_internal_irq_nr;
  30. static void pxa_mask_irq(unsigned int irq)
  31. {
  32. _ICMR(irq) &= ~(1 << IRQ_BIT(irq));
  33. }
  34. static void pxa_unmask_irq(unsigned int irq)
  35. {
  36. _ICMR(irq) |= 1 << IRQ_BIT(irq);
  37. }
  38. static struct irq_chip pxa_internal_irq_chip = {
  39. .name = "SC",
  40. .ack = pxa_mask_irq,
  41. .mask = pxa_mask_irq,
  42. .unmask = pxa_unmask_irq,
  43. };
  44. void __init pxa_init_irq(int irq_nr, set_wake_t fn)
  45. {
  46. int irq;
  47. pxa_internal_irq_nr = irq_nr;
  48. for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq += 32) {
  49. _ICMR(irq) = 0; /* disable all IRQs */
  50. _ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */
  51. }
  52. /* only unmasked interrupts kick us out of idle */
  53. ICCR = 1;
  54. for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
  55. set_irq_chip(irq, &pxa_internal_irq_chip);
  56. set_irq_handler(irq, handle_level_irq);
  57. set_irq_flags(irq, IRQF_VALID);
  58. }
  59. pxa_internal_irq_chip.set_wake = fn;
  60. }
  61. #ifdef CONFIG_PM
  62. static unsigned long saved_icmr[2];
  63. static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
  64. {
  65. int i, irq = PXA_IRQ(0);
  66. for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
  67. saved_icmr[i] = _ICMR(irq);
  68. _ICMR(irq) = 0;
  69. }
  70. return 0;
  71. }
  72. static int pxa_irq_resume(struct sys_device *dev)
  73. {
  74. int i, irq = PXA_IRQ(0);
  75. for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
  76. _ICMR(irq) = saved_icmr[i];
  77. _ICLR(irq) = 0;
  78. }
  79. ICCR = 1;
  80. return 0;
  81. }
  82. #else
  83. #define pxa_irq_suspend NULL
  84. #define pxa_irq_resume NULL
  85. #endif
  86. struct sysdev_class pxa_irq_sysclass = {
  87. .name = "irq",
  88. .suspend = pxa_irq_suspend,
  89. .resume = pxa_irq_resume,
  90. };
  91. static int __init pxa_irq_init(void)
  92. {
  93. return sysdev_class_register(&pxa_irq_sysclass);
  94. }
  95. core_initcall(pxa_irq_init);