uboot/arch/sparc/cpu/leon3/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#include <ambapp.h>
  42
  43/* 15 normal irqs and a non maskable interrupt */
  44#define NR_IRQS 15
  45
  46struct irq_action {
  47        interrupt_handler_t *handler;
  48        void *arg;
  49        unsigned int count;
  50};
  51
  52extern ambapp_dev_irqmp *irqmp;
  53extern ambapp_dev_gptimer *gptimer;
  54
  55static struct irq_action irq_handlers[NR_IRQS] = { {0}, };
  56static int spurious_irq_cnt = 0;
  57static int spurious_irq = 0;
  58
  59static inline unsigned int irqmp_get_irqmask(unsigned int irq)
  60{
  61        if ((irq < 0) || (irq >= NR_IRQS)) {
  62                return 0;
  63        } else {
  64                return (1 << irq);
  65        }
  66
  67}
  68
  69static void leon3_ic_disable(unsigned int irq)
  70{
  71        unsigned int mask, pil;
  72        if (!irqmp)
  73                return;
  74
  75        pil = intLock();
  76
  77        /* get mask of interrupt */
  78        mask = irqmp_get_irqmask(irq);
  79
  80        /* set int level */
  81        irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) & (~mask);
  82
  83        intUnlock(pil);
  84}
  85
  86static void leon3_ic_enable(unsigned int irq)
  87{
  88        unsigned int mask, pil;
  89        if (!irqmp)
  90                return;
  91
  92        pil = intLock();
  93
  94        /* get mask of interrupt */
  95        mask = irqmp_get_irqmask(irq);
  96
  97        /* set int level */
  98        irqmp->cpu_mask[0] = SPARC_NOCACHE_READ(&irqmp->cpu_mask[0]) | mask;
  99
 100        intUnlock(pil);
 101
 102}
 103
 104void handler_irq(int irq, struct pt_regs *regs)
 105{
 106        if (irq_handlers[irq].handler) {
 107                if (((unsigned int)irq_handlers[irq].handler > CONFIG_SYS_RAM_END) ||
 108                    ((unsigned int)irq_handlers[irq].handler < CONFIG_SYS_RAM_BASE)
 109                    ) {
 110                        printf("handler_irq: bad handler: %x, irq number %d\n",
 111                               (unsigned int)irq_handlers[irq].handler, irq);
 112                        return;
 113                }
 114                irq_handlers[irq].handler(irq_handlers[irq].arg);
 115                irq_handlers[irq].count++;
 116        } else {
 117                spurious_irq_cnt++;
 118                spurious_irq = irq;
 119        }
 120}
 121
 122void leon3_force_int(int irq)
 123{
 124        if (!irqmp || (irq >= NR_IRQS) || (irq < 0))
 125                return;
 126        printf("Forcing interrupt %d\n", irq);
 127
 128        irqmp->iforce = SPARC_NOCACHE_READ(&irqmp->iforce) | (1 << irq);
 129}
 130
 131/****************************************************************************/
 132
 133int interrupt_init_cpu(void)
 134{
 135
 136        return (0);
 137}
 138
 139/****************************************************************************/
 140
 141/* Handle Timer 0 IRQ */
 142void timer_interrupt_cpu(void *arg)
 143{
 144        gptimer->e[0].ctrl = (LEON3_GPTIMER_EN |
 145                              LEON3_GPTIMER_RL |
 146                              LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
 147        /* nothing to do here */
 148        return;
 149}
 150
 151/****************************************************************************/
 152
 153/*
 154 * Install and free a interrupt handler.
 155 */
 156
 157void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
 158{
 159        if (irq < 0 || irq >= NR_IRQS) {
 160                printf("irq_install_handler: bad irq number %d\n", irq);
 161                return;
 162        }
 163
 164        if (irq_handlers[irq].handler != NULL)
 165                printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
 166                       (ulong) handler, (ulong) irq_handlers[irq].handler);
 167
 168        if (((unsigned int)handler > CONFIG_SYS_RAM_END) ||
 169            ((unsigned int)handler < CONFIG_SYS_RAM_BASE)
 170            ) {
 171                printf("irq_install_handler: bad handler: %x, irq number %d\n",
 172                       (unsigned int)handler, irq);
 173                return;
 174        }
 175        irq_handlers[irq].handler = handler;
 176        irq_handlers[irq].arg = arg;
 177
 178        /* enable irq on IRQMP hardware */
 179        leon3_ic_enable(irq);
 180
 181}
 182
 183void irq_free_handler(int irq)
 184{
 185        if (irq < 0 || irq >= NR_IRQS) {
 186                printf("irq_free_handler: bad irq number %d\n", irq);
 187                return;
 188        }
 189
 190        /* disable irq on IRQMP hardware */
 191        leon3_ic_disable(irq);
 192
 193        irq_handlers[irq].handler = NULL;
 194        irq_handlers[irq].arg = NULL;
 195}
 196
 197/****************************************************************************/
 198
 199#if defined(CONFIG_CMD_IRQ)
 200void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
 201{
 202        int irq;
 203        unsigned int pil = get_pil();
 204        printf("PIL level: %u\n\r", pil);
 205        printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
 206               spurious_irq_cnt, spurious_irq);
 207
 208        puts("\nInterrupt-Information:\n" "Nr  Routine   Arg       Count\n");
 209
 210        for (irq = 0; irq < NR_IRQS; irq++) {
 211                if (irq_handlers[irq].handler != NULL) {
 212                        printf("%02d  %08lx  %08lx  %ld\n", irq,
 213                               (unsigned int)irq_handlers[irq].handler,
 214                               (unsigned int)irq_handlers[irq].arg,
 215                               irq_handlers[irq].count);
 216                }
 217        }
 218}
 219#endif
 220