/*****************************************************************************
  LPD SDKLH79524_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_CTRL_OFFS 0x00000000
#define RCPC_CHIPID_OFFS 0x00000004
#define RCPC_REMAP_OFFS 0x00000008
#define RCPC_SOFTRESET_OFFS 0x0000000c
#define RCPC_RSTSTATUS_OFFS 0x00000010
#define RCPC_STATUSCLR_OFFS 0x00000014
#define RCPC_SYSCLKPRE_OFFS 0x00000018
#define RCPC_CPUCLKPRE_OFFS 0x0000001c
#define RCPC_PCLKCTRL0_OFFS 0x00000024
#define RCPC_PCLKCTRL1_OFFS 0x00000028
#define RCPC_AHBCLKCTRL_OFFS 0x0000002c
#define RCPC_PCLKSEL0_OFFS 0x00000030
#define RCPC_PCLKSEL2_OFFS 0x00000034
#define RCPC_LCDPRE_OFFS 0x00000040
#define RCPC_SSPPRE_OFFS 0x00000044
#define RCPC_ADCPRE_OFFS 0x00000048
#define RCPC_USBPRE_OFFS 0x0000004c
#define RCPC_INTCONFIG_OFFS 0x00000080
#define RCPC_INTCLR_OFFS 0x00000084
#define RCPC_CORECONFIG_OFFS 0x00000088
#define RCPC_SYSPLLCNTL_OFFS 0x000000c0
#define RCPC_USBPLLCTL_OFFS 0x000000c4

#define EMC_BASE 0xFFFF1000
#define EMC_CONTROL_OFFS 0x00000000
#define EMC_STATUS_OFFS 0x00000004
#define EMC_CONFIG_OFFS 0x00000008
#define EMC_DYNMCTRL_OFFS 0x00000020
#define EMC_DYNMREF_OFFS 0x00000024
#define EMC_PRECHARGE_OFFS 0x00000030
#define EMC_DYNM2PRE_OFFS 0x00000034
#define EMC_REFEXIT_OFFS 0x00000038
#define EMC_DOACTIVE_OFFS 0x0000003c
#define EMC_DIACTIVE_OFFS 0x00000040
#define EMC_DWRT_OFFS 0x00000044
#define EMC_DYNACTCMD_OFFS 0x00000048
#define EMC_DYNAUTO_OFFS 0x0000004c
#define EMC_DYNREFEXIT_OFFS 0x00000050
#define EMC_DYNACTIVEAB_OFFS 0x00000054
#define EMC_DYNAMICMRD_OFFS 0x00000058
#define EMC_WAIT_OFFS 0x00000080
#define EMC_DYNCFG0_OFFS 0x00000100
#define EMC_DYNRASCAS0_OFFS 0x00000104
#define EMC_DYNCFG1_OFFS 0x00000120
#define EMC_DYNRASCAS1_OFFS 0x00000124
#define EMC_SCONFIG0_OFFS 0x00000200
#define EMC_SWAITWEN0_OFFS 0x00000204
#define EMC_SWAITOEN0_OFFS 0x00000208
#define EMC_SWAITRD0_OFFS 0x0000020c
#define EMC_SWAITPAGE0_OFFS 0x00000210
#define EMC_SWAITWR0_OFFS 0x00000214
#define EMC_STURN0_OFFS 0x00000218
#define EMC_SCONFIG1_OFFS 0x00000220
#define EMC_SWAITWEN1_OFFS 0x00000224
#define EMC_SWAITOEN1_OFFS 0x00000228
#define EMC_SWAITRD1_OFFS 0x0000022c
#define EMC_SWAITPAGE1_OFFS 0x00000230
#define EMC_SWAITWR1_OFFS 0x00000234
#define EMC_STURN1_OFFS 0x00000238
#define EMC_SCONFIG2_OFFS 0x00000240
#define EMC_SWAITWEN2_OFFS 0x00000244
#define EMC_SWAITOEN2_OFFS 0x00000248
#define EMC_SWAITRD2_OFFS 0x0000024c
#define EMC_SWAITPAGE2_OFFS 0x00000250
#define EMC_SWAITWR2_OFFS 0x00000254
#define EMC_STURN2_OFFS 0x00000258
#define EMC_SCONFIG3_OFFS 0x00000260
#define EMC_SWAITWEN3_OFFS 0x00000264
#define EMC_SWAITOEN3_OFFS 0x00000268
#define EMC_SWAITRD3_OFFS 0x0000026c
#define EMC_SWAITPAGE3_OFFS 0x00000270
#define EMC_SWAITWR3_OFFS 0x00000274
#define EMC_STURN3_OFFS 0x00000278

#define IOCON_BASE_BASE 0xfffe5000
#define IOCON_MUXCTL1_OFFS 0x00000000
#define IOCON_RESCTL1_OFFS 0x00000004
#define IOCON_MUXCTL3_OFFS 0x00000010
#define IOCON_RESCTL3_OFFS 0x00000014
#define IOCON_MUXCTL4_OFFS 0x00000018
#define IOCON_RESCTL4_OFFS 0x0000001c
#define IOCON_MUXCTL5_OFFS 0x00000020
#define IOCON_RESCTL5_OFFS 0x00000024
#define IOCON_MUXCTL6_OFFS 0x00000028
#define IOCON_RESCTL6_OFFS 0x0000002c
#define IOCON_MUXCTL7_OFFS 0x00000030
#define IOCON_RESCTL7_OFFS 0x00000034
#define IOCON_MUXCTL10_OFFS 0x00000048
#define IOCON_RESCTL10_OFFS 0x0000004c
#define IOCON_MUXCTL11_OFFS 0x00000050
#define IOCON_RESCTL11_OFFS 0x00000054
#define IOCON_MUXCTL12_OFFS 0x00000058
#define IOCON_RESCTL12_OFFS 0x0000005c
#define IOCON_RESCTL13_OFFS 0x00000064
#define IOCON_MUXCTL14_OFFS 0x00000068
#define IOCON_MUXCTL15_OFFS 0x00000070
#define IOCON_RESCTL15_OFFS 0x00000074
#define IOCON_RESCTL17_OFFS 0x00000084
#define IOCON_MUXCTL19_OFFS 0x00000090
#define IOCON_RESCTL19_OFFS 0x00000094
#define IOCON_MUXCTL20_OFFS 0x00000098
#define IOCON_RESCTL20_OFFS 0x0000009c
#define IOCON_MUXCTL21_OFFS 0x000000a0
#define IOCON_RESCTL21_OFFS 0x000000a4
#define IOCON_MUXCTL22_OFFS 0x000000a8
#define IOCON_RESCTL22_OFFS 0x000000ac
#define IOCON_MUXCTL23_OFFS 0x000000b0
#define IOCON_RESCTL23_OFFS 0x000000b4
#define IOCON_MUXCTL24_OFFS 0x000000b8
#define IOCON_RESCTL24_OFFS 0x000000bc
#define IOCON_MUXCTL25_OFFS 0x000000c0

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

/*****************************************************************************
  Function    : _start
  Description : Minimal startup code for C system.
 *****************************************************************************/
