#ifndef CYGONCE_HAL_PLATFORM_SETUP_H
#define CYGONCE_HAL_PLATFORM_SETUP_H
/*=============================================================================
//
//      hal_platform_setup.h
//
//      Platform specific support for HAL (assembly code)
//
//=============================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
// -------------------------------------------                              
// This file is part of eCos, the Embedded Configurable Operating System.   
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
// Copyright (C) 2003, 2004, 2006 eCosCentric Limited                       
//
// eCos is free software; you can redistribute it and/or modify it under    
// the terms of the GNU General Public License as published by the Free     
// Software Foundation; either version 2 or (at your option) any later      
// version.                                                                 
//
// eCos is distributed in the hope that it will be useful, but WITHOUT      
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
// for more details.                                                        
//
// You should have received a copy of the GNU General Public License        
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
//
// As a special exception, if other files instantiate templates or use      
// macros or inline functions from this file, or you compile this file      
// and link it with other works to produce a work based on this file,       
// this file does not by itself cause the resulting work to be covered by   
// the GNU General Public License. However the source code for this file    
// must still be made available in accordance with section (3) of the GNU   
// General Public License v2.                                               
//
// This exception does not invalidate any other reasons why a work based    
// on this file might be covered by the GNU General Public License.         
// -------------------------------------------                              
// ####ECOSGPLCOPYRIGHTEND####                                              
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    nickg
// Contributors: nickg
// Date:         2004-07-05
// Purpose:      Motorola MX1ADS_A platform specific support routines
// Description: 
// Usage:        #include <cyg/hal/hal_platform_setup.h>
//     Only used by "vectors.S"         
//
//####DESCRIPTIONEND####
//
//===========================================================================*/

#include <pkgconf/system.h>             // System-wide configuration info
#include CYGBLD_HAL_VARIANT_H           // Variant specific configuration
#include CYGBLD_HAL_PLATFORM_H          // Platform specific configuration
#include <cyg/hal/hal_mmu.h>            // MMU definitions
#include <cyg/hal/mc9328mxl.h>          // Platform specific hardware definitions        
#include <cyg/hal/mx1ads_a.h>           // Platform specific hardware definitions


//===========================================================================*/

        .macro  _platform_setup1

#ifndef CYG_HAL_STARTUP_RAM
//--------------------------------------------------------------------------------

#ifdef CYG_HAL_STARTUP_ROMRAM
        ldr     r10,=(0x10000000-0x8000)
#else
        mov     r10,#0        
#endif        
        
        ldr     r0,=1f
        add     r0,r0,r10
        mov     pc,r0
1:   

        ldr     r0, =0x2001           // allow access to all coprocessors
        mcr     p15,0,r0,c15,c1,0
        nop
        nop
        nop

        ldr     r0, =0x00000078
        mcr     p15,0,r0,c1,c0,0      // Disable MMU, caches, write buffer 
        nop
        nop
        nop

        ldr     r0, =0x00000000
        mcr     p15,0,r0,c8,c7,0      // flush TLB's 
        mcr     p15,0,r0,c7,c7,0      // flush Caches 
        mcr     p15,0,r0,c7,c10,4     // Flush Write Buffer 
        nop
        nop
        nop

        mvn     r0, #0                // grant manager access to all domains
        mcr     p15,0,r0,c3,c0,0  

        // ------------------------------------------------------------------------
        // Start up the Memory controllers and other hardware
        // This is table driven, to make it easier to maintain

        .equ    DONE, 0         // end of table
        .equ    LOOP, 1         // spin for a while
        .equ    READ, 2         // read a value and keep it
        .equ    AND,  3         // AND with read value
        .equ    OR ,  4         // OR with read value
        .equ    WRITE,5         // write read value back

        ldr     r0, =88f        // R0 = table pointer
        add     r0,r0,r10       // Adjust by ROM offset
1:      
        ldr     r1,[r0],#4      // R1 = *R0++
        ldr     r2,[r0],#4      // R2 = *R0++
        cmp     r1,#DONE        // end of table?
        beq     99f             // all done, jump over table
        cmp     r1,#LOOP        // check for LOOP
        bne     3f              // branch if not
2:      
        sub     r2,r2,#1        // R2--
        bne     2b              // loop while !=0
        b       1b              // go back for next entry
3:
        cmp     r1,#READ        // READ?
        ldreq   r4,[r2]         // if so: R4 = *R2
	cmp     r1,#READ
        beq     1b
        cmp     r1,#AND         // AND?
        andeq   r4,r4,r2        // if so: R4 = R4 & R2 
        cmp     r1,#AND         // AND?
        beq     1b
        cmp     r1,#OR          // OR?
        orreq   r4,r4,r2        // if so: R4 = R4 | R2 
        cmp     r1,#OR          // OR?
	beq     1b
        cmp     r1,#WRITE       // WRITE?
        streq   r4,[r2]         // if so: *R2 = R4
	strne   r2,[r1]         // if not: *R1 = R2
        b       1b              // go back for next entry
                                
88:
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // Set up AIPIs

        // These don't seem to need setting up
