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 <frieder.schrempf@kontron.de>
This commit is contained in:
committed by
Fabio Estevam
parent
0089270b45
commit
f00b09abbf
14
board/kontron/common/Kconfig
Normal file
14
board/kontron/common/Kconfig
Normal file
@@ -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.
|
||||
1
board/kontron/common/Makefile
Normal file
1
board/kontron/common/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
obj-$(CONFIG_KONTRON_HW_UID) += hw-uid.o
|
||||
75
board/kontron/common/hw-uid.c
Normal file
75
board/kontron/common/hw-uid.c
Normal file
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2024 Kontron Electronics GmbH
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <compiler.h>
|
||||
#include <asm/io.h>
|
||||
#include <env.h>
|
||||
#include <string.h>
|
||||
#include <vsprintf.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
26
board/kontron/common/hw-uid.h
Normal file
26
board/kontron/common/hw-uid.h
Normal file
@@ -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 <compiler.h>
|
||||
#include <stddef.h>
|
||||
|
||||
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 */
|
||||
Reference in New Issue
Block a user