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