blob: a29fe36231749a86c0198ccb18c5e0104921b4d4 [file] [log] [blame]
Pali Rohár6ac08dc2022-04-08 16:30:12 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
Marek Behún61143f72022-06-01 17:17:06 +02003 * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
Pali Rohár6ac08dc2022-04-08 16:30:12 +02004 * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
5 */
6
7#include <env.h>
8#include <net.h>
Pali Roháre33879a2022-05-19 11:11:52 +02009#include <dm/device.h>
Pali Rohár6ac08dc2022-04-08 16:30:12 +020010#include <dm/uclass.h>
11#include <atsha204a-i2c.h>
12
13#include "turris_atsha_otp.h"
14
15#define TURRIS_ATSHA_OTP_VERSION 0
16#define TURRIS_ATSHA_OTP_SERIAL 1
17#define TURRIS_ATSHA_OTP_MAC0 3
18#define TURRIS_ATSHA_OTP_MAC1 4
19
Pali Roháre33879a2022-05-19 11:11:52 +020020extern U_BOOT_DRIVER(atsha204);
21
Pali Rohár6ac08dc2022-04-08 16:30:12 +020022static struct udevice *get_atsha204a_dev(void)
23{
Pali Rohárada791d2022-04-08 16:30:13 +020024 /* Cannot be static because BSS does not have to be ready at this early stage */
25 struct udevice *dev;
Pali Rohár6ac08dc2022-04-08 16:30:12 +020026
Pali Roháre33879a2022-05-19 11:11:52 +020027 if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(atsha204), &dev)) {
Pali Rohár6ac08dc2022-04-08 16:30:12 +020028 puts("Cannot find ATSHA204A on I2C bus!\n");
29 dev = NULL;
30 }
31
32 return dev;
33}
34
35static void increment_mac(u8 *mac)
36{
37 int i;
38
39 for (i = 5; i >= 3; i--) {
40 mac[i] += 1;
41 if (mac[i])
42 break;
43 }
44}
45
46static void set_mac_if_invalid(int i, u8 *mac)
47{
48 u8 oldmac[6];
49
50 if (is_valid_ethaddr(mac) &&
51 !eth_env_get_enetaddr_by_index("eth", i, oldmac))
52 eth_env_set_enetaddr_by_index("eth", i, mac);
53}
54
Pali Rohár98bbb6e2022-04-08 16:30:14 +020055int turris_atsha_otp_init_mac_addresses(int first_idx)
Pali Rohár6ac08dc2022-04-08 16:30:12 +020056{
57 struct udevice *dev = get_atsha204a_dev();
58 u8 mac0[4], mac1[4], mac[6];
59 int ret;
60
61 if (!dev)
62 return -1;
63
64 ret = atsha204a_wakeup(dev);
65 if (ret)
66 return ret;
67
68 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
69 TURRIS_ATSHA_OTP_MAC0, mac0);
70 if (ret)
71 return ret;
72
73 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
74 TURRIS_ATSHA_OTP_MAC1, mac1);
75 if (ret)
76 return ret;
77
78 atsha204a_sleep(dev);
79
80 mac[0] = mac0[1];
81 mac[1] = mac0[2];
82 mac[2] = mac0[3];
83 mac[3] = mac1[1];
84 mac[4] = mac1[2];
85 mac[5] = mac1[3];
86
Pali Rohár98bbb6e2022-04-08 16:30:14 +020087 set_mac_if_invalid((first_idx + 0) % 3, mac);
Pali Rohár6ac08dc2022-04-08 16:30:12 +020088 increment_mac(mac);
Pali Rohár98bbb6e2022-04-08 16:30:14 +020089 set_mac_if_invalid((first_idx + 1) % 3, mac);
Pali Rohár6ac08dc2022-04-08 16:30:12 +020090 increment_mac(mac);
Pali Rohár98bbb6e2022-04-08 16:30:14 +020091 set_mac_if_invalid((first_idx + 2) % 3, mac);
Pali Rohár6ac08dc2022-04-08 16:30:12 +020092
93 return 0;
94}
95
Pali Rohár7bb9ea42022-08-27 20:06:30 +020096int turris_atsha_otp_init_serial_number(void)
97{
98 char serial[17];
99 int ret;
100
101 ret = turris_atsha_otp_get_serial_number(serial);
102 if (ret)
103 return ret;
104
105 if (!env_get("serial#"))
106 return -1;
107
108 return 0;
109}
110
111int turris_atsha_otp_get_serial_number(char serial[17])
Pali Rohár6ac08dc2022-04-08 16:30:12 +0200112{
113 struct udevice *dev = get_atsha204a_dev();
Pali Rohár7bb9ea42022-08-27 20:06:30 +0200114 u32 version_num, serial_num;
115 const char *serial_env;
Pali Rohár6ac08dc2022-04-08 16:30:12 +0200116 int ret;
117
118 if (!dev)
119 return -1;
120
Pali Rohár7bb9ea42022-08-27 20:06:30 +0200121 serial_env = env_get("serial#");
122 if (serial_env && strlen(serial_env) == 16) {
123 memcpy(serial, serial_env, 17);
124 return 0;
125 }
126
Pali Rohár6ac08dc2022-04-08 16:30:12 +0200127 ret = atsha204a_wakeup(dev);
128 if (ret)
129 return ret;
130
131 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
132 TURRIS_ATSHA_OTP_VERSION,
Pali Rohár7bb9ea42022-08-27 20:06:30 +0200133 (u8 *)&version_num);
Pali Rohár6ac08dc2022-04-08 16:30:12 +0200134 if (ret)
135 return ret;
136
137 ret = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
138 TURRIS_ATSHA_OTP_SERIAL,
Pali Rohár7bb9ea42022-08-27 20:06:30 +0200139 (u8 *)&serial_num);
Pali Rohár6ac08dc2022-04-08 16:30:12 +0200140 if (ret)
141 return ret;
142
143 atsha204a_sleep(dev);
Pali Rohár7bb9ea42022-08-27 20:06:30 +0200144
145 sprintf(serial, "%08X%08X", be32_to_cpu(version_num), be32_to_cpu(serial_num));
146 env_set("serial#", serial);
147
Pali Rohár6ac08dc2022-04-08 16:30:12 +0200148 return 0;
149}