arm: mvebu: turris_omnia: Do not fail in fixup_mtd_partitions when partitions do...
[platform/kernel/u-boot.git] / board / CZ.NIC / turris_atsha_otp.c
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
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
20 extern U_BOOT_DRIVER(atsha204);
21
22 static struct udevice *get_atsha204a_dev(void)
23 {
24         /* Cannot be static because BSS does not have to be ready at this early stage */
25         struct udevice *dev;
26
27         if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(atsha204), &dev)) {
28                 puts("Cannot find ATSHA204A on I2C bus!\n");
29                 dev = NULL;
30         }
31
32         return dev;
33 }
34
35 static 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
46 static 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
55 int turris_atsha_otp_init_mac_addresses(int first_idx)
56 {
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
87         set_mac_if_invalid((first_idx + 0) % 3, mac);
88         increment_mac(mac);
89         set_mac_if_invalid((first_idx + 1) % 3, mac);
90         increment_mac(mac);
91         set_mac_if_invalid((first_idx + 2) % 3, mac);
92
93         return 0;
94 }
95
96 int turris_atsha_otp_get_serial_number(u32 *version_num, u32 *serial_num)
97 {
98         struct udevice *dev = get_atsha204a_dev();
99         int ret;
100
101         if (!dev)
102                 return -1;
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         return 0;
122 }