260 lines
7.6 KiB
ArmAsm
260 lines
7.6 KiB
ArmAsm
/* Startup code, we can't use non-PIC code nor RAM before the LMI is initialized:
|
|
* The CPU starts with physical address 0x0, however the linker is linked to virtual
|
|
* addresses and LMI.
|
|
* Non-PIC code means any indirect addressing other than relative to PC.
|
|
*/
|
|
.section .text.init, "ax"
|
|
.global _start
|
|
|
|
_start:
|
|
nop
|
|
nop
|
|
mov.l _sr_k, r0
|
|
ldc r0, sr
|
|
|
|
_disable_wdt:
|
|
mov.l _cpg_wdt_wtcsr_k, r0
|
|
mov.l _cpg_wdt_wtcsr_value_k, r1
|
|
mov.w r1, @r0
|
|
|
|
_configure_spinor:
|
|
mov.l _emi_spinor_config_data_k, r0
|
|
mov.l _emi_spinor_config_data_value_k, r1
|
|
mov.l r1, @r0
|
|
mov.l _emi_spinor_modeselect_k, r0
|
|
mov.l _emi_spinor_modeselect_value_k, r1
|
|
mov.l r1, @r0
|
|
|
|
/* TODO: Initialize PMB, setup caches !! */
|
|
|
|
/*
|
|
* We need PMBs for LMI and EMI, both cached and uncached.
|
|
* To configure an PMB region, two register writes need to be issued:
|
|
* 1: Write to PMB address array, with region virtual address.
|
|
* The PMB address array entry is calculated as follows:
|
|
* - PMB_SLOT_X_ADDR=0xF610_0X00, X=0-F, with a maximum of 16 regions.
|
|
* The slot contents are defined as follows:
|
|
* - 0xAA00_0100, AA=Virtual page number, bit 31:30 has to be 0b10
|
|
* i.e. VA should located in range 0x8000_0000 - 0xBFFF_FFFF
|
|
* Note: VA needs to align with its configured size.
|
|
* 2: Write to PMB data array, with region size and cache modes.
|
|
* The PMB data array entry is calculated as follows:
|
|
* PMB_SLOT_X_DATA=0xF710_0X00, X=0-F, with a maximum of 16 regions.
|
|
*/
|
|
_invalidate_pmb:
|
|
mov.l _pmb_address_base, r1 /* PMB address slot base address */
|
|
mov #0, r2 /* Value to be written to PMB address slot */
|
|
mov #1, r3 /* PMB address stride, 0x100 */
|
|
shll8 r3 /* See above */
|
|
mov #0, r0 /* Counter */
|
|
|
|
_loop_invalid_pmb:
|
|
mov.l r2, @r1 /* Clear slot N */
|
|
add r3, r1 /* Slot += 1 */
|
|
cmp/eq #15, r0 /* Counter == 15? */
|
|
bf/s _loop_invalid_pmb /* Note: this is a delayed branch, be careful. */
|
|
add #1, r0 /* Counter += 1 */
|
|
|
|
_setup_pmb:
|
|
mova _pmb_poke_start_k, r0
|
|
mov r0, r1
|
|
mova _pmb_poke_end_k, r0
|
|
mov r0, r2
|
|
|
|
_loop_setup_pmb:
|
|
mov.l @r1+, r0 /* 1st word, register address */
|
|
mov.l @r1+, r3 /* 2nd word, register value */
|
|
mov.l r3, @r0
|
|
cmp/gt r1, r2
|
|
bt _loop_setup_pmb
|
|
|
|
_invalidate_caches:
|
|
mov.l _ccn_ccr_k, r0
|
|
mov #0, r1
|
|
mov.l r1, @r0 /* Clear all bits */
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
_setup_caches:
|
|
mov.l _ccn_ccr_value_k, r1
|
|
mov.l r1, @r0
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
_init_lmi:
|
|
mov.l _init_ram_k, r1 /* Load actual function address to r1 */
|
|
jsr @r1 /* Jump to the init_ram function */
|
|
nop
|
|
|
|
_enable_se_mode:
|
|
mov.l _ccn_mmucr_k, r0
|
|
mov #4, r1 /* SH4_MMUCR_TI */
|
|
mov.l r1, @r0
|
|
|
|
mov.l _ccn_pascr_k, r0
|
|
mov.l _ccn_pascr_value_k, r1
|
|
mov.l r1, @r0
|
|
|
|
_go_non_privileged:
|
|
mov.l _copy_app_k, r0
|
|
ldc r0, spc
|
|
stc sr, r0
|
|
ldc r0, ssr
|
|
rte
|
|
nop
|
|
|
|
_copy_app:
|
|
mov.l _app_copy_end_k, r0 /* App load location, in EMI */
|
|
mov.l @r0, r1 /* Offset 0x04, eidata */
|
|
mov.l _app_base_k, r0 /* App base location, in LMI */
|
|
mov.l @r0, r2 /* Offset 0x00, stext */
|
|
|
|
_loop_copy_app:
|
|
mov.l @r0+, r3
|
|
mov.l r3, @r2
|
|
add #4, r2
|
|
cmp/gt r2, r1
|
|
bt _loop_copy_app
|
|
|
|
_jump_to_app:
|
|
mov.l _app_entry_k, r0 /* App entry point, in LMI, defined by app */
|
|
mov.l @r0, r1
|
|
jsr @r1
|
|
|
|
|
|
/* It would be more efficient by using indirect addressing instead of 8 instructions... */
|
|
/* Align to 4 byte boundary since we are loading the whole word */
|
|
.align 4
|
|
|
|
/* PMB address register */
|
|
_pmb_address_base:
|
|
.long 0xF6100000
|
|
|
|
/* PMB poke tables */
|
|
_pmb_poke_start_k:
|
|
.long 0xF6100000 /* Address entry #0 register : LMI lower half, 128MB, mapped to 0x8000_0000 */
|
|
.long 0x80000100 /* Address entry #0 data : LMI lower half, 128MB, mapped to 0x8000_0000 */
|
|
.long 0xF6100100 /* Address entry #1 register : LMI higher half, 128MB, mapped to 0x8800_0000 */
|
|
.long 0x88000100 /* Address entry #1 data : LMI higher half, 128MB, mapped to 0x8800_0000 */
|
|
.long 0xF6100200 /* Address entry #2 register : LMI lower half, 128MB, mapped to 0x9000_0000 */
|
|
.long 0x90000100 /* Address entry #2 data : LMI lower half, 128MB, mapped to 0x9000_0000 */
|
|
.long 0xF6100300 /* Address entry #3 register : LMI higher half, 128MB, mapped to 0x9800_0000 */
|
|
.long 0x98000100 /* Address entry #3 data : LMI higher half, 128MB, mapped to 0x9800_0000 */
|
|
.long 0xF6100400 /* Address entry #4 register : EMI NOR uncached, 64MB, mapped to 0xA000_0000 */
|
|
.long 0xA0000100 /* Address entry #4 data : EMI NOR uncached, 64MB, mapped to 0xA000_0000 */
|
|
.long 0xF6100500 /* Address entry #5 register : EMI NOR cached, 64MB, mapped to 0xA400_0000 */
|
|
.long 0xA4000100 /* Address entry #5 data : EMI NOR cached, 64MB, mapped to 0xA400_0000 */
|
|
.long 0xF7100000 /* Data entry #0 register : LMI lower half, 128MB, uncached, unbuffered */
|
|
.long 0x40000380 /* Data entry #0 data : LMI lower half, 128MB, uncached, unbuffered */
|
|
.long 0xF7100100 /* Data entry #1 register : LMI higher half, 128MB, uncached, unbuffered */
|
|
.long 0x48000380 /* Data entry #1 data : LMI higher half, 128MB, uncached, unbuffered */
|
|
.long 0xF7100200 /* Data entry #2 register : LMI lower half, 128MB, cached, buffered */
|
|
.long 0x40000188 /* Data entry #2 data : LMI lower half, 128MB, cached, buffered */
|
|
.long 0xF7100300 /* Data entry #3 register : LMI higher half, 128MB, cached, buffered */
|
|
.long 0x48000188 /* Data entry #3 data : LMI higher half, 128MB, cached, buffered */
|
|
.long 0xF7100400 /* Data entry #4 register : EMI NOR uncached, 64MB, uncached, unbuffered */
|
|
.long 0x00000310 /* Data entry #4 data : EMI NOR uncached, 64MB, uncached, unbuffered */
|
|
.long 0xF7100500 /* Data entry #5 register : EMI NOR cached, 64MB, cached, buffered */
|
|
.long 0x00000118 /* Data entry #5 data : EMI NOR cached, 64MB, cached, buffered */
|
|
|
|
_pmb_poke_end_k:
|
|
.long 0x0000000
|
|
|
|
/* CCN CCR address */
|
|
_ccn_ccr_k:
|
|
.long 0xFF00001C
|
|
_ccn_ccr_value_k:
|
|
.long 0x8000090D
|
|
_ccn_mmucr_k:
|
|
.long 0xFF000010
|
|
_ccn_pascr_k:
|
|
.long 0xFF000070
|
|
_ccn_pascr_value_k:
|
|
.long 0x80000000
|
|
|
|
/* SR content */
|
|
_sr_k:
|
|
.long 0x400000F0
|
|
|
|
/* WDT */
|
|
_cpg_wdt_wtcsr_k:
|
|
.long 0xFFC0000C
|
|
_cpg_wdt_wtcsr_value_k:
|
|
.long 0x0000A500
|
|
|
|
/* EMI SPI NOR configuration registers */
|
|
_emi_spinor_config_data_k:
|
|
.long 0xFE702020
|
|
_emi_spinor_config_data_value_k:
|
|
.long 0x00020011
|
|
_emi_spinor_modeselect_k:
|
|
.long 0xFE702018
|
|
_emi_spinor_modeselect_value_k:
|
|
.long 0x00000002
|
|
|
|
/* PIO registers for debugging */
|
|
_gpio_set_k:
|
|
.long 0xFD020004
|
|
_gpio_clr_k:
|
|
.long 0xFD020008
|
|
_gpio_clr_pc0_k:
|
|
.long 0xFD020028
|
|
_gpio_set_pc1_k:
|
|
.long 0xFD020034
|
|
_gpio_clr_pc2_k:
|
|
.long 0xFD020048
|
|
|
|
_system_config_34_k:
|
|
.long 0xFE001188
|
|
_system_config_34_value_k:
|
|
.long 0x00000F00
|
|
_gpio4_clr_pc0_k:
|
|
.long 0xFD024028
|
|
_gpio4_set_pc1_k:
|
|
.long 0xFD024034
|
|
_gpio4_set_pc2_k:
|
|
.long 0xFD024044
|
|
|
|
_copy_app_k:
|
|
.long _copy_app
|
|
|
|
/* libc FPU routine */
|
|
_set_fpscr_k:
|
|
.long ___set_fpscr
|
|
|
|
/* C library consts */
|
|
_stack_k:
|
|
.long _stack
|
|
_sidata_k:
|
|
.long _sidata
|
|
_sdata_k:
|
|
.long _sdata
|
|
_edata_k:
|
|
.long _edata
|
|
_end_k:
|
|
.long _end
|
|
|
|
/* Function pointers */
|
|
_init_ram_k:
|
|
.long _memory_setup_init_ram
|
|
|
|
_app_base_k:
|
|
.long 0xA0008000U /* stext */
|
|
_app_copy_end_k:
|
|
.long 0xA0008004U /* eiaddr */
|
|
_app_entry_k:
|
|
.long 0xA0008008U /* entry */ |