3 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
6 * Detlev Zundel, DENX Software Engineering, dzu@denx.de
9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
12 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
14 * SPDX-License-Identifier: GPL-2.0+
17 #include <asm/stack.h>
20 #include <asm/processor.h>
27 /* 15 normal irqs and a non maskable interrupt */
31 interrupt_handler_t *handler;
36 extern ambapp_dev_irqmp *irqmp;
37 extern ambapp_dev_gptimer *gptimer;
39 static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
40 static int spurious_irq_cnt = 0;
41 static int spurious_irq = 0;
43 static inline unsigned int irqmp_get_irqmask(unsigned int irq)
45 if ((irq < 0) || (irq >= NR_IRQS)) {
53 static void leon3_ic_disable(unsigned int irq)
55 unsigned int mask, pil;
61 /* get mask of interrupt */
62 mask = irqmp_get_irqmask(irq);
65 irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) & (~mask);
70 static void leon3_ic_enable(unsigned int irq)
72 unsigned int mask, pil;
78 /* get mask of interrupt */
79 mask = irqmp_get_irqmask(irq);
82 irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) | mask;
88 void handler_irq(int irq, struct pt_regs *regs)
90 if (irq_handlers[irq].handler) {
91 if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
92 ((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
94 printf("handler_irq: bad handler: %x, irq number %d\n",
95 (unsigned int)irq_handlers[irq].handler, irq);
98 irq_handlers[irq].handler(irq_handlers[irq].arg);
99 irq_handlers[irq].count++;
106 void leon3_force_int(int irq)
108 if (!irqmp || (irq >= NR_IRQS) || (irq < 0))
110 printf("Forcing interrupt %d\n", irq);
112 irqmp->iforce = SPARC_NOCACHE_READ(&irqmp->iforce) | (1 << irq);
115 /****************************************************************************/
117 int interrupt_init_cpu(void)
123 /****************************************************************************/
125 /* Handle Timer 0 IRQ */
126 void timer_interrupt_cpu(void *arg)
128 gptimer->e[0].ctrl = (LEON3_GPTIMER_EN |
130 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
131 /* nothing to do here */
135 /****************************************************************************/
138 * Install and free a interrupt handler.
141 void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
143 if (irq < 0 || irq >= NR_IRQS) {
144 printf("irq_install_handler: bad irq number %d\n", irq);
148 if (irq_handlers[irq].handler != NULL)
149 printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
150 (ulong) handler, (ulong) irq_handlers[irq].handler);
152 if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
153 ((unsigned int)handler < CONFIG_SYS_RAM_BASE)
155 printf("irq_install_handler: bad handler: %x, irq number %d\n",
156 (unsigned int)handler, irq);
159 irq_handlers[irq].handler = handler;
160 irq_handlers[irq].arg = arg;
162 /* enable irq on IRQMP hardware */
163 leon3_ic_enable(irq);
167 void irq_free_handler(int irq)
169 if (irq < 0 || irq >= NR_IRQS) {
170 printf("irq_free_handler: bad irq number %d\n", irq);
174 /* disable irq on IRQMP hardware */
175 leon3_ic_disable(irq);
177 irq_handlers[irq].handler = NULL;
178 irq_handlers[irq].arg = NULL;
181 /****************************************************************************/
183 #if defined(CONFIG_CMD_IRQ)
184 void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
187 unsigned int pil = get_pil();
188 printf("PIL level: %u\n\r", pil);
189 printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
190 spurious_irq_cnt, spurious_irq);
192 puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n");
194 for (irq = 0; irq < NR_IRQS; irq++) {
195 if (irq_handlers[irq].handler != NULL) {
196 printf("%02d %p %p %d\n", irq,
197 irq_handlers[irq].handler,
198 irq_handlers[irq].arg,
199 irq_handlers[irq].count);