From: Marek Behún Date: Thu, 4 Apr 2024 07:50:54 +0000 (+0200) Subject: arm: mvebu: turris_omnia: Implement getting board information from MCU X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=2f1b88affad2094aeab4cd617e22e79ee9dc22a3;p=u-boot.git arm: mvebu: turris_omnia: Implement getting board information from MCU 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 Reviewed-by: Stefan Roese --- diff --git a/board/CZ.NIC/turris_atsha_otp.c b/board/CZ.NIC/turris_atsha_otp.c index a29fe36231..85eebcdf18 100644 --- a/board/CZ.NIC/turris_atsha_otp.c +++ b/board/CZ.NIC/turris_atsha_otp.c @@ -11,6 +11,7 @@ #include #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 0000000000..1717dda82e --- /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 + */ + +#include +#include + +#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 0000000000..5565ea9fd2 --- /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 + +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 dc39b44ae1..341378b4e5 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 -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 6dfde5ee7a..f63640ad64 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,12 +26,14 @@ #include #include #include +#include #include #include #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; @@ -186,6 +189,70 @@ static bool omnia_mcu_has_feature(u32 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; @@ -965,13 +1032,23 @@ 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(" 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; @@ -979,8 +1056,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; }