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