|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/hal/arm/integrator/interrupt.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.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] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |