diff options
author | Hugo Villeneuve | 2023-05-25 17:02:25 -0400 |
---|---|---|
committer | Stefano Babic | 2023-07-11 14:40:04 +0200 |
commit | fc1b8e1e7ecd927d6f65ea2dc256f8b81134759e (patch) | |
tree | 6de35f9979e29afbfb11dc6d7e71d85067efe2d6 /board | |
parent | cb4e79b7ba9aef961e7a6549ec35467e3c1f8e85 (diff) |
imx8mn-var-som: read and print SoM infos from eeprom on startup
Enable support to read and display configuration/manufacturing infos
from 4Kbit EEPROM located on SOM board.
Note: CONFIG_DISPLAY_BOARDINFO is automatically selected for ARM arch.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Diffstat (limited to 'board')
-rw-r--r-- | board/variscite/imx8mn_var_som/imx8mn_var_som.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/board/variscite/imx8mn_var_som/imx8mn_var_som.c b/board/variscite/imx8mn_var_som/imx8mn_var_som.c index d40f4d01761..a89457e8f57 100644 --- a/board/variscite/imx8mn_var_som/imx8mn_var_som.c +++ b/board/variscite/imx8mn_var_som/imx8mn_var_som.c @@ -1,11 +1,49 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2021 Collabora Ltd. + * Copyright 2018-2020 Variscite Ltd. + * Copyright 2023 DimOnOff Inc. */ #include <common.h> +#include <dm.h> #include <env.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <i2c_eeprom.h> +#include <malloc.h> #include <asm/io.h> +#include <asm/global_data.h> +#include <linux/libfdt.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Optional SOM features flags. */ +#define VAR_EEPROM_F_WIFI BIT(0) +#define VAR_EEPROM_F_ETH BIT(1) /* Ethernet PHY on SOM. */ +#define VAR_EEPROM_F_AUDIO BIT(2) +#define VAR_EEPROM_F_MX8M_LVDS BIT(3) /* i.MX8MM, i.MX8MN, i.MX8MQ only */ +#define VAR_EEPROM_F_MX8Q_SOC_ID BIT(3) /* 0 = i.MX8QM, 1 = i.MX8QP */ +#define VAR_EEPROM_F_NAND BIT(4) + +#define VAR_IMX8_EEPROM_MAGIC 0x384D /* "8M" */ + +/* Number of DRAM adjustment tables. */ +#define DRAM_TABLES_NUM 7 + +struct var_imx8_eeprom_info { + u16 magic; + u8 partnumber[3]; /* Part number */ + u8 assembly[10]; /* Assembly number */ + u8 date[9]; /* Build date */ + u8 mac[6]; /* MAC address */ + u8 somrev; + u8 eeprom_version; + u8 features; /* SOM features */ + u8 dramsize; /* DRAM size */ + u8 off[DRAM_TABLES_NUM + 1]; /* DRAM table offsets */ + u8 partnumber2[5]; /* Part number 2 */ +} __packed; static void setup_fec(void) { @@ -28,3 +66,99 @@ int board_mmc_get_env_dev(int devno) { return devno; } + +#if !defined(CONFIG_SPL_BUILD) + +#if defined(CONFIG_DISPLAY_BOARDINFO) + +static void display_som_infos(struct var_imx8_eeprom_info *info) +{ + char partnumber[sizeof(info->partnumber) + + sizeof(info->partnumber2) + 1]; + char assembly[sizeof(info->assembly) + 1]; + char date[sizeof(info->date) + 1]; + + /* Read first part of P/N. */ + memcpy(partnumber, info->partnumber, sizeof(info->partnumber)); + + /* Read second part of P/N. */ + if (info->eeprom_version >= 3) + memcpy(partnumber + sizeof(info->partnumber), info->partnumber2, + sizeof(info->partnumber2)); + + memcpy(assembly, info->assembly, sizeof(info->assembly)); + memcpy(date, info->date, sizeof(info->date)); + + /* Make sure strings are null terminated. */ + partnumber[sizeof(partnumber) - 1] = '\0'; + assembly[sizeof(assembly) - 1] = '\0'; + date[sizeof(date) - 1] = '\0'; + + printf("SOM board: P/N: %s, Assy: %s, Date: %s\n" + " Wifi: %s, EthPhy: %s, Rev: %d\n", + partnumber, assembly, date, + info->features & VAR_EEPROM_F_WIFI ? "yes" : "no", + info->features & VAR_EEPROM_F_ETH ? "yes" : "no", + info->somrev); +} + +static int var_read_som_eeprom(struct var_imx8_eeprom_info *info) +{ + const char *path = "eeprom-som"; + struct udevice *dev; + int ret, off; + + off = fdt_path_offset(gd->fdt_blob, path); + if (off < 0) { + pr_err("%s: fdt_path_offset() failed: %d\n", __func__, off); + return off; + } + + ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev); + if (ret) { + pr_err("%s: uclass_get_device_by_of_offset() failed: %d\n", + __func__, ret); + return ret; + } + + ret = i2c_eeprom_read(dev, 0, (uint8_t *)info, + sizeof(struct var_imx8_eeprom_info)); + if (ret) { + pr_err("%s: i2c_eeprom_read() failed: %d\n", __func__, ret); + return ret; + } + + if (htons(info->magic) != VAR_IMX8_EEPROM_MAGIC) { + /* Do not fail if the content is invalid */ + pr_err("Board: Invalid board info magic: 0x%08x, expected 0x%08x\n", + htons(info->magic), VAR_IMX8_EEPROM_MAGIC); + } + + return 0; +} + +int checkboard(void) +{ + int rc; + struct var_imx8_eeprom_info *info; + + info = malloc(sizeof(struct var_imx8_eeprom_info)); + if (!info) + return -ENOMEM; + + rc = var_read_som_eeprom(info); + if (rc) + return rc; + + display_som_infos(info); + +#if defined(CONFIG_BOARD_TYPES) + gd->board_type = info->features; +#endif /* CONFIG_BOARD_TYPES */ + + return 0; +} + +#endif /* CONFIG_DISPLAY_BOARDINFO */ + +#endif /* CONFIG_SPL_BUILD */ |