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 22b66babdaSAlexander Graf __weak void board_quiesce_devices(void) 23b66babdaSAlexander Graf { 24b66babdaSAlexander Graf } 25b66babdaSAlexander Graf 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 */ 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 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 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 89c3b1a990SLukas Auer debug("## Transferring control to Linux (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) 96*3c85099aSBin Meng kernel(gd->arch.boot_hart, images->ft_addr); 97c3b1a990SLukas Auer } 98c3b1a990SLukas Auer } 9922b7e6fbSRick Chen 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