blob: 840721a9b737548aabaadb063e16a847e30db210 [file] [log] [blame]
Pali Rohár6ac08dc2022-04-08 16:30:12 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
4 * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
5 */
6
7#include <env.h>
8#include <net.h>
9#include <dm/uclass.h>
10#include <atsha204a-i2c.h>
11
12#include "turris_atsha_otp.h"
13
14#define TURRIS_ATSHA_OTP_VERSION 0
15#define TURRIS_ATSHA_OTP_SERIAL 1
16#define TURRIS_ATSHA_OTP_MAC0 3
17#define TURRIS_ATSHA_OTP_MAC1 4
18
19static struct udevice *get_atsha204a_dev(void)
20{
Pali Rohárada791d2022-04-08 16:30:13 +020021 /* Cannot be static because BSS does not have to be ready at this early stage */
22 struct udevice *dev;
Pali Rohár6ac08dc2022-04-08 16:30:12 +020023
24 if (uclass_get_device_by_name(UCLASS_MISC, "atsha204a@64", &dev)) {
25 puts("Cannot find ATSHA204A on I2C bus!\n");
26 dev = NULL;
27 }
28
29 return dev;
30}
31
32static void increment_mac(u8 *mac)
33{
34 int i;
35
36 for (i = 5; i >= 3; i--) {
37 mac[i] += 1;
38 if (mac[i])
39 break;
40 }
41}
42
43static void set_mac_if_invalid(int i, u8 *mac)
44{
45 u8 oldmac[6];
46
47 if (is_valid_ethaddr(mac) &&
48 !eth_env_get_enetaddr_by_index("eth", i, oldmac))
49 eth_env_set_enetaddr_by_index("eth", i, mac);
50}
51
52int turris_atsha_otp_init_mac_addresses(void)
53{
54 struct udevice *dev = get_atsha204a_dev();
55 u8 mac0[4], mac1[4], mac[6];
56 int ret;
57
58 if (!dev)
59 return -1;
60
61 ret = atsha204a_wakeup(dev);
62 if (ret)
63 return ret;
64
65 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
66 TURRIS_ATSHA_OTP_MAC0, mac0);
67 if (ret)
68 return ret;
69
70 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
71 TURRIS_ATSHA_OTP_MAC1, mac1);
72 if (ret)
73 return ret;
74
75 atsha204a_sleep(dev);
76
77 mac[0] = mac0[1];
78 mac[1] = mac0[2];
79 mac[2] = mac0[3];
80 mac[3] = mac1[1];
81 mac[4] = mac1[2];
82 mac[5] = mac1[3];
83
84 set_mac_if_invalid(1, mac);
85 increment_mac(mac);
86 set_mac_if_invalid(2, mac);
87 increment_mac(mac);
88 set_mac_if_invalid(0, mac);
89
90 return 0;
91}
92
93int turris_atsha_otp_get_serial_number(u32 *version_num, u32 *serial_num)
94{
95 struct udevice *dev = get_atsha204a_dev();
96 int ret;
97
98 if (!dev)
99 return -1;
100
101 ret = atsha204a_wakeup(dev);
102 if (ret)
103 return ret;
104
105 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
106 TURRIS_ATSHA_OTP_VERSION,
107 (u8 *)version_num);
108 if (ret)
109 return ret;
110
111 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
112 TURRIS_ATSHA_OTP_SERIAL,
113 (u8 *)serial_num);
114 if (ret)
115 return ret;
116
117 atsha204a_sleep(dev);
118 return 0;
119}