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