xref: /openbmc/u-boot/arch/microblaze/cpu/start.S (revision 9d24274509cdd463992dc1fb1a2820d6a4b6d21d)
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 *
81a459660SWolfgang Denk * SPDX-License-Identifier:	GPL-2.0+
96260fb04SPeter Tyser */
106260fb04SPeter Tyser
1125ddd1fbSWolfgang Denk#include <asm-offsets.h>
126260fb04SPeter Tyser#include <config.h>
136260fb04SPeter Tyser
146260fb04SPeter Tyser	.text
156260fb04SPeter Tyser	.global _start
166260fb04SPeter Tyser_start:
1786c1b2a8SMichal Simek	/*
1886c1b2a8SMichal Simek	 * reserve registers:
1986c1b2a8SMichal Simek	 * r10: Stores little/big endian offset for vectors
2086c1b2a8SMichal Simek	 * r2: Stores imm opcode
2186c1b2a8SMichal Simek	 * r3: Stores brai opcode
2286c1b2a8SMichal Simek	 */
2386c1b2a8SMichal Simek
246260fb04SPeter Tyser	mts	rmsr, r0	/* disable cache */
25*9d242745SMichal Simek
26*9d242745SMichal Simek#if defined(CONFIG_SPL_BUILD)
27*9d242745SMichal Simek	addi	r1, r0, CONFIG_SPL_STACK_ADDR
28*9d242745SMichal Simek	addi	r1, r1, -4	/* Decrement SP to top of memory */
29*9d242745SMichal Simek#else
306260fb04SPeter Tyser	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
316260fb04SPeter Tyser	addi	r1, r1, -4	/* Decrement SP to top of memory */
32b98cba09SMichal Simek
33b98cba09SMichal Simek	/* Find-out if u-boot is running on BIG/LITTLE endian platform
34b98cba09SMichal Simek	 * There are some steps which is necessary to keep in mind:
35b98cba09SMichal Simek	 * 1. Setup offset value to r6
36b98cba09SMichal Simek	 * 2. Store word offset value to address 0x0
37b98cba09SMichal Simek	 * 3. Load just byte from address 0x0
38b98cba09SMichal Simek	 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
39b98cba09SMichal Simek	 *     value that's why is on address 0x0
40b98cba09SMichal Simek	 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
41b98cba09SMichal Simek	 */
42b98cba09SMichal Simek	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
43f3090fceSMichal Simek	lwi	r7, r0, 0x28
44f3090fceSMichal Simek	swi	r6, r0, 0x28 /* used first unused MB vector */
45f3090fceSMichal Simek	lbui	r10, r0, 0x28 /* used first unused MB vector */
46f3090fceSMichal Simek	swi	r7, r0, 0x28
47b98cba09SMichal Simek
486260fb04SPeter Tyser	/* add opcode instruction for 32bit jump - 2 instruction imm & brai */
4986c1b2a8SMichal Simek	addi	r2, r0, 0xb0000000	/* hex b000 opcode imm */
5086c1b2a8SMichal Simek	addi	r3, r0, 0xb8080000	/* hew b808 opcode brai */
516260fb04SPeter Tyser
526260fb04SPeter Tyser#ifdef CONFIG_SYS_RESET_ADDRESS
536260fb04SPeter Tyser	/* reset address */
5486c1b2a8SMichal Simek	swi	r2, r0, 0x0	/* reset address - imm opcode */
5586c1b2a8SMichal Simek	swi	r3, r0, 0x4	/* reset address - brai opcode */
5686c1b2a8SMichal Simek
576260fb04SPeter Tyser	addik	r6, r0, CONFIG_SYS_RESET_ADDRESS
586260fb04SPeter Tyser	sw	r6, r1, r0
595562bcc2SMichal Simek	lhu	r7, r1, r10
605562bcc2SMichal Simek	rsubi	r8, r10, 0x2
615562bcc2SMichal Simek	sh	r7, r0, r8
625562bcc2SMichal Simek	rsubi	r8, r10, 0x6
635562bcc2SMichal Simek	sh	r6, r0, r8
646260fb04SPeter Tyser#endif
656260fb04SPeter Tyser
666260fb04SPeter Tyser#ifdef CONFIG_SYS_USR_EXCEP
676260fb04SPeter Tyser	/* user_vector_exception */
6886c1b2a8SMichal Simek	swi	r2, r0, 0x8	/* user vector exception - imm opcode */
6986c1b2a8SMichal Simek	swi	r3, r0, 0xC	/* user vector exception - brai opcode */
7086c1b2a8SMichal Simek
716260fb04SPeter Tyser	addik	r6, r0, _exception_handler
726260fb04SPeter Tyser	sw	r6, r1, r0
73b98cba09SMichal Simek	/*
74b98cba09SMichal Simek	 * BIG ENDIAN memory map for user exception
75b98cba09SMichal Simek	 * 0x8: 0xB000XXXX
76b98cba09SMichal Simek	 * 0xC: 0xB808XXXX
77b98cba09SMichal Simek	 *
78b98cba09SMichal Simek	 * then it is necessary to count address for storing the most significant
79b98cba09SMichal Simek	 * 16bits from _exception_handler address and copy it to
80b98cba09SMichal Simek	 * 0xa address. Big endian use offset in r10=0 that's why is it just
81b98cba09SMichal Simek	 * 0xa address. The same is done for the least significant 16 bits
82b98cba09SMichal Simek	 * for 0xe address.
83b98cba09SMichal Simek	 *
84b98cba09SMichal Simek	 * LITTLE ENDIAN memory map for user exception
85b98cba09SMichal Simek	 * 0x8: 0xXXXX00B0
86b98cba09SMichal Simek	 * 0xC: 0xXXXX08B8
87b98cba09SMichal Simek	 *
88b98cba09SMichal Simek	 * Offset is for little endian setup to 0x2. rsubi instruction decrease
89b98cba09SMichal Simek	 * address value to ensure that points to proper place which is
90b98cba09SMichal Simek	 * 0x8 for the most significant 16 bits and
91b98cba09SMichal Simek	 * 0xC for the least significant 16 bits
92b98cba09SMichal Simek	 */
93b98cba09SMichal Simek	lhu	r7, r1, r10
94b98cba09SMichal Simek	rsubi	r8, r10, 0xa
95b98cba09SMichal Simek	sh	r7, r0, r8
96b98cba09SMichal Simek	rsubi	r8, r10, 0xe
97b98cba09SMichal Simek	sh	r6, r0, r8
986260fb04SPeter Tyser#endif
996260fb04SPeter Tyser
1006260fb04SPeter Tyser	/* interrupt_handler */
10186c1b2a8SMichal Simek	swi	r2, r0, 0x10	/* interrupt - imm opcode */
10286c1b2a8SMichal Simek	swi	r3, r0, 0x14	/* interrupt - brai opcode */
10386c1b2a8SMichal Simek
1046260fb04SPeter Tyser	addik	r6, r0, _interrupt_handler
1056260fb04SPeter Tyser	sw	r6, r1, r0
106b98cba09SMichal Simek	lhu	r7, r1, r10
107b98cba09SMichal Simek	rsubi	r8, r10, 0x12
108b98cba09SMichal Simek	sh	r7, r0, r8
109b98cba09SMichal Simek	rsubi	r8, r10, 0x16
110b98cba09SMichal Simek	sh	r6, r0, r8
1116260fb04SPeter Tyser
1126260fb04SPeter Tyser	/* hardware exception */
11386c1b2a8SMichal Simek	swi	r2, r0, 0x20	/* hardware exception - imm opcode */
11486c1b2a8SMichal Simek	swi	r3, r0, 0x24	/* hardware exception - brai opcode */
11586c1b2a8SMichal Simek
1166260fb04SPeter Tyser	addik	r6, r0, _hw_exception_handler
1176260fb04SPeter Tyser	sw	r6, r1, r0
118b98cba09SMichal Simek	lhu	r7, r1, r10
119b98cba09SMichal Simek	rsubi	r8, r10, 0x22
120b98cba09SMichal Simek	sh	r7, r0, r8
121b98cba09SMichal Simek	rsubi	r8, r10, 0x26
122b98cba09SMichal Simek	sh	r6, r0, r8
123*9d242745SMichal Simek#endif /* BUILD_SPL */
1246260fb04SPeter Tyser
1255811830fSMichal Simek	/* Flush cache before enable cache */
1265811830fSMichal Simek	addik	r5, r0, 0
1275811830fSMichal Simek	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
1285811830fSMichal Simekflush:	bralid r15, flush_cache
1295811830fSMichal Simek	nop
1305811830fSMichal Simek
1316260fb04SPeter Tyser	/* enable instruction and data cache */
1326260fb04SPeter Tyser	mfs	r12, rmsr
1336260fb04SPeter Tyser	ori	r12, r12, 0xa0
1346260fb04SPeter Tyser	mts	rmsr, r12
1356260fb04SPeter Tyser
1366260fb04SPeter Tyserclear_bss:
1376260fb04SPeter Tyser	/* clear BSS segments */
1386260fb04SPeter Tyser	addi	r5, r0, __bss_start
1396260fb04SPeter Tyser	addi	r4, r0, __bss_end
1406260fb04SPeter Tyser	cmp	r6, r5, r4
1416260fb04SPeter Tyser	beqi	r6, 3f
1426260fb04SPeter Tyser2:
1436260fb04SPeter Tyser	swi     r0, r5, 0 /* write zero to loc */
1446260fb04SPeter Tyser	addi    r5, r5, 4 /* increment to next loc */
1456260fb04SPeter Tyser	cmp     r6, r5, r4 /* check if we have reach the end */
1466260fb04SPeter Tyser	bnei    r6, 2b
1476260fb04SPeter Tyser3:	/* jumping to board_init */
148*9d242745SMichal Simek#ifndef CONFIG_SPL_BUILD
1492380b8f5SMichal Simek	brai	board_init_f
150*9d242745SMichal Simek#else
151*9d242745SMichal Simek	brai	board_init_r
152*9d242745SMichal Simek#endif
1536260fb04SPeter Tyser1:	bri	1b
1546260fb04SPeter Tyser
155*9d242745SMichal Simek#ifndef CONFIG_SPL_BUILD
1566260fb04SPeter Tyser/*
1576260fb04SPeter Tyser * Read 16bit little endian
1586260fb04SPeter Tyser */
1596260fb04SPeter Tyser	.text
1606260fb04SPeter Tyser	.global	in16
1616260fb04SPeter Tyser	.ent	in16
1626260fb04SPeter Tyser	.align	2
1636260fb04SPeter Tyserin16:	lhu	r3, r0, r5
1646260fb04SPeter Tyser	bslli	r4, r3, 8
1656260fb04SPeter Tyser	bsrli	r3, r3, 8
1666260fb04SPeter Tyser	andi	r4, r4, 0xffff
1676260fb04SPeter Tyser	or	r3, r3, r4
1686260fb04SPeter Tyser	rtsd	r15, 8
1696260fb04SPeter Tyser	sext16	r3, r3
1706260fb04SPeter Tyser	.end	in16
1716260fb04SPeter Tyser
1726260fb04SPeter Tyser/*
1736260fb04SPeter Tyser * Write 16bit little endian
1746260fb04SPeter Tyser * first parameter(r5) - address, second(r6) - short value
1756260fb04SPeter Tyser */
1766260fb04SPeter Tyser	.text
1776260fb04SPeter Tyser	.global	out16
1786260fb04SPeter Tyser	.ent	out16
1796260fb04SPeter Tyser	.align	2
1806260fb04SPeter Tyserout16:	bslli	r3, r6, 8
1816260fb04SPeter Tyser	bsrli	r6, r6, 8
1826260fb04SPeter Tyser	andi	r3, r3, 0xffff
1836260fb04SPeter Tyser	or	r3, r3, r6
1846260fb04SPeter Tyser	sh	r3, r0, r5
1856260fb04SPeter Tyser	rtsd	r15, 8
1866260fb04SPeter Tyser	or	r0, r0, r0
1876260fb04SPeter Tyser	.end	out16
188*9d242745SMichal Simek#endif
189