irq.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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/system.h>
  18. #include <asm/traps.h>
  19. #include <asm/io.h>
  20. #include <asm/setup.h>
  21. #include <asm/errno.h>
  22. /*#define DEBUG*/
  23. extern unsigned long *interrupt_redirect_table;
  24. extern const int h8300_saved_vectors[];
  25. extern const h8300_vector h8300_trap_table[];
  26. int h8300_enable_irq_pin(unsigned int irq);
  27. void h8300_disable_irq_pin(unsigned int irq);
  28. #define CPU_VECTOR ((unsigned long *)0x000000)
  29. #define ADDR_MASK (0xffffff)
  30. static inline int is_ext_irq(unsigned int irq)
  31. {
  32. return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
  33. }
  34. static void h8300_enable_irq(unsigned int irq)
  35. {
  36. if (is_ext_irq(irq))
  37. IER_REGS |= 1 << (irq - EXT_IRQ0);
  38. }
  39. static void h8300_disable_irq(unsigned int irq)
  40. {
  41. if (is_ext_irq(irq))
  42. IER_REGS &= ~(1 << (irq - EXT_IRQ0));
  43. }
  44. static void h8300_end_irq(unsigned int irq)
  45. {
  46. }
  47. static unsigned int h8300_startup_irq(unsigned int irq)
  48. {
  49. if (is_ext_irq(irq))
  50. return h8300_enable_irq_pin(irq);
  51. else
  52. return 0;
  53. }
  54. static void h8300_shutdown_irq(unsigned int irq)
  55. {
  56. if (is_ext_irq(irq))
  57. h8300_disable_irq_pin(irq);
  58. }
  59. /*
  60. * h8300 interrupt controller implementation
  61. */
  62. struct irq_chip h8300irq_chip = {
  63. .name = "H8300-INTC",
  64. .startup = h8300_startup_irq,
  65. .shutdown = h8300_shutdown_irq,
  66. .enable = h8300_enable_irq,
  67. .disable = h8300_disable_irq,
  68. .ack = NULL,
  69. .end = h8300_end_irq,
  70. };
  71. void ack_bad_irq(unsigned int irq)
  72. {
  73. printk("unexpected IRQ trap at vector %02x\n", irq);
  74. }
  75. #if defined(CONFIG_RAMKERNEL)
  76. static unsigned long __init *get_vector_address(void)
  77. {
  78. unsigned long *rom_vector = CPU_VECTOR;
  79. unsigned long base,tmp;
  80. int vec_no;
  81. base = rom_vector[EXT_IRQ0] & ADDR_MASK;
  82. /* check romvector format */
  83. for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
  84. if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
  85. return NULL;
  86. }
  87. /* ramvector base address */
  88. base -= EXT_IRQ0*4;
  89. /* writerble check */
  90. tmp = ~(*(volatile unsigned long *)base);
  91. (*(volatile unsigned long *)base) = tmp;
  92. if ((*(volatile unsigned long *)base) != tmp)
  93. return NULL;
  94. return (unsigned long *)base;
  95. }
  96. static void __init setup_vector(void)
  97. {
  98. int i;
  99. unsigned long *ramvec,*ramvec_p;
  100. const h8300_vector *trap_entry;
  101. const int *saved_vector;
  102. ramvec = get_vector_address();
  103. if (ramvec == NULL)
  104. panic("interrupt vector serup failed.");
  105. else
  106. printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
  107. /* create redirect table */
  108. ramvec_p = ramvec;
  109. trap_entry = h8300_trap_table;
  110. saved_vector = h8300_saved_vectors;
  111. for ( i = 0; i < NR_IRQS; i++) {
  112. if (i == *saved_vector) {
  113. ramvec_p++;
  114. saved_vector++;
  115. } else {
  116. if ( i < NR_TRAPS ) {
  117. if (*trap_entry)
  118. *ramvec_p = VECTOR(*trap_entry);
  119. ramvec_p++;
  120. trap_entry++;
  121. } else
  122. *ramvec_p++ = REDIRECT(interrupt_entry);
  123. }
  124. }
  125. interrupt_redirect_table = ramvec;
  126. #ifdef DEBUG
  127. ramvec_p = ramvec;
  128. for (i = 0; i < NR_IRQS; i++) {
  129. if ((i % 8) == 0)
  130. printk(KERN_DEBUG "\n%p: ",ramvec_p);
  131. printk(KERN_DEBUG "%p ",*ramvec_p);
  132. ramvec_p++;
  133. }
  134. printk(KERN_DEBUG "\n");
  135. #endif
  136. }
  137. #else
  138. #define setup_vector() do { } while(0)
  139. #endif
  140. void __init init_IRQ(void)
  141. {
  142. int c;
  143. setup_vector();
  144. for (c = 0; c < NR_IRQS; c++) {
  145. irq_desc[c].status = IRQ_DISABLED;
  146. irq_desc[c].action = NULL;
  147. irq_desc[c].depth = 1;
  148. irq_desc[c].chip = &h8300irq_chip;
  149. }
  150. }
  151. asmlinkage void do_IRQ(int irq)
  152. {
  153. irq_enter();
  154. __do_IRQ(irq);
  155. irq_exit();
  156. }
  157. #if defined(CONFIG_PROC_FS)
  158. int show_interrupts(struct seq_file *p, void *v)
  159. {
  160. int i = *(loff_t *) v;
  161. struct irqaction * action;
  162. unsigned long flags;
  163. if (i == 0)
  164. seq_puts(p, " CPU0");
  165. if (i < NR_IRQS) {
  166. spin_lock_irqsave(&irq_desc[i].lock, flags);
  167. action = irq_desc[i].action;
  168. if (!action)
  169. goto unlock;
  170. seq_printf(p, "%3d: ",i);
  171. seq_printf(p, "%10u ", kstat_irqs(i));
  172. seq_printf(p, " %14s", irq_desc[i].chip->name);
  173. seq_printf(p, "-%-8s", irq_desc[i].name);
  174. seq_printf(p, " %s", action->name);
  175. for (action=action->next; action; action = action->next)
  176. seq_printf(p, ", %s", action->name);
  177. seq_putc(p, '\n');
  178. unlock:
  179. spin_unlock_irqrestore(&irq_desc[i].lock, flags);
  180. }
  181. return 0;
  182. }
  183. #endif