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 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 27#include <asm-offsets.h> 28#include <config.h> 29 30 .text 31 .global _start 32_start: 33 /* 34 * reserve registers: 35 * r10: Stores little/big endian offset for vectors 36 * r2: Stores imm opcode 37 * r3: Stores brai opcode 38 */ 39 40 mts rmsr, r0 /* disable cache */ 41 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET 42 addi r1, r1, -4 /* Decrement SP to top of memory */ 43 44 /* Find-out if u-boot is running on BIG/LITTLE endian platform 45 * There are some steps which is necessary to keep in mind: 46 * 1. Setup offset value to r6 47 * 2. Store word offset value to address 0x0 48 * 3. Load just byte from address 0x0 49 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest 50 * value that's why is on address 0x0 51 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3 52 */ 53 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ 54 lwi r7, r0, 0x28 55 swi r6, r0, 0x28 /* used first unused MB vector */ 56 lbui r10, r0, 0x28 /* used first unused MB vector */ 57 swi r7, r0, 0x28 58 59 /* add opcode instruction for 32bit jump - 2 instruction imm & brai */ 60 addi r2, r0, 0xb0000000 /* hex b000 opcode imm */ 61 addi r3, r0, 0xb8080000 /* hew b808 opcode brai */ 62 63#ifdef CONFIG_SYS_RESET_ADDRESS 64 /* reset address */ 65 swi r2, r0, 0x0 /* reset address - imm opcode */ 66 swi r3, r0, 0x4 /* reset address - brai opcode */ 67 68 addik r6, r0, CONFIG_SYS_RESET_ADDRESS 69 sw r6, r1, r0 70 lhu r7, r1, r0 71 shi r7, r0, 0x2 72 shi r6, r0, 0x6 73/* 74 * Copy U-Boot code to CONFIG_SYS_TEXT_BASE 75 * solve problem with sbrk_base 76 */ 77#if (CONFIG_SYS_RESET_ADDRESS != CONFIG_SYS_TEXT_BASE) 78 addi r4, r0, __end 79 addi r5, r0, __text_start 80 rsub r4, r5, r4 /* size = __end - __text_start */ 81 addi r6, r0, CONFIG_SYS_RESET_ADDRESS /* source address */ 82 addi r7, r0, 0 /* counter */ 834: 84 lw r8, r6, r7 85 sw r8, r5, r7 86 addi r7, r7, 0x4 87 cmp r8, r4, r7 88 blti r8, 4b 89#endif 90#endif 91 92#ifdef CONFIG_SYS_USR_EXCEP 93 /* user_vector_exception */ 94 swi r2, r0, 0x8 /* user vector exception - imm opcode */ 95 swi r3, r0, 0xC /* user vector exception - brai opcode */ 96 97 addik r6, r0, _exception_handler 98 sw r6, r1, r0 99 /* 100 * BIG ENDIAN memory map for user exception 101 * 0x8: 0xB000XXXX 102 * 0xC: 0xB808XXXX 103 * 104 * then it is necessary to count address for storing the most significant 105 * 16bits from _exception_handler address and copy it to 106 * 0xa address. Big endian use offset in r10=0 that's why is it just 107 * 0xa address. The same is done for the least significant 16 bits 108 * for 0xe address. 109 * 110 * LITTLE ENDIAN memory map for user exception 111 * 0x8: 0xXXXX00B0 112 * 0xC: 0xXXXX08B8 113 * 114 * Offset is for little endian setup to 0x2. rsubi instruction decrease 115 * address value to ensure that points to proper place which is 116 * 0x8 for the most significant 16 bits and 117 * 0xC for the least significant 16 bits 118 */ 119 lhu r7, r1, r10 120 rsubi r8, r10, 0xa 121 sh r7, r0, r8 122 rsubi r8, r10, 0xe 123 sh r6, r0, r8 124#endif 125 126#ifdef CONFIG_SYS_INTC_0 127 /* interrupt_handler */ 128 swi r2, r0, 0x10 /* interrupt - imm opcode */ 129 swi r3, r0, 0x14 /* interrupt - brai opcode */ 130 131 addik r6, r0, _interrupt_handler 132 sw r6, r1, r0 133 lhu r7, r1, r10 134 rsubi r8, r10, 0x12 135 sh r7, r0, r8 136 rsubi r8, r10, 0x16 137 sh r6, r0, r8 138#endif 139 140 /* hardware exception */ 141 swi r2, r0, 0x20 /* hardware exception - imm opcode */ 142 swi r3, r0, 0x24 /* hardware exception - brai opcode */ 143 144 addik r6, r0, _hw_exception_handler 145 sw r6, r1, r0 146 lhu r7, r1, r10 147 rsubi r8, r10, 0x22 148 sh r7, r0, r8 149 rsubi r8, r10, 0x26 150 sh r6, r0, r8 151 152 /* enable instruction and data cache */ 153 mfs r12, rmsr 154 ori r12, r12, 0xa0 155 mts rmsr, r12 156 157clear_bss: 158 /* clear BSS segments */ 159 addi r5, r0, __bss_start 160 addi r4, r0, __bss_end 161 cmp r6, r5, r4 162 beqi r6, 3f 1632: 164 swi r0, r5, 0 /* write zero to loc */ 165 addi r5, r5, 4 /* increment to next loc */ 166 cmp r6, r5, r4 /* check if we have reach the end */ 167 bnei r6, 2b 1683: /* jumping to board_init */ 169 brai board_init 1701: bri 1b 171 172/* 173 * Read 16bit little endian 174 */ 175 .text 176 .global in16 177 .ent in16 178 .align 2 179in16: lhu r3, r0, r5 180 bslli r4, r3, 8 181 bsrli r3, r3, 8 182 andi r4, r4, 0xffff 183 or r3, r3, r4 184 rtsd r15, 8 185 sext16 r3, r3 186 .end in16 187 188/* 189 * Write 16bit little endian 190 * first parameter(r5) - address, second(r6) - short value 191 */ 192 .text 193 .global out16 194 .ent out16 195 .align 2 196out16: bslli r3, r6, 8 197 bsrli r6, r6, 8 198 andi r3, r3, 0xffff 199 or r3, r3, r6 200 sh r3, r0, r5 201 rtsd r15, 8 202 or r0, r0, r0 203 .end out16 204