1 //==========================================================================
5 // HAL misc board support code for StrongARM EBSA285-1
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.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
46 // Purpose: HAL board support
47 // Description: Implementations of HAL board interfaces
49 //####DESCRIPTIONEND####
51 //========================================================================*/
53 #include <pkgconf/hal.h>
54 #include <pkgconf/system.h>
55 #include CYGBLD_HAL_PLATFORM_H
56 #include CYGHWR_MEMORY_LAYOUT_H
58 #include <cyg/infra/cyg_type.h> // base types
59 #include <cyg/infra/cyg_trac.h> // tracing macros
60 #include <cyg/infra/cyg_ass.h> // assertion macros
62 #include <cyg/hal/hal_io.h> // IO macros
63 #include <cyg/hal/hal_if.h> // calling interface API
64 #include <cyg/hal/hal_arch.h> // Register state info
65 #include <cyg/hal/hal_diag.h>
66 #include <cyg/hal/hal_intr.h> // Interrupt names
67 #include <cyg/hal/hal_cache.h>
68 #include <cyg/hal/hal_ebsa285.h> // Hardware definitions
70 #include <cyg/infra/diag.h> // diag_printf
72 #include <string.h> // memset
75 * Toggle LED for debugging purposes.
78 * EBSA-285 Soft I/O Register
80 #define EBSA_285_SOFT_IO_REGISTER ((cyg_uint32 *)0x40012000)
83 * EBSA-285 Soft I/O Register Bit Field definitions
85 #define EBSA_285_SOFT_IO_TOGGLE 0x80
86 #define EBSA_285_SOFT_IO_RED_LED 0x04
87 #define EBSA_285_SOFT_IO_GREEN_LED 0x02
88 #define EBSA_285_SOFT_IO_AMBER_LED 0x01
89 #define EBSA_285_SOFT_IO_J9_9_10_MASK 0x40
90 #define EBSA_285_SOFT_IO_J9_11_12_MASK 0x20
91 #define EBSA_285_SOFT_IO_J9_13_14_MASK 0x10
92 #define EBSA_285_SOFT_IO_SWITCH_L_MASK 0x0F
95 hal_bsp_mmu_init(int sdram_size);
97 // Some initialization has already been done before we get here.
99 // Set up the interrupt environment.
100 // Set up the MMU so that we can use caches.
105 void hal_hardware_init(void)
107 // Disable all interrupt sources:
108 *SA110_IRQCONT_IRQENABLECLEAR = 0xffffffff;
109 *SA110_IRQCONT_FIQENABLECLEAR = 0xffffffff; // including FIQ
110 // Disable the timers
111 *SA110_TIMER1_CONTROL = 0;
112 *SA110_TIMER2_CONTROL = 0;
113 *SA110_TIMER3_CONTROL = 0;
114 *SA110_TIMER4_CONTROL = 0;
116 *SA110_TIMER1_CLEAR = 0; // Clear any pending interrupt
117 *SA110_TIMER2_CLEAR = 0; // (Data: don't care)
118 *SA110_TIMER3_CLEAR = 0;
119 *SA110_TIMER4_CLEAR = 0;
121 // Let the timer run at a default rate (for delays)
122 hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
124 // Set up MMU so that we can use caches
125 hal_bsp_mmu_init( hal_dram_size );
131 // Set up eCos/ROM interfaces
135 // -------------------------------------------------------------------------
136 // MMU initialization:
139 hal_bsp_mmu_init(int sdram_size)
141 unsigned long ttb_base = ((unsigned long)0x4000); // could be external
144 *EBSA_285_SOFT_IO_REGISTER = ~EBSA_285_SOFT_IO_RED_LED; // Red LED on
147 // For if we assign the ttb base dynamically:
148 // if ((ttb_base & ARM_TRANSLATION_TABLE_MASK) != ttb_base) {
149 // // we cannot do this:
151 // *EBSA_285_SOFT_IO_REGISTER = 0; // All LEDs on
152 // for ( i = 100000; i > 0 ; i++ ) ;
153 // *EBSA_285_SOFT_IO_REGISTER = 7; // All LEDs off
154 // for ( i = 100000; i > 0 ; i++ ) ;
155 //#ifdef CYG_HAL_STARTUP_RAM
156 // return; // Do not bother looping forever...
162 * Set the TTB register
164 asm volatile ("mcr p15,0,%0,c2,c0,0"
170 * Set the Domain Access Control Register
172 i = ARM_ACCESS_TYPE_MANAGER(0) |
173 ARM_ACCESS_TYPE_NO_ACCESS(1) |
174 ARM_ACCESS_TYPE_NO_ACCESS(2) |
175 ARM_ACCESS_TYPE_NO_ACCESS(3) |
176 ARM_ACCESS_TYPE_NO_ACCESS(4) |
177 ARM_ACCESS_TYPE_NO_ACCESS(5) |
178 ARM_ACCESS_TYPE_NO_ACCESS(6) |
179 ARM_ACCESS_TYPE_NO_ACCESS(7) |
180 ARM_ACCESS_TYPE_NO_ACCESS(8) |
181 ARM_ACCESS_TYPE_NO_ACCESS(9) |
182 ARM_ACCESS_TYPE_NO_ACCESS(10) |
183 ARM_ACCESS_TYPE_NO_ACCESS(11) |
184 ARM_ACCESS_TYPE_NO_ACCESS(12) |
185 ARM_ACCESS_TYPE_NO_ACCESS(13) |
186 ARM_ACCESS_TYPE_NO_ACCESS(14) |
187 ARM_ACCESS_TYPE_NO_ACCESS(15);
189 asm volatile ("mcr p15,0,%0,c3,c0,0"
196 * First clear all TT entries - ie Set them to Faulting
198 memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
201 * We only do direct mapping for the EBSA board. That is, all
202 * virt_addr == phys_addr.
206 * Actual Base = 0x000(00000)
207 * Virtual Base = 0x000(00000)
211 for (i = 0x000; i < (sdram_size >> 20); i++) {
212 ARM_MMU_SECTION(ttb_base, i, i,
213 ARM_CACHEABLE, ARM_BUFFERABLE,
214 ARM_ACCESS_PERM_RW_RW);
219 * Actual Base = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE
220 * Virtual Base = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE
221 * Size = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE
222 * Memory accessible from PCI space. Overrides part of the above mapping.
224 for (i = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE >> 20;
225 i < ((CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE+CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE) >> 20);
227 ARM_MMU_SECTION(ttb_base, i, i,
228 ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
229 ARM_ACCESS_PERM_RW_RW);
234 * Actual Base = 0x400(00000)
235 * Virtual Base = 0x400(00000)
239 * Actual Base = 0x400(10000)
240 * Virtual Base = 0x400(10000)
242 * Soft I/O port and XBus IO
244 ARM_MMU_SECTION(ttb_base, 0x400, 0x400,
245 ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
246 ARM_ACCESS_PERM_RW_RW);
249 * Actual Base = 0x410(00000) - 0x413(FFFFF)
250 * Virtual Base = 0x410(00000) - 0x413(FFFFF)
254 for (i = 0x410; i <= 0x413; i++) {
255 ARM_MMU_SECTION(ttb_base, i, i,
256 ARM_CACHEABLE, ARM_UNBUFFERABLE,
257 ARM_ACCESS_PERM_RW_RW);
261 * Actual Base = 0x420(00000)
262 * Virtual Base = 0x420(00000)
266 ARM_MMU_SECTION(ttb_base, 0x420, 0x420,
267 ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
268 ARM_ACCESS_PERM_RW_RW);
271 * Actual Base = 0x500(00000)-0x50F(FFFFF)
272 * Virtual Base = 0x500(00000)-0x50F(FFFFF)
274 * Zeros (Cache Clean) Bank
276 for (i = 0x500; i <= 0x50F; i++) {
277 ARM_MMU_SECTION(ttb_base, i, i,
278 ARM_CACHEABLE, ARM_BUFFERABLE,
279 ARM_ACCESS_PERM_RW_RW);
283 * Actual Base = 0x780(00000)-0x78F(FFFFF)
284 * Virtual Base = 0x780(00000)-0x78F(FFFFF)
286 * Outbound Write Flush
288 for (i = 0x780; i <= 0x78F; i++) {
289 ARM_MMU_SECTION(ttb_base, i, i,
290 ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
291 ARM_ACCESS_PERM_RW_RW);
295 * Actual Base = 0x790(00000)-0x7C0(FFFFF)
296 * Virtual Base = 0x790(00000)-0x7C0(FFFFF)
298 * PCI IACK/Config/IO Space
300 for (i = 0x790; i <= 0x7C0; i++) {
301 ARM_MMU_SECTION(ttb_base, i, i,
302 ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
303 ARM_ACCESS_PERM_RW_RW);
307 * Actual Base = 0x800(00000) - 0xFFF(FFFFF)
308 * Virtual Base = 0x800(00000) - 0xFFF(FFFFF)
312 for (i = 0x800; i <= 0xFFF; i++) {
313 ARM_MMU_SECTION(ttb_base, i, i,
314 ARM_UNCACHEABLE, ARM_BUFFERABLE,
315 ARM_ACCESS_PERM_RW_RW);
318 *EBSA_285_SOFT_IO_REGISTER = ~EBSA_285_SOFT_IO_AMBER_LED; // AmberLED on
322 /*------------------------------------------------------------------------*/
329 hal_arm_mem_real_region_top( cyg_uint8 *regionend )
331 CYG_ASSERT( hal_dram_size > 0, "Didn't detect DRAM size!" );
332 CYG_ASSERT( hal_dram_size <= 256<<20,
333 "More than 256MB reported - that can't be right" );
335 // is it the "normal" end of the DRAM region? If so, it should be
336 // replaced by the real size
338 ((cyg_uint8 *)CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE) ) {
339 regionend = (cyg_uint8 *)CYGMEM_REGION_ram + hal_dram_size;
342 } // hal_arm_mem_real_region_top()
346 // -------------------------------------------------------------------------
347 static cyg_uint32 _period;
349 void hal_clock_initialize(cyg_uint32 period)
353 *SA110_TIMER3_CONTROL = 0; // Disable while we are setting up
355 *SA110_TIMER3_LOAD = period; // Reload value
357 *SA110_TIMER3_CLEAR = 0; // Clear any pending interrupt
358 // (Data: don't care)
360 *SA110_TIMER3_CONTROL = 0x000000cc; // Enable, Periodic (auto-reload),
361 // External clock (3.68MHz on irq_in_l[2] for Timer 3)
363 *SA110_TIMER3_CLEAR = 0; // Clear any pending interrupt again
368 // This routine is called during a clock interrupt.
370 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
372 *SA110_TIMER3_CLEAR = period; // Clear any pending interrupt (Data: don't care)
375 // Read the current value of the clock, returning the number of hardware
376 // "ticks" that have occurred (i.e. how far away the current value is from
379 void hal_clock_read(cyg_uint32 *pvalue)
381 *pvalue = (cyg_uint32)(_period) - *SA110_TIMER3_VALUE;
385 // Delay for some number of micro-seconds
387 void hal_delay_us(cyg_int32 usecs)
390 cyg_uint32 val1, val2;
392 while (usecs-- > 0) {
394 val1 = *SA110_TIMER3_VALUE;
396 while ((val2 = *SA110_TIMER3_VALUE) == val1) ;
397 if (*SA110_TIMER3_LOAD) {
398 // A kernel is running, the counter may get reset as we watch
400 if (diff2 < 0) diff2 += *SA110_TIMER3_LOAD;
409 // -------------------------------------------------------------------------
411 // This routine is called to respond to a hardware interrupt (IRQ). It
412 // should interrogate the hardware and return the IRQ vector number.
413 int hal_IRQ_handler(void)
418 #if 0 // test FIQ and print alert if active - really for debugging
419 sources = *SA110_IRQCONT_FIQSTATUS;
421 diag_printf( "FIQ source active!!! - fiqstatus %08x irqstatus %08x\n",
422 sources, *SA110_IRQCONT_IRQSTATUS );
424 #endif // Scan FIQ sources also
426 sources = *SA110_IRQCONT_IRQSTATUS;
428 // if we come to support FIQ properly...
429 // if ( 0 == sources )
430 // sources = *SA110_IRQCONT_FIQSTATUS;
432 // Nothing wrong with scanning them in the order provided...
433 // and it'll make the serial device steal fewer cycles.
434 // So, knowing this is an ARM:
435 if ( sources & 0xff )
437 else if ( sources & 0xff00 )
439 else if ( sources & 0xff0000 )
441 else // if ( sources & 0xff000000 )
445 if ( (1 << index) & sources )
448 } while ( index & 7 );
450 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
457 void hal_interrupt_mask(int vector)
459 *SA110_IRQCONT_IRQENABLECLEAR = 1 << vector;
462 void hal_interrupt_unmask(int vector)
464 *SA110_IRQCONT_IRQENABLESET = 1 << vector;
467 void hal_interrupt_acknowledge(int vector)
469 // Nothing to do here.
472 void hal_interrupt_configure(int vector, int level, int up)
474 // No interrupts are configurable on this hardware
477 void hal_interrupt_set_level(int vector, int level)
479 // No interrupts are configurable on this hardware
482 #include CYGHWR_MEMORY_LAYOUT_H
483 typedef void code_fun(void);
484 void ebsa285_program_new_stack(void *func)
486 register CYG_ADDRESS stack_ptr asm("sp");
487 register CYG_ADDRESS old_stack asm("r4");
488 register code_fun *new_func asm("r0");
489 old_stack = stack_ptr;
490 stack_ptr = CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - sizeof(CYG_ADDRESS);
491 new_func = (code_fun*)func;
493 stack_ptr = old_stack;
497 /*------------------------------------------------------------------------*/
498 // EOF ebsa285_misc.c