/*****************************************************************************
  Exception handlers and startup code for ATMEL AT91SAM7A1_EK.

  Copyright (c) 2005 Rowley Associates Limited.

  This file may be distributed under the terms of the License Agreement
  provided with this software. 
 
  THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *****************************************************************************/

#ifndef PLL_FREQ_IN
#define PLL_FREQ_IN 6000000
#endif

#ifndef PLL_FREQ_OUT
#define PLL_FREQ_OUT 30000000
#endif

#define AMC_BASE 0xFFE00000
#define AMC_CSR0_OFFS 0x00
#define AMC_CSR1_OFFS 0x04
#define AMC_CSR2_OFFS 0x08
#define AMC_CSR3_OFFS 0x1C
#define AMC_RCR_OFFS  0x20
#define AMC_MCR_OFFS  0x24

#define CM_BASE  0xFFFEC000
#define CM_CE_OFFS    0x00
#define CM_CD_OFFS    0x04
#define CM_CS_OFFS    0x08
#define CM_PST_OFFS   0x0C
#define CM_PDIV_OFFS  0x10
#define CM_OST_OFFS   0x14
#define CM_MDIV_OFFS  0x18

  .section .vectors, "ax"
  .code 32
  .align 0

#ifdef __FLASH_BUILD
/*****************************************************************************
 * Exception Vectors (Prior to remap)                                        *
 *****************************************************************************/
_pre_remap_vectors:
  b reset_handler
  b undef_handler
  b swi_handler
  b pabort_handler
  b dabort_handler
  .word 0 
  b irq_handler
  b fiq_handler
#endif
  
/*****************************************************************************
  Exception Vectors (Post remap)
 *****************************************************************************/
_vectors:
  ldr pc, [pc, #reset_handler_address - . - 8]  /* reset */
  ldr pc, [pc, #undef_handler_address - . - 8]  /* undefined instruction */
  ldr pc, [pc, #swi_handler_address - . - 8]    /* swi handler */
  ldr pc, [pc, #pabort_handler_address - . - 8] /* abort prefetch */
  ldr pc, [pc, #dabort_handler_address - . - 8] /* abort data */
  nop
  ldr pc, [pc, #irq_handler_address - . - 8]    /* irq */
  ldr pc, [pc, #fiq_handler_address - . - 8]    /* fiq */

reset_handler_address:
  .word reset_handler
undef_handler_address:
  .word undef_handler
swi_handler_address:
  .word swi_handler
pabort_handler_address:
  .word pabort_handler
dabort_handler_address:
  .word dabort_handler
irq_handler_address:
  .word irq_handler
fiq_handler_address:
  .word fiq_handler

  .section .init, "ax"
  .code 32
  .align 0

/*****************************************************************************
  Reset Handler
 *****************************************************************************/
reset_handler:
  /* Configure clocks */
  ldr r10, =CM_BASE
  ldr r0, =0x18070004
  str r0, [r10, #CM_CD_OFFS]
  ldr r0, =(0x762D8000 | (PLL_FREQ_OUT / (PLL_FREQ_IN / 2)))
  str r0, [r10, #CM_PDIV_OFFS]
  ldr r0, =0x23050004
  str r0, [r10, #CM_CE_OFFS]

#ifdef __FLASH_BUILD
  ldr r10, =AMC_BASE

  /* Configure memory */
  ldr r0, =0x400030A5
  str r0, [r10, #AMC_CSR0_OFFS]
  ldr r0, =0x48003081
  str r0, [r10, #AMC_CSR1_OFFS]
  ldr r0, =0x40000017
  str r0, [r10, #AMC_MCR_OFFS]

  /* Copy exception vectors into Internal SRAM */
  ldr r8, =0x00300000
  mov r9, #(_vectors - _pre_remap_vectors) /* Address of _vectors in FLASH prior
                                              to remap (FLASH at 0x00000000) */
  ldmia r9!, {r0-r7}
  stmia r8!, {r0-r7}
  ldmia r9!, {r0-r6}
  stmia r8!, {r0-r6}

  /* Remap Internal SRAM to 0x00000000 and jump to the default C runtime startup code */
  ldr r12, =_start
  ldr r0, =0x00000001
  str r0, [r10, #AMC_RCR_OFFS]
  mov pc, r12
#else
  /* Jump to the default C runtime startup code */
  b _start
#endif

/******************************************************************************
  Default exception handlers
  (These are declared weak symbols so they can be redefined in user code)
 ******************************************************************************/
undef_handler:
  b undef_handler
  
swi_handler:
  b swi_handler
  
pabort_handler:
  b pabort_handler
  
dabort_handler:
  b dabort_handler
  
irq_handler:
  b irq_handler
  
fiq_handler:
  b fiq_handler

  .weak undef_handler, swi_handler, pabort_handler, dabort_handler, irq_handler, fiq_handler
