1 //==========================================================================
5 // HAL misc board support code for Intel PXA2X0
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 Gary Thomas
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####
44 // Author(s): <knud.woehler@microplex.de>
47 //####DESCRIPTIONEND####
49 //========================================================================*/
51 #include <pkgconf/hal.h>
52 #include <pkgconf/system.h>
53 #include CYGBLD_HAL_PLATFORM_H
54 #include <cyg/infra/cyg_type.h>
55 #include <cyg/infra/cyg_trac.h>
56 #include <cyg/infra/cyg_ass.h>
57 #include <cyg/hal/hal_misc.h>
58 #include <cyg/hal/hal_io.h>
59 #include <cyg/hal/hal_stub.h>
60 #include <cyg/hal/hal_arch.h>
61 #include <cyg/hal/hal_diag.h>
62 #include <cyg/hal/hal_intr.h>
63 #include <cyg/hal/hal_cache.h>
64 #include <cyg/hal/hal_pxa2x0.h>
65 #include <cyg/hal/hal_mm.h>
66 #include <cyg/infra/diag.h>
69 // Initialize the interrupt environment
70 externC void plf_hardware_init(void);
72 void hal_hardware_init(void)
74 hal_xscale_core_init();
76 *PXA2X0_ICMR = 0; // IRQ Mask
77 *PXA2X0_ICLR = 0; // Route interrupts to IRQ
80 *PXA2X0_GRER0 = 0; // Disable rising edge detect
84 *PXA2X0_GFER0 = 0; // Disable falling edge detect
88 *PXA2X0_GEDR0 = 0xffffffff; // Clear edge detect status
89 *PXA2X0_GEDR1 = 0xffffffff;
90 *PXA2X0_GEDR2 = 0x0001ffff;
92 plf_hardware_init(); // Perform any platform specific initializations
94 *PXA2X0_OSCR = 0; // Let the "OS" counter run
97 #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
98 HAL_DCACHE_ENABLE(); // Enable caches
100 #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
106 // GPIO support functions
109 _pxa2x0_set_GPIO_mode(int bit, int mode, int dir)
112 unsigned volatile long *gpdr, *gafr;
114 gpdr = &PXA2X0_GPDR0[bank];
115 gafr = &PXA2X0_GAFR0_L[(bit&0x30)>>4];
117 // Data direction registers have 1 bit per GPIO
118 *gpdr = (*gpdr & ~(1<<bit)) | (dir<<bit);
119 // Alternate function regusters have 2 bits per GPIO
120 bit = (bit & 0x0F) * 2;
121 *gafr = (*gafr & ~(3<<bit)) | (mode<<bit);
125 // Initialize the clock
126 static cyg_uint32 clock_period;
128 void hal_clock_initialize(cyg_uint32 period)
130 *PXA2X0_OSMR0 = period; // Load match value
131 clock_period = period;
133 *PXA2X0_OSCR = 0; // Start the counter
134 *PXA2X0_OSSR = PXA2X0_OSSR_TIMER0; // Clear any pending interrupt
135 *PXA2X0_OIER |= PXA2X0_OIER_TIMER0; // Enable timer 0 interrupt
137 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_TIMER0 ); // Unmask timer 0 interrupt
140 // This routine is called during a clock interrupt.
141 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
143 *PXA2X0_OSMR0 = *PXA2X0_OSCR + period; // Load new match value
144 *PXA2X0_OSSR = PXA2X0_OSSR_TIMER0; // Clear any pending interrupt
147 // Read the current value of the clock, returning the number of hardware
148 // "ticks" that have occurred (i.e. how far away the current value is from
151 // Note: The "contract" for this function is that the value is the number
152 // of hardware clocks that have happened since the last interrupt (i.e.
153 // when it was reset). This value is used to measure interrupt latencies.
154 // However, since the hardware counter runs freely, this routine computes
155 // the difference between the current clock period and the number of hardware
156 // ticks left before the next timer interrupt.
157 void hal_clock_read(cyg_uint32 *pvalue)
160 HAL_DISABLE_INTERRUPTS(orig);
161 *pvalue = clock_period + *PXA2X0_OSCR - *PXA2X0_OSMR0;
162 HAL_RESTORE_INTERRUPTS(orig);
165 // Delay for some number of micro-seconds
166 void hal_delay_us(cyg_int32 usecs)
169 cyg_uint32 ctr = *PXA2X0_OSCR;
170 while (usecs-- > 0) {
172 if (ctr != *PXA2X0_OSCR) {
173 val += 271267; // 271267ps (3.6865Mhz -> 271.267ns)
176 } while (val < 1000000);
182 // Interrupt handling
184 // This routine is called to respond to a hardware interrupt (IRQ). It
185 // should interrogate the hardware and return the IRQ vector number.
186 int hal_IRQ_handler(void)
188 cyg_uint32 sources, index;
190 sources = *PXA2X0_ICIP;
192 #ifdef HAL_EXTENDED_IRQ_HANDLER
193 // Use platform specific IRQ handler, if defined
194 // Note: this macro should do a 'return' with the appropriate
195 // interrupt number if such an extended interrupt exists. The
196 // assumption is that the line after the macro starts 'normal' processing.
197 HAL_EXTENDED_IRQ_HANDLER(sources);
200 if ( sources & 0xff0000 )
202 else if ( sources & 0xff00 )
204 else if ( sources & 0xff )
206 else // if ( sources & 0xff000000 )
210 if ( (1 << index) & sources ) {
211 if (index == CYGNUM_HAL_INTERRUPT_GPIO) {
212 // Special case of GPIO cascade. Search for lowest set bit
213 sources = *PXA2X0_GEDR0;
216 if (sources & (1 << index)) {
220 } while (index < 32);
221 sources = *PXA2X0_GEDR1;
224 if (sources & (1 << index)) {
228 } while (index < 32);
229 sources = *PXA2X0_GEDR2;
232 if (sources & (1 << index)) {
236 } while (index < 21);
242 } while ( index & 7 );
244 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
247 void hal_interrupt_mask(int vector)
250 #ifdef HAL_EXTENDED_INTERRUPT_MASK
251 // Use platform specific handling, if defined
252 // Note: this macro should do a 'return' for "extended" values of 'vector'
253 // Normal vectors are handled by code subsequent to the macro call.
254 HAL_EXTENDED_INTERRUPT_MASK(vector);
257 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO2) {
258 vector = CYGNUM_HAL_INTERRUPT_GPIO;
260 *PXA2X0_ICMR &= ~(1 << vector);
263 void hal_interrupt_unmask(int vector)
266 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
267 // Use platform specific handling, if defined
268 // Note: this macro should do a 'return' for "extended" values of 'vector'
269 // Normal vectors are handled by code subsequent to the macro call.
270 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
273 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO2) {
274 vector = CYGNUM_HAL_INTERRUPT_GPIO;
276 *PXA2X0_ICMR |= (1 << vector);
279 void hal_interrupt_acknowledge(int vector)
282 #ifdef HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE
283 // Use platform specific handling, if defined
284 // Note: this macro should do a 'return' for "extended" values of 'vector'
285 // Normal vectors are handled by code subsequent to the macro call.
286 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
288 if (vector == CYGNUM_HAL_INTERRUPT_GPIO0 || vector == CYGNUM_HAL_INTERRUPT_GPIO1)
290 *PXA2X0_GEDR0 = (1 << (vector - 8));
292 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO64) {
293 *PXA2X0_GEDR2 = (1 << (vector - 96));
294 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO32) {
295 *PXA2X0_GEDR1 = (1 << (vector - 64));
296 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO2) {
297 *PXA2X0_GEDR0 = (1 << (vector - 32));
299 // Not a GPIO interrupt
305 void hal_interrupt_configure(int vector, int level, int up)
308 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
309 // Use platform specific handling, if defined
310 // Note: this macro should do a 'return' for "extended" values of 'vector'
311 // Normal vectors are handled by code subsequent to the macro call.
312 HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
314 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO64) {
318 *PXA2X0_GRER2 |= (1 << (vector - 96));
319 *PXA2X0_GFER2 |= (1 << (vector - 96));
321 // Disable both edges
322 *PXA2X0_GRER2 &= ~(1 << (vector - 96));
323 *PXA2X0_GFER2 &= ~(1 << (vector - 96));
326 // Only interested in one edge
328 // Set rising edge detect and clear falling edge detect.
329 *PXA2X0_GRER2 |= (1 << (vector - 96));
330 *PXA2X0_GFER2 &= ~(1 << (vector - 96));
332 // Set falling edge detect and clear rising edge detect.
333 *PXA2X0_GFER2 |= (1 << (vector - 96));
334 *PXA2X0_GRER2 &= ~(1 << (vector - 96));
337 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO32) {
341 *PXA2X0_GRER1 |= (1 << (vector - 64));
342 *PXA2X0_GFER1 |= (1 << (vector - 64));
344 // Disable both edges
345 *PXA2X0_GRER1 &= ~(1 << (vector - 64));
346 *PXA2X0_GFER1 &= ~(1 << (vector - 64));
349 // Only interested in one edge
351 // Set rising edge detect and clear falling edge detect.
352 *PXA2X0_GRER1 |= (1 << (vector - 64));
353 *PXA2X0_GFER1 &= ~(1 << (vector - 64));
355 // Set falling edge detect and clear rising edge detect.
356 *PXA2X0_GFER1 |= (1 << (vector - 64));
357 *PXA2X0_GRER1 &= ~(1 << (vector - 64));
360 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO2) {
364 *PXA2X0_GRER0 |= (1 << (vector - 32));
365 *PXA2X0_GFER0 |= (1 << (vector - 32));
367 // Disable both edges
368 *PXA2X0_GRER0 &= ~(1 << (vector - 32));
369 *PXA2X0_GFER0 &= ~(1 << (vector - 32));
372 // Only interested in one edge
374 // Set rising edge detect and clear falling edge detect.
375 *PXA2X0_GRER0 |= (1 << (vector - 32));
376 *PXA2X0_GFER0 &= ~(1 << (vector - 32));
378 // Set falling edge detect and clear rising edge detect.
379 *PXA2X0_GFER0 |= (1 << (vector - 32));
380 *PXA2X0_GRER0 &= ~(1 << (vector - 32));
383 } else if (vector == CYGNUM_HAL_INTERRUPT_GPIO0 || vector == CYGNUM_HAL_INTERRUPT_GPIO1)
388 *PXA2X0_GRER0 |= (1 << (vector - 8));
389 *PXA2X0_GFER0 |= (1 << (vector - 8));
391 // Disable both edges
392 *PXA2X0_GRER0 &= ~(1 << (vector - 8));
393 *PXA2X0_GFER0 &= ~(1 << (vector - 8));
396 // Only interested in one edge
398 // Set rising edge detect and clear falling edge detect.
399 *PXA2X0_GRER0 |= (1 << (vector - 8));
400 *PXA2X0_GFER0 &= ~(1 << (vector - 8));
402 // Set falling edge detect and clear rising edge detect.
403 *PXA2X0_GFER0 |= (1 << (vector - 8));
404 *PXA2X0_GRER0 &= ~(1 << (vector - 8));
412 void hal_interrupt_set_level(int vector, int level)
415 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
416 // Use platform specific handling, if defined
417 // Note: this macro should do a 'return' for "extended" values of 'vector'
418 // Normal vectors are handled by code subsequent to the macro call.
419 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);