All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Marek Behún" <kabel@kernel.org>
To: Stefan Roese <sr@denx.de>
Cc: u-boot@lists.denx.de, "Marek Behún" <kabel@kernel.org>
Subject: [PATCH u-boot-mvebu 2/4] arm: mvebu: turris_omnia: Implement getting board information from MCU
Date: Mon,  4 Mar 2024 16:21:46 +0100	[thread overview]
Message-ID: <20240304152148.3847-3-kabel@kernel.org> (raw)
In-Reply-To: <20240304152148.3847-1-kabel@kernel.org>

Implement reading board serial number, first MAC address and board
version from MCU. MCU supports board information if the FEAT_BOARD_INFO
feature bit is set in MCU features.

Prefer getting board information from MCU if supported, fallback to
Atmel SHA chip.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 board/CZ.NIC/turris_atsha_otp.c          | 27 +------
 board/CZ.NIC/turris_common.c             | 42 ++++++++++
 board/CZ.NIC/turris_common.h             | 10 +++
 board/CZ.NIC/turris_omnia/Makefile       |  2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 98 +++++++++++++++++++++++-
 5 files changed, 149 insertions(+), 30 deletions(-)
 create mode 100644 board/CZ.NIC/turris_common.c
 create mode 100644 board/CZ.NIC/turris_common.h

diff --git a/board/CZ.NIC/turris_atsha_otp.c b/board/CZ.NIC/turris_atsha_otp.c
index a29fe362317..85eebcdf18e 100644
--- a/board/CZ.NIC/turris_atsha_otp.c
+++ b/board/CZ.NIC/turris_atsha_otp.c
@@ -11,6 +11,7 @@
 #include <atsha204a-i2c.h>
 
 #include "turris_atsha_otp.h"
+#include "turris_common.h"
 
 #define TURRIS_ATSHA_OTP_VERSION	0
 #define TURRIS_ATSHA_OTP_SERIAL		1
@@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
 	return dev;
 }
 
-static void increment_mac(u8 *mac)
-{
-	int i;
-
-	for (i = 5; i >= 3; i--) {
-		mac[i] += 1;
-		if (mac[i])
-			break;
-	}
-}
-
-static void set_mac_if_invalid(int i, u8 *mac)
-{
-	u8 oldmac[6];
-
-	if (is_valid_ethaddr(mac) &&
-	    !eth_env_get_enetaddr_by_index("eth", i, oldmac))
-		eth_env_set_enetaddr_by_index("eth", i, mac);
-}
-
 int turris_atsha_otp_init_mac_addresses(int first_idx)
 {
 	struct udevice *dev = get_atsha204a_dev();
@@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
 	mac[4] = mac1[2];
 	mac[5] = mac1[3];
 
-	set_mac_if_invalid((first_idx + 0) % 3, mac);
-	increment_mac(mac);
-	set_mac_if_invalid((first_idx + 1) % 3, mac);
-	increment_mac(mac);
-	set_mac_if_invalid((first_idx + 2) % 3, mac);
+	turris_init_mac_addresses(first_idx, mac);
 
 	return 0;
 }
diff --git a/board/CZ.NIC/turris_common.c b/board/CZ.NIC/turris_common.c
new file mode 100644
index 00000000000..1717dda82eb
--- /dev/null
+++ b/board/CZ.NIC/turris_common.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
+ */
+
+#include <env.h>
+#include <net.h>
+
+#include "turris_common.h"
+
+static void increment_mac(u8 *mac)
+{
+	int i;
+
+	for (i = 5; i >= 3; i--) {
+		mac[i] += 1;
+		if (mac[i])
+			break;
+	}
+}
+
+static void set_mac_if_invalid(int i, u8 *mac)
+{
+	u8 oldmac[6];
+
+	if (is_valid_ethaddr(mac) &&
+	    !eth_env_get_enetaddr_by_index("eth", i, oldmac))
+		eth_env_set_enetaddr_by_index("eth", i, mac);
+}
+
+void turris_init_mac_addresses(int first_idx, const u8 *first_mac)
+{
+	u8 mac[6];
+
+	memcpy(mac, first_mac, sizeof(mac));
+
+	set_mac_if_invalid((first_idx + 0) % 3, mac);
+	increment_mac(mac);
+	set_mac_if_invalid((first_idx + 1) % 3, mac);
+	increment_mac(mac);
+	set_mac_if_invalid((first_idx + 2) % 3, mac);
+}
diff --git a/board/CZ.NIC/turris_common.h b/board/CZ.NIC/turris_common.h
new file mode 100644
index 00000000000..5565ea9fd2a
--- /dev/null
+++ b/board/CZ.NIC/turris_common.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef TURRIS_COMMON_H
+#define TURRIS_COMMON_H
+
+#include <asm/types.h>
+
+void turris_init_mac_addresses(int first_idx, const u8 *first_mac);
+
+#endif
diff --git a/board/CZ.NIC/turris_omnia/Makefile b/board/CZ.NIC/turris_omnia/Makefile
index dc39b44ae19..341378b4e54 100644
--- a/board/CZ.NIC/turris_omnia/Makefile
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -2,4 +2,4 @@
 #
 # Copyright (C) 2017 Marek Behún <kabel@kernel.org>
 
-obj-y	:= turris_omnia.o ../turris_atsha_otp.o
+obj-y	:= turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
index b285e959d06..7a51ed3ace5 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -18,18 +18,21 @@
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
+#include <asm/unaligned.h>
 #include <dm/uclass.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <fdt_support.h>
 #include <hexdump.h>
 #include <time.h>
 #include <linux/bitops.h>
