Project

General

Profile

Download (4.53 KB) Statistics
| Branch: | Tag: | Revision:
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
}
(25-25/40)
Add picture from clipboard (Maximum size: 48.8 MB)