diff packages/hal/arm/ebsa285/current/src/ebsa285_misc.c @ 76:435cced73e2f ecos-v1_3_1-release

eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
author jlarmour
date Tue, 28 Mar 2000 14:10:45 +0000
parents
children 84e4bde58b26
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/hal/arm/ebsa285/current/src/ebsa285_misc.c
@@ -0,0 +1,425 @@
+//==========================================================================
+//
+//      ebsa285_misc.c
+//
+//      HAL misc board support code for StrongARM EBSA285-1
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    gthomas
+// Contributors: gthomas
+// Date:         1999-02-20
+// Purpose:      HAL board support
+// Description:  Implementations of HAL board interfaces
+//
+//####DESCRIPTIONEND####
+//
+//========================================================================*/
+
+#include <pkgconf/hal.h>
+#include <pkgconf/system.h>
+#include CYGBLD_HAL_PLATFORM_H
+
+#include <cyg/infra/cyg_type.h>         // base types
+#include <cyg/infra/cyg_trac.h>         // tracing macros
+#include <cyg/infra/cyg_ass.h>          // assertion macros
+
+#include <cyg/hal/hal_io.h>             // IO macros
+#include <cyg/hal/hal_arch.h>           // Register state info
+#include <cyg/hal/hal_diag.h>
+#include <cyg/hal/hal_intr.h>           // Interrupt names
+#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_ebsa285.h>        // Hardware definitions
+
+#include <cyg/infra/diag.h>             // diag_printf
+
+/*
+ * Toggle LED for debugging purposes.
+ */
+/*
+ * EBSA-285 Soft I/O Register
+ */
+#define EBSA_285_SOFT_IO_REGISTER           ((cyg_uint32 *)0x40012000)
+
+/*
+ * EBSA-285 Soft I/O Register Bit Field definitions
+ */
+#define EBSA_285_SOFT_IO_TOGGLE             0x80
+#define EBSA_285_SOFT_IO_RED_LED            0x04
+#define EBSA_285_SOFT_IO_GREEN_LED          0x02
+#define EBSA_285_SOFT_IO_AMBER_LED          0x01
+#define EBSA_285_SOFT_IO_J9_9_10_MASK       0x40
+#define EBSA_285_SOFT_IO_J9_11_12_MASK      0x20
+#define EBSA_285_SOFT_IO_J9_13_14_MASK      0x10
+#define EBSA_285_SOFT_IO_SWITCH_L_MASK      0x0F
+
+static void
+hal_bsp_mmu_init(int sdram_size);
+
+// Some initialization has already been done before we get here.
+//
+// Set up the interrupt environment.
+// Set up the MMU so that we can use caches.
+// Enable caches.
+// - All done!
+
+
+void hal_hardware_init(void)
+{
+    // Disable all interrupt sources:
+    *SA110_IRQCONT_IRQENABLECLEAR = 0xffffffff;
+    *SA110_IRQCONT_FIQENABLECLEAR = 0xffffffff; // including FIQ
+    // Disable the timers
+    *SA110_TIMER1_CONTROL = 0;
+    *SA110_TIMER2_CONTROL = 0;
+    *SA110_TIMER3_CONTROL = 0;
+    *SA110_TIMER4_CONTROL = 0;
+
+    *SA110_TIMER1_CLEAR = 0;            // Clear any pending interrupt
+    *SA110_TIMER2_CLEAR = 0;            // (Data: don't care)
+    *SA110_TIMER3_CLEAR = 0;
+    *SA110_TIMER4_CLEAR = 0;
+
+    // Set up MMU so that we can use caches
+    hal_bsp_mmu_init( hal_dram_size );
+
+    // Enable caches
+    HAL_DCACHE_ENABLE();
+    HAL_ICACHE_ENABLE();
+
+#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
+    // then enable the interrupt for incoming characters and break
+    // into the stub ROM if the char is a ^C.
+    HAL_INTERRUPT_UNMASK( CYG_DIAG_DEV_INT );
+    // hal_diag.c: hal_ctrlc_isr( CYG_ADDRWORD vector, CYG_ADDRWORD data)
+    // is polled from the default ISR so it's OK just to enable this.   
+#endif
+#endif
+}
+
+// -------------------------------------------------------------------------
+// MMU initialization:
+
+static void
+hal_bsp_mmu_init(int sdram_size)
+{
+    unsigned long ttb_base = ((unsigned long)0x4000); // could be external
+    unsigned long i;
+
+    *EBSA_285_SOFT_IO_REGISTER = ~EBSA_285_SOFT_IO_RED_LED; // Red LED on
+
+
+// For if we assign the ttb base dynamically:
+//    if ((ttb_base & ARM_TRANSLATION_TABLE_MASK) != ttb_base) {
+//        // we cannot do this:
+//        while ( 1 ) {
+//            *EBSA_285_SOFT_IO_REGISTER = 0; // All LEDs on
+//            for ( i = 100000; i > 0 ; i++ ) ;
+//            *EBSA_285_SOFT_IO_REGISTER = 7; // All LEDs off
+//            for ( i = 100000; i > 0 ; i++ ) ;
+//#ifdef CYG_HAL_STARTUP_RAM
+//            return; // Do not bother looping forever...
+//#endif
+//        }
+//    }
+
+    /*
+     * Set the TTB register
+     */
+    asm volatile ("mcr  p15,0,%0,c2,c0,0" 
+                  :
+                  : "r"(ttb_base)
+                /*:*/
+        );
+    /*
+     * Set the Domain Access Control Register
+     */
+    i = ARM_ACCESS_TYPE_MANAGER(0)    | 
+        ARM_ACCESS_TYPE_NO_ACCESS(1)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(2)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(3)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(4)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(5)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(6)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(7)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(8)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(9)  |
+        ARM_ACCESS_TYPE_NO_ACCESS(10) |
+        ARM_ACCESS_TYPE_NO_ACCESS(11) |
+        ARM_ACCESS_TYPE_NO_ACCESS(12) |
+        ARM_ACCESS_TYPE_NO_ACCESS(13) |
+        ARM_ACCESS_TYPE_NO_ACCESS(14) |
+        ARM_ACCESS_TYPE_NO_ACCESS(15);
+
+    asm volatile ("mcr  p15,0,%0,c3,c0,0" 
+                  :
+                  : "r"(i)
+                /*:*/
+        );
+
+    /*
+     * First clear all TT entries - ie Set them to Faulting
+     */
+    memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
+
+    /*
+     * We only do direct mapping for the EBSA board. That is, all
+     * virt_addr == phys_addr.
+     */
+
+    /*
+     * Actual Base = 0x000(00000)
+     * Virtual Base = 0x000(00000)
+     * Size = Max SDRAM
+     * SDRAM
+     */
+    for (i = 0x000; i < (sdram_size >> 20); i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_CACHEABLE, ARM_BUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+
+#ifdef CYGPKG_IO_PCI
+    /*
+     * Actual Base = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE
+     * Virtual Base = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE
+     * Size = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE
+     * Memory accessible from PCI space. Overrides part of the above mapping.
+     */
+    for (i = CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE >> 20;
+         i < ((CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE+CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE) >> 20); 
+         i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+#endif
+
+    /*
+     * Actual Base = 0x400(00000)
+     * Virtual Base = 0x400(00000)
+     * Size = 1M
+     * 21285 Registers
+     *
+     * Actual Base = 0x400(10000)
+     * Virtual Base = 0x400(10000)
+     * Size = 1M
+     * Soft I/O port and XBus IO
+     */
+    ARM_MMU_SECTION(ttb_base, 0x400, 0x400,
+		    ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
+		    ARM_ACCESS_PERM_RW_RW);
+
+    /*
+     * Actual Base = 0x410(00000) - 0x413(FFFFF)
+     * Virtual Base = 0x410(00000) - 0x413(FFFFF)
+     * Size = 4M
+     * FLASH ROM
+     */
+    for (i = 0x410; i <= 0x413; i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_CACHEABLE, ARM_UNBUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+
+    /*
+     * Actual Base = 0x420(00000)
+     * Virtual Base = 0x420(00000)
+     * Size = 1M
+     * 21285 CSR Space
+     */
+    ARM_MMU_SECTION(ttb_base, 0x420, 0x420, 
+                    ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
+                    ARM_ACCESS_PERM_RW_RW);
+
+    /*
+     * Actual Base = 0x500(00000)-0x50F(FFFFF)
+     * Virtual Base = 0x500(00000)-0x50F(FFFFF)
+     * Size = 16M
+     * Zeros (Cache Clean) Bank
+     */
+    for (i = 0x500; i <= 0x50F; i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_CACHEABLE, ARM_BUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+
+    /*
+     * Actual Base = 0x780(00000)-0x78F(FFFFF)
+     * Virtual Base = 0x780(00000)-0x78F(FFFFF)
+     * Size = 16M
+     * Outbound Write Flush
+     */
+    for (i = 0x780; i <= 0x78F; i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+
+    /*
+     * Actual Base = 0x790(00000)-0x7C0(FFFFF)
+     * Virtual Base = 0x790(00000)-0x7C0(FFFFF)
+     * Size = 65M
+     * PCI IACK/Config/IO Space
+     */
+    for (i = 0x790; i <= 0x7C0; i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_UNCACHEABLE, ARM_UNBUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+
+    /*
+     * Actual Base = 0x800(00000) - 0xFFF(FFFFF)
+     * Virtual Base = 0x800(00000) - 0xFFF(FFFFF)
+     * Size = 2G
+     * PCI Memory Space
+     */
+    for (i = 0x800; i <= 0xFFF; i++) {
+        ARM_MMU_SECTION(ttb_base, i, i,
+                        ARM_UNCACHEABLE, ARM_BUFFERABLE,
+                        ARM_ACCESS_PERM_RW_RW);
+    }
+
+    *EBSA_285_SOFT_IO_REGISTER = ~EBSA_285_SOFT_IO_AMBER_LED; // AmberLED on
+
+}
+
+// -------------------------------------------------------------------------
+static cyg_uint32 _period;
+
+void hal_clock_initialize(cyg_uint32 period)
+{
+    _period = period;
+
+    *SA110_TIMER3_CONTROL = 0;          // Disable while we are setting up
+
+    *SA110_TIMER3_LOAD = period;        // Reload value
+
+    *SA110_TIMER3_CLEAR = 0;            // Clear any pending interrupt
+                                        // (Data: don't care)
+
+    *SA110_TIMER3_CONTROL = 0x000000cc; // Enable, Periodic (auto-reload),
+                   // External clock (3.68MHz on irq_in_l[2] for Timer 3)
+
+    *SA110_TIMER3_CLEAR = 0;            // Clear any pending interrupt again
+
+    // That's all.
+}
+
+// This routine is called during a clock interrupt.
+
+void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
+{
+    *SA110_TIMER3_CLEAR = period; // Clear any pending interrupt (Data: don't care)
+}
+
+// Read the current value of the clock, returning the number of hardware
+// "ticks" that have occurred (i.e. how far away the current value is from
+// the start)
+
+void hal_clock_read(cyg_uint32 *pvalue)
+{
+    *pvalue = (cyg_uint32)(_period) - *SA110_TIMER3_VALUE;
+}
+
+// -------------------------------------------------------------------------
+
+// This routine is called to respond to a hardware interrupt (IRQ).  It
+// should interrogate the hardware and return the IRQ vector number.
+int hal_IRQ_handler(void)
+{
+    int sources;
+    int index;
+
+#if 0 // test FIQ and print alert if active - really for debugging
+    sources = *SA110_IRQCONT_FIQSTATUS;
+    if ( 0 != sources )
+        diag_printf( "FIQ source active!!! - fiqstatus %08x irqstatus %08x\n",
+                     sources, *SA110_IRQCONT_IRQSTATUS );
+    else
+#endif // Scan FIQ sources also
+
+    sources = *SA110_IRQCONT_IRQSTATUS;
+
+// if we come to support FIQ properly...
+//    if ( 0 == sources )
+//        sources = *SA110_IRQCONT_FIQSTATUS;
+
+    // Nothing wrong with scanning them in the order provided...
+    // and it'll make the serial device steal fewer cycles.
+    // So, knowing this is an ARM:
+    if ( sources & 0xff )
+        index = 0;
+    else if ( sources & 0xff00 )
+        index = 8;
+    else if ( sources & 0xff0000 )
+        index = 16;
+    else // if ( sources & 0xff000000 )
+        index = 24;
+
+    do {
+        if ( (1 << index) & sources )
+            return index;
+        index++;
+    } while ( index & 7 );
+    
+    return CYGNUM_HAL_INTERRUPT_reserved0; // This shouldn't happen!
+}
+
+//
+// Interrupt control
+//
+
+void hal_interrupt_mask(int vector)
+{
+    *SA110_IRQCONT_IRQENABLECLEAR = 1 << vector;
+}
+
+void hal_interrupt_unmask(int vector)
+{
+    *SA110_IRQCONT_IRQENABLESET = 1 << vector;
+}
+
+void hal_interrupt_acknowledge(int vector)
+{
+    // Nothing to do here.
+}
+
+void hal_interrupt_configure(int vector, int level, int up)
+{
+    // No interrupts are configurable on this hardware
+}
+
+void hal_interrupt_set_level(int vector, int level)
+{
+    // No interrupts are configurable on this hardware
+}
+
+/*------------------------------------------------------------------------*/
+// EOF ebsa285_misc.c