xref: /openbmc/u-boot/arch/nios2/cpu/start.S (revision ecc30663)
137e4dafaSPeter Tyser/*
237e4dafaSPeter Tyser * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
337e4dafaSPeter Tyser * Scott McNutt <smcnutt@psyent.com>
437e4dafaSPeter Tyser *
51a459660SWolfgang Denk * SPDX-License-Identifier:	GPL-2.0+
637e4dafaSPeter Tyser */
737e4dafaSPeter Tyser
825ddd1fbSWolfgang Denk#include <asm-offsets.h>
937e4dafaSPeter Tyser#include <config.h>
1037e4dafaSPeter Tyser#include <version.h>
1137e4dafaSPeter Tyser
1255e2b4d4SThomas Chou/*
1355e2b4d4SThomas Chou * icache and dcache configuration used only for start.S.
1455e2b4d4SThomas Chou * the values are chosen so that it will work for all configuration.
1555e2b4d4SThomas Chou */
1655e2b4d4SThomas Chou#define ICACHE_LINE_SIZE	32 /* fixed 32 */
1755e2b4d4SThomas Chou#define ICACHE_SIZE_MAX		0x10000 /* 64k max */
1855e2b4d4SThomas Chou#define DCACHE_LINE_SIZE_MIN	4 /* 4, 16, 32 */
1955e2b4d4SThomas Chou#define DCACHE_SIZE_MAX		0x10000 /* 64k max */
2055e2b4d4SThomas Chou
214a572fa8SThomas Chou	/* RESTART */
2237e4dafaSPeter Tyser	.text
23b8112091SThomas Chou	.global _start, _except_start, _except_end
2437e4dafaSPeter Tyser
2537e4dafaSPeter Tyser_start:
26fd2712d0SThomas Chou	wrctl	status, r0		/* Disable interrupts */
274a572fa8SThomas Chou	/*
284a572fa8SThomas Chou	 * ICACHE INIT -- only the icache line at the reset address
2937e4dafaSPeter Tyser	 * is invalidated at reset. So the init must stay within
3037e4dafaSPeter Tyser	 * the cache line size (8 words). If GERMS is used, we'll
3137e4dafaSPeter Tyser	 * just be invalidating the cache a second time. If cache
3237e4dafaSPeter Tyser	 * is not implemented initi behaves as nop.
3337e4dafaSPeter Tyser	 */
3455e2b4d4SThomas Chou	ori	r4, r0, %lo(ICACHE_LINE_SIZE)
3555e2b4d4SThomas Chou	movhi	r5, %hi(ICACHE_SIZE_MAX)
3655e2b4d4SThomas Chou	ori	r5, r5, %lo(ICACHE_SIZE_MAX)
37fd2712d0SThomas Chou0:	initi	r5
38fd2712d0SThomas Chou	sub	r5, r5, r4
39fd2712d0SThomas Chou	bgt	r5, r0, 0b
4037e4dafaSPeter Tyser	br	_except_end	/* Skip the tramp */
4137e4dafaSPeter Tyser
424a572fa8SThomas Chou	/*
434a572fa8SThomas Chou	 * EXCEPTION TRAMPOLINE -- the following gets copied
4437e4dafaSPeter Tyser	 * to the exception address (below), but is otherwise at the
4537e4dafaSPeter Tyser	 * default exception vector offset (0x0020).
4637e4dafaSPeter Tyser	 */
4737e4dafaSPeter Tyser_except_start:
4837e4dafaSPeter Tyser	movhi	et, %hi(_exception)
4937e4dafaSPeter Tyser	ori	et, et, %lo(_exception)
5037e4dafaSPeter Tyser	jmp	et
5137e4dafaSPeter Tyser_except_end:
5237e4dafaSPeter Tyser
534a572fa8SThomas Chou	/*
544a572fa8SThomas Chou	 * INTERRUPTS -- for now, all interrupts masked and globally
5537e4dafaSPeter Tyser	 * disabled.
5637e4dafaSPeter Tyser	 */
5737e4dafaSPeter Tyser	wrctl	ienable, r0		/* All disabled	*/
5837e4dafaSPeter Tyser
594a572fa8SThomas Chou	/*
604a572fa8SThomas Chou	 * DCACHE INIT -- if dcache not implemented, initd behaves as
6137e4dafaSPeter Tyser	 * nop.
6237e4dafaSPeter Tyser	 */
6355e2b4d4SThomas Chou	ori	r4, r0, %lo(DCACHE_LINE_SIZE_MIN)
6455e2b4d4SThomas Chou	movhi	r5, %hi(DCACHE_SIZE_MAX)
6555e2b4d4SThomas Chou	ori	r5, r5, %lo(DCACHE_SIZE_MAX)
6637e4dafaSPeter Tyser	mov	r6, r0
6737e4dafaSPeter Tyser1:	initd	0(r6)
6837e4dafaSPeter Tyser	add	r6, r6, r4
6937e4dafaSPeter Tyser	bltu	r6, r5, 1b
7037e4dafaSPeter Tyser
714a572fa8SThomas Chou	/*
724a572fa8SThomas Chou	 * RELOCATE CODE, DATA & COMMAND TABLE -- the following code
7337e4dafaSPeter Tyser	 * assumes code, data and the command table are all
7437e4dafaSPeter Tyser	 * contiguous. This lets us relocate everything as a single
7537e4dafaSPeter Tyser	 * block. Make sure the linker script matches this ;-)
7637e4dafaSPeter Tyser	 */
7737e4dafaSPeter Tyser	nextpc	r4
7837e4dafaSPeter Tyser_cur:	movhi	r5, %hi(_cur - _start)
7937e4dafaSPeter Tyser	ori	r5, r5, %lo(_cur - _start)
8037e4dafaSPeter Tyser	sub	r4, r4, r5		/* r4 <- cur _start */
8137e4dafaSPeter Tyser	mov	r8, r4
8237e4dafaSPeter Tyser	movhi	r5, %hi(_start)
8337e4dafaSPeter Tyser	ori	r5, r5, %lo(_start)	/* r5 <- linked _start */
8465af9f69SThomas Chou	mov	sp, r5		/* initial stack below u-boot code */
8537e4dafaSPeter Tyser	beq	r4, r5, 3f
8637e4dafaSPeter Tyser
87e900298eSThomas Chou	movhi	r6, %hi(CONFIG_SYS_MONITOR_LEN)
88e900298eSThomas Chou	ori	r6, r6, %lo(CONFIG_SYS_MONITOR_LEN)
89e900298eSThomas Chou	add	r6, r6, r5
9037e4dafaSPeter Tyser2:	ldwio	r7, 0(r4)
9137e4dafaSPeter Tyser	addi	r4, r4, 4
9237e4dafaSPeter Tyser	stwio	r7, 0(r5)
9337e4dafaSPeter Tyser	addi	r5, r5, 4
9437e4dafaSPeter Tyser	bne	r5, r6, 2b
9537e4dafaSPeter Tyser3:
9637e4dafaSPeter Tyser
9737e4dafaSPeter Tyser	/* JUMP TO RELOC ADDR */
9837e4dafaSPeter Tyser	movhi	r4, %hi(_reloc)
9937e4dafaSPeter Tyser	ori	r4, r4, %lo(_reloc)
10037e4dafaSPeter Tyser	jmp	r4
10137e4dafaSPeter Tyser_reloc:
10237e4dafaSPeter Tyser
1034a572fa8SThomas Chou	/* STACK INIT -- zero top two words for call back chain. */
10437e4dafaSPeter Tyser	addi	sp, sp, -8
10537e4dafaSPeter Tyser	stw	r0, 0(sp)
10637e4dafaSPeter Tyser	stw	r0, 4(sp)
10737e4dafaSPeter Tyser	mov	fp, sp
10837e4dafaSPeter Tyser
109*ecc30663SAlbert ARIBAUD	/* Allocate and initialize reserved area, update SP */
1103e468e68SThomas Chou	mov	r4, sp
111*ecc30663SAlbert ARIBAUD	movhi	r2, %hi(board_init_f_alloc_reserve@h)
112*ecc30663SAlbert ARIBAUD	ori	r2, r2, %lo(board_init_f_alloc_reserve@h)
113*ecc30663SAlbert ARIBAUD	callr	r2
114*ecc30663SAlbert ARIBAUD	mov	sp, r2
115*ecc30663SAlbert ARIBAUD	mov	r4, sp
116*ecc30663SAlbert ARIBAUD	movhi	r2, %hi(board_init_f_init_reserve@h)
117*ecc30663SAlbert ARIBAUD	ori	r2, r2, %lo(board_init_f_init_reserve@h)
1183e468e68SThomas Chou	callr	r2
1193e468e68SThomas Chou
120*ecc30663SAlbert ARIBAUD	/* Update frame-pointer */
1213e468e68SThomas Chou	mov	fp, sp
1223e468e68SThomas Chou
1234a572fa8SThomas Chou	/* Call board_init_f -- never returns */
1245ff10aa7SThomas Chou	mov	r4, r0
1255ff10aa7SThomas Chou	movhi	r2, %hi(board_init_f@h)
1265ff10aa7SThomas Chou	ori	r2, r2, %lo(board_init_f@h)
1275ff10aa7SThomas Chou	callr	r2
12837e4dafaSPeter Tyser
1294a572fa8SThomas Chou	/*
1304a572fa8SThomas Chou	 * NEVER RETURNS -- but branch to the _start just
13137e4dafaSPeter Tyser	 * in case ;-)
13237e4dafaSPeter Tyser	 */
13337e4dafaSPeter Tyser	br	_start
13437e4dafaSPeter Tyser
1355ff10aa7SThomas Chou	/*
1365ff10aa7SThomas Chou	 * relocate_code -- Nios2 handles the relocation above. But
1375ff10aa7SThomas Chou	 * the generic board code monkeys with the heap, stack, etc.
1385ff10aa7SThomas Chou	 * (it makes some assumptions that may not be appropriate
1395ff10aa7SThomas Chou	 * for Nios). Nevertheless, we capitulate here.
1405ff10aa7SThomas Chou	 *
1415ff10aa7SThomas Chou	 * We'll call the board_init_r from here since this isn't
1425ff10aa7SThomas Chou	 * supposed to return.
1435ff10aa7SThomas Chou	 *
1445ff10aa7SThomas Chou	 * void relocate_code (ulong sp, gd_t *global_data,
1455ff10aa7SThomas Chou	 *			ulong reloc_addr)
1465ff10aa7SThomas Chou	 *			__attribute__ ((noreturn));
1475ff10aa7SThomas Chou	 */
1485ff10aa7SThomas Chou	.text
1495ff10aa7SThomas Chou	.global relocate_code
1505ff10aa7SThomas Chou
1515ff10aa7SThomas Chourelocate_code:
1525ff10aa7SThomas Chou	mov	sp, r4		/* Set the new sp */
1535ff10aa7SThomas Chou	mov	r4, r5
1544192b8c3SThomas Chou
1554192b8c3SThomas Chou	/*
1564192b8c3SThomas Chou	 * ZERO BSS/SBSS -- bss and sbss are assumed to be adjacent
1574192b8c3SThomas Chou	 * and between __bss_start and __bss_end.
1584192b8c3SThomas Chou	 */
1594192b8c3SThomas Chou	movhi	r5, %hi(__bss_start)
1604192b8c3SThomas Chou	ori	r5, r5, %lo(__bss_start)
1614192b8c3SThomas Chou	movhi	r6, %hi(__bss_end)
1624192b8c3SThomas Chou	ori	r6, r6, %lo(__bss_end)
1634192b8c3SThomas Chou	beq	r5, r6, 5f
1644192b8c3SThomas Chou
1659208d7ebSThomas Chou4:	stw	r0, 0(r5)
1664192b8c3SThomas Chou	addi	r5, r5, 4
1674192b8c3SThomas Chou	bne	r5, r6, 4b
1684192b8c3SThomas Chou5:
1694192b8c3SThomas Chou
1705ff10aa7SThomas Chou	movhi	r8, %hi(board_init_r@h)
1715ff10aa7SThomas Chou	ori	r8, r8, %lo(board_init_r@h)
1725ff10aa7SThomas Chou	callr	r8
1735ff10aa7SThomas Chou	ret
174