xref: /rk3399_rockchip-uboot/arch/microblaze/cpu/start.S (revision e945f6dc2814f5f0d30b5b7e23821b3fd4faff5b)
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 */
259d242745SMichal Simek
26da931af1SMichal Simek	addi	r8, r0, __end
27da931af1SMichal Simek	mts	rslr, r8
289d242745SMichal Simek#if defined(CONFIG_SPL_BUILD)
299d242745SMichal Simek	addi	r1, r0, CONFIG_SPL_STACK_ADDR
30da931af1SMichal Simek	mts	rshr, r1
319d242745SMichal Simek	addi	r1, r1, -4	/* Decrement SP to top of memory */
329d242745SMichal Simek#else
336260fb04SPeter Tyser	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
34da931af1SMichal Simek	mts	rshr, r1
356260fb04SPeter Tyser	addi	r1, r1, -4	/* Decrement SP to top of memory */
36b98cba09SMichal Simek
37b98cba09SMichal Simek	/* Find-out if u-boot is running on BIG/LITTLE endian platform
38b98cba09SMichal Simek	 * There are some steps which is necessary to keep in mind:
39b98cba09SMichal Simek	 * 1. Setup offset value to r6
40b98cba09SMichal Simek	 * 2. Store word offset value to address 0x0
41b98cba09SMichal Simek	 * 3. Load just byte from address 0x0
42b98cba09SMichal Simek	 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
43b98cba09SMichal Simek	 *     value that's why is on address 0x0
44b98cba09SMichal Simek	 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
45b98cba09SMichal Simek	 */
46b98cba09SMichal Simek	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
47f3090fceSMichal Simek	lwi	r7, r0, 0x28
48f3090fceSMichal Simek	swi	r6, r0, 0x28 /* used first unused MB vector */
49f3090fceSMichal Simek	lbui	r10, r0, 0x28 /* used first unused MB vector */
50f3090fceSMichal Simek	swi	r7, r0, 0x28
51b98cba09SMichal Simek
526260fb04SPeter Tyser	/* add opcode instruction for 32bit jump - 2 instruction imm & brai */
5386c1b2a8SMichal Simek	addi	r2, r0, 0xb0000000	/* hex b000 opcode imm */
5486c1b2a8SMichal Simek	addi	r3, r0, 0xb8080000	/* hew b808 opcode brai */
556260fb04SPeter Tyser
566260fb04SPeter Tyser#ifdef CONFIG_SYS_RESET_ADDRESS
576260fb04SPeter Tyser	/* reset address */
5886c1b2a8SMichal Simek	swi	r2, r0, 0x0	/* reset address - imm opcode */
5986c1b2a8SMichal Simek	swi	r3, r0, 0x4	/* reset address - brai opcode */
6086c1b2a8SMichal Simek
616260fb04SPeter Tyser	addik	r6, r0, CONFIG_SYS_RESET_ADDRESS
626260fb04SPeter Tyser	sw	r6, r1, r0
635562bcc2SMichal Simek	lhu	r7, r1, r10
645562bcc2SMichal Simek	rsubi	r8, r10, 0x2
655562bcc2SMichal Simek	sh	r7, r0, r8
665562bcc2SMichal Simek	rsubi	r8, r10, 0x6
675562bcc2SMichal Simek	sh	r6, r0, r8
686260fb04SPeter Tyser#endif
696260fb04SPeter Tyser
706260fb04SPeter Tyser#ifdef CONFIG_SYS_USR_EXCEP
716260fb04SPeter Tyser	/* user_vector_exception */
7286c1b2a8SMichal Simek	swi	r2, r0, 0x8	/* user vector exception - imm opcode */
7386c1b2a8SMichal Simek	swi	r3, r0, 0xC	/* user vector exception - brai opcode */
7486c1b2a8SMichal Simek
756260fb04SPeter Tyser	addik	r6, r0, _exception_handler
766260fb04SPeter Tyser	sw	r6, r1, r0
77b98cba09SMichal Simek	/*
78b98cba09SMichal Simek	 * BIG ENDIAN memory map for user exception
79b98cba09SMichal Simek	 * 0x8: 0xB000XXXX
80b98cba09SMichal Simek	 * 0xC: 0xB808XXXX
81b98cba09SMichal Simek	 *
82b98cba09SMichal Simek	 * then it is necessary to count address for storing the most significant
83b98cba09SMichal Simek	 * 16bits from _exception_handler address and copy it to
84b98cba09SMichal Simek	 * 0xa address. Big endian use offset in r10=0 that's why is it just
85b98cba09SMichal Simek	 * 0xa address. The same is done for the least significant 16 bits
86b98cba09SMichal Simek	 * for 0xe address.
87b98cba09SMichal Simek	 *
88b98cba09SMichal Simek	 * LITTLE ENDIAN memory map for user exception
89b98cba09SMichal Simek	 * 0x8: 0xXXXX00B0
90b98cba09SMichal Simek	 * 0xC: 0xXXXX08B8
91b98cba09SMichal Simek	 *
92b98cba09SMichal Simek	 * Offset is for little endian setup to 0x2. rsubi instruction decrease
93b98cba09SMichal Simek	 * address value to ensure that points to proper place which is
94b98cba09SMichal Simek	 * 0x8 for the most significant 16 bits and
95b98cba09SMichal Simek	 * 0xC for the least significant 16 bits
96b98cba09SMichal Simek	 */
97b98cba09SMichal Simek	lhu	r7, r1, r10
98b98cba09SMichal Simek	rsubi	r8, r10, 0xa
99b98cba09SMichal Simek	sh	r7, r0, r8
100b98cba09SMichal Simek	rsubi	r8, r10, 0xe
101b98cba09SMichal Simek	sh	r6, r0, r8
1026260fb04SPeter Tyser#endif
1036260fb04SPeter Tyser
1046260fb04SPeter Tyser	/* interrupt_handler */
10586c1b2a8SMichal Simek	swi	r2, r0, 0x10	/* interrupt - imm opcode */
10686c1b2a8SMichal Simek	swi	r3, r0, 0x14	/* interrupt - brai opcode */
10786c1b2a8SMichal Simek
1086260fb04SPeter Tyser	addik	r6, r0, _interrupt_handler
1096260fb04SPeter Tyser	sw	r6, r1, r0
110b98cba09SMichal Simek	lhu	r7, r1, r10
111b98cba09SMichal Simek	rsubi	r8, r10, 0x12
112b98cba09SMichal Simek	sh	r7, r0, r8
113b98cba09SMichal Simek	rsubi	r8, r10, 0x16
114b98cba09SMichal Simek	sh	r6, r0, r8
1156260fb04SPeter Tyser
1166260fb04SPeter Tyser	/* hardware exception */
11786c1b2a8SMichal Simek	swi	r2, r0, 0x20	/* hardware exception - imm opcode */
11886c1b2a8SMichal Simek	swi	r3, r0, 0x24	/* hardware exception - brai opcode */
11986c1b2a8SMichal Simek
1206260fb04SPeter Tyser	addik	r6, r0, _hw_exception_handler
1216260fb04SPeter Tyser	sw	r6, r1, r0
122b98cba09SMichal Simek	lhu	r7, r1, r10
123b98cba09SMichal Simek	rsubi	r8, r10, 0x22
124b98cba09SMichal Simek	sh	r7, r0, r8
125b98cba09SMichal Simek	rsubi	r8, r10, 0x26
126b98cba09SMichal Simek	sh	r6, r0, r8
1279d242745SMichal Simek#endif /* BUILD_SPL */
1286260fb04SPeter Tyser
1295811830fSMichal Simek	/* Flush cache before enable cache */
1305811830fSMichal Simek	addik	r5, r0, 0
1315811830fSMichal Simek	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
132e4a4743eSMichal Simek	bralid r15, flush_cache
1335811830fSMichal Simek	nop
1345811830fSMichal Simek
1356260fb04SPeter Tyser	/* enable instruction and data cache */
1366260fb04SPeter Tyser	mfs	r12, rmsr
137822d43a6SMichal Simek	ori	r12, r12, 0x1a0
1386260fb04SPeter Tyser	mts	rmsr, r12
1396260fb04SPeter Tyser
1406260fb04SPeter Tyserclear_bss:
1416260fb04SPeter Tyser	/* clear BSS segments */
1426260fb04SPeter Tyser	addi	r5, r0, __bss_start
1436260fb04SPeter Tyser	addi	r4, r0, __bss_end
1446260fb04SPeter Tyser	cmp	r6, r5, r4
1456260fb04SPeter Tyser	beqi	r6, 3f
1466260fb04SPeter Tyser2:
1476260fb04SPeter Tyser	swi     r0, r5, 0 /* write zero to loc */
1486260fb04SPeter Tyser	addi    r5, r5, 4 /* increment to next loc */
1496260fb04SPeter Tyser	cmp     r6, r5, r4 /* check if we have reach the end */
1506260fb04SPeter Tyser	bnei    r6, 2b
1516260fb04SPeter Tyser3:	/* jumping to board_init */
1529d242745SMichal Simek#ifndef CONFIG_SPL_BUILD
153*e945f6dcSMichal Simek	or	r5, r0, r0	/* flags - empty */
1542380b8f5SMichal Simek	brai	board_init_f
1559d242745SMichal Simek#else
1569cef20b1SMichal Simek	addi	r31, r0, CONFIG_SYS_SPL_MALLOC_END
1579d242745SMichal Simek	brai	board_init_r
1589d242745SMichal Simek#endif
1596260fb04SPeter Tyser1:	bri	1b
1606260fb04SPeter Tyser
1619d242745SMichal Simek#ifndef CONFIG_SPL_BUILD
1626260fb04SPeter Tyser/*
1636260fb04SPeter Tyser * Read 16bit little endian
1646260fb04SPeter Tyser */
1656260fb04SPeter Tyser	.text
1666260fb04SPeter Tyser	.global	in16
1676260fb04SPeter Tyser	.ent	in16
1686260fb04SPeter Tyser	.align	2
1696260fb04SPeter Tyserin16:	lhu	r3, r0, r5
1706260fb04SPeter Tyser	bslli	r4, r3, 8
1716260fb04SPeter Tyser	bsrli	r3, r3, 8
1726260fb04SPeter Tyser	andi	r4, r4, 0xffff
1736260fb04SPeter Tyser	or	r3, r3, r4
1746260fb04SPeter Tyser	rtsd	r15, 8
1756260fb04SPeter Tyser	sext16	r3, r3
1766260fb04SPeter Tyser	.end	in16
1776260fb04SPeter Tyser
1786260fb04SPeter Tyser/*
1796260fb04SPeter Tyser * Write 16bit little endian
1806260fb04SPeter Tyser * first parameter(r5) - address, second(r6) - short value
1816260fb04SPeter Tyser */
1826260fb04SPeter Tyser	.text
1836260fb04SPeter Tyser	.global	out16
1846260fb04SPeter Tyser	.ent	out16
1856260fb04SPeter Tyser	.align	2
1866260fb04SPeter Tyserout16:	bslli	r3, r6, 8
1876260fb04SPeter Tyser	bsrli	r6, r6, 8
1886260fb04SPeter Tyser	andi	r3, r3, 0xffff
1896260fb04SPeter Tyser	or	r3, r3, r6
1906260fb04SPeter Tyser	sh	r3, r0, r5
1916260fb04SPeter Tyser	rtsd	r15, 8
1926260fb04SPeter Tyser	or	r0, r0, r0
1936260fb04SPeter Tyser	.end	out16
194*e945f6dcSMichal Simek
195*e945f6dcSMichal Simek/*
196*e945f6dcSMichal Simek * Relocate u-boot
197*e945f6dcSMichal Simek */
198*e945f6dcSMichal Simek	.text
199*e945f6dcSMichal Simek	.global	relocate_code
200*e945f6dcSMichal Simek	.ent	relocate_code
201*e945f6dcSMichal Simek	.align	2
202*e945f6dcSMichal Simekrelocate_code:
203*e945f6dcSMichal Simek	/*
204*e945f6dcSMichal Simek	 * r5 - start_addr_sp
205*e945f6dcSMichal Simek	 * r6 - new_gd
206*e945f6dcSMichal Simek	 * r7 - reloc_addr
207*e945f6dcSMichal Simek	 */
208*e945f6dcSMichal Simek	addi	r1, r5, 0 /* Start to use new SP */
209*e945f6dcSMichal Simek	addi	r31, r6, 0 /* Start to use new GD */
210*e945f6dcSMichal Simek
211*e945f6dcSMichal Simek	add	r23, r0, r7 /* Move reloc addr to r23 */
212*e945f6dcSMichal Simek	/* Relocate text and data - r12 temp value */
213*e945f6dcSMichal Simek	addi	r21, r0, _start
214*e945f6dcSMichal Simek	addi	r22, r0, __end - 4 /* Include BSS too */
215*e945f6dcSMichal Simek1:	lwi	r12, r21, 0 /* Load u-boot data */
216*e945f6dcSMichal Simek	swi	r12, r23, 0 /* Write zero to loc */
217*e945f6dcSMichal Simek	addi	r21, r21, 4 /* Increment to next loc - origin code */
218*e945f6dcSMichal Simek	cmp	r12, r21, r22 /* Check if we have reach the end */
219*e945f6dcSMichal Simek	bneid	r12, 1b
220*e945f6dcSMichal Simek	addi	r23, r23, 4 /* Increment to next loc - relocate code */
221*e945f6dcSMichal Simek
222*e945f6dcSMichal Simek       /* R23 points to the base address. */
223*e945f6dcSMichal Simek	add	r23, r0, r7 /* Move reloc addr to r23 */
224*e945f6dcSMichal Simek	addi	r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
225*e945f6dcSMichal Simek	rsub	r23, r24, r23 /* keep - this is already here gd->reloc_off */
226*e945f6dcSMichal Simek
227*e945f6dcSMichal Simek	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
228*e945f6dcSMichal Simek	lwi	r7, r0, 0x28
229*e945f6dcSMichal Simek	swi	r6, r0, 0x28 /* used first unused MB vector */
230*e945f6dcSMichal Simek	lbui	r10, r0, 0x28 /* used first unused MB vector */
231*e945f6dcSMichal Simek	swi	r7, r0, 0x28
232*e945f6dcSMichal Simek
233*e945f6dcSMichal Simek#ifdef CONFIG_SYS_USR_EXCEP
234*e945f6dcSMichal Simek	addik	r6, r0, _exception_handler
235*e945f6dcSMichal Simek	addk	r6, r6, r23 /* add offset */
236*e945f6dcSMichal Simek	sw	r6, r1, r0
237*e945f6dcSMichal Simek	lhu	r7, r1, r10
238*e945f6dcSMichal Simek	rsubi	r8, r10, 0xa
239*e945f6dcSMichal Simek	sh	r7, r0, r8
240*e945f6dcSMichal Simek	rsubi	r8, r10, 0xe
241*e945f6dcSMichal Simek	sh	r6, r0, r8
242*e945f6dcSMichal Simek#endif
243*e945f6dcSMichal Simek	addik	r6, r0, _hw_exception_handler
244*e945f6dcSMichal Simek	addk	r6, r6, r23 /* add offset */
245*e945f6dcSMichal Simek	sw	r6, r1, r0
246*e945f6dcSMichal Simek	lhu	r7, r1, r10
247*e945f6dcSMichal Simek	rsubi	r8, r10, 0x22
248*e945f6dcSMichal Simek	sh	r7, r0, r8
249*e945f6dcSMichal Simek	rsubi	r8, r10, 0x26
250*e945f6dcSMichal Simek	sh	r6, r0, r8
251*e945f6dcSMichal Simek
252*e945f6dcSMichal Simek	addik	r6, r0, _interrupt_handler
253*e945f6dcSMichal Simek	addk	r6, r6, r23 /* add offset */
254*e945f6dcSMichal Simek	sw	r6, r1, r0
255*e945f6dcSMichal Simek	lhu	r7, r1, r10
256*e945f6dcSMichal Simek	rsubi	r8, r10, 0x12
257*e945f6dcSMichal Simek	sh	r7, r0, r8
258*e945f6dcSMichal Simek	rsubi	r8, r10, 0x16
259*e945f6dcSMichal Simek	sh	r6, r0, r8
260*e945f6dcSMichal Simek
261*e945f6dcSMichal Simek	/* Check if GOT exist */
262*e945f6dcSMichal Simek	addik	r21, r23, _got_start
263*e945f6dcSMichal Simek	addik	r22, r23, _got_end
264*e945f6dcSMichal Simek	cmpu	r12, r21, r22
265*e945f6dcSMichal Simek	beqi	r12, 2f /* No GOT table - jump over */
266*e945f6dcSMichal Simek
267*e945f6dcSMichal Simek	/* Skip last 3 entries plus 1 because of loop boundary below */
268*e945f6dcSMichal Simek	addik	r22, r22, -0x10
269*e945f6dcSMichal Simek
270*e945f6dcSMichal Simek        /* Relocate the GOT. */
271*e945f6dcSMichal Simek3:	lw	r12, r21, r0 /* Load entry */
272*e945f6dcSMichal Simek	addk	r12, r12, r23 /* Add reloc offset */
273*e945f6dcSMichal Simek	sw	r12, r21, r0 /* Save entry back */
274*e945f6dcSMichal Simek
275*e945f6dcSMichal Simek	cmpu	r12, r21, r22 /* Check if this cross boundary */
276*e945f6dcSMichal Simek	bneid	r12, 3b
277*e945f6dcSMichal Simek	addik	r21. r21, 4
278*e945f6dcSMichal Simek
279*e945f6dcSMichal Simek	/* Update pointer to GOT */
280*e945f6dcSMichal Simek	mfs	r20, rpc
281*e945f6dcSMichal Simek	addik	r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
282*e945f6dcSMichal Simek	addk	r20, r20, r23
283*e945f6dcSMichal Simek
284*e945f6dcSMichal Simek	/* Flush caches to ensure consistency */
285*e945f6dcSMichal Simek	addik	r5, r0, 0
286*e945f6dcSMichal Simek	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE
287*e945f6dcSMichal Simek	bralid	r15, flush_cache
288*e945f6dcSMichal Simek	nop
289*e945f6dcSMichal Simek
290*e945f6dcSMichal Simek2:	addi	r5, r31, 0 /* gd is initialized in board_r.c */
291*e945f6dcSMichal Simek	addi	r6, r0, CONFIG_SYS_TEXT_BASE
292*e945f6dcSMichal Simek	addi	r12, r23, board_init_r
293*e945f6dcSMichal Simek	bra	r12 /* Jump to relocated code */
294*e945f6dcSMichal Simek
295*e945f6dcSMichal Simek	.end	relocate_code
2969d242745SMichal Simek#endif
297