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 static cyg_uint32 _period;
77 void hal_clock_initialize(cyg_uint32 period)
79 CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
81 CYG_ASSERT(period < 0x10000, "Invalid clock period");
84 HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
87 HAL_WRITE_UINT32(timer+AT91_TC_CMR, AT91_TC_CMR_CPCTRG | // Reset counter on CPC
88 AT91_TC_CMR_CLKS_MCK32); // 1 MHz
89 HAL_WRITE_UINT32(timer+AT91_TC_RC, period);
92 HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
94 // Enable timer 0 interrupt
95 HAL_WRITE_UINT32(timer+AT91_TC_IER, AT91_TC_IER_CPC);
98 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
100 CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
103 CYG_ASSERT(period < 0x10000, "Invalid clock period");
105 HAL_READ_UINT32(timer+AT91_TC_SR, sr); // Clear interrupt
107 if (period != _period) {
108 hal_clock_initialize(period);
114 void hal_clock_read(cyg_uint32 *pvalue)
116 CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
119 HAL_READ_UINT32(timer+AT91_TC_CV, val);
123 // -------------------------------------------------------------------------
125 // Delay for some number of micro-seconds
126 // Use timer #2 in MCLOCK/32 mode.
128 void hal_delay_us(cyg_int32 usecs)
132 #if defined(CYGHWR_HAL_ARM_AT91_JTST)
133 // TC2 is reserved for AD/DA. Use TC1 instead.
134 CYG_ADDRESS timer = AT91_TC+AT91_TC_TC1;
136 CYG_ADDRESS timer = AT91_TC+AT91_TC_TC2;
138 // Calculate how many timer ticks the required number of
139 // microseconds equate to. We do this calculation in 64 bit
140 // arithmetic to avoid overflow.
141 ticks = (((cyg_uint64)usecs) * ((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/32000000LL;
144 HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
147 HAL_WRITE_UINT32(timer+AT91_TC_CMR, AT91_TC_CMR_CLKS_MCK32); // 1MHz
148 HAL_WRITE_UINT32(timer+AT91_TC_RA, 0);
149 HAL_WRITE_UINT32(timer+AT91_TC_RC, ticks);
151 // Clear status flags
152 HAL_READ_UINT32(timer+AT91_TC_SR, stat);
155 HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
157 // Wait for the compare
159 HAL_READ_UINT32(timer+AT91_TC_SR, stat);
160 } while ((stat & AT91_TC_SR_CPC) == 0);
163 // -------------------------------------------------------------------------
166 void hal_hardware_init(void)
170 // Reset all interrupts
171 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);
173 // Flush internal priority level stack
174 for (i = 0; i < 8; ++i)
175 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
177 // Set up eCos/ROM interfaces
182 // -------------------------------------------------------------------------
183 // This routine is called to respond to a hardware interrupt (IRQ). It
184 // should interrogate the hardware and return the IRQ vector number.
186 int hal_IRQ_handler(void)
190 #ifdef CYGHWR_HAL_ARM_AT91_FIQ
191 // handle fiq interrupts as irq
194 HAL_READ_UINT32(AT91_AIC+AT91_AIC_IPR, ipr);
195 HAL_READ_UINT32(AT91_AIC+AT91_AIC_IMR, imr);
197 if (imr & ipr & (1 << CYGNUM_HAL_INTERRUPT_FIQ)) {
198 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_ICCR, (1 << CYGNUM_HAL_INTERRUPT_FIQ));
199 return CYGNUM_HAL_INTERRUPT_FIQ;
202 // Calculate active interrupt (updates ISR)
203 HAL_READ_UINT32(AT91_AIC+AT91_AIC_IVR, ivr);
205 HAL_READ_UINT32(AT91_AIC+AT91_AIC_ISR, irq_num);
207 // An invalid interrrupt source is treated as a spurious interrupt
208 if (irq_num < CYGNUM_HAL_ISR_MIN || irq_num > CYGNUM_HAL_ISR_MAX)
209 irq_num = CYGNUM_HAL_INTERRUPT_NONE;
214 // -------------------------------------------------------------------------
218 void hal_interrupt_mask(int vector)
220 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
221 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
223 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, (1<<vector));
226 void hal_interrupt_unmask(int vector)
228 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
229 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
231 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR, (1<<vector));
234 void hal_interrupt_acknowledge(int vector)
236 // No check for valid vector here! Spurious interrupts
237 // must be acknowledged, too.
238 HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
241 void hal_interrupt_configure(int vector, int level, int up)
245 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
246 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
250 mode = AT91_AIC_SMR_LEVEL_HI;
252 mode = AT91_AIC_SMR_LEVEL_LOW;
256 mode = AT91_AIC_SMR_EDGE_POS;
258 mode = AT91_AIC_SMR_EDGE_NEG;
261 mode |= 7; // Default priority
262 HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
265 void hal_interrupt_set_level(int vector, int level)
269 CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
270 vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
271 CYG_ASSERT(level >= 0 && level <= 7, "Invalid level");
273 HAL_READ_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
274 mode = (mode & ~AT91_AIC_SMR_PRIORITY) | level;
275 HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
278 void hal_show_IRQ(int vector, int data, int handler)
280 // UNDEFINED(__FUNCTION__); // FIXME
284 /* Use the watchdog to generate a reset */
285 void hal_at91_reset_cpu(void)
287 HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY);
288 HAL_WRITE_UINT32(AT91_WD + AT91_WD_CMR, AT91_WD_CMR_CKEY);
289 HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
290 HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY | AT91_WD_OMR_RSTEN | AT91_WD_OMR_WDEN);
291 while(1) CYG_EMPTY_STATEMENT;
294 //--------------------------------------------------------------------------