/*****************************************************************************
  LPD SDKLH79520_10 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.
 *****************************************************************************/
  .text
  .code 32
  .align 0

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

#define RCPC_BASE 0xFFFE2000
#define RCPC_RCPCCtrl_OFFS 0x00
#define RCPC_HCLKPrescale_OFFS 0x18
#define RCPC_CpuClkPrescale_OFFS 0x1C
#define RCPC_AHBClkCtrl_OFFS 0x2C

#define IOCON_BASE 0xFFFE5000
#define IOCON_MemMux_OFFS 0x00
#define IOCON_LCDMux_OFFS 0x04
#define IOCON_MiscMux_OFFS 0x08
#define IOCON_DMAMux_OFFS 0x0C
#define IOCON_UARTMux_OFFS 0x10
#define IOCON_SSPMux_OFFS 0x14

#define SMC_BASE 0xFFFF1000
#define SMC_SMCBCR0_OFFS 0x00
#define SMC_SMCBCR1_OFFS 0x04
#define SMC_SMCBCR2_OFFS 0x08
#define SMC_SMCBCR3_OFFS 0x0C
#define SMC_SMCBCR4_OFFS 0x10
#define SMC_SMCBCR5_OFFS 0x14
#define SMC_SMCBCR6_OFFS 0x18

#define SDRC_BASE 0xFFFF2000
#define SDRC_SDRCConfig0_OFFS 0x00
#define SDRC_SDRCConfig1_OFFS 0x04
#define SDRC_SDRCRefTimer_OFFS 0x08
#define SDRC_SDRCWBTimeout_OFFS 0x0C

#define SDRAM_BASE 0x20022000
#define SDRAM_INIT_NOP  0x03
#define SDRAM_INIT_MODE 0x02
#define SDRAM_INIT_PALL 0x01
#define SDRAM_INIT_NORMAL 0x0c

/* Wait for SDRAM idle status
 * NOTE: Assumes R1 = SDRC_BASE
 */
sdram_wait_for_idle:
  ldr r0, [r1, #SDRC_SDRCConfig1_OFFS]
  tst r0, #0x20
  bne sdram_wait_for_idle
  mov pc, lr

delay:
  subs r0, r0, #1
  bne delay
  mov pc, lr

/*****************************************************************************
  Function    : _start
  Description : Minimal startup code for C system.
 *****************************************************************************/
_start:
  /* Set up clocks */
  ldr r1, =RCPC_BASE
  mov r0, #3 /* Divider = 6 */
  str r0, [r1, #RCPC_CpuClkPrescale_OFFS]
  str r0, [r1, #RCPC_HCLKPrescale_OFFS]
  ldr r0, =0x263 /* Start PLL */
  str r0, [r1, #RCPC_RCPCCtrl_OFFS]

  /* Configure static memory */
  ldr r1, =SMC_BASE
  ldr r0, =static_memory_configuration
  ldmia r0, {r2-r7}
  stmia r1, {r2-r7}
  
  /* Configure I/O control and multiplexing */
  ldr r1, =IOCON_BASE
  ldr r0, =0x17EF
  str r0, [r1, #IOCON_MemMux_OFFS]
  
  ldr r0, =0x1FE
  str r0, [r1, #IOCON_MiscMux_OFFS]

  ldr r0, =0xF
  str r0, [r1, #IOCON_UARTMux_OFFS]

  ldr r1, =SDRC_BASE
  ldr r0, =0xA
  str r0, [r1, #SDRC_SDRCRefTimer_OFFS]

  ldr r1, =RCPC_BASE
  ldr r0, =0x5
  str r0, [r1, #RCPC_AHBClkCtrl_OFFS]

  /* Configure SDRAM */
  ldr r1, =SDRC_BASE

  mov r0, #200
  bl delay

  mov r0, #SDRAM_INIT_NOP
  str r0, [r1, #SDRC_SDRCConfig1_OFFS]
  str r0, [r1, #SDRC_SDRCConfig1_OFFS]

  /* DELAY to allow sdram clocks to settle */
  mov r0, #200 
  bl delay

  mov r0, #SDRAM_INIT_PALL /* SDRCCONFIG1: Issue a "pre-charge all" command */
  str r0, [r1, #SDRC_SDRCConfig1_OFFS] 
  mov r0, #250
  bl delay

  ldr r0, =0x2EE
  str r0, [r1, #SDRC_SDRCRefTimer_OFFS] 
  mov r0, #250
  bl delay

  mov r0, #SDRAM_INIT_MODE /* SDRCCONFIG1: Select mode register update mode */
  str r0, [r1, #SDRC_SDRCConfig1_OFFS] 
  ldr r2, =SDRAM_BASE
  ldr r0, [r2]
  bl sdram_wait_for_idle

  ldr r0, =0x01A40088 /* SDRCCONFIG0: Latency = 2, 32 bits, 4 banks */
  str r0, [r1, #SDRC_SDRCConfig0_OFFS]
  bl sdram_wait_for_idle

  mov r0, #SDRAM_INIT_NORMAL /* SDRCCONFIG1: Select normal operating mode */
  str r0, [r1, #SDRC_SDRCConfig1_OFFS]
  bl sdram_wait_for_idle
  mov r0, #128
  bl delay

  /* 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:
                  
static_memory_configuration:
  .word 0x100020EF /* SMCBCR0 */
  .word 0x1000FFEF /* SMCBCR1 */
  .word 0x1000FFEF /* SMCBCR2 */
  .word 0x0000FBEF /* SMCBCR3 */
  .word 0x10007580 /* SMCBCR4 */
  .word 0x100034c0 /* SMCBCR5 */
  .word 0x1000ffef /* SMCBCR6 */
