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