// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2017 Marek BehĂșn * Copyright (C) 2016 Tomas Hlavacek */ #include #include #include #include #include #include "turris_atsha_otp.h" #define TURRIS_ATSHA_OTP_VERSION 0 #define TURRIS_ATSHA_OTP_SERIAL 1 #define TURRIS_ATSHA_OTP_MAC0 3 #define TURRIS_ATSHA_OTP_MAC1 4 extern U_BOOT_DRIVER(atsha204); static struct udevice *get_atsha204a_dev(void) { /* Cannot be static because BSS does not have to be ready at this early stage */ struct udevice *dev; if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(atsha204), &dev)) { puts("Cannot find ATSHA204A on I2C bus!\n"); dev = NULL; } 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(); u8 mac0[4], mac1[4], mac[6]; int ret; if (!dev) return -1; ret = atsha204a_wakeup(dev); if (ret) return ret; ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, TURRIS_ATSHA_OTP_MAC0, mac0); if (ret) return ret; ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, TURRIS_ATSHA_OTP_MAC1, mac1); if (ret) return ret; atsha204a_sleep(dev); mac[0] = mac0[1]; mac[1] = mac0[2]; mac[2] = mac0[3]; mac[3] = mac1[1]; 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); return 0; } int turris_atsha_otp_get_serial_number(u32 *version_num, u32 *serial_num) { struct udevice *dev = get_atsha204a_dev(); int ret; if (!dev) return -1; ret = atsha204a_wakeup(dev); if (ret) return ret; ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, TURRIS_ATSHA_OTP_VERSION, (u8 *)version_num); if (ret) return ret; ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, TURRIS_ATSHA_OTP_SERIAL, (u8 *)serial_num); if (ret) return ret; atsha204a_sleep(dev); return 0; }