leon_kernel.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
  3. * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/errno.h>
  8. #include <linux/mutex.h>
  9. #include <linux/slab.h>
  10. #include <linux/of.h>
  11. #include <linux/of_platform.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/of_device.h>
  14. #include <asm/oplib.h>
  15. #include <asm/timer.h>
  16. #include <asm/prom.h>
  17. #include <asm/leon.h>
  18. #include <asm/leon_amba.h>
  19. #include "prom.h"
  20. #include "irq.h"
  21. struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */
  22. struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */
  23. struct amba_apb_device leon_percpu_timer_dev[16];
  24. int leondebug_irq_disable;
  25. int leon_debug_irqout;
  26. static int dummy_master_l10_counter;
  27. unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */
  28. unsigned int sparc_leon_eirq;
  29. #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
  30. /* Return the IRQ of the pending IRQ on the extended IRQ controller */
  31. int sparc_leon_eirq_get(int eirq, int cpu)
  32. {
  33. return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f;
  34. }
  35. irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id)
  36. {
  37. printk(KERN_ERR "sparc_leon_eirq_isr: ERROR EXTENDED IRQ\n");
  38. return IRQ_HANDLED;
  39. }
  40. /* The extended IRQ controller has been found, this function registers it */
  41. void sparc_leon_eirq_register(int eirq)
  42. {
  43. int irq;
  44. /* Register a "BAD" handler for this interrupt, it should never happen */
  45. irq = request_irq(eirq, sparc_leon_eirq_isr,
  46. (IRQF_DISABLED | SA_STATIC_ALLOC), "extirq", NULL);
  47. if (irq) {
  48. printk(KERN_ERR
  49. "sparc_leon_eirq_register: unable to attach IRQ%d\n",
  50. eirq);
  51. } else {
  52. sparc_leon_eirq = eirq;
  53. }
  54. }
  55. static inline unsigned long get_irqmask(unsigned int irq)
  56. {
  57. unsigned long mask;
  58. if (!irq || ((irq > 0xf) && !sparc_leon_eirq)
  59. || ((irq > 0x1f) && sparc_leon_eirq)) {
  60. printk(KERN_ERR
  61. "leon_get_irqmask: false irq number: %d\n", irq);
  62. mask = 0;
  63. } else {
  64. mask = LEON_HARD_INT(irq);
  65. }
  66. return mask;
  67. }
  68. static void leon_enable_irq(unsigned int irq_nr)
  69. {
  70. unsigned long mask, flags;
  71. mask = get_irqmask(irq_nr);
  72. local_irq_save(flags);
  73. LEON3_BYPASS_STORE_PA(LEON_IMASK,
  74. (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask)));
  75. local_irq_restore(flags);
  76. }
  77. static void leon_disable_irq(unsigned int irq_nr)
  78. {
  79. unsigned long mask, flags;
  80. mask = get_irqmask(irq_nr);
  81. local_irq_save(flags);
  82. LEON3_BYPASS_STORE_PA(LEON_IMASK,
  83. (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask)));
  84. local_irq_restore(flags);
  85. }
  86. void __init leon_init_timers(irq_handler_t counter_fn)
  87. {
  88. int irq;
  89. leondebug_irq_disable = 0;
  90. leon_debug_irqout = 0;
  91. master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
  92. dummy_master_l10_counter = 0;
  93. if (leon3_gptimer_regs && leon3_irqctrl_regs) {
  94. LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
  95. LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
  96. (((1000000 / 100) - 1)));
  97. LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
  98. } else {
  99. printk(KERN_ERR "No Timer/irqctrl found\n");
  100. BUG();
  101. }
  102. irq = request_irq(leon3_gptimer_irq,
  103. counter_fn,
  104. (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
  105. if (irq) {
  106. printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n",
  107. LEON_INTERRUPT_TIMER1);
  108. prom_halt();
  109. }
  110. if (leon3_gptimer_regs) {
  111. LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl,
  112. LEON3_GPTIMER_EN |
  113. LEON3_GPTIMER_RL |
  114. LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
  115. }
  116. }
  117. void leon_clear_clock_irq(void)
  118. {
  119. }
  120. void leon_load_profile_irq(int cpu, unsigned int limit)
  121. {
  122. BUG();
  123. }
  124. void __init leon_trans_init(struct device_node *dp)
  125. {
  126. if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) {
  127. struct property *p;
  128. p = of_find_property(dp, "mid", (void *)0);
  129. if (p) {
  130. int mid;
  131. dp->name = prom_early_alloc(5 + 1);
  132. memcpy(&mid, p->value, p->length);
  133. sprintf((char *)dp->name, "cpu%.2d", mid);
  134. }
  135. }
  136. }
  137. void __initdata (*prom_amba_init)(struct device_node *dp, struct device_node ***nextp) = 0;
  138. void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
  139. {
  140. if (prom_amba_init &&
  141. strcmp(dp->type, "ambapp") == 0 &&
  142. strcmp(dp->name, "ambapp0") == 0) {
  143. prom_amba_init(dp, nextp);
  144. }
  145. }
  146. void __init leon_init_IRQ(void)
  147. {
  148. sparc_init_timers = leon_init_timers;
  149. BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM);
  150. BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM);
  151. BTFIXUPSET_CALL(enable_pil_irq, leon_enable_irq, BTFIXUPCALL_NORM);
  152. BTFIXUPSET_CALL(disable_pil_irq, leon_disable_irq, BTFIXUPCALL_NORM);
  153. BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq,
  154. BTFIXUPCALL_NORM);
  155. BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq,
  156. BTFIXUPCALL_NOP);
  157. #ifdef CONFIG_SMP
  158. BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM);
  159. BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM);
  160. BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM);
  161. #endif
  162. }
  163. void __init leon_init(void)
  164. {
  165. prom_build_more = &leon_node_init;
  166. }