irq.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * linux/arch/h8300/kernel/irq.c
  3. *
  4. * Copyright 2007 Yoshinori Sato <ysato@users.sourceforge.jp>
  5. */
  6. #include <linux/module.h>
  7. #include <linux/types.h>
  8. #include <linux/kernel.h>
  9. #include <linux/sched.h>
  10. #include <linux/kernel_stat.h>
  11. #include <linux/seq_file.h>
  12. #include <linux/init.h>
  13. #include <linux/random.h>
  14. #include <linux/bootmem.h>
  15. #include <linux/irq.h>
  16. #include <linux/interrupt.h>
  17. #include <asm/traps.h>
  18. #include <asm/io.h>
  19. #include <asm/setup.h>
  20. #include <asm/errno.h>
  21. /*#define DEBUG*/
  22. extern unsigned long *interrupt_redirect_table;
  23. extern const int h8300_saved_vectors[];
  24. extern const h8300_vector h8300_trap_table[];
  25. int h8300_enable_irq_pin(unsigned int irq);
  26. void h8300_disable_irq_pin(unsigned int irq);
  27. #define CPU_VECTOR ((unsigned long *)0x000000)
  28. #define ADDR_MASK (0xffffff)
  29. static inline int is_ext_irq(unsigned int irq)
  30. {
  31. return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
  32. }
  33. static void h8300_enable_irq(struct irq_data *data)
  34. {
  35. if (is_ext_irq(data->irq))
  36. IER_REGS |= 1 << (data->irq - EXT_IRQ0);
  37. }
  38. static void h8300_disable_irq(struct irq_data *data)
  39. {
  40. if (is_ext_irq(data->irq))
  41. IER_REGS &= ~(1 << (data->irq - EXT_IRQ0));
  42. }
  43. static unsigned int h8300_startup_irq(struct irq_data *data)
  44. {
  45. if (is_ext_irq(data->irq))
  46. return h8300_enable_irq_pin(data->irq);
  47. else
  48. return 0;
  49. }
  50. static void h8300_shutdown_irq(struct irq_data *data)
  51. {
  52. if (is_ext_irq(data->irq))
  53. h8300_disable_irq_pin(data->irq);
  54. }
  55. /*
  56. * h8300 interrupt controller implementation
  57. */
  58. struct irq_chip h8300irq_chip = {
  59. .name = "H8300-INTC",
  60. .irq_startup = h8300_startup_irq,
  61. .irq_shutdown = h8300_shutdown_irq,
  62. .irq_enable = h8300_enable_irq,
  63. .irq_disable = h8300_disable_irq,
  64. };
  65. #if defined(CONFIG_RAMKERNEL)
  66. static unsigned long __init *get_vector_address(void)
  67. {
  68. unsigned long *rom_vector = CPU_VECTOR;
  69. unsigned long base,tmp;
  70. int vec_no;
  71. base = rom_vector[EXT_IRQ0] & ADDR_MASK;
  72. /* check romvector format */
  73. for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
  74. if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
  75. return NULL;
  76. }
  77. /* ramvector base address */
  78. base -= EXT_IRQ0*4;
  79. /* writerble check */
  80. tmp = ~(*(volatile unsigned long *)base);
  81. (*(volatile unsigned long *)base) = tmp;
  82. if ((*(volatile unsigned long *)base) != tmp)
  83. return NULL;
  84. return (unsigned long *)base;
  85. }
  86. static void __init setup_vector(void)
  87. {
  88. int i;
  89. unsigned long *ramvec,*ramvec_p;
  90. const h8300_vector *trap_entry;
  91. const int *saved_vector;
  92. ramvec = get_vector_address();
  93. if (ramvec == NULL)
  94. panic("interrupt vector serup failed.");
  95. else
  96. printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
  97. /* create redirect table */
  98. ramvec_p = ramvec;
  99. trap_entry = h8300_trap_table;
  100. saved_vector = h8300_saved_vectors;
  101. for ( i = 0; i < NR_IRQS; i++) {
  102. if (i == *saved_vector) {
  103. ramvec_p++;
  104. saved_vector++;
  105. } else {
  106. if ( i < NR_TRAPS ) {
  107. if (*trap_entry)
  108. *ramvec_p = VECTOR(*trap_entry);
  109. ramvec_p++;
  110. trap_entry++;
  111. } else
  112. *ramvec_p++ = REDIRECT(interrupt_entry);
  113. }
  114. }
  115. interrupt_redirect_table = ramvec;
  116. #ifdef DEBUG
  117. ramvec_p = ramvec;
  118. for (i = 0; i < NR_IRQS; i++) {
  119. if ((i % 8) == 0)
  120. printk(KERN_DEBUG "\n%p: ",ramvec_p);
  121. printk(KERN_DEBUG "%p ",*ramvec_p);
  122. ramvec_p++;
  123. }
  124. printk(KERN_DEBUG "\n");
  125. #endif
  126. }
  127. #else
  128. #define setup_vector() do { } while(0)
  129. #endif
  130. void __init init_IRQ(void)
  131. {
  132. int c;
  133. setup_vector();
  134. for (c = 0; c < NR_IRQS; c++)
  135. irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
  136. }
  137. asmlinkage void do_IRQ(int irq)
  138. {
  139. irq_enter();
  140. generic_handle_irq(irq);
  141. irq_exit();
  142. }