xref: /openbmc/u-boot/arch/riscv/lib/bootm.c (revision 7e40d0a3)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
28bbb2909SRick Chen /*
38bbb2909SRick Chen  * Copyright (C) 2011 Andes Technology Corporation
48bbb2909SRick Chen  * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
58bbb2909SRick Chen  * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
68bbb2909SRick Chen  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
78bbb2909SRick Chen  */
88bbb2909SRick Chen 
98bbb2909SRick Chen #include <common.h>
108bbb2909SRick Chen #include <command.h>
11c3b1a990SLukas Auer #include <dm.h>
12c3b1a990SLukas Auer #include <dm/root.h>
138bbb2909SRick Chen #include <image.h>
148bbb2909SRick Chen #include <asm/byteorder.h>
15ed49ba4dSBin Meng #include <asm/csr.h>
16b1893a9eSBin Meng #include <dm/device.h>
17b1893a9eSBin Meng #include <dm/root.h>
18b1893a9eSBin Meng #include <u-boot/zlib.h>
198bbb2909SRick Chen 
208bbb2909SRick Chen DECLARE_GLOBAL_DATA_PTR;
218bbb2909SRick Chen 
board_quiesce_devices(void)22b66babdaSAlexander Graf __weak void board_quiesce_devices(void)
23b66babdaSAlexander Graf {
24b66babdaSAlexander Graf }
25b66babdaSAlexander Graf 
arch_fixup_fdt(void * blob)268bbb2909SRick Chen int arch_fixup_fdt(void *blob)
278bbb2909SRick Chen {
288bbb2909SRick Chen 	return 0;
298bbb2909SRick Chen }
308bbb2909SRick Chen 
31c3b1a990SLukas Auer /**
32c3b1a990SLukas Auer  * announce_and_cleanup() - Print message and prepare for kernel boot
33c3b1a990SLukas Auer  *
34c3b1a990SLukas Auer  * @fake: non-zero to do everything except actually boot
358bbb2909SRick Chen  */
announce_and_cleanup(int fake)36c3b1a990SLukas Auer static void announce_and_cleanup(int fake)
37c3b1a990SLukas Auer {
38c3b1a990SLukas Auer 	printf("\nStarting kernel ...%s\n\n", fake ?
39c3b1a990SLukas Auer 		"(fake run for tracing)" : "");
40c3b1a990SLukas Auer 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
41c3b1a990SLukas Auer #ifdef CONFIG_BOOTSTAGE_FDT
42c3b1a990SLukas Auer 	bootstage_fdt_add_report();
438bbb2909SRick Chen #endif
44c3b1a990SLukas Auer #ifdef CONFIG_BOOTSTAGE_REPORT
45c3b1a990SLukas Auer 	bootstage_report();
46c3b1a990SLukas Auer #endif
478bbb2909SRick Chen 
48c3b1a990SLukas Auer #ifdef CONFIG_USB_DEVICE
49c3b1a990SLukas Auer 	udc_disconnect();
50c3b1a990SLukas Auer #endif
51c3b1a990SLukas Auer 
52c3b1a990SLukas Auer 	board_quiesce_devices();
538bbb2909SRick Chen 
54b1893a9eSBin Meng 	/*
55b1893a9eSBin Meng 	 * Call remove function of all devices with a removal flag set.
56b1893a9eSBin Meng 	 * This may be useful for last-stage operations, like cancelling
57b1893a9eSBin Meng 	 * of DMA operation or releasing device internal buffers.
58b1893a9eSBin Meng 	 */
59b1893a9eSBin Meng 	dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
60b1893a9eSBin Meng 
618bbb2909SRick Chen 	cleanup_before_linux();
62c3b1a990SLukas Auer }
63ed49ba4dSBin Meng 
boot_prep_linux(bootm_headers_t * images)64c3b1a990SLukas Auer static void boot_prep_linux(bootm_headers_t *images)
65c3b1a990SLukas Auer {
66c3b1a990SLukas Auer 	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
67c3b1a990SLukas Auer #ifdef CONFIG_OF_LIBFDT
68c3b1a990SLukas Auer 		debug("using: FDT\n");
69c3b1a990SLukas Auer 		if (image_setup_linux(images)) {
70c3b1a990SLukas Auer 			printf("FDT creation failed! hanging...");
71c3b1a990SLukas Auer 			hang();
72c3b1a990SLukas Auer 		}
73c3b1a990SLukas Auer #endif
74c3b1a990SLukas Auer 	} else {
75c3b1a990SLukas Auer 		printf("Device tree not found or missing FDT support\n");
76c3b1a990SLukas Auer 		hang();
77c3b1a990SLukas Auer 	}
78c3b1a990SLukas Auer }
79c3b1a990SLukas Auer 
boot_jump_linux(bootm_headers_t * images,int flag)80c3b1a990SLukas Auer static void boot_jump_linux(bootm_headers_t *images, int flag)
81c3b1a990SLukas Auer {
82c3b1a990SLukas Auer 	void (*kernel)(ulong hart, void *dtb);
83c3b1a990SLukas Auer 	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
84c3b1a990SLukas Auer 
85c3b1a990SLukas Auer 	kernel = (void (*)(ulong, void *))images->ep;
86c3b1a990SLukas Auer 
87c3b1a990SLukas Auer 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
88c3b1a990SLukas Auer 
89*08337cd6SBin Meng 	debug("## Transferring control to kernel (at address %08lx) ...\n",
90c3b1a990SLukas Auer 	      (ulong)kernel);
91c3b1a990SLukas Auer 
92c3b1a990SLukas Auer 	announce_and_cleanup(fake);
93c3b1a990SLukas Auer 
94c3b1a990SLukas Auer 	if (!fake) {
958bbb2909SRick Chen 		if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
963c85099aSBin Meng 			kernel(gd->arch.boot_hart, images->ft_addr);
97c3b1a990SLukas Auer 	}
98c3b1a990SLukas Auer }
9922b7e6fbSRick Chen 
do_bootm_linux(int flag,int argc,char * const argv[],bootm_headers_t * images)100c3b1a990SLukas Auer int do_bootm_linux(int flag, int argc, char * const argv[],
101c3b1a990SLukas Auer 		   bootm_headers_t *images)
102c3b1a990SLukas Auer {
103c3b1a990SLukas Auer 	/* No need for those on RISC-V */
104c3b1a990SLukas Auer 	if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
105c3b1a990SLukas Auer 		return -1;
1068bbb2909SRick Chen 
107c3b1a990SLukas Auer 	if (flag & BOOTM_STATE_OS_PREP) {
108c3b1a990SLukas Auer 		boot_prep_linux(images);
109c3b1a990SLukas Auer 		return 0;
110c3b1a990SLukas Auer 	}
111c3b1a990SLukas Auer 
112c3b1a990SLukas Auer 	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
113c3b1a990SLukas Auer 		boot_jump_linux(images, flag);
114c3b1a990SLukas Auer 		return 0;
115c3b1a990SLukas Auer 	}
116c3b1a990SLukas Auer 
117c3b1a990SLukas Auer 	boot_prep_linux(images);
118c3b1a990SLukas Auer 	boot_jump_linux(images, flag);
119c3b1a990SLukas Auer 	return 0;
1208bbb2909SRick Chen }
121*08337cd6SBin Meng 
do_bootm_vxworks(int flag,int argc,char * const argv[],bootm_headers_t * images)122*08337cd6SBin Meng int do_bootm_vxworks(int flag, int argc, char * const argv[],
123*08337cd6SBin Meng 		     bootm_headers_t *images)
124*08337cd6SBin Meng {
125*08337cd6SBin Meng 	return do_bootm_linux(flag, argc, argv, images);
126*08337cd6SBin Meng }
127