From 8e10a95228f7310f0254f8e1e4b7aadbaf37725a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 12 Apr 2019 11:26:29 +0200 Subject: [PATCH] arm64: zynqmp: Add board detection based on FRU Identification depends on eeprom with FRU content. For example 2 eeproms to check. chosen { xlnx,eeprom = <&eeprom>, <&eeprom2>; }; Signed-off-by: Michal Simek --- board/xilinx/zynqmp/Kconfig | 7 ++ board/xilinx/zynqmp/Makefile | 1 + board/xilinx/zynqmp/board_detect_fru.c | 149 +++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 board/xilinx/zynqmp/board_detect_fru.c diff --git a/board/xilinx/zynqmp/Kconfig b/board/xilinx/zynqmp/Kconfig index 7d1f7398c3e..e81ae2de555 100644 --- a/board/xilinx/zynqmp/Kconfig +++ b/board/xilinx/zynqmp/Kconfig @@ -15,4 +15,11 @@ config CMD_ZYNQMP and authentication feature enabled while generating BOOT.BIN using Xilinx bootgen tool. +config ZYNQMP_BOARD_DETECT_FRU + bool "Enable ZynqMP board detection via FRU" + help + Enabling this option u-boot will look at chosen/xlnx,eeprom + property and will try to decode board name written in IPMI + FRU format. + endif diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index b4d39edc118..2592faee673 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -39,6 +39,7 @@ $(obj)/pm_cfg_obj.o: $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_SPL_PM_C endif obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o +obj-$(CONFIG_ZYNQMP_BOARD_DETECT_FRU) += board_detect_fru.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZYNQMP) += cmds.o diff --git a/board/xilinx/zynqmp/board_detect_fru.c b/board/xilinx/zynqmp/board_detect_fru.c new file mode 100644 index 00000000000..a3fe956863d --- /dev/null +++ b/board/xilinx/zynqmp/board_detect_fru.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2018 - 2019 Xilinx, Inc. + * + * Michal Simek + */ + +#define DEBUG + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_SPL_BUILD + +#define FRU_DATA_START 0 +#define FRU_DATA_SIZE 256 + +#if defined(CONFIG_DTB_RESELECT) +static int get_fru(uint8_t *fru_space) +{ + struct udevice *dev; + int ret, i, count; + u32 *phandles; + ofnode chosen_node; + + chosen_node = ofnode_path("/chosen"); + + count = ofnode_count_phandle_with_args(chosen_node, "xlnx,eeprom", + NULL); + /* If there is no node or count is 0 fail */ + if (count < 0 || !count) { + debug("%s: Incorrect or missing xlnx,eeprom property %d\n", + __func__, count); + return -EINVAL; + } + + debug("%s: Found %d eeprom phandles\n", __func__, count); + + phandles = calloc(count, sizeof(*phandles)); + if (!phandles) + return -ENOMEM; + + ret = ofnode_read_u32_array(chosen_node, "xlnx,eeprom", + phandles, count); + if (ret) { + debug("%s: Reading phandles failed\n", __func__); + return ret; + } + + /* Interate over phandles and try to read FRU data */ + for (i = 0; i < count; i++) { + debug("%s: %d: Reading device phandle %x\n", + __func__, i, phandles[i]); + /* Get device from phandle_id */ + ret = uclass_get_device_by_phandle_id(UCLASS_I2C_EEPROM, + phandles[i], &dev); + if (ret) { + debug("%s: %d: Get device phandle %x failed %d\n", + __func__, i, phandles[i], ret); + continue; + } + + /* Setup alen to 2 */ + ret = i2c_set_chip_offset_len(dev, 2); + if (ret) + break; + + /* Read data to fru_space */ + ret = dm_i2c_read(dev, FRU_DATA_START, fru_space, + FRU_DATA_SIZE); + if (!ret) { + debug("%s: %i: I2C FRU location %p\n", + __func__, i, fru_space); + break; + } + + debug("%s: %d: I2C FRU read failed\n", __func__, i); + } + + free(phandles); + return ret; +} + +static int do_board_detect(void) +{ + int ret; + void *fru_space; + + fru_space = calloc(FRU_DATA_SIZE, sizeof(u8)); + if (!fru_space) { + debug("%s: Malloc failed\n", __func__); + return -ENOMEM; + } + + ret = get_fru(fru_space); + if (!ret) { + ret = fru_capture((ulong)fru_space); + if (ret) + debug("%s: FRU decoding failed\n", __func__); + else + debug("%s: Board detected via FRU\n", __func__); + + } else { + debug("%s: Cannot read EEPROM\n", __func__); + } + + free(fru_space); + return ret; +} + +int embedded_dtb_select(void) +{ + int ret; + + debug("%s: Start board detect\n", __func__); + + ret = do_board_detect(); + if (ret < 0) + debug("%s: Board detection failed\n", __func__); + + fdtdec_setup(); + + return 0; +} +#endif + +int board_fit_config_name_match(const char *name) +{ + if (!fru_data.captured) { + debug("%s: FRU data not captured\n", __func__); + return -EINVAL; + } + + debug("%s: checking name %s with %s\n", __func__, name, + fru_data.brd.product_name); + + if (!strcmp(name, (char *)fru_data.brd.product_name)) { + debug("Board found finally\n"); + return 0; + } + + return -EINVAL; +} +#endif + -- 2.47.3