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#if defined(CONFIG_SPL_BUILD) 27 addi r1, r0, CONFIG_SPL_STACK_ADDR 28 addi r1, r1, -4 /* Decrement SP to top of memory */ 29#else 30 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET 31 addi r1, r1, -4 /* Decrement SP to top of memory */ 32 33 /* Find-out if u-boot is running on BIG/LITTLE endian platform 34 * There are some steps which is necessary to keep in mind: 35 * 1. Setup offset value to r6 36 * 2. Store word offset value to address 0x0 37 * 3. Load just byte from address 0x0 38 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest 39 * value that's why is on address 0x0 40 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3 41 */ 42 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ 43 lwi r7, r0, 0x28 44 swi r6, r0, 0x28 /* used first unused MB vector */ 45 lbui r10, r0, 0x28 /* used first unused MB vector */ 46 swi r7, r0, 0x28 47 48 /* add opcode instruction for 32bit jump - 2 instruction imm & brai */ 49 addi r2, r0, 0xb0000000 /* hex b000 opcode imm */ 50 addi r3, r0, 0xb8080000 /* hew b808 opcode brai */ 51 52#ifdef CONFIG_SYS_RESET_ADDRESS 53 /* reset address */ 54 swi r2, r0, 0x0 /* reset address - imm opcode */ 55 swi r3, r0, 0x4 /* reset address - brai opcode */ 56 57 addik r6, r0, CONFIG_SYS_RESET_ADDRESS 58 sw r6, r1, r0 59 lhu r7, r1, r10 60 rsubi r8, r10, 0x2 61 sh r7, r0, r8 62 rsubi r8, r10, 0x6 63 sh r6, r0, r8 64#endif 65 66#ifdef CONFIG_SYS_USR_EXCEP 67 /* user_vector_exception */ 68 swi r2, r0, 0x8 /* user vector exception - imm opcode */ 69 swi r3, r0, 0xC /* user vector exception - brai opcode */ 70 71 addik r6, r0, _exception_handler 72 sw r6, r1, r0 73 /* 74 * BIG ENDIAN memory map for user exception 75 * 0x8: 0xB000XXXX 76 * 0xC: 0xB808XXXX 77 * 78 * then it is necessary to count address for storing the most significant 79 * 16bits from _exception_handler address and copy it to 80 * 0xa address. Big endian use offset in r10=0 that's why is it just 81 * 0xa address. The same is done for the least significant 16 bits 82 * for 0xe address. 83 * 84 * LITTLE ENDIAN memory map for user exception 85 * 0x8: 0xXXXX00B0 86 * 0xC: 0xXXXX08B8 87 * 88 * Offset is for little endian setup to 0x2. rsubi instruction decrease 89 * address value to ensure that points to proper place which is 90 * 0x8 for the most significant 16 bits and 91 * 0xC for the least significant 16 bits 92 */ 93 lhu r7, r1, r10 94 rsubi r8, r10, 0xa 95 sh r7, r0, r8 96 rsubi r8, r10, 0xe 97 sh r6, r0, r8 98#endif 99 100 /* interrupt_handler */ 101 swi r2, r0, 0x10 /* interrupt - imm opcode */ 102 swi r3, r0, 0x14 /* interrupt - brai opcode */ 103 104 addik r6, r0, _interrupt_handler 105 sw r6, r1, r0 106 lhu r7, r1, r10 107 rsubi r8, r10, 0x12 108 sh r7, r0, r8 109 rsubi r8, r10, 0x16 110 sh r6, r0, r8 111 112 /* hardware exception */ 113 swi r2, r0, 0x20 /* hardware exception - imm opcode */ 114 swi r3, r0, 0x24 /* hardware exception - brai opcode */ 115 116 addik r6, r0, _hw_exception_handler 117 sw r6, r1, r0 118 lhu r7, r1, r10 119 rsubi r8, r10, 0x22 120 sh r7, r0, r8 121 rsubi r8, r10, 0x26 122 sh r6, r0, r8 123#endif /* BUILD_SPL */ 124 125 /* Flush cache before enable cache */ 126 addik r5, r0, 0 127 addik r6, r0, XILINX_DCACHE_BYTE_SIZE 128flush: bralid r15, flush_cache 129 nop 130 131 /* enable instruction and data cache */ 132 mfs r12, rmsr 133 ori r12, r12, 0xa0 134 mts rmsr, r12 135 136clear_bss: 137 /* clear BSS segments */ 138 addi r5, r0, __bss_start 139 addi r4, r0, __bss_end 140 cmp r6, r5, r4 141 beqi r6, 3f 1422: 143 swi r0, r5, 0 /* write zero to loc */ 144 addi r5, r5, 4 /* increment to next loc */ 145 cmp r6, r5, r4 /* check if we have reach the end */ 146 bnei r6, 2b 1473: /* jumping to board_init */ 148#ifndef CONFIG_SPL_BUILD 149 brai board_init_f 150#else 151 brai board_init_r 152#endif 1531: bri 1b 154 155#ifndef CONFIG_SPL_BUILD 156/* 157 * Read 16bit little endian 158 */ 159 .text 160 .global in16 161 .ent in16 162 .align 2 163in16: lhu r3, r0, r5 164 bslli r4, r3, 8 165 bsrli r3, r3, 8 166 andi r4, r4, 0xffff 167 or r3, r3, r4 168 rtsd r15, 8 169 sext16 r3, r3 170 .end in16 171 172/* 173 * Write 16bit little endian 174 * first parameter(r5) - address, second(r6) - short value 175 */ 176 .text 177 .global out16 178 .ent out16 179 .align 2 180out16: bslli r3, r6, 8 181 bsrli r6, r6, 8 182 andi r3, r3, 0xffff 183 or r3, r3, r6 184 sh r3, r0, r5 185 rtsd r15, 8 186 or r0, r0, r0 187 .end out16 188#endif 189