]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/sparc/cpu/leon3/interrupts.c
Merge branch 'master' of git://git.denx.de/u-boot-video
[karo-tx-uboot.git] / 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  * See file CREDITS for list of people who contributed to this
15  * project.
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License as
19  * published by the Free Software Foundation; either version 2 of
20  * the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30  * MA 02111-1307 USA
31  */
32
33 #include <asm/stack.h>
34 #include <common.h>
35 #include <asm/io.h>
36 #include <asm/processor.h>
37 #include <command.h>
38 #include <asm/irq.h>
39
40 #include <asm/leon.h>
41 #include <ambapp.h>
42
43 /* 15 normal irqs and a non maskable interrupt */
44 #define NR_IRQS 15
45
46 struct irq_action {
47         interrupt_handler_t *handler;
48         void *arg;
49         unsigned int count;
50 };
51
52 extern ambapp_dev_irqmp *irqmp;
53 extern ambapp_dev_gptimer *gptimer;
54
55 static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
56 static int spurious_irq_cnt = 0;
57 static int spurious_irq = 0;
58
59 static inline unsigned int irqmp_get_irqmask(unsigned int irq)
60 {
61         if ((irq < 0) || (irq >= NR_IRQS)) {
62                 return 0;
63         } else {
64                 return (1 << irq);
65         }
66
67 }
68
69 static void leon3_ic_disable(unsigned int irq)
70 {
71         unsigned int mask, pil;
72         if (!irqmp)
73                 return;
74
75         pil = intLock();
76
77         /* get mask of interrupt */
78         mask = irqmp_get_irqmask(irq);
79
80         /* set int level */
81         irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) & (~mask);
82
83         intUnlock(pil);
84 }
85
86 static void leon3_ic_enable(unsigned int irq)
87 {
88         unsigned int mask, pil;
89         if (!irqmp)
90                 return;
91
92         pil = intLock();
93
94         /* get mask of interrupt */
95         mask = irqmp_get_irqmask(irq);
96
97         /* set int level */
98         irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) | mask;
99
100         intUnlock(pil);
101
102 }
103
104 void handler_irq(int irq, struct pt_regs *regs)
105 {
106         if (irq_handlers[irq].handler) {
107                 if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
108                     ((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
109                     ) {
110                         printf("handler_irq: bad handler: %x, irq number %d\n",
111                                (unsigned int)irq_handlers[irq].handler, irq);
112                         return;
113                 }
114                 irq_handlers[irq].handler(irq_handlers[irq].arg);
115                 irq_handlers[irq].count++;
116         } else {
117                 spurious_irq_cnt++;
118                 spurious_irq = irq;
119         }
120 }
121
122 void leon3_force_int(int irq)
123 {
124         if (!irqmp || (irq >= NR_IRQS) || (irq < 0))
125                 return;
126         printf("Forcing interrupt %d\n", irq);
127
128         irqmp->iforce = SPARC_NOCACHE_READ(&irqmp->iforce) | (1 << irq);
129 }
130
131 /****************************************************************************/
132
133 int interrupt_init_cpu(void)
134 {
135
136         return (0);
137 }
138
139 /****************************************************************************/
140
141 /* Handle Timer 0 IRQ */
142 void timer_interrupt_cpu(void *arg)
143 {
144         gptimer->e[0].ctrl = (LEON3_GPTIMER_EN |
145                               LEON3_GPTIMER_RL |
146                               LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
147         /* nothing to do here */
148         return;
149 }
150
151 /****************************************************************************/
152
153 /*
154  * Install and free a interrupt handler.
155  */
156
157 void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
158 {
159         if (irq < 0 || irq >= NR_IRQS) {
160                 printf("irq_install_handler: bad irq number %d\n", irq);
161                 return;
162         }
163
164         if (irq_handlers[irq].handler != NULL)
165                 printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
166                        (ulong) handler, (ulong) irq_handlers[irq].handler);
167
168         if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
169             ((unsigned int)handler < CONFIG_SYS_RAM_BASE)
170             ) {
171                 printf("irq_install_handler: bad handler: %x, irq number %d\n",
172                        (unsigned int)handler, irq);
173                 return;
174         }
175         irq_handlers[irq].handler = handler;
176         irq_handlers[irq].arg = arg;
177
178         /* enable irq on IRQMP hardware */
179         leon3_ic_enable(irq);
180
181 }
182
183 void irq_free_handler(int irq)
184 {
185         if (irq < 0 || irq >= NR_IRQS) {
186                 printf("irq_free_handler: bad irq number %d\n", irq);
187                 return;
188         }
189
190         /* disable irq on IRQMP hardware */
191         leon3_ic_disable(irq);
192
193         irq_handlers[irq].handler = NULL;
194         irq_handlers[irq].arg = NULL;
195 }
196
197 /****************************************************************************/
198
199 #if defined(CONFIG_CMD_IRQ)
200 void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
201 {
202         int irq;
203         unsigned int pil = get_pil();
204         printf("PIL level: %u\n\r", pil);
205         printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
206                spurious_irq_cnt, spurious_irq);
207
208         puts("\nInterrupt-Information:\n" "Nr  Routine   Arg       Count\n");
209
210         for (irq = 0; irq < NR_IRQS; irq++) {
211                 if (irq_handlers[irq].handler != NULL) {
212                         printf("%02d  %p  %p  %d\n", irq,
213                                irq_handlers[irq].handler,
214                                irq_handlers[irq].arg,
215                                irq_handlers[irq].count);
216                 }
217         }
218 }
219 #endif