Home | History | Annotate | Download | only in cpu
      1 /* SPDX-License-Identifier: GPL-2.0+ */
      2 /*
      3  * (C) Copyright 2007 Michal Simek
      4  * (C) Copyright 2004 Atmark Techno, Inc.
      5  *
      6  * Michal  SIMEK <monstr (at) monstr.eu>
      7  * Yasushi SHOJI <yashi (at) atmark-techno.com>
      8  */
      9 
     10 #include <asm-offsets.h>
     11 #include <config.h>
     12 
     13 	.text
     14 	.global _start
     15 _start:
     16 	/*
     17 	 * reserve registers:
     18 	 * r10: Stores little/big endian offset for vectors
     19 	 * r2: Stores imm opcode
     20 	 * r3: Stores brai opcode
     21 	 */
     22 
     23 	mts	rmsr, r0	/* disable cache */
     24 
     25 	addi	r8, r0, __end
     26 	mts	rslr, r8
     27 	/* TODO: Redo this code to call board_init_f_*() */
     28 #if defined(CONFIG_SPL_BUILD)
     29 	addi	r1, r0, CONFIG_SPL_STACK_ADDR
     30 	mts	rshr, r1
     31 	addi	r1, r1, -4	/* Decrement SP to top of memory */
     32 #else
     33 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
     34 	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN)
     35 #else
     36 	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
     37 #endif
     38 	mts	rshr, r1
     39 	addi	r1, r1, -4	/* Decrement SP to top of memory */
     40 
     41 	/* Find-out if u-boot is running on BIG/LITTLE endian platform
     42 	 * There are some steps which is necessary to keep in mind:
     43 	 * 1. Setup offset value to r6
     44 	 * 2. Store word offset value to address 0x0
     45 	 * 3. Load just byte from address 0x0
     46 	 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
     47 	 *     value that's why is on address 0x0
     48 	 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
     49 	 */
     50 	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
     51 	lwi	r7, r0, 0x28
     52 	swi	r6, r0, 0x28 /* used first unused MB vector */
     53 	lbui	r10, r0, 0x28 /* used first unused MB vector */
     54 	swi	r7, r0, 0x28
     55 
     56 	/* add opcode instruction for 32bit jump - 2 instruction imm & brai */
     57 	addi	r2, r0, 0xb0000000	/* hex b000 opcode imm */
     58 	addi	r3, r0, 0xb8080000	/* hew b808 opcode brai */
     59 
     60 #ifdef CONFIG_SYS_RESET_ADDRESS
     61 	/* reset address */
     62 	swi	r2, r0, 0x0	/* reset address - imm opcode */
     63 	swi	r3, r0, 0x4	/* reset address - brai opcode */
     64 
     65 	addik	r6, r0, CONFIG_SYS_RESET_ADDRESS
     66 	sw	r6, r1, r0
     67 	lhu	r7, r1, r10
     68 	rsubi	r8, r10, 0x2
     69 	sh	r7, r0, r8
     70 	rsubi	r8, r10, 0x6
     71 	sh	r6, r0, r8
     72 #endif
     73 
     74 #ifdef CONFIG_SYS_USR_EXCEP
     75 	/* user_vector_exception */
     76 	swi	r2, r0, 0x8	/* user vector exception - imm opcode */
     77 	swi	r3, r0, 0xC	/* user vector exception - brai opcode */
     78 
     79 	addik	r6, r0, _exception_handler
     80 	sw	r6, r1, r0
     81 	/*
     82 	 * BIG ENDIAN memory map for user exception
     83 	 * 0x8: 0xB000XXXX
     84 	 * 0xC: 0xB808XXXX
     85 	 *
     86 	 * then it is necessary to count address for storing the most significant
     87 	 * 16bits from _exception_handler address and copy it to
     88 	 * 0xa address. Big endian use offset in r10=0 that's why is it just
     89 	 * 0xa address. The same is done for the least significant 16 bits
     90 	 * for 0xe address.
     91 	 *
     92 	 * LITTLE ENDIAN memory map for user exception
     93 	 * 0x8: 0xXXXX00B0
     94 	 * 0xC: 0xXXXX08B8
     95 	 *
     96 	 * Offset is for little endian setup to 0x2. rsubi instruction decrease
     97 	 * address value to ensure that points to proper place which is
     98 	 * 0x8 for the most significant 16 bits and
     99 	 * 0xC for the least significant 16 bits
    100 	 */
    101 	lhu	r7, r1, r10
    102 	rsubi	r8, r10, 0xa
    103 	sh	r7, r0, r8
    104 	rsubi	r8, r10, 0xe
    105 	sh	r6, r0, r8
    106 #endif
    107 
    108 	/* interrupt_handler */
    109 	swi	r2, r0, 0x10	/* interrupt - imm opcode */
    110 	swi	r3, r0, 0x14	/* interrupt - brai opcode */
    111 
    112 	addik	r6, r0, _interrupt_handler
    113 	sw	r6, r1, r0
    114 	lhu	r7, r1, r10
    115 	rsubi	r8, r10, 0x12
    116 	sh	r7, r0, r8
    117 	rsubi	r8, r10, 0x16
    118 	sh	r6, r0, r8
    119 
    120 	/* hardware exception */
    121 	swi	r2, r0, 0x20	/* hardware exception - imm opcode */
    122 	swi	r3, r0, 0x24	/* hardware exception - brai opcode */
    123 
    124 	addik	r6, r0, _hw_exception_handler
    125 	sw	r6, r1, r0
    126 	lhu	r7, r1, r10
    127 	rsubi	r8, r10, 0x22
    128 	sh	r7, r0, r8
    129 	rsubi	r8, r10, 0x26
    130 	sh	r6, r0, r8
    131 #endif /* CONFIG_SPL_BUILD */
    132 
    133 	/* Flush cache before enable cache */
    134 	addik	r5, r0, 0
    135 	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
    136 	bralid r15, flush_cache
    137 	nop
    138 
    139 	/* enable instruction and data cache */
    140 	mfs	r12, rmsr
    141 	ori	r12, r12, 0x1a0
    142 	mts	rmsr, r12
    143 
    144 	/* TODO: Redo this code to call board_init_f_*() */
    145 clear_bss:
    146 	/* clear BSS segments */
    147 	addi	r5, r0, __bss_start
    148 	addi	r4, r0, __bss_end
    149 	cmp	r6, r5, r4
    150 	beqi	r6, 3f
    151 2:
    152 	swi     r0, r5, 0 /* write zero to loc */
    153 	addi    r5, r5, 4 /* increment to next loc */
    154 	cmp     r6, r5, r4 /* check if we have reach the end */
    155 	bnei    r6, 2b
    156 3:	/* jumping to board_init */
    157 #ifdef CONFIG_DEBUG_UART
    158 	bralid	r15, debug_uart_init
    159 	nop
    160 #endif
    161 #ifndef CONFIG_SPL_BUILD
    162 	or	r5, r0, r0	/* flags - empty */
    163 	addi    r31, r0, _gd
    164 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
    165 	addi	r6, r0, CONFIG_SYS_INIT_SP_OFFSET
    166 	swi	r6, r31, GD_MALLOC_BASE
    167 #endif
    168 	brai	board_init_f
    169 #else
    170 	addi	r31, r0, _gd
    171 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
    172 	addi	r6, r0, CONFIG_SPL_STACK_ADDR
    173 	swi	r6, r31, GD_MALLOC_BASE
    174 #endif
    175 	brai	board_init_r
    176 #endif
    177 1:	bri	1b
    178 
    179  .section .bss
    180 .align 4
    181 _gd:
    182          .space  GENERATED_GBL_DATA_SIZE
    183 
    184 #ifndef CONFIG_SPL_BUILD
    185 /*
    186  * Read 16bit little endian
    187  */
    188 	.text
    189 	.global	in16
    190 	.ent	in16
    191 	.align	2
    192 in16:	lhu	r3, r0, r5
    193 	bslli	r4, r3, 8
    194 	bsrli	r3, r3, 8
    195 	andi	r4, r4, 0xffff
    196 	or	r3, r3, r4
    197 	rtsd	r15, 8
    198 	sext16	r3, r3
    199 	.end	in16
    200 
    201 /*
    202  * Write 16bit little endian
    203  * first parameter(r5) - address, second(r6) - short value
    204  */
    205 	.text
    206 	.global	out16
    207 	.ent	out16
    208 	.align	2
    209 out16:	bslli	r3, r6, 8
    210 	bsrli	r6, r6, 8
    211 	andi	r3, r3, 0xffff
    212 	or	r3, r3, r6
    213 	sh	r3, r0, r5
    214 	rtsd	r15, 8
    215 	or	r0, r0, r0
    216 	.end	out16
    217 
    218 /*
    219  * Relocate u-boot
    220  */
    221 	.text
    222 	.global	relocate_code
    223 	.ent	relocate_code
    224 	.align	2
    225 relocate_code:
    226 	/*
    227 	 * r5 - start_addr_sp
    228 	 * r6 - new_gd
    229 	 * r7 - reloc_addr
    230 	 */
    231 	addi	r1, r5, 0 /* Start to use new SP */
    232 	addi	r31, r6, 0 /* Start to use new GD */
    233 
    234 	add	r23, r0, r7 /* Move reloc addr to r23 */
    235 	/* Relocate text and data - r12 temp value */
    236 	addi	r21, r0, _start
    237 	addi	r22, r0, __end - 4 /* Include BSS too */
    238 
    239 	rsub	r6, r21, r22
    240 	or	r5, r0, r0
    241 1:	lw	r12, r21, r5 /* Load u-boot data */
    242 	sw	r12, r23, r5 /* Write zero to loc */
    243 	cmp	r12, r5, r6 /* Check if we have reach the end */
    244 	bneid	r12, 1b
    245 	addi	r5, r5, 4 /* Increment to next loc - relocate code */
    246 
    247        /* R23 points to the base address. */
    248 	add	r23, r0, r7 /* Move reloc addr to r23 */
    249 	addi	r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
    250 	rsub	r23, r24, r23 /* keep - this is already here gd->reloc_off */
    251 
    252 	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
    253 	lwi	r7, r0, 0x28
    254 	swi	r6, r0, 0x28 /* used first unused MB vector */
    255 	lbui	r10, r0, 0x28 /* used first unused MB vector */
    256 	swi	r7, r0, 0x28
    257 
    258 #ifdef CONFIG_SYS_USR_EXCEP
    259 	addik	r6, r0, _exception_handler
    260 	addk	r6, r6, r23 /* add offset */
    261 	sw	r6, r1, r0
    262 	lhu	r7, r1, r10
    263 	rsubi	r8, r10, 0xa
    264 	sh	r7, r0, r8
    265 	rsubi	r8, r10, 0xe
    266 	sh	r6, r0, r8
    267 #endif
    268 	addik	r6, r0, _hw_exception_handler
    269 	addk	r6, r6, r23 /* add offset */
    270 	sw	r6, r1, r0
    271 	lhu	r7, r1, r10
    272 	rsubi	r8, r10, 0x22
    273 	sh	r7, r0, r8
    274 	rsubi	r8, r10, 0x26
    275 	sh	r6, r0, r8
    276 
    277 	addik	r6, r0, _interrupt_handler
    278 	addk	r6, r6, r23 /* add offset */
    279 	sw	r6, r1, r0
    280 	lhu	r7, r1, r10
    281 	rsubi	r8, r10, 0x12
    282 	sh	r7, r0, r8
    283 	rsubi	r8, r10, 0x16
    284 	sh	r6, r0, r8
    285 
    286 	/* Check if GOT exist */
    287 	addik	r21, r23, _got_start
    288 	addik	r22, r23, _got_end
    289 	cmpu	r12, r21, r22
    290 	beqi	r12, 2f /* No GOT table - jump over */
    291 
    292 	/* Skip last 3 entries plus 1 because of loop boundary below */
    293 	addik	r22, r22, -0x10
    294 
    295         /* Relocate the GOT. */
    296 3:	lw	r12, r21, r0 /* Load entry */
    297 	addk	r12, r12, r23 /* Add reloc offset */
    298 	sw	r12, r21, r0 /* Save entry back */
    299 
    300 	cmpu	r12, r21, r22 /* Check if this cross boundary */
    301 	bneid	r12, 3b
    302 	addik	r21. r21, 4
    303 
    304 	/* Update pointer to GOT */
    305 	mfs	r20, rpc
    306 	addik	r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
    307 	addk	r20, r20, r23
    308 
    309 	/* Flush caches to ensure consistency */
    310 	addik	r5, r0, 0
    311 	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
    312 	bralid	r15, flush_cache
    313 	nop
    314 
    315 2:	addi	r5, r31, 0 /* gd is initialized in board_r.c */
    316 	addi	r6, r0, CONFIG_SYS_TEXT_BASE
    317 	addi	r12, r23, board_init_r
    318 	bra	r12 /* Jump to relocated code */
    319 
    320 	.end	relocate_code
    321 #endif
    322