183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2fea25720SGraeme Russ /*
3fea25720SGraeme Russ * (C) Copyright 2009
4fea25720SGraeme Russ * Graeme Russ, <graeme.russ@gmail.com>
5fea25720SGraeme Russ *
6fea25720SGraeme Russ * (C) Copyright 2007
7fea25720SGraeme Russ * Daniel Hellstrom, Gaisler Research, <daniel@gaisler.com>
8fea25720SGraeme Russ *
9fea25720SGraeme Russ * (C) Copyright 2006
10fea25720SGraeme Russ * Detlev Zundel, DENX Software Engineering, <dzu@denx.de>
11fea25720SGraeme Russ *
12fea25720SGraeme Russ * (C) Copyright -2003
13fea25720SGraeme Russ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
14fea25720SGraeme Russ *
15fea25720SGraeme Russ * (C) Copyright 2002
16fa82f871SAlbert ARIBAUD * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
17fea25720SGraeme Russ *
18fea25720SGraeme Russ * (C) Copyright 2001
19fea25720SGraeme Russ * Josh Huber, Mission Critical Linux, Inc, <huber@mclx.com>
20fea25720SGraeme Russ */
21fea25720SGraeme Russ
22fea25720SGraeme Russ /*
23fea25720SGraeme Russ * This file contains the high-level API for the interrupt sub-system
24fea25720SGraeme Russ * of the x86 port of U-Boot. Most of the functionality has been
25fea25720SGraeme Russ * shamelessly stolen from the leon2 / leon3 ports of U-Boot.
26fea25720SGraeme Russ * Daniel Hellstrom, Detlev Zundel, Wolfgang Denk and Josh Huber are
27fea25720SGraeme Russ * credited for the corresponding work on those ports. The original
28fea25720SGraeme Russ * interrupt handling routines for the x86 port were written by
29fa82f871SAlbert ARIBAUD * Daniel Engström
30fea25720SGraeme Russ */
31fea25720SGraeme Russ
32fea25720SGraeme Russ #include <common.h>
33fea25720SGraeme Russ #include <asm/interrupt.h>
34fea25720SGraeme Russ
35c2bf0dfaSSimon Glass #if !CONFIG_IS_ENABLED(X86_64)
36c2bf0dfaSSimon Glass
37fea25720SGraeme Russ struct irq_action {
38fea25720SGraeme Russ interrupt_handler_t *handler;
39fea25720SGraeme Russ void *arg;
40fea25720SGraeme Russ unsigned int count;
41fea25720SGraeme Russ };
42fea25720SGraeme Russ
436c505271SBin Meng static struct irq_action irq_handlers[SYS_NUM_IRQS] = { {0} };
4483088afbSGraeme Russ static int spurious_irq_cnt;
4583088afbSGraeme Russ static int spurious_irq;
46fea25720SGraeme Russ
irq_install_handler(int irq,interrupt_handler_t * handler,void * arg)47fea25720SGraeme Russ void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
48fea25720SGraeme Russ {
49fea25720SGraeme Russ int status;
50fea25720SGraeme Russ
516c505271SBin Meng if (irq < 0 || irq >= SYS_NUM_IRQS) {
52fea25720SGraeme Russ printf("irq_install_handler: bad irq number %d\n", irq);
53fea25720SGraeme Russ return;
54fea25720SGraeme Russ }
55fea25720SGraeme Russ
56fea25720SGraeme Russ if (irq_handlers[irq].handler != NULL)
57fea25720SGraeme Russ printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
58fea25720SGraeme Russ (ulong) handler,
59fea25720SGraeme Russ (ulong) irq_handlers[irq].handler);
60fea25720SGraeme Russ
61fea25720SGraeme Russ status = disable_interrupts();
62fea25720SGraeme Russ
63fea25720SGraeme Russ irq_handlers[irq].handler = handler;
64fea25720SGraeme Russ irq_handlers[irq].arg = arg;
65fea25720SGraeme Russ irq_handlers[irq].count = 0;
66fea25720SGraeme Russ
67*c6410104SBin Meng if (CONFIG_IS_ENABLED(I8259_PIC))
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
87*c6410104SBin Meng if (CONFIG_IS_ENABLED(I8259_PIC))
88fea25720SGraeme Russ mask_irq(irq);
89fea25720SGraeme Russ
90fea25720SGraeme Russ irq_handlers[irq].handler = NULL;
91fea25720SGraeme Russ irq_handlers[irq].arg = NULL;
92fea25720SGraeme Russ
93fea25720SGraeme Russ if (status)
94fea25720SGraeme Russ enable_interrupts();
95fea25720SGraeme Russ
96fea25720SGraeme Russ return;
97fea25720SGraeme Russ }
98fea25720SGraeme Russ
do_irq(int hw_irq)99fea25720SGraeme Russ void do_irq(int hw_irq)
100fea25720SGraeme Russ {
101fea25720SGraeme Russ int irq = hw_irq - 0x20;
102fea25720SGraeme Russ
1036c505271SBin Meng if (irq < 0 || irq >= SYS_NUM_IRQS) {
104fea25720SGraeme Russ printf("do_irq: bad irq number %d\n", irq);
105fea25720SGraeme Russ return;
106fea25720SGraeme Russ }
107fea25720SGraeme Russ
108fea25720SGraeme Russ if (irq_handlers[irq].handler) {
109*c6410104SBin Meng if (CONFIG_IS_ENABLED(I8259_PIC))
110fea25720SGraeme Russ mask_irq(irq);
111fea25720SGraeme Russ
112fea25720SGraeme Russ irq_handlers[irq].handler(irq_handlers[irq].arg);
113fea25720SGraeme Russ irq_handlers[irq].count++;
114fea25720SGraeme Russ
115*c6410104SBin Meng if (CONFIG_IS_ENABLED(I8259_PIC)) {
116fea25720SGraeme Russ unmask_irq(irq);
117fea25720SGraeme Russ specific_eoi(irq);
118*c6410104SBin Meng }
119fea25720SGraeme Russ } else {
120fea25720SGraeme Russ if ((irq & 7) != 7) {
121fea25720SGraeme Russ spurious_irq_cnt++;
122fea25720SGraeme Russ spurious_irq = irq;
123fea25720SGraeme Russ }
124fea25720SGraeme Russ }
125fea25720SGraeme Russ }
126c2bf0dfaSSimon Glass #endif
127fea25720SGraeme Russ
128fea25720SGraeme Russ #if defined(CONFIG_CMD_IRQ)
do_irqinfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])129fea25720SGraeme Russ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
130fea25720SGraeme Russ {
131c2bf0dfaSSimon Glass #if !CONFIG_IS_ENABLED(X86_64)
132fea25720SGraeme Russ int irq;
133fea25720SGraeme Russ
134fea25720SGraeme Russ printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
135fea25720SGraeme Russ spurious_irq_cnt, spurious_irq);
136fea25720SGraeme Russ
137fea25720SGraeme Russ printf("Interrupt-Information:\n");
138fea25720SGraeme Russ printf("Nr Routine Arg Count\n");
139fea25720SGraeme Russ
1406c505271SBin Meng for (irq = 0; irq < SYS_NUM_IRQS; irq++) {
141fea25720SGraeme Russ if (irq_handlers[irq].handler != NULL) {
142fea25720SGraeme Russ printf("%02d %08lx %08lx %d\n",
143fea25720SGraeme Russ irq,
144fea25720SGraeme Russ (ulong)irq_handlers[irq].handler,
145fea25720SGraeme Russ (ulong)irq_handlers[irq].arg,
146fea25720SGraeme Russ irq_handlers[irq].count);
147fea25720SGraeme Russ }
148fea25720SGraeme Russ }
149c2bf0dfaSSimon Glass #endif
150fea25720SGraeme Russ
151fea25720SGraeme Russ return 0;
152fea25720SGraeme Russ }
153fea25720SGraeme Russ #endif
154