]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/ebsa285/v2_0/src/ebsa285_misc.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / ebsa285 / v2_0 / src / ebsa285_misc.c
1 //==========================================================================
2 //
3 //      ebsa285_misc.c
4 //
5 //      HAL misc board support code for StrongARM EBSA285-1
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 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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####
42 //
43 // Author(s):    gthomas
44 // Contributors: gthomas
45 // Date:         1999-02-20
46 // Purpose:      HAL board support
47 // Description:  Implementations of HAL board interfaces
48 //
49 //####DESCRIPTIONEND####
50 //
51 //========================================================================*/
52
53 #include <pkgconf/hal.h>
54 #include <pkgconf/system.h>
55 #include CYGBLD_HAL_PLATFORM_H
56 #include CYGHWR_MEMORY_LAYOUT_H
57
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
61
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
69
70 #include <cyg/infra/diag.h>             // diag_printf
71
72 #include <string.h> // memset
73
74 /*
75  * Toggle LED for debugging purposes.
76  */
77 /*
78  * EBSA-285 Soft I/O Register
79  */
80 #define EBSA_285_SOFT_IO_REGISTER           ((cyg_uint32 *)0x40012000)
81
82 /*
83  * EBSA-285 Soft I/O Register Bit Field definitions
84  */
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
93
94 static void
95 hal_bsp_mmu_init(int sdram_size);
96
97 // Some initialization has already been done before we get here.
98 //
99 // Set up the interrupt environment.
100 // Set up the MMU so that we can use caches.
101 // Enable caches.
102 // - All done!
103
104
105 void hal_hardware_init(void)
106 {
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;
115
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;
120
121     // Let the timer run at a default rate (for delays)
122     hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
123
124     // Set up MMU so that we can use caches
125     hal_bsp_mmu_init( hal_dram_size );
126
127     // Enable caches
128     HAL_DCACHE_ENABLE();
129     HAL_ICACHE_ENABLE();
130
131     // Set up eCos/ROM interfaces
132     hal_if_init();
133 }
134
135 // -------------------------------------------------------------------------
136 // MMU initialization:
137
138 static void
139 hal_bsp_mmu_init(int sdram_size)
140 {
141     unsigned long ttb_base = ((unsigned long)0x4000); // could be external
142     unsigned long i;
143
144     *EBSA_285_SOFT_IO_REGISTER = ~EBSA_285_SOFT_IO_RED_LED; // Red LED on
145
146
147 // For if we assign the ttb base dynamically:
148 //    if ((ttb_base & ARM_TRANSLATION_TABLE_MASK) != ttb_base) {
149 //        // we cannot do this:
150 //        while ( 1 ) {
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...
157 //#endif
158 //        }
159 //    }
160
161     /*
162      * Set the TTB register
163      */
164     asm volatile ("mcr  p15,0,%0,c2,c0,0" 
165                   :
166                   : "r"(ttb_base)
167                 /*:*/
168         );
169     /*
170      * Set the Domain Access Control Register
171      */
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);
188
189     asm volatile ("mcr  p15,0,%0,c3,c0,0" 
190                   :
191                   : "r"(i)
192                 /*:*/
193         );
194
195     /*
196      * First clear all TT entries - ie Set them to Faulting
197      */
198     memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
199
200     /*
201      * We only do direct mapping for the EBSA board. That is, all
202      * virt_addr == phys_addr.
203      */
204
205     /*
206      * Actual Base = 0x000(00000)
207      * Virtual Base = 0x000(00000)
208      * Size = Max SDRAM
209      * SDRAM
210      */
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);
215     }
216
217 #ifdef CYGPKG_IO_PCI
218     /*
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.
223      */
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); 
226          i++) {
227         ARM_MMU_SECTION(ttb_base, i, i,
228                         ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
229                         ARM_ACCESS_PERM_RW_RW);
230     }
231 #endif
232
233     /*
234      * Actual Base = 0x400(00000)
235      * Virtual Base = 0x400(00000)
236      * Size = 1M
237      * 21285 Registers
238      *
239      * Actual Base = 0x400(10000)
240      * Virtual Base = 0x400(10000)
241      * Size = 1M
242      * Soft I/O port and XBus IO
243      */
244     ARM_MMU_SECTION(ttb_base, 0x400, 0x400,
245                     ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
246                     ARM_ACCESS_PERM_RW_RW);
247
248     /*
249      * Actual Base = 0x410(00000) - 0x413(FFFFF)
250      * Virtual Base = 0x410(00000) - 0x413(FFFFF)
251      * Size = 4M
252      * FLASH ROM
253      */
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);
258     }
259
260     /*
261      * Actual Base = 0x420(00000)
262      * Virtual Base = 0x420(00000)
263      * Size = 1M
264      * 21285 CSR Space
265      */
266     ARM_MMU_SECTION(ttb_base, 0x420, 0x420, 
267                     ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
268                     ARM_ACCESS_PERM_RW_RW);
269
270     /*
271      * Actual Base = 0x500(00000)-0x50F(FFFFF)
272      * Virtual Base = 0x500(00000)-0x50F(FFFFF)
273      * Size = 16M
274      * Zeros (Cache Clean) Bank
275      */
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);
280     }
281
282     /*
283      * Actual Base = 0x780(00000)-0x78F(FFFFF)
284      * Virtual Base = 0x780(00000)-0x78F(FFFFF)
285      * Size = 16M
286      * Outbound Write Flush
287      */
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);
292     }
293
294     /*
295      * Actual Base = 0x790(00000)-0x7C0(FFFFF)
296      * Virtual Base = 0x790(00000)-0x7C0(FFFFF)
297      * Size = 65M
298      * PCI IACK/Config/IO Space
299      */
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);
304     }
305
306     /*
307      * Actual Base = 0x800(00000) - 0xFFF(FFFFF)
308      * Virtual Base = 0x800(00000) - 0xFFF(FFFFF)
309      * Size = 2G
310      * PCI Memory Space
311      */
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);
316     }
317
318     *EBSA_285_SOFT_IO_REGISTER = ~EBSA_285_SOFT_IO_AMBER_LED; // AmberLED on
319
320 }
321
322 /*------------------------------------------------------------------------*/
323
324 //
325 // Memory layout
326 //
327
328 externC cyg_uint8 *
329 hal_arm_mem_real_region_top( cyg_uint8 *regionend )
330 {
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" );
334
335     // is it the "normal" end of the DRAM region? If so, it should be
336     // replaced by the real size
337     if ( regionend ==
338          ((cyg_uint8 *)CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE) ) {
339         regionend = (cyg_uint8 *)CYGMEM_REGION_ram + hal_dram_size;
340     }
341     return regionend;
342 } // hal_arm_mem_real_region_top()
343
344
345
346 // -------------------------------------------------------------------------
347 static cyg_uint32 _period;
348
349 void hal_clock_initialize(cyg_uint32 period)
350 {
351     _period = period;
352
353     *SA110_TIMER3_CONTROL = 0;          // Disable while we are setting up
354
355     *SA110_TIMER3_LOAD = period;        // Reload value
356
357     *SA110_TIMER3_CLEAR = 0;            // Clear any pending interrupt
358                                         // (Data: don't care)
359
360     *SA110_TIMER3_CONTROL = 0x000000cc; // Enable, Periodic (auto-reload),
361                    // External clock (3.68MHz on irq_in_l[2] for Timer 3)
362
363     *SA110_TIMER3_CLEAR = 0;            // Clear any pending interrupt again
364
365     // That's all.
366 }
367
368 // This routine is called during a clock interrupt.
369
370 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
371 {
372     *SA110_TIMER3_CLEAR = period; // Clear any pending interrupt (Data: don't care)
373 }
374
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
377 // the start)
378
379 void hal_clock_read(cyg_uint32 *pvalue)
380 {
381     *pvalue = (cyg_uint32)(_period) - *SA110_TIMER3_VALUE;
382 }
383
384 //
385 // Delay for some number of micro-seconds
386 //
387 void hal_delay_us(cyg_int32 usecs)
388 {
389     int diff, diff2;
390     cyg_uint32 val1, val2;
391
392     while (usecs-- > 0) {
393         diff = 0;
394         val1 = *SA110_TIMER3_VALUE;
395         while (diff < 3) {
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
399                 diff2 = val2 - val1;
400                 if (diff2 < 0) diff2 += *SA110_TIMER3_LOAD;
401                 diff += diff2;
402             } else {
403                 diff += val2 - val1;
404             }
405         }
406     }
407 }
408
409 // -------------------------------------------------------------------------
410
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)
414 {
415     int sources;
416     int index;
417
418 #if 0 // test FIQ and print alert if active - really for debugging
419     sources = *SA110_IRQCONT_FIQSTATUS;
420     if ( 0 != sources )
421         diag_printf( "FIQ source active!!! - fiqstatus %08x irqstatus %08x\n",
422                      sources, *SA110_IRQCONT_IRQSTATUS );
423     else
424 #endif // Scan FIQ sources also
425
426     sources = *SA110_IRQCONT_IRQSTATUS;
427
428 // if we come to support FIQ properly...
429 //    if ( 0 == sources )
430 //        sources = *SA110_IRQCONT_FIQSTATUS;
431
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 )
436         index = 0;
437     else if ( sources & 0xff00 )
438         index = 8;
439     else if ( sources & 0xff0000 )
440         index = 16;
441     else // if ( sources & 0xff000000 )
442         index = 24;
443
444     do {
445         if ( (1 << index) & sources )
446             return index;
447         index++;
448     } while ( index & 7 );
449     
450     return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
451 }
452
453 //
454 // Interrupt control
455 //
456
457 void hal_interrupt_mask(int vector)
458 {
459     *SA110_IRQCONT_IRQENABLECLEAR = 1 << vector;
460 }
461
462 void hal_interrupt_unmask(int vector)
463 {
464     *SA110_IRQCONT_IRQENABLESET = 1 << vector;
465 }
466
467 void hal_interrupt_acknowledge(int vector)
468 {
469     // Nothing to do here.
470 }
471
472 void hal_interrupt_configure(int vector, int level, int up)
473 {
474     // No interrupts are configurable on this hardware
475 }
476
477 void hal_interrupt_set_level(int vector, int level)
478 {
479     // No interrupts are configurable on this hardware
480 }
481
482 #include CYGHWR_MEMORY_LAYOUT_H
483 typedef void code_fun(void);
484 void ebsa285_program_new_stack(void *func)
485 {
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;
492     new_func();
493     stack_ptr = old_stack;
494     return;
495 }
496
497 /*------------------------------------------------------------------------*/
498 // EOF ebsa285_misc.c