Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2011 Andes Technology Corporation * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> * Rick Chen, Andes Technology Corporation <rick@andestech.com> */ #include <common.h> #include <bootstage.h> #include <command.h> #include <dm.h> #include <fdt_support.h> #include <hang.h> #include <log.h> #include <asm/global_data.h> #include <dm/root.h> #include <image.h> #include <asm/byteorder.h> #include <asm/csr.h> #include <asm/smp.h> #include <dm/device.h> #include <dm/root.h> #include <u-boot/zlib.h> DECLARE_GLOBAL_DATA_PTR; __weak void board_quiesce_devices(void) { } /** * announce_and_cleanup() - Print message and prepare for kernel boot * * @fake: non-zero to do everything except actually boot */ static void announce_and_cleanup(int fake) { printf("\nStarting kernel ...%s\n\n", fake ? "(fake run for tracing)" : ""); bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); #ifdef CONFIG_BOOTSTAGE_FDT bootstage_fdt_add_report(); #endif #ifdef CONFIG_BOOTSTAGE_REPORT bootstage_report(); #endif #ifdef CONFIG_USB_DEVICE udc_disconnect(); #endif board_quiesce_devices(); /* * Call remove function of all devices with a removal flag set. * This may be useful for last-stage operations, like cancelling * of DMA operation or releasing device internal buffers. */ dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); cleanup_before_linux(); } static void boot_prep_linux(struct bootm_headers *images) { if (CONFIG_IS_ENABLED(OF_LIBFDT) && CONFIG_IS_ENABLED(LMB) && images->ft_len) { debug("using: FDT\n"); if (image_setup_linux(images)) { printf("FDT creation failed! hanging..."); hang(); } } else { printf("Device tree not found or missing FDT support\n"); hang(); } } static void boot_jump_linux(struct bootm_headers *images, int flag) { void (*kernel)(ulong hart, void *dtb); int fake = (flag & BOOTM_STATE_OS_FAKE_GO); #ifdef CONFIG_SMP int ret; #endif kernel = (void (*)(ulong, void *))images->ep; bootstage_mark(BOOTSTAGE_ID_RUN_OS); debug("## Transferring control to kernel (at address %08lx) ...\n", (ulong)kernel); announce_and_cleanup(fake); if (!fake) { if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) { #ifdef CONFIG_SMP ret = smp_call_function(images->ep, (ulong)images->ft_addr, 0, 0); if (ret) hang(); #endif kernel(gd->arch.boot_hart, images->ft_addr); } } } int do_bootm_linux(int flag, int argc, char *const argv[], struct bootm_headers *images) { /* No need for those on RISC-V */ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) return -1; if (flag & BOOTM_STATE_OS_PREP) { boot_prep_linux(images); return 0; } if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { boot_jump_linux(images, flag); return 0; } boot_prep_linux(images); boot_jump_linux(images, flag); return 0; } int do_bootm_vxworks(int flag, int argc, char *const argv[], struct bootm_headers *images) { return do_bootm_linux(flag, argc, argv, images); } static ulong get_sp(void) { ulong ret; asm("mv %0, sp" : "=r"(ret) : ); return ret; } void arch_lmb_reserve(struct lmb *lmb) { arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096); } |