intc2.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. defined(CONFIG_CPU_SUBTYPE_SH7785)
  22. #define INTC2_BASE 0xffd40000
  23. #define INTC2_INTMSK (INTC2_BASE + 0x38)
  24. #define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
  25. #endif
  26. static void disable_intc2_irq(unsigned int irq)
  27. {
  28. struct intc2_data *p = get_irq_chip_data(irq);
  29. ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
  30. }
  31. static void enable_intc2_irq(unsigned int irq)
  32. {
  33. struct intc2_data *p = get_irq_chip_data(irq);
  34. ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
  35. }
  36. static struct irq_chip intc2_irq_chip = {
  37. .name = "INTC2",
  38. .mask = disable_intc2_irq,
  39. .unmask = enable_intc2_irq,
  40. .mask_ack = disable_intc2_irq,
  41. };
  42. /*
  43. * Setup an INTC2 style interrupt.
  44. * NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
  45. * allowing the use of the numbers straight out of the datasheet.
  46. * For example:
  47. * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
  48. * would be: ^ ^ ^ ^
  49. * | | | |
  50. * { 84, 0, 16, 0, 13 },
  51. *
  52. * in the intc2_data table.
  53. */
  54. void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
  55. {
  56. int i;
  57. for (i = 0; i < nr_irqs; i++) {
  58. unsigned long ipr, flags;
  59. struct intc2_data *p = table + i;
  60. disable_irq_nosync(p->irq);
  61. /* Set the priority level */
  62. local_irq_save(flags);
  63. ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
  64. ipr &= ~(0xf << p->ipr_shift);
  65. ipr |= p->priority << p->ipr_shift;
  66. ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
  67. local_irq_restore(flags);
  68. set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
  69. handle_level_irq, "level");
  70. set_irq_chip_data(p->irq, p);
  71. enable_intc2_irq(p->irq);
  72. }
  73. }