Prex Home / Browse Source - Prex Version: 0.9.0

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

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

DEFINITIONS

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

   1 /*-
   2  * Copyright (c) 2005-2007, 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 for GBA
  32  */
  33 
  34 #include <sys/ipl.h>
  35 #include <kernel.h>
  36 #include <hal.h>
  37 #include <irq.h>
  38 #include <locore.h>
  39 #include <cpufunc.h>
  40 #include <context.h>
  41 
  42 /* Number of IRQ lines */
  43 #define NIRQS           14
  44 
  45 /* Interrupt hook vector */
  46 #define IRQ_VECTOR      *(uint32_t *)0x3007ffc
  47 
  48 /* Registers for interrupt control unit - enable/flag/master */
  49 #define ICU_IE          (*(volatile uint16_t *)0x4000200)
  50 #define ICU_IF          (*(volatile uint16_t *)0x4000202)
  51 #define ICU_IME         (*(volatile uint16_t *)0x4000208)
  52 
  53 /* ICU_IE */
  54 #define IRQ_VALID       0x3fff
  55 
  56 /* ICU_IME */
  57 #define IRQ_OFF         0
  58 #define IRQ_ON          1
  59 
  60 /*
  61  * Interrupt priority level
  62  *
  63  * Each interrupt has its logical priority level, with 0 being
  64  * the lowest priority. While some ISR is running, all lower
  65  * priority interrupts are masked off.
  66  */
  67 volatile int irq_level;
  68 
  69 /*
  70  * Interrupt mapping table
  71  */
  72 static int ipl_table[NIRQS];            /* Vector -> level */
  73 static uint16_t mask_table[NIPLS];      /* Level -> mask */
  74 
  75 /*
  76  * Set mask for current ipl
  77  */
  78 #define update_mask()   ICU_IE = mask_table[irq_level]
  79 
  80 /*
  81  * Unmask interrupt in PIC 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         uint16_t unmask = (uint16_t)1 << vector;
  90 
  91         /* Save level mapping */
  92         ipl_table[vector] = level;
  93 
  94         /*
  95          * Unmask 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 PIC 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  * Dispatch interrupt
 132  */
 133 void
 134 interrupt_dispatch(int vector)
 135 {
 136         int old_ipl;
 137 
 138         /* Save & update interrupt level */
 139         old_ipl = irq_level;
 140         irq_level = ipl_table[vector];
 141         update_mask();
 142 
 143         /* Send acknowledge to ICU for this irq */
 144         ICU_IF = (uint16_t)(1 << vector);
 145 
 146         /* Allow another interrupt that has higher priority */
 147         splon();
 148 
 149         /* Dispatch interrupt */
 150         irq_handler(vector);
 151 
 152         sploff();
 153 
 154         /* Restore interrupt level */
 155         irq_level = old_ipl;
 156         update_mask();
 157 }
 158 
 159 /*
 160  * Common interrupt handler.
 161  */
 162 void
 163 interrupt_handler(void)
 164 {
 165         uint16_t bits;
 166         int vector;
 167 
 168         bits = ICU_IF;
 169 retry:
 170         for (vector = 0; vector < NIRQS; vector++) {
 171                 if (bits & (uint16_t)(1 << vector))
 172                         break;
 173         }
 174         if (vector == NIRQS)
 175                 goto out;
 176 
 177         interrupt_dispatch(vector);
 178 
 179         /*
 180          * Multiple interrupts can be fired in case of GBA.
 181          * So, we have to check the interrupt status, again.
 182          */
 183         bits = ICU_IF;
 184         if (bits & IRQ_VALID)
 185                 goto retry;
 186 out:
 187         return;
 188 }
 189 
 190 /*
 191  * Initialize interrupt controllers.
 192  * All interrupts will be masked off.
 193  */
 194 void
 195 interrupt_init(void)
 196 {
 197         int i;
 198 
 199         irq_level = IPL_NONE;
 200 
 201         for (i = 0; i < NIRQS; i++)
 202                 ipl_table[i] = IPL_NONE;
 203 
 204         for (i = 0; i < NIPLS; i++)
 205                 mask_table[i] = 0;
 206 
 207         ICU_IME = IRQ_OFF;
 208 
 209         /*
 210          * Since GBA has its own interrupt vector in ROM area,
 211          * we can not modify it. Instead, the GBA BIOS will
 212          * call the user's interrupt hook routine placed in
 213          * the address in 0x3007ffc.
 214          */
 215         IRQ_VECTOR = (uint32_t)interrupt_entry; /* Interrupt hook address */
 216         ICU_IE = 0;                     /* Mask all interrupts */
 217         ICU_IME = IRQ_ON;
 218 }

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