intc2.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * Interrupt handling for INTC2-based IRQ.
  3. *
  4. * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
  5. * Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org)
  6. *
  7. * May be copied or modified under the terms of the GNU General Public
  8. * License. See linux/COPYING for more information.
  9. *
  10. * These are the "new Hitachi style" interrupts, as present on the
  11. * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/io.h>
  16. #if defined(CONFIG_CPU_SUBTYPE_SH7760)
  17. #define INTC2_BASE 0xfe080000
  18. #define INTC2_INTMSK (INTC2_BASE + 0x40)
  19. #define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
  20. #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
  21. #define INTC2_BASE 0xffd40000
  22. #define INTC2_INTMSK (INTC2_BASE + 0x38)
  23. #define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
  24. #endif
  25. static void disable_intc2_irq(unsigned int irq)
  26. {
  27. struct intc2_data *p = get_irq_chip_data(irq);
  28. ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
  29. }
  30. static void enable_intc2_irq(unsigned int irq)
  31. {
  32. struct intc2_data *p = get_irq_chip_data(irq);
  33. ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
  34. }
  35. static struct irq_chip intc2_irq_chip = {
  36. .name = "INTC2",
  37. .mask = disable_intc2_irq,
  38. .unmask = enable_intc2_irq,
  39. .mask_ack = disable_intc2_irq,
  40. };
  41. /*
  42. * Setup an INTC2 style interrupt.
  43. * NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
  44. * allowing the use of the numbers straight out of the datasheet.
  45. * For example:
  46. * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
  47. * would be: ^ ^ ^ ^
  48. * | | | |
  49. * { 84, 0, 16, 0, 13 },
  50. *
  51. * in the intc2_data table.
  52. */
  53. void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
  54. {
  55. int i;
  56. for (i = 0; i < nr_irqs; i++) {
  57. unsigned long ipr, flags;
  58. struct intc2_data *p = table + i;
  59. disable_irq_nosync(p->irq);
  60. /* Set the priority level */
  61. local_irq_save(flags);
  62. ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
  63. ipr &= ~(0xf << p->ipr_shift);
  64. ipr |= p->priority << p->ipr_shift;
  65. ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
  66. local_irq_restore(flags);
  67. set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
  68. handle_level_irq, "level");
  69. set_irq_chip_data(p->irq, p);
  70. enable_intc2_irq(p->irq);
  71. }
  72. }