_start:
  mov r1, #0x00000070
  mcr p15, 0, r1, c1, c0, 0

  ldr r1, =0xFFFFF000
  ldr r0, =0x00000000
  str r0, [r1, #0x14]
  ldr r0, =0xFFFFFFFE
  str r0, [r1, #0x1C]


  ldr r1, =RCPC_BASE
  /* Unlock RCPC registers, CLKOUT Source = HCLK, Power down mode = Active */
  ldr r0, =0x00000260
  str r0, [r1, #RCPC_CTRL_OFFS]
  /* Enable SDRAM controller and DMA clocks */
  ldr r0, =0x0000001C
  str r0, [r1, #RCPC_AHBCLKCTRL_OFFS]
  ldr r0, =0x000000207
  str r0, [r1, #RCPC_PCLKCTRL0_OFFS]
  ldr r0, =0x00000000F
  str r0, [r1, #RCPC_PCLKCTRL1_OFFS]

  /* Setup the system PLL frequency */
  ldr r0, =0x000003049
  str r0, [r1, #RCPC_SYSPLLCNTL_OFFS]
  /* Setup HCLK and FCLK frequency */
  ldr r0, =0x000000001
  str r0, [r1, #RCPC_SYSCLKPRE_OFFS]
  str r0, [r1, #RCPC_CPUCLKPRE_OFFS]
  /* Setup core clock configuration (standard mode, synchronous) */
  ldr r0, =0x000000001
  str r0, [r1, #RCPC_CORECONFIG_OFFS]

  ldr r1, =EMC_BASE
  /* Enable the EMC */
  ldr r0, =0x00000001
  str r0, [r1, #EMC_CONTROL_OFFS]
  ldr r0, =0x00000000
  str r0, [r1, #EMC_CONFIG_OFFS]

  /* Setup the initial I/O configuration */
  ldr r1, =IOCON_BASE_BASE
  ldr r0, =0x00005000
  str r0, [r1, #IOCON_MUXCTL12_OFFS]
  ldr r0, =0x00005555
  str r0, [r1, #IOCON_MUXCTL11_OFFS]
  str r0, [r1, #IOCON_MUXCTL10_OFFS]
  ldr r0, =0x00001110
  str r0, [r1, #IOCON_MUXCTL20_OFFS]
  ldr r0, =0x00000441
  str r0, [r1, #IOCON_MUXCTL19_OFFS]
  ldr r0, =0x00005555
  str r0, [r1, #IOCON_MUXCTL7_OFFS]

  ldr r1, =EMC_BASE
  /* Setup nCS0 static memory configuration */
  ldr r0, =0x00000002
  str r0, [r1, #EMC_SCONFIG0_OFFS]
  ldr r0, =0x0000000C
  str r0, [r1, #EMC_SWAITWEN0_OFFS]
  str r0, [r1, #EMC_SWAITOEN0_OFFS]
  str r0, [r1, #EMC_SWAITRD0_OFFS]
  str r0, [r1, #EMC_SWAITPAGE0_OFFS]
  str r0, [r1, #EMC_SWAITWR0_OFFS]
  str r0, [r1, #EMC_STURN0_OFFS]

  /* Setup nCS1 static memory configuration */
  ldr r0, =0x00000081
  str r0, [r1, #EMC_SCONFIG1_OFFS]
  ldr r0, =0x00000001
  str r0, [r1, #EMC_SWAITWEN1_OFFS]
  str r0, [r1, #EMC_SWAITOEN1_OFFS]
  ldr r0, =0x00000006
  str r0, [r1, #EMC_SWAITRD1_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_SWAITPAGE1_OFFS]
  ldr r0, =0x00000006
  str r0, [r1, #EMC_SWAITWR1_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_STURN1_OFFS]

  /* Setup nCS2 static memory configuration */
  ldr r0, =0x00000081
  str r0, [r1, #EMC_SCONFIG2_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_SWAITWEN2_OFFS]
  str r0, [r1, #EMC_SWAITOEN2_OFFS]
  ldr r0, =0x00000010
  str r0, [r1, #EMC_SWAITRD2_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_SWAITPAGE2_OFFS]
  ldr r0, =0x0000000E
  str r0, [r1, #EMC_SWAITWR2_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_STURN2_OFFS]

  /* Setup nCS3 static memory configuration */
  ldr r0, =0x00000081
  str r0, [r1, #EMC_SCONFIG3_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_SWAITWEN3_OFFS]
  str r0, [r1, #EMC_SWAITOEN3_OFFS]
  ldr r0, =0x00000005
  str r0, [r1, #EMC_SWAITRD3_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_SWAITPAGE3_OFFS]
  ldr r0, =0x00000005
  str r0, [r1, #EMC_SWAITWR3_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_STURN3_OFFS]

  /* Configure SDRAM */
  ldr r0, =0x00000001
  str r0, [r1, #0x00000028]

  ldr r0, =0x10000
  bl delay

  ldr r0, =0x00005480
  str r0, [r1, #EMC_DYNCFG0_OFFS]
  ldr r0, =0x00000203
  str r0, [r1, #EMC_DYNRASCAS0_OFFS]
  ldr r0, =0x00000001
  str r0, [r1, #EMC_PRECHARGE_OFFS]
  ldr r0, =0x00000003
  str r0, [r1, #EMC_DYNM2PRE_OFFS]
  ldr r0, =0x00000006
  str r0, [r1, #EMC_REFEXIT_OFFS]
  str r0, [r1, #EMC_DOACTIVE_OFFS]
  str r0, [r1, #EMC_DIACTIVE_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_DWRT_OFFS]
  ldr r0, =0x00000006
  str r0, [r1, #EMC_DYNACTCMD_OFFS]
  str r0, [r1, #EMC_DYNAUTO_OFFS]
  str r0, [r1, #EMC_DYNREFEXIT_OFFS]
  ldr r0, =0x00000002
  str r0, [r1, #EMC_DYNACTIVEAB_OFFS]
  str r0, [r1, #EMC_DYNAMICMRD_OFFS]
  ldr r0, =0x00000003 /* Enable and run SDCLK */
  str r0, [r1, #EMC_DYNMCTRL_OFFS]

  ldr r0, =0x10000
  bl delay

  ldr r0, =0x00000183 /* SDRAM NOP command */
  str r0, [r1, #EMC_DYNMCTRL_OFFS]

  ldr r0, =0x10000
  bl delay
  
  ldr r0, =0x00000103 /* SDRAM PALL (precharge all) command */
  str r0, [r1, #EMC_DYNMCTRL_OFFS]
  ldr r0, =0x00000000 /* Disable SDRAM refresh */
  str r0, [r1, #EMC_DYNMREF_OFFS]

  ldr r0, =0x10000
  bl delay

  ldr r0, =0x00000018 /* Set SDRAM refresh cycles */
  str r0, [r1, #EMC_DYNMREF_OFFS]
  ldr r0, =0x00000083 /* SDRAM MODE command */
  str r0, [r1, #EMC_DYNMCTRL_OFFS]
  ldr r2, =0x20011000
  ldr r2, [r2]
  ldr r0, =0x00085480 /* Enable SDRAM, 128Mb (8M × 16), 4 banks, row length = 12, column length = 9 */
  str r0, [r1, #EMC_DYNCFG0_OFFS]
  ldr r0, =0x10000
  bl delay
  ldr r0, =0x00000203
  str r0, [r1, #EMC_DYNRASCAS0_OFFS]
  ldr r0, =0x00000003 /* SDRAM NORMAL operation command */
  str r0, [r1, #EMC_DYNMCTRL_OFFS]

  ldr r0, =0x00085480 /* Enable SDRAM, 128Mb (8M × 16), 4 banks, row length = 12, column length = 9 */
  str r0, [r1, #EMC_DYNCFG0_OFFS]
  ldr r0, =0x10000
  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:
                  
