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