]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/at91/var/v2_0/src/at91_misc.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / at91 / var / v2_0 / src / at91_misc.c
1 /*==========================================================================
2 //
3 //      at91_misc.c
4 //
5 //      HAL misc board support code for Atmel AT91
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    gthomas
45 // Contributors: gthomas, jskov, nickg, tkoeller
46 // Date:         2001-07-12
47 // Purpose:      HAL board support
48 // Description:  Implementations of HAL board interfaces
49 //
50 //####DESCRIPTIONEND####
51 //
52 //========================================================================*/
53
54 #include <pkgconf/hal.h>
55
56 #include <cyg/infra/cyg_type.h>         // base types
57 #include <cyg/infra/cyg_trac.h>         // tracing macros
58 #include <cyg/infra/cyg_ass.h>          // assertion macros
59
60 #include <cyg/hal/hal_io.h>             // IO macros
61 #include <cyg/hal/hal_arch.h>           // Register state info
62 #include <cyg/hal/hal_diag.h>
63 #include <cyg/hal/hal_intr.h>           // necessary?
64 #include <cyg/hal/hal_cache.h>
65 #include <cyg/hal/hal_if.h>             // calling interface
66 #include <cyg/hal/hal_misc.h>           // helper functions
67 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
68 #include <cyg/hal/drv_api.h>            // HAL ISR support
69 #endif
70 #include <cyg/hal/var_io.h>             // platform registers
71
72 // -------------------------------------------------------------------------
73 // Hardware init
74
75 void hal_hardware_init(void)
76 {
77     unsigned i;
78
79     // Reset all interrupts
80     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);
81
82     // Flush internal priority level stack
83     for (i = 0; i < 8; ++i)
84         HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
85
86 #ifdef HAL_PLF_HARDWARE_INIT
87     // Perform any platform specific initializations
88     HAL_PLF_HARDWARE_INIT();
89 #endif
90
91     // Set up eCos/ROM interfaces
92     hal_if_init();
93 }
94
95 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
96 // Decode a system interrupt. Not all systems have all interrupts. So
97 // code will only be generated for those interrupts which have a
98 // defined value.
99 static int sys_irq_handler(void)
100 {
101   cyg_uint32 sr, mr;
102
103 #ifdef CYGNUM_HAL_INTERRUPT_PITC
104   // Periodic Interrupt Timer Controller
105   HAL_READ_UINT32((AT91_PITC+AT91_PITC_PISR), sr);
106   if (sr & AT91_PITC_PISR_PITS) {
107     return CYGNUM_HAL_INTERRUPT_PITC;
108   }
109 #endif
110
111 #ifdef CYGNUM_HAL_INTERRUPT_DBG
112   // Debug Unit
113   HAL_READ_UINT32((AT91_DBG + AT91_DBG_CSR), sr);
114   HAL_READ_UINT32((AT91_DBG + AT91_DBG_IMR), mr);
115   if (sr & mr) {
116     return CYGNUM_HAL_INTERRUPT_DBG;
117   }
118 #endif
119
120 #ifdef CYGNUM_HAL_INTERRUPT_RTTC
121   /* Real Time Timer. Check the interrupt is enabled, not that just
122      the status indicates there is an interrupt. It takes a while for
123      the status bit to clear. */
124   HAL_READ_UINT32((AT91_RTTC+AT91_RTTC_RTSR), sr);
125   HAL_READ_UINT32((AT91_RTTC+AT91_RTTC_RTMR), mr);
126   if (((mr & AT91_RTTC_RTMR_ALMIEN) &&
127        (sr & AT91_RTTC_RTSR_ALMS)) ||
128       ((mr & AT91_RTTC_RTMR_RTTINCIEN) &&
129        (sr & AT91_RTTC_RTSR_RTTINC))) {
130     return CYGNUM_HAL_INTERRUPT_RTTC;
131   }
132 #endif
133
134 #ifdef CYGNUM_HAL_INTERRUPT_PMC
135   // Power Management Controller
136   HAL_READ_UINT32((AT91_PMC+AT91_PMC_IMR), mr);
137   HAL_READ_UINT32((AT91_PMC+AT91_PMC_SR), sr);
138   if ((sr & mr) & 
139       (AT91_PMC_SR_MOSCS   |
140        AT91_PMC_SR_LOCK    |
141        AT91_PMC_SR_MCKRDY  |
142        AT91_PMC_SR_PCK0RDY |
143        AT91_PMC_SR_PCK1RDY |
144        AT91_PMC_SR_PCK2RDY |
145        AT91_PMC_SR_PCK3RDY)) {
146     return CYGNUM_HAL_INTERRUPT_PMC;
147   }
148 #endif
149
150 #ifdef CYGNUM_HAL_INTERRUPT_MC
151   // Memory controller
152   HAL_READ_UINT32((AT91_MC+AT91_MC_FMR), mr);
153   HAL_READ_UINT32((AT91_MC+AT91_MC_FSR), sr);
154   if ((sr & mr) & 
155       (AT91_MC_FSR_FRDY  |
156        AT91_MC_FSR_LOCKE |
157        AT91_MC_FSR_PROGE)) {
158     return CYGNUM_HAL_INTERRUPT_MC;
159   }
160 #endif
161
162 #ifdef CYGNUM_HAL_INTERRUPT_WDTC
163   // Watchdog Timer Controller
164   HAL_READ_UINT32((AT91_WDTC+AT91_WDTC_WDSR), sr);
165   HAL_READ_UINT32((AT91_WDTC+AT91_WDTC_WDMR), mr);
166   if ((mr & AT91_WDTC_WDMR_FIEN) &&
167       sr & (AT91_WDTC_WDSR_UNDER |
168             AT91_WDTC_WDSR_ERROR)) {
169     return CYGNUM_HAL_INTERRUPT_WDTC;
170   }
171 #endif
172
173 #ifdef CYGNUM_HAL_INTERRUPT_RSTC
174   // Reset Controller
175   HAL_READ_UINT32((AT91_RST + AT91_RST_RSR), sr);
176   HAL_READ_UINT32((AT91_RST + AT91_RST_RMR), mr);
177   if (((mr & AT91_RST_RMR_URSTIEN) && (sr & AT91_RST_RSR_USER)) ||  
178       ((mr & AT91_RST_RMR_BODIEN) && (sr & AT91_RST_RSR_BROWN)))
179     return CYGNUM_HAL_INTERRUPT_RSTC;
180 #endif
181   
182   return CYGNUM_HAL_INTERRUPT_NONE;
183 }
184 #endif
185
186 // -------------------------------------------------------------------------
187 // This routine is called to respond to a hardware interrupt (IRQ).  It
188 // should interrogate the hardware and return the IRQ vector number.
189
190 int hal_IRQ_handler(void)
191 {
192     cyg_uint32 irq_num;
193     cyg_uint32 ivr;
194 #ifdef CYGHWR_HAL_ARM_AT91_FIQ
195     // handle fiq interrupts as irq 
196     cyg_uint32 ipr,imr;
197
198     HAL_READ_UINT32(AT91_AIC+AT91_AIC_IPR, ipr);
199     HAL_READ_UINT32(AT91_AIC+AT91_AIC_IMR, imr);
200
201     if (imr & ipr & (1 << CYGNUM_HAL_INTERRUPT_FIQ)) {
202       HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_ICCR, (1 << CYGNUM_HAL_INTERRUPT_FIQ));
203       return CYGNUM_HAL_INTERRUPT_FIQ;
204     }
205 #endif
206     // Calculate active interrupt (updates ISR)
207     HAL_READ_UINT32(AT91_AIC+AT91_AIC_IVR, ivr);
208
209     HAL_READ_UINT32(AT91_AIC+AT91_AIC_ISR, irq_num);
210
211 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
212     if (irq_num == CYGNUM_HAL_INTERRUPT_SYS) {
213       // determine the source of the system interrupt
214       irq_num = sys_irq_handler();
215     }
216 #endif
217     // An invalid interrupt source is treated as a spurious interrupt    
218     if (irq_num < CYGNUM_HAL_ISR_MIN || irq_num > CYGNUM_HAL_ISR_MAX)
219       irq_num = CYGNUM_HAL_INTERRUPT_NONE;
220     
221     return irq_num;
222 }
223
224 // -------------------------------------------------------------------------
225 // Interrupt control
226 //
227
228 void hal_interrupt_mask(int vector)
229 {
230     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
231                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
232
233 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
234     if (vector >= 32) {
235       HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 
236                        (1 << CYGINT_HAL_ARM_AT91_SYS_INTERRUPT));
237       return;
238     }
239 #endif
240     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, (1<<vector));
241 }
242
243 void hal_interrupt_unmask(int vector)
244 {
245     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
246                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
247
248 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
249     if (vector >= 32) {
250       hal_interrupt_configure(CYGINT_HAL_ARM_AT91_SYS_INTERRUPT, true, true);
251       HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR, 
252                        (1 <<CYGINT_HAL_ARM_AT91_SYS_INTERRUPT));
253       return;
254     }
255 #endif
256     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR, (1<<vector));
257 }
258
259 void hal_interrupt_acknowledge(int vector)
260 {
261     // No check for valid vector here! Spurious interrupts
262     // must be acknowledged, too.
263     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);  
264 }
265
266 void hal_interrupt_configure(int vector, int level, int up)
267 {
268     cyg_uint32 mode;
269
270     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
271                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
272
273 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
274     if (vector >= 32) 
275       return;
276 #endif
277     if (level) {
278         if (up) {
279             mode = AT91_AIC_SMR_LEVEL_HI;
280         } else {
281             mode = AT91_AIC_SMR_LEVEL_LOW;
282         }
283     } else {
284         if (up) {
285             mode = AT91_AIC_SMR_EDGE_POS;
286         } else {
287             mode = AT91_AIC_SMR_EDGE_NEG;
288         }
289     }
290     mode |= 7;  // Default priority
291     HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
292 }
293
294 void hal_interrupt_set_level(int vector, int level)
295 {
296     cyg_uint32 mode;
297
298     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
299                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
300     CYG_ASSERT(level >= 0 && level <= 7, "Invalid level");
301
302 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
303     if (vector >= 32) 
304       return;
305 #endif
306
307     HAL_READ_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
308     mode = (mode & ~AT91_AIC_SMR_PRIORITY) | level;
309     HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
310 }
311
312 void hal_show_IRQ(int vector, int data, int handler)
313 {
314 //    UNDEFINED(__FUNCTION__);  // FIXME
315 }
316
317
318 #ifndef AT91_RST
319 /* Use the watchdog to generate a reset */
320 void hal_at91_reset_cpu(void)
321 {
322     HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY);
323     HAL_WRITE_UINT32(AT91_WD + AT91_WD_CMR, AT91_WD_CMR_CKEY);
324     HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
325     HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, 
326                      (AT91_WD_OMR_OKEY | 
327                       AT91_WD_OMR_RSTEN |
328                       AT91_WD_OMR_EXTEN | // also reset external circuitry
329                       AT91_WD_OMR_WDEN));
330     while(1) CYG_EMPTY_STATEMENT;
331 }
332 #else
333 /* Use the Reset Controller to generate a reset */
334 void hal_at91_reset_cpu(void)
335 {
336   HAL_WRITE_UINT32(AT91_RST + AT91_RST_RCR,
337                    AT91_RST_RCR_PROCRST |                   
338                    AT91_RST_RCR_ICERST  |
339                    AT91_RST_RCR_PERRST  |
340                    AT91_RST_RCR_KEY);
341   while(1) CYG_EMPTY_STATEMENT;
342 }
343 #endif
344 //--------------------------------------------------------------------------
345 // EOF at91_misc.c