From: Frieder Schrempf Date: Tue, 4 Nov 2025 12:54:26 +0000 (+0100) Subject: imx: kontron: Add common function to get HW UIDs from OTPs X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f00b09abbf18b9cc91311b0330f4f49fc1917019;p=thirdparty%2Fu-boot.git imx: kontron: Add common function to get HW UIDs from OTPs The factory provides a CPU UID in the OTPs and the SoM module and the carrier board might provide additional UIDs in the GP registers of the OTPs. Provide a common function to load UIDs from arbitrary OTP registers and generate a serial number string that is saved in the "serial#" env variable. Signed-off-by: Frieder Schrempf --- diff --git a/board/kontron/common/Kconfig b/board/kontron/common/Kconfig new file mode 100644 index 00000000000..d581006c203 --- /dev/null +++ b/board/kontron/common/Kconfig @@ -0,0 +1,14 @@ +menuconfig KONTRON_HW_UID + bool "Enable reading Kontron HW UID from OTP fuses" + help + Enable support for reading Kontron hardware UIDs from OTP fuse registers. + The UIDs are factory-programmed for SoMs and boards and are printed to the + console and used as serial numbers if this option is enabled. + +menuconfig KONTRON_HW_UID_USE_SOC_FALLBACK + bool "Use the unique ID of the SoC as fallback serial number" + depends on KONTRON_HW_UID + default n + help + Enable the fallback to the UID of the SoC programmed by the SoC + manufacturer if no Kontron UID is found in the OTP fuses. diff --git a/board/kontron/common/Makefile b/board/kontron/common/Makefile new file mode 100644 index 00000000000..634744dc542 --- /dev/null +++ b/board/kontron/common/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KONTRON_HW_UID) += hw-uid.o diff --git a/board/kontron/common/hw-uid.c b/board/kontron/common/hw-uid.c new file mode 100644 index 00000000000..5358b1dfcf1 --- /dev/null +++ b/board/kontron/common/hw-uid.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Kontron Electronics GmbH + */ + +#include +#include +#include +#include +#include +#include + +#include "hw-uid.h" + +int get_serial_str_from_otp(struct uid_otp_loc loc, char *str, size_t str_len) +{ + u64 uid; + int ret; + + if (loc.len < 1 || loc.len > 2) { + printf("Invalid number of UID OTP registers set!\n"); + return -EINVAL; + } + + uid = readl(loc.addr); + + if (loc.len == 2) + uid |= (u64)readl(loc.addr + 0x4) << 32; + + if (!uid) + return -ENOENT; + + if (uid) { + switch (loc.format) { + case UID_OTP_FORMAT_DEC: + ret = snprintf(str, str_len, "%010llu", uid); + break; + case UID_OTP_FORMAT_HEX: + ret = snprintf(str, str_len, "%016llX", uid); + break; + } + if (ret < 0 || ret >= str_len) { + printf("Failed to convert UID!\n"); + return -EFAULT; + } + } + + return 0; +} + +void get_serial_number(struct uid_otp_loc *locs, unsigned int num) +{ + char serial_string[17]; + unsigned int i; + int ret; + + for (i = 0; i < num; i++) { + ret = get_serial_str_from_otp(locs[i], serial_string, sizeof(serial_string)); + if (ret == 0) + break; + } + + /* No valid UID in the OTP fuses, skip. */ + if (ret) { + printf("Serial Number: None\n"); + return; + } + + printf("Serial Number: %s (%s)\n", serial_string, locs[i].desc); + + if (!env_get("serial#")) + env_set("serial#", serial_string); + else if (strcmp(env_get("serial#"), serial_string)) + printf("Warning: mismatch of UIDs in env and OTPs!\n"); +} diff --git a/board/kontron/common/hw-uid.h b/board/kontron/common/hw-uid.h new file mode 100644 index 00000000000..7eaf2cc9b6c --- /dev/null +++ b/board/kontron/common/hw-uid.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2024 Kontron Electronics GmbH + */ + +#ifndef _KONTRON_HW_UID_H +#define _KONTRON_HW_UID_H + +#include +#include + +enum { + UID_OTP_FORMAT_DEC = 0, + UID_OTP_FORMAT_HEX, +}; + +struct uid_otp_loc { + u32 *addr; + size_t len; + unsigned int format; + char *desc; +}; + +void get_serial_number(struct uid_otp_loc *locs, unsigned int num); + +#endif /* _KONTRON_HW_UID_H */