From 7f7deb0c72f559ab892c5f9013078c885120a64c Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 17 May 2018 15:24:07 +0200 Subject: stm32mp1: use OTP to configure MAC address and serial number Use OTP57 and 58 for MAC address - OTP57 = MAC address bits [31:0] - OTP58 = MAC address bit [47:32] stored in OTP LSB's Use manufacture information in OTP13 to OTP15 to build unique chip id saved in env variable "serial#" (used for USB device enumeration) Signed-off-by: Patrick Delaunay Signed-off-by: Patrice Chotard --- arch/arm/mach-stm32mp/cpu.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 2deee09618..0e01f8e613 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -5,9 +5,12 @@ #include #include #include +#include +#include #include #include #include +#include #include /* RCC register */ @@ -51,6 +54,10 @@ #define BOOTROM_INSTANCE_MASK GENMASK(31, 16) #define BOOTROM_INSTANCE_SHIFT 16 +/* BSEC OTP index */ +#define BSEC_OTP_SERIAL 13 +#define BSEC_OTP_MAC 57 + #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) static void security_init(void) { @@ -274,9 +281,83 @@ static void setup_boot_mode(void) } } +/* + * If there is no MAC address in the environment, then it will be initialized + * (silently) from the value in the OTP. + */ +static int setup_mac_address(void) +{ +#if defined(CONFIG_NET) + int ret; + int i; + u32 otp[2]; + uchar enetaddr[6]; + struct udevice *dev; + + /* MAC already in environment */ + if (eth_env_get_enetaddr("ethaddr", enetaddr)) + return 0; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET, + otp, sizeof(otp)); + if (ret) + return ret; + + for (i = 0; i < 6; i++) + enetaddr[i] = ((uint8_t *)&otp)[i]; + + if (!is_valid_ethaddr(enetaddr)) { + pr_err("invalid MAC address in OTP %pM", enetaddr); + return -EINVAL; + } + pr_debug("OTP MAC address = %pM\n", enetaddr); + ret = !eth_env_set_enetaddr("ethaddr", enetaddr); + if (!ret) + pr_err("Failed to set mac address %pM from OTP: %d\n", + enetaddr, ret); +#endif + + return 0; +} + +static int setup_serial_number(void) +{ + char serial_string[25]; + u32 otp[3] = {0, 0, 0 }; + struct udevice *dev; + int ret; + + if (env_get("serial#")) + return 0; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) + return ret; + + ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET, + otp, sizeof(otp)); + if (ret) + return ret; + + sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]); + env_set("serial#", serial_string); + + return 0; +} + int arch_misc_init(void) { setup_boot_mode(); + setup_mac_address(); + setup_serial_number(); return 0; } -- cgit