1367b8112SChris Zankel#include <variant/core.h>
2173d6681SChris Zankel#include <asm/regs.h>
3173d6681SChris Zankel#include <asm/asmmacro.h>
4173d6681SChris Zankel#include <asm/cacheasm.h>
54bedea94SChris Zankel	/*
64bedea94SChris Zankel	 * RB-Data: RedBoot data/bss
74bedea94SChris Zankel	 * P:	    Boot-Parameters
84bedea94SChris Zankel	 * L:	    Kernel-Loader
94bedea94SChris Zankel	 *
104bedea94SChris Zankel	 * The Linux-Kernel image including the loader must be loaded
114bedea94SChris Zankel	 * to a position so that the kernel and the boot parameters
124bedea94SChris Zankel	 * can fit in the space before the load address.
134bedea94SChris Zankel	 *  ______________________________________________________
144bedea94SChris Zankel	 * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
154bedea94SChris Zankel	 *                          ^
164bedea94SChris Zankel	 *                          ^ Load address
174bedea94SChris Zankel	 *  ______________________________________________________
184bedea94SChris Zankel	 * |___Linux-Kernel___|_P_|_L_|___________________________|
194bedea94SChris Zankel	 *
204bedea94SChris Zankel	 * The loader copies the parameter to the position that will
214bedea94SChris Zankel	 * be the end of the kernel and itself to the end of the
224bedea94SChris Zankel	 * parameter list.
234bedea94SChris Zankel	 */
244bedea94SChris Zankel
254bedea94SChris Zankel/* Make sure we have enough space for the 'uncompressor' */
264bedea94SChris Zankel
274bedea94SChris Zankel#define STACK_SIZE 32768
284bedea94SChris Zankel#define HEAP_SIZE (131072*4)
294bedea94SChris Zankel
304bedea94SChris Zankel	# a2: Parameter list
314bedea94SChris Zankel	# a3: Size of parameter list
324bedea94SChris Zankel
334bedea94SChris Zankel	.section .start, "ax"
344bedea94SChris Zankel
354bedea94SChris Zankel	.globl __start
364bedea94SChris Zankel	/* this must be the first byte of the loader! */
374bedea94SChris Zankel__start:
384bedea94SChris Zankel	entry	sp, 32		# we do not intend to return
394bedea94SChris Zankel	_call0	_start
404bedea94SChris Zankel__start_a0:
414bedea94SChris Zankel	.align 4
424bedea94SChris Zankel
434bedea94SChris Zankel	.section .text, "ax"
444bedea94SChris Zankel	.begin literal_prefix .text
454bedea94SChris Zankel
464bedea94SChris Zankel	/* put literals in here! */
474bedea94SChris Zankel
484bedea94SChris Zankel	.globl _start
494bedea94SChris Zankel_start:
504bedea94SChris Zankel
514bedea94SChris Zankel	/* 'reset' window registers */
524bedea94SChris Zankel
534bedea94SChris Zankel	movi	a4, 1
54bc5378fcSMax Filippov	wsr	a4, ps
554bedea94SChris Zankel	rsync
564bedea94SChris Zankel
57bc5378fcSMax Filippov	rsr	a5, windowbase
584bedea94SChris Zankel	ssl	a5
594bedea94SChris Zankel	sll	a4, a4
60bc5378fcSMax Filippov	wsr	a4, windowstart
614bedea94SChris Zankel	rsync
624bedea94SChris Zankel
634bedea94SChris Zankel	movi	a4, 0x00040000
64bc5378fcSMax Filippov	wsr	a4, ps
654bedea94SChris Zankel	rsync
664bedea94SChris Zankel
674bedea94SChris Zankel	/* copy the loader to its address
684bedea94SChris Zankel	 * Note: The loader itself is a very small piece, so we assume we
694bedea94SChris Zankel	 *       don't partially overlap. We also assume (even more important)
704bedea94SChris Zankel	 *	 that the kernel image is out of the way. Usually, when the
714bedea94SChris Zankel	 *	 load address of this image is not at an arbitrary address,
724bedea94SChris Zankel	 *	 but aligned to some 10K's we shouldn't overlap.
734bedea94SChris Zankel	 */
744bedea94SChris Zankel
754bedea94SChris Zankel	/* Note: The assembler cannot relax "addi a0, a0, ..." to an
764bedea94SChris Zankel	   l32r, so we load to a4 first. */
774bedea94SChris Zankel
78173d6681SChris Zankel	# addi	a4, a0, __start - __start_a0
79173d6681SChris Zankel	# mov	a0, a4
80173d6681SChris Zankel
81173d6681SChris Zankel	movi	a4, __start
82173d6681SChris Zankel	movi	a5, __start_a0
83173d6681SChris Zankel	add	a4, a0, a4
84173d6681SChris Zankel	sub	a0, a4, a5
85173d6681SChris Zankel
864bedea94SChris Zankel	movi	a4, __start
874bedea94SChris Zankel	movi	a5, __reloc_end
884bedea94SChris Zankel
894bedea94SChris Zankel	# a0: address where this code has been loaded
904bedea94SChris Zankel	# a4: compiled address of __start
914bedea94SChris Zankel	# a5: compiled end address
924bedea94SChris Zankel
934bedea94SChris Zankel	mov.n	a7, a0
944bedea94SChris Zankel	mov.n	a8, a4
954bedea94SChris Zankel
964bedea94SChris Zankel1:
974bedea94SChris Zankel	l32i	a10, a7, 0
984bedea94SChris Zankel	l32i	a11, a7, 4
994bedea94SChris Zankel	s32i	a10, a8, 0
1004bedea94SChris Zankel	s32i	a11, a8, 4
1014bedea94SChris Zankel	l32i	a10, a7, 8
1024bedea94SChris Zankel	l32i	a11, a7, 12
1034bedea94SChris Zankel	s32i	a10, a8, 8
1044bedea94SChris Zankel	s32i	a11, a8, 12
1054bedea94SChris Zankel	addi	a8, a8, 16
1064bedea94SChris Zankel	addi	a7, a7, 16
1074bedea94SChris Zankel	blt	a8, a5, 1b
1084bedea94SChris Zankel
1094bedea94SChris Zankel
1104bedea94SChris Zankel	/* We have to flush and invalidate the caches here before we jump. */
1114bedea94SChris Zankel
1124bedea94SChris Zankel#if XCHAL_DCACHE_IS_WRITEBACK
113173d6681SChris Zankel
114173d6681SChris Zankel	___flush_dcache_all a5 a6
115173d6681SChris Zankel
1164bedea94SChris Zankel#endif
117173d6681SChris Zankel
118173d6681SChris Zankel	___invalidate_icache_all a5 a6
119173d6681SChris Zankel	isync
1204bedea94SChris Zankel
1214bedea94SChris Zankel	movi	a11, _reloc
1224bedea94SChris Zankel	jx	a11
1234bedea94SChris Zankel
1244bedea94SChris Zankel	.globl _reloc
1254bedea94SChris Zankel_reloc:
1264bedea94SChris Zankel
1274bedea94SChris Zankel	/* RedBoot is now at the end of the memory, so we don't have
1284bedea94SChris Zankel	 * to copy the parameter list. Keep the code around; in case
1294bedea94SChris Zankel	 * we need it again. */
1304bedea94SChris Zankel#if 0
1314bedea94SChris Zankel	# a0: load address
1324bedea94SChris Zankel	# a2: start address of parameter list
1334bedea94SChris Zankel	# a3: length of parameter list
1344bedea94SChris Zankel	# a4: __start
1354bedea94SChris Zankel
1364bedea94SChris Zankel	/* copy the parameter list out of the way */
1374bedea94SChris Zankel
1384bedea94SChris Zankel	movi	a6, _param_start
1394bedea94SChris Zankel	add	a3, a2, a3
1404bedea94SChris Zankel2:
1414bedea94SChris Zankel	l32i	a8, a2, 0
1424bedea94SChris Zankel	s32i	a8, a6, 0
1434bedea94SChris Zankel	addi	a2, a2, 4
1444bedea94SChris Zankel	addi	a6, a6, 4
1454bedea94SChris Zankel	blt	a2, a3, 2b
1464bedea94SChris Zankel#endif
1474bedea94SChris Zankel
1484bedea94SChris Zankel	/* clear BSS section */
1494bedea94SChris Zankel	movi	a6, __bss_start
1504bedea94SChris Zankel	movi	a7, __bss_end
1514bedea94SChris Zankel	movi.n	a5, 0
1524bedea94SChris Zankel3:
1534bedea94SChris Zankel	s32i	a5, a6, 0
1544bedea94SChris Zankel	addi	a6, a6, 4
1554bedea94SChris Zankel	blt	a6, a7, 3b
1564bedea94SChris Zankel
1574bedea94SChris Zankel	movi	a5, -16
1584bedea94SChris Zankel	movi	a1, _stack + STACK_SIZE
1594bedea94SChris Zankel	and	a1, a1, a5
1604bedea94SChris Zankel
1614bedea94SChris Zankel	/* Uncompress the kernel */
1624bedea94SChris Zankel
1634bedea94SChris Zankel	# a0: load address
1644bedea94SChris Zankel	# a2: boot parameter
1654bedea94SChris Zankel	# a4: __start
1664bedea94SChris Zankel
1674bedea94SChris Zankel	movi	a3, __image_load
1684bedea94SChris Zankel	sub	a4, a3, a4
1694bedea94SChris Zankel	add	a8, a0, a4
1704bedea94SChris Zankel
1714bedea94SChris Zankel	# a1  Stack
1724bedea94SChris Zankel	# a8(a4)  Load address of the image
1734bedea94SChris Zankel
1744bedea94SChris Zankel	movi	a6, _image_start
1754bedea94SChris Zankel	movi	a10, _image_end
1764bedea94SChris Zankel	movi	a7, 0x1000000
1774bedea94SChris Zankel	sub	a11, a10, a6
1784bedea94SChris Zankel	movi	a9, complen
1794bedea94SChris Zankel	s32i	a11, a9, 0
1804bedea94SChris Zankel
1814bedea94SChris Zankel	movi	a0, 0
1824bedea94SChris Zankel
1834bedea94SChris Zankel	# a6 destination
1844bedea94SChris Zankel	# a7 maximum size of destination
1854bedea94SChris Zankel	# a8 source
1864bedea94SChris Zankel	# a9 ptr to length
1874bedea94SChris Zankel
1884bedea94SChris Zankel	.extern gunzip
1894bedea94SChris Zankel	movi	a4, gunzip
1904bedea94SChris Zankel	beqz	a4, 1f
1914bedea94SChris Zankel
1924bedea94SChris Zankel	callx4	a4
1934bedea94SChris Zankel
1944bedea94SChris Zankel	j	2f
1954bedea94SChris Zankel
1964bedea94SChris Zankel
1974bedea94SChris Zankel	# a6 destination start
1984bedea94SChris Zankel	# a7 maximum size of destination
1994bedea94SChris Zankel	# a8 source start
2004bedea94SChris Zankel	# a9 ptr to length
2014bedea94SChris Zankel	# a10 destination end
2024bedea94SChris Zankel
2034bedea94SChris Zankel1:
2044bedea94SChris Zankel        l32i    a9, a8, 0
2054bedea94SChris Zankel        l32i    a11, a8, 4
2064bedea94SChris Zankel        s32i    a9, a6, 0
2074bedea94SChris Zankel        s32i    a11, a6, 4
2084bedea94SChris Zankel        l32i    a9, a8, 8
2094bedea94SChris Zankel        l32i    a11, a8, 12
2104bedea94SChris Zankel        s32i    a9, a6, 8
2114bedea94SChris Zankel        s32i    a11, a6, 12
2124bedea94SChris Zankel        addi    a6, a6, 16
2134bedea94SChris Zankel        addi    a8, a8, 16
2144bedea94SChris Zankel        blt     a6, a10, 1b
2154bedea94SChris Zankel
2164bedea94SChris Zankel
2174bedea94SChris Zankel	/* jump to the kernel */
2184bedea94SChris Zankel2:
2194bedea94SChris Zankel#if XCHAL_DCACHE_IS_WRITEBACK
220173d6681SChris Zankel
221173d6681SChris Zankel	___flush_dcache_all a5 a6
222173d6681SChris Zankel
2234bedea94SChris Zankel#endif
224173d6681SChris Zankel
225173d6681SChris Zankel	___invalidate_icache_all a5 a6
226173d6681SChris Zankel
227173d6681SChris Zankel	isync
2284bedea94SChris Zankel
2294bedea94SChris Zankel	# a2  Boot parameter list
2304bedea94SChris Zankel
2314bedea94SChris Zankel	movi	a0, _image_start
2324bedea94SChris Zankel	jx	a0
2334bedea94SChris Zankel
2344bedea94SChris Zankel	.align 16
2354bedea94SChris Zankel	.data
2364bedea94SChris Zankel	.globl avail_ram
2374bedea94SChris Zankelavail_ram:
2384bedea94SChris Zankel	.long	_heap
2394bedea94SChris Zankel	.globl end_avail
2404bedea94SChris Zankelend_avail:
2414bedea94SChris Zankel	.long	_heap + HEAP_SIZE
2424bedea94SChris Zankel
2434bedea94SChris Zankel	.comm _stack, STACK_SIZE
2444bedea94SChris Zankel	.comm _heap, HEAP_SIZE
2454bedea94SChris Zankel
2464bedea94SChris Zankel	.globl end_avail
2474bedea94SChris Zankel	.comm complen, 4
2484bedea94SChris Zankel
2494bedea94SChris Zankel	.end	literal_prefix
250