2007-09-22 06:04:14 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
2011-02-06 20:10:45 +00:00
|
|
|
* Copyright (C) 2010 by Karl Kurbjun
|
2007-09-22 15:43:38 +00:00
|
|
|
*
|
2008-06-28 18:10:04 +00:00
|
|
|
* This program 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
|
|
|
|
* of the License, or (at your option) any later version.
|
2007-09-22 06:04:14 +00:00
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
|
2011-02-06 20:10:45 +00:00
|
|
|
#define CACHE_NONE 0
|
|
|
|
#define CACHE_ALL 0x0C
|
|
|
|
#define BUFFERED 0x04
|
2007-09-22 06:04:14 +00:00
|
|
|
|
2011-02-06 20:10:45 +00:00
|
|
|
#define LONG_VECTORS 1
|
2007-09-22 06:04:14 +00:00
|
|
|
|
2011-02-06 20:10:45 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* vectors: *
|
|
|
|
* This is the ARM vector table *
|
|
|
|
* Long call exception handlers are used for simplicity between flash *
|
|
|
|
* bootloader and SDRAM main-application. These need to be copied to address *
|
|
|
|
* 0x0 at start. *
|
|
|
|
******************************************************************************/
|
|
|
|
.section .vectors,"ax"
|
|
|
|
.code 32
|
|
|
|
|
|
|
|
.global _vectors
|
|
|
|
@entry:
|
|
|
|
_vectors:
|
|
|
|
|
|
|
|
#if defined(SHORT_VECTORS) /* Use relative branch vectors (64 MB limit) */
|
2012-04-06 12:36:02 +00:00
|
|
|
b _start /* Reset Vector */
|
|
|
|
b undef_instr_handler /* Undefined instruction */
|
|
|
|
b software_int_handler /* Software Vector */
|
|
|
|
b prefetch_abort_handler /* Prefetch Abort */
|
|
|
|
b data_abort_handler /* Data Abort */
|
|
|
|
b reserved_handler /* Reserved/Unused */
|
|
|
|
b irq_handler /* IRQ vector */
|
|
|
|
b fiq_handler /* FIQ vector */
|
2011-02-06 20:10:45 +00:00
|
|
|
#else
|
|
|
|
#if defined(LONG_VECTORS)
|
|
|
|
/* Load the PC with the word values stored below */
|
|
|
|
ldr pc, [pc, #0x18] /* Reset */
|
|
|
|
ldr pc, [pc, #0x18] /* Undefined instruction */
|
|
|
|
ldr pc, [pc, #0x18] /* Software interrupt */
|
|
|
|
ldr pc, [pc, #0x18] /* Prefetch Abort */
|
|
|
|
ldr pc, [pc, #0x18] /* Data Abort */
|
|
|
|
ldr pc, [pc, #0x18] /* Reserved/Unused */
|
|
|
|
ldr pc, [pc, #0x18] /* IRQ */
|
|
|
|
ldr pc, [pc, #0x18] /* FIQ */
|
|
|
|
|
|
|
|
/* Addresses of the handlers */
|
|
|
|
.word _start
|
2012-04-06 12:36:02 +00:00
|
|
|
.word undef_instr_handler
|
|
|
|
.word software_int_handler
|
|
|
|
.word prefetch_abort_handler
|
|
|
|
.word data_abort_handler
|
|
|
|
.word reserved_handler
|
2011-02-06 20:10:45 +00:00
|
|
|
.word irq_handler
|
|
|
|
.word fiq_handler
|
|
|
|
#else
|
|
|
|
#error Vector type undefined
|
|
|
|
#endif
|
2008-05-17 14:20:09 +00:00
|
|
|
#endif
|
2007-09-22 06:04:14 +00:00
|
|
|
|
2011-02-06 20:10:45 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* _start: *
|
|
|
|
* This is the main entry point to the program *
|
|
|
|
******************************************************************************/
|
|
|
|
.section .init, "ax"
|
|
|
|
.code 32
|
|
|
|
.align 0x04
|
|
|
|
.global _start
|
|
|
|
_start:
|
|
|
|
/* Go into supervisor state with IRQ's disabled.
|
|
|
|
* This register is described in section "A2.5 Program status registers"
|
|
|
|
* of the "ARM Architecture Reference Manual".
|
|
|
|
*/
|
|
|
|
msr cpsr, #0xd3
|
|
|
|
|
|
|
|
/* Disable all the fancy stuff */
|
|
|
|
mov r0, #0
|
|
|
|
mcr p15, 0, r0, c1, c0, 0
|
|
|
|
|
|
|
|
/* Disable data and instruction cache, high vectors (at 0xffff0000 instead
|
|
|
|
* of 0x00000000)
|
|
|
|
*/
|
2007-11-02 08:43:56 +00:00
|
|
|
mrc p15, 0, r0, c1, c0, 0
|
|
|
|
/* clear bits 13, 9:8 (--VI --RS) */
|
|
|
|
bic r0, r0, #0x00003300
|
|
|
|
/* clear bits 7, 2:0 (B--- -C-M) */
|
|
|
|
bic r0, r0, #0x00000085
|
|
|
|
/* make sure bit 2 (A) Align is set */
|
|
|
|
orr r0, r0, #0x00000002
|
|
|
|
mcr p15, 0, r0, c1, c0, 0
|
2007-09-25 04:45:49 +00:00
|
|
|
|
2011-02-06 20:10:45 +00:00
|
|
|
/* Add a few cycles of delay before continuing due to system requirements */
|
|
|
|
mov r0, #0x20
|
|
|
|
bl _delay_cycles
|
|
|
|
|
2011-02-06 20:26:33 +00:00
|
|
|
#if defined(BOOTLOADER) && !defined(CREATIVE_ZVx)
|
2011-02-06 20:10:45 +00:00
|
|
|
bl _init_board
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Copy exception handler code to address 0 */
|
|
|
|
ldr r0, =_vectorscopy
|
|
|
|
ldr r1, =_vectorsstart
|
|
|
|
ldr r2, =_vectorsend
|
|
|
|
bl _copy_section
|
|
|
|
|
2016-05-19 17:57:20 +00:00
|
|
|
#if !defined(SANSA_CONNECT)
|
2011-02-06 20:10:45 +00:00
|
|
|
/* Add some delay time to make sure JTAG can be accessed cleanly */
|
|
|
|
mov r0, #0x100000
|
|
|
|
bl _delay_cycles
|
2016-05-19 17:57:20 +00:00
|
|
|
#endif
|
2011-02-06 20:10:45 +00:00
|
|
|
|
|
|
|
#if defined(BOOTLOADER)
|
|
|
|
/* Copy the DRAM */
|
|
|
|
ldr r0, =_dramcopy
|
|
|
|
ldr r1, =_dramstart
|
|
|
|
ldr r2, =_dramend
|
|
|
|
bl _copy_section
|
2008-05-17 14:20:09 +00:00
|
|
|
#endif
|
2011-02-06 20:10:45 +00:00
|
|
|
|
|
|
|
/* Zero out the IBSS */
|
|
|
|
mov r0, #0
|
|
|
|
ldr r1, =_ibss_start
|
|
|
|
ldr r2, =_ibss_end
|
|
|
|
bl _init_section
|
|
|
|
|
|
|
|
/* Copy the IRAM */
|
|
|
|
ldr r0, =_iramcopy
|
|
|
|
ldr r1, =_iramstart
|
|
|
|
ldr r2, =_iramend
|
|
|
|
bl _copy_section
|
|
|
|
|
|
|
|
/* Zero out the BSS */
|
|
|
|
mov r0, #0
|
|
|
|
ldr r1, =_bss_start
|
|
|
|
ldr r2, =_bss_end
|
|
|
|
bl _init_section
|
|
|
|
|
|
|
|
/* Initialize fiq stack */
|
|
|
|
ldr r0, =0xDEADBEEF
|
|
|
|
ldr r1, =_fiq_stack_end /* Stack counts backwards, so end is first*/
|
|
|
|
ldr r2, =_fiq_stack_start
|
|
|
|
bl _init_section
|
|
|
|
|
|
|
|
msr cpsr_c, #0xd1 /* Go into fiq state */
|
|
|
|
ldr sp, =_fiq_stack_start /* set the fiq stack pointer */
|
|
|
|
|
|
|
|
/* Initialize irq stack */
|
|
|
|
ldr r0, =0xDEADBEEF /* Can be taken out; left for clarity */
|
|
|
|
ldr r1, =_irq_stack_end /* Stack counts backwards, so end is first*/
|
|
|
|
ldr r2, =_irq_stack_start
|
|
|
|
bl _init_section
|
|
|
|
|
|
|
|
msr cpsr_c, #0xd2 /* Go into irq state */
|
|
|
|
ldr sp, =_irq_stack_start /* set the irq stack pointer */
|
|
|
|
|
2011-10-11 16:06:03 +00:00
|
|
|
/* SVC, ABT, UNDEF share irq stack */
|
|
|
|
msr cpsr_c, #0xd3 /* Go into svc state */
|
|
|
|
ldr sp, =_irq_stack_start /* set svc stack pointer */
|
|
|
|
|
|
|
|
msr cpsr_c, #0xd7 /* Go into abort state */
|
2011-02-06 20:10:45 +00:00
|
|
|
ldr sp, =_irq_stack_start /* set the stack pointer */
|
|
|
|
|
2011-10-11 16:06:03 +00:00
|
|
|
msr cpsr_c, #0xdb /* Go into undefined state */
|
2011-02-06 20:10:45 +00:00
|
|
|
ldr sp, =_irq_stack_start /* set the stack pointer */
|
|
|
|
|
|
|
|
/* Initialize program stack */
|
2011-10-11 16:06:03 +00:00
|
|
|
msr cpsr_c, #0xdf /* Go into sys state */
|
|
|
|
|
2011-02-06 20:10:45 +00:00
|
|
|
ldr r0, =0xDEADBEEF /* Can be taken out; left for clarity */
|
|
|
|
ldr r1, =_pro_stack_end /* Stack counts backwards, so end is first*/
|
|
|
|
ldr r2, =_pro_stack_start
|
|
|
|
bl _init_section
|
|
|
|
|
2011-10-11 16:06:03 +00:00
|
|
|
ldr sp, =_pro_stack_start /* set the sys stack pointer */
|
2011-02-06 20:10:45 +00:00
|
|
|
|
|
|
|
/* MMU initialization */
|
|
|
|
bl ttb_init
|
|
|
|
|
|
|
|
/* Make sure everything is mapped on itself */
|
|
|
|
ldr r0, =0x0
|
|
|
|
ldr r1, =0x0
|
|
|
|
ldr r2, =0x1000
|
|
|
|
mov r3, #CACHE_NONE
|
|
|
|
bl map_section
|
|
|
|
|
2021-05-20 19:16:46 +00:00
|
|
|
/* Enable write-through caching for FLASH */
|
2011-02-06 20:10:45 +00:00
|
|
|
ldr r0, =_flash_start
|
|
|
|
ldr r1, =_flash_start
|
|
|
|
ldr r2, =_flash_sizem
|
2021-05-20 19:16:46 +00:00
|
|
|
mov r3, #(CACHE_ALL & ~BUFFERED)
|
2011-02-06 20:10:45 +00:00
|
|
|
bl map_section
|
|
|
|
|
2021-05-20 19:16:46 +00:00
|
|
|
/* Enable write-back caching for RAM */
|
2011-02-06 20:10:45 +00:00
|
|
|
ldr r0, =_sdram_start
|
|
|
|
ldr r1, =_sdram_start
|
|
|
|
ldr r2, =_sdram_sizem
|
|
|
|
mov r3, #CACHE_ALL
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
bl enable_mmu
|
|
|
|
|
|
|
|
/* Initial setup is complete, go into main */
|
|
|
|
ldr pc, =main
|
|
|
|
|
|
|
|
/* If main returns go into an infinite loop */
|
|
|
|
b _dead_loop
|
|
|
|
|
|
|
|
/* Constants go here (from _start - .ltorg): */
|
|
|
|
.ltorg
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* _init_section: *
|
|
|
|
* This function initializes a section with the 32-bit value specified. *
|
|
|
|
******************************************************************************/
|
|
|
|
.section .init, "ax"
|
|
|
|
.code 32
|
|
|
|
.align 0x04
|
|
|
|
.global _init_section
|
|
|
|
.type _init_section, %function
|
|
|
|
/* r0 = init value
|
|
|
|
* r1 = start location
|
|
|
|
* r2 = end location
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* This function will not run if end is less than or equal to start */
|
|
|
|
_init_section:
|
|
|
|
cmp r2, r1
|
|
|
|
strhi r0, [r1], #4 /* store and increment start location */
|
|
|
|
bhi _init_section
|
|
|
|
bx lr
|
|
|
|
.ltorg
|
|
|
|
.size _init_section, .-_init_section
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* _copy_section: *
|
|
|
|
* This function copies a section to a new location *
|
|
|
|
******************************************************************************/
|
|
|
|
.section .init, "ax"
|
|
|
|
.code 32
|
|
|
|
.align 0x04
|
|
|
|
.global _copy_section
|
|
|
|
.type _copy_section, %function
|
|
|
|
/* r0 = source address
|
|
|
|
* r1 = destination start address
|
|
|
|
* r2 = destination end address
|
|
|
|
*
|
|
|
|
* r3 is a scratch register
|
2007-09-22 06:04:14 +00:00
|
|
|
*/
|
2011-02-06 20:10:45 +00:00
|
|
|
|
|
|
|
_copy_section:
|
|
|
|
cmp r2, r1
|
|
|
|
ldrhi r3, [r0], #4
|
|
|
|
strhi r3, [r1], #4
|
|
|
|
bhi _copy_section
|
|
|
|
bx lr
|
|
|
|
.ltorg
|
|
|
|
.size _copy_section, .-_copy_section
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* _delay_cycles: *
|
|
|
|
* This function delays for the specified number of cycles *
|
|
|
|
******************************************************************************/
|
|
|
|
.section .init, "ax"
|
|
|
|
.code 32
|
|
|
|
.align 0x04
|
|
|
|
.global _delay_cycles
|
|
|
|
.type _delay_cycles, %function
|
|
|
|
/* r0 = number of cycles to delay */
|
|
|
|
|
|
|
|
/* If r0 is zero it will be the maximum length delay */
|
|
|
|
_delay_cycles:
|
|
|
|
subs r0, r0, #1
|
|
|
|
bne _delay_cycles
|
|
|
|
bx lr
|
|
|
|
.ltorg
|
|
|
|
.size _delay_cycles, .-_delay_cycles
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* _dead_loop: Something really unexpected happened (like a reserved *
|
|
|
|
* exception). Just hang. *
|
|
|
|
******************************************************************************/
|
|
|
|
_dead_loop:
|
|
|
|
b _dead_loop
|
|
|
|
|
|
|
|
.ltorg
|
2007-09-22 06:04:14 +00:00
|
|
|
|