/*****************************************************************************
  ATMEL AT91SAM7A1_EK loader startup code.

  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

  .global _start
  .extern C_Entry
  .global stack_start
  .global stack_end

/*****************************************************************************
 * Minimal set of exception handlers which will be in place once memory      *
 * has been remapped.                                                        *
 *****************************************************************************/
reset_handler:
  b configure_and_start
undef_handler:
  b undef_handler
swi_handler:
  b swi_handler
pabort_handler:
  b pabort_handler
dabort_handler:
  b dabort_handler
  .word 0
irq_handler:
  b irq_handler
fiq_handler:
  b fiq_handler

  .text
  .code 32
  .align 0

  .global _start
  .extern C_Entry
  .global stack_start
  .global stack_end

/*****************************************************************************
  Function    : _start
  Description : Minimal startup code for C system.
 *****************************************************************************/
configure_and_start:
  /* 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]
  
  /* Configure memory */
  ldr r10, =AMC_BASE
  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]

  ldr r12, =_start

  /* Remap Internal SRAM to 0x00000000 */
  ldr r0, =0x00000001
  str r0, [r10, #AMC_RCR_OFFS]
 
  mov pc, r12

_start:
  /* Setup stack */ 
  add sp, pc, #1024 
  
  /* Jump to main entry point */
  bl C_Entry

  /* Return from main, loop forever. */
loop:
  b loop
                          
stack_start:
  .fill 1024
stack_end:
                  
