blob: 52a38147ed26c3091b4d2414646c6866906df22a [file] [log] [blame]
Michal Simek9755e3d2019-01-21 15:25:02 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
Michal Simek8174cd22023-01-06 09:38:52 +01003 * (C) Copyright 2014 - 2022, Xilinx, Inc.
4 * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc.
5 *
6 * Michal Simek <michal.simek@amd.com>
Michal Simek9755e3d2019-01-21 15:25:02 +01007 */
8
9#include <common.h>
Sughosh Ganu741ef862022-04-15 11:29:34 +053010#include <efi.h>
11#include <efi_loader.h>
Simon Glass09140112020-05-10 11:40:03 -060012#include <env.h>
Michal Simeka32c3e92022-08-25 14:23:10 +020013#include <image.h>
Algapally Santosh Sagarfb737f12023-01-19 22:36:14 -070014#include <init.h>
Michal Simeka32c3e92022-08-25 14:23:10 +020015#include <lmb.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060016#include <log.h>
Simon Glass401d1c42020-10-30 21:38:53 -060017#include <asm/global_data.h>
Michal Simekfc274a52019-12-19 17:45:15 +010018#include <asm/sections.h>
Michal Simek9755e3d2019-01-21 15:25:02 +010019#include <dm/uclass.h>
20#include <i2c.h>
Michal Simeka29511e2020-04-08 10:51:36 +020021#include <linux/sizes.h>
Michal Simekd61728c2020-08-03 13:01:45 +020022#include <malloc.h>
Michal Simek80fdef12020-03-31 12:39:37 +020023#include "board.h"
Michal Simekd61728c2020-08-03 13:01:45 +020024#include <dm.h>
25#include <i2c_eeprom.h>
26#include <net.h>
Michal Simek05af4832020-10-26 12:26:13 +010027#include <generated/dt.h>
Michal Simek8174cd22023-01-06 09:38:52 +010028#include <slre.h>
T Karthik Reddy80c0d382021-08-10 06:50:20 -060029#include <soc.h>
Michal Simek52ff1622021-08-11 14:23:54 +020030#include <linux/ctype.h>
Sughosh Ganu741ef862022-04-15 11:29:34 +053031#include <linux/kernel.h>
Michal Simekee5a4b82022-07-21 16:19:17 +020032#include <uuid.h>
Michal Simek9755e3d2019-01-21 15:25:02 +010033
Michal Simekf149b392020-08-03 16:14:23 +020034#include "fru.h"
35
Sughosh Ganu741ef862022-04-15 11:29:34 +053036#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
37struct efi_fw_image fw_images[] = {
38#if defined(XILINX_BOOT_IMAGE_GUID)
39 {
40 .image_type_id = XILINX_BOOT_IMAGE_GUID,
41 .fw_name = u"XILINX-BOOT",
42 .image_index = 1,
43 },
44#endif
45#if defined(XILINX_UBOOT_IMAGE_GUID)
46 {
47 .image_type_id = XILINX_UBOOT_IMAGE_GUID,
48 .fw_name = u"XILINX-UBOOT",
49 .image_index = 2,
50 },
51#endif
52};
53
54struct efi_capsule_update_info update_info = {
55 .images = fw_images,
56};
57
58u8 num_image_type_guids = ARRAY_SIZE(fw_images);
59#endif /* EFI_HAVE_CAPSULE_SUPPORT */
60
Michal Simekd61728c2020-08-03 13:01:45 +020061#define EEPROM_HEADER_MAGIC 0xdaaddeed
62#define EEPROM_HDR_MANUFACTURER_LEN 16
63#define EEPROM_HDR_NAME_LEN 16
64#define EEPROM_HDR_REV_LEN 8
65#define EEPROM_HDR_SERIAL_LEN 20
66#define EEPROM_HDR_NO_OF_MAC_ADDR 4
67#define EEPROM_HDR_ETH_ALEN ETH_ALEN
Michal Simekee5a4b82022-07-21 16:19:17 +020068#define EEPROM_HDR_UUID_LEN 16
Michal Simekd61728c2020-08-03 13:01:45 +020069
70struct xilinx_board_description {
71 u32 header;
72 char manufacturer[EEPROM_HDR_MANUFACTURER_LEN + 1];
73 char name[EEPROM_HDR_NAME_LEN + 1];
74 char revision[EEPROM_HDR_REV_LEN + 1];
75 char serial[EEPROM_HDR_SERIAL_LEN + 1];
76 u8 mac_addr[EEPROM_HDR_NO_OF_MAC_ADDR][EEPROM_HDR_ETH_ALEN + 1];
Michal Simekee5a4b82022-07-21 16:19:17 +020077 char uuid[EEPROM_HDR_UUID_LEN + 1];
Michal Simekd61728c2020-08-03 13:01:45 +020078};
79
Michal Simeka03b5942020-08-03 12:57:05 +020080static int highest_id = -1;
Michal Simekd9c93c92021-08-12 12:30:36 +020081static struct xilinx_board_description *board_info;
Michal Simekd61728c2020-08-03 13:01:45 +020082
Michal Simekf149b392020-08-03 16:14:23 +020083#define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr)
Michal Simekd61728c2020-08-03 13:01:45 +020084
85/* Variable which stores pointer to array which stores eeprom content */
86struct xilinx_legacy_format {
87 char board_sn[18]; /* 0x0 */
88 char unused0[14]; /* 0x12 */
89 char eth_mac[6]; /* 0x20 */
90 char unused1[170]; /* 0x26 */
91 char board_name[11]; /* 0xd0 */
92 char unused2[5]; /* 0xdc */
93 char board_revision[3]; /* 0xe0 */
94 char unused3[29]; /* 0xe3 */
95};
96
97static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size)
98{
99 int i;
Venkatesh Yadav Abbarapue1a193b2022-09-26 12:22:42 +0530100 unsigned char byte;
Michal Simekd61728c2020-08-03 13:01:45 +0200101
102 for (i = 0; i < size; i++) {
103 byte = eeprom[i];
104
105 /* Remove all ffs and spaces */
106 if (byte == 0xff || byte == ' ')
107 eeprom[i] = 0;
108
109 /* Convert strings to lower case */
110 if (byte >= 'A' && byte <= 'Z')
111 eeprom[i] = byte + 'a' - 'A';
112 }
113}
114
115static int xilinx_read_eeprom_legacy(struct udevice *dev, char *name,
116 struct xilinx_board_description *desc)
117{
118 int ret, size;
119 struct xilinx_legacy_format *eeprom_content;
120 bool eth_valid = false;
121
122 size = sizeof(*eeprom_content);
123
124 eeprom_content = calloc(1, size);
125 if (!eeprom_content)
126 return -ENOMEM;
127
128 debug("%s: I2C EEPROM read pass data at %p\n", __func__,
129 eeprom_content);
130
131 ret = dm_i2c_read(dev, 0, (uchar *)eeprom_content, size);
132 if (ret) {
133 debug("%s: I2C EEPROM read failed\n", __func__);
134 free(eeprom_content);
135 return ret;
136 }
137
138 xilinx_eeprom_legacy_cleanup((char *)eeprom_content, size);
139
140 printf("Xilinx I2C Legacy format at %s:\n", name);
141 printf(" Board name:\t%s\n", eeprom_content->board_name);
142 printf(" Board rev:\t%s\n", eeprom_content->board_revision);
143 printf(" Board SN:\t%s\n", eeprom_content->board_sn);
144
145 eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac);
146 if (eth_valid)
147 printf(" Ethernet mac:\t%pM\n", eeprom_content->eth_mac);
148
149 /* Terminating \0 chars ensure end of string */
150 strcpy(desc->name, eeprom_content->board_name);
151 strcpy(desc->revision, eeprom_content->board_revision);
152 strcpy(desc->serial, eeprom_content->board_sn);
153 if (eth_valid)
154 memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN);
155
156 desc->header = EEPROM_HEADER_MAGIC;
157
158 free(eeprom_content);
159
160 return ret;
161}
162
163static bool xilinx_detect_legacy(u8 *buffer)
164{
165 int i;
166 char c;
167
168 for (i = 0; i < XILINX_I2C_DETECTION_BITS; i++) {
169 c = buffer[i];
170
171 if (c < '0' || c > '9')
172 return false;
173 }
174
175 return true;
176}
177
Michal Simekf149b392020-08-03 16:14:23 +0200178static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
179 struct xilinx_board_description *desc)
180{
Michal Simek530560b2021-08-12 11:03:49 +0200181 int i, ret, eeprom_size;
Michal Simekf149b392020-08-03 16:14:23 +0200182 u8 *fru_content;
Ashok Reddy Soma7a036b62022-02-23 15:00:59 +0100183 u8 id = 0;
Michal Simekf149b392020-08-03 16:14:23 +0200184
185 /* FIXME this is shortcut - if eeprom type is wrong it will fail */
186 eeprom_size = i2c_eeprom_size(dev);
187
188 fru_content = calloc(1, eeprom_size);
189 if (!fru_content)
190 return -ENOMEM;
191
192 debug("%s: I2C EEPROM read pass data at %p\n", __func__,
193 fru_content);
194
195 ret = dm_i2c_read(dev, 0, (uchar *)fru_content,
196 eeprom_size);
197 if (ret) {
198 debug("%s: I2C EEPROM read failed\n", __func__);
Michal Simekb2628632021-08-13 09:17:10 +0200199 goto end;
Michal Simekf149b392020-08-03 16:14:23 +0200200 }
201
Michal Simekf149b392020-08-03 16:14:23 +0200202 fru_capture((unsigned long)fru_content);
Michal Simek52ff1622021-08-11 14:23:54 +0200203 if (gd->flags & GD_FLG_RELOC || (_DEBUG && CONFIG_IS_ENABLED(DTB_RESELECT))) {
204 printf("Xilinx I2C FRU format at %s:\n", name);
205 ret = fru_display(0);
206 if (ret) {
207 printf("FRU format decoding failed.\n");
208 goto end;
209 }
Michal Simekf149b392020-08-03 16:14:23 +0200210 }
211
212 if (desc->header == EEPROM_HEADER_MAGIC) {
213 debug("Information already filled\n");
Michal Simekb2628632021-08-13 09:17:10 +0200214 ret = -EINVAL;
215 goto end;
Michal Simekf149b392020-08-03 16:14:23 +0200216 }
217
218 /* It is clear that FRU was captured and structures were filled */
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200219 strlcpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
Michal Simekf149b392020-08-03 16:14:23 +0200220 sizeof(desc->manufacturer));
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200221 strlcpy(desc->uuid, (char *)fru_data.brd.uuid,
Michal Simekee5a4b82022-07-21 16:19:17 +0200222 sizeof(desc->uuid));
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200223 strlcpy(desc->name, (char *)fru_data.brd.product_name,
Michal Simekf149b392020-08-03 16:14:23 +0200224 sizeof(desc->name));
Michal Simek530560b2021-08-12 11:03:49 +0200225 for (i = 0; i < sizeof(desc->name); i++) {
226 if (desc->name[i] == ' ')
227 desc->name[i] = '\0';
228 }
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200229 strlcpy(desc->revision, (char *)fru_data.brd.rev,
Michal Simekf149b392020-08-03 16:14:23 +0200230 sizeof(desc->revision));
Michal Simek93216272022-06-06 09:31:27 +0200231 for (i = 0; i < sizeof(desc->revision); i++) {
232 if (desc->revision[i] == ' ')
233 desc->revision[i] = '\0';
234 }
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200235 strlcpy(desc->serial, (char *)fru_data.brd.serial_number,
Michal Simekf149b392020-08-03 16:14:23 +0200236 sizeof(desc->serial));
Ashok Reddy Soma7a036b62022-02-23 15:00:59 +0100237
238 while (id < EEPROM_HDR_NO_OF_MAC_ADDR) {
239 if (is_valid_ethaddr((const u8 *)fru_data.mac.macid[id]))
240 memcpy(&desc->mac_addr[id],
241 (char *)fru_data.mac.macid[id], ETH_ALEN);
242 id++;
243 }
244
Michal Simekf149b392020-08-03 16:14:23 +0200245 desc->header = EEPROM_HEADER_MAGIC;
246
Michal Simekb2628632021-08-13 09:17:10 +0200247end:
248 free(fru_content);
249 return ret;
Michal Simekf149b392020-08-03 16:14:23 +0200250}
251
252static bool xilinx_detect_fru(u8 *buffer)
253{
254 u8 checksum = 0;
255 int i;
256
257 checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr));
258 if (checksum) {
259 debug("%s Common header CRC FAIL\n", __func__);
260 return false;
261 }
262
263 bool all_zeros = true;
264 /* Checksum over all zeros is also zero that's why detect this case */
265 for (i = 0; i < sizeof(struct fru_common_hdr); i++) {
266 if (buffer[i] != 0)
267 all_zeros = false;
268 }
269
270 if (all_zeros)
271 return false;
272
273 debug("%s Common header CRC PASS\n", __func__);
274 return true;
275}
276
Michal Simekd61728c2020-08-03 13:01:45 +0200277static int xilinx_read_eeprom_single(char *name,
278 struct xilinx_board_description *desc)
279{
280 int ret;
281 struct udevice *dev;
282 ofnode eeprom;
283 u8 buffer[XILINX_I2C_DETECTION_BITS];
284
285 eeprom = ofnode_get_aliases_node(name);
286 if (!ofnode_valid(eeprom))
287 return -ENODEV;
288
289 ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
290 if (ret)
291 return ret;
292
293 ret = dm_i2c_read(dev, 0, buffer, sizeof(buffer));
294 if (ret) {
295 debug("%s: I2C EEPROM read failed\n", __func__);
296 return ret;
297 }
298
299 debug("%s: i2c memory detected: %s\n", __func__, name);
300
Michal Simekf149b392020-08-03 16:14:23 +0200301 if (CONFIG_IS_ENABLED(CMD_FRU) && xilinx_detect_fru(buffer))
302 return xilinx_read_eeprom_fru(dev, name, desc);
303
Michal Simekd61728c2020-08-03 13:01:45 +0200304 if (xilinx_detect_legacy(buffer))
305 return xilinx_read_eeprom_legacy(dev, name, desc);
306
307 return -ENODEV;
308}
309
310__maybe_unused int xilinx_read_eeprom(void)
311{
Michal Simekd9c93c92021-08-12 12:30:36 +0200312 int id;
Michal Simekd61728c2020-08-03 13:01:45 +0200313 char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
Michal Simeka03b5942020-08-03 12:57:05 +0200314 struct xilinx_board_description *desc;
Michal Simekd61728c2020-08-03 13:01:45 +0200315
316 highest_id = dev_read_alias_highest_id("nvmem");
317 /* No nvmem aliases present */
318 if (highest_id < 0)
319 return -EINVAL;
320
Michal Simekd9c93c92021-08-12 12:30:36 +0200321 board_info = calloc(1, sizeof(*desc) * (highest_id + 1));
Michal Simekd61728c2020-08-03 13:01:45 +0200322 if (!board_info)
323 return -ENOMEM;
324
325 debug("%s: Highest ID %d, board_info %p\n", __func__,
326 highest_id, board_info);
327
328 for (id = 0; id <= highest_id; id++) {
329 snprintf(name_buf, sizeof(name_buf), "nvmem%d", id);
330
Michal Simeka03b5942020-08-03 12:57:05 +0200331 /* Alloc structure */
Michal Simekd9c93c92021-08-12 12:30:36 +0200332 desc = &board_info[id];
Michal Simeka03b5942020-08-03 12:57:05 +0200333
Michal Simekd61728c2020-08-03 13:01:45 +0200334 /* Ignoring return value for supporting multiple chips */
Michal Simekd9c93c92021-08-12 12:30:36 +0200335 xilinx_read_eeprom_single(name_buf, desc);
Michal Simekd61728c2020-08-03 13:01:45 +0200336 }
337
Michal Simeka03b5942020-08-03 12:57:05 +0200338 /*
339 * Consider to clean board_info structure when board/cards are not
340 * detected.
341 */
Michal Simekd61728c2020-08-03 13:01:45 +0200342
343 return 0;
344}
345
Michal Simekf0631002022-02-17 14:28:38 +0100346#if defined(CONFIG_OF_BOARD)
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300347void *board_fdt_blob_setup(int *err)
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100348{
Michal Simeke2572b52020-09-04 16:21:47 +0200349 void *fdt_blob;
Michal Simek453bb772020-03-19 10:23:56 +0100350
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300351 *err = 0;
Michal Simeka672b982021-01-04 11:07:28 +0100352 if (!IS_ENABLED(CONFIG_SPL_BUILD) &&
353 !IS_ENABLED(CONFIG_VERSAL_NO_DDR) &&
Michal Simekfc3c6fd2021-02-02 13:33:22 +0100354 !IS_ENABLED(CONFIG_ZYNQMP_NO_DDR)) {
Michal Simek506009f2021-01-04 11:03:36 +0100355 fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100356
Michal Simek506009f2021-01-04 11:03:36 +0100357 if (fdt_magic(fdt_blob) == FDT_MAGIC)
358 return fdt_blob;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100359
Michal Simek506009f2021-01-04 11:03:36 +0100360 debug("DTB is not passed via %p\n", fdt_blob);
361 }
Michal Simekfc274a52019-12-19 17:45:15 +0100362
Michal Simek506009f2021-01-04 11:03:36 +0100363 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
364 /*
365 * FDT is at end of BSS unless it is in a different memory
366 * region
367 */
368 if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
369 fdt_blob = (ulong *)&_image_binary_end;
370 else
371 fdt_blob = (ulong *)&__bss_end;
372 } else {
373 /* FDT is at end of image */
374 fdt_blob = (ulong *)&_end;
375 }
Michal Simekfc274a52019-12-19 17:45:15 +0100376
377 if (fdt_magic(fdt_blob) == FDT_MAGIC)
378 return fdt_blob;
379
380 debug("DTB is also not passed via %p\n", fdt_blob);
381
Michal Simekf0631002022-02-17 14:28:38 +0100382 *err = -EINVAL;
Michal Simekfc274a52019-12-19 17:45:15 +0100383 return NULL;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100384}
385#endif
Michal Simek80fdef12020-03-31 12:39:37 +0200386
Michal Simek7c553ac2020-10-22 11:14:20 +0200387#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simeka03b5942020-08-03 12:57:05 +0200388static int env_set_by_index(const char *name, int index, char *data)
389{
390 char var[32];
391
392 if (!index)
393 sprintf(var, "board_%s", name);
394 else
395 sprintf(var, "card%d_%s", index, name);
396
397 return env_set(var, data);
398}
399
Michal Simek80fdef12020-03-31 12:39:37 +0200400int board_late_init_xilinx(void)
401{
Michal Simekca0f6162020-08-12 12:16:49 +0200402 u32 ret = 0;
Michal Simeka03b5942020-08-03 12:57:05 +0200403 int i, id, macid = 0;
404 struct xilinx_board_description *desc;
Ricardo Salvetie6e3b9d2022-01-20 16:17:30 -0300405 phys_size_t bootm_size = gd->ram_top - gd->ram_base;
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600406
T Karthik Reddy25484d92021-04-02 01:49:17 -0600407 if (!CONFIG_IS_ENABLED(MICROBLAZE)) {
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600408 ulong scriptaddr;
409
410 scriptaddr = env_get_hex("scriptaddr", 0);
T Karthik Reddy25484d92021-04-02 01:49:17 -0600411 ret |= env_set_hex("scriptaddr", gd->ram_base + scriptaddr);
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600412 }
Michal Simek2570cc62020-08-12 12:17:53 +0200413
Michal Simek12305822020-10-23 07:54:18 +0200414 if (CONFIG_IS_ENABLED(ARCH_ZYNQ) || CONFIG_IS_ENABLED(MICROBLAZE))
Michal Simek2570cc62020-08-12 12:17:53 +0200415 bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M));
Michal Simek80fdef12020-03-31 12:39:37 +0200416
Michal Simekca0f6162020-08-12 12:16:49 +0200417 ret |= env_set_hex("script_offset_f", CONFIG_BOOT_SCRIPT_OFFSET);
418
419 ret |= env_set_addr("bootm_low", (void *)gd->ram_base);
Michal Simek2570cc62020-08-12 12:17:53 +0200420 ret |= env_set_addr("bootm_size", (void *)bootm_size);
Michal Simekca0f6162020-08-12 12:16:49 +0200421
Michal Simeka03b5942020-08-03 12:57:05 +0200422 for (id = 0; id <= highest_id; id++) {
Michal Simekd9c93c92021-08-12 12:30:36 +0200423 desc = &board_info[id];
Michal Simeka03b5942020-08-03 12:57:05 +0200424 if (desc && desc->header == EEPROM_HEADER_MAGIC) {
425 if (desc->manufacturer[0])
426 ret |= env_set_by_index("manufacturer", id,
427 desc->manufacturer);
428 if (desc->name[0])
429 ret |= env_set_by_index("name", id,
430 desc->name);
431 if (desc->revision[0])
432 ret |= env_set_by_index("rev", id,
433 desc->revision);
434 if (desc->serial[0])
435 ret |= env_set_by_index("serial", id,
436 desc->serial);
Michal Simekd61728c2020-08-03 13:01:45 +0200437
Michal Simekee5a4b82022-07-21 16:19:17 +0200438 if (desc->uuid[0]) {
Venkatesh Yadav Abbarapue1a193b2022-09-26 12:22:42 +0530439 unsigned char uuid[UUID_STR_LEN + 1];
440 unsigned char *t = desc->uuid;
Michal Simekee5a4b82022-07-21 16:19:17 +0200441
442 memset(uuid, 0, UUID_STR_LEN + 1);
443
444 sprintf(uuid, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
445 t[0], t[1], t[2], t[3], t[4], t[5],
446 t[6], t[7], t[8], t[9], t[10], t[11],
447 t[12], t[13], t[14], t[15]);
448 ret |= env_set_by_index("uuid", id, uuid);
449 }
450
Michal Simekd61728c2020-08-03 13:01:45 +0200451 if (!CONFIG_IS_ENABLED(NET))
452 continue;
453
Michal Simeka03b5942020-08-03 12:57:05 +0200454 for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
Michal Simeka03b5942020-08-03 12:57:05 +0200455 if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
456 ret |= eth_env_set_enetaddr_by_index("eth",
457 macid++, desc->mac_addr[i]);
458 }
Michal Simekd61728c2020-08-03 13:01:45 +0200459 }
460 }
461
Michal Simekca0f6162020-08-12 12:16:49 +0200462 if (ret)
463 printf("%s: Saving run time variables FAILED\n", __func__);
Michal Simekc8da6512020-07-09 15:57:56 +0200464
Michal Simek80fdef12020-03-31 12:39:37 +0200465 return 0;
466}
Michal Simek7c553ac2020-10-22 11:14:20 +0200467#endif
Michal Simek05af4832020-10-26 12:26:13 +0100468
Michal Simek57f71032021-07-23 09:55:59 +0200469static char *board_name = DEVICE_TREE;
470
Michal Simek05af4832020-10-26 12:26:13 +0100471int __maybe_unused board_fit_config_name_match(const char *name)
472{
Michal Simek57f71032021-07-23 09:55:59 +0200473 debug("%s: Check %s, default %s\n", __func__, name, board_name);
Michal Simek05af4832020-10-26 12:26:13 +0100474
Michal Simek8174cd22023-01-06 09:38:52 +0100475#if !defined(CONFIG_SPL_BUILD)
476 if (CONFIG_IS_ENABLED(REGEX)) {
477 struct slre slre;
478 int ret;
479
480 ret = slre_compile(&slre, name);
481 if (ret) {
482 ret = slre_match(&slre, board_name, strlen(board_name),
483 NULL);
484 debug("%s: name match ret = %d\n", __func__, ret);
485 return !ret;
486 }
487 }
488#endif
489
Michal Simek57f71032021-07-23 09:55:59 +0200490 if (!strcmp(name, board_name))
Michal Simek05af4832020-10-26 12:26:13 +0100491 return 0;
492
493 return -1;
494}
T Karthik Reddy80c0d382021-08-10 06:50:20 -0600495
Michal Simek88232532021-07-23 09:59:59 +0200496#if CONFIG_IS_ENABLED(DTB_RESELECT)
Michal Simek52ff1622021-08-11 14:23:54 +0200497#define MAX_NAME_LENGTH 50
498
Michal Simek88232532021-07-23 09:59:59 +0200499char * __maybe_unused __weak board_name_decode(void)
500{
Michal Simek52ff1622021-08-11 14:23:54 +0200501 char *board_local_name;
502 struct xilinx_board_description *desc;
503 int i, id;
504
505 board_local_name = calloc(1, MAX_NAME_LENGTH);
506 if (!board_info)
507 return NULL;
508
509 for (id = 0; id <= highest_id; id++) {
510 desc = &board_info[id];
511
512 /* No board description */
513 if (!desc)
514 goto error;
515
516 /* Board is not detected */
517 if (desc->header != EEPROM_HEADER_MAGIC)
518 continue;
519
520 /* The first string should be soc name */
521 if (!id)
522 strcat(board_local_name, CONFIG_SYS_BOARD);
523
524 /*
525 * For two purpose here:
526 * soc_name- eg: zynqmp-
527 * and between base board and CC eg: ..revA-sck...
528 */
529 strcat(board_local_name, "-");
530
531 if (desc->name[0]) {
532 /* For DT composition name needs to be lowercase */
533 for (i = 0; i < sizeof(desc->name); i++)
534 desc->name[i] = tolower(desc->name[i]);
535
536 strcat(board_local_name, desc->name);
537 }
538 if (desc->revision[0]) {
539 strcat(board_local_name, "-rev");
540
541 /* And revision needs to be uppercase */
542 for (i = 0; i < sizeof(desc->revision); i++)
543 desc->revision[i] = toupper(desc->revision[i]);
544
545 strcat(board_local_name, desc->revision);
546 }
547 }
548
549 /*
550 * Longer strings will end up with buffer overflow and potential
551 * attacks that's why check it
552 */
553 if (strlen(board_local_name) >= MAX_NAME_LENGTH)
554 panic("Board name can't be determined\n");
555
556 if (strlen(board_local_name))
557 return board_local_name;
558
559error:
560 free(board_local_name);
Michal Simek88232532021-07-23 09:59:59 +0200561 return NULL;
562}
563
564bool __maybe_unused __weak board_detection(void)
565{
Michal Simek52ff1622021-08-11 14:23:54 +0200566 if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) {
567 int ret;
568
569 ret = xilinx_read_eeprom();
570 return !ret ? true : false;
571 }
572
Michal Simek88232532021-07-23 09:59:59 +0200573 return false;
574}
575
Michal Simek39d3c3c2022-09-06 12:40:41 +0200576bool __maybe_unused __weak soc_detection(void)
577{
578 return false;
579}
580
581char * __maybe_unused __weak soc_name_decode(void)
582{
583 return NULL;
584}
585
Michal Simek88232532021-07-23 09:59:59 +0200586int embedded_dtb_select(void)
587{
Michal Simek39d3c3c2022-09-06 12:40:41 +0200588 if (soc_detection()) {
589 char *soc_local_name;
590
591 soc_local_name = soc_name_decode();
592 if (soc_local_name) {
593 board_name = soc_local_name;
594 printf("Detected SOC name: %s\n", board_name);
595
596 /* Time to change DTB on fly */
597 /* Both ways should work here */
598 /* fdtdec_resetup(&rescan); */
599 return fdtdec_setup();
600 }
601 }
602
Michal Simek88232532021-07-23 09:59:59 +0200603 if (board_detection()) {
604 char *board_local_name;
605
606 board_local_name = board_name_decode();
607 if (board_local_name) {
608 board_name = board_local_name;
Michal Simek52ff1622021-08-11 14:23:54 +0200609 printf("Detected name: %s\n", board_name);
Michal Simek88232532021-07-23 09:59:59 +0200610
611 /* Time to change DTB on fly */
612 /* Both ways should work here */
613 /* fdtdec_resetup(&rescan); */
614 fdtdec_setup();
615 }
616 }
617 return 0;
618}
619#endif
Michal Simeka32c3e92022-08-25 14:23:10 +0200620
621#if defined(CONFIG_LMB)
Pali Rohár049704f2022-09-09 17:32:40 +0200622phys_size_t board_get_usable_ram_top(phys_size_t total_size)
Michal Simeka32c3e92022-08-25 14:23:10 +0200623{
624 phys_size_t size;
625 phys_addr_t reg;
626 struct lmb lmb;
627
628 if (!total_size)
629 return gd->ram_top;
630
631 if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
632 panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
633
634 /* found enough not-reserved memory to relocated U-Boot */
635 lmb_init(&lmb);
636 lmb_add(&lmb, gd->ram_base, gd->ram_size);
637 boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
638 size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
639 reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
640
641 if (!reg)
642 reg = gd->ram_top - size;
643
644 return reg + size;
645}
646#endif