xref: /rk3399_rockchip-uboot/arch/x86/lib/interrupts.c (revision fa82f871c8dbc9a15e8dc274b3f99dd5fa0da458)
1fea25720SGraeme Russ /*
2fea25720SGraeme Russ  * (C) Copyright 2009
3fea25720SGraeme Russ  * Graeme Russ, <graeme.russ@gmail.com>
4fea25720SGraeme Russ  *
5fea25720SGraeme Russ  * (C) Copyright 2007
6fea25720SGraeme Russ  * Daniel Hellstrom, Gaisler Research, <daniel@gaisler.com>
7fea25720SGraeme Russ  *
8fea25720SGraeme Russ  * (C) Copyright 2006
9fea25720SGraeme Russ  * Detlev Zundel, DENX Software Engineering, <dzu@denx.de>
10fea25720SGraeme Russ  *
11fea25720SGraeme Russ  * (C) Copyright -2003
12fea25720SGraeme Russ  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
13fea25720SGraeme Russ  *
14fea25720SGraeme Russ  * (C) Copyright 2002
15*fa82f871SAlbert ARIBAUD  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
16fea25720SGraeme Russ  *
17fea25720SGraeme Russ  * (C) Copyright 2001
18fea25720SGraeme Russ  * Josh Huber, Mission Critical Linux, Inc, <huber@mclx.com>
19fea25720SGraeme Russ  *
20fea25720SGraeme Russ  * See file CREDITS for list of people who contributed to this
21fea25720SGraeme Russ  * project.
22fea25720SGraeme Russ  *
23fea25720SGraeme Russ  * This program is free software; you can redistribute it and/or
24fea25720SGraeme Russ  * modify it under the terms of the GNU General Public License as
25fea25720SGraeme Russ  * published by the Free Software Foundation; either version 2 of
26fea25720SGraeme Russ  * the License, or (at your option) any later version.
27fea25720SGraeme Russ  *
28fea25720SGraeme Russ  * This program is distributed in the hope that it will be useful,
29fea25720SGraeme Russ  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30fea25720SGraeme Russ  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31fea25720SGraeme Russ  * GNU General Public License for more details.
32fea25720SGraeme Russ  *
33fea25720SGraeme Russ  * You should have received a copy of the GNU General Public License
34fea25720SGraeme Russ  * along with this program; if not, write to the Free Software
35fea25720SGraeme Russ  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
36fea25720SGraeme Russ  * MA 02111-1307 USA
37fea25720SGraeme Russ  */
38fea25720SGraeme Russ 
39fea25720SGraeme Russ /*
40fea25720SGraeme Russ  * This file contains the high-level API for the interrupt sub-system
41fea25720SGraeme Russ  * of the x86 port of U-Boot. Most of the functionality has been
42fea25720SGraeme Russ  * shamelessly stolen from the leon2 / leon3 ports of U-Boot.
43fea25720SGraeme Russ  * Daniel Hellstrom, Detlev Zundel, Wolfgang Denk and Josh Huber are
44fea25720SGraeme Russ  * credited for the corresponding work on those ports. The original
45fea25720SGraeme Russ  * interrupt handling routines for the x86 port were written by
46*fa82f871SAlbert ARIBAUD  * Daniel Engström
47fea25720SGraeme Russ  */
48fea25720SGraeme Russ 
49fea25720SGraeme Russ #include <common.h>
50fea25720SGraeme Russ #include <asm/interrupt.h>
51fea25720SGraeme Russ 
52fea25720SGraeme Russ struct irq_action {
53fea25720SGraeme Russ 	interrupt_handler_t *handler;
54fea25720SGraeme Russ 	void *arg;
55fea25720SGraeme Russ 	unsigned int count;
56fea25720SGraeme Russ };
57fea25720SGraeme Russ 
58fea25720SGraeme Russ static struct irq_action irq_handlers[CONFIG_SYS_NUM_IRQS] = { {0} };
59fea25720SGraeme Russ static int spurious_irq_cnt = 0;
60fea25720SGraeme Russ static int spurious_irq = 0;
61fea25720SGraeme Russ 
62fea25720SGraeme Russ void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
63fea25720SGraeme Russ {
64fea25720SGraeme Russ 	int status;
65fea25720SGraeme Russ 
66fea25720SGraeme Russ 	if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
67fea25720SGraeme Russ 		printf("irq_install_handler: bad irq number %d\n", irq);
68fea25720SGraeme Russ 		return;
69fea25720SGraeme Russ 	}
70fea25720SGraeme Russ 
71fea25720SGraeme Russ 	if (irq_handlers[irq].handler != NULL)
72fea25720SGraeme Russ 		printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
73fea25720SGraeme Russ 		       (ulong) handler,
74fea25720SGraeme Russ 		       (ulong) irq_handlers[irq].handler);
75fea25720SGraeme Russ 
76fea25720SGraeme Russ 	status = disable_interrupts ();
77fea25720SGraeme Russ 
78fea25720SGraeme Russ 	irq_handlers[irq].handler = handler;
79fea25720SGraeme Russ 	irq_handlers[irq].arg = arg;
80fea25720SGraeme Russ 	irq_handlers[irq].count = 0;
81fea25720SGraeme Russ 
82fea25720SGraeme Russ 	unmask_irq(irq);
83fea25720SGraeme Russ 
84fea25720SGraeme Russ 	if (status)
85fea25720SGraeme Russ 		enable_interrupts();
86fea25720SGraeme Russ 
87fea25720SGraeme Russ 	return;
88fea25720SGraeme Russ }
89fea25720SGraeme Russ 
90fea25720SGraeme Russ void irq_free_handler(int irq)
91fea25720SGraeme Russ {
92fea25720SGraeme Russ 	int status;
93fea25720SGraeme Russ 
94fea25720SGraeme Russ 	if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
95fea25720SGraeme Russ 		printf("irq_free_handler: bad irq number %d\n", irq);
96fea25720SGraeme Russ 		return;
97fea25720SGraeme Russ 	}
98fea25720SGraeme Russ 
99fea25720SGraeme Russ 	status = disable_interrupts ();
100fea25720SGraeme Russ 
101fea25720SGraeme Russ 	mask_irq(irq);
102fea25720SGraeme Russ 
103fea25720SGraeme Russ 	irq_handlers[irq].handler = NULL;
104fea25720SGraeme Russ 	irq_handlers[irq].arg = NULL;
105fea25720SGraeme Russ 
106fea25720SGraeme Russ 	if (status)
107fea25720SGraeme Russ 		enable_interrupts();
108fea25720SGraeme Russ 
109fea25720SGraeme Russ 	return;
110fea25720SGraeme Russ }
111fea25720SGraeme Russ 
112fea25720SGraeme Russ void do_irq(int hw_irq)
113fea25720SGraeme Russ {
114fea25720SGraeme Russ 	int irq = hw_irq - 0x20;
115fea25720SGraeme Russ 
116fea25720SGraeme Russ 	if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
117fea25720SGraeme Russ 		printf("do_irq: bad irq number %d\n", irq);
118fea25720SGraeme Russ 		return;
119fea25720SGraeme Russ 	}
120fea25720SGraeme Russ 
121fea25720SGraeme Russ 	if (irq_handlers[irq].handler) {
122fea25720SGraeme Russ 		mask_irq(irq);
123fea25720SGraeme Russ 
124fea25720SGraeme Russ 		irq_handlers[irq].handler(irq_handlers[irq].arg);
125fea25720SGraeme Russ 		irq_handlers[irq].count++;
126fea25720SGraeme Russ 
127fea25720SGraeme Russ 		unmask_irq(irq);
128fea25720SGraeme Russ 		specific_eoi(irq);
129fea25720SGraeme Russ 
130fea25720SGraeme Russ 	} else {
131fea25720SGraeme Russ 		if ((irq & 7) != 7) {
132fea25720SGraeme Russ 			spurious_irq_cnt++;
133fea25720SGraeme Russ 			spurious_irq = irq;
134fea25720SGraeme Russ 		}
135fea25720SGraeme Russ 	}
136fea25720SGraeme Russ }
137fea25720SGraeme Russ 
138fea25720SGraeme Russ #if defined(CONFIG_CMD_IRQ)
139fea25720SGraeme Russ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
140fea25720SGraeme Russ {
141fea25720SGraeme Russ 	int irq;
142fea25720SGraeme Russ 
143fea25720SGraeme Russ 	printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
144fea25720SGraeme Russ 	       spurious_irq_cnt, spurious_irq);
145fea25720SGraeme Russ 
146fea25720SGraeme Russ 	printf ("Interrupt-Information:\n");
147fea25720SGraeme Russ 	printf ("Nr  Routine   Arg       Count\n");
148fea25720SGraeme Russ 
149fea25720SGraeme Russ 	for (irq = 0; irq <= CONFIG_SYS_NUM_IRQS; irq++) {
150fea25720SGraeme Russ 		if (irq_handlers[irq].handler != NULL) {
151fea25720SGraeme Russ 			printf ("%02d  %08lx  %08lx  %d\n",
152fea25720SGraeme Russ 					irq,
153fea25720SGraeme Russ 					(ulong)irq_handlers[irq].handler,
154fea25720SGraeme Russ 					(ulong)irq_handlers[irq].arg,
155fea25720SGraeme Russ 					irq_handlers[irq].count);
156fea25720SGraeme Russ 		}
157fea25720SGraeme Russ 	}
158fea25720SGraeme Russ 
159fea25720SGraeme Russ 	return 0;
160fea25720SGraeme Russ }
161fea25720SGraeme Russ #endif
162