]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/sparc/cpu/leon3/interrupts.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / arch / sparc / cpu / leon3 / interrupts.c
CommitLineData
1e9a164e
DH
1/*
2 * (C) Copyright 2007
3 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
4 *
5 * (C) Copyright 2006
6 * Detlev Zundel, DENX Software Engineering, dzu@denx.de
7 *
8 * (C) Copyright -2003
9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10 *
11 * (C) Copyright 2001
12 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
13 *
1a459660 14 * SPDX-License-Identifier: GPL-2.0+
1e9a164e
DH
15 */
16
17#include <asm/stack.h>
18#include <common.h>
19#include <asm/io.h>
20#include <asm/processor.h>
21#include <command.h>
22#include <asm/irq.h>
23
24#include <asm/leon.h>
25#include <ambapp.h>
26
27/* 15 normal irqs and a non maskable interrupt */
28#define NR_IRQS 15
29
30struct irq_action {
31 interrupt_handler_t *handler;
32 void *arg;
33 unsigned int count;
34};
35
36extern ambapp_dev_irqmp *irqmp;
37extern ambapp_dev_gptimer *gptimer;
38
39static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
40static int spurious_irq_cnt = 0;
41static int spurious_irq = 0;
42
43static inline unsigned int irqmp_get_irqmask(unsigned int irq)
44{
45 if ((irq < 0) || (irq >= NR_IRQS)) {
46 return 0;
47 } else {
48 return (1 << irq);
49 }
50
51}
52
53static void leon3_ic_disable(unsigned int irq)
54{
55 unsigned int mask, pil;
56 if (!irqmp)
57 return;
58
59 pil = intLock();
60
61 /* get mask of interrupt */
62 mask = irqmp_get_irqmask(irq);
63
64 /* set int level */
65 irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) & (~mask);
66
67 intUnlock(pil);
68}
69
70static void leon3_ic_enable(unsigned int irq)
71{
72 unsigned int mask, pil;
73 if (!irqmp)
74 return;
75
76 pil = intLock();
77
78 /* get mask of interrupt */
79 mask = irqmp_get_irqmask(irq);
80
81 /* set int level */
82 irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) | mask;
83
84 intUnlock(pil);
85
86}
87
88void handler_irq(int irq, struct pt_regs *regs)
89{
90 if (irq_handlers[irq].handler) {
6d0f6bcf
JCPV
91 if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
92 ((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
1e9a164e
DH
93 ) {
94 printf("handler_irq: bad handler: %x, irq number %d\n",
95 (unsigned int)irq_handlers[irq].handler, irq);
96 return;
97 }
98 irq_handlers[irq].handler(irq_handlers[irq].arg);
99 irq_handlers[irq].count++;
100 } else {
101 spurious_irq_cnt++;
102 spurious_irq = irq;
103 }
104}
105
106void leon3_force_int(int irq)
107{
108 if (!irqmp || (irq >= NR_IRQS) || (irq < 0))
109 return;
110 printf("Forcing interrupt %d\n", irq);
111
112 irqmp->iforce = SPARC_NOCACHE_READ(&irqmp->iforce) | (1 << irq);
113}
114
115/****************************************************************************/
116
117int interrupt_init_cpu(void)
118{
119
120 return (0);
121}
122
123/****************************************************************************/
124
125/* Handle Timer 0 IRQ */
126void timer_interrupt_cpu(void *arg)
127{
128 gptimer->e[0].ctrl = (LEON3_GPTIMER_EN |
129 LEON3_GPTIMER_RL |
130 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
131 /* nothing to do here */
132 return;
133}
134
135/****************************************************************************/
136
137/*
138 * Install and free a interrupt handler.
139 */
140
141void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
142{
143 if (irq < 0 || irq >= NR_IRQS) {
144 printf("irq_install_handler: bad irq number %d\n", irq);
145 return;
146 }
147
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);
151
6d0f6bcf
JCPV
152 if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
153 ((unsigned int)handler < CONFIG_SYS_RAM_BASE)
1e9a164e
DH
154 ) {
155 printf("irq_install_handler: bad handler: %x, irq number %d\n",
156 (unsigned int)handler, irq);
157 return;
158 }
159 irq_handlers[irq].handler = handler;
160 irq_handlers[irq].arg = arg;
161
162 /* enable irq on IRQMP hardware */
163 leon3_ic_enable(irq);
164
165}
166
167void irq_free_handler(int irq)
168{
169 if (irq < 0 || irq >= NR_IRQS) {
170 printf("irq_free_handler: bad irq number %d\n", irq);
171 return;
172 }
173
174 /* disable irq on IRQMP hardware */
175 leon3_ic_disable(irq);
176
177 irq_handlers[irq].handler = NULL;
178 irq_handlers[irq].arg = NULL;
179}
180
181/****************************************************************************/
182
183#if defined(CONFIG_CMD_IRQ)
54841ab5 184void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
1e9a164e
DH
185{
186 int irq;
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);
191
192 puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n");
193
194 for (irq = 0; irq < NR_IRQS; irq++) {
195 if (irq_handlers[irq].handler != NULL) {
b2f27600
MV
196 printf("%02d %p %p %d\n", irq,
197 irq_handlers[irq].handler,
198 irq_handlers[irq].arg,
1e9a164e
DH
199 irq_handlers[irq].count);
200 }
201 }
202}
203#endif