uboot/arch/openrisc/cpu/interrupts.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
   3 * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation; either version 2 of
   8 * the License, or (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  18 * MA 02111-1307 USA
  19 */
  20
  21#include <common.h>
  22#include <asm/types.h>
  23#include <asm/ptrace.h>
  24#include <asm/system.h>
  25#include <asm/openrisc_exc.h>
  26
  27struct irq_action {
  28        interrupt_handler_t *handler;
  29        void *arg;
  30        int count;
  31};
  32
  33static struct irq_action handlers[32];
  34
  35void interrupt_handler(void)
  36{
  37        int irq;
  38
  39        while ((irq = ffs(mfspr(SPR_PICSR)))) {
  40                if (handlers[--irq].handler) {
  41                        handlers[irq].handler(handlers[irq].arg);
  42                        handlers[irq].count++;
  43                } else {
  44                        /* disable the interrupt */
  45                        mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1 << irq));
  46                        printf("Unhandled interrupt: %d\n", irq);
  47                }
  48                /* clear the interrupt */
  49                mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1 << irq));
  50        }
  51}
  52
  53int interrupt_init(void)
  54{
  55        /* install handler for external interrupt exception */
  56        exception_install_handler(EXC_EXT_IRQ, interrupt_handler);
  57        /* Enable interrupts in supervisor register */
  58        mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
  59
  60        return 0;
  61}
  62
  63void enable_interrupts(void)
  64{
  65        /* Set interrupt enable bit in supervisor register */
  66        mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
  67        /* Enable timer exception */
  68        mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_TEE);
  69}
  70
  71int disable_interrupts(void)
  72{
  73        /* Clear interrupt enable bit in supervisor register */
  74        mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE);
  75        /* Disable timer exception */
  76        mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_TEE);
  77
  78        return 0;
  79}
  80
  81void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
  82{
  83        if (irq < 0 || irq > 31)
  84                return;
  85
  86        handlers[irq].handler = handler;
  87        handlers[irq].arg = arg;
  88}
  89
  90void irq_free_handler(int irq)
  91{
  92        if (irq < 0 || irq > 31)
  93                return;
  94
  95        handlers[irq].handler = 0;
  96        handlers[irq].arg = 0;
  97}
  98
  99#if defined(CONFIG_CMD_IRQ)
 100int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 101{
 102        int i;
 103
 104        printf("\nInterrupt-Information:\n\n");
 105        printf("Nr  Routine   Arg       Count\n");
 106        printf("-----------------------------\n");
 107
 108        for (i = 0; i < 32; i++) {
 109                if (handlers[i].handler) {
 110                        printf("%02d  %08lx  %08lx  %d\n",
 111                                i,
 112                                (ulong)handlers[i].handler,
 113                                (ulong)handlers[i].arg,
 114                                handlers[i].count);
 115                }
 116        }
 117        printf("\n");
 118
 119        return 0;
 120}
 121#endif
 122