All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lothar Rubusch <l.rubusch@gmail.com>
To: u-boot@lists.denx.de, trini@konsulko.com, marex@denx.de,
	simon.k.r.goldschmidt@gmail.com, tien.fong.chee@intel.com
Cc: l.rubusch@gmail.com
Subject: [PATCH 7/9] ARM: socfpga: AA1: support MAC from secure eeprom
Date: Thu, 12 Sep 2024 06:06:47 +0000	[thread overview]
Message-ID: <20240912060649.190-8-l.rubusch@gmail.com> (raw)
In-Reply-To: <20240912060649.190-1-l.rubusch@gmail.com>

Several Enclustra devices store MAC address in a secure eeprom device. In
most cases this is the atsha204a (alternatively DS28). The atsha204a device
is preconfigured accordingly. Reading then is based on u-boot's atsha204a
driver. Add such support for Enclustra's AA1 SoMs.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 board/enclustra/common/Kconfig                | 23 +++++
 board/enclustra/common/Makefile               |  3 +
 board/enclustra/common/enclustra_mac.h        | 48 +++++++++
 board/enclustra/common/mac_atsha204.c         | 97 +++++++++++++++++++
 board/enclustra/common/mac_common.c           | 54 +++++++++++
 board/enclustra/common/mac_ds28.c             | 88 +++++++++++++++++
 board/enclustra/mercury_aa1/mercury_aa1.c     |  7 ++
 .../socfpga_enclustra_mercury_aa1_defconfig   |  1 +
 drivers/misc/Kconfig                          |  2 +-
 9 files changed, 322 insertions(+), 1 deletion(-)
 create mode 100644 board/enclustra/common/enclustra_mac.h
 create mode 100644 board/enclustra/common/mac_atsha204.c
 create mode 100644 board/enclustra/common/mac_common.c
 create mode 100644 board/enclustra/common/mac_ds28.c

diff --git a/board/enclustra/common/Kconfig b/board/enclustra/common/Kconfig
index 51169bada3..51991f7882 100644
--- a/board/enclustra/common/Kconfig
+++ b/board/enclustra/common/Kconfig
@@ -1 +1,24 @@
+config ENCLUSTRA_EEPROM_MAC
+	bool "Enclustra MAC address"
+	select ATSHA204A
+	default y if TARGET_SOCFPGA_ENCLUSTRA_MERCURY_AA1
+	help
+	  Reads the MAC address out of the EEPROM and configures the MAC
+	  addresses in the environment.
+
+choice
+	prompt "Enclustra EEPROM device"
+	depends on ENCLUSTRA_EEPROM_MAC
+	default ENCLUSTRA_EEPROM_MAC_ATSHA204 if TARGET_SOCFPGA_ENCLUSTRA_MERCURY_AA1
+	help
+	  Specify the device where the MAC is stored.
+
+config ENCLUSTRA_EEPROM_MAC_ATSHA204
+	bool "MAC stored in 'ATSHA204'"
+
+config ENCLUSTRA_EEPROM_MAC_DS28
+	bool "MAC stored in 'DS28'"
+
+endchoice
+
 source "board/enclustra/mercury_aa1/Kconfig"
diff --git a/board/enclustra/common/Makefile b/board/enclustra/common/Makefile
index 16c8531d74..c83743abe7 100644
--- a/board/enclustra/common/Makefile
+++ b/board/enclustra/common/Makefile
@@ -2,3 +2,6 @@
 # Copyright (c) 2024 Enclustra GmbH
 
 # Common for several Enclustra modules
