Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / bsp / hal / arm / integrator / interrupt.c @ 03e9c04a

History | View | Annotate | Download (4.46 KB)

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
}