Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / x86 / lib / spl.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2016 Google, Inc
4  */
5
6 #include <common.h>
7 #include <cpu_func.h>
8 #include <debug_uart.h>
9 #include <dm.h>
10 #include <hang.h>
11 #include <image.h>
12 #include <init.h>
13 #include <irq_func.h>
14 #include <log.h>
15 #include <malloc.h>
16 #include <spl.h>
17 #include <syscon.h>
18 #include <asm/cpu.h>
19 #include <asm/cpu_common.h>
20 #include <asm/mrccache.h>
21 #include <asm/mtrr.h>
22 #include <asm/pci.h>
23 #include <asm/processor.h>
24 #include <asm/spl.h>
25 #include <asm-generic/sections.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 __weak int arch_cpu_init_dm(void)
30 {
31         return 0;
32 }
33
34 #ifdef CONFIG_TPL
35
36 static int set_max_freq(void)
37 {
38         if (cpu_get_burst_mode_state() == BURST_MODE_UNAVAILABLE) {
39                 /*
40                  * Burst Mode has been factory-configured as disabled and is not
41                  * available in this physical processor package
42                  */
43                 debug("Burst Mode is factory-disabled\n");
44                 return -ENOENT;
45         }
46
47         /* Enable burst mode */
48         cpu_set_burst_mode(true);
49
50         /* Enable speed step */
51         cpu_set_eist(true);
52
53         /* Set P-State ratio */
54         cpu_set_p_state_to_turbo_ratio();
55
56         return 0;
57 }
58 #endif
59
60 static int x86_spl_init(void)
61 {
62 #ifndef CONFIG_TPL
63         /*
64          * TODO(sjg@chromium.org): We use this area of RAM for the stack
65          * and global_data in SPL. Once U-Boot starts up and releocates it
66          * is not needed. We could make this a CONFIG option or perhaps
67          * place it immediately below CONFIG_SYS_TEXT_BASE.
68          */
69         __maybe_unused char *ptr = (char *)0x110000;
70 #else
71         struct udevice *punit;
72 #endif
73         int ret;
74
75         debug("%s starting\n", __func__);
76         if (IS_ENABLED(TPL))
77                 ret = x86_cpu_reinit_f();
78         else
79                 ret = x86_cpu_init_f();
80         ret = spl_init();
81         if (ret) {
82                 debug("%s: spl_init() failed\n", __func__);
83                 return ret;
84         }
85         ret = arch_cpu_init();
86         if (ret) {
87                 debug("%s: arch_cpu_init() failed\n", __func__);
88                 return ret;
89         }
90 #ifndef CONFIG_TPL
91         ret = arch_cpu_init_dm();
92         if (ret) {
93                 debug("%s: arch_cpu_init_dm() failed\n", __func__);
94                 return ret;
95         }
96 #endif
97         preloader_console_init();
98 #ifndef CONFIG_TPL
99         ret = print_cpuinfo();
100         if (ret) {
101                 debug("%s: print_cpuinfo() failed\n", __func__);
102                 return ret;
103         }
104 #endif
105         ret = dram_init();
106         if (ret) {
107                 debug("%s: dram_init() failed\n", __func__);
108                 return ret;
109         }
110         if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
111                 ret = mrccache_spl_save();
112                 if (ret)
113                         debug("%s: Failed to write to mrccache (err=%d)\n",
114                               __func__, ret);
115         }
116
117 #ifndef CONFIG_SYS_COREBOOT
118 # ifndef CONFIG_TPL
119         memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
120
121         /* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */
122         ret = interrupt_init();
123         if (ret) {
124                 debug("%s: interrupt_init() failed\n", __func__);
125                 return ret;
126         }
127
128         /*
129          * The stack grows down from ptr. Put the global data at ptr. This
130          * will only be used for SPL. Once SPL loads U-Boot proper it will
131          * set up its own stack.
132          */
133         gd->new_gd = (struct global_data *)ptr;
134         memcpy(gd->new_gd, gd, sizeof(*gd));
135         arch_setup_gd(gd->new_gd);
136         gd->start_addr_sp = (ulong)ptr;
137
138         /* Cache the SPI flash. Otherwise copying the code to RAM takes ages */
139         ret = mtrr_add_request(MTRR_TYPE_WRBACK,
140                                (1ULL << 32) - CONFIG_XIP_ROM_SIZE,
141                                CONFIG_XIP_ROM_SIZE);
142         if (ret) {
143                 debug("%s: SPI cache setup failed (err=%d)\n", __func__, ret);
144                 return ret;
145         }
146         mtrr_commit(true);
147 # else
148         ret = syscon_get_by_driver_data(X86_SYSCON_PUNIT, &punit);
149         if (ret)
150                 debug("Could not find PUNIT (err=%d)\n", ret);
151
152         ret = set_max_freq();
153         if (ret)
154                 debug("Failed to set CPU frequency (err=%d)\n", ret);
155 # endif
156 #endif
157
158         return 0;
159 }
160
161 void board_init_f(ulong flags)
162 {
163         int ret;
164
165         ret = x86_spl_init();
166         if (ret) {
167                 printf("x86_spl_init: error %d\n", ret);
168                 hang();
169         }
170 #if IS_ENABLED(CONFIG_TPL) || IS_ENABLED(CONFIG_SYS_COREBOOT)
171         gd->bd = malloc(sizeof(*gd->bd));
172         if (!gd->bd) {
173                 printf("Out of memory for bd_info size %x\n", sizeof(*gd->bd));
174                 hang();
175         }
176         board_init_r(gd, 0);
177 #else
178         /* Uninit CAR and jump to board_init_f_r() */
179         board_init_f_r_trampoline(gd->start_addr_sp);
180 #endif
181 }
182
183 void board_init_f_r(void)
184 {
185         init_cache_f_r();
186         gd->flags &= ~GD_FLG_SERIAL_READY;
187         debug("cache status %d\n", dcache_status());
188         board_init_r(gd, 0);
189 }
190
191 u32 spl_boot_device(void)
192 {
193         return BOOT_DEVICE_SPI_MMAP;
194 }
195
196 int spl_start_uboot(void)
197 {
198         return 0;
199 }
200
201 void spl_board_announce_boot_device(void)
202 {
203         printf("SPI flash");
204 }
205
206 static int spl_board_load_image(struct spl_image_info *spl_image,
207                                 struct spl_boot_device *bootdev)
208 {
209         spl_image->size = CONFIG_SYS_MONITOR_LEN;
210         spl_image->entry_point = CONFIG_SYS_TEXT_BASE;
211         spl_image->load_addr = CONFIG_SYS_TEXT_BASE;
212         spl_image->os = IH_OS_U_BOOT;
213         spl_image->name = "U-Boot";
214
215         if (!IS_ENABLED(CONFIG_SYS_COREBOOT)) {
216                 /*
217                  * Copy U-Boot from ROM
218                  * TODO(sjg@chromium.org): Figure out a way to get the text base
219                  * correctly here, and in the device-tree binman definition.
220                  *
221                  * Also consider using FIT so we get the correct image length
222                  * and parameters.
223                  */
224                 memcpy((char *)spl_image->load_addr, (char *)0xfff00000,
225                        0x100000);
226         }
227
228         debug("Loading to %lx\n", spl_image->load_addr);
229
230         return 0;
231 }
232 SPL_LOAD_IMAGE_METHOD("SPI", 5, BOOT_DEVICE_SPI_MMAP, spl_board_load_image);
233
234 int spl_spi_load_image(void)
235 {
236         return -EPERM;
237 }
238
239 #ifdef CONFIG_X86_RUN_64BIT
240 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
241 {
242         int ret;
243
244         printf("Jumping to 64-bit U-Boot: Note many features are missing\n");
245         ret = cpu_jump_to_64bit_uboot(spl_image->entry_point);
246         debug("ret=%d\n", ret);
247         hang();
248 }
249 #endif
250
251 void spl_board_init(void)
252 {
253 #ifndef CONFIG_TPL
254         preloader_console_init();
255 #endif
256 }