[PATCH 4/4] xilinx: board: Add FRU decoder support

Michal Simek michal.simek at xilinx.com
Tue Oct 20 16:50:30 CEST 2020


FMC cards are using FRU format for card identification. That's why add
support for this format.

Signed-off-by: Michal Simek <michal.simek at xilinx.com>
---

 board/xilinx/common/board.c | 83 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 1 deletion(-)

diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 0d0c21ca3d40..74e81c18bd5a 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -17,6 +17,8 @@
 #include <i2c_eeprom.h>
 #include <net.h>
 
+#include "fru.h"
+
 #if defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET)
 int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
 {
@@ -65,7 +67,7 @@ struct xilinx_board_description {
 static int highest_id = -1;
 static struct xilinx_board_description **board_info;
 
-#define XILINX_I2C_DETECTION_BITS	8
+#define XILINX_I2C_DETECTION_BITS	sizeof(struct fru_common_hdr)
 
 /* Variable which stores pointer to array which stores eeprom content */
 struct xilinx_legacy_format {
@@ -160,6 +162,82 @@ static bool xilinx_detect_legacy(u8 *buffer)
 	return true;
 }
 
+static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
+				  struct xilinx_board_description *desc)
+{
+	int ret, eeprom_size;
+	u8 *fru_content;
+
+	/* FIXME this is shortcut - if eeprom type is wrong it will fail */
+	eeprom_size = i2c_eeprom_size(dev);
+
+	fru_content = calloc(1, eeprom_size);
+	if (!fru_content)
+		return -ENOMEM;
+
+	debug("%s: I2C EEPROM read pass data at %p\n", __func__,
+	      fru_content);
+
+	ret = dm_i2c_read(dev, 0, (uchar *)fru_content,
+			  eeprom_size);
+	if (ret) {
+		debug("%s: I2C EEPROM read failed\n", __func__);
+		free(fru_content);
+		return ret;
+	}
+
+	printf("Xilinx I2C FRU format at %s:\n", name);
+	fru_capture((unsigned long)fru_content);
+	ret = fru_display(0);
+	if (ret) {
+		printf("FRU format decoding failed.\n");
+		return ret;
+	}
+
+	if (desc->header == EEPROM_HEADER_MAGIC) {
+		debug("Information already filled\n");
+		return -EINVAL;
+	}
+
+	/* It is clear that FRU was captured and structures were filled */
+	strncpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
+		sizeof(desc->manufacturer));
+	strncpy(desc->name, (char *)fru_data.brd.product_name,
+		sizeof(desc->name));
+	strncpy(desc->revision, (char *)fru_data.brd.rev,
+		sizeof(desc->revision));
+	strncpy(desc->serial, (char *)fru_data.brd.serial_number,
+		sizeof(desc->serial));
+	desc->header = EEPROM_HEADER_MAGIC;
+
+	return 0;
+}
+
+static bool xilinx_detect_fru(u8 *buffer)
+{
+	u8 checksum = 0;
+	int i;
+
+	checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr));
+	if (checksum) {
+		debug("%s Common header CRC FAIL\n", __func__);
+		return false;
+	}
+
+	bool all_zeros = true;
+	/* Checksum over all zeros is also zero that's why detect this case */
+	for (i = 0; i < sizeof(struct fru_common_hdr); i++) {
+		if (buffer[i] != 0)
+			all_zeros = false;
+	}
+
+	if (all_zeros)
+		return false;
+
+	debug("%s Common header CRC PASS\n", __func__);
+	return true;
+}
+
 static int xilinx_read_eeprom_single(char *name,
 				     struct xilinx_board_description *desc)
 {
@@ -184,6 +262,9 @@ static int xilinx_read_eeprom_single(char *name,
 
 	debug("%s: i2c memory detected: %s\n", __func__, name);
 
+	if (CONFIG_IS_ENABLED(CMD_FRU) && xilinx_detect_fru(buffer))
+		return xilinx_read_eeprom_fru(dev, name, desc);
+
 	if (xilinx_detect_legacy(buffer))
 		return xilinx_read_eeprom_legacy(dev, name, desc);
 
-- 
2.28.0



More information about the U-Boot mailing list