public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH 1/2] arm64: imx8mp: Read MAC address from M24C32-D write-lockable page on DH i.MX8MP DHCOM if available
@ 2024-10-10 13:23 Christoph Niedermaier
  2024-10-10 13:23 ` [PATCH 2/2] arm64: imx8mp: Read item and serial number from EEPROM ID page on DH i.MX8MP DHCOM Christoph Niedermaier
  2024-10-12 20:42 ` [PATCH 1/2] arm64: imx8mp: Read MAC address from M24C32-D write-lockable page on DH i.MX8MP DHCOM if available Marek Vasut
  0 siblings, 2 replies; 22+ messages in thread
From: Christoph Niedermaier @ 2024-10-10 13:23 UTC (permalink / raw)
  To: u-boot
  Cc: Christoph Niedermaier, NXP i.MX U-Boot Team, Marek Vasut,
	Fabio Estevam, Stefano Babic, Tom Rini, u-boot

The i.MX8M Plus DHCOM currently supports parsing ethernet MAC address
from multiple sources in the following priority order:

1) U-Boot environment 'ethaddr'/'eth1addr' environment variable
2) SoC OTP fuses
3) On-SoM EEPROM

The new i.MX8M Plus DHCOM rev.200 is populated with M24C32-D EEPROM
which contains additional write-lockable page, which can also be
populated with a structure containing ethernet MAC address.

Add support for parsing the content of this new write-lockable page
and place it between 2) and 3) on the priority list. The new entry is
2.5) On-SoM EEPROM write-lockable page

Because the write-lockable page is not present on rev.100 i.MX8MP DHCOM
SoM, test whether EEPROM ID page exists in DT and whether it is enabled
first. If so, read the entire ID page out, validate it, and determine
whether EEPROM MAC address is populated in it in DH specific format. If
so, use the MAC address. There may be multiple EEPROMs with an ID page
on this platform, always use the first one.

Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
---
Cc: "NXP i.MX U-Boot Team" <uboot-imx@nxp.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Tom Rini <trini@konsulko.com>
Cc: u-boot@dh-electronics.com
---
 board/dhelectronics/common/dh_common.c        | 113 ++++++++++++++++++
 board/dhelectronics/common/dh_common.h        |  23 ++++
 .../dh_imx8mp/imx8mp_dhcom_pdk2.c             |   6 +
 3 files changed, 142 insertions(+)

diff --git a/board/dhelectronics/common/dh_common.c b/board/dhelectronics/common/dh_common.c
index 32c50b4f0f..8ea70fc984 100644
--- a/board/dhelectronics/common/dh_common.c
+++ b/board/dhelectronics/common/dh_common.c
@@ -7,9 +7,22 @@
 #include <dm.h>
 #include <i2c_eeprom.h>
 #include <net.h>
+#include <u-boot/crc.h>
 
 #include "dh_common.h"
 
+struct eeprom_id_page {
+	u8	id[3];		/* Identifier 'D', 'H', 'E' - 'D' is at index 0 */
+	u8	version;	/* 0x10 -- Version 1.0 */
+	u8	data_crc16[2];	/* [1] is MSbyte */
+	u8	header_crc8;
+	u8	mac0[6];
+	u8	mac1[6];
+	u8	item_prefix;	/* H/F is coded in MSbits, Vendor coding starts at LSbits */
+	u8	item_num[3];	/* [2] is MSbyte */
+	u8	serial[9];	/* [8] is MSbyte */
+} __packed;
+
 bool dh_mac_is_in_env(const char *env)
 {
 	unsigned char enetaddr[6];
@@ -30,6 +43,106 @@ int dh_get_mac_is_enabled(const char *alias)
 	return 0;
 }
 
