Prex Home / Browse Source - Prex Version: 0.9.0

root/bsp/hal/arm/integrator/interrupt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. update_mask
  2. interrupt_unmask
  3. interrupt_mask
  4. interrupt_setup
  5. interrupt_handler
  6. interrupt_init

   1 /*-
   2  * Copyright (c) 2008, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * interrupt.c - interrupt handling routines
  32  */
  33 
  34 #include <sys/ipl.h>
  35 #include <kernel.h>
  36 #include <hal.h>
  37 #include <irq.h>
  38 #include <cpufunc.h>
  39 #include <context.h>
  40 #include <locore.h>
  41 
  42 #include "platform.h"
  43 
  44 /* Number of IRQ lines */
  45 #define NIRQS           29
  46 
  47 /* Registers for interrupt control unit - enable/flag/master */
  48 #define ICU_IRQSTS      (*(volatile uint32_t *)(ICU_BASE + 0x00))
  49 #define ICU_IRQEN       (*(volatile uint32_t *)(ICU_BASE + 0x08))
  50 #define ICU_IRQENSET    (*(volatile uint32_t *)(ICU_BASE + 0x08))
  51 #define ICU_IRQENCLR    (*(volatile uint32_t *)(ICU_BASE + 0x0C))
  52 
  53 /*
  54  * Interrupt Priority Level
  55  *
  56  * Each interrupt has its logical priority level, with 0 being
  57  * the lowest priority. While some ISR is running, all lower
  58  * priority interrupts are masked off.
  59  */
  60 volatile int irq_level;
  61 
  62 /*
  63  * Interrupt mapping table
  64  */
  65 static int ipl_table[NIRQS];            /* vector -> level */
  66 static uint32_t mask_table[NIPLS];      /* level -> mask */
  67 
  68 /*
  69  * Set mask for current ipl
  70  */
  71 static void
  72 update_mask(void)
  73 {
  74         u_int mask = mask_table[irq_level];
  75 
  76         ICU_IRQENCLR = ~mask;
  77         ICU_IRQENSET = mask;
  78 }
  79 
  80 /*
  81  * Unmask interrupt in ICU for specified irq.
  82  * The interrupt mask table is also updated.
  83  * Assumes CPU interrupt is disabled in caller.
  84  */
  85 void
  86 interrupt_unmask(int vector, int level)
  87 {
  88         int i;
  89         uint32_t unmask = (uint32_t)1 << vector;
  90 
  91         /* Save level mapping */
  92         ipl_table[vector] = level;
  93 
  94         /*
  95          * Unmask the target interrupt for all
  96          * lower interrupt levels.
  97          */
  98         for (i = 0; i < level; i++)
  99                 mask_table[i] |= unmask;
 100         update_mask();
 101 }
 102 
 103 /*
 104  * Mask interrupt in ICU for specified irq.
 105  * Interrupt must be disabled when this routine is called.
 106  */
 107 void
 108 interrupt_mask(int vector)
 109 {
 110         int i, level;
 111         u_int mask = (uint16_t)~(1 << vector);
 112 
 113         level = ipl_table[vector];
 114         for (i = 0; i < level; i++)
 115                 mask_table[i] &= mask;
 116         ipl_table[vector] = IPL_NONE;
 117         update_mask();
 118 }
 119 
 120 /*
 121  * Setup interrupt mode.
 122  * Select whether an interrupt trigger is edge or level.
 123  */
 124 void
 125 interrupt_setup(int vector, int mode)
 126 {
 127         /* nop */
 128 }
 129 
 130 /*
 131  * Common interrupt handler.
 132  */
 133 void
 134 interrupt_handler(void)
 135 {
 136         uint32_t bits;
 137         int vector, old_ipl, new_ipl;
 138 
 139         /* Get interrupt source */
 140         bits = ICU_IRQSTS;
 141         for (vector = 0; vector < NIRQS; vector++) {
 142                 if (bits & (uint32_t)(1 << vector))
 143                         break;
 144         }
 145         if (vector == NIRQS)
 146                 goto out;
 147 
 148         /* Adjust interrupt level */
 149         old_ipl = irq_level;
 150         new_ipl = ipl_table[vector];
 151         if (new_ipl > old_ipl)          /* Ignore spurious interrupt */
 152                 irq_level = new_ipl;
 153         update_mask();
 154 
 155         /* Allow another interrupt that has higher priority */
 156         splon();
 157 
 158         /* Dispatch interrupt */
 159         irq_handler(vector);
 160 
 161         sploff();
 162 
 163         /* Restore interrupt level */
 164         irq_level = old_ipl;
 165         update_mask();
 166 out:
 167         return;
 168 }
 169 
 170 /*
 171  * Initialize interrupt controllers.
 172  * All interrupts will be masked off.
 173  */
 174 void
 175 interrupt_init(void)
 176 {
 177         int i;
 178 
 179         irq_level = IPL_NONE;
 180 
 181         for (i = 0; i < NIRQS; i++)
 182                 ipl_table[i] = IPL_NONE;
 183 
 184         for (i = 0; i < NIPLS; i++)
 185                 mask_table[i] = 0;
 186 
 187         ICU_IRQENCLR = 0xffff;          /* Mask all interrupts */
 188 }

/* [<][>][^][v][top][bottom][index][help] */