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 #if defined(CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA25X)
89 *PXA2X0_GEDR0 = 0xffffffff; // Clear edge detect status
90 *PXA2X0_GEDR1 = 0xffffffff;
91 *PXA2X0_GEDR2 = 0x0001ffff;
92 #elif defined(CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X)
99 *PXA2X0_GEDR0 = 0xfffff71b;
100 *PXA2X0_GEDR1 = 0xffffffff;
101 *PXA2X0_GEDR2 = 0xffffffff;
102 *PXA2X0_GEDR3 = 0x1fffffff;
105 plf_hardware_init(); // Perform any platform specific initializations
107 *PXA2X0_OSCR = 0; // Let the "OS" counter run
110 #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
111 HAL_DCACHE_ENABLE(); // Enable caches
113 #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
119 // GPIO support functions
122 _pxa2x0_set_GPIO_mode(int bit, int mode, int dir)
125 unsigned volatile long *gpdr, *gafr;
127 gpdr = &PXA2X0_GPDR0[bank];
128 gafr = &PXA2X0_GAFR0_L[(bit&0x30)>>4];
130 // Data direction registers have 1 bit per GPIO
131 *gpdr = (*gpdr & ~(1<<bit)) | (dir<<bit);
132 // Alternate function regusters have 2 bits per GPIO
133 bit = (bit & 0x0F) * 2;
134 *gafr = (*gafr & ~(3<<bit)) | (mode<<bit);
138 // Initialize the clock
139 static cyg_uint32 clock_period;
141 void hal_clock_initialize(cyg_uint32 period)
143 *PXA2X0_OSMR0 = period; // Load match value
144 clock_period = period;
146 *PXA2X0_OSCR = 0; // Start the counter
147 *PXA2X0_OSSR = PXA2X0_OSSR_TIMER0; // Clear any pending interrupt
148 *PXA2X0_OIER |= PXA2X0_OIER_TIMER0; // Enable timer 0 interrupt
150 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_TIMER0 ); // Unmask timer 0 interrupt
153 // This routine is called during a clock interrupt.
154 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
156 *PXA2X0_OSMR0 = *PXA2X0_OSCR + period; // Load new match value
157 *PXA2X0_OSSR = PXA2X0_OSSR_TIMER0; // Clear any pending interrupt
160 // Read the current value of the clock, returning the number of hardware
161 // "ticks" that have occurred (i.e. how far away the current value is from
164 // Note: The "contract" for this function is that the value is the number
165 // of hardware clocks that have happened since the last interrupt (i.e.
166 // when it was reset). This value is used to measure interrupt latencies.
167 // However, since the hardware counter runs freely, this routine computes
168 // the difference between the current clock period and the number of hardware
169 // ticks left before the next timer interrupt.
170 void hal_clock_read(cyg_uint32 *pvalue)
173 HAL_DISABLE_INTERRUPTS(orig);
174 *pvalue = clock_period + *PXA2X0_OSCR - *PXA2X0_OSMR0;
175 HAL_RESTORE_INTERRUPTS(orig);
178 // Delay for some number of micro-seconds
179 void hal_delay_us(cyg_int32 usecs)
181 #if defined(CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA25X)
182 # define NSECS_PER_TICK 271267 /* 3.6865 MHz clock */
183 #elif defined(CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X)
184 # define NSECS_PER_TICK 307692 /* 3.25 MHz clock */
188 cyg_uint32 prev = *PXA2X0_OSCR;
189 while (usecs-- > 0) {
190 while (val < 1000000) {
191 cyg_uint32 now = *PXA2X0_OSCR;
192 cyg_uint32 diff = now - prev;
193 val += NSECS_PER_TICK * diff;
201 // Interrupt handling
203 // This routine is called to respond to a hardware interrupt (IRQ). It
204 // should interrogate the hardware and return the IRQ vector number.
205 int hal_IRQ_handler(void)
207 cyg_uint32 sources, index;
209 sources = *PXA2X0_ICIP;
211 #ifdef HAL_EXTENDED_IRQ_HANDLER
212 // Use platform specific IRQ handler, if defined
213 // Note: this macro should do a 'return' with the appropriate
214 // interrupt number if such an extended interrupt exists. The
215 // assumption is that the line after the macro starts 'normal' processing.
216 HAL_EXTENDED_IRQ_HANDLER(sources);
219 if ( sources & 0xff0000 )
221 else if ( sources & 0xff00 )
223 else if ( sources & 0xff )
225 else // if ( sources & 0xff000000 )
229 if ( (1 << index) & sources ) {
230 if (index == CYGNUM_HAL_INTERRUPT_GPIOX) {
231 // Special case of GPIO cascade. Search for lowest set bit
232 sources = *PXA2X0_GEDR0;
235 if (sources & (1 << index)) {
236 return CYGNUM_HAL_INTERNAL_IRQS + index;
239 } while (index < 32);
240 sources = *PXA2X0_GEDR1;
243 if (sources & (1 << index)) {
244 return CYGNUM_HAL_INTERNAL_IRQS + 32 + index;
247 } while (index < 32);
248 sources = *PXA2X0_GEDR2;
251 if (sources & (1 << index)) {
252 return CYGNUM_HAL_INTERNAL_IRQS + 64 + index;
255 } while (index < 32);
256 #ifdef CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X
257 sources = *PXA2X0_GEDR3;
260 if (sources & (1 << index)) {
261 return CYGNUM_HAL_INTERNAL_IRQS + 96 + index;
264 } while (index < 32);
270 } while ( index & 7 );
272 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
275 void hal_interrupt_mask(int vector)
278 #ifdef HAL_EXTENDED_INTERRUPT_MASK
279 // Use platform specific handling, if defined
280 // Note: this macro should do a 'return' for "extended" values of 'vector'
281 // Normal vectors are handled by code subsequent to the macro call.
282 HAL_EXTENDED_INTERRUPT_MASK(vector);
284 #ifdef CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X
285 if (vector >= 32 && vector < CYGNUM_HAL_INTERNAL_IRQS) {
286 *PXA2X0_ICMR2 &= ~(1 << (vector - 32));
290 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(2)) {
291 vector = CYGNUM_HAL_INTERRUPT_GPIOX;
293 *PXA2X0_ICMR &= ~(1 << vector);
296 void hal_interrupt_unmask(int vector)
299 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
300 // Use platform specific handling, if defined
301 // Note: this macro should do a 'return' for "extended" values of 'vector'
302 // Normal vectors are handled by code subsequent to the macro call.
303 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
305 #ifdef CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X
306 if (vector >= 32 && vector < CYGNUM_HAL_INTERNAL_IRQS) {
307 *PXA2X0_ICMR2 |= (1 << (vector - 32));
311 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(2)) {
312 vector = CYGNUM_HAL_INTERRUPT_GPIOX;
314 *PXA2X0_ICMR |= (1 << vector);
317 void hal_interrupt_acknowledge(int vector)
320 #ifdef HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE
321 // Use platform specific handling, if defined
322 // Note: this macro should do a 'return' for "extended" values of 'vector'
323 // Normal vectors are handled by code subsequent to the macro call.
324 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
326 if (vector == CYGNUM_HAL_INTERRUPT_GPIO0 || vector == CYGNUM_HAL_INTERRUPT_GPIO1) {
327 *PXA2X0_GEDR0 = (1 << (vector - 8));
329 #ifdef CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X
330 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(96)) {
331 *PXA2X0_GEDR3 = (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 96));
334 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(64)) {
335 *PXA2X0_GEDR2 = (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 64));
336 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(32)) {
337 *PXA2X0_GEDR1 = (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 32));
338 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(2)) {
339 *PXA2X0_GEDR0 = (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS));
341 // Not a GPIO interrupt
347 void hal_interrupt_configure(int vector, int level, int up)
349 cyg_bool falling = level || !up;
350 cyg_bool rising = level || up;
352 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
353 // Use platform specific handling, if defined
354 // Note: this macro should do a 'return' for "extended" values of 'vector'
355 // Normal vectors are handled by code subsequent to the macro call.
356 HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
358 #ifdef CYGOPT_HAL_ARM_XSCALE_PXA2X0_VARIANT_PXA27X
359 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(96)) {
361 *PXA2X0_GFER3 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 96));
363 *PXA2X0_GFER3 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 96));
365 *PXA2X0_GRER3 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 96));
367 *PXA2X0_GRER3 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 96));
370 if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(64)) {
372 *PXA2X0_GFER2 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 64));
374 *PXA2X0_GFER2 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 64));
376 *PXA2X0_GRER2 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 64));
378 *PXA2X0_GRER2 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 64));
379 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(32)) {
381 *PXA2X0_GFER1 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 32));
383 *PXA2X0_GFER1 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 32));
385 *PXA2X0_GRER1 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 32));
387 *PXA2X0_GRER1 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS - 32));
388 } else if (vector >= CYGNUM_HAL_INTERRUPT_GPIO(2)) {
390 *PXA2X0_GFER1 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS));
392 *PXA2X0_GFER1 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS));
394 *PXA2X0_GRER1 |= (1 << (vector - CYGNUM_HAL_INTERNAL_IRQS));
396 *PXA2X0_GRER1 &= ~(1 << (vector - CYGNUM_HAL_INTERNAL_IRQS));
397 } else if (vector == CYGNUM_HAL_INTERRUPT_GPIO0 || vector == CYGNUM_HAL_INTERRUPT_GPIO1) {
399 *PXA2X0_GFER0 |= (1 << (vector - 8));
401 *PXA2X0_GFER0 &= ~(1 << (vector - 8));
403 *PXA2X0_GRER0 |= (1 << (vector - 8));
405 *PXA2X0_GRER0 &= ~(1 << (vector - 8));
409 void hal_interrupt_set_level(int vector, int level)
412 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
413 // Use platform specific handling, if defined
414 // Note: this macro should do a 'return' for "extended" values of 'vector'
415 // Normal vectors are handled by code subsequent to the macro call.
416 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);