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