18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#include <asm/core.h>
38c2ecf20Sopenharmony_ci#include <asm/regs.h>
48c2ecf20Sopenharmony_ci#include <asm/asmmacro.h>
58c2ecf20Sopenharmony_ci#include <asm/cacheasm.h>
68c2ecf20Sopenharmony_ci	/*
78c2ecf20Sopenharmony_ci	 * RB-Data: RedBoot data/bss
88c2ecf20Sopenharmony_ci	 * P:	    Boot-Parameters
98c2ecf20Sopenharmony_ci	 * L:	    Kernel-Loader
108c2ecf20Sopenharmony_ci	 *
118c2ecf20Sopenharmony_ci	 * The Linux-Kernel image including the loader must be loaded
128c2ecf20Sopenharmony_ci	 * to a position so that the kernel and the boot parameters
138c2ecf20Sopenharmony_ci	 * can fit in the space before the load address.
148c2ecf20Sopenharmony_ci	 *  ______________________________________________________
158c2ecf20Sopenharmony_ci	 * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
168c2ecf20Sopenharmony_ci	 *                          ^
178c2ecf20Sopenharmony_ci	 *                          ^ Load address
188c2ecf20Sopenharmony_ci	 *  ______________________________________________________
198c2ecf20Sopenharmony_ci	 * |___Linux-Kernel___|_P_|_L_|___________________________|
208c2ecf20Sopenharmony_ci	 *
218c2ecf20Sopenharmony_ci	 * The loader copies the parameter to the position that will
228c2ecf20Sopenharmony_ci	 * be the end of the kernel and itself to the end of the
238c2ecf20Sopenharmony_ci	 * parameter list.
248c2ecf20Sopenharmony_ci	 */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* Make sure we have enough space for the 'uncompressor' */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define STACK_SIZE 32768
298c2ecf20Sopenharmony_ci#define HEAP_SIZE (131072*4)
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	# a2: Parameter list
328c2ecf20Sopenharmony_ci	# a3: Size of parameter list
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	.section .start, "ax"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	.globl __start
378c2ecf20Sopenharmony_ci	/* this must be the first byte of the loader! */
388c2ecf20Sopenharmony_ci__start:
398c2ecf20Sopenharmony_ci	entry	sp, 32		# we do not intend to return
408c2ecf20Sopenharmony_ci	_call0	_start
418c2ecf20Sopenharmony_ci__start_a0:
428c2ecf20Sopenharmony_ci	.align 4
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	.section .text, "ax"
458c2ecf20Sopenharmony_ci	.literal_position
468c2ecf20Sopenharmony_ci	.begin literal_prefix .text
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	/* put literals in here! */
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	.globl _start
518c2ecf20Sopenharmony_ci_start:
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	/* 'reset' window registers */
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	movi	a4, 1
568c2ecf20Sopenharmony_ci	wsr	a4, ps
578c2ecf20Sopenharmony_ci	rsync
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	rsr	a5, windowbase
608c2ecf20Sopenharmony_ci	ssl	a5
618c2ecf20Sopenharmony_ci	sll	a4, a4
628c2ecf20Sopenharmony_ci	wsr	a4, windowstart
638c2ecf20Sopenharmony_ci	rsync
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	movi	a4, 0x00040000
668c2ecf20Sopenharmony_ci	wsr	a4, ps
678c2ecf20Sopenharmony_ci	rsync
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	/* copy the loader to its address
708c2ecf20Sopenharmony_ci	 * Note: The loader itself is a very small piece, so we assume we
718c2ecf20Sopenharmony_ci	 *       don't partially overlap. We also assume (even more important)
728c2ecf20Sopenharmony_ci	 *	 that the kernel image is out of the way. Usually, when the
738c2ecf20Sopenharmony_ci	 *	 load address of this image is not at an arbitrary address,
748c2ecf20Sopenharmony_ci	 *	 but aligned to some 10K's we shouldn't overlap.
758c2ecf20Sopenharmony_ci	 */
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* Note: The assembler cannot relax "addi a0, a0, ..." to an
788c2ecf20Sopenharmony_ci	   l32r, so we load to a4 first. */
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	# addi	a4, a0, __start - __start_a0
818c2ecf20Sopenharmony_ci	# mov	a0, a4
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	movi	a4, __start
848c2ecf20Sopenharmony_ci	movi	a5, __start_a0
858c2ecf20Sopenharmony_ci	add	a4, a0, a4
868c2ecf20Sopenharmony_ci	sub	a0, a4, a5
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	movi	a4, __start
898c2ecf20Sopenharmony_ci	movi	a5, __reloc_end
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	# a0: address where this code has been loaded
928c2ecf20Sopenharmony_ci	# a4: compiled address of __start
938c2ecf20Sopenharmony_ci	# a5: compiled end address
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	mov.n	a7, a0
968c2ecf20Sopenharmony_ci	mov.n	a8, a4
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci1:
998c2ecf20Sopenharmony_ci	l32i	a10, a7, 0
1008c2ecf20Sopenharmony_ci	l32i	a11, a7, 4
1018c2ecf20Sopenharmony_ci	s32i	a10, a8, 0
1028c2ecf20Sopenharmony_ci	s32i	a11, a8, 4
1038c2ecf20Sopenharmony_ci	l32i	a10, a7, 8
1048c2ecf20Sopenharmony_ci	l32i	a11, a7, 12
1058c2ecf20Sopenharmony_ci	s32i	a10, a8, 8
1068c2ecf20Sopenharmony_ci	s32i	a11, a8, 12
1078c2ecf20Sopenharmony_ci	addi	a8, a8, 16
1088c2ecf20Sopenharmony_ci	addi	a7, a7, 16
1098c2ecf20Sopenharmony_ci	blt	a8, a5, 1b
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	/* We have to flush and invalidate the caches here before we jump. */
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci#if XCHAL_DCACHE_IS_WRITEBACK
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	___flush_dcache_all a5 a6
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#endif
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	___invalidate_icache_all a5 a6
1218c2ecf20Sopenharmony_ci	isync
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	movi	a11, _reloc
1248c2ecf20Sopenharmony_ci	jx	a11
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	.globl _reloc
1278c2ecf20Sopenharmony_ci_reloc:
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	/* RedBoot is now at the end of the memory, so we don't have
1308c2ecf20Sopenharmony_ci	 * to copy the parameter list. Keep the code around; in case
1318c2ecf20Sopenharmony_ci	 * we need it again. */
1328c2ecf20Sopenharmony_ci#if 0
1338c2ecf20Sopenharmony_ci	# a0: load address
1348c2ecf20Sopenharmony_ci	# a2: start address of parameter list
1358c2ecf20Sopenharmony_ci	# a3: length of parameter list
1368c2ecf20Sopenharmony_ci	# a4: __start
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	/* copy the parameter list out of the way */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	movi	a6, _param_start
1418c2ecf20Sopenharmony_ci	add	a3, a2, a3
1428c2ecf20Sopenharmony_ci2:
1438c2ecf20Sopenharmony_ci	l32i	a8, a2, 0
1448c2ecf20Sopenharmony_ci	s32i	a8, a6, 0
1458c2ecf20Sopenharmony_ci	addi	a2, a2, 4
1468c2ecf20Sopenharmony_ci	addi	a6, a6, 4
1478c2ecf20Sopenharmony_ci	blt	a2, a3, 2b
1488c2ecf20Sopenharmony_ci#endif
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	/* clear BSS section */
1518c2ecf20Sopenharmony_ci	movi	a6, __bss_start
1528c2ecf20Sopenharmony_ci	movi	a7, __bss_end
1538c2ecf20Sopenharmony_ci	movi.n	a5, 0
1548c2ecf20Sopenharmony_ci3:
1558c2ecf20Sopenharmony_ci	s32i	a5, a6, 0
1568c2ecf20Sopenharmony_ci	addi	a6, a6, 4
1578c2ecf20Sopenharmony_ci	blt	a6, a7, 3b
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	movi	a5, -16
1608c2ecf20Sopenharmony_ci	movi	a1, _stack + STACK_SIZE
1618c2ecf20Sopenharmony_ci	and	a1, a1, a5
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	/* Uncompress the kernel */
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	# a0: load address
1668c2ecf20Sopenharmony_ci	# a2: boot parameter
1678c2ecf20Sopenharmony_ci	# a4: __start
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	movi	a3, __image_load
1708c2ecf20Sopenharmony_ci	sub	a4, a3, a4
1718c2ecf20Sopenharmony_ci	add	a8, a0, a4
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	# a1  Stack
1748c2ecf20Sopenharmony_ci	# a8(a4)  Load address of the image
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	movi	a6, _image_start
1778c2ecf20Sopenharmony_ci	movi	a10, _image_end
1788c2ecf20Sopenharmony_ci	movi	a7, 0x1000000
1798c2ecf20Sopenharmony_ci	sub	a11, a10, a6
1808c2ecf20Sopenharmony_ci	movi	a9, complen
1818c2ecf20Sopenharmony_ci	s32i	a11, a9, 0
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	movi	a0, 0
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	# a6 destination
1868c2ecf20Sopenharmony_ci	# a7 maximum size of destination
1878c2ecf20Sopenharmony_ci	# a8 source
1888c2ecf20Sopenharmony_ci	# a9 ptr to length
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	.extern gunzip
1918c2ecf20Sopenharmony_ci	movi	a4, gunzip
1928c2ecf20Sopenharmony_ci	beqz	a4, 1f
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	callx4	a4
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	j	2f
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	# a6 destination start
2008c2ecf20Sopenharmony_ci	# a7 maximum size of destination
2018c2ecf20Sopenharmony_ci	# a8 source start
2028c2ecf20Sopenharmony_ci	# a9 ptr to length
2038c2ecf20Sopenharmony_ci	# a10 destination end
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci1:
2068c2ecf20Sopenharmony_ci        l32i    a9, a8, 0
2078c2ecf20Sopenharmony_ci        l32i    a11, a8, 4
2088c2ecf20Sopenharmony_ci        s32i    a9, a6, 0
2098c2ecf20Sopenharmony_ci        s32i    a11, a6, 4
2108c2ecf20Sopenharmony_ci        l32i    a9, a8, 8
2118c2ecf20Sopenharmony_ci        l32i    a11, a8, 12
2128c2ecf20Sopenharmony_ci        s32i    a9, a6, 8
2138c2ecf20Sopenharmony_ci        s32i    a11, a6, 12
2148c2ecf20Sopenharmony_ci        addi    a6, a6, 16
2158c2ecf20Sopenharmony_ci        addi    a8, a8, 16
2168c2ecf20Sopenharmony_ci        blt     a6, a10, 1b
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	/* jump to the kernel */
2208c2ecf20Sopenharmony_ci2:
2218c2ecf20Sopenharmony_ci#if XCHAL_DCACHE_IS_WRITEBACK
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	___flush_dcache_all a5 a6
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci#endif
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	___invalidate_icache_all a5 a6
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	isync
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	# a2  Boot parameter list
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	movi	a0, _image_start
2348c2ecf20Sopenharmony_ci	jx	a0
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	.align 16
2378c2ecf20Sopenharmony_ci	.data
2388c2ecf20Sopenharmony_ci	.globl avail_ram
2398c2ecf20Sopenharmony_ciavail_ram:
2408c2ecf20Sopenharmony_ci	.long	_heap
2418c2ecf20Sopenharmony_ci	.globl end_avail
2428c2ecf20Sopenharmony_ciend_avail:
2438c2ecf20Sopenharmony_ci	.long	_heap + HEAP_SIZE
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	.comm _stack, STACK_SIZE
2468c2ecf20Sopenharmony_ci	.comm _heap, HEAP_SIZE
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	.globl end_avail
2498c2ecf20Sopenharmony_ci	.comm complen, 4
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	.end	literal_prefix
252