blob: d827f728a08c427612b46139e12d714fbfae48f2 [file] [log] [blame]
Jan Kiszka8ff2ff82021-09-18 08:17:53 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Board specific initialization for IOT2050
Jan Kiszkab2d24f92023-07-27 06:34:54 +02004 * Copyright (c) Siemens AG, 2018-2023
Jan Kiszka8ff2ff82021-09-18 08:17:53 +02005 *
6 * Authors:
7 * Le Jin <le.jin@siemens.com>
8 * Jan Kiszka <jan.kiszka@siemens.com>
9 */
10
Tom Rinidec7ea02024-05-20 13:35:03 -060011#include <config.h>
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020012#include <bootstage.h>
13#include <dm.h>
Jan Kiszkae31f16c2023-02-28 19:19:23 +010014#include <fdt_support.h>
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020015#include <i2c.h>
16#include <led.h>
17#include <malloc.h>
Jan Kiszkae31f16c2023-02-28 19:19:23 +010018#include <mapmem.h>
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020019#include <net.h>
20#include <phy.h>
21#include <spl.h>
22#include <version.h>
23#include <linux/delay.h>
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020024#include <asm/arch/hardware.h>
25#include <asm/gpio.h>
26#include <asm/io.h>
27
Baocheng Su06f0e3b2025-02-18 10:36:14 +080028#include "../../../../drivers/sysinfo/iot2050.h"
Jan Kiszka8ff2ff82021-09-18 08:17:53 +020029
30DECLARE_GLOBAL_DATA_PTR;
31
Jan Kiszkae31f16c2023-02-28 19:19:23 +010032struct gpio_config {
33 const char *gpio_name;
34 const char *label;
35};
36
37enum m2_connector_mode {
38 BKEY_PCIEX2 = 0,
39 BKEY_PCIE_EKEY_PCIE,
40 BKEY_USB30_EKEY_PCIE,
41 CONNECTOR_MODE_INVALID
42};
43
44struct m2_config_pins {
45 int config[4];
46};
47
48struct serdes_mux_control {
49 int ctrl_usb30_pcie0_lane0;
50 int ctrl_pcie1_pcie0;
51 int ctrl_usb30_pcie0_lane1;
52};
53
54struct m2_config_table {
55 struct m2_config_pins config_pins;
56 enum m2_connector_mode mode;
57};
58
59static const struct gpio_config serdes_mux_ctl_pin_info[] = {
60 {"gpio@600000_88", "CTRL_USB30_PCIE0_LANE0"},
61 {"gpio@600000_82", "CTRL_PCIE1_PCIE0"},
62 {"gpio@600000_89", "CTRL_USB30_PCIE0_LANE1"},
63};
64
65static const struct gpio_config m2_bkey_cfg_pin_info[] = {
66 {"gpio@601000_18", "KEY_CONFIG_0"},
67 {"gpio@601000_19", "KEY_CONFIG_1"},
68 {"gpio@601000_88", "KEY_CONFIG_2"},
69 {"gpio@601000_89", "KEY_CONFIG_3"},
70};
71
72static const struct m2_config_table m2_config_table[] = {
73 {{{0, 1, 0, 0}}, BKEY_PCIEX2},
74 {{{0, 0, 1, 0}}, BKEY_PCIE_EKEY_PCIE},
75 {{{0, 1, 1, 0}}, BKEY_PCIE_EKEY_PCIE},
76 {{{1, 0, 0, 1}}, BKEY_PCIE_EKEY_PCIE},
77 {{{1, 1, 0, 1}}, BKEY_PCIE_EKEY_PCIE},
78 {{{0, 0, 0, 1}}, BKEY_USB30_EKEY_PCIE},
79 {{{0, 1, 0, 1}}, BKEY_USB30_EKEY_PCIE},
80 {{{0, 0, 1, 1}}, BKEY_USB30_EKEY_PCIE},
81 {{{0, 1, 1, 1}}, BKEY_USB30_EKEY_PCIE},
82 {{{1, 0, 1, 1}}, BKEY_USB30_EKEY_PCIE},
83};
84
85static const struct serdes_mux_control serdes_mux_ctrl[] = {
86 [BKEY_PCIEX2] = {0, 0, 1},
87 [BKEY_PCIE_EKEY_PCIE] = {0, 1, 0},
88 [BKEY_USB30_EKEY_PCIE] = {1, 1, 0},
89};
90
91static const char *m2_connector_mode_name[] = {
92 [BKEY_PCIEX2] = "PCIe x2 (key B)",
93 [BKEY_PCIE_EKEY_PCIE] = "PCIe (key B) / PCIe (key E)",
94 [BKEY_USB30_EKEY_PCIE] = "USB 3.0 (key B) / PCIe (key E)",
95};
96
97static enum m2_connector_mode connector_mode;
98
Baocheng Su06f0e3b2025-02-18 10:36:14 +080099static char iot2050_board_name[21];
100
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100101#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
102static void *connector_overlay;
103static u32 connector_overlay_size;
104#endif
105
106static int get_pinvalue(const char *gpio_name, const char *label)
107{
108 struct gpio_desc gpio;
109
110 if (dm_gpio_lookup_name(gpio_name, &gpio) < 0 ||
111 dm_gpio_request(&gpio, label) < 0 ||
112 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0) {
113 pr_err("Cannot get pin %s for M.2 configuration\n", gpio_name);
114 return 0;
115 }
116
117 return dm_gpio_get_value(&gpio);
118}
119
120static void set_pinvalue(const char *gpio_name, const char *label, int value)
121{
122 struct gpio_desc gpio;
123
124 if (dm_gpio_lookup_name(gpio_name, &gpio) < 0 ||
125 dm_gpio_request(&gpio, label) < 0 ||
126 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT) < 0) {
127 pr_err("Cannot set pin %s for M.2 configuration\n", gpio_name);
128 return;
129 }
130 dm_gpio_set_value(&gpio, value);
131}
132
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800133static bool setup_sysinfo(struct udevice **sysinfo_ptr)
134{
135 if (sysinfo_get(sysinfo_ptr)) {
136 pr_err("Could not find sysinfo device.\n");
137 return false;
138 }
139 if (sysinfo_detect(*sysinfo_ptr)) {
140 pr_err("Board info parsing error\n");
141 return false;
142 }
143 return true;
144}
145
146static void get_board_name(void)
147{
148 struct udevice *sysinfo;
149
150 if (iot2050_board_name[0] != 0)
151 return;
152
153 if (!setup_sysinfo(&sysinfo))
154 return;
155
156 sysinfo_get_str(sysinfo, BOARD_NAME, sizeof(iot2050_board_name),
157 iot2050_board_name);
158}
159
Jan Kiszkab2d24f92023-07-27 06:34:54 +0200160static bool board_is_advanced(void)
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100161{
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100162
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800163 get_board_name();
164 return strstr(iot2050_board_name, "IOT2050-ADVANCED") != NULL;
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100165}
166
Jan Kiszka80085052023-10-17 07:20:14 +0200167static bool board_is_pg1(void)
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200168{
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800169 get_board_name();
170 return strcmp(iot2050_board_name, "IOT2050-BASIC") == 0 ||
171 strcmp(iot2050_board_name, "IOT2050-ADVANCED") == 0;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200172}
173
Jan Kiszkab2d24f92023-07-27 06:34:54 +0200174static bool board_is_m2(void)
175{
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800176 get_board_name();
177 return strcmp(iot2050_board_name, "IOT2050-ADVANCED-M2") == 0;
Jan Kiszkab2d24f92023-07-27 06:34:54 +0200178}
179
Baocheng Su0b064eb2024-10-22 08:04:27 +0200180static bool board_is_sm(void)
181{
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800182 get_board_name();
183 return strcmp(iot2050_board_name, "IOT2050-ADVANCED-SM") == 0;
Baocheng Su0b064eb2024-10-22 08:04:27 +0200184}
185
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200186static void remove_mmc1_target(void)
187{
188 char *boot_targets = strdup(env_get("boot_targets"));
189 char *mmc1 = strstr(boot_targets, "mmc1");
190
191 if (mmc1) {
192 memmove(mmc1, mmc1 + 4, strlen(mmc1 + 4) + 1);
193 env_set("boot_targets", boot_targets);
194 }
195
196 free(boot_targets);
197}
198
Baocheng Su6e8b7162024-10-22 08:04:20 +0200199static void enable_pcie_connector_power(void)
200{
Baocheng Su0b064eb2024-10-22 08:04:27 +0200201 if (board_is_sm())
202 set_pinvalue("gpio@601000_22", "P3V3_PCIE_CON_EN", 1);
203 else
204 set_pinvalue("gpio@601000_17", "P3V3_PCIE_CON_EN", 1);
Baocheng Su6e8b7162024-10-22 08:04:20 +0200205 udelay(4 * 100);
206}
207
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200208void set_board_info_env(void)
209{
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800210 struct udevice *sysinfo;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200211 const char *fdtfile;
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800212 char buf[41];
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200213
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800214 if (env_get("board_uuid"))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200215 return;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200216
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800217 if (!setup_sysinfo(&sysinfo))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200218 return;
219
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800220 if (sysinfo_get_str(sysinfo, BOARD_NAME, sizeof(buf), buf) == 0)
221 env_set("board_name", buf);
222 if (sysinfo_get_str(sysinfo, SYSID_SM_SYSTEM_SERIAL, sizeof(buf), buf) == 0)
223 env_set("board_serial", buf);
224 if (sysinfo_get_str(sysinfo, BOARD_MLFB, sizeof(buf), buf) == 0)
225 env_set("mlfb", buf);
226 if (sysinfo_get_str(sysinfo, BOARD_UUID, sizeof(buf), buf) == 0)
227 env_set("board_uuid", buf);
228 if (sysinfo_get_str(sysinfo, BOARD_A5E, sizeof(buf), buf) == 0)
229 env_set("board_a5e", buf);
230 if (sysinfo_get_str(sysinfo, BOARD_SEBOOT_VER, sizeof(buf), buf) == 0)
231 env_set("seboot_version", buf);
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200232 env_set("fw_version", PLAIN_VERSION);
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200233
234 if (IS_ENABLED(CONFIG_NET)) {
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800235 int mac_cnt;
236
237 mac_cnt = sysinfo_get_item_count(sysinfo, SYSID_BOARD_MAC_ADDR);
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200238 /* set MAC addresses to ensure forwarding to the OS */
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800239 for (int i = 0; i < mac_cnt; i++) {
240 u8 *mac = NULL;
241 size_t bytes = 0;
242
243 sysinfo_get_data_by_index(sysinfo, SYSID_BOARD_MAC_ADDR,
244 i, (void **)&mac, &bytes);
245 if (bytes == ARP_HLEN && is_valid_ethaddr(mac))
246 eth_env_set_enetaddr_by_index("eth", i + 1, mac);
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200247 }
248 }
249
250 if (board_is_advanced()) {
Jan Kiszka80085052023-10-17 07:20:14 +0200251 if (board_is_pg1())
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200252 fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
Baocheng Succdeb5b2024-10-22 08:04:19 +0200253 else if (board_is_m2())
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100254 fdtfile = "ti/k3-am6548-iot2050-advanced-m2.dtb";
Baocheng Su0b064eb2024-10-22 08:04:27 +0200255 else if (board_is_sm())
256 fdtfile = "ti/k3-am6548-iot2050-advanced-sm.dtb";
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200257 else
258 fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
259 } else {
Jan Kiszka80085052023-10-17 07:20:14 +0200260 if (board_is_pg1())
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200261 fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
262 else
263 fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
264 /* remove the unavailable eMMC (mmc1) from the list */
265 remove_mmc1_target();
266 }
267 env_set("fdtfile", fdtfile);
268
269 env_save();
270}
271
Baocheng Suc99731e2024-10-22 08:04:22 +0200272static void do_overlay_prepare(const char *overlay_path)
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100273{
274#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100275 void *overlay;
276 u64 loadaddr;
277 ofnode node;
278 int ret;
279
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100280 node = ofnode_path(overlay_path);
281 if (!ofnode_valid(node))
282 goto fit_error;
283
284 ret = ofnode_read_u64(node, "load", &loadaddr);
285 if (ret)
286 goto fit_error;
287
288 ret = ofnode_read_u32(node, "size", &connector_overlay_size);
289 if (ret)
290 goto fit_error;
291
292 overlay = map_sysmem(loadaddr, connector_overlay_size);
293
294 connector_overlay = malloc(connector_overlay_size);
295 if (!connector_overlay)
296 goto fit_error;
297
298 memcpy(connector_overlay, overlay, connector_overlay_size);
299 return;
300
301fit_error:
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800302 pr_err("M.2 device tree overlay %s not available.\n", overlay_path);
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100303#endif
304}
305
Baocheng Suc99731e2024-10-22 08:04:22 +0200306static void m2_overlay_prepare(void)
307{
308 const char *overlay_path;
309
310 if (connector_mode == BKEY_PCIEX2)
311 return;
312
313 if (connector_mode == BKEY_PCIE_EKEY_PCIE)
314 overlay_path = "/fit-images/bkey-ekey-pcie-overlay";
315 else
316 overlay_path = "/fit-images/bkey-usb3-overlay";
317
318 do_overlay_prepare(overlay_path);
319}
320
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100321static void m2_connector_setup(void)
322{
323 ulong m2_manual_config = env_get_ulong("m2_manual_config", 10,
324 CONNECTOR_MODE_INVALID);
325 const char *mode_info = "";
326 struct m2_config_pins config_pins;
327 unsigned int n;
328
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100329 if (m2_manual_config < CONNECTOR_MODE_INVALID) {
330 mode_info = " [manual mode]";
331 connector_mode = m2_manual_config;
332 } else { /* auto detection */
333 for (n = 0; n < ARRAY_SIZE(config_pins.config); n++)
334 config_pins.config[n] =
335 get_pinvalue(m2_bkey_cfg_pin_info[n].gpio_name,
336 m2_bkey_cfg_pin_info[n].label);
337 connector_mode = CONNECTOR_MODE_INVALID;
338 for (n = 0; n < ARRAY_SIZE(m2_config_table); n++) {
339 if (!memcmp(config_pins.config,
340 m2_config_table[n].config_pins.config,
341 sizeof(config_pins.config))) {
342 connector_mode = m2_config_table[n].mode;
343 break;
344 }
345 }
346 if (connector_mode == CONNECTOR_MODE_INVALID) {
347 mode_info = " [fallback, card unknown/unsupported]";
348 connector_mode = BKEY_USB30_EKEY_PCIE;
349 }
350 }
351
352 printf("M.2: %s%s\n", m2_connector_mode_name[connector_mode],
353 mode_info);
354
355 /* configure serdes mux */
356 set_pinvalue(serdes_mux_ctl_pin_info[0].gpio_name,
357 serdes_mux_ctl_pin_info[0].label,
358 serdes_mux_ctrl[connector_mode].ctrl_usb30_pcie0_lane0);
359 set_pinvalue(serdes_mux_ctl_pin_info[1].gpio_name,
360 serdes_mux_ctl_pin_info[1].label,
361 serdes_mux_ctrl[connector_mode].ctrl_pcie1_pcie0);
362 set_pinvalue(serdes_mux_ctl_pin_info[2].gpio_name,
363 serdes_mux_ctl_pin_info[2].label,
364 serdes_mux_ctrl[connector_mode].ctrl_usb30_pcie0_lane1);
365
366 m2_overlay_prepare();
367}
368
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200369int board_init(void)
370{
371 return 0;
372}
373
374int dram_init(void)
375{
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800376 struct udevice *sysinfo;
377 u32 ddr_size_mb;
378
379 if (!setup_sysinfo(&sysinfo))
380 return -ENODEV;
381
382 sysinfo_get_int(sysinfo, SYSID_BOARD_RAM_SIZE_MB, &ddr_size_mb);
383
384 gd->ram_size = ((phys_size_t)(ddr_size_mb)) << 20;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200385
386 return 0;
387}
388
Baocheng Suc9bdd3d2024-10-22 08:04:21 +0200389ulong board_get_usable_ram_top(ulong total_size)
390{
391 /* Limit RAM used by U-Boot to the DDR low region */
392 if (gd->ram_top > 0x100000000)
393 return 0x100000000;
394
395 return gd->ram_top;
396}
397
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200398int dram_init_banksize(void)
399{
400 dram_init();
401
Baocheng Suc9bdd3d2024-10-22 08:04:21 +0200402 if (gd->ram_size > SZ_2G) {
403 /* Bank 0 declares the memory available in the DDR low region */
404 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
405 gd->bd->bi_dram[0].size = SZ_2G;
406
407 /* Bank 1 declares the memory available in the DDR high region */
408 gd->bd->bi_dram[1].start = CFG_SYS_SDRAM_BASE1;
409 gd->bd->bi_dram[1].size = gd->ram_size - SZ_2G;
410 } else {
411 /* Bank 0 declares the memory available in the DDR low region */
412 gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
413 gd->bd->bi_dram[0].size = gd->ram_size;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200414
Baocheng Suc9bdd3d2024-10-22 08:04:21 +0200415 /* Bank 1 declares the memory available in the DDR high region */
416 gd->bd->bi_dram[1].start = 0;
417 gd->bd->bi_dram[1].size = 0;
418 }
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200419
420 return 0;
421}
422
423#ifdef CONFIG_SPL_LOAD_FIT
424int board_fit_config_name_match(const char *name)
425{
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200426 char upper_name[32];
427
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800428 get_board_name();
429
Jan Kiszka3fedadf2024-10-22 08:04:26 +0200430 /* skip the prefix "ti/k3-am65x8-" */
431 name += 13;
Su Baocheng8999cc52023-02-28 19:19:10 +0100432
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800433 if (strlen(name) >= sizeof(upper_name))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200434 return -1;
435
436 str_to_upper(name, upper_name, sizeof(upper_name));
Baocheng Su06f0e3b2025-02-18 10:36:14 +0800437 if (!strcmp(upper_name, iot2050_board_name))
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200438 return 0;
439
440 return -1;
441}
442#endif
443
444int do_board_detect(void)
445{
446 return 0;
447}
448
449#ifdef CONFIG_IOT2050_BOOT_SWITCH
450static bool user_button_pressed(void)
451{
452 struct udevice *red_led = NULL;
453 unsigned long count = 0;
454 struct gpio_desc gpio;
455
456 memset(&gpio, 0, sizeof(gpio));
457
chao zeng7d933ad2023-02-28 19:19:20 +0100458 if (dm_gpio_lookup_name("gpio@42110000_25", &gpio) < 0 ||
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200459 dm_gpio_request(&gpio, "USER button") < 0 ||
460 dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
461 return false;
462
463 if (dm_gpio_get_value(&gpio) == 1)
464 return false;
465
466 printf("USER button pressed - booting from external media only\n");
467
468 led_get_by_label("status-led-red", &red_led);
469
470 if (red_led)
471 led_set_state(red_led, LEDST_ON);
472
473 while (dm_gpio_get_value(&gpio) == 0 && count++ < 10000)
474 mdelay(1);
475
476 if (red_led)
477 led_set_state(red_led, LEDST_OFF);
478
479 return true;
480}
481#endif
482
483#define SERDES0_LANE_SELECT 0x00104080
484
485int board_late_init(void)
486{
487 /* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
488 writel(0x3, SERDES0_LANE_SELECT);
489
Baocheng Su6e8b7162024-10-22 08:04:20 +0200490 enable_pcie_connector_power();
491
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100492 if (board_is_m2())
493 m2_connector_setup();
494
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200495 set_board_info_env();
496
497 /* remove the eMMC if requested via button */
498 if (IS_ENABLED(CONFIG_IOT2050_BOOT_SWITCH) && board_is_advanced() &&
499 user_button_pressed())
500 remove_mmc1_target();
501
502 return 0;
503}
504
505#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
Baocheng Suc99731e2024-10-22 08:04:22 +0200506static void variants_fdt_fixup(void *blob)
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100507{
508 void *overlay_copy = NULL;
509 void *fdt_copy = NULL;
510 u32 fdt_size;
511 int err;
512
513 if (!connector_overlay)
514 return;
515
516 /*
517 * We need to work with temporary copies here because fdt_overlay_apply
518 * is destructive to the overlay and also to the target blob, even if
519 * application fails.
520 */
521 fdt_size = fdt_totalsize(blob);
522 fdt_copy = malloc(fdt_size);
523 if (!fdt_copy)
524 goto fixup_error;
525
526 memcpy(fdt_copy, blob, fdt_size);
527
528 overlay_copy = malloc(connector_overlay_size);
529 if (!overlay_copy)
530 goto fixup_error;
531
532 memcpy(overlay_copy, connector_overlay, connector_overlay_size);
533
534 err = fdt_overlay_apply_verbose(fdt_copy, overlay_copy);
535 if (err)
536 goto fixup_error;
537
538 memcpy(blob, fdt_copy, fdt_size);
539
540cleanup:
541 free(fdt_copy);
542 free(overlay_copy);
543 return;
544
545fixup_error:
Baocheng Suc99731e2024-10-22 08:04:22 +0200546 pr_err("Could not apply device tree overlay\n");
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100547 goto cleanup;
548}
549
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200550int ft_board_setup(void *blob, struct bd_info *bd)
551{
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100552 if (board_is_m2())
Baocheng Suc99731e2024-10-22 08:04:22 +0200553 variants_fdt_fixup(blob);
Jan Kiszkae31f16c2023-02-28 19:19:23 +0100554
Andrew Davisb1c29792023-04-06 11:38:10 -0500555 return 0;
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200556}
557#endif
558
559void spl_board_init(void)
560{
561}
562
Marek Vasut98154342021-10-23 03:06:03 +0200563#if CONFIG_IS_ENABLED(LED) && CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200564/*
565 * Indicate any error or (accidental?) entering of CLI via the red status LED.
566 */
567void show_boot_progress(int progress)
568{
569 struct udevice *dev;
570 int ret;
571
Jan Kiszkaa8ea4f42021-11-03 15:12:30 +0100572 if ((progress < 0 && progress != -BOOTSTAGE_ID_NET_ETH_START) ||
573 progress == BOOTSTAGE_ID_ENTER_CLI_LOOP) {
Jan Kiszka8ff2ff82021-09-18 08:17:53 +0200574 ret = led_get_by_label("status-led-green", &dev);
575 if (ret == 0)
576 led_set_state(dev, LEDST_OFF);
577
578 ret = led_get_by_label("status-led-red", &dev);
579 if (ret == 0)
580 led_set_state(dev, LEDST_ON);
581 }
582}
583#endif