205 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0+ */
 | |
| /*
 | |
|  * Startup Code for RISC-V Core
 | |
|  *
 | |
|  * Copyright (c) 2017 Microsemi Corporation.
 | |
|  * Copyright (c) 2017 Padmarao Begari <Padmarao.Begari@microsemi.com>
 | |
|  *
 | |
|  * Copyright (C) 2017 Andes Technology Corporation
 | |
|  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
 | |
|  */
 | |
| 
 | |
| #include <asm-offsets.h>
 | |
| #include <config.h>
 | |
| #include <common.h>
 | |
| #include <elf.h>
 | |
| #include <asm/encoding.h>
 | |
| #include <generated/asm-offsets.h>
 | |
| 
 | |
| #ifdef CONFIG_32BIT
 | |
| #define LREG			lw
 | |
| #define SREG			sw
 | |
| #define REGBYTES		4
 | |
| #define RELOC_TYPE		R_RISCV_32
 | |
| #define SYM_INDEX		0x8
 | |
| #define SYM_SIZE		0x10
 | |
| #else
 | |
| #define LREG			ld
 | |
| #define SREG			sd
 | |
| #define REGBYTES		8
 | |
| #define RELOC_TYPE		R_RISCV_64
 | |
| #define SYM_INDEX		0x20
 | |
| #define SYM_SIZE		0x18
 | |
| #endif
 | |
| 
 | |
| .section .text
 | |
| .globl _start
 | |
| _start:
 | |
| 	/* save hart id and dtb pointer */
 | |
| 	mv	s0, a0
 | |
| 	mv	s1, a1
 | |
| 
 | |
| 	la	t0, trap_entry
 | |
| 	csrw	MODE_PREFIX(tvec), t0
 | |
| 
 | |
| 	/* mask all interrupts */
 | |
| 	csrw	MODE_PREFIX(ie), zero
 | |
| 
 | |
| 	/* Enable cache */
 | |
| 	jal	icache_enable
 | |
| 	jal	dcache_enable
 | |
| 
 | |
| /*
 | |
|  * Set stackpointer in internal/ex RAM to call board_init_f
 | |
|  */
 | |
| call_board_init_f:
 | |
| 	li	t0, -16
 | |
| 	li	t1, CONFIG_SYS_INIT_SP_ADDR
 | |
| 	and	sp, t1, t0		/* force 16 byte alignment */
 | |
| 
 | |
| #ifdef CONFIG_DEBUG_UART
 | |
| 	jal	debug_uart_init
 | |
| #endif
 | |
| 
 | |
| call_board_init_f_0:
 | |
| 	mv	a0, sp
 | |
| 	jal	board_init_f_alloc_reserve
 | |
| 	mv	sp, a0
 | |
| 
 | |
| 	la	t0, prior_stage_fdt_address
 | |
| 	SREG	s1, 0(t0)
 | |
| 
 | |
| 	jal	board_init_f_init_reserve
 | |
| 
 | |
| 	/* save the boot hart id to global_data */
 | |
| 	SREG	s0, GD_BOOT_HART(gp)
 | |
| 
 | |
| 	mv	a0, zero		/* a0 <-- boot_flags = 0 */
 | |
| 	la	t5, board_init_f
 | |
| 	jr	t5			/* jump to board_init_f() */
 | |
| 
 | |
| /*
 | |
|  * void relocate_code (addr_sp, gd, addr_moni)
 | |
|  *
 | |
|  * This "function" does not return, instead it continues in RAM
 | |
|  * after relocating the monitor code.
 | |
|  *
 | |
|  */
 | |
| .globl relocate_code
 | |
| relocate_code:
 | |
| 	mv	s2, a0			/* save addr_sp */
 | |
| 	mv	s3, a1			/* save addr of gd */
 | |
| 	mv	s4, a2			/* save addr of destination */
 | |
| 
 | |
| /*
 | |
|  *Set up the stack
 | |
|  */
 | |
| stack_setup:
 | |
| 	mv	sp, s2
 | |
| 	la	t0, _start
 | |
| 	sub	t6, s4, t0		/* t6 <- relocation offset */
 | |
| 	beq	t0, s4, clear_bss	/* skip relocation */
 | |
| 
 | |
| 	mv	t1, s4			/* t1 <- scratch for copy_loop */
 | |
| 	la	t3, __bss_start
 | |
| 	sub	t3, t3, t0		/* t3 <- __bss_start_ofs */
 | |
| 	add	t2, t0, t3		/* t2 <- source end address */
 | |
| 
 | |
| copy_loop:
 | |
