#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, 2005, 2006 Free Software Foundation, Inc.
// Copyright (C) 2003, 2004, 2005, 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):    eCosCentric
// Contributors: 
// Date:         2005-07-29
// Purpose:      Atmel AT91RM9200 DK/EK 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 <pkgconf/hal_arm.h>
#include <pkgconf/hal_arm_arm9.h>
#include <pkgconf/hal_arm_arm9_at91rm9200.h>

#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/atmel-at91rm9200-kits.h>   // Platform specific hardware definitions
#include <cyg/hal/at91rm9200_init.inc>       // AT91RM9200 common init helper macros

//===========================================================================*/
// User LED display

        .macro  ldrc reg,val
#ifdef __thumb__
        ldr     \reg,=\val
#else
        mov     \reg,#\val
#endif
        .endm

        .macro _led y
        ldr     r0,=AT91RM9200_PIOB
        ldrc    r1,0x00000007
        str     r1,[r0,#_PIO_SODR]
        ldrc    r1,(\y&7)
        str     r1,[r0,#_PIO_CODR]
        .endm
        
#define CYGHWR_LED_MACRO _led \x

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

// This macro represents the initial startup code for the platform.
// This is derived from the kb9200 HAL with additional information gleaned
// from Atmel example startup code, particularly
// AT91_Microcontroller/AT91RM9200-BasicsCompilation-ADS1_2-2_0/AT91RM9200-BasicBoot/init_ram.c
// from the CD supplied with the kits.
        

        .macro  _platform_setup1

//--------------------------------------------------------------------------------
// Set up the CPU

        at91rm9200_init_cpu

//--------------------------------------------------------------------------------
        // Set CS0 for access to flash
        // 
        // 4 wait states, 2 float, 16-bit, standard read, standard acss, 0 setup, 0 hold
        // This needs to be set now before the clocks, otherwise we may be running too fast
        // for the Flash

        ldr     r1,=_EBI_SMC2_CSR0
        ldr     r2,=0x00003284
        str     r2,[r1]

//--------------------------------------------------------------------------------
// Get the clocks running

        // Enable PLLA at 180Mhz (really 179.712MHz) for PCK
        // 180MHz ~= 18.432MHz Main/4 x 39
        // DIVA         = 4
        // PLLACOUNT    = 63
        // OUTA         = 2 == 150..240MHz
        // MULA         = 38 == multiplier-1

        // Enable PLLB at 96MHz for USB (really 96.110MHz)
        // USB really wants 48MHz, so we set the USB_96M bit
        // resulting in a USB clock of 48.055MHz
        // 96MHz ~= 18.432MHz Main/14 x 73
        // DIVB          = 14
        // PLLBCOUNT     = 62
        // OUTB          = 0 == 80..160MHz
        // MULB          = 72 == multiplier-1
        
#define PLLA_VAL 0x2026BF04
#define PLLB_VAL 0x10483E0E

        at91rm9200_init_clocks PLLA_VAL,PLLB_VAL


#if !defined(CYG_HAL_STARTUP_SRAM)                    


//--------------------------------------------------------------------------------            
// GPIO Initialization

        // Port C
        // PC16-PC31 = D16-D31.  Thus set as peripheral function A.
        // PC13 = Codetest port NCS7. Thus set as peripheral function A.
        // PC6 = Display controller nWAIT - SMC can do LCD interface, so
        //       set as periph A function i.e. nWAIT input to SMC
        // PC4 = PHY nMDINTR. Thus leave as GPIO line and set as input.
        // (BFOE function is unused - no burst flash)

        ldr     r1,=AT91RM9200_PIOC
        ldr     r2,=0xFFFF2040
        str     r2,[r1,#_PIO_ASR]
        str     r2,[r1,#_PIO_PDR]
        mvn     r2,r2
        str     r2,[r1,#_PIO_PER]

        ldr     r2,=0xFFFFFFFF          // Set all gpio as input
        str     r2,[r1,#_PIO_ODR]

        // Port A
        // PA31 = DBGU_TXD. Thus set as peripheral function A.
        // (NB it is also boot mode select jumper)
        // PA30 = DBGU_RXD. Thus set as peripheral function A.
        // PA27-PA29 = MMC i/f lines. Thus set as peripheral function A.
        // PA25-26 = TWI. Thus set as peripheral function A.
        // PA17 = SD Card WP. Thus leave as GPIO and set as input.
        // PA7-PA16 = Ethernet PHY lines. Thus set as peripheral function A.
        // PA6 = MMC_CS. Thus leave as GPIO and set as output.
        // PA0-PA3 = SPI data Flash i/f lines. PA3 is NPCS0.
        // Thus set as peripheral function A.
        
        ldr     r1,=AT91RM9200_PIOA
        ldr     r2,=0xFE01FF8F
        str     r2,[r1,#_PIO_ASR]
        str     r2,[r1,#_PIO_PDR]
        mvn     r2,r2
        str     r2,[r1,#_PIO_PER]

        ldr     r2,=0xFFFFFFBF          // Set all gpio as input, except PA6.
        str     r2,[r1,#_PIO_ODR]
        mvn     r2,r2
        str     r2,[r1,#_PIO_OER]

        // Port B
        // PB27 = SD Card CD1_SW<1>. Thus leave as GPIO and set as input, with a pull-up.
        // PB23-PB26 = RS232. Thus set as peripheral function A.
        // PB22 = MMC_TYPE. Thus leave as GPIO and set as output.
        // PB18-PB21 = RS232. Thus set as peripheral function A.
        // PB10 = Data flash only i/f CD2_SW<1>. Thus leave as GPIO and set as input with a pull-up.
        // PB6-PB8 = SSC TF1,TK1,TD1 on DAC. Thus set as peripheral function A.
        // PB3-PB5 = MMC i/f MCDA1-3. Thus set as peripheral function B.
        // PB0,1,2 = User LED 1,2,3 (green, yellow, red).
        // Thus leave as GPIO and set as output.

        ldr     r1,=AT91RM9200_PIOB

        // First, set to drive all GPIO outputs low, except user LEDS on PB0/1/2,
        // which are driven high (LEDs all off)
        ldr     r2,=0xFFFFFFFF
        str     r2,[r1,#_PIO_CODR]
        ldr     r2,=0x00000007
        str     r2,[r1,#_PIO_SODR]

        // Set GPIO vs. peripheral
        ldr     r2,=0x07BC01F8
        str     r2,[r1,#_PIO_PDR]
        mvn     r2,r2
        str     r2,[r1,#_PIO_PER]

        ldr     r2,=0xFFFFFFC7          // Assign all to Function A except PB3-5.
        str     r2,[r1,#_PIO_ASR]
        ldr     r2,=0x00000038          // Function B: PB3-5
        str     r2,[r1,#_PIO_BSR]

        ldr     r2,=0x00400007          // Set all GPIO as input, except PB0-2,PB22
        str     r2,[r1,#_PIO_OER]

        ldr     r2,=0x08000400          // Set PB10 and PB27 with pull-up resistor enabled
        str     r2,[r1,#_PIO_PUER]

//--------------------------------------------------------------------------------                    
// SDRAM Initialization

        // Sdram configuration register values from Atmel examples.
#define SDRAM_CR (_EBI_SDRC_CR_NC_9 | _EBI_SDRC_CR_NR_12 | _EBI_SDRC_CR_NB_4_BANKS | \
                  _EBI_SDRC_CR_CAS_2 | 0x100 | 0x4000 | 0x8000 |        \
                  0x880000 | 0x21000000)

        // Refresh magic value from Atmel code.
#define SDRAM_REFRESH 0x2E0

        at91rm9200_init_sdram SDRAM_CR, ATMEL_AT91RM9200_KITS_SDRAM_PHYS_BASE, SDRAM_REFRESH

#endif  // !CYG_HAL_STARTUP_SRAM

//--------------------------------------------------------------------------------
// Handle ROM->RAM copy in ROMRAM startups and initialize the MMU

// To handle ROMRAM placement, we mask our current PC to find the base of the
// image (we know we're near the start), and OR in the physical base of the
// ROM, in order to find where we are to be copying from.
#define IMAGE_BASE_MASK      0xFF01FFFF   // Bits to ignore
#define ROM_IMAGE_PHYS_BASE  0x60000000   // Phys Base of Flash

        // This will cause hal_mmu_init to be called
        at91rm9200_init_mmu IMAGE_BASE_MASK, ROM_IMAGE_PHYS_BASE, ATMEL_AT91RM9200_KITS_SDRAM_PHYS_BASE

        .endm

//--------------------------------------------------------------------------------
                
#define PLATFORM_SETUP1 _platform_setup1
#define CYGSEM_HAL_ROM_RESET_USES_JUMP

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