1/* 2 * (C) Copyright 2007 Michal Simek 3 * (C) Copyright 2004 Atmark Techno, Inc. 4 * 5 * Michal SIMEK <monstr@monstr.eu> 6 * Yasushi SHOJI <yashi@atmark-techno.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11#include <asm-offsets.h> 12#include <config.h> 13 14 .text 15 .global _start 16_start: 17 /* 18 * reserve registers: 19 * r10: Stores little/big endian offset for vectors 20 * r2: Stores imm opcode 21 * r3: Stores brai opcode 22 */ 23 24 mts rmsr, r0 /* disable cache */ 25 26 addi r8, r0, __end 27 mts rslr, r8 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 defined(CONFIG_SYS_MALLOC_F_LEN) 34 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_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 /* BUILD_SPL */ 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 144clear_bss: 145 /* clear BSS segments */ 146 addi r5, r0, __bss_start 147 addi r4, r0, __bss_end 148 cmp r6, r5, r4 149 beqi r6, 3f 1502: 151 swi r0, r5, 0 /* write zero to loc */ 152 addi r5, r5, 4 /* increment to next loc */ 153 cmp r6, r5, r4 /* check if we have reach the end */ 154 bnei r6, 2b 1553: /* jumping to board_init */ 156#ifndef CONFIG_SPL_BUILD 157 or r5, r0, r0 /* flags - empty */ 158 addi r31, r0, _gd 159#if defined(CONFIG_SYS_MALLOC_F_LEN) 160 addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET 161 swi r6, r31, GD_MALLOC_BASE 162#endif 163 brai board_init_f 164#else 165 addi r31, r0, _gd 166#if defined(CONFIG_SYS_MALLOC_F_LEN) 167 addi r6, r0, CONFIG_SPL_STACK_ADDR 168 swi r6, r31, GD_MALLOC_BASE 169#endif 170 brai board_init_r 171#endif 1721: bri 1b 173 174 .section .bss 175.align 4 176_gd: 177 .space GENERATED_GBL_DATA_SIZE 178 179#ifndef CONFIG_SPL_BUILD 180/* 181 * Read 16bit little endian 182 */ 183 .text 184 .global in16 185 .ent in16 186 .align 2 187in16: lhu r3, r0, r5 188 bslli r4, r3, 8 189 bsrli r3, r3, 8 190 andi r4, r4, 0xffff 191 or r3, r3, r4 192 rtsd r15, 8 193 sext16 r3, r3 194 .end in16 195 196/* 197 * Write 16bit little endian 198 * first parameter(r5) - address, second(r6) - short value 199 */ 200 .text 201 .global out16 202 .ent out16 203 .align 2 204out16: bslli r3, r6, 8 205 bsrli r6, r6, 8 206 andi r3, r3, 0xffff 207 or r3, r3, r6 208 sh r3, r0, r5 209 rtsd r15, 8 210 or r0, r0, r0 211 .end out16 212 213/* 214 * Relocate u-boot 215 */ 216 .text 217 .global relocate_code 218 .ent relocate_code 219 .align 2 220relocate_code: 221 /* 222 * r5 - start_addr_sp 223 * r6 - new_gd 224 * r7 - reloc_addr 225 */ 226 addi r1, r5, 0 /* Start to use new SP */ 227 addi r31, r6, 0 /* Start to use new GD */ 228 229 add r23, r0, r7 /* Move reloc addr to r23 */ 230 /* Relocate text and data - r12 temp value */ 231 addi r21, r0, _start 232 addi r22, r0, __end - 4 /* Include BSS too */ 233 234 rsub r6, r21, r22 235 or r5, r0, r0 2361: lw r12, r21, r5 /* Load u-boot data */ 237 sw r12, r23, r5 /* Write zero to loc */ 238 cmp r12, r5, r6 /* Check if we have reach the end */ 239 bneid r12, 1b 240 addi r5, r5, 4 /* Increment to next loc - relocate code */ 241 242 /* R23 points to the base address. */ 243 add r23, r0, r7 /* Move reloc addr to r23 */ 244 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */ 245 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */ 246 247 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ 248 lwi r7, r0, 0x28 249 swi r6, r0, 0x28 /* used first unused MB vector */ 250 lbui r10, r0, 0x28 /* used first unused MB vector */ 251 swi r7, r0, 0x28 252 253#ifdef CONFIG_SYS_USR_EXCEP 254 addik r6, r0, _exception_handler 255 addk r6, r6, r23 /* add offset */ 256 sw r6, r1, r0 257 lhu r7, r1, r10 258 rsubi r8, r10, 0xa 259 sh r7, r0, r8 260 rsubi r8, r10, 0xe 261 sh r6, r0, r8 262#endif 263 addik r6, r0, _hw_exception_handler 264 addk r6, r6, r23 /* add offset */ 265 sw r6, r1, r0 266 lhu r7, r1, r10 267 rsubi r8, r10, 0x22 268 sh r7, r0, r8 269 rsubi r8, r10, 0x26 270 sh r6, r0, r8 271 272 addik r6, r0, _interrupt_handler 273 addk r6, r6, r23 /* add offset */ 274 sw r6, r1, r0 275 lhu r7, r1, r10 276 rsubi r8, r10, 0x12 277 sh r7, r0, r8 278 rsubi r8, r10, 0x16 279 sh r6, r0, r8 280 281 /* Check if GOT exist */ 282 addik r21, r23, _got_start 283 addik r22, r23, _got_end 284 cmpu r12, r21, r22 285 beqi r12, 2f /* No GOT table - jump over */ 286 287 /* Skip last 3 entries plus 1 because of loop boundary below */ 288 addik r22, r22, -0x10 289 290 /* Relocate the GOT. */ 2913: lw r12, r21, r0 /* Load entry */ 292 addk r12, r12, r23 /* Add reloc offset */ 293 sw r12, r21, r0 /* Save entry back */ 294 295 cmpu r12, r21, r22 /* Check if this cross boundary */ 296 bneid r12, 3b 297 addik r21. r21, 4 298 299 /* Update pointer to GOT */ 300 mfs r20, rpc 301 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8 302 addk r20, r20, r23 303 304 /* Flush caches to ensure consistency */ 305 addik r5, r0, 0 306 addik r6, r0, XILINX_DCACHE_BYTE_SIZE 307 bralid r15, flush_cache 308 nop 309 3102: addi r5, r31, 0 /* gd is initialized in board_r.c */ 311 addi r6, r0, CONFIG_SYS_TEXT_BASE 312 addi r12, r23, board_init_r 313 bra r12 /* Jump to relocated code */ 314 315 .end relocate_code 316#endif 317