summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@xilinx.com>2020-08-03 16:14:23 +0200
committerMichal Simek <michal.simek@xilinx.com>2020-10-27 08:13:32 +0100
commitf149b39ca3afbe3645f3e50ebd8a1e8af9a445a3 (patch)
tree47d215a89ac79634e1255138196cf4241aa04f9a
parent4489e0aa9b5548a2ad1beb2853bbc0db56cf1db5 (diff)
downloadu-boot-f149b39ca3afbe3645f3e50ebd8a1e8af9a445a3.tar.gz
xilinx: board: Add FRU decoder support
FMC cards are using FRU format for card identification. That's why add support for this format. Signed-off-by: Michal Simek <michal.simek@xilinx.com>
-rw-r--r--board/xilinx/common/board.c83
1 files changed, 82 insertions, 1 deletions
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 410b4cd998..821ee836dd 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);