xref: /openbmc/u-boot/arch/microblaze/cpu/start.S (revision f3090fce77202a867ae23d0df91a2b54ed9ee6e4)
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:
3386c1b2a8SMichal Simek	/*
3486c1b2a8SMichal Simek	 * reserve registers:
3586c1b2a8SMichal Simek	 * r10: Stores little/big endian offset for vectors
3686c1b2a8SMichal Simek	 * r2: Stores imm opcode
3786c1b2a8SMichal Simek	 * r3: Stores brai opcode
3886c1b2a8SMichal Simek	 */
3986c1b2a8SMichal 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 */
54*f3090fceSMichal Simek	lwi	r7, r0, 0x28
55*f3090fceSMichal Simek	swi	r6, r0, 0x28 /* used first unused MB vector */
56*f3090fceSMichal Simek	lbui	r10, r0, 0x28 /* used first unused MB vector */
57*f3090fceSMichal Simek	swi	r7, r0, 0x28
58b98cba09SMichal Simek
596260fb04SPeter Tyser	/* add opcode instruction for 32bit jump - 2 instruction imm & brai */
6086c1b2a8SMichal Simek	addi	r2, r0, 0xb0000000	/* hex b000 opcode imm */
6186c1b2a8SMichal Simek	addi	r3, r0, 0xb8080000	/* hew b808 opcode brai */
626260fb04SPeter Tyser
636260fb04SPeter Tyser#ifdef CONFIG_SYS_RESET_ADDRESS
646260fb04SPeter Tyser	/* reset address */
6586c1b2a8SMichal Simek	swi	r2, r0, 0x0	/* reset address - imm opcode */
6686c1b2a8SMichal Simek	swi	r3, r0, 0x4	/* reset address - brai opcode */
6786c1b2a8SMichal Simek
686260fb04SPeter Tyser	addik	r6, r0, CONFIG_SYS_RESET_ADDRESS
696260fb04SPeter Tyser	sw	r6, r1, r0
706260fb04SPeter Tyser	lhu	r7, r1, r0
716260fb04SPeter Tyser	shi	r7, r0, 0x2
726260fb04SPeter Tyser	shi	r6, r0, 0x6
736260fb04SPeter Tyser/*
7414d0a02aSWolfgang Denk * Copy U-Boot code to CONFIG_SYS_TEXT_BASE
756260fb04SPeter Tyser * solve problem with sbrk_base
766260fb04SPeter Tyser */
7714d0a02aSWolfgang Denk#if (CONFIG_SYS_RESET_ADDRESS != CONFIG_SYS_TEXT_BASE)
786260fb04SPeter Tyser	addi	r4, r0, __end
796260fb04SPeter Tyser	addi	r5, r0, __text_start
806260fb04SPeter Tyser	rsub	r4, r5, r4	/* size = __end - __text_start */
816260fb04SPeter Tyser	addi	r6, r0, CONFIG_SYS_RESET_ADDRESS	/* source address */
826260fb04SPeter Tyser	addi	r7, r0, 0	/* counter */
836260fb04SPeter Tyser4:
846260fb04SPeter Tyser	lw	r8, r6, r7
856260fb04SPeter Tyser	sw	r8, r5, r7
866260fb04SPeter Tyser	addi	r7, r7, 0x4
876260fb04SPeter Tyser	cmp	r8, r4, r7
886260fb04SPeter Tyser	blti	r8, 4b
896260fb04SPeter Tyser#endif
906260fb04SPeter Tyser#endif
916260fb04SPeter Tyser
926260fb04SPeter Tyser#ifdef CONFIG_SYS_USR_EXCEP
936260fb04SPeter Tyser	/* user_vector_exception */
9486c1b2a8SMichal Simek	swi	r2, r0, 0x8	/* user vector exception - imm opcode */
9586c1b2a8SMichal Simek	swi	r3, r0, 0xC	/* user vector exception - brai opcode */
9686c1b2a8SMichal Simek
976260fb04SPeter Tyser	addik	r6, r0, _exception_handler
986260fb04SPeter Tyser	sw	r6, r1, r0
99b98cba09SMichal Simek	/*
100b98cba09SMichal Simek	 * BIG ENDIAN memory map for user exception
101b98cba09SMichal Simek	 * 0x8: 0xB000XXXX
102b98cba09SMichal Simek	 * 0xC: 0xB808XXXX
103b98cba09SMichal Simek	 *
104b98cba09SMichal Simek	 * then it is necessary to count address for storing the most significant
105b98cba09SMichal Simek	 * 16bits from _exception_handler address and copy it to
106b98cba09SMichal Simek	 * 0xa address. Big endian use offset in r10=0 that's why is it just
107b98cba09SMichal Simek	 * 0xa address. The same is done for the least significant 16 bits
108b98cba09SMichal Simek	 * for 0xe address.
109b98cba09SMichal Simek	 *
110b98cba09SMichal Simek	 * LITTLE ENDIAN memory map for user exception
111b98cba09SMichal Simek	 * 0x8: 0xXXXX00B0
112b98cba09SMichal Simek	 * 0xC: 0xXXXX08B8
113b98cba09SMichal Simek	 *
114b98cba09SMichal Simek	 * Offset is for little endian setup to 0x2. rsubi instruction decrease
115b98cba09SMichal Simek	 * address value to ensure that points to proper place which is
116b98cba09SMichal Simek	 * 0x8 for the most significant 16 bits and
117b98cba09SMichal Simek	 * 0xC for the least significant 16 bits
118b98cba09SMichal Simek	 */
119b98cba09SMichal Simek	lhu	r7, r1, r10
120b98cba09SMichal Simek	rsubi	r8, r10, 0xa
121b98cba09SMichal Simek	sh	r7, r0, r8
122b98cba09SMichal Simek	rsubi	r8, r10, 0xe
123b98cba09SMichal Simek	sh	r6, r0, r8
1246260fb04SPeter Tyser#endif
1256260fb04SPeter Tyser
1266260fb04SPeter Tyser#ifdef CONFIG_SYS_INTC_0
1276260fb04SPeter Tyser	/* interrupt_handler */
12886c1b2a8SMichal Simek	swi	r2, r0, 0x10	/* interrupt - imm opcode */
12986c1b2a8SMichal Simek	swi	r3, r0, 0x14	/* interrupt - brai opcode */
13086c1b2a8SMichal Simek
1316260fb04SPeter Tyser	addik	r6, r0, _interrupt_handler
1326260fb04SPeter Tyser	sw	r6, r1, r0
133b98cba09SMichal Simek	lhu	r7, r1, r10
134b98cba09SMichal Simek	rsubi	r8, r10, 0x12
135b98cba09SMichal Simek	sh	r7, r0, r8
136b98cba09SMichal Simek	rsubi	r8, r10, 0x16
137b98cba09SMichal Simek	sh	r6, r0, r8
1386260fb04SPeter Tyser#endif
1396260fb04SPeter Tyser
1406260fb04SPeter Tyser	/* hardware exception */
14186c1b2a8SMichal Simek	swi	r2, r0, 0x20	/* hardware exception - imm opcode */
14286c1b2a8SMichal Simek	swi	r3, r0, 0x24	/* hardware exception - brai opcode */
14386c1b2a8SMichal Simek
1446260fb04SPeter Tyser	addik	r6, r0, _hw_exception_handler
1456260fb04SPeter Tyser	sw	r6, r1, r0
146b98cba09SMichal Simek	lhu	r7, r1, r10
147b98cba09SMichal Simek	rsubi	r8, r10, 0x22
148b98cba09SMichal Simek	sh	r7, r0, r8
149b98cba09SMichal Simek	rsubi	r8, r10, 0x26
150b98cba09SMichal Simek	sh	r6, r0, r8
1516260fb04SPeter Tyser
1526260fb04SPeter Tyser	/* enable instruction and data cache */
1536260fb04SPeter Tyser	mfs	r12, rmsr
1546260fb04SPeter Tyser	ori	r12, r12, 0xa0
1556260fb04SPeter Tyser	mts	rmsr, r12
1566260fb04SPeter Tyser
1576260fb04SPeter Tyserclear_bss:
1586260fb04SPeter Tyser	/* clear BSS segments */
1596260fb04SPeter Tyser	addi	r5, r0, __bss_start
1606260fb04SPeter Tyser	addi	r4, r0, __bss_end
1616260fb04SPeter Tyser	cmp	r6, r5, r4
1626260fb04SPeter Tyser	beqi	r6, 3f
1636260fb04SPeter Tyser2:
1646260fb04SPeter Tyser	swi     r0, r5, 0 /* write zero to loc */
1656260fb04SPeter Tyser	addi    r5, r5, 4 /* increment to next loc */
1666260fb04SPeter Tyser	cmp     r6, r5, r4 /* check if we have reach the end */
1676260fb04SPeter Tyser	bnei    r6, 2b
1686260fb04SPeter Tyser3:	/* jumping to board_init */
1696260fb04SPeter Tyser	brai	board_init
1706260fb04SPeter Tyser1:	bri	1b
1716260fb04SPeter Tyser
1726260fb04SPeter Tyser/*
1736260fb04SPeter Tyser * Read 16bit little endian
1746260fb04SPeter Tyser */
1756260fb04SPeter Tyser	.text
1766260fb04SPeter Tyser	.global	in16
1776260fb04SPeter Tyser	.ent	in16
1786260fb04SPeter Tyser	.align	2
1796260fb04SPeter Tyserin16:	lhu	r3, r0, r5
1806260fb04SPeter Tyser	bslli	r4, r3, 8
1816260fb04SPeter Tyser	bsrli	r3, r3, 8
1826260fb04SPeter Tyser	andi	r4, r4, 0xffff
1836260fb04SPeter Tyser	or	r3, r3, r4
1846260fb04SPeter Tyser	rtsd	r15, 8
1856260fb04SPeter Tyser	sext16	r3, r3
1866260fb04SPeter Tyser	.end	in16
1876260fb04SPeter Tyser
1886260fb04SPeter Tyser/*
1896260fb04SPeter Tyser * Write 16bit little endian
1906260fb04SPeter Tyser * first parameter(r5) - address, second(r6) - short value
1916260fb04SPeter Tyser */
1926260fb04SPeter Tyser	.text
1936260fb04SPeter Tyser	.global	out16
1946260fb04SPeter Tyser	.ent	out16
1956260fb04SPeter Tyser	.align	2
1966260fb04SPeter Tyserout16:	bslli	r3, r6, 8
1976260fb04SPeter Tyser	bsrli	r6, r6, 8
1986260fb04SPeter Tyser	andi	r3, r3, 0xffff
1996260fb04SPeter Tyser	or	r3, r3, r6
2006260fb04SPeter Tyser	sh	r3, r0, r5
2016260fb04SPeter Tyser	rtsd	r15, 8
2026260fb04SPeter Tyser	or	r0, r0, r0
2036260fb04SPeter Tyser	.end	out16
204