/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include /* exports */ GTEXT(__start) GTEXT(__reset) /* imports */ GTEXT(_PrepC) GTEXT(_interrupt_stack) /* Allow use of r1/at (the assembler temporary register) in this * code, normally reserved for internal assembler use */ .set noat #if CONFIG_INCLUDE_RESET_VECTOR /* * Reset vector entry point into the system. Placed into special 'reset' * section so that the linker puts this at ALT_CPU_RESET_ADDR defined in * system.h * * This code can be at most 0x20 bytes, since the exception vector for Nios II * is usually configured to be 0x20 past the reset vector. */ SECTION_FUNC(reset, __reset) #if ALT_CPU_ICACHE_SIZE > 0 /* Aside from the instruction cache line associated with the reset * vector, the contents of the cache memories are indeterminate after * reset. To ensure cache coherency after reset, the reset handler * located at the reset vector must immediately initialize the * instruction cache. Next, either the reset handler or a subsequent * routine should proceed to initialize the data cache. * * The cache memory sizes are *always* a power of 2. */ #if ALT_CPU_ICACHE_SIZE > 0x8000 movhi r2, %hi(ALT_CPU_ICACHE_SIZE) #else movui r2, ALT_CPU_ICACHE_SIZE #endif 0: /* If ECC present, need to execute initd for each word address * to ensure ECC parity bits in data RAM get initialized */ #ifdef ALT_CPU_ECC_PRESENT subi r2, r2, 4 #else subi r2, r2, ALT_CPU_ICACHE_LINE_SIZE #endif initi r2 bgt r2, zero, 0b #endif /* ALT_CPU_ICACHE_SIZE > 0 */ /* Done all we need to do here, jump to __text_start */ movhi r1, %hi(__start) ori r1, r1, %lo(__start) jmp r1 #endif /* CONFIG_INCLUDE_RESET_VECTOR */ /* Remainder of asm-land initialization code before we can jump into * the C domain */ SECTION_FUNC(TEXT, __start) /* TODO if shadow register sets enabled, ensure we are in set 0 * ZEP-258 */ /* Initialize the data cache if booting from bare metal. If * we're not booting from our reset vector, either by a bootloader * or JTAG, assume caches already initialized. */ #if ALT_CPU_DCACHE_SIZE > 0 && defined(CONFIG_INCLUDE_RESET_VECTOR) /* Per documentation data cache size is always a power of two. */ #if ALT_CPU_DCACHE_SIZE > 0x8000 movhi r2, %hi(ALT_CPU_DCACHE_SIZE) #else movui r2, ALT_CPU_DCACHE_SIZE #endif 0: /* If ECC present, need to execute initd for each word address * to ensure ECC parity bits in data RAM get initialized */ #ifdef ALT_CPU_ECC_PRESENT subi r2, r2, 4 #else subi r2, r2, ALT_CPU_DCACHE_LINE_SIZE #endif initd 0(r2) bgt r2, zero, 0b #endif /* ALT_CPU_DCACHE_SIZE && defined(CONFIG_INCLUDE_RESET_VECTOR) */ #ifdef CONFIG_INIT_STACKS /* Pre-populate all bytes in _interrupt_stack with 0xAA * init.c enforces that the _interrupt_stack pointer * and CONFIG_ISR_STACK_SIZE are a multiple of STACK_ALIGN (4) */ movhi r1, %hi(_interrupt_stack) ori r1, r1, %lo(_interrupt_stack) movhi r2, %hi(CONFIG_ISR_STACK_SIZE) ori r2, r2, %lo(CONFIG_ISR_STACK_SIZE) /* Put constant 0xaaaaaaaa in r3 */ movhi r3, 0xaaaa ori r3, r3, 0xaaaa 1: /* Loop through the _interrupt_stack treating it as an array of * u32_t, setting each element to r3 */ stw r3, (r1) subi r2, r2, 4 addi r1, r1, 4 blt r0, r2, 1b #endif /* Set up the initial stack pointer to the interrupt stack, safe * to use this as the CPU boots up with interrupts disabled and we * don't turn them on until much later, when the kernel is on * the main stack */ movhi sp, %hi(_interrupt_stack) ori sp, sp, %lo(_interrupt_stack) addi sp, sp, CONFIG_ISR_STACK_SIZE #if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL) || \ defined(CONFIG_GP_ALL_DATA) /* Initialize global pointer with the linker variable we set */ movhi gp, %hi(_gp) ori gp, gp, %lo(_gp) #endif /* TODO if shadow register sets enabled, interate through them to set * up. Need to clear r0, write gp, set the execption stack pointer * ZEP-258 */ /* Jump into C domain. _PrepC zeroes BSS, copies rw data into RAM, * and then enters _Cstart */ call _PrepC