uboot/cpu/leon2/interrupts.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007
   3 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
   4 *
   5 * (C) Copyright 2006
   6 * Detlev Zundel, DENX Software Engineering, dzu@denx.de
   7 *
   8 * (C) Copyright -2003
   9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  10 *
  11 * (C) Copyright 2001
  12 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
  13 *
  14 * See file CREDITS for list of people who contributed to this
  15 * project.
  16 *
  17 * This program is free software; you can redistribute it and/or
  18 * modify it under the terms of the GNU General Public License as
  19 * published by the Free Software Foundation; either version 2 of
  20 * the License, or (at your option) any later version.
  21 *
  22 * This program is distributed in the hope that it will be useful,
  23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25 * GNU General Public License for more details.
  26 *
  27 * You should have received a copy of the GNU General Public License
  28 * along with this program; if not, write to the Free Software
  29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  30 * MA 02111-1307 USA
  31 */
  32
  33#include <asm/stack.h>
  34#include <common.h>
  35#include <asm/io.h>
  36#include <asm/processor.h>
  37#include <command.h>
  38#include <asm/irq.h>
  39
  40#include <asm/leon.h>
  41
  42/* 15 normal irqs and a non maskable interrupt */
  43#define NR_IRQS 15
  44
  45struct irq_action {
  46        interrupt_handler_t *handler;
  47        void *arg;
  48        unsigned int count;
  49};
  50
  51static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
  52static int spurious_irq_cnt = 0;
  53static int spurious_irq = 0;
  54
  55static inline unsigned int leon2_get_irqmask(unsigned int irq)
  56{
  57        if ((irq < 0) || (irq >= NR_IRQS)) {
  58                return 0;
  59        } else {
  60                return (1 << irq);
  61        }
  62}
  63
  64static void leon2_ic_disable(unsigned int irq)
  65{
  66        unsigned int mask, pil;
  67        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
  68
  69        pil = intLock();
  70
  71        /* get mask of interrupt */
  72        mask = leon2_get_irqmask(irq);
  73
  74        /* set int level */
  75        leon2->Interrupt_Mask =
  76            SPARC_NOCACHE_READ(&leon2->Interrupt_Mask) & (~mask);
  77
  78        intUnlock(pil);
  79}
  80
  81static void leon2_ic_enable(unsigned int irq)
  82{
  83        unsigned int mask, pil;
  84        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
  85
  86        pil = intLock();
  87
  88        /* get mask of interrupt */
  89        mask = leon2_get_irqmask(irq);
  90
  91        /* set int level */
  92        leon2->Interrupt_Mask =
  93            SPARC_NOCACHE_READ(&leon2->Interrupt_Mask) | mask;
  94
  95        intUnlock(pil);
  96}
  97
  98void handler_irq(int irq, struct pt_regs *regs)
  99{
 100        if (irq_handlers[irq].handler) {
 101                if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
 102                    ((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
 103                    ) {
 104                        printf("handler_irq: bad handler: %x, irq number %d\n",
 105                               (unsigned int)irq_handlers[irq].handler, irq);
 106                        return;
 107                }
 108                irq_handlers[irq].handler(irq_handlers[irq].arg);
 109                irq_handlers[irq].count++;
 110        } else {
 111                spurious_irq_cnt++;
 112                spurious_irq = irq;
 113        }
 114}
 115
 116void leon2_force_int(int irq)
 117{
 118        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
 119
 120        if ((irq >= NR_IRQS) || (irq < 0))
 121                return;
 122        printf("Forcing interrupt %d\n", irq);
 123
 124        leon2->Interrupt_Force =
 125            SPARC_NOCACHE_READ(&leon2->Interrupt_Force) | (1 << irq);
 126}
 127
 128/****************************************************************************/
 129
 130int interrupt_init_cpu(void)
 131{
 132        return (0);
 133}
 134
 135/****************************************************************************/
 136
 137/* Handle Timer 0 IRQ */
 138void timer_interrupt_cpu(void *arg)
 139{
 140        LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
 141
 142        leon2->Timer_Control_1 =
 143            (LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | LEON2_TIMER_CTRL_LD);
 144
 145        /* nothing to do here */
 146        return;
 147}
 148
 149/****************************************************************************/
 150
 151/*
 152 * Install and free a interrupt handler.
 153 */
 154
 155void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
 156{
 157        if (irq < 0 || irq >= NR_IRQS) {
 158                printf("irq_install_handler: bad irq number %d\n", irq);
 159                return;
 160        }
 161
 162        if (irq_handlers[irq].handler != NULL)
 163                printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
 164                       (ulong) handler, (ulong) irq_handlers[irq].handler);
 165
 166        if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
 167            ((unsigned int)handler < CONFIG_SYS_RAM_BASE)
 168            ) {
 169                printf("irq_install_handler: bad handler: %x, irq number %d\n",
 170                       (unsigned int)handler, irq);
 171                return;
 172        }
 173        irq_handlers[irq].handler = handler;
 174        irq_handlers[irq].arg = arg;
 175
 176        /* enable irq on LEON2 hardware */
 177        leon2_ic_enable(irq);
 178
 179}
 180
 181void irq_free_handler(int irq)
 182{
 183        if (irq < 0 || irq >= NR_IRQS) {
 184                printf("irq_free_handler: bad irq number %d\n", irq);
 185                return;
 186        }
 187
 188        /* disable irq on LEON2 hardware */
 189        leon2_ic_disable(irq);
 190
 191        irq_handlers[irq].handler = NULL;
 192        irq_handlers[irq].arg = NULL;
 193}
 194
 195/****************************************************************************/
 196
 197#if defined(CONFIG_CMD_IRQ)
 198void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
 199{
 200        int irq;
 201        unsigned int pil = get_pil();
 202        printf("PIL level: %u\n\r", pil);
 203        printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
 204               spurious_irq_cnt, spurious_irq);
 205
 206        puts("\nInterrupt-Information:\n" "Nr  Routine   Arg       Count\n");
 207
 208        for (irq = 0; irq < NR_IRQS; irq++) {
 209                if (irq_handlers[irq].handler != NULL) {
 210                        printf("%02d  %08lx  %08lx  %ld\n", irq,
 211                               (unsigned int)irq_handlers[irq].handler,
 212                               (unsigned int)irq_handlers[irq].arg,
 213                               irq_handlers[irq].count);
 214                }
 215        }
 216}
 217#endif
 218