16260fb04SPeter Tyser/* 26260fb04SPeter Tyser * (C) Copyright 2007 Michal Simek 36260fb04SPeter Tyser * (C) Copyright 2004 Atmark Techno, Inc. 46260fb04SPeter Tyser * 56260fb04SPeter Tyser * Michal SIMEK <monstr@monstr.eu> 66260fb04SPeter Tyser * Yasushi SHOJI <yashi@atmark-techno.com> 76260fb04SPeter Tyser * 86260fb04SPeter Tyser * See file CREDITS for list of people who contributed to this 96260fb04SPeter Tyser * project. 106260fb04SPeter Tyser * 116260fb04SPeter Tyser * This program is free software; you can redistribute it and/or 126260fb04SPeter Tyser * modify it under the terms of the GNU General Public License as 136260fb04SPeter Tyser * published by the Free Software Foundation; either version 2 of 146260fb04SPeter Tyser * the License, or (at your option) any later version. 156260fb04SPeter Tyser * 166260fb04SPeter Tyser * This program is distributed in the hope that it will be useful, 176260fb04SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 186260fb04SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 196260fb04SPeter Tyser * GNU General Public License for more details. 206260fb04SPeter Tyser * 216260fb04SPeter Tyser * You should have received a copy of the GNU General Public License 226260fb04SPeter Tyser * along with this program; if not, write to the Free Software 236260fb04SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 246260fb04SPeter Tyser * MA 02111-1307 USA 256260fb04SPeter Tyser */ 266260fb04SPeter Tyser 2725ddd1fbSWolfgang Denk#include <asm-offsets.h> 286260fb04SPeter Tyser#include <config.h> 296260fb04SPeter Tyser 306260fb04SPeter Tyser .text 316260fb04SPeter Tyser .global _start 326260fb04SPeter Tyser_start: 33*86c1b2a8SMichal Simek /* 34*86c1b2a8SMichal Simek * reserve registers: 35*86c1b2a8SMichal Simek * r10: Stores little/big endian offset for vectors 36*86c1b2a8SMichal Simek * r2: Stores imm opcode 37*86c1b2a8SMichal Simek * r3: Stores brai opcode 38*86c1b2a8SMichal Simek */ 39*86c1b2a8SMichal Simek 406260fb04SPeter Tyser mts rmsr, r0 /* disable cache */ 416260fb04SPeter Tyser addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET 426260fb04SPeter Tyser addi r1, r1, -4 /* Decrement SP to top of memory */ 43b98cba09SMichal Simek 44b98cba09SMichal Simek /* Find-out if u-boot is running on BIG/LITTLE endian platform 45b98cba09SMichal Simek * There are some steps which is necessary to keep in mind: 46b98cba09SMichal Simek * 1. Setup offset value to r6 47b98cba09SMichal Simek * 2. Store word offset value to address 0x0 48b98cba09SMichal Simek * 3. Load just byte from address 0x0 49b98cba09SMichal Simek * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest 50b98cba09SMichal Simek * value that's why is on address 0x0 51b98cba09SMichal Simek * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3 52b98cba09SMichal Simek */ 53b98cba09SMichal Simek addik r6, r0, 0x2 /* BIG/LITTLE endian offset */ 54b98cba09SMichal Simek swi r6, r0, 0 55b98cba09SMichal Simek lbui r10, r0, 0 56b98cba09SMichal Simek 576260fb04SPeter Tyser /* add opcode instruction for 32bit jump - 2 instruction imm & brai */ 58*86c1b2a8SMichal Simek addi r2, r0, 0xb0000000 /* hex b000 opcode imm */ 59*86c1b2a8SMichal Simek addi r3, r0, 0xb8080000 /* hew b808 opcode brai */ 606260fb04SPeter Tyser 616260fb04SPeter Tyser#ifdef CONFIG_SYS_RESET_ADDRESS 626260fb04SPeter Tyser /* reset address */ 63*86c1b2a8SMichal Simek swi r2, r0, 0x0 /* reset address - imm opcode */ 64*86c1b2a8SMichal Simek swi r3, r0, 0x4 /* reset address - brai opcode */ 65*86c1b2a8SMichal Simek 666260fb04SPeter Tyser addik r6, r0, CONFIG_SYS_RESET_ADDRESS 676260fb04SPeter Tyser sw r6, r1, r0 686260fb04SPeter Tyser lhu r7, r1, r0 696260fb04SPeter Tyser shi r7, r0, 0x2 706260fb04SPeter Tyser shi r6, r0, 0x6 716260fb04SPeter Tyser/* 7214d0a02aSWolfgang Denk * Copy U-Boot code to CONFIG_SYS_TEXT_BASE 736260fb04SPeter Tyser * solve problem with sbrk_base 746260fb04SPeter Tyser */ 7514d0a02aSWolfgang Denk#if (CONFIG_SYS_RESET_ADDRESS != CONFIG_SYS_TEXT_BASE) 766260fb04SPeter Tyser addi r4, r0, __end 776260fb04SPeter Tyser addi r5, r0, __text_start 786260fb04SPeter Tyser rsub r4, r5, r4 /* size = __end - __text_start */ 796260fb04SPeter Tyser addi r6, r0, CONFIG_SYS_RESET_ADDRESS /* source address */ 806260fb04SPeter Tyser addi r7, r0, 0 /* counter */ 816260fb04SPeter Tyser4: 826260fb04SPeter Tyser lw r8, r6, r7 836260fb04SPeter Tyser sw r8, r5, r7 846260fb04SPeter Tyser addi r7, r7, 0x4 856260fb04SPeter Tyser cmp r8, r4, r7 866260fb04SPeter Tyser blti r8, 4b 876260fb04SPeter Tyser#endif 886260fb04SPeter Tyser#endif 896260fb04SPeter Tyser 906260fb04SPeter Tyser#ifdef CONFIG_SYS_USR_EXCEP 916260fb04SPeter Tyser /* user_vector_exception */ 92*86c1b2a8SMichal Simek swi r2, r0, 0x8 /* user vector exception - imm opcode */ 93*86c1b2a8SMichal Simek swi r3, r0, 0xC /* user vector exception - brai opcode */ 94*86c1b2a8SMichal Simek 956260fb04SPeter Tyser addik r6, r0, _exception_handler 966260fb04SPeter Tyser sw r6, r1, r0 97b98cba09SMichal Simek /* 98b98cba09SMichal Simek * BIG ENDIAN memory map for user exception 99b98cba09SMichal Simek * 0x8: 0xB000XXXX 100b98cba09SMichal Simek * 0xC: 0xB808XXXX 101b98cba09SMichal Simek * 102b98cba09SMichal Simek * then it is necessary to count address for storing the most significant 103b98cba09SMichal Simek * 16bits from _exception_handler address and copy it to 104b98cba09SMichal Simek * 0xa address. Big endian use offset in r10=0 that's why is it just 105b98cba09SMichal Simek * 0xa address. The same is done for the least significant 16 bits 106b98cba09SMichal Simek * for 0xe address. 107b98cba09SMichal Simek * 108b98cba09SMichal Simek * LITTLE ENDIAN memory map for user exception 109b98cba09SMichal Simek * 0x8: 0xXXXX00B0 110b98cba09SMichal Simek * 0xC: 0xXXXX08B8 111b98cba09SMichal Simek * 112b98cba09SMichal Simek * Offset is for little endian setup to 0x2. rsubi instruction decrease 113b98cba09SMichal Simek * address value to ensure that points to proper place which is 114b98cba09SMichal Simek * 0x8 for the most significant 16 bits and 115b98cba09SMichal Simek * 0xC for the least significant 16 bits 116b98cba09SMichal Simek */ 117b98cba09SMichal Simek lhu r7, r1, r10 118b98cba09SMichal Simek rsubi r8, r10, 0xa 119b98cba09SMichal Simek sh r7, r0, r8 120b98cba09SMichal Simek rsubi r8, r10, 0xe 121b98cba09SMichal Simek sh r6, r0, r8 1226260fb04SPeter Tyser#endif 1236260fb04SPeter Tyser 1246260fb04SPeter Tyser#ifdef CONFIG_SYS_INTC_0 1256260fb04SPeter Tyser /* interrupt_handler */ 126*86c1b2a8SMichal Simek swi r2, r0, 0x10 /* interrupt - imm opcode */ 127*86c1b2a8SMichal Simek swi r3, r0, 0x14 /* interrupt - brai opcode */ 128*86c1b2a8SMichal Simek 1296260fb04SPeter Tyser addik r6, r0, _interrupt_handler 1306260fb04SPeter Tyser sw r6, r1, r0 131b98cba09SMichal Simek lhu r7, r1, r10 132b98cba09SMichal Simek rsubi r8, r10, 0x12 133b98cba09SMichal Simek sh r7, r0, r8 134b98cba09SMichal Simek rsubi r8, r10, 0x16 135b98cba09SMichal Simek sh r6, r0, r8 1366260fb04SPeter Tyser#endif 1376260fb04SPeter Tyser 1386260fb04SPeter Tyser /* hardware exception */ 139*86c1b2a8SMichal Simek swi r2, r0, 0x20 /* hardware exception - imm opcode */ 140*86c1b2a8SMichal Simek swi r3, r0, 0x24 /* hardware exception - brai opcode */ 141*86c1b2a8SMichal Simek 1426260fb04SPeter Tyser addik r6, r0, _hw_exception_handler 1436260fb04SPeter Tyser sw r6, r1, r0 144b98cba09SMichal Simek lhu r7, r1, r10 145b98cba09SMichal Simek rsubi r8, r10, 0x22 146b98cba09SMichal Simek sh r7, r0, r8 147b98cba09SMichal Simek rsubi r8, r10, 0x26 148b98cba09SMichal Simek sh r6, r0, r8 1496260fb04SPeter Tyser 1506260fb04SPeter Tyser /* enable instruction and data cache */ 1516260fb04SPeter Tyser mfs r12, rmsr 1526260fb04SPeter Tyser ori r12, r12, 0xa0 1536260fb04SPeter Tyser mts rmsr, r12 1546260fb04SPeter Tyser 1556260fb04SPeter Tyserclear_bss: 1566260fb04SPeter Tyser /* clear BSS segments */ 1576260fb04SPeter Tyser addi r5, r0, __bss_start 1586260fb04SPeter Tyser addi r4, r0, __bss_end 1596260fb04SPeter Tyser cmp r6, r5, r4 1606260fb04SPeter Tyser beqi r6, 3f 1616260fb04SPeter Tyser2: 1626260fb04SPeter Tyser swi r0, r5, 0 /* write zero to loc */ 1636260fb04SPeter Tyser addi r5, r5, 4 /* increment to next loc */ 1646260fb04SPeter Tyser cmp r6, r5, r4 /* check if we have reach the end */ 1656260fb04SPeter Tyser bnei r6, 2b 1666260fb04SPeter Tyser3: /* jumping to board_init */ 1676260fb04SPeter Tyser brai board_init 1686260fb04SPeter Tyser1: bri 1b 1696260fb04SPeter Tyser 1706260fb04SPeter Tyser/* 1716260fb04SPeter Tyser * Read 16bit little endian 1726260fb04SPeter Tyser */ 1736260fb04SPeter Tyser .text 1746260fb04SPeter Tyser .global in16 1756260fb04SPeter Tyser .ent in16 1766260fb04SPeter Tyser .align 2 1776260fb04SPeter Tyserin16: lhu r3, r0, r5 1786260fb04SPeter Tyser bslli r4, r3, 8 1796260fb04SPeter Tyser bsrli r3, r3, 8 1806260fb04SPeter Tyser andi r4, r4, 0xffff 1816260fb04SPeter Tyser or r3, r3, r4 1826260fb04SPeter Tyser rtsd r15, 8 1836260fb04SPeter Tyser sext16 r3, r3 1846260fb04SPeter Tyser .end in16 1856260fb04SPeter Tyser 1866260fb04SPeter Tyser/* 1876260fb04SPeter Tyser * Write 16bit little endian 1886260fb04SPeter Tyser * first parameter(r5) - address, second(r6) - short value 1896260fb04SPeter Tyser */ 1906260fb04SPeter Tyser .text 1916260fb04SPeter Tyser .global out16 1926260fb04SPeter Tyser .ent out16 1936260fb04SPeter Tyser .align 2 1946260fb04SPeter Tyserout16: bslli r3, r6, 8 1956260fb04SPeter Tyser bsrli r6, r6, 8 1966260fb04SPeter Tyser andi r3, r3, 0xffff 1976260fb04SPeter Tyser or r3, r3, r6 1986260fb04SPeter Tyser sh r3, r0, r5 1996260fb04SPeter Tyser rtsd r15, 8 2006260fb04SPeter Tyser or r0, r0, r0 2016260fb04SPeter Tyser .end out16 202