blob: 828973a8e28caa4dc1811d69881e0cf8dd3ce32a [file] [log] [blame]
Tom Rinidec7ea02024-05-20 13:35:03 -06001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2024 PHYTEC Messtechnik GmbH
4 * Author: Wadim Egorov <w.egorov@phytec.de>
5 */
6
Wadim Egorov648d2852024-11-27 13:17:35 +01007#include <efi_loader.h>
Tom Rinidec7ea02024-05-20 13:35:03 -06008#include <env_internal.h>
Wadim Egorov4baf2a62024-06-10 15:33:42 +02009#include <fdt_support.h>
Wadim Egorov94d92522024-10-30 17:48:15 +010010#include <dm/ofnode.h>
Wadim Egorov648d2852024-11-27 13:17:35 +010011#include <mtd.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060012#include <spl.h>
Wadim Egorov94d92522024-10-30 17:48:15 +010013#include <malloc.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060014#include <asm/arch/hardware.h>
15
Daniel Schultz80677cb2024-05-21 23:18:26 -070016#include "../am6_som_detection.h"
17
Wadim Egorov648d2852024-11-27 13:17:35 +010018#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
19struct efi_fw_image fw_images[] = {
20 {
21 .fw_name = PHYCORE_AM6XX_FW_NAME_TIBOOT3,
22 .image_index = 1,
23 },
24 {
25 .fw_name = PHYCORE_AM6XX_FW_NAME_SPL,
26 .image_index = 2,
27 },
28 {
29 .fw_name = PHYCORE_AM6XX_FW_NAME_UBOOT,
30 .image_index = 3,
31 }
32};
33
34struct efi_capsule_update_info update_info = {
35 .dfu_string = NULL,
36 .num_images = ARRAY_SIZE(fw_images),
37 .images = fw_images,
38};
39
40/**
41 * configure_capsule_updates() - Set up the DFU string for capsule updates
42 *
43 * Configures all three bootloader binaries for updates on the current
44 * booted flash device, which may be eMMC, OSPI NOR, or a uSD card. If
45 * booting from USB or Serial, capsule updates will be performed on the
46 * eMMC device.
47 *
48 * Note: Currently, eMMC hardware partitions are not differentiated; Updates
49 * are always applied to the first boot partition.
50 */
Wadim Egorov58ec1832025-03-05 05:58:35 +010051static void configure_capsule_updates(void)
Wadim Egorov648d2852024-11-27 13:17:35 +010052{
53 static char dfu_string[128] = { 0 };
54 const char *dfu_raw = "tiboot3.bin raw 0x0 0x400 mmcpart 1;"
55 "tispl.bin raw 0x400 0x1000 mmcpart 1;"
56 "u-boot.img.raw raw 0x1400 0x2000 mmcpart 1";
57 const char *dfu_fat = "tiboot3.bin fat 1 1;"
58 "tispl.bin fat 1 1;"
59 "u-boot.img fat 1 1";
60 const char *dfu_spi = "tiboot3.bin part 1;"
61 "tispl.bin part 2;"
62 "u-boot.img part 3";
63 u32 boot_device = get_boot_device();
64
65 switch (boot_device) {
66 case BOOT_DEVICE_MMC1:
67 snprintf(dfu_string, 128, "mmc 0=%s", dfu_raw);
68 break;
69 case BOOT_DEVICE_MMC2:
70 snprintf(dfu_string, 128, "mmc 1=%s", dfu_fat);
71 break;
72 case BOOT_DEVICE_SPI:
73 mtd_probe_devices();
74 snprintf(dfu_string, 128, "mtd nor0=%s", dfu_spi);
75 break;
76 default:
77 snprintf(dfu_string, 128, "mmc 0=%s", dfu_raw);
78 break;
79 };
80
81 update_info.dfu_string = dfu_string;
82}
83#endif
84
Tom Rinidec7ea02024-05-20 13:35:03 -060085#if IS_ENABLED(CONFIG_ENV_IS_IN_FAT) || IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
86int mmc_get_env_dev(void)
87{
88 u32 boot_device = get_boot_device();
89
90 switch (boot_device) {
91 case BOOT_DEVICE_MMC1:
92 return 0;
93 case BOOT_DEVICE_MMC2:
94 return 1;
95 };
96
97 return CONFIG_SYS_MMC_ENV_DEV;
98}
99#endif
100
101enum env_location env_get_location(enum env_operation op, int prio)
102{
103 u32 boot_device = get_boot_device();
104
105 if (prio)
106 return ENVL_UNKNOWN;
107
108 switch (boot_device) {
109 case BOOT_DEVICE_MMC1:
110 case BOOT_DEVICE_MMC2:
111 if (CONFIG_IS_ENABLED(ENV_IS_IN_FAT))
112 return ENVL_FAT;
113 if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC))
114 return ENVL_MMC;
115 case BOOT_DEVICE_SPI:
116 if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH))
117 return ENVL_SPI_FLASH;
118 default:
119 return ENVL_NOWHERE;
120 };
121}
122
123#if IS_ENABLED(CONFIG_BOARD_LATE_INIT)
124int board_late_init(void)
125{
126 u32 boot_device = get_boot_device();
127
128 switch (boot_device) {
129 case BOOT_DEVICE_MMC1:
130 env_set_ulong("mmcdev", 0);
131 env_set("boot", "mmc");
132 break;
133 case BOOT_DEVICE_MMC2:
134 env_set_ulong("mmcdev", 1);
135 env_set("boot", "mmc");
136 break;
137 case BOOT_DEVICE_SPI:
138 env_set("boot", "spi");
139 break;
140 case BOOT_DEVICE_ETHERNET:
141 env_set("boot", "net");
142 break;
Daniel Schultz8592bbb2025-01-16 03:29:29 -0800143 case BOOT_DEVICE_UART:
144 env_set("boot", "uart");
145 break;
146 case BOOT_DEVICE_DFU:
147 env_set("boot", "usbdfu");
148 break;
Tom Rinidec7ea02024-05-20 13:35:03 -0600149 };
150
Daniel Schultz80677cb2024-05-21 23:18:26 -0700151 if (IS_ENABLED(CONFIG_PHYTEC_SOM_DETECTION_BLOCKS)) {
152 struct phytec_api3_element *block_element;
153 struct phytec_eeprom_data data;
154 int ret;
155
156 ret = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
157 if (ret || !data.valid)
158 return 0;
159
160 PHYTEC_API3_FOREACH_BLOCK(block_element, &data) {
161 switch (block_element->block_type) {
162 case PHYTEC_API3_BLOCK_MAC:
163 phytec_blocks_add_mac_to_env(block_element);
164 break;
165 default:
166 debug("%s: Unknown block type %i\n", __func__,
167 block_element->block_type);
168 }
169 }
170 }
171
Tom Rinie20fe8c2024-12-13 17:30:27 -0600172#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
173 configure_capsule_updates();
174#endif
Wadim Egorov648d2852024-11-27 13:17:35 +0100175
Tom Rinidec7ea02024-05-20 13:35:03 -0600176 return 0;
177}
178#endif
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200179
180#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP)
Wadim Egorov94d92522024-10-30 17:48:15 +0100181static int fdt_apply_overlay_from_fit(const char *overlay_path, void *fdt)
182{
183 u64 loadaddr;
184 ofnode node;
185 int ret;
186
187 node = ofnode_path(overlay_path);
188 if (!ofnode_valid(node))
189 return -FDT_ERR_NOTFOUND;
190
191 ret = ofnode_read_u64(node, "load", &loadaddr);
192 if (ret)
193 return ret;
194
195 return fdt_overlay_apply_verbose(fdt, (void *)loadaddr);
196}
197
198static void fdt_apply_som_overlays(void *blob)
199{
200 void *fdt_copy;
201 u32 fdt_size;
202 struct phytec_eeprom_data data;
203 int err;
204
205 fdt_size = fdt_totalsize(blob);
206 fdt_copy = malloc(fdt_size);
207 if (!fdt_copy)
208 goto fixup_error;
209
210 memcpy(fdt_copy, blob, fdt_size);
211
212 err = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
213 if (err)
214 goto fixup_error;
215
216 if (phytec_get_am6_rtc(&data) == 0) {
217 err = fdt_apply_overlay_from_fit("/fit-images/som-no-rtc", fdt_copy);
218 if (err)
219 goto fixup_error;
220 }
221
222 if (phytec_get_am6_spi(&data) == PHYTEC_EEPROM_VALUE_X) {
223 err = fdt_apply_overlay_from_fit("/fit-images/som-no-spi", fdt_copy);
224 if (err)
225 goto fixup_error;
226 }
227
228 if (phytec_get_am6_eth(&data) == 0) {
229 err = fdt_apply_overlay_from_fit("/fit-images/som-no-eth", fdt_copy);
230 if (err)
231 goto fixup_error;
232 }
233
234 if (phytec_am6_is_qspi(&data)) {
235 err = fdt_apply_overlay_from_fit("/fit-images/som-qspi-nor", fdt_copy);
236 if (err)
237 goto fixup_error;
238 }
239
240 memcpy(blob, fdt_copy, fdt_size);
241
242cleanup:
243 free(fdt_copy);
244 return;
245
246fixup_error:
247 pr_err("Failed to apply SoM overlays\n");
248 goto cleanup;
249}
250
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200251int ft_board_setup(void *blob, struct bd_info *bd)
252{
Daniel Schultz0b65a382025-01-23 06:43:50 -0800253 struct phytec_eeprom_data data;
254 int ret;
255
Wadim Egorov94d92522024-10-30 17:48:15 +0100256 fdt_apply_som_overlays(blob);
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200257 fdt_copy_fixed_partitions(blob);
258
Daniel Schultz0b65a382025-01-23 06:43:50 -0800259 ret = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
260 if (ret || !data.valid)
261 return 0;
262
263 ret = phytec_ft_board_fixup(&data, blob);
264 if (ret)
265 pr_err("%s: Failed to add PHYTEC information to fdt.\n",
266 __func__);
267
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200268 return 0;
269}
270#endif