Home | History | Annotate | Download | only in cpu
      1 /* SPDX-License-Identifier: GPL-2.0+ */
      2 /*
      3  * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
      4  * Scott McNutt <smcnutt (at) psyent.com>
      5  */
      6 
      7 #include <asm-offsets.h>
      8 #include <config.h>
      9 #include <version.h>
     10 
     11 /*
     12  * icache and dcache configuration used only for start.S.
     13  * the values are chosen so that it will work for all configuration.
     14  */
     15 #define ICACHE_LINE_SIZE	32 /* fixed 32 */
     16 #define ICACHE_SIZE_MAX		0x10000 /* 64k max */
     17 #define DCACHE_LINE_SIZE_MIN	4 /* 4, 16, 32 */
     18 #define DCACHE_SIZE_MAX		0x10000 /* 64k max */
     19 
     20 	/* RESTART */
     21 	.text
     22 	.global _start, _except_start, _except_end
     23 
     24 _start:
     25 	wrctl	status, r0		/* Disable interrupts */
     26 	/*
     27 	 * ICACHE INIT -- only the icache line at the reset address
     28 	 * is invalidated at reset. So the init must stay within
     29 	 * the cache line size (8 words). If GERMS is used, we'll
     30 	 * just be invalidating the cache a second time. If cache
     31 	 * is not implemented initi behaves as nop.
     32 	 */
     33 	ori	r4, r0, %lo(ICACHE_LINE_SIZE)
     34 	movhi	r5, %hi(ICACHE_SIZE_MAX)
     35 	ori	r5, r5, %lo(ICACHE_SIZE_MAX)
     36 0:	initi	r5
     37 	sub	r5, r5, r4
     38 	bgt	r5, r0, 0b
     39 	br	_except_end	/* Skip the tramp */
     40 
     41 	/*
     42 	 * EXCEPTION TRAMPOLINE -- the following gets copied
     43 	 * to the exception address (below), but is otherwise at the
     44 	 * default exception vector offset (0x0020).
     45 	 */
     46 _except_start:
     47 	movhi	et, %hi(_exception)
     48 	ori	et, et, %lo(_exception)
     49 	jmp	et
     50 _except_end:
     51 
     52 	/*
     53 	 * INTERRUPTS -- for now, all interrupts masked and globally
     54 	 * disabled.
     55 	 */
     56 	wrctl	ienable, r0		/* All disabled	*/
     57 
     58 	/*
     59 	 * DCACHE INIT -- if dcache not implemented, initd behaves as
     60 	 * nop.
     61 	 */
     62 	ori	r4, r0, %lo(DCACHE_LINE_SIZE_MIN)
     63 	movhi	r5, %hi(DCACHE_SIZE_MAX)
     64 	ori	r5, r5, %lo(DCACHE_SIZE_MAX)
     65 	mov	r6, r0
     66 1:	initd	0(r6)
     67 	add	r6, r6, r4
     68 	bltu	r6, r5, 1b
     69 
     70 	/*
     71 	 * RELOCATE CODE, DATA & COMMAND TABLE -- the following code
     72 	 * assumes code, data and the command table are all
     73 	 * contiguous. This lets us relocate everything as a single
     74 	 * block. Make sure the linker script matches this ;-)
     75 	 */
     76 	nextpc	r4
     77 _cur:	movhi	r5, %hi(_cur - _start)
     78 	ori	r5, r5, %lo(_cur - _start)
     79 	sub	r4, r4, r5		/* r4 <- cur _start */
     80 	mov	r8, r4
     81 	movhi	r5, %hi(_start)
     82 	ori	r5, r5, %lo(_start)	/* r5 <- linked _start */
     83 	mov	sp, r5		/* initial stack below u-boot code */
     84 	beq	r4, r5, 3f
     85 
     86 	movhi	r6, %hi(CONFIG_SYS_MONITOR_LEN)
     87 	ori	r6, r6, %lo(CONFIG_SYS_MONITOR_LEN)
     88 	add	r6, r6, r5
     89 2:	ldwio	r7, 0(r4)
     90 	addi	r4, r4, 4
     91 	stwio	r7, 0(r5)
     92 	addi	r5, r5, 4
     93 	bne	r5, r6, 2b
     94 3:
     95 
     96 	/* JUMP TO RELOC ADDR */
     97 	movhi	r4, %hi(_reloc)
     98 	ori	r4, r4, %lo(_reloc)
     99 	jmp	r4
    100 _reloc:
    101 
    102 	/* STACK INIT -- zero top two words for call back chain. */
    103 	addi	sp, sp, -8
    104 	stw	r0, 0(sp)
    105 	stw	r0, 4(sp)
    106 	mov	fp, sp
    107 
    108 #ifdef CONFIG_DEBUG_UART
    109 	/* Set up the debug UART */
    110 	movhi	r2, %hi(debug_uart_init@h)
    111 	ori	r2, r2, %lo(debug_uart_init@h)
    112 	callr	r2
    113 #endif
    114 
    115 	/* Allocate and initialize reserved area, update SP */
    116 	mov	r4, sp
    117 	movhi	r2, %hi(board_init_f_alloc_reserve@h)
    118 	ori	r2, r2, %lo(board_init_f_alloc_reserve@h)
    119 	callr	r2
    120 	mov	sp, r2
    121 	mov	r4, sp
    122 	movhi	r2, %hi(board_init_f_init_reserve@h)
    123 	ori	r2, r2, %lo(board_init_f_init_reserve@h)
    124 	callr	r2
    125 
    126 	/* Update frame-pointer */
    127 	mov	fp, sp
    128 
    129 	/* Call board_init_f -- never returns */
    130 	mov	r4, r0
    131 	movhi	r2, %hi(board_init_f@h)
    132 	ori	r2, r2, %lo(board_init_f@h)
    133 	callr	r2
    134 
    135 	/*
    136 	 * NEVER RETURNS -- but branch to the _start just
    137 	 * in case ;-)
    138 	 */
    139 	br	_start
    140 
    141 	/*
    142 	 * relocate_code -- Nios2 handles the relocation above. But
    143 	 * the generic board code monkeys with the heap, stack, etc.
    144 	 * (it makes some assumptions that may not be appropriate
    145 	 * for Nios). Nevertheless, we capitulate here.
    146 	 *
    147 	 * We'll call the board_init_r from here since this isn't
    148 	 * supposed to return.
    149 	 *
    150 	 * void relocate_code (ulong sp, gd_t *global_data,
    151 	 *			ulong reloc_addr)
    152 	 *			__attribute__ ((noreturn));
    153 	 */
    154 	.text
    155 	.global relocate_code
    156 
    157 relocate_code:
    158 	mov	sp, r4		/* Set the new sp */
    159 	mov	r4, r5
    160 
    161 	/*
    162 	 * ZERO BSS/SBSS -- bss and sbss are assumed to be adjacent
    163 	 * and between __bss_start and __bss_end.
    164 	 */
    165 	movhi	r5, %hi(__bss_start)
    166 	ori	r5, r5, %lo(__bss_start)
    167 	movhi	r6, %hi(__bss_end)
    168 	ori	r6, r6, %lo(__bss_end)
    169 	beq	r5, r6, 5f
    170 
    171 4:	stw	r0, 0(r5)
    172 	addi	r5, r5, 4
    173 	bne	r5, r6, 4b
    174 5:
    175 
    176 	movhi	r8, %hi(board_init_r@h)
    177 	ori	r8, r8, %lo(board_init_r@h)
    178 	callr	r8
    179 	ret
    180