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, CONFIG_SYS_SPL_MALLOC_END 166 brai board_init_r 167#endif 1681: bri 1b 169 170 .section .bss 171.align 4 172_gd: 173 .space GENERATED_GBL_DATA_SIZE 174 175#ifndef CONFIG_SPL_BUILD 176/* 177 * Read 16bit little endian 178 */ 179 .text 180 .global in16 181 .ent in16 182 .align 2 183in16: lhu r3, r0, r5 184 bslli r4, r3, 8 185 bsrli r3, r3, 8 186 andi r4, r4, 0xffff 187 or r3, r3, r4 188 rtsd r15, 8 189 sext16 r3, r3 190 .end in16 191 192/* 193 * Write 16bit little endian 194 * first parameter(r5) - address, second(r6) - short value 195 */ 196 .text 197 .global out16 198 .ent out16 199 .align 2 200out16: bslli r3, r6, 8 201 bsrli r6, r6, 8 202 andi r3, r3, 0xffff 203 or r3, r3, r6 204 sh r3, r0, r5 205 rtsd r15, 8 206 or r0, r0, r0 207 .end out16 208 209/* 210 * Relocate u-boot 211 */ 212 .text 213 .global relocate_code 214 .ent relocate_code 215 .align 2 216relocate_code: 217 /* 218 * r5 - start_addr_sp 219 * r6 - new_gd 220 * r7 - reloc_addr 221 */ 222 addi r1, r5, 0 /* Start to use new SP */ 223 addi r31, r6, 0 /* Start to use new GD */ 224 225 add r23, r0, r7 /* Move reloc addr to r23 */ 226 /* Relocate text and data - r12 temp value */ 227 addi r21, r0, _start 228 addi r22, r0, __end - 4 /* Include BSS too */ 229 230 rsub r6, r21, r22 231 or r5, r0, r0 2321: lw r12, r21, r5 /* Load u-boot data */ 233 sw r12, r23, r5 /* Write zero to loc */ 234 cmp r12, r5, r6 /* Check if we have reach the end */ 235 bneid r12, 1b 236 addi r5, r5, 4 /* Increment to next loc - relocate code */ 237 238 /* R23 points to the base address. */ 239 add r23, r0, r7 /* Move reloc addr to r23 */ 240 addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */ 241 rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */ 242 243 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ 244 lwi r7, r0, 0x28 245 swi r6, r0, 0x28 /* used first unused MB vector */ 246 lbui r10, r0, 0x28 /* used first unused MB vector */ 247 swi r7, r0, 0x28 248 249#ifdef CONFIG_SYS_USR_EXCEP 250 addik r6, r0, _exception_handler 251 addk r6, r6, r23 /* add offset */ 252 sw r6, r1, r0 253 lhu r7, r1, r10 254 rsubi r8, r10, 0xa 255 sh r7, r0, r8 256 rsubi r8, r10, 0xe 257 sh r6, r0, r8 258#endif 259 addik r6, r0, _hw_exception_handler 260 addk r6, r6, r23 /* add offset */ 261 sw r6, r1, r0 262 lhu r7, r1, r10 263 rsubi r8, r10, 0x22 264 sh r7, r0, r8 265 rsubi r8, r10, 0x26 266 sh r6, r0, r8 267 268 addik r6, r0, _interrupt_handler 269 addk r6, r6, r23 /* add offset */ 270 sw r6, r1, r0 271 lhu r7, r1, r10 272 rsubi r8, r10, 0x12 273 sh r7, r0, r8 274 rsubi r8, r10, 0x16 275 sh r6, r0, r8 276 277 /* Check if GOT exist */ 278 addik r21, r23, _got_start 279 addik r22, r23, _got_end 280 cmpu r12, r21, r22 281 beqi r12, 2f /* No GOT table - jump over */ 282 283 /* Skip last 3 entries plus 1 because of loop boundary below */ 284 addik r22, r22, -0x10 285 286 /* Relocate the GOT. */ 2873: lw r12, r21, r0 /* Load entry */ 288 addk r12, r12, r23 /* Add reloc offset */ 289 sw r12, r21, r0 /* Save entry back */ 290 291 cmpu r12, r21, r22 /* Check if this cross boundary */ 292 bneid r12, 3b 293 addik r21. r21, 4 294 295 /* Update pointer to GOT */ 296 mfs r20, rpc 297 addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8 298 addk r20, r20, r23 299 300 /* Flush caches to ensure consistency */ 301 addik r5, r0, 0 302 addik r6, r0, XILINX_DCACHE_BYTE_SIZE 303 bralid r15, flush_cache 304 nop 305 3062: addi r5, r31, 0 /* gd is initialized in board_r.c */ 307 addi r6, r0, CONFIG_SYS_TEXT_BASE 308 addi r12, r23, board_init_r 309 bra r12 /* Jump to relocated code */ 310 311 .end relocate_code 312#endif 313