irq.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * linux/arch/h8300/kernel/irq.c
  3. *
  4. * Copyright 2014-2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  5. */
  6. #include <linux/init.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/irq.h>
  9. #include <linux/irqdomain.h>
  10. #include <linux/of_irq.h>
  11. #include <asm/traps.h>
  12. #ifdef CONFIG_RAMKERNEL
  13. typedef void (*h8300_vector)(void);
  14. static const h8300_vector __initconst trap_table[] = {
  15. 0, 0, 0, 0,
  16. _trace_break,
  17. 0, 0,
  18. _nmi,
  19. _system_call,
  20. 0, 0,
  21. _trace_break,
  22. };
  23. static unsigned long __init *get_vector_address(void)
  24. {
  25. unsigned long *rom_vector = CPU_VECTOR;
  26. unsigned long base, tmp;
  27. int vec_no;
  28. base = rom_vector[EXT_IRQ0] & ADDR_MASK;
  29. /* check romvector format */
  30. for (vec_no = EXT_IRQ0 + 1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
  31. if ((base+(vec_no - EXT_IRQ0)*4) !=
  32. (rom_vector[vec_no] & ADDR_MASK))
  33. return NULL;
  34. }
  35. /* ramvector base address */
  36. base -= EXT_IRQ0*4;
  37. /* writerble? */
  38. tmp = ~(*(volatile unsigned long *)base);
  39. (*(volatile unsigned long *)base) = tmp;
  40. if ((*(volatile unsigned long *)base) != tmp)
  41. return NULL;
  42. return (unsigned long *)base;
  43. }
  44. static void __init setup_vector(void)
  45. {
  46. int i;
  47. unsigned long *ramvec, *ramvec_p;
  48. const h8300_vector *trap_entry;
  49. ramvec = get_vector_address();
  50. if (ramvec == NULL)
  51. panic("interrupt vector serup failed.");
  52. else
  53. pr_debug("virtual vector at 0x%p\n", ramvec);
  54. /* create redirect table */
  55. ramvec_p = ramvec;
  56. trap_entry = trap_table;
  57. for (i = 0; i < NR_IRQS; i++) {
  58. if (i < 12) {
  59. if (*trap_entry)
  60. *ramvec_p = VECTOR(*trap_entry);
  61. ramvec_p++;
  62. trap_entry++;
  63. } else
  64. *ramvec_p++ = REDIRECT(_interrupt_entry);
  65. }
  66. _interrupt_redirect_table = ramvec;
  67. }
  68. #else
  69. void setup_vector(void)
  70. {
  71. /* noting do */
  72. }
  73. #endif
  74. void __init init_IRQ(void)
  75. {
  76. setup_vector();
  77. irqchip_init();
  78. }
  79. asmlinkage void do_IRQ(int irq)
  80. {
  81. irq_enter();
  82. generic_handle_irq(irq);
  83. irq_exit();
  84. }