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