Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / arch / sparc / cpu / leon3 / interrupts.c
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  *
14  * SPDX-License-Identifier:     GPL-2.0+
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
30 struct irq_action {
31         interrupt_handler_t *handler;
32         void *arg;
33         unsigned int count;
34 };
35
36 extern ambapp_dev_irqmp *irqmp;
37 extern ambapp_dev_gptimer *gptimer;
38
39 static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
40 static int spurious_irq_cnt = 0;
41 static int spurious_irq = 0;
42
43 static 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
53 static 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
70 static 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
88 void handler_irq(int irq, struct pt_regs *regs)
89 {
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)
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
106 void 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
117 int interrupt_init_cpu(void)
118 {
119
120         return (0);
121 }
122
123 /****************************************************************************/
124
125 /* Handle Timer 0 IRQ */
126 void 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
141 void 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
152         if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
153             ((unsigned int)handler < CONFIG_SYS_RAM_BASE)
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
167 void 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)
184 void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
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) {
196                         printf("%02d  %p  %p  %d\n", irq,
197                                irq_handlers[irq].handler,
198                                irq_handlers[irq].arg,
199                                irq_handlers[irq].count);
200                 }
201         }
202 }
203 #endif