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 mts rmsr, r0 /* disable cache */ 34 addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET 35 addi r1, r1, -4 /* Decrement SP to top of memory */ 36 37 /* Find-out if u-boot is running on BIG/LITTLE endian platform 38 * There are some steps which is necessary to keep in mind: 39 * 1. Setup offset value to r6 40 * 2. Store word offset value to address 0x0 41 * 3. Load just byte from address 0x0 42 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest 43 * value that's why is on address 0x0 44 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3 45 */ 46 addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ 47 swi r6, r0, 0 48 lbui r10, r0, 0 49 50 /* add opcode instruction for 32bit jump - 2 instruction imm & brai*/ 51 addi r6, r0, 0xb0000000 /* hex b000 opcode imm */ 52 swi r6, r0, 0x0 /* reset address */ 53 swi r6, r0, 0x8 /* user vector exception */ 54 swi r6, r0, 0x10 /* interrupt */ 55 swi r6, r0, 0x20 /* hardware exception */ 56 57 addi r6, r0, 0xb8080000 /* hew b808 opcode brai*/ 58 swi r6, r0, 0x4 /* reset address */ 59 swi r6, r0, 0xC /* user vector exception */ 60 swi r6, r0, 0x14 /* interrupt */ 61 swi r6, r0, 0x24 /* hardware exception */ 62 63#ifdef CONFIG_SYS_RESET_ADDRESS 64 /* reset address */ 65 addik r6, r0, CONFIG_SYS_RESET_ADDRESS 66 sw r6, r1, r0 67 lhu r7, r1, r0 68 shi r7, r0, 0x2 69 shi r6, r0, 0x6 70/* 71 * Copy U-Boot code to CONFIG_SYS_TEXT_BASE 72 * solve problem with sbrk_base 73 */ 74#if (CONFIG_SYS_RESET_ADDRESS != CONFIG_SYS_TEXT_BASE) 75 addi r4, r0, __end 76 addi r5, r0, __text_start 77 rsub r4, r5, r4 /* size = __end - __text_start */ 78 addi r6, r0, CONFIG_SYS_RESET_ADDRESS /* source address */ 79 addi r7, r0, 0 /* counter */ 804: 81 lw r8, r6, r7 82 sw r8, r5, r7 83 addi r7, r7, 0x4 84 cmp r8, r4, r7 85 blti r8, 4b 86#endif 87#endif 88 89#ifdef CONFIG_SYS_USR_EXCEP 90 /* user_vector_exception */ 91 addik r6, r0, _exception_handler 92 sw r6, r1, r0 93 /* 94 * BIG ENDIAN memory map for user exception 95 * 0x8: 0xB000XXXX 96 * 0xC: 0xB808XXXX 97 * 98 * then it is necessary to count address for storing the most significant 99 * 16bits from _exception_handler address and copy it to 100 * 0xa address. Big endian use offset in r10=0 that's why is it just 101 * 0xa address. The same is done for the least significant 16 bits 102 * for 0xe address. 103 * 104 * LITTLE ENDIAN memory map for user exception 105 * 0x8: 0xXXXX00B0 106 * 0xC: 0xXXXX08B8 107 * 108 * Offset is for little endian setup to 0x2. rsubi instruction decrease 109 * address value to ensure that points to proper place which is 110 * 0x8 for the most significant 16 bits and 111 * 0xC for the least significant 16 bits 112 */ 113 lhu r7, r1, r10 114 rsubi r8, r10, 0xa 115 sh r7, r0, r8 116 rsubi r8, r10, 0xe 117 sh r6, r0, r8 118#endif 119 120#ifdef CONFIG_SYS_INTC_0 121 /* interrupt_handler */ 122 addik r6, r0, _interrupt_handler 123 sw r6, r1, r0 124 lhu r7, r1, r10 125 rsubi r8, r10, 0x12 126 sh r7, r0, r8 127 rsubi r8, r10, 0x16 128 sh r6, r0, r8 129#endif 130 131 /* hardware exception */ 132 addik r6, r0, _hw_exception_handler 133 sw r6, r1, r0 134 lhu r7, r1, r10 135 rsubi r8, r10, 0x22 136 sh r7, r0, r8 137 rsubi r8, r10, 0x26 138 sh r6, r0, r8 139 140 /* enable instruction and data cache */ 141 mfs r12, rmsr 142 ori r12, r12, 0xa0 143 mts rmsr, r12 144 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 brai board_init 1581: bri 1b 159 160/* 161 * Read 16bit little endian 162 */ 163 .text 164 .global in16 165 .ent in16 166 .align 2 167in16: lhu r3, r0, r5 168 bslli r4, r3, 8 169 bsrli r3, r3, 8 170 andi r4, r4, 0xffff 171 or r3, r3, r4 172 rtsd r15, 8 173 sext16 r3, r3 174 .end in16 175 176/* 177 * Write 16bit little endian 178 * first parameter(r5) - address, second(r6) - short value 179 */ 180 .text 181 .global out16 182 .ent out16 183 .align 2 184out16: bslli r3, r6, 8 185 bsrli r6, r6, 8 186 andi r3, r3, 0xffff 187 or r3, r3, r6 188 sh r3, r0, r5 189 rtsd r15, 8 190 or r0, r0, r0 191 .end out16 192