blob: 065e446e15459ab861f7062a33a6c2bdda21a1d2 [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;
151 };
152
Daniel Schultz80677cb2024-05-21 23:18:26 -0700153 if (IS_ENABLED(CONFIG_PHYTEC_SOM_DETECTION_BLOCKS)) {
154 struct phytec_api3_element *block_element;
155 struct phytec_eeprom_data data;
156 int ret;
157
158 ret = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
159 if (ret || !data.valid)
160 return 0;
161
162 PHYTEC_API3_FOREACH_BLOCK(block_element, &data) {
163 switch (block_element->block_type) {
164 case PHYTEC_API3_BLOCK_MAC:
165 phytec_blocks_add_mac_to_env(block_element);
166 break;
167 default:
168 debug("%s: Unknown block type %i\n", __func__,
169 block_element->block_type);
170 }
171 }
172 }
173
Wadim Egorov648d2852024-11-27 13:17:35 +0100174 if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
175 configure_capsule_updates();
176
Tom Rinidec7ea02024-05-20 13:35:03 -0600177 return 0;
178}
179#endif
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200180
181#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP)
Wadim Egorov94d92522024-10-30 17:48:15 +0100182static int fdt_apply_overlay_from_fit(const char *overlay_path, void *fdt)
183{
184 u64 loadaddr;
185 ofnode node;
186 int ret;
187
188 node = ofnode_path(overlay_path);
189 if (!ofnode_valid(node))
190 return -FDT_ERR_NOTFOUND;
191
192 ret = ofnode_read_u64(node, "load", &loadaddr);
193 if (ret)
194 return ret;
195
196 return fdt_overlay_apply_verbose(fdt, (void *)loadaddr);
197}
198
199static void fdt_apply_som_overlays(void *blob)
200{
201 void *fdt_copy;
202 u32 fdt_size;
203 struct phytec_eeprom_data data;
204 int err;
205
206 fdt_size = fdt_totalsize(blob);
207 fdt_copy = malloc(fdt_size);
208 if (!fdt_copy)
209 goto fixup_error;
210
211 memcpy(fdt_copy, blob, fdt_size);
212
213 err = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
214 if (err)
215 goto fixup_error;
216
217 if (phytec_get_am6_rtc(&data) == 0) {
218 err = fdt_apply_overlay_from_fit("/fit-images/som-no-rtc", fdt_copy);
219 if (err)
220 goto fixup_error;
221 }
222
223 if (phytec_get_am6_spi(&data) == PHYTEC_EEPROM_VALUE_X) {
224 err = fdt_apply_overlay_from_fit("/fit-images/som-no-spi", fdt_copy);
225 if (err)
226 goto fixup_error;
227 }
228
229 if (phytec_get_am6_eth(&data) == 0) {
230 err = fdt_apply_overlay_from_fit("/fit-images/som-no-eth", fdt_copy);
231 if (err)
232 goto fixup_error;
233 }
234
235 if (phytec_am6_is_qspi(&data)) {
236 err = fdt_apply_overlay_from_fit("/fit-images/som-qspi-nor", fdt_copy);
237 if (err)
238 goto fixup_error;
239 }
240
241 memcpy(blob, fdt_copy, fdt_size);
242
243cleanup:
244 free(fdt_copy);
245 return;
246
247fixup_error:
248 pr_err("Failed to apply SoM overlays\n");
249 goto cleanup;
250}
251
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200252int ft_board_setup(void *blob, struct bd_info *bd)
253{
Wadim Egorov94d92522024-10-30 17:48:15 +0100254 fdt_apply_som_overlays(blob);
Wadim Egorov4baf2a62024-06-10 15:33:42 +0200255 fdt_copy_fixed_partitions(blob);
256
257 return 0;
258}
259#endif