]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
507bbe3e | 2 | /* |
cfc67116 | 3 | * (C) Copyright 2007 Michal Simek |
507bbe3e WD |
4 | * (C) Copyright 2004 Atmark Techno, Inc. |
5 | * | |
cfc67116 | 6 | * Michal SIMEK <monstr@monstr.eu> |
507bbe3e | 7 | * Yasushi SHOJI <yashi@atmark-techno.com> |
507bbe3e WD |
8 | */ |
9 | ||
10 | #include <common.h> | |
52f24238 | 11 | #include <bootstage.h> |
507bbe3e | 12 | #include <command.h> |
1eb69ae4 | 13 | #include <cpu_func.h> |
7b51b576 | 14 | #include <env.h> |
73223f0e | 15 | #include <fdt_support.h> |
db41d65a | 16 | #include <hang.h> |
cfc67116 | 17 | #include <image.h> |
4d72caa5 | 18 | #include <lmb.h> |
90526e9f | 19 | #include <asm/cache.h> |
a31e091a | 20 | #include <u-boot/zlib.h> |
cfc67116 | 21 | #include <asm/byteorder.h> |
507bbe3e | 22 | |
6131a36b MS |
23 | DECLARE_GLOBAL_DATA_PTR; |
24 | ||
25 | static ulong get_sp(void) | |
26 | { | |
27 | ulong ret; | |
28 | ||
29 | asm("addik %0, r1, 0" : "=r"(ret) : ); | |
30 | return ret; | |
31 | } | |
32 | ||
33 | void arch_lmb_reserve(struct lmb *lmb) | |
34 | { | |
35 | ulong sp, bank_end; | |
36 | int bank; | |
37 | ||
38 | /* | |
39 | * Booting a (Linux) kernel image | |
40 | * | |
41 | * Allocate space for command line and board info - the | |
42 | * address should be as high as possible within the reach of | |
43 | * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused | |
44 | * memory, which means far enough below the current stack | |
45 | * pointer. | |
46 | */ | |
47 | sp = get_sp(); | |
48 | debug("## Current stack ends at 0x%08lx ", sp); | |
49 | ||
50 | /* adjust sp by 4K to be safe */ | |
51 | sp -= 4096; | |
52 | for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { | |
53 | if (sp < gd->bd->bi_dram[bank].start) | |
54 | continue; | |
55 | bank_end = gd->bd->bi_dram[bank].start + | |
56 | gd->bd->bi_dram[bank].size; | |
57 | if (sp >= bank_end) | |
58 | continue; | |
59 | lmb_reserve(lmb, sp, bank_end - sp); | |
60 | break; | |
61 | } | |
62 | } | |
63 | ||
09050460 | 64 | static void boot_jump_linux(bootm_headers_t *images, int flag) |
507bbe3e | 65 | { |
09050460 MS |
66 | void (*thekernel)(char *cmdline, ulong rd, ulong dt); |
67 | ulong dt = (ulong)images->ft_addr; | |
68 | ulong rd_start = images->initrd_start; | |
69 | ulong cmdline = images->cmdline_start; | |
70 | int fake = (flag & BOOTM_STATE_OS_FAKE_GO); | |
398b1d57 | 71 | |
1e71fa43 | 72 | thekernel = (void (*)(char *, ulong, ulong))images->ep; |
398b1d57 | 73 | |
f3035cf2 MS |
74 | debug("## Transferring control to Linux (at address 0x%08lx) ", |
75 | (ulong)thekernel); | |
76 | debug("cmdline 0x%08lx, ramdisk 0x%08lx, FDT 0x%08lx...\n", | |
77 | cmdline, rd_start, dt); | |
78 | bootstage_mark(BOOTSTAGE_ID_RUN_OS); | |
79 | ||
80 | printf("\nStarting kernel ...%s\n\n", fake ? | |
81 | "(fake run for tracing)" : ""); | |
82 | bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); | |
cfc67116 | 83 | |
9b4d9056 | 84 | #ifdef XILINX_USE_DCACHE |
9b4d9056 | 85 | flush_cache(0, XILINX_DCACHE_BYTE_SIZE); |
9b4d9056 | 86 | #endif |
a3a08c0c | 87 | |
09050460 MS |
88 | if (!fake) { |
89 | /* | |
90 | * Linux Kernel Parameters (passing device tree): | |
91 | * r5: pointer to command line | |
92 | * r6: pointer to ramdisk | |
93 | * r7: pointer to the fdt, followed by the board info data | |
94 | */ | |
95 | thekernel((char *)cmdline, rd_start, dt); | |
96 | /* does not return */ | |
97 | } | |
98 | } | |
99 | ||
100 | static void boot_prep_linux(bootm_headers_t *images) | |
101 | { | |
102 | if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) { | |
4ab8d632 | 103 | debug("using: FDT\n"); |
09050460 MS |
104 | if (image_setup_linux(images)) { |
105 | printf("FDT creation failed! hanging..."); | |
106 | hang(); | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | int do_bootm_linux(int flag, int argc, char * const argv[], | |
112 | bootm_headers_t *images) | |
113 | { | |
114 | images->cmdline_start = (ulong)env_get("bootargs"); | |
115 | ||
116 | /* cmdline init is the part of 'prep' and nothing to do for 'bdt' */ | |
117 | if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) | |
118 | return -1; | |
119 | ||
120 | if (flag & BOOTM_STATE_OS_PREP) { | |
121 | boot_prep_linux(images); | |
122 | return 0; | |
123 | } | |
124 | ||
125 | if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { | |
126 | boot_jump_linux(images, flag); | |
127 | return 0; | |
128 | } | |
129 | ||
130 | boot_prep_linux(images); | |
131 | boot_jump_linux(images, flag); | |
40d7e99d | 132 | return 1; |
507bbe3e | 133 | } |