blob: dc44bf3ab3ad753b9db7a314676a218ee627ac8d [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marian Balakowicz2437cf22008-01-08 18:11:43 +01002/*
3 * (C) Copyright 2008 Semihalf
4 *
5 * (C) Copyright 2000-2006
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
Marian Balakowicz2437cf22008-01-08 18:11:43 +01007 */
8
Tom Rinidec7ea02024-05-20 13:35:03 -06009#include <config.h>
Simon Glass0726d9d2023-12-15 20:14:13 -070010#include <bootm.h>
Simon Glass1ea97892020-05-10 11:40:00 -060011#include <bootstage.h>
Simon Glass63334482019-11-14 12:57:39 -070012#include <cpu_func.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -060013#include <env.h>
Simon Glass8e16b1e2019-12-28 10:45:05 -070014#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Marian Balakowicz2437cf22008-01-08 18:11:43 +010016#include <watchdog.h>
17#include <command.h>
18#include <image.h>
19#include <malloc.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060020#include <asm/global_data.h>
Jean-Christophe PLAGNIOL-VILLARD6bb94492009-04-04 12:49:11 +020021#include <u-boot/zlib.h>
Marian Balakowicz2437cf22008-01-08 18:11:43 +010022#include <bzlib.h>
Marian Balakowicz2437cf22008-01-08 18:11:43 +010023#include <asm/byteorder.h>
Kumar Gala365024c2011-01-31 15:51:20 -060024#include <asm/mp.h>
Christophe Leroy4a4750b2017-07-13 15:10:08 +020025#include <bootm.h>
26#include <vxworks.h>
Marian Balakowicz2437cf22008-01-08 18:11:43 +010027
28#if defined(CONFIG_OF_LIBFDT)
Masahiro Yamada75f82d02018-03-05 01:20:11 +090029#include <linux/libfdt.h>
Marian Balakowicz2437cf22008-01-08 18:11:43 +010030#include <fdt_support.h>
Wolfgang Denk1e0f07e2009-07-26 23:28:02 +020031#endif
32
33#ifdef CONFIG_SYS_INIT_RAM_LOCK
34#include <asm/cache.h>
Marian Balakowicz2437cf22008-01-08 18:11:43 +010035#endif
36
Marian Balakowicz2437cf22008-01-08 18:11:43 +010037DECLARE_GLOBAL_DATA_PTR;
Marian Balakowicz2437cf22008-01-08 18:11:43 +010038
Miao Yan1bd54562013-11-28 17:51:38 +080039extern void ft_fixup_num_cores(void *blob);
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +090040static void set_clocks_in_mhz (struct bd_info *kbd);
Marian Balakowicz2437cf22008-01-08 18:11:43 +010041
Simon Glassdf00afa2022-09-06 20:26:50 -060042static void boot_jump_linux(struct bootm_headers *images)
Kumar Galaffccb572008-10-21 17:25:46 -050043{
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +090044 void (*kernel)(struct bd_info *, ulong r4, ulong r5, ulong r6,
45 ulong r7, ulong r8, ulong r9);
Kumar Galaffccb572008-10-21 17:25:46 -050046#ifdef CONFIG_OF_LIBFDT
47 char *of_flat_tree = images->ft_addr;
48#endif
49
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +090050 kernel = (void (*)(struct bd_info *, ulong, ulong, ulong,
Kumar Galaffccb572008-10-21 17:25:46 -050051 ulong, ulong, ulong))images->ep;
Simon Glass8f055af2020-05-10 11:40:04 -060052 debug("## Transferring control to Linux (at address %08lx) ...\n",
53 (ulong)kernel);
Kumar Galaffccb572008-10-21 17:25:46 -050054
Simon Glass0169e6b2012-02-13 13:51:18 +000055 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
Kumar Galaffccb572008-10-21 17:25:46 -050056
Mela Custodiobe11d892014-02-20 00:16:57 +090057#ifdef CONFIG_BOOTSTAGE_FDT
58 bootstage_fdt_add_report();
59#endif
60#ifdef CONFIG_BOOTSTAGE_REPORT
61 bootstage_report();
62#endif
63
Wolfgang Denk1e0f07e2009-07-26 23:28:02 +020064#if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
65 unlock_ram_in_cache();
66#endif
67
Kumar Galaffccb572008-10-21 17:25:46 -050068#if defined(CONFIG_OF_LIBFDT)
69 if (of_flat_tree) { /* device tree; boot new style */
70 /*
71 * Linux Kernel Parameters (passing device tree):
72 * r3: pointer to the fdt
73 * r4: 0
74 * r5: 0
75 * r6: epapr magic
76 * r7: size of IMA in bytes
77 * r8: 0
78 * r9: 0
79 */
Simon Glass8f055af2020-05-10 11:40:04 -060080 debug(" Booting using OF flat tree...\n");
Stefan Roese80877fa2022-09-02 14:10:46 +020081 schedule();
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +090082 (*kernel) ((struct bd_info *)of_flat_tree, 0, 0, EPAPR_MAGIC,
Simon Glassda1a1342017-08-03 12:22:15 -060083 env_get_bootm_mapsize(), 0, 0);
Kumar Galaffccb572008-10-21 17:25:46 -050084 /* does not return */
85 } else
86#endif
87 {
88 /*
89 * Linux Kernel Parameters (passing board info data):
90 * r3: ptr to board info data
91 * r4: initrd_start or 0 if no initrd
92 * r5: initrd_end - unused if r4 is 0
93 * r6: Start of command line string
94 * r7: End of command line string
95 * r8: 0
96 * r9: 0
97 */
98 ulong cmd_start = images->cmdline_start;
99 ulong cmd_end = images->cmdline_end;
100 ulong initrd_start = images->initrd_start;
101 ulong initrd_end = images->initrd_end;
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900102 struct bd_info *kbd = images->kbd;
Kumar Galaffccb572008-10-21 17:25:46 -0500103
Simon Glass8f055af2020-05-10 11:40:04 -0600104 debug(" Booting using board info...\n");
Stefan Roese80877fa2022-09-02 14:10:46 +0200105 schedule();
Kumar Galaffccb572008-10-21 17:25:46 -0500106 (*kernel) (kbd, initrd_start, initrd_end,
107 cmd_start, cmd_end, 0, 0);
108 /* does not return */
109 }
Bin Meng75a6a372022-10-26 12:40:07 +0800110 return;
Kumar Galab02d7222008-10-16 21:52:08 -0500111}
112
Simon Glassdf00afa2022-09-06 20:26:50 -0600113static void boot_prep_linux(struct bootm_headers *images)
Kumar Gala180c5812011-12-07 04:42:58 +0000114{
115#ifdef CONFIG_MP
116 /*
117 * if we are MP make sure to flush the device tree so any changes are
118 * made visibile to all other cores. In AMP boot scenarios the cores
119 * might not be HW cache coherent with each other.
120 */
121 flush_cache((unsigned long)images->ft_addr, images->ft_len);
122#endif
123}
124
Simon Glassdf00afa2022-09-06 20:26:50 -0600125static int boot_cmdline_linux(struct bootm_headers *images)
Kumar Galaffccb572008-10-21 17:25:46 -0500126{
Kumar Galaffccb572008-10-21 17:25:46 -0500127 ulong of_size = images->ft_len;
Kumar Galaffccb572008-10-21 17:25:46 -0500128 ulong *cmd_start = &images->cmdline_start;
129 ulong *cmd_end = &images->cmdline_end;
Kumar Galab02d7222008-10-16 21:52:08 -0500130
Kumar Galaffccb572008-10-21 17:25:46 -0500131 int ret = 0;
Kumar Galab02d7222008-10-16 21:52:08 -0500132
Kumar Galaa56d7d52008-02-27 21:51:44 -0600133 if (!of_size) {
134 /* allocate space and init command line */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530135 ret = boot_get_cmdline(cmd_start, cmd_end);
Kumar Galab937bb72008-02-27 21:51:49 -0600136 if (ret) {
137 puts("ERROR with allocation of cmdline\n");
Kumar Galaffccb572008-10-21 17:25:46 -0500138 return ret;
Kumar Galab937bb72008-02-27 21:51:49 -0600139 }
Kumar Galaffccb572008-10-21 17:25:46 -0500140 }
141
142 return ret;
143}
144
Simon Glassdf00afa2022-09-06 20:26:50 -0600145static int boot_bd_t_linux(struct bootm_headers *images)
Kumar Galaffccb572008-10-21 17:25:46 -0500146{
Kumar Galaffccb572008-10-21 17:25:46 -0500147 ulong of_size = images->ft_len;
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900148 struct bd_info **kbd = &images->kbd;
Kumar Galaffccb572008-10-21 17:25:46 -0500149
150 int ret = 0;
Kumar Galaa56d7d52008-02-27 21:51:44 -0600151
Kumar Galaffccb572008-10-21 17:25:46 -0500152 if (!of_size) {
Kumar Galaa56d7d52008-02-27 21:51:44 -0600153 /* allocate space for kernel copy of board info */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530154 ret = boot_get_kbd(kbd);
Kumar Galab937bb72008-02-27 21:51:49 -0600155 if (ret) {
156 puts("ERROR with allocation of kernel bd\n");
Kumar Galaffccb572008-10-21 17:25:46 -0500157 return ret;
Kumar Galab937bb72008-02-27 21:51:49 -0600158 }
Kumar Galaffccb572008-10-21 17:25:46 -0500159 set_clocks_in_mhz(*kbd);
Kumar Galaa56d7d52008-02-27 21:51:44 -0600160 }
Marian Balakowicz2437cf22008-01-08 18:11:43 +0100161
Kumar Galaffccb572008-10-21 17:25:46 -0500162 return ret;
163}
164
Simon Glassdf00afa2022-09-06 20:26:50 -0600165static int boot_body_linux(struct bootm_headers *images)
Kumar Galaffccb572008-10-21 17:25:46 -0500166{
Kumar Galaffccb572008-10-21 17:25:46 -0500167 int ret;
168
Kumar Galaffccb572008-10-21 17:25:46 -0500169 /* allocate space for kernel copy of board info */
170 ret = boot_bd_t_linux(images);
171 if (ret)
172 return ret;
173
Simon Glassae7ed572023-02-05 15:40:13 -0700174 if (IS_ENABLED(CONFIG_LMB)) {
Ashok Reddy Soma8aaae3d2022-07-07 10:45:37 +0200175 ret = image_setup_linux(images);
176 if (ret)
177 return ret;
178 }
Marian Balakowicz2437cf22008-01-08 18:11:43 +0100179
Kumar Galaffccb572008-10-21 17:25:46 -0500180 return 0;
181}
Kumar Gala56bdf1d2008-02-27 21:51:45 -0600182
Simon Glass0726d9d2023-12-15 20:14:13 -0700183int do_bootm_linux(int flag, struct bootm_info *bmi)
Kumar Galaffccb572008-10-21 17:25:46 -0500184{
Simon Glass0726d9d2023-12-15 20:14:13 -0700185 struct bootm_headers *images = bmi->images;
Kumar Galaffccb572008-10-21 17:25:46 -0500186 int ret;
Marian Balakowicz2437cf22008-01-08 18:11:43 +0100187
Kumar Galaffccb572008-10-21 17:25:46 -0500188 if (flag & BOOTM_STATE_OS_CMDLINE) {
189 boot_cmdline_linux(images);
190 return 0;
191 }
Marian Balakowicz2437cf22008-01-08 18:11:43 +0100192
Kumar Galaffccb572008-10-21 17:25:46 -0500193 if (flag & BOOTM_STATE_OS_BD_T) {
194 boot_bd_t_linux(images);
195 return 0;
196 }
Marian Balakowicz2437cf22008-01-08 18:11:43 +0100197
Kumar Gala180c5812011-12-07 04:42:58 +0000198 if (flag & BOOTM_STATE_OS_PREP) {
199 boot_prep_linux(images);
Kumar Galaffccb572008-10-21 17:25:46 -0500200 return 0;
Kumar Gala180c5812011-12-07 04:42:58 +0000201 }
Kumar Galadcdcfea2008-08-15 08:24:31 -0500202
Kumar Gala180c5812011-12-07 04:42:58 +0000203 boot_prep_linux(images);
Kumar Galaffccb572008-10-21 17:25:46 -0500204 ret = boot_body_linux(images);
205 if (ret)
206 return ret;
207 boot_jump_linux(images);
Kumar Gala18f4c0f2008-02-27 21:51:46 -0600208
Kumar Galaffccb572008-10-21 17:25:46 -0500209 return 0;
Marian Balakowicz2437cf22008-01-08 18:11:43 +0100210}
Marian Balakowicz28fb6152008-01-31 13:20:08 +0100211
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900212static void set_clocks_in_mhz (struct bd_info *kbd)
Marian Balakowicz2efc2642008-01-31 13:58:13 +0100213{
214 char *s;
215
Simon Glass64b723f2017-08-03 12:22:12 -0600216 s = env_get("clocks_in_mhz");
217 if (s) {
Marian Balakowicz2efc2642008-01-31 13:58:13 +0100218 /* convert all clock information to MHz */
219 kbd->bi_intfreq /= 1000000L;
220 kbd->bi_busfreq /= 1000000L;
Marian Balakowicz2efc2642008-01-31 13:58:13 +0100221 }
Marian Balakowicz351d3e32008-02-27 11:02:26 +0100222}
Miao Yan1bd54562013-11-28 17:51:38 +0800223
224#if defined(CONFIG_BOOTM_VXWORKS)
Simon Glassdf00afa2022-09-06 20:26:50 -0600225void boot_prep_vxworks(struct bootm_headers *images)
Miao Yan1bd54562013-11-28 17:51:38 +0800226{
227#if defined(CONFIG_OF_LIBFDT)
228 int off;
229 u64 base, size;
230
231 if (!images->ft_addr)
232 return;
233
Stefan Roesea13a2aa2020-08-12 13:16:36 +0200234 base = (u64)gd->ram_base;
235 size = (u64)gd->ram_size;
Miao Yan1bd54562013-11-28 17:51:38 +0800236
237 off = fdt_path_offset(images->ft_addr, "/memory");
238 if (off < 0)
239 fdt_fixup_memory(images->ft_addr, base, size);
240
241#if defined(CONFIG_MP)
242#if defined(CONFIG_MPC85xx)
243 ft_fixup_cpu(images->ft_addr, base + size);
244 ft_fixup_num_cores(images->ft_addr);
245#elif defined(CONFIG_MPC86xx)
246 off = fdt_add_mem_rsv(images->ft_addr,
247 determine_mp_bootpg(NULL), (u64)4096);
248 if (off < 0)
249 printf("## WARNING %s: %s\n", __func__, fdt_strerror(off));
250 ft_fixup_num_cores(images->ft_addr);
251#endif
252 flush_cache((unsigned long)images->ft_addr, images->ft_len);
253#endif
254#endif
255}
256
Simon Glassdf00afa2022-09-06 20:26:50 -0600257void boot_jump_vxworks(struct bootm_headers *images)
Miao Yan1bd54562013-11-28 17:51:38 +0800258{
259 /* PowerPC VxWorks boot interface conforms to the ePAPR standard
260 * general purpuse registers:
261 *
262 * r3: Effective address of the device tree image
263 * r4: 0
264 * r5: 0
265 * r6: ePAPR magic value
266 * r7: shall be the size of the boot IMA in bytes
267 * r8: 0
268 * r9: 0
269 * TCR: WRC = 0, no watchdog timer reset will occur
270 */
Stefan Roese80877fa2022-09-02 14:10:46 +0200271 schedule();
Miao Yan1bd54562013-11-28 17:51:38 +0800272
273 ((void (*)(void *, ulong, ulong, ulong,
274 ulong, ulong, ulong))images->ep)(images->ft_addr,
Simon Glassda1a1342017-08-03 12:22:15 -0600275 0, 0, EPAPR_MAGIC, env_get_bootm_mapsize(), 0, 0);
Miao Yan1bd54562013-11-28 17:51:38 +0800276}
277#endif