xref: /rk3399_rockchip-uboot/arch/arc/lib/bootm.c (revision f05ce84792cbd2e5573a414010d421eb8fbb7689)
122723828SAlexey Brodkin /*
222723828SAlexey Brodkin  * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
322723828SAlexey Brodkin  *
422723828SAlexey Brodkin  * SPDX-License-Identifier:	GPL-2.0+
522723828SAlexey Brodkin  */
622723828SAlexey Brodkin 
722723828SAlexey Brodkin #include <common.h>
822723828SAlexey Brodkin 
922723828SAlexey Brodkin DECLARE_GLOBAL_DATA_PTR;
1022723828SAlexey Brodkin 
get_sp(void)1122723828SAlexey Brodkin static ulong get_sp(void)
1222723828SAlexey Brodkin {
1322723828SAlexey Brodkin 	ulong ret;
1422723828SAlexey Brodkin 
1522723828SAlexey Brodkin 	asm("mov %0, sp" : "=r"(ret) : );
1622723828SAlexey Brodkin 	return ret;
1722723828SAlexey Brodkin }
1822723828SAlexey Brodkin 
arch_lmb_reserve(struct lmb * lmb)1922723828SAlexey Brodkin void arch_lmb_reserve(struct lmb *lmb)
2022723828SAlexey Brodkin {
2122723828SAlexey Brodkin 	ulong sp;
2222723828SAlexey Brodkin 
2322723828SAlexey Brodkin 	/*
2422723828SAlexey Brodkin 	 * Booting a (Linux) kernel image
2522723828SAlexey Brodkin 	 *
2622723828SAlexey Brodkin 	 * Allocate space for command line and board info - the
2722723828SAlexey Brodkin 	 * address should be as high as possible within the reach of
2822723828SAlexey Brodkin 	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
2922723828SAlexey Brodkin 	 * memory, which means far enough below the current stack
3022723828SAlexey Brodkin 	 * pointer.
3122723828SAlexey Brodkin 	 */
3222723828SAlexey Brodkin 	sp = get_sp();
3322723828SAlexey Brodkin 	debug("## Current stack ends at 0x%08lx ", sp);
3422723828SAlexey Brodkin 
3522723828SAlexey Brodkin 	/* adjust sp by 4K to be safe */
3622723828SAlexey Brodkin 	sp -= 4096;
3722723828SAlexey Brodkin 	lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp));
3822723828SAlexey Brodkin }
3922723828SAlexey Brodkin 
cleanup_before_linux(void)4022723828SAlexey Brodkin static int cleanup_before_linux(void)
4122723828SAlexey Brodkin {
4222723828SAlexey Brodkin 	disable_interrupts();
4322723828SAlexey Brodkin 	flush_dcache_all();
4422723828SAlexey Brodkin 	invalidate_icache_all();
4522723828SAlexey Brodkin 
4622723828SAlexey Brodkin 	return 0;
4722723828SAlexey Brodkin }
4822723828SAlexey Brodkin 
4922723828SAlexey Brodkin /* Subcommand: PREP */
boot_prep_linux(bootm_headers_t * images)5022723828SAlexey Brodkin static void boot_prep_linux(bootm_headers_t *images)
5122723828SAlexey Brodkin {
5222723828SAlexey Brodkin 	if (image_setup_linux(images))
5322723828SAlexey Brodkin 		hang();
5422723828SAlexey Brodkin }
5522723828SAlexey Brodkin 
smp_set_core_boot_addr(unsigned long addr,int corenr)568b2eb776SAlexey Brodkin __weak void smp_set_core_boot_addr(unsigned long addr, int corenr) {}
smp_kick_all_cpus(void)578b2eb776SAlexey Brodkin __weak void smp_kick_all_cpus(void) {}
588b2eb776SAlexey Brodkin 
5922723828SAlexey Brodkin /* Subcommand: GO */
boot_jump_linux(bootm_headers_t * images,int flag)6022723828SAlexey Brodkin static void boot_jump_linux(bootm_headers_t *images, int flag)
6122723828SAlexey Brodkin {
6222723828SAlexey Brodkin 	void (*kernel_entry)(int zero, int arch, uint params);
6322723828SAlexey Brodkin 	unsigned int r0, r2;
6422723828SAlexey Brodkin 	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
6522723828SAlexey Brodkin 
6622723828SAlexey Brodkin 	kernel_entry = (void (*)(int, int, uint))images->ep;
6722723828SAlexey Brodkin 
6822723828SAlexey Brodkin 	debug("## Transferring control to Linux (at address %08lx)...\n",
6922723828SAlexey Brodkin 	      (ulong) kernel_entry);
7022723828SAlexey Brodkin 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
7122723828SAlexey Brodkin 
7222723828SAlexey Brodkin 	printf("\nStarting kernel ...%s\n\n", fake ?
7322723828SAlexey Brodkin 	       "(fake run for tracing)" : "");
7422723828SAlexey Brodkin 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
7522723828SAlexey Brodkin 
7622723828SAlexey Brodkin 	cleanup_before_linux();
7722723828SAlexey Brodkin 
7822723828SAlexey Brodkin 	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
7922723828SAlexey Brodkin 		r0 = 2;
8022723828SAlexey Brodkin 		r2 = (unsigned int)images->ft_addr;
8122723828SAlexey Brodkin 	} else {
8222723828SAlexey Brodkin 		r0 = 1;
83*00caae6dSSimon Glass 		r2 = (unsigned int)env_get("bootargs");
8422723828SAlexey Brodkin 	}
8522723828SAlexey Brodkin 
868b2eb776SAlexey Brodkin 	smp_set_core_boot_addr((unsigned long)kernel_entry, -1);
878b2eb776SAlexey Brodkin 	smp_kick_all_cpus();
888b2eb776SAlexey Brodkin 
8922723828SAlexey Brodkin 	if (!fake)
9022723828SAlexey Brodkin 		kernel_entry(r0, 0, r2);
9122723828SAlexey Brodkin }
9222723828SAlexey Brodkin 
do_bootm_linux(int flag,int argc,char * argv[],bootm_headers_t * images)9322723828SAlexey Brodkin int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
9422723828SAlexey Brodkin {
9522723828SAlexey Brodkin 	/* No need for those on ARC */
9622723828SAlexey Brodkin 	if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE))
9722723828SAlexey Brodkin 		return -1;
9822723828SAlexey Brodkin 
9922723828SAlexey Brodkin 	if (flag & BOOTM_STATE_OS_PREP) {
10022723828SAlexey Brodkin 		boot_prep_linux(images);
10122723828SAlexey Brodkin 		return 0;
10222723828SAlexey Brodkin 	}
10322723828SAlexey Brodkin 
10422723828SAlexey Brodkin 	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
10522723828SAlexey Brodkin 		boot_jump_linux(images, flag);
10622723828SAlexey Brodkin 		return 0;
10722723828SAlexey Brodkin 	}
10822723828SAlexey Brodkin 
10922723828SAlexey Brodkin 	boot_prep_linux(images);
11022723828SAlexey Brodkin 	boot_jump_linux(images, flag);
11122723828SAlexey Brodkin 	return 0;
11222723828SAlexey Brodkin }
113