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 /* 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_*() */ 145clear_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 1512: 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 1563: /* 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 1771: 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 192in16: 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 209out16: 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 225relocate_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 2411: 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. */ 2963: 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 3152: 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