blob: 9d8334568107ec38f7fdfc183051c6ef5a123516 [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 */
51void configure_capsule_updates(void)
52{
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
85#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
86void set_dfu_alt_info(char *interface, char *devstr)
87{
88 if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
89 env_set("dfu_alt_info", update_info.dfu_string);
90}
91#endif
92
Tom Rinidec7ea02024-05-20 13:35:03 -060093#if IS_ENABLED(CONFIG_ENV_IS_IN_FAT) || IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
94int mmc_get_env_dev(void)
95{
96 u32 boot_device = get_boot_device();
97
98 switch (boot_device) {
99 case BOOT_DEVICE_MMC1:
100 return 0;
101 case BOOT_DEVICE_MMC2:
102 return 1;
103 };
104
105 return CONFIG_SYS_MMC_ENV_DEV;
106}
107#endif
108
109enum env_location env_get_location(enum env_operation op, int prio)
110{
111 u32 boot_device = get_boot_device();
112
113 if (prio)
114 return ENVL_UNKNOWN;
115
116 switch (boot_device) {
117 case BOOT_DEVICE_MMC1:
118 case BOOT_DEVICE_MMC2:
119 if (CONFIG_IS_ENABLED(ENV_IS_IN_FAT))
120 return ENVL_FAT;
121 if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC))
122 return ENVL_MMC;
123 case BOOT_DEVICE_SPI:
124 if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH))
125 return ENVL_SPI_FLASH;
126 default:
127 return ENVL_NOWHERE;
128 };
129}
130
131#if IS_ENABLED(CONFIG_BOARD_LATE_INIT)
132int board_late_init(void)
133{
134 u32 boot_device = get_boot_device();
135
136 switch (boot_device) {
137 case BOOT_DEVICE_MMC1:
138 env_set_ulong("mmcdev", 0);
139 env_set("boot", "mmc");
140 break;
141 case BOOT_DEVICE_MMC2:
142 env_set_ulong("mmcdev", 1);
143 env_set("boot", "mmc");
144 break;
145 case BOOT_DEVICE_SPI:
146 env_set("boot", "spi");
147 break;
148 case BOOT_DEVICE_ETHERNET:
149 env_set("boot", "net");
150 break;
Daniel Schultz8592bbb2025-01-16 03:29:29 -0800151 case BOOT_DEVICE_UART:
152 env_set("boot", "uart");
153 break;
154 case BOOT_DEVICE_DFU:
155 env_set("boot", "usbdfu");
156 break;
Tom Rinidec7ea02024-05-20 13:35:03 -0600157 };
158
Daniel Schultz80677cb2024-05-21 23:18:26 -0700159 if (IS_ENABLED(CONFIG_PHYTEC_SOM_DETECTION_BLOCKS)) {
160 struct phytec_api3_element *block_element;
161 struct phytec_eeprom_data data;
162 int ret;
163
164 ret = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
165 if (ret || !data.valid)
166 return 0;
167
168 PHYTEC_API3_FOREACH_BLOCK(block_element, &data) {
169 switch (block_element->block_type) {
170 case PHYTEC_API3_BLOCK_MAC:
171 phytec_blocks_add_mac_to_env(block_element);
172 break;
173 default:
174 debug("%s: Unknown block type %i\n", __func__,
175 block_element->block_type);
176 }
177 }
178 }
179
Tom Rinie20fe8c2024-12-13 17:30:27 -0600180#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
181 configure_capsule_updates();
182#endif
Wadim Egorov648d2852024-11-27 13:17:35 +0100183
Tom Rinidec7ea02024-05-20 13:35:03 -0600184 return 0;
185}
186#endif
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200187
188#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP)
Wadim Egorov94d92522024-10-30 17:48:15 +0100189static int fdt_apply_overlay_from_fit(const char *overlay_path, void *fdt)
190{
191 u64 loadaddr;
192 ofnode node;
193 int ret;
194
195 node = ofnode_path(overlay_path);
196 if (!ofnode_valid(node))
197 return -FDT_ERR_NOTFOUND;
198
199 ret = ofnode_read_u64(node, "load", &loadaddr);
200 if (ret)
201 return ret;
202
203 return fdt_overlay_apply_verbose(fdt, (void *)loadaddr);
204}
205
206static void fdt_apply_som_overlays(void *blob)
207{
208 void *fdt_copy;
209 u32 fdt_size;
210 struct phytec_eeprom_data data;
211 int err;
212
213 fdt_size = fdt_totalsize(blob);
214 fdt_copy = malloc(fdt_size);
215 if (!fdt_copy)
216 goto fixup_error;
217
218 memcpy(fdt_copy, blob, fdt_size);
219
220 err = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
221 if (err)
222 goto fixup_error;
223
224 if (phytec_get_am6_rtc(&data) == 0) {
225 err = fdt_apply_overlay_from_fit("/fit-images/som-no-rtc", fdt_copy);
226 if (err)
227 goto fixup_error;
228 }
229
230 if (phytec_get_am6_spi(&data) == PHYTEC_EEPROM_VALUE_X) {
231 err = fdt_apply_overlay_from_fit("/fit-images/som-no-spi", fdt_copy);
232 if (err)
233 goto fixup_error;
234 }
235
236 if (phytec_get_am6_eth(&data) == 0) {
237 err = fdt_apply_overlay_from_fit("/fit-images/som-no-eth", fdt_copy);
238 if (err)
239 goto fixup_error;
240 }
241
242 if (phytec_am6_is_qspi(&data)) {
243 err = fdt_apply_overlay_from_fit("/fit-images/som-qspi-nor", fdt_copy);
244 if (err)
245 goto fixup_error;
246 }
247
248 memcpy(blob, fdt_copy, fdt_size);
249
250cleanup:
251 free(fdt_copy);
252 return;
253
254fixup_error:
255 pr_err("Failed to apply SoM overlays\n");
256 goto cleanup;
257}
258
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200259int ft_board_setup(void *blob, struct bd_info *bd)
260{
Daniel Schultz0b65a382025-01-23 06:43:50 -0800261 struct phytec_eeprom_data data;
262 int ret;
263
Wadim Egorov94d92522024-10-30 17:48:15 +0100264 fdt_apply_som_overlays(blob);
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200265 fdt_copy_fixed_partitions(blob);
266
Daniel Schultz0b65a382025-01-23 06:43:50 -0800267 ret = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
268 if (ret || !data.valid)
269 return 0;
270
271 ret = phytec_ft_board_fixup(&data, blob);
272 if (ret)
273 pr_err("%s: Failed to add PHYTEC information to fdt.\n",
274 __func__);
275
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200276 return 0;
277}
278#endif