+#include <linux/bitrev.h>
 #include <linux/delay.h>
 #include <u-boot/crc.h>
 
 #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
 #include <../serdes/a38x/high_speed_env_spec.h>
 #include "../turris_atsha_otp.h"
+#include "../turris_common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -71,6 +74,9 @@ enum mcu_commands {
 
 	/* available if EXT_CMD bit set in features */
 	CMD_EXT_CONTROL		= 0x12,
+
+	/* available if BOARD_INFO it set in features */
+	CMD_BOARD_INFO_GET	= 0x2c,
 };
 
 enum status_word_bits {
@@ -88,6 +94,7 @@ enum status_word_bits {
 enum features_e {
 	FEAT_PERIPH_MCU		= BIT(0),
 	FEAT_EXT_CMDS		= BIT(1),
+	FEAT_BOARD_INFO		= BIT(15),
 };
 
 /* CMD_EXT_CONTROL */
@@ -214,6 +221,70 @@ static bool omnia_mcu_has_feature(u16 feature)
 	return feature & features;
 }
 
+static u32 omnia_mcu_crc32(const void *p, size_t len)
+{
+	u32 val, crc = 0;
+
+	compiletime_assert(!(len % 4), "length has to be a multiple of 4");
+
+	while (len) {
+		val = bitrev32(get_unaligned_le32(p));
+		crc = crc32(crc, (void *)&val, 4);
+		p += 4;
+		len -= 4;
+	}
+
+	return ~bitrev32(crc);
+}
+
+/* Can only be called after relocation, since it needs cleared BSS */
+static int omnia_mcu_board_info(char *serial, u8 *mac, char *version)
+{
+	static u8 reply[17];
+	static bool cached;
+
+	if (!cached) {
+		u8 csum;
+		int ret;
+
+		ret = omnia_mcu_read(CMD_BOARD_INFO_GET, reply, sizeof(reply));
+		if (ret)
+			return ret;
+
+		if (reply[0] != 16)
+			return -EBADMSG;
+
+		csum = reply[16];
+		reply[16] = 0;
+
+		if ((omnia_mcu_crc32(&reply[1], 16) & 0xff) != csum)
+			return -EBADMSG;
+
+		cached = true;
+	}
+
+	if (serial) {
+		const char *serial_env;
+
+		serial_env = env_get("serial#");
+		if (serial_env && strlen(serial_env) == 16) {
+			strcpy(serial, serial_env);
+		} else {
+			sprintf(serial, "%016llX",
+				get_unaligned_le64(&reply[1]));
+			env_set("serial#", serial);
+		}
+	}
+
+	if (mac)
+		memcpy(mac, &reply[9], ETH_ALEN);
+
+	if (version)
+		sprintf(version, "%u", reply[15]);
+
+	return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
 	struct sar_freq_modes sar_freq;
@@ -989,14 +1060,24 @@ int board_late_init(void)
 
 int checkboard(void)
 {
-	char serial[17];
+	char serial[17], version[4];
+	bool has_version;
 	int err;
 
-	err = turris_atsha_otp_get_serial_number(serial);
 	printf("Model: Turris Omnia\n");
 	printf("  MCU type: %s\n", omnia_get_mcu_type());
 	printf("  MCU version: %s\n", omnia_get_mcu_version());
 	printf("  RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
+
+	if (omnia_mcu_has_feature(FEAT_BOARD_INFO)) {
+		err = omnia_mcu_board_info(serial, NULL, version);
+		has_version = !err;
+	} else {
+		err = turris_atsha_otp_get_serial_number(serial);
+		has_version = false;
+	}
+
+	printf("  Board version: %s\n", has_version ? version : "unknown");
 	printf("  Serial Number: %s\n", !err ? serial : "unknown");
 
 	return 0;
@@ -1004,8 +1085,17 @@ int checkboard(void)
 
 int misc_init_r(void)
 {
-	turris_atsha_otp_init_mac_addresses(1);
-	turris_atsha_otp_init_serial_number();
+	if (omnia_mcu_has_feature(FEAT_BOARD_INFO)) {
+		char serial[17];
+		u8 first_mac[6];
+
+		if (!omnia_mcu_board_info(serial, first_mac, NULL))
+			turris_init_mac_addresses(1, first_mac);
+	} else {
+		turris_atsha_otp_init_mac_addresses(1);
+		turris_atsha_otp_init_serial_number();
+	}
+
 	return 0;
 }
 
-- 
2.43.0


  parent reply	other threads:[~2024-03-04 15:22 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-04 15:21 [PATCH u-boot-mvebu 0/4] Turris Omnia - New board revision support Marek Behún
2024-03-04 15:21 ` [PATCH u-boot-mvebu 1/4] arm: mvebu: turris_omnia: Refactor MCU status and features reading Marek Behún
2024-03-04 15:21 ` Marek Behún [this message]
2024-03-04 15:21 ` [PATCH u-boot-mvebu 3/4] arm: mvebu: turris_omnia: Print board ECDSA public key if available Marek Behún
2024-03-04 15:21 ` [PATCH u-boot-mvebu 4/4] arm: mvebu: turris_omnia: Disable Atmel SHA node if not present Marek Behún
2024-03-23 16:58 ` [PATCH u-boot-mvebu 0/4] Turris Omnia - New board revision support Marek Behún

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=20240304152148.3847-3-kabel@kernel.org \
    --to=kabel@kernel.org \
    --cc=sr@denx.de \
    --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.