]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/at91/var/v2_0/src/at91_misc.c
Initial revision
[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 // Clock support
74
75 static cyg_uint32 _period;
76
77 void hal_clock_initialize(cyg_uint32 period)
78 {
79     CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
80
81     CYG_ASSERT(period < 0x10000, "Invalid clock period");
82
83     // Disable counter
84     HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
85
86     // Set registers
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);
90
91     // Start timer
92     HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
93
94     // Enable timer 0 interrupt    
95     HAL_WRITE_UINT32(timer+AT91_TC_IER, AT91_TC_IER_CPC);
96 }
97
98 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
99 {
100     CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
101     cyg_uint32 sr;
102
103     CYG_ASSERT(period < 0x10000, "Invalid clock period");
104
105     HAL_READ_UINT32(timer+AT91_TC_SR, sr);  // Clear interrupt
106
107     if (period != _period) {
108         hal_clock_initialize(period);
109     }
110     _period = period;
111
112 }
113
114 void hal_clock_read(cyg_uint32 *pvalue)
115 {
116     CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
117     cyg_uint32 val;
118
119     HAL_READ_UINT32(timer+AT91_TC_CV, val);
120     *pvalue = val;
121 }
122
123 // -------------------------------------------------------------------------
124 //
125 // Delay for some number of micro-seconds
126 //   Use timer #2 in MCLOCK/32 mode.
127 //
128 void hal_delay_us(cyg_int32 usecs)
129 {
130     cyg_uint32 stat;
131     cyg_uint64 ticks;
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;
135 #else
136     CYG_ADDRESS timer = AT91_TC+AT91_TC_TC2;
137 #endif
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;
142     
143     // Disable counter
144     HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
145
146     // Set registers
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);
150
151         // Clear status flags
152     HAL_READ_UINT32(timer+AT91_TC_SR, stat);
153
154     // Start timer
155     HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
156
157     // Wait for the compare
158     do {
159         HAL_READ_UINT32(timer+AT91_TC_SR, stat);
160     } while ((stat & AT91_TC_SR_CPC) == 0);
161 }
162
163 // -------------------------------------------------------------------------
164 // Hardware init
165
166 void hal_hardware_init(void)
167 {
168     unsigned i;
169
170     // Reset all interrupts
171     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);
172
173     // Flush internal priority level stack
174     for (i = 0; i < 8; ++i)
175         HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
176     
177     // Set up eCos/ROM interfaces
178     hal_if_init();
179
180 }
181
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.
185
186 int hal_IRQ_handler(void)
187 {
188     cyg_uint32 irq_num;
189     cyg_uint32 ivr;
190 #ifdef CYGHWR_HAL_ARM_AT91_FIQ
191     // handle fiq interrupts as irq 
192     cyg_uint32 ipr,imr;
193
194     HAL_READ_UINT32(AT91_AIC+AT91_AIC_IPR, ipr);
195     HAL_READ_UINT32(AT91_AIC+AT91_AIC_IMR, imr);
196
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;
200     }
201 #endif
202     // Calculate active interrupt (updates ISR)
203     HAL_READ_UINT32(AT91_AIC+AT91_AIC_IVR, ivr);
204
205     HAL_READ_UINT32(AT91_AIC+AT91_AIC_ISR, irq_num);
206
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;
210     
211     return irq_num;
212 }
213
214 // -------------------------------------------------------------------------
215 // Interrupt control
216 //
217
218 void hal_interrupt_mask(int vector)
219 {
220     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
221                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
222
223     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, (1<<vector));
224 }
225
226 void hal_interrupt_unmask(int vector)
227 {
228     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
229                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
230
231     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR, (1<<vector));
232 }
233
234 void hal_interrupt_acknowledge(int vector)
235 {
236     // No check for valid vector here! Spurious interrupts
237     // must be acknowledged, too.
238     HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);  
239 }
240
241 void hal_interrupt_configure(int vector, int level, int up)
242 {
243     cyg_uint32 mode;
244
245     CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
246                vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
247
248     if (level) {
249         if (up) {
250             mode = AT91_AIC_SMR_LEVEL_HI;
251         } else {
252             mode = AT91_AIC_SMR_LEVEL_LOW;
253         }
254     } else {
255         if (up) {
256             mode = AT91_AIC_SMR_EDGE_POS;
257         } else {
258             mode = AT91_AIC_SMR_EDGE_NEG;
259         }
260     }
261     mode |= 7;  // Default priority
262     HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
263 }
264
265 void hal_interrupt_set_level(int vector, int level)
266 {
267     cyg_uint32 mode;
268
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");
272
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);
276 }
277
278 void hal_show_IRQ(int vector, int data, int handler)
279 {
280 //    UNDEFINED(__FUNCTION__);  // FIXME
281 }
282
283
284 /* Use the watchdog to generate a reset */
285 void hal_at91_reset_cpu(void)
286 {
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;
292 }
293
294 //--------------------------------------------------------------------------
295 // EOF at91_misc.c