2022-04-08 14:30:12 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
|
|
|
/*
|
2022-06-01 15:17:06 +00:00
|
|
|
* Copyright (C) 2017 Marek Behún <kabel@kernel.org>
|
2022-04-08 14:30:12 +00:00
|
|
|
* Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <env.h>
|
|
|
|
#include <net.h>
|
2022-05-19 09:11:52 +00:00
|
|
|
#include <dm/device.h>
|
2022-04-08 14:30:12 +00:00
|
|
|
#include <dm/uclass.h>
|
|
|
|
#include <atsha204a-i2c.h>
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
2022-05-19 09:11:52 +00:00
|
|
|
extern U_BOOT_DRIVER(atsha204);
|
|
|
|
|
2022-04-08 14:30:12 +00:00
|
|
|
static struct udevice *get_atsha204a_dev(void)
|
|
|
|
{
|
2022-04-08 14:30:13 +00:00
|
|
|
/* Cannot be static because BSS does not have to be ready at this early stage */
|
|
|
|
struct udevice *dev;
|
2022-04-08 14:30:12 +00:00
|
|
|
|
2022-05-19 09:11:52 +00:00
|
|
|
if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(atsha204), &dev)) {
|
2022-04-08 14:30:12 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-04-08 14:30:14 +00:00
|
|
|
int turris_atsha_otp_init_mac_addresses(int first_idx)
|
2022-04-08 14:30:12 +00:00
|
|
|
{
|
|
|
|
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];
|
|
|
|
|
2022-04-08 14:30:14 +00:00
|
|
|
set_mac_if_invalid((first_idx + 0) % 3, mac);
|
2022-04-08 14:30:12 +00:00
|
|
|
increment_mac(mac);
|
2022-04-08 14:30:14 +00:00
|
|
|
set_mac_if_invalid((first_idx + 1) % 3, mac);
|
2022-04-08 14:30:12 +00:00
|
|
|
increment_mac(mac);
|
2022-04-08 14:30:14 +00:00
|
|
|
set_mac_if_invalid((first_idx + 2) % 3, mac);
|
2022-04-08 14:30:12 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-27 18:06:30 +00:00
|
|
|
int turris_atsha_otp_init_serial_number(void)
|
|
|
|
{
|
|
|
|
char serial[17];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = turris_atsha_otp_get_serial_number(serial);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (!env_get("serial#"))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int turris_atsha_otp_get_serial_number(char serial[17])
|
2022-04-08 14:30:12 +00:00
|
|
|
{
|
|
|
|
struct udevice *dev = get_atsha204a_dev();
|
2022-08-27 18:06:30 +00:00
|
|
|
u32 version_num, serial_num;
|
|
|
|
const char *serial_env;
|
2022-04-08 14:30:12 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!dev)
|
|
|
|
return -1;
|
|
|
|
|
2022-08-27 18:06:30 +00:00
|
|
|
serial_env = env_get("serial#");
|
|
|
|
if (serial_env && strlen(serial_env) == 16) {
|
|
|
|
memcpy(serial, serial_env, 17);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-04-08 14:30:12 +00:00
|
|
|
ret = atsha204a_wakeup(dev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
|
|
|
|
TURRIS_ATSHA_OTP_VERSION,
|
2022-08-27 18:06:30 +00:00
|
|
|
(u8 *)&version_num);
|
2022-04-08 14:30:12 +00:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
|
|
|
|
TURRIS_ATSHA_OTP_SERIAL,
|
2022-08-27 18:06:30 +00:00
|
|
|
(u8 *)&serial_num);
|
2022-04-08 14:30:12 +00:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
atsha204a_sleep(dev);
|
2022-08-27 18:06:30 +00:00
|
|
|
|
|
|
|
sprintf(serial, "%08X%08X", be32_to_cpu(version_num), be32_to_cpu(serial_num));
|
|
|
|
env_set("serial#", serial);
|
|
|
|
|
2022-04-08 14:30:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|