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