+obj-$(CONFIG_ENCLUSTRA_EEPROM_MAC) += mac_common.o
+obj-$(CONFIG_ENCLUSTRA_EEPROM_MAC_ATSHA204) += mac_atsha204.o
+obj-$(CONFIG_ENCLUSTRA_EEPROM_MAC_DS28) += mac_ds28.o
diff --git a/board/enclustra/common/enclustra_mac.h b/board/enclustra/common/enclustra_mac.h
new file mode 100644
index 0000000000..9631e9d458
--- /dev/null
+++ b/board/enclustra/common/enclustra_mac.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright 2024 Enclustra GmbH, <info@enclustra.com>
+ */
+
+#ifndef ENCLUSTRA_MAC
+# define ENCLUSTRA_MAC               0xF7B020
+#endif
+
+/*
+ * enclustra_mac_is_in_env - Check if MAC address is already set
+ *
+ * @env: name of the environment variable
+ * Return: true if MAC is set, false otherwise
+ */
+bool enclustra_mac_is_in_env(const char *env);
+
+/*
+ * enclustra_get_mac_is_enabled - Test if ethernet MAC is enabled in DT
+ *
+ * @alias: alias for ethernet MAC device tree node
+ * Return: 0 if OK, other value on error
+ */
+int enclustra_get_mac_is_enabled(const char *alias);
+
+/*
+ * enclustra_get_mac_from_eeprom - Get MAC address from eeprom and write it to enetaddr
+ *
+ * @enetaddr: buffer where address is to be stored
+ * @alias: alias for EEPROM device tree node
+ * Return: 0 if OK, other value on error
+ */
+int enclustra_get_mac_from_eeprom(unsigned char *enetaddr, const char *alias);
+
+/*
+ * enclustra_get_mac1_from_mac - Get MAC1 address from MAC and write it to enetaddr
+ *
+ * @enetaddr: buffer where MAC is passed, MAC will be modified to MAC1
+ * Return: 0 if OK, else error value
+ */
+int enclustra_get_mac1_from_mac(unsigned char *enetaddr);
+
+/*
+ * enclustra_setup_mac_address - Try to get MAC address from various locations and write it to env
+ *
+ * Return: 0 if OK, other value on error
+ */
+int enclustra_setup_mac_address(void);
diff --git a/board/enclustra/common/mac_atsha204.c b/board/enclustra/common/mac_atsha204.c
new file mode 100644
index 0000000000..4bd25505d6
--- /dev/null
+++ b/board/enclustra/common/mac_atsha204.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024 Enclustra GmbH
+ */
+
+#include <dm.h>
+#include <atsha204a-i2c.h>
+#include <net.h>
+
+#include "enclustra_mac.h"
+
+int enclustra_get_mac_from_eeprom(unsigned char *enetaddr, const char *alias)
+{
+	struct udevice *dev;
+	u32 hwaddr_h;
+	u8 data[4];
+	int i, j, eeprom_addr, mac_len, ret;
+
+	ret = uclass_get_device_by_name(UCLASS_MISC, alias, &dev);
+	if (ret) {
+		printf("%s: Failed, cannot find EEPROM! ret = %d\n", __func__, ret);
+		return ret;
+	}
+
+	/* Make sure atsha204a is in a defined state (part of protocol) */
+	if (atsha204a_sleep(dev)) {
+		printf("%s(): Failed to bring EEPROM in defined state\n", __func__);
+		return -ENODEV;
+	}
+
+	if (atsha204a_wakeup(dev)) {
+		printf("%s(): Failed to wakeup EEPROM\n", __func__);
+		return -ENODEV;
+	}
+
+	/* Read twice portions of 4 bytes (atsha204 protocol). One from address 4
+	 * the other from address 5 of the OTP zone. Then convert the data to
+	 * the 6 elements of the MAC address.
+	 */
+	eeprom_addr = 4;
+	mac_len = 6;
+	for (i = 0; i < 2; i++) {
+		eeprom_addr += i;
+		if (atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, eeprom_addr, data)) {
+			printf("%s(): Failed to parse ATSHA204A_ZONE_OTP of EEPROM\n",
+			       __func__);
+			return -EFAULT;
+		}
+
+		for (j = 0; j < 4 && j + i * 4 < mac_len; j++)
+			enetaddr[j + i * 4] = data[j];
+	}
+
+	/* Check if the value is a valid mac registered for
+	 * Enclustra  GmbH
+	 */
+	hwaddr_h = enetaddr[0] | enetaddr[1] << 8 | enetaddr[2] << 16;
+	if ((hwaddr_h & 0xFFFFFF) != ENCLUSTRA_MAC) {
+		printf("%s(): Failed, parsed MAC is no Enclustra MAC\n", __func__);
+		return -ENOENT;
+	}
+
+	if (!is_valid_ethaddr(enetaddr)) {
+		printf("%s(): Failed, address read from EEPROM is invalid!\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	printf("ethaddr set to %02X:%02X:%02X:%02X:%02X:%02X\n",
+	       enetaddr[0], enetaddr[1], enetaddr[2],
+	       enetaddr[3], enetaddr[4], enetaddr[5]);
+
+	return 0;
+}
+
+__weak int enclustra_setup_mac_address(void)
+{
+	unsigned char enetaddr[6];
+
+	if (enclustra_mac_is_in_env("ethaddr"))
+		return 0;
+
+	if (enclustra_get_mac_is_enabled("ethernet0"))
+		return 0;
+
+	if (enclustra_get_mac_from_eeprom(enetaddr, "atsha204a@64"))
+		return -ENXIO;
+
+	if (eth_env_set_enetaddr("ethaddr", enetaddr))
+		return -ENXIO;
+
+	if (!enclustra_get_mac1_from_mac(enetaddr))
+		return eth_env_set_enetaddr("eth1addr", enetaddr);
+
+	printf("%s(): Failed, unable to set mac address!\n", __func__);
+	return -ENXIO;
+}
diff --git a/board/enclustra/common/mac_common.c b/board/enclustra/common/mac_common.c
new file mode 100644
index 0000000000..cf5dac0e0e
--- /dev/null
+++ b/board/enclustra/common/mac_common.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024 Enclustra GmbH
+ */
+
+#include <dm.h>
+#include <atsha204a-i2c.h>
+#include <net.h>
+
+#include "enclustra_mac.h"
+
+bool enclustra_mac_is_in_env(const char *env)
+{
+	unsigned char enetaddr[6];
+
+	return eth_env_get_enetaddr(env, enetaddr);
+}
+
+int enclustra_get_mac_is_enabled(const char *alias)
+{
+	ofnode node =   ofnode_path(alias);
+
+	if (!ofnode_valid(node))
+		return -EINVAL;
+
+	if (!ofnode_is_enabled(node))
+		return -EINVAL;
+
+	return 0;
+}
+
+int enclustra_get_mac1_from_mac(unsigned char *enetaddr)
+{
+	u32 hwaddr_h;
+
+	/* Increment MAC addr */
+	hwaddr_h = (enetaddr[3] << 16) | (enetaddr[4] << 8) | enetaddr[5];
+	hwaddr_h = (hwaddr_h + 1) & 0xFFFFFF;
+	enetaddr[3] = (hwaddr_h >> 16) & 0xFF;
+	enetaddr[4] = (hwaddr_h >> 8) & 0xFF;
+	enetaddr[5] = hwaddr_h & 0xFF;
+
+	if (!is_valid_ethaddr(enetaddr)) {
+		printf("%s(): Failed, address computed from enetaddr is invalid!\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	printf("eth1addr set to %02X:%02X:%02X:%02X:%02X:%02X\n",
+	       enetaddr[0], enetaddr[1], enetaddr[2],
+	       enetaddr[3], enetaddr[4], enetaddr[5]);
+
+	return 0;
+}
diff --git a/board/enclustra/common/mac_ds28.c b/board/enclustra/common/mac_ds28.c
new file mode 100644
index 0000000000..9aed4f1de1
--- /dev/null
+++ b/board/enclustra/common/mac_ds28.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024 Enclustra GmbH
+ */
+
+#include <linux/compat.h>
+#include <dm.h>
+#include <i2c.h>
+#include <net.h>
+
+#include "enclustra_mac.h"
+
+#define DS28_I2C_ADDR 0x5C
+#define DS28_SYS_I2C_EEPROM_BUS 0
+
+int enclustra_get_mac_from_eeprom(unsigned char *enetaddr, const char *alias)
+{
+	struct udevice *dev;
+	u32 hwaddr_h;
+	struct dm_i2c_chip *chip;
+	uint chip_addr = DS28_I2C_ADDR;
+	int alen = 1;
+	int ret;
+
+	if (i2c_get_chip_for_busnum(DS28_SYS_I2C_EEPROM_BUS, chip_addr,
+				    alen, &dev))
+		return -ENODEV;
+
+	chip = dev_get_parent_plat(dev);
+	if (chip->offset_len != alen) {
+		debug("I2C chip %x: alen %d does not match offset_len %d\n",
+		      chip_addr, alen, chip->offset_len);
+		return -EADDRNOTAVAIL;
+	}
+
+	ret = dm_i2c_read(dev, 0x10, enetaddr, 6);
+	if (ret) {
+		printf("%s(): Failed reading EEPROM! ret = %d\n", __func__, ret);
+		return ret;
+	}
+
+	/* Check if the value is a valid mac registered for
+	 * Enclustra  GmbH
+	 */
+	hwaddr_h = enetaddr[0] | enetaddr[1] << 8 | enetaddr[2] << 16;
+	if ((hwaddr_h & 0xFFFFFF) != ENCLUSTRA_MAC) {
+		printf("%s(): Failed, parsed MAC is no Enclustra MAC\n", __func__);
+		return -ENOENT;
+	}
+
+	if (!is_valid_ethaddr(enetaddr)) {
+		printf("%s(): Failed, address read from EEPROM is invalid!\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	printf("ethaddr set to %02X:%02X:%02X:%02X:%02X:%02X\n",
+	       enetaddr[0], enetaddr[1], enetaddr[2],
+	       enetaddr[3], enetaddr[4], enetaddr[5]);
+
+	return 0;
+}
+
+__weak int enclustra_setup_mac_address(void)
+{
+	unsigned char enetaddr[6];
+
+	if (enclustra_mac_is_in_env("ethaddr"))
+		return 0;
+
+	if (enclustra_get_mac_is_enabled("ethernet0"))
+		return 0;
+
+	// NB: DS28 is still not available in official DT, so referencing
+	// here by i2c busnumber and address directly
+	// preparation for DT access here, though
+	if (enclustra_get_mac_from_eeprom(enetaddr, ""))
+		return -ENXIO;
+
+	if (eth_env_set_enetaddr("ethaddr", enetaddr))
+		return -ENXIO;
+
+	if (!enclustra_get_mac1_from_mac(enetaddr))
+		return eth_env_set_enetaddr("eth1addr", enetaddr);
+
+	printf("%s(): Failed, unable to set mac address!\n", __func__);
+	return -ENXIO;
+}
diff --git a/board/enclustra/mercury_aa1/mercury_aa1.c b/board/enclustra/mercury_aa1/mercury_aa1.c
index 7de9b287d9..c53ae128f0 100644
--- a/board/enclustra/mercury_aa1/mercury_aa1.c
+++ b/board/enclustra/mercury_aa1/mercury_aa1.c
@@ -11,6 +11,8 @@
 #include <asm-generic/gpio.h>
 #include <asm/io.h>
 
+#include "../common/enclustra_mac.h"
+
 /* Pin muxing */
 #if !defined(CONFIG_SPL_BUILD)
 
@@ -27,6 +29,11 @@ static int altera_current_storage = ALTERA_NONE;
 
 #endif
 
+int board_late_init(void)
+{
+	return enclustra_setup_mac_address();
+}
+
 #if !defined(CONFIG_SPL_BUILD)
 
 static void set_mux_mmc(void)
diff --git a/configs/socfpga_enclustra_mercury_aa1_defconfig b/configs/socfpga_enclustra_mercury_aa1_defconfig
index b475bd916d..58c718864b 100644
--- a/configs/socfpga_enclustra_mercury_aa1_defconfig
+++ b/configs/socfpga_enclustra_mercury_aa1_defconfig
@@ -26,6 +26,7 @@ CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
 CONFIG_SYS_CONSOLE_ENV_OVERWRITE=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_BOARD_LATE_INIT=y
 CONFIG_CLOCKS=y
 CONFIG_SPL_PAD_TO=0x40000
 CONFIG_SPL_NO_BSS_LIMIT=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6009d55f40..90fa8c9eae 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -73,7 +73,7 @@ config ATSHA204A
 	help
 	   Enable support for I2C connected Atmel's ATSHA204A
 	   CryptoAuthentication module found for example on the Turris Omnia
-	   board.
+	   board and Enclustra SoC FPGA boards.
 
 config GATEWORKS_SC
 	bool "Gateworks System Controller Support"
-- 
2.25.1


  parent reply	other threads:[~2024-09-12  6:14 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-12  6:06 [PATCH 0/9] add support for Enclustra Mercury AA1 SoMs Lothar Rubusch
2024-09-12  6:06 ` [PATCH 1/9] doc: board: enclustra: add Enclustra Intel AA1 SoM Lothar Rubusch
2024-09-12 23:01   ` Marek Vasut
2024-09-14 20:08     ` Lothar Rubusch
2024-09-12  6:06 ` [PATCH 2/9] ARM: dts: socfpga: add Enclustra Intel AA1 Lothar Rubusch
2024-09-12 23:02   ` Marek Vasut
2024-09-14 20:14     ` Lothar Rubusch
2024-09-25 22:49     ` Lothar Rubusch
2024-09-26  1:33       ` Marek Vasut
2024-09-26 22:53         ` Lothar Rubusch
2024-09-26 23:13           ` Marek Vasut
2024-09-27 22:47             ` Lothar Rubusch
2024-09-29 15:20               ` Marek Vasut
2024-09-29 19:19                 ` Lothar Rubusch
2024-10-05  1:23                   ` Marek Vasut
2024-10-07 10:20                     ` Sumit Garg
2024-10-07 13:59                       ` Lothar Rubusch
2024-09-12  6:06 ` [PATCH 3/9] ARM: socfpga: add Enclustra AA1 SoM support Lothar Rubusch
2024-09-12 17:45   ` Tom Rini
2024-09-14 20:17     ` Lothar Rubusch
2024-09-16 20:42       ` Tom Rini
2024-09-12  6:06 ` [PATCH 4/9] ARM: socfpga: add Enclustra AA1 extra env settings Lothar Rubusch
2024-09-12  6:06 ` [PATCH 5/9] ARM: socfpga: add Enclustra AA1 demo env files Lothar Rubusch
2024-09-12  6:06 ` [PATCH 6/9] ARM: socfpga: add Enclustra AA1 boot scripts Lothar Rubusch
2024-09-12  6:06 ` Lothar Rubusch [this message]
2024-09-12  6:06 ` [PATCH 8/9] ARM: socfpga: add si5338 clock generator support Lothar Rubusch
2024-09-12 23:04   ` Marek Vasut
2024-09-14 20:05     ` Lothar Rubusch
2024-09-12  6:06 ` [PATCH 9/9] ARM: socfpga: make AA1 use si5338 clock gen Lothar Rubusch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240912060649.190-8-l.rubusch@gmail.com \
    --to=l.rubusch@gmail.com \
    --cc=marex@denx.de \
    --cc=simon.k.r.goldschmidt@gmail.com \
    --cc=tien.fong.chee@intel.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.