| 	LREG	t5, 0(t0)
 | |
| 	addi	t0, t0, REGBYTES
 | |
| 	SREG	t5, 0(t1)
 | |
| 	addi	t1, t1, REGBYTES
 | |
| 	blt	t0, t2, copy_loop
 | |
| 
 | |
| /*
 | |
|  * Update dynamic relocations after board_init_f
 | |
|  */
 | |
| fix_rela_dyn:
 | |
| 	la	t1, __rel_dyn_start
 | |
| 	la	t2, __rel_dyn_end
 | |
| 	beq	t1, t2, clear_bss
 | |
| 	add	t1, t1, t6		/* t1 <- rela_dyn_start in RAM */
 | |
| 	add	t2, t2, t6		/* t2 <- rela_dyn_end in RAM */
 | |
| 
 | |
| /*
 | |
|  * skip first reserved entry: address, type, addend
 | |
|  */
 | |
| 	bne	t1, t2, 7f
 | |
| 
 | |
| 6:
 | |
| 	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
 | |
| 	li	t3, R_RISCV_RELATIVE	/* reloc type R_RISCV_RELATIVE */
 | |
| 	bne	t5, t3, 8f		/* skip non-RISCV_RELOC entries */
 | |
| 	LREG	t3, -(REGBYTES*3)(t1)
 | |
| 	LREG	t5, -(REGBYTES)(t1)	/* t5 <-- addend */
 | |
| 	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
 | |
| 	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
 | |
| 	SREG	t5, 0(t3)
 | |
| 7:
 | |
| 	addi	t1, t1, (REGBYTES*3)
 | |
| 	ble	t1, t2, 6b
 | |
| 
 | |
| 8:
 | |
| 	la	t4, __dyn_sym_start
 | |
| 	add	t4, t4, t6
 | |
| 
 | |
| 9:
 | |
| 	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
 | |
| 	srli	t0, t5, SYM_INDEX	/* t0 <--- sym table index */
 | |
| 	andi	t5, t5, 0xFF		/* t5 <--- relocation type */
 | |
| 	li	t3, RELOC_TYPE
 | |
| 	bne	t5, t3, 10f		/* skip non-addned entries */
 | |
| 
 | |
| 	LREG	t3, -(REGBYTES*3)(t1)
 | |
| 	li	t5, SYM_SIZE
 | |
| 	mul	t0, t0, t5
 | |
| 	add	s5, t4, t0
 | |
| 	LREG	t5, REGBYTES(s5)
 | |
| 	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
 | |
| 	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
 | |
| 	SREG	t5, 0(t3)
 | |
| 10:
 | |
| 	addi	t1, t1, (REGBYTES*3)
 | |
| 	ble	t1, t2, 9b
 | |
| 
 | |
| /*
 | |
|  * trap update
 | |
| */
 | |
| 	la	t0, trap_entry
 | |
| 	add	t0, t0, t6
 | |
| 	csrw	MODE_PREFIX(tvec), t0
 | |
| 
 | |
| clear_bss:
 | |
| 	la	t0, __bss_start		/* t0 <- rel __bss_start in FLASH */
 | |
| 	add	t0, t0, t6		/* t0 <- rel __bss_start in RAM */
 | |
| 	la	t1, __bss_end		/* t1 <- rel __bss_end in FLASH */
 | |
| 	add	t1, t1, t6		/* t1 <- rel __bss_end in RAM */
 | |
| 	beq	t0, t1, call_board_init_r
 | |
| 
 | |
| clbss_l:
 | |
| 	SREG	zero, 0(t0)		/* clear loop... */
 | |
| 	addi	t0, t0, REGBYTES
 | |
| 	bne	t0, t1, clbss_l
 | |
| 
 | |
| /*
 | |
|  * We are done. Do not return, instead branch to second part of board
 | |
|  * initialization, now running from RAM.
 | |
|  */
 | |
| call_board_init_r:
 | |
| 	jal	invalidate_icache_all
 | |
| 	jal	flush_dcache_all
 | |
| 	la	t0, board_init_r
 | |
| 	mv	t4, t0			/* offset of board_init_r() */
 | |
| 	add	t4, t4, t6		/* real address of board_init_r() */
 | |
| /*
 | |
|  * setup parameters for board_init_r
 | |
|  */
 | |
| 	mv	a0, s3			/* gd_t */
 | |
| 	mv	a1, s4			/* dest_addr */
 | |
| 
 | |
| /*
 | |
|  * jump to it ...
 | |
|  */
 | |
| 	jr	t4			/* jump to board_init_r() */
 | 