+int dh_get_value_from_eeprom_id_page(enum eip_request_values request, u8 *data,
+				     int data_len, const char *alias)
+{
+	struct eeprom_id_page *eipp;
+	struct udevice *dev;
+	static u8 eipa[32];
+	char path[128];
+	int len, ret;
+	ofnode node;
+	u16 c16;
+	u8 c8;
+
+	eipp = (struct eeprom_id_page *)eipa;
+
+	if (!(eipp->id[0] == 'D' && eipp->id[1] == 'H' && eipp->id[2] == 'E')) {
+		node = ofnode_path(alias);
+		if (!ofnode_valid(node)) {
+			printf("%s: ofnode for %s not found!", __func__, alias);
+			return -ENOENT;
+		}
+
+		ret = ofnode_get_path(node, path, sizeof(path));
+		if (ret)
+			return ret;
+
+		len = strlen(path);
+		if (len <= 0)
+			return -EINVAL;
+
+		if (path[len - 1] == '0')
+			path[len - 1] = '8';
+		else if (path[len - 1] == '3')
+			path[len - 1] = 'b';
+		else
+			return -ENOENT;
+
+		node = ofnode_path(path);
+		if (!ofnode_valid(node))	/* ID page not present in DT */
+			return -ENOENT;
+
+		if (!ofnode_is_enabled(node))	/* ID page not enabled in DT */
+			return -ENOENT;
+
+		ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, node, &dev);
+		if (ret) {
+			printf("%s: Cannot find ID page! ret = %d\n", __func__, ret);
+			return ret;
+		}
+
+		ret = i2c_eeprom_read(dev, 0x0, eipa, sizeof(eipa));
+		if (ret) {
+			printf("%s: Error reading ID page! ret = %d\n", __func__, ret);
+			return ret;
+		}
+	}
+
+	/* Validate header checksum */
+	c8 = crc8(0xff, eipa, offsetof(struct eeprom_id_page, header_crc8));
+	if (eipp->header_crc8 != c8)
+		return -EINVAL;
+
+	/* Validate header magic */
+	if (eipp->id[0] != 'D' || eipp->id[1] != 'H' || eipp->id[2] != 'E')
+		return -EINVAL;
+
+	/* Validate header version */
+	if (eipp->version != 0x10)
+		return -EINVAL;
+
+	/* Validate structure checksum */
+	c16 = crc16(0xffff, eipa + offsetof(struct eeprom_id_page, mac0),
+		    sizeof(*eipp) - offsetof(struct eeprom_id_page, mac0));
+	if (((eipp->data_crc16[1] << 8) | eipp->data_crc16[0]) != c16)
+		return -EINVAL;
+
+	/* Copy requested data */
+	switch (request) {
+	case MAC0:
+		if (!is_valid_ethaddr(eipp->mac0))
+			return -EINVAL;
+		if (data_len >= sizeof(eipp->mac0))
+			memcpy(data, eipp->mac0, sizeof(eipp->mac0));
+		else
+			return -EINVAL;
+		break;
+	case MAC1:
+		if (!is_valid_ethaddr(eipp->mac1))
+			return -EINVAL;
+		if (data_len >= sizeof(eipp->mac1))
+			memcpy(data, eipp->mac1, sizeof(eipp->mac1));
+		else
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int dh_get_mac_from_eeprom(unsigned char *enetaddr, const char *alias)
 {
 	struct udevice *dev;
diff --git a/board/dhelectronics/common/dh_common.h b/board/dhelectronics/common/dh_common.h
index a2de5b1553..4c22ece435 100644
--- a/board/dhelectronics/common/dh_common.h
+++ b/board/dhelectronics/common/dh_common.h
@@ -3,6 +3,11 @@
  * Copyright 2022 DENX Software Engineering GmbH, Philip Oberfichtner <pro@denx.de>
  */
 
+enum eip_request_values {
+	MAC0,
+	MAC1,
+};
+
 /*
  * dh_mac_is_in_env - Check if MAC address is already set
  *
@@ -28,6 +33,24 @@ int dh_get_mac_is_enabled(const char *alias);
  */
 int dh_get_mac_from_eeprom(unsigned char *enetaddr, const char *alias);
 
+/*
+ * dh_get_value_from_eeprom_id_page() - Get value from EEPROM ID page
+ * @eip_request_values:	Requested value as enum
+ * @data:		Buffer where value is to be stored
+ * @data_len:		Length of the value buffer
+ * @alias:		Alias for EEPROM device tree node
+ *
+ * Gets the value specified by the parameter eip_request_values from the ID
+ * page of the specified EEPROM. The EEPROM device is selected via alias
+ * device tree name (parameter alias). The data is written to the specified
+ * data buffer (parameter data). If the length of the data (parameter data_len)
+ * is not sufficient to copy the data into the buffer, an error is returned.
+ *
+ * Return: 0 if OK, other value on error
+ */
+int dh_get_value_from_eeprom_id_page(enum eip_request_values request, u8 *data,
+				     int data_len, const char *alias);
+
 /*
  * dh_setup_mac_address - Try to get MAC address from various locations and write it to env
  *
diff --git a/board/dhelectronics/dh_imx8mp/imx8mp_dhcom_pdk2.c b/board/dhelectronics/dh_imx8mp/imx8mp_dhcom_pdk2.c
index 78aae41235..9a8f09fcd4 100644
--- a/board/dhelectronics/dh_imx8mp/imx8mp_dhcom_pdk2.c
+++ b/board/dhelectronics/dh_imx8mp/imx8mp_dhcom_pdk2.c
@@ -53,6 +53,9 @@ static int dh_imx8_setup_ethaddr(void)
 	if (!dh_imx_get_mac_from_fuse(enetaddr))
 		goto out;
 
+	if (!dh_get_value_from_eeprom_id_page(MAC0, enetaddr, sizeof(enetaddr), "eeprom0"))
+		goto out;
+
 	if (!dh_get_mac_from_eeprom(enetaddr, "eeprom0"))
 		goto out;
 
@@ -75,6 +78,9 @@ static int dh_imx8_setup_eth1addr(void)
 	if (!dh_imx_get_mac_from_fuse(enetaddr))
 		goto increment_out;
 
+	if (!dh_get_value_from_eeprom_id_page(MAC1, enetaddr, sizeof(enetaddr), "eeprom0"))
+		goto out;
+
 	if (!dh_get_mac_from_eeprom(enetaddr, "eeprom1"))
 		goto out;
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2024-10-25 15:37 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-10 13:23 [PATCH 1/2] arm64: imx8mp: Read MAC address from M24C32-D write-lockable page on DH i.MX8MP DHCOM if available Christoph Niedermaier
2024-10-10 13:23 ` [PATCH 2/2] arm64: imx8mp: Read item and serial number from EEPROM ID page on DH i.MX8MP DHCOM Christoph Niedermaier
2024-10-12 20:55   ` Marek Vasut
2024-10-16 12:31     ` Christoph Niedermaier
2024-10-17  0:22       ` Marek Vasut
2024-10-17 11:55         ` Christoph Niedermaier
2024-10-17 18:35           ` Marek Vasut
2024-10-21 15:38             ` Christoph Niedermaier
2024-10-21 23:00               ` Marek Vasut
2024-10-22  9:31                 ` Christoph Niedermaier
2024-10-22 11:57                   ` Marek Vasut
2024-10-23 12:18                     ` Christoph Niedermaier
2024-10-23 12:41                       ` Marek Vasut
2024-10-23 13:20                         ` Christoph Niedermaier
2024-10-23 14:04                           ` Marek Vasut
2024-10-25 15:36                             ` Christoph Niedermaier
2024-10-12 20:42 ` [PATCH 1/2] arm64: imx8mp: Read MAC address from M24C32-D write-lockable page on DH i.MX8MP DHCOM if available Marek Vasut
2024-10-16 11:57   ` Christoph Niedermaier
2024-10-16 12:15     ` Marek Vasut
2024-10-17 11:09       ` Christoph Niedermaier
2024-10-17 14:01         ` Marek Vasut
2024-10-21 15:08           ` Christoph Niedermaier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox