1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
28f8d5745SMax Filippov#include <asm/core.h>
3173d6681SChris Zankel#include <asm/regs.h>
4173d6681SChris Zankel#include <asm/asmmacro.h>
5173d6681SChris Zankel#include <asm/cacheasm.h>
60b537257SMax Filippov#include <asm/processor.h>
74bedea94SChris Zankel	/*
84bedea94SChris Zankel	 * RB-Data: RedBoot data/bss
94bedea94SChris Zankel	 * P:	    Boot-Parameters
104bedea94SChris Zankel	 * L:	    Kernel-Loader
114bedea94SChris Zankel	 *
124bedea94SChris Zankel	 * The Linux-Kernel image including the loader must be loaded
134bedea94SChris Zankel	 * to a position so that the kernel and the boot parameters
144bedea94SChris Zankel	 * can fit in the space before the load address.
154bedea94SChris Zankel	 *  ______________________________________________________
164bedea94SChris Zankel	 * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
174bedea94SChris Zankel	 *                          ^
184bedea94SChris Zankel	 *                          ^ Load address
194bedea94SChris Zankel	 *  ______________________________________________________
204bedea94SChris Zankel	 * |___Linux-Kernel___|_P_|_L_|___________________________|
214bedea94SChris Zankel	 *
224bedea94SChris Zankel	 * The loader copies the parameter to the position that will
234bedea94SChris Zankel	 * be the end of the kernel and itself to the end of the
244bedea94SChris Zankel	 * parameter list.
254bedea94SChris Zankel	 */
264bedea94SChris Zankel
274bedea94SChris Zankel/* Make sure we have enough space for the 'uncompressor' */
284bedea94SChris Zankel
294bedea94SChris Zankel#define STACK_SIZE 32768
304bedea94SChris Zankel#define HEAP_SIZE (131072*4)
314bedea94SChris Zankel
324bedea94SChris Zankel	# a2: Parameter list
334bedea94SChris Zankel	# a3: Size of parameter list
344bedea94SChris Zankel
354bedea94SChris Zankel	.section .start, "ax"
364bedea94SChris Zankel
374bedea94SChris Zankel	.globl __start
384bedea94SChris Zankel	/* this must be the first byte of the loader! */
394bedea94SChris Zankel__start:
400b537257SMax Filippov	abi_entry(32)		# we do not intend to return
414bedea94SChris Zankel	_call0	_start
424bedea94SChris Zankel__start_a0:
434bedea94SChris Zankel	.align 4
444bedea94SChris Zankel
454bedea94SChris Zankel	.section .text, "ax"
46f8f02ca7SMax Filippov	.literal_position
474bedea94SChris Zankel	.begin literal_prefix .text
484bedea94SChris Zankel
494bedea94SChris Zankel	/* put literals in here! */
504bedea94SChris Zankel
514bedea94SChris Zankel	.globl _start
524bedea94SChris Zankel_start:
534bedea94SChris Zankel
544bedea94SChris Zankel	/* 'reset' window registers */
554bedea94SChris Zankel
564bedea94SChris Zankel	movi	a4, 1
57bc5378fcSMax Filippov	wsr	a4, ps
584bedea94SChris Zankel	rsync
59*09af39f6SMax Filippov#if XCHAL_HAVE_WINDOWED
60bc5378fcSMax Filippov	rsr	a5, windowbase
614bedea94SChris Zankel	ssl	a5
624bedea94SChris Zankel	sll	a4, a4
63bc5378fcSMax Filippov	wsr	a4, windowstart
644bedea94SChris Zankel	rsync
65*09af39f6SMax Filippov#endif
660b537257SMax Filippov	movi	a4, KERNEL_PS_WOE_MASK
67bc5378fcSMax Filippov	wsr	a4, ps
684bedea94SChris Zankel	rsync
694bedea94SChris Zankel
700b537257SMax FilippovKABI_C0	mov	abi_saved0, abi_arg0
710b537257SMax Filippov
724bedea94SChris Zankel	/* copy the loader to its address
734bedea94SChris Zankel	 * Note: The loader itself is a very small piece, so we assume we
744bedea94SChris Zankel	 *       don't partially overlap. We also assume (even more important)
754bedea94SChris Zankel	 *	 that the kernel image is out of the way. Usually, when the
764bedea94SChris Zankel	 *	 load address of this image is not at an arbitrary address,
774bedea94SChris Zankel	 *	 but aligned to some 10K's we shouldn't overlap.
784bedea94SChris Zankel	 */
794bedea94SChris Zankel
804bedea94SChris Zankel	/* Note: The assembler cannot relax "addi a0, a0, ..." to an
814bedea94SChris Zankel	   l32r, so we load to a4 first. */
824bedea94SChris Zankel
83173d6681SChris Zankel	# addi	a4, a0, __start - __start_a0
84173d6681SChris Zankel	# mov	a0, a4
85173d6681SChris Zankel
86173d6681SChris Zankel	movi	a4, __start
87173d6681SChris Zankel	movi	a5, __start_a0
88173d6681SChris Zankel	add	a4, a0, a4
89173d6681SChris Zankel	sub	a0, a4, a5
90173d6681SChris Zankel
914bedea94SChris Zankel	movi	a4, __start
924bedea94SChris Zankel	movi	a5, __reloc_end
934bedea94SChris Zankel
944bedea94SChris Zankel	# a0: address where this code has been loaded
954bedea94SChris Zankel	# a4: compiled address of __start
964bedea94SChris Zankel	# a5: compiled end address
974bedea94SChris Zankel
984bedea94SChris Zankel	mov.n	a7, a0
994bedea94SChris Zankel	mov.n	a8, a4
1004bedea94SChris Zankel
1014bedea94SChris Zankel1:
1024bedea94SChris Zankel	l32i	a10, a7, 0
1034bedea94SChris Zankel	l32i	a11, a7, 4
1044bedea94SChris Zankel	s32i	a10, a8, 0
1054bedea94SChris Zankel	s32i	a11, a8, 4
1064bedea94SChris Zankel	l32i	a10, a7, 8
1074bedea94SChris Zankel	l32i	a11, a7, 12
1084bedea94SChris Zankel	s32i	a10, a8, 8
1094bedea94SChris Zankel	s32i	a11, a8, 12
1104bedea94SChris Zankel	addi	a8, a8, 16
1114bedea94SChris Zankel	addi	a7, a7, 16
1124bedea94SChris Zankel	blt	a8, a5, 1b
1134bedea94SChris Zankel
1144bedea94SChris Zankel
1154bedea94SChris Zankel	/* We have to flush and invalidate the caches here before we jump. */
1164bedea94SChris Zankel
1174bedea94SChris Zankel#if XCHAL_DCACHE_IS_WRITEBACK
118173d6681SChris Zankel
119173d6681SChris Zankel	___flush_dcache_all a5 a6
120173d6681SChris Zankel
1214bedea94SChris Zankel#endif
122173d6681SChris Zankel
123173d6681SChris Zankel	___invalidate_icache_all a5 a6
124173d6681SChris Zankel	isync
1254bedea94SChris Zankel
1264bedea94SChris Zankel	movi	a11, _reloc
1274bedea94SChris Zankel	jx	a11
1284bedea94SChris Zankel
1294bedea94SChris Zankel	.globl _reloc
1304bedea94SChris Zankel_reloc:
1314bedea94SChris Zankel
1324bedea94SChris Zankel	/* RedBoot is now at the end of the memory, so we don't have
1334bedea94SChris Zankel	 * to copy the parameter list. Keep the code around; in case
1344bedea94SChris Zankel	 * we need it again. */
1354bedea94SChris Zankel#if 0
1364bedea94SChris Zankel	# a0: load address
1374bedea94SChris Zankel	# a2: start address of parameter list
1384bedea94SChris Zankel	# a3: length of parameter list
1394bedea94SChris Zankel	# a4: __start
1404bedea94SChris Zankel
1414bedea94SChris Zankel	/* copy the parameter list out of the way */
1424bedea94SChris Zankel
1434bedea94SChris Zankel	movi	a6, _param_start
1444bedea94SChris Zankel	add	a3, a2, a3
1454bedea94SChris Zankel2:
1464bedea94SChris Zankel	l32i	a8, a2, 0
1474bedea94SChris Zankel	s32i	a8, a6, 0
1484bedea94SChris Zankel	addi	a2, a2, 4
1494bedea94SChris Zankel	addi	a6, a6, 4
1504bedea94SChris Zankel	blt	a2, a3, 2b
1514bedea94SChris Zankel#endif
1524bedea94SChris Zankel
1534bedea94SChris Zankel	/* clear BSS section */
1544bedea94SChris Zankel	movi	a6, __bss_start
1554bedea94SChris Zankel	movi	a7, __bss_end
1564bedea94SChris Zankel	movi.n	a5, 0
1574bedea94SChris Zankel3:
1584bedea94SChris Zankel	s32i	a5, a6, 0
1594bedea94SChris Zankel	addi	a6, a6, 4
1604bedea94SChris Zankel	blt	a6, a7, 3b
1614bedea94SChris Zankel
1624bedea94SChris Zankel	movi	a5, -16
1634bedea94SChris Zankel	movi	a1, _stack + STACK_SIZE
1644bedea94SChris Zankel	and	a1, a1, a5
1654bedea94SChris Zankel
1664bedea94SChris Zankel	/* Uncompress the kernel */
1674bedea94SChris Zankel
1684bedea94SChris Zankel	# a0: load address
1694bedea94SChris Zankel	# a2: boot parameter
1704bedea94SChris Zankel	# a4: __start
1714bedea94SChris Zankel
1724bedea94SChris Zankel	movi	a3, __image_load
1734bedea94SChris Zankel	sub	a4, a3, a4
1740b537257SMax Filippov	add	abi_arg2, a0, a4
1754bedea94SChris Zankel
1764bedea94SChris Zankel	# a1  Stack
1774bedea94SChris Zankel	# a8(a4)  Load address of the image
1784bedea94SChris Zankel
1790b537257SMax Filippov	movi	abi_arg0, _image_start
1800b537257SMax Filippov	movi	abi_arg4, _image_end
1810b537257SMax Filippov	movi	abi_arg1, 0x1000000
1820b537257SMax Filippov	sub	abi_tmp0, abi_arg4, abi_arg0
1830b537257SMax Filippov	movi	abi_arg3, complen
1840b537257SMax Filippov	s32i	abi_tmp0, abi_arg3, 0
1854bedea94SChris Zankel
1864bedea94SChris Zankel	movi	a0, 0
1874bedea94SChris Zankel
1880b537257SMax Filippov	# abi_arg0 destination
1890b537257SMax Filippov	# abi_arg1 maximum size of destination
1900b537257SMax Filippov	# abi_arg2 source
1910b537257SMax Filippov	# abi_arg3 ptr to length
1924bedea94SChris Zankel
1934bedea94SChris Zankel	.extern gunzip
1940b537257SMax Filippov	movi	abi_tmp0, gunzip
1950b537257SMax Filippov	beqz	abi_tmp0, 1f
1964bedea94SChris Zankel
1970b537257SMax Filippov	abi_callx	abi_tmp0
1984bedea94SChris Zankel
1994bedea94SChris Zankel	j	2f
2004bedea94SChris Zankel
2014bedea94SChris Zankel
2020b537257SMax Filippov	# abi_arg0 destination start
2030b537257SMax Filippov	# abi_arg1 maximum size of destination
2040b537257SMax Filippov	# abi_arg2 source start
2050b537257SMax Filippov	# abi_arg3 ptr to length
2060b537257SMax Filippov	# abi_arg4 destination end
2074bedea94SChris Zankel
2084bedea94SChris Zankel1:
2090b537257SMax Filippov        l32i    abi_tmp0, abi_arg2, 0
2100b537257SMax Filippov        l32i    abi_tmp1, abi_arg2, 4
2110b537257SMax Filippov        s32i    abi_tmp0, abi_arg0, 0
2120b537257SMax Filippov        s32i    abi_tmp1, abi_arg0, 4
2130b537257SMax Filippov        l32i    abi_tmp0, abi_arg2, 8
2140b537257SMax Filippov        l32i    abi_tmp1, abi_arg2, 12
2150b537257SMax Filippov        s32i    abi_tmp0, abi_arg0, 8
2160b537257SMax Filippov        s32i    abi_tmp1, abi_arg0, 12
2170b537257SMax Filippov        addi    abi_arg0, abi_arg0, 16
2180b537257SMax Filippov        addi    abi_arg2, abi_arg2, 16
2190b537257SMax Filippov        blt     abi_arg0, abi_arg4, 1b
2204bedea94SChris Zankel
2214bedea94SChris Zankel
2224bedea94SChris Zankel	/* jump to the kernel */
2234bedea94SChris Zankel2:
2244bedea94SChris Zankel#if XCHAL_DCACHE_IS_WRITEBACK
225173d6681SChris Zankel
226173d6681SChris Zankel	___flush_dcache_all a5 a6
227173d6681SChris Zankel
2284bedea94SChris Zankel#endif
229173d6681SChris Zankel
230173d6681SChris Zankel	___invalidate_icache_all a5 a6
231173d6681SChris Zankel
232173d6681SChris Zankel	isync
2334bedea94SChris Zankel
2344bedea94SChris Zankel	# a2  Boot parameter list
2354bedea94SChris Zankel
2360b537257SMax FilippovKABI_C0	mov	abi_arg0, abi_saved0
2374bedea94SChris Zankel	movi	a0, _image_start
2384bedea94SChris Zankel	jx	a0
2394bedea94SChris Zankel
2404bedea94SChris Zankel	.align 16
2414bedea94SChris Zankel	.data
2424bedea94SChris Zankel	.globl avail_ram
2434bedea94SChris Zankelavail_ram:
2444bedea94SChris Zankel	.long	_heap
2454bedea94SChris Zankel	.globl end_avail
2464bedea94SChris Zankelend_avail:
2474bedea94SChris Zankel	.long	_heap + HEAP_SIZE
2484bedea94SChris Zankel
2494bedea94SChris Zankel	.comm _stack, STACK_SIZE
2504bedea94SChris Zankel	.comm _heap, HEAP_SIZE
2514bedea94SChris Zankel
2524bedea94SChris Zankel	.globl end_avail
2534bedea94SChris Zankel	.comm complen, 4
2544bedea94SChris Zankel
2554bedea94SChris Zankel	.end	literal_prefix
256