//        .long   MC9328MXL_AIPI1+MC9328MXL_AIPI_PSR0,            0x00000304
//        .long   MC9328MXL_AIPI1+MC9328MXL_AIPI_PSR1,            0xfffffcfb
//        .long   MC9328MXL_AIPI2+MC9328MXL_AIPI_PSR0,            0x3ffc0000
//        .long   MC9328MXL_AIPI2+MC9328MXL_AIPI_PSR1,            0xffffffff

        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // System controller

        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // GPIO

        // Set up various GPIO pins to their peripheral
	// functions. These include:
        // UART1
        // UART2
        // CS4 enables
  
        .long   READ,                   MC9328MXL_GPIOA+MC9328MXL_GPIO_GIUS
        .long   AND,                    0xff3fffff
        .long   WRITE,                  MC9328MXL_GPIOA+MC9328MXL_GPIO_GIUS

        .long   READ,                   MC9328MXL_GPIOA+MC9328MXL_GPIO_GPR
        .long   AND,                    0xff3fffff
        .long   WRITE,                  MC9328MXL_GPIOA+MC9328MXL_GPIO_GPR
                
        .long   MC9328MXL_GPIOB+MC9328MXL_GPIO_GIUS,            0x0fffffff
        .long   MC9328MXL_GPIOB+MC9328MXL_GPIO_GPR,             0x00000000
        
        .long   MC9328MXL_GPIOC+MC9328MXL_GPIO_GIUS,            0x0007e1ff
        .long   MC9328MXL_GPIOC+MC9328MXL_GPIO_GPR,             0x00000000

        .long   MC9328MXL_GPIOD+MC9328MXL_GPIO_GIUS,            0xfffff87f
        .long   MC9328MXL_GPIOD+MC9328MXL_GPIO_GPR,             0x00000780
        
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // Clocks

        // Set up the PLLs and transfer clock to 48MHz
        .long   MC9328MXL_PCC+MC9328MXL_PCC_CSCR,               0xAf008403
        .long   MC9328MXL_PCC+MC9328MXL_PCC_MPCTL0,             0x04632410
        .long   MC9328MXL_PCC+MC9328MXL_PCC_CSCR,               0xAf208403        
        .long   MC9328MXL_PCC+MC9328MXL_PCC_CSCR,               0xAf000403        
        .long   MC9328MXL_PCC+MC9328MXL_PCC_PCDR,               0x000b0055
                
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)        
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // SDRAM controller
        // Only do this if we are booting from reset

        // precharge
        .long   MC9328MXL_SDC+MC9328MXL_SDC_CTL0,               0x92120200
        .long   READ,                                           0x08200000

        // auto refresh command
        .long   MC9328MXL_SDC+MC9328MXL_SDC_CTL0,               0xa2120200
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000
        .long   READ,                                           0x08000000

        // set mode reg
        .long   MC9328MXL_SDC+MC9328MXL_SDC_CTL0,               0xb2120200
        .long   READ,                                           0x08111800

        // set normal mode
        .long  MC9328MXL_SDC+MC9328MXL_SDC_CTL0,               0x82124200
#endif
        
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // External Interface Module        

        // CS0 - flash
//        .long   MC9328MXL_EIM+MC9328MXL_EIM_CS0_U,               0x00000801
//        .long   MC9328MXL_EIM+MC9328MXL_EIM_CS0_L,               0x11110E01

        // CS4 - ethernet
        .long   MC9328MXL_EIM+MC9328MXL_EIM_CS4_U,               0x00000F00
        .long   MC9328MXL_EIM+MC9328MXL_EIM_CS4_L,               0x00001501

        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        .long   DONE, DONE
        
99:          
sdram_running:
                
#endif  // CYG_HAL_STARTUP_RAM

        // ------------------------------------------------------------------------
                
#ifdef CYG_HAL_STARTUP_ROMRAM
        // Compute [logical] base address of this image in ROM
        bl      10f
10:     mov     r9,lr
        ldr     r8,=~0xFF01FFFF         // Bits to ignore
        and     r9,r9,r8
        orr     r9,r9,#0x10000000       // Turn into ROM address 3
#endif

#if !defined(CYG_HAL_STARTUP_SRAM)
        // Test whether MMU is already running. If it is then we skip
	// over the setup code.
        ldr     r1,=MMU_Control_M
        mrc     MMU_CP,0,r2,MMU_Control,c0
        and     r1,r1,r2
        cmp     r1,#0
        bne     mmu_ok
        
        // Set up a stack [for calling C code]
        ldr     r1,=__startup_stack
        ldr     r2,=MX1ADS_A_SDRAM_PHYS_BASE
        orr     sp,r1,r2

        // Create MMU tables
        bl      hal_mmu_init

        // Enable MMU
        ldr     r2,=10f
#ifdef CYG_HAL_STARTUP_ROMRAM
        ldr     r1,=__exception_handlers
        sub     r1,r2,r1
        add     r2,r9,r1        // r9 has ROM offset
#endif        
        ldr    r1,=MMU_Control_Init|MMU_Control_M
        mcr    MMU_CP,0,r1,MMU_Control,c0
        mov    pc,r2    /* Change address spaces */
        nop
        nop
        nop
10:

mmu_ok:

#endif        
        // ------------------------------------------------------------------------

#ifdef CYG_HAL_STARTUP_ROMRAM
        mov     r0,r9                     // Relocate FLASH/ROM to RAM
        ldr     r1,=__exception_handlers  // ram base & length
        ldr     r2,=__rom_data_end
20:     ldr     r3,[r0],#4
        str     r3,[r1],#4
        cmp     r1,r2
        bne     20b
        ldr     r0,=30f
        mov     pc,r0
        nop
        nop
        nop
        nop
30:             
#endif
        
        .endm
        
#define CYGHWR_HAL_ARM_HAS_MMU
#define PLATFORM_SETUP1 _platform_setup1
#define CYGSEM_HAL_ROM_RESET_USES_JUMP

//-----------------------------------------------------------------------------
// end of hal_platform_setup.h
#endif // CYGONCE_HAL_PLATFORM_SETUP_H
