1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
4 * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
5 */
6
7 #include <env.h>
8 #include <net.h>
9 #include <dm/device.h>
10 #include <dm/uclass.h>
11 #include <atsha204a-i2c.h>
12
13 #include "turris_atsha_otp.h"
14 #include "turris_common.h"
15
16 #define TURRIS_ATSHA_OTP_VERSION 0
17 #define TURRIS_ATSHA_OTP_SERIAL 1
18 #define TURRIS_ATSHA_OTP_MAC0 3
19 #define TURRIS_ATSHA_OTP_MAC1 4
20
21 extern U_BOOT_DRIVER(atsha204);
22
get_atsha204a_dev(void)23 static struct udevice *get_atsha204a_dev(void)
24 {
25 /* Cannot be static because BSS does not have to be ready at this early stage */
26 struct udevice *dev;
27
28 if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(atsha204), &dev)) {
29 puts("Cannot find ATSHA204A on I2C bus!\n");
30 dev = NULL;
31 }
32
33 return dev;
34 }
35
turris_atsha_otp_init_mac_addresses(int first_idx)36 int turris_atsha_otp_init_mac_addresses(int first_idx)
37 {
38 struct udevice *dev = get_atsha204a_dev();
39 u8 mac0[4], mac1[4], mac[6];
40 int ret;
41
42 if (!dev)
43 return -1;
44
45 ret = atsha204a_wakeup(dev);
46 if (ret)
47 return ret;
48
49 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
50 TURRIS_ATSHA_OTP_MAC0, mac0);
51 if (ret)
52 return ret;
53
54 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
55 TURRIS_ATSHA_OTP_MAC1, mac1);
56 if (ret)
57 return ret;
58
59 atsha204a_sleep(dev);
60
61 mac[0] = mac0[1];
62 mac[1] = mac0[2];
63 mac[2] = mac0[3];
64 mac[3] = mac1[1];
65 mac[4] = mac1[2];
66 mac[5] = mac1[3];
67
68 turris_init_mac_addresses(first_idx, mac);
69
70 return 0;
71 }
72
turris_atsha_otp_init_serial_number(void)73 int turris_atsha_otp_init_serial_number(void)
74 {
75 char serial[17];
76 int ret;
77
78 ret = turris_atsha_otp_get_serial_number(serial);
79 if (ret)
80 return ret;
81
82 if (!env_get("serial#"))
83 return -1;
84
85 return 0;
86 }
87
turris_atsha_otp_get_serial_number(char serial[17])88 int turris_atsha_otp_get_serial_number(char serial[17])
89 {
90 struct udevice *dev = get_atsha204a_dev();
91 u32 version_num, serial_num;
92 const char *serial_env;
93 int ret;
94
95 if (!dev)
96 return -1;
97
98 serial_env = env_get("serial#");
99 if (serial_env && strlen(serial_env) == 16) {
100 memcpy(serial, serial_env, 17);
101 return 0;
102 }
103
104 ret = atsha204a_wakeup(dev);
105 if (ret)
106 return ret;
107
108 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
109 TURRIS_ATSHA_OTP_VERSION,
110 (u8 *)&version_num);
111 if (ret)
112 return ret;
113
114 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
115 TURRIS_ATSHA_OTP_SERIAL,
116 (u8 *)&serial_num);
117 if (ret)
118 return ret;
119
120 atsha204a_sleep(dev);
121
122 sprintf(serial, "%08X%08X", be32_to_cpu(version_num), be32_to_cpu(serial_num));
123 env_set("serial#", serial);
124
125 return 0;
126 }
127