1 /*==========================================================================
5 // HAL misc board support code for Atmel AT91
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>
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.
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
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.
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.
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.
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####
45 // Contributors: gthomas, jskov, nickg, tkoeller
47 // Purpose: HAL board support
48 // Description: Implementations of HAL board interfaces
50 //####DESCRIPTIONEND####
52 //========================================================================*/
54 #include <pkgconf/hal.h>
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
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
70 #include <cyg/hal/var_io.h> // platform registers
72 // -------------------------------------------------------------------------
75 void hal_hardware_init(void)
79 // Reset all interrupts
80 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);
82 // Flush internal priority level stack
83 for (i = 0; i < 8; ++i)
84 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
86 #ifdef HAL_PLF_HARDWARE_INIT
87 // Perform any platform specific initializations
88 HAL_PLF_HARDWARE_INIT();
91 // Set up eCos/ROM interfaces
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
99 static int sys_irq_handler(void)
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;
111 #ifdef CYGNUM_HAL_INTERRUPT_DBG
113 HAL_READ_UINT32((AT91_DBG + AT91_DBG_CSR), sr);
114 HAL_READ_UINT32((AT91_DBG + AT91_DBG_IMR), mr);
116 return CYGNUM_HAL_INTERRUPT_DBG;
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;
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);
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;
150 #ifdef CYGNUM_HAL_INTERRUPT_MC
152 HAL_READ_UINT32((AT91_MC+AT91_MC_FMR), mr);
153 HAL_READ_UINT32((AT91_MC+AT91_MC_FSR), sr);
157 AT91_MC_FSR_PROGE)) {
158 return CYGNUM_HAL_INTERRUPT_MC;
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;
173 #ifdef CYGNUM_HAL_INTERRUPT_RSTC
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;
182 return CYGNUM_HAL_INTERRUPT_NONE;
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.
190 int hal_IRQ_handler(void)
194 #ifdef CYGHWR_HAL_ARM_AT91_FIQ
195 // handle fiq interrupts as irq
198 HAL_READ_UINT32(AT91_AIC+AT91_AIC_IPR, ipr);
199 HAL_READ_UINT32(AT91_AIC+AT91_AIC_IMR, imr);
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;
206 // Calculate active interrupt (updates ISR)
207 HAL_READ_UINT32(AT91_AIC+AT91_AIC_IVR, ivr);
209 HAL_READ_UINT32(AT91_AIC+AT91_AIC_ISR, irq_num);
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();
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;
224 // -------------------------------------------------------------------------
228 void hal_interrupt_mask(int vector)
230 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
231 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
233 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
235 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR,
236 (1 << CYGINT_HAL_ARM_AT91_SYS_INTERRUPT));
240 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, (1<<vector));
243 void hal_interrupt_unmask(int vector)
245 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
246 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
248 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
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));
256 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR, (1<<vector));
259 void hal_interrupt_acknowledge(int vector)
261 // No check for valid vector here! Spurious interrupts
262 // must be acknowledged, too.
263 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
266 void hal_interrupt_configure(int vector, int level, int up)
270 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
271 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
273 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
279 mode = AT91_AIC_SMR_LEVEL_HI;
281 mode = AT91_AIC_SMR_LEVEL_LOW;
285 mode = AT91_AIC_SMR_EDGE_POS;
287 mode = AT91_AIC_SMR_EDGE_NEG;
290 mode |= 7; // Default priority
291 HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
294 void hal_interrupt_set_level(int vector, int level)
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");
302 #if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
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);
312 void hal_show_IRQ(int vector, int data, int handler)
314 // UNDEFINED(__FUNCTION__); // FIXME
319 /* Use the watchdog to generate a reset */
320 void hal_at91_reset_cpu(void)
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,
328 AT91_WD_OMR_EXTEN | // also reset external circuitry
330 while(1) CYG_EMPTY_STATEMENT;
333 /* Use the Reset Controller to generate a reset */
334 void hal_at91_reset_cpu(void)
336 HAL_WRITE_UINT32(AT91_RST + AT91_RST_RCR,
337 AT91_RST_RCR_PROCRST |
338 AT91_RST_RCR_ICERST |
339 AT91_RST_RCR_PERRST |
341 while(1) CYG_EMPTY_STATEMENT;
344 //--------------------------------------------------------------------------