1
|
/* SAM7S system interrupt demultiplexer
|
2
|
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
|
3
|
*
|
4
|
* This program is free software; you can redistribute it and/or modify
|
5
|
* it under the terms of the GNU General Public License as published by
|
6
|
* the Free Software Foundation; either version 2 of the License, or
|
7
|
* (at your option) any later version.
|
8
|
*
|
9
|
* This program is distributed in the hope that it will be useful,
|
10
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
* GNU General Public License for more details.
|
13
|
*
|
14
|
* You should have received a copy of the GNU General Public License
|
15
|
* along with this program; if not, write to the Free Software
|
16
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
*
|
18
|
*/
|
19
|
|
20
|
#undef DEBUG
|
21
|
|
22
|
#include <sys/types.h>
|
23
|
#include <lib_AT91SAM7.h>
|
24
|
#include <AT91SAM7.h>
|
25
|
|
26
|
#include <os/system_irq.h>
|
27
|
#include <os/dbgu.h>
|
28
|
#include <string.h>
|
29
|
|
30
|
#include "../openpcd.h"
|
31
|
|
32
|
static sysirq_hdlr *sysirq_hdlrs[AT91SAM7_SYSIRQ_COUNT];
|
33
|
|
34
|
void sys_irq(uint32_t previous_pc)
|
35
|
{
|
36
|
uint32_t sr;
|
37
|
|
38
|
/* Somehow Atmel decided to do really stupid interrupt sharing
|
39
|
* for commonly-used interrupts such as the timer irq */
|
40
|
|
41
|
/* dbgu */
|
42
|
if (*AT91C_DBGU_IMR) {
|
43
|
sr = *AT91C_DBGU_CSR;
|
44
|
if (sr & *AT91C_DBGU_IMR) {
|
45
|
DEBUGP("DBGU(");
|
46
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_DBGU]) {
|
47
|
DEBUGP("handler ");
|
48
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_DBGU](sr);
|
49
|
} else {
|
50
|
*AT91C_DBGU_IDR = *AT91C_DBGU_IMR;
|
51
|
DEBUGP("no handler ");
|
52
|
}
|
53
|
DEBUGP(") ");
|
54
|
}
|
55
|
}
|
56
|
|
57
|
/* pit_irq */
|
58
|
if (*AT91C_PITC_PIMR & AT91C_PITC_PITIEN) {
|
59
|
sr = *AT91C_PITC_PISR;
|
60
|
if (sr & AT91C_PITC_PITS) {
|
61
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_PIT]) {
|
62
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_PIT](sr);
|
63
|
} else {
|
64
|
DEBUGP("no handler DISABLE_PIT ");
|
65
|
*AT91C_PITC_PIMR &= ~AT91C_PITC_PITIEN;
|
66
|
}
|
67
|
}
|
68
|
}
|
69
|
|
70
|
/* rtt_irq */
|
71
|
if (*AT91C_RTTC_RTMR & (AT91C_RTTC_ALMIEN|AT91C_RTTC_RTTINCIEN)) {
|
72
|
sr = *AT91C_RTTC_RTSR;
|
73
|
if (sr) {
|
74
|
DEBUGP("RTT(");
|
75
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_RTT]) {
|
76
|
DEBUGP("handler ");
|
77
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_RTT](sr);
|
78
|
} else {
|
79
|
*AT91C_RTTC_RTMR &= ~(AT91C_RTTC_ALMIEN|
|
80
|
AT91C_RTTC_RTTINCIEN);
|
81
|
DEBUGP("no handler ");
|
82
|
}
|
83
|
DEBUGP(") ");
|
84
|
}
|
85
|
}
|
86
|
|
87
|
/* pmc_irq */
|
88
|
if (*AT91C_PMC_IMR) {
|
89
|
sr = *AT91C_PMC_SR;
|
90
|
if (sr & *AT91C_PMC_IMR) {
|
91
|
DEBUGP("PMC(");
|
92
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC]) {
|
93
|
DEBUGP("handler ");
|
94
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC](sr);
|
95
|
} else {
|
96
|
*AT91C_PMC_IDR = *AT91C_PMC_IMR;
|
97
|
DEBUGP("no handler ");
|
98
|
}
|
99
|
DEBUGP(") ");
|
100
|
}
|
101
|
}
|
102
|
|
103
|
/* rstc_irq */
|
104
|
if (*AT91C_RSTC_RMR & (AT91C_RSTC_URSTIEN|AT91C_RSTC_BODIEN)) {
|
105
|
sr = *AT91C_RSTC_RSR;
|
106
|
if (sr & (AT91C_RSTC_URSTS|AT91C_RSTC_BODSTS)) {
|
107
|
DEBUGP("RSTC(");
|
108
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_RSTC]) {
|
109
|
DEBUGP("handler ");
|
110
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_RSTC](sr);
|
111
|
} else {
|
112
|
*AT91C_RSTC_RMR &= ~(AT91C_RSTC_URSTIEN|
|
113
|
AT91C_RSTC_BODIEN);
|
114
|
DEBUGP("no handler ");
|
115
|
}
|
116
|
DEBUGP(") ");
|
117
|
}
|
118
|
}
|
119
|
|
120
|
/* mc_irq */
|
121
|
if (*AT91C_MC_FMR & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
|
122
|
sr = *AT91C_MC_FSR;
|
123
|
if ((*AT91C_MC_FMR & AT91C_MC_LOCKE && (sr & AT91C_MC_LOCKE))||
|
124
|
(*AT91C_MC_FMR & AT91C_MC_PROGE && (sr & AT91C_MC_PROGE))){
|
125
|
DEBUGP("EFC(");
|
126
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_EFC]) {
|
127
|
DEBUGP("handler ");
|
128
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_EFC](sr);
|
129
|
} else {
|
130
|
*AT91C_MC_FMR &= ~(AT91C_MC_LOCKE |
|
131
|
AT91C_MC_PROGE);
|
132
|
DEBUGP("no handler ");
|
133
|
}
|
134
|
DEBUGP(") ");
|
135
|
}
|
136
|
}
|
137
|
|
138
|
/* wdt_irq */
|
139
|
if (*AT91C_WDTC_WDMR & AT91C_WDTC_WDFIEN) {
|
140
|
sr = *AT91C_WDTC_WDSR;
|
141
|
if (sr) {
|
142
|
char dbg_buf[100];
|
143
|
sprintf(dbg_buf, "sys_irq [Old PC = %08X]\n\r", previous_pc);
|
144
|
AT91F_DBGU_Frame(dbg_buf);
|
145
|
|
146
|
DEBUGP("WDT(");
|
147
|
if (sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT]) {
|
148
|
DEBUGP("handler ");
|
149
|
sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT](sr);
|
150
|
} else {
|
151
|
/* we can't disable it... */
|
152
|
DEBUGP("no handler ");
|
153
|
}
|
154
|
DEBUGP(") ");
|
155
|
}
|
156
|
}
|
157
|
AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SYS);
|
158
|
DEBUGPCR("END");
|
159
|
}
|
160
|
|
161
|
static void sysirq_entry(void)
|
162
|
{
|
163
|
/* DON'T MODIFY THIS SECTION AND Cstartup.S/IRQ_Handler_Entry */
|
164
|
register unsigned *previous_pc asm("r0");
|
165
|
asm("ADD R1, SP, #16; LDR R0, [R1]");
|
166
|
sys_irq(previous_pc);
|
167
|
}
|
168
|
|
169
|
void sysirq_register(enum sysirqs irq, sysirq_hdlr *hdlr)
|
170
|
{
|
171
|
if (irq >= AT91SAM7_SYSIRQ_COUNT)
|
172
|
return;
|
173
|
|
174
|
sysirq_hdlrs[irq] = hdlr;
|
175
|
}
|
176
|
|
177
|
void sysirq_init(void)
|
178
|
{
|
179
|
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS,
|
180
|
OPENPCD_IRQ_PRIO_SYS,
|
181
|
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
|
182
|
&sysirq_entry);
|
183
|
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
|
184
|
}
|