xref: /rk3399_rockchip-uboot/arch/x86/lib/interrupts.c (revision c2bf0dfaa3b313b941e52e565f6a2d20c02fe11a)
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
15fa82f871SAlbert 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  *
201a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
21fea25720SGraeme Russ  */
22fea25720SGraeme Russ 
23fea25720SGraeme Russ /*
24fea25720SGraeme Russ  * This file contains the high-level API for the interrupt sub-system
25fea25720SGraeme Russ  * of the x86 port of U-Boot. Most of the functionality has been
26fea25720SGraeme Russ  * shamelessly stolen from the leon2 / leon3 ports of U-Boot.
27fea25720SGraeme Russ  * Daniel Hellstrom, Detlev Zundel, Wolfgang Denk and Josh Huber are
28fea25720SGraeme Russ  * credited for the corresponding work on those ports. The original
29fea25720SGraeme Russ  * interrupt handling routines for the x86 port were written by
30fa82f871SAlbert ARIBAUD  * Daniel Engström
31fea25720SGraeme Russ  */
32fea25720SGraeme Russ 
33fea25720SGraeme Russ #include <common.h>
34fea25720SGraeme Russ #include <asm/interrupt.h>
35fea25720SGraeme Russ 
36*c2bf0dfaSSimon Glass #if !CONFIG_IS_ENABLED(X86_64)
37*c2bf0dfaSSimon Glass 
38fea25720SGraeme Russ struct irq_action {
39fea25720SGraeme Russ 	interrupt_handler_t *handler;
40fea25720SGraeme Russ 	void *arg;
41fea25720SGraeme Russ 	unsigned int count;
42fea25720SGraeme Russ };
43fea25720SGraeme Russ 
446c505271SBin Meng static struct irq_action irq_handlers[SYS_NUM_IRQS] = { {0} };
4583088afbSGraeme Russ static int spurious_irq_cnt;
4683088afbSGraeme Russ static int spurious_irq;
47fea25720SGraeme Russ 
irq_install_handler(int irq,interrupt_handler_t * handler,void * arg)48fea25720SGraeme Russ void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
49fea25720SGraeme Russ {
50fea25720SGraeme Russ 	int status;
51fea25720SGraeme Russ 
526c505271SBin Meng 	if (irq < 0 || irq >= SYS_NUM_IRQS) {
53fea25720SGraeme Russ 		printf("irq_install_handler: bad irq number %d\n", irq);
54fea25720SGraeme Russ 		return;
55fea25720SGraeme Russ 	}
56fea25720SGraeme Russ 
57fea25720SGraeme Russ 	if (irq_handlers[irq].handler != NULL)
58fea25720SGraeme Russ 		printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
59fea25720SGraeme Russ 				(ulong) handler,
60fea25720SGraeme Russ 				(ulong) irq_handlers[irq].handler);
61fea25720SGraeme Russ 
62fea25720SGraeme Russ 	status = disable_interrupts();
63fea25720SGraeme Russ 
64fea25720SGraeme Russ 	irq_handlers[irq].handler = handler;
65fea25720SGraeme Russ 	irq_handlers[irq].arg = arg;
66fea25720SGraeme Russ 	irq_handlers[irq].count = 0;
67fea25720SGraeme Russ 
68fea25720SGraeme Russ 	unmask_irq(irq);
69fea25720SGraeme Russ 
70fea25720SGraeme Russ 	if (status)
71fea25720SGraeme Russ 		enable_interrupts();
72fea25720SGraeme Russ 
73fea25720SGraeme Russ 	return;
74fea25720SGraeme Russ }
75fea25720SGraeme Russ 
irq_free_handler(int irq)76fea25720SGraeme Russ void irq_free_handler(int irq)
77fea25720SGraeme Russ {
78fea25720SGraeme Russ 	int status;
79fea25720SGraeme Russ 
806c505271SBin Meng 	if (irq < 0 || irq >= SYS_NUM_IRQS) {
81fea25720SGraeme Russ 		printf("irq_free_handler: bad irq number %d\n", irq);
82fea25720SGraeme Russ 		return;
83fea25720SGraeme Russ 	}
84fea25720SGraeme Russ 
85fea25720SGraeme Russ 	status = disable_interrupts();
86fea25720SGraeme Russ 
87fea25720SGraeme Russ 	mask_irq(irq);
88fea25720SGraeme Russ 
89fea25720SGraeme Russ 	irq_handlers[irq].handler = NULL;
90fea25720SGraeme Russ 	irq_handlers[irq].arg = NULL;
91fea25720SGraeme Russ 
92fea25720SGraeme Russ 	if (status)
93fea25720SGraeme Russ 		enable_interrupts();
94fea25720SGraeme Russ 
95fea25720SGraeme Russ 	return;
96fea25720SGraeme Russ }
97fea25720SGraeme Russ 
do_irq(int hw_irq)98fea25720SGraeme Russ void do_irq(int hw_irq)
99fea25720SGraeme Russ {
100fea25720SGraeme Russ 	int irq = hw_irq - 0x20;
101fea25720SGraeme Russ 
1026c505271SBin Meng 	if (irq < 0 || irq >= SYS_NUM_IRQS) {
103fea25720SGraeme Russ 		printf("do_irq: bad irq number %d\n", irq);
104fea25720SGraeme Russ 		return;
105fea25720SGraeme Russ 	}
106fea25720SGraeme Russ 
107fea25720SGraeme Russ 	if (irq_handlers[irq].handler) {
108fea25720SGraeme Russ 		mask_irq(irq);
109fea25720SGraeme Russ 
110fea25720SGraeme Russ 		irq_handlers[irq].handler(irq_handlers[irq].arg);
111fea25720SGraeme Russ 		irq_handlers[irq].count++;
112fea25720SGraeme Russ 
113fea25720SGraeme Russ 		unmask_irq(irq);
114fea25720SGraeme Russ 		specific_eoi(irq);
115fea25720SGraeme Russ 
116fea25720SGraeme Russ 	} else {
117fea25720SGraeme Russ 		if ((irq & 7) != 7) {
118fea25720SGraeme Russ 			spurious_irq_cnt++;
119fea25720SGraeme Russ 			spurious_irq = irq;
120fea25720SGraeme Russ 		}
121fea25720SGraeme Russ 	}
122fea25720SGraeme Russ }
123*c2bf0dfaSSimon Glass #endif
124fea25720SGraeme Russ 
125fea25720SGraeme Russ #if defined(CONFIG_CMD_IRQ)
do_irqinfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])126fea25720SGraeme Russ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
127fea25720SGraeme Russ {
128*c2bf0dfaSSimon Glass #if !CONFIG_IS_ENABLED(X86_64)
129fea25720SGraeme Russ 	int irq;
130fea25720SGraeme Russ 
131fea25720SGraeme Russ 	printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
132fea25720SGraeme Russ 			spurious_irq_cnt, spurious_irq);
133fea25720SGraeme Russ 
134fea25720SGraeme Russ 	printf("Interrupt-Information:\n");
135fea25720SGraeme Russ 	printf("Nr  Routine   Arg       Count\n");
136fea25720SGraeme Russ 
1376c505271SBin Meng 	for (irq = 0; irq < SYS_NUM_IRQS; irq++) {
138fea25720SGraeme Russ 		if (irq_handlers[irq].handler != NULL) {
139fea25720SGraeme Russ 			printf("%02d  %08lx  %08lx  %d\n",
140fea25720SGraeme Russ 					irq,
141fea25720SGraeme Russ 					(ulong)irq_handlers[irq].handler,
142fea25720SGraeme Russ 					(ulong)irq_handlers[irq].arg,
143fea25720SGraeme Russ 					irq_handlers[irq].count);
144fea25720SGraeme Russ 		}
145fea25720SGraeme Russ 	}
146*c2bf0dfaSSimon Glass #endif
147fea25720SGraeme Russ 
148fea25720SGraeme Russ 	return 0;
149fea25720SGraeme Russ }
150fea25720SGraeme Russ #endif
151