uboot/arch/microblaze/cpu/interrupts.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007 Michal Simek
   3 * (C) Copyright 2004 Atmark Techno, Inc.
   4 *
   5 * Michal  SIMEK <monstr@monstr.eu>
   6 * Yasushi SHOJI <yashi@atmark-techno.com>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <command.h>
  13#include <malloc.h>
  14#include <asm/microblaze_intc.h>
  15#include <asm/asm.h>
  16
  17void enable_interrupts(void)
  18{
  19        debug("Enable interrupts for the whole CPU\n");
  20        MSRSET(0x2);
  21}
  22
  23int disable_interrupts(void)
  24{
  25        unsigned int msr;
  26
  27        MFS(msr, rmsr);
  28        MSRCLR(0x2);
  29        return (msr & 0x2) != 0;
  30}
  31
  32static struct irq_action *vecs;
  33static u32 irq_no;
  34
  35/* mapping structure to interrupt controller */
  36microblaze_intc_t *intc;
  37
  38/* default handler */
  39static void def_hdlr(void)
  40{
  41        puts("def_hdlr\n");
  42}
  43
  44static void enable_one_interrupt(int irq)
  45{
  46        int mask;
  47        int offset = 1;
  48
  49        offset <<= irq;
  50        mask = intc->ier;
  51        intc->ier = (mask | offset);
  52
  53        debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
  54              intc->ier);
  55        debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
  56              intc->iar, intc->mer);
  57}
  58
  59static void disable_one_interrupt(int irq)
  60{
  61        int mask;
  62        int offset = 1;
  63
  64        offset <<= irq;
  65        mask = intc->ier;
  66        intc->ier = (mask & ~offset);
  67
  68        debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
  69              intc->ier);
  70        debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
  71              intc->iar, intc->mer);
  72}
  73
  74int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
  75{
  76        struct irq_action *act;
  77
  78        /* irq out of range */
  79        if ((irq < 0) || (irq > irq_no)) {
  80                puts("IRQ out of range\n");
  81                return -1;
  82        }
  83        act = &vecs[irq];
  84        if (hdlr) {             /* enable */
  85                act->handler = hdlr;
  86                act->arg = arg;
  87                act->count = 0;
  88                enable_one_interrupt(irq);
  89                return 0;
  90        }
  91
  92        /* Disable */
  93        act->handler = (interrupt_handler_t *)def_hdlr;
  94        act->arg = (void *)irq;
  95        disable_one_interrupt(irq);
  96        return 1;
  97}
  98
  99/* initialization interrupt controller - hardware */
 100static void intc_init(void)
 101{
 102        intc->mer = 0;
 103        intc->ier = 0;
 104        intc->iar = 0xFFFFFFFF;
 105        /* XIntc_Start - hw_interrupt enable and all interrupt enable */
 106        intc->mer = 0x3;
 107
 108        debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
 109              intc->iar, intc->mer);
 110}
 111
 112int interrupt_init(void)
 113{
 114        int i;
 115
 116#if defined(CONFIG_SYS_INTC_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM)
 117        intc = (microblaze_intc_t *)CONFIG_SYS_INTC_0_ADDR;
 118        irq_no = CONFIG_SYS_INTC_0_NUM;
 119#endif
 120        if (irq_no) {
 121                vecs = calloc(1, sizeof(struct irq_action) * irq_no);
 122                if (vecs == NULL) {
 123                        puts("Interrupt vector allocation failed\n");
 124                        return -1;
 125                }
 126
 127                /* initialize irq list */
 128                for (i = 0; i < irq_no; i++) {
 129                        vecs[i].handler = (interrupt_handler_t *)def_hdlr;
 130                        vecs[i].arg = (void *)i;
 131                        vecs[i].count = 0;
 132                }
 133                /* initialize intc controller */
 134                intc_init();
 135                enable_interrupts();
 136        } else {
 137                puts("Undefined interrupt controller\n");
 138        }
 139        return 0;
 140}
 141
 142void interrupt_handler(void)
 143{
 144        int irqs = intc->ivr;   /* find active interrupt */
 145        int mask = 1;
 146        int value;
 147        struct irq_action *act = vecs + irqs;
 148
 149        debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
 150              intc->iar, intc->mer);
 151#ifdef DEBUG
 152        R14(value);
 153#endif
 154        debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
 155
 156        debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
 157              (u32)act->handler, act->count, (u32)act->arg);
 158        act->handler(act->arg);
 159        act->count++;
 160
 161        intc->iar = mask << irqs;
 162
 163        debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
 164              intc->ier, intc->iar, intc->mer);
 165#ifdef DEBUG
 166        R14(value);
 167#endif
 168        debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
 169}
 170
 171#if defined(CONFIG_CMD_IRQ)
 172int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, const char *argv[])
 173{
 174        int i;
 175        struct irq_action *act = vecs;
 176
 177        if (irq_no) {
 178                puts("\nInterrupt-Information:\n\n"
 179                      "Nr  Routine   Arg       Count\n"
 180                      "-----------------------------\n");
 181
 182                for (i = 0; i < irq_no; i++) {
 183                        if (act->handler != (interrupt_handler_t *)def_hdlr) {
 184                                printf("%02d  %08x  %08x  %d\n", i,
 185                                       (int)act->handler, (int)act->arg,
 186                                       act->count);
 187                        }
 188                        act++;
 189                }
 190                puts("\n");
 191        } else {
 192                puts("Undefined interrupt controller\n");
 193        }
 194        return 0;
 195}
 196#endif
 197