SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / board / corscience / tricorder / tricorder-eeprom.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2013
4  * Corscience GmbH & Co. KG, <www.corscience.de>
5  * Andreas Bießmann <andreas.biessmann@corscience.de>
6  */
7 #include <common.h>
8 #include <i2c.h>
9
10 #include "tricorder-eeprom.h"
11
12 static inline void warn_wrong_value(const char *msg, unsigned int a,
13                 unsigned int b)
14 {
15         printf("Expected EEPROM %s %08x, got %08x\n", msg, a, b);
16 }
17
18 static int handle_eeprom_v0(struct tricorder_eeprom *eeprom)
19 {
20         struct tricorder_eeprom_v0 {
21                 uint32_t magic;
22                 uint16_t length;
23                 uint16_t version;
24                 char board_name[TRICORDER_BOARD_NAME_LENGTH];
25                 char board_version[TRICORDER_BOARD_VERSION_LENGTH];
26                 char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
27                 uint32_t crc32;
28         } __packed eepromv0;
29         uint32_t crc;
30
31         printf("Old EEPROM (v0), consider rewrite!\n");
32
33         if (be16_to_cpu(eeprom->length) != sizeof(eepromv0)) {
34                 warn_wrong_value("length", sizeof(eepromv0),
35                                  be16_to_cpu(eeprom->length));
36                 return 1;
37         }
38
39         memcpy(&eepromv0, eeprom, sizeof(eepromv0));
40
41         crc = crc32(0L, (unsigned char *)&eepromv0,
42                     sizeof(eepromv0) - sizeof(eepromv0.crc32));
43         if (be32_to_cpu(eepromv0.crc32) != crc) {
44                 warn_wrong_value("CRC", be32_to_cpu(eepromv0.crc32),
45                                  crc);
46                 return 1;
47         }
48
49         /* Ok the content is correct, do the conversion */
50         memset(eeprom->interface_version, 0x0,
51                TRICORDER_INTERFACE_VERSION_LENGTH);
52         crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
53         eeprom->crc32 = cpu_to_be32(crc);
54
55         return 0;
56 }
57
58 static int handle_eeprom_v1(struct tricorder_eeprom *eeprom)
59 {
60         uint32_t crc;
61
62         if (be16_to_cpu(eeprom->length) != TRICORDER_EEPROM_SIZE) {
63                 warn_wrong_value("length", TRICORDER_EEPROM_SIZE,
64                                  be16_to_cpu(eeprom->length));
65                 return 1;
66         }
67
68         crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
69         if (be32_to_cpu(eeprom->crc32) != crc) {
70                 warn_wrong_value("CRC", be32_to_cpu(eeprom->crc32), crc);
71                 return 1;
72         }
73
74         return 0;
75 }
76
77 int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
78 {
79         unsigned int bus = i2c_get_bus_num();
80         i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
81
82         memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
83
84         i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
85         i2c_set_bus_num(bus);
86
87         if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
88                 warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
89                                  be32_to_cpu(eeprom->magic));
90                 return 1;
91         }
92
93         switch (be16_to_cpu(eeprom->version)) {
94         case 0:
95                 return handle_eeprom_v0(eeprom);
96         case 1:
97                 return handle_eeprom_v1(eeprom);
98         default:
99                 warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
100                                  be16_to_cpu(eeprom->version));
101                 return 1;
102         }
103 }
104
105 #if !defined(CONFIG_SPL)
106 int tricorder_eeprom_read(unsigned devaddr)
107 {
108         struct tricorder_eeprom eeprom;
109         int ret = tricorder_get_eeprom(devaddr, &eeprom);
110
111         if (ret)
112                 return ret;
113
114         printf("Board type:               %.*s\n",
115                sizeof(eeprom.board_name), eeprom.board_name);
116         printf("Board version:            %.*s\n",
117                sizeof(eeprom.board_version), eeprom.board_version);
118         printf("Board serial:             %.*s\n",
119                sizeof(eeprom.board_serial), eeprom.board_serial);
120         printf("Board interface version:  %.*s\n",
121                sizeof(eeprom.interface_version),
122                eeprom.interface_version);
123
124         return ret;
125 }
126
127 int tricorder_eeprom_write(unsigned devaddr, const char *name,
128                 const char *version, const char *serial, const char *interface)
129 {
130         struct tricorder_eeprom eeprom, eeprom_verify;
131         size_t length;
132         uint32_t crc;
133         int ret;
134         unsigned char *p;
135         int i;
136
137         memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
138         memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
139
140         eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
141         eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
142         eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
143
144         length = min(sizeof(eeprom.board_name), strlen(name));
145         strncpy(eeprom.board_name, name, length);
146
147         length = min(sizeof(eeprom.board_version), strlen(version));
148         strncpy(eeprom.board_version, version, length);
149
150         length = min(sizeof(eeprom.board_serial), strlen(serial));
151         strncpy(eeprom.board_serial, serial, length);
152
153         if (interface) {
154                 length = min(sizeof(eeprom.interface_version),
155                                 strlen(interface));
156                 strncpy(eeprom.interface_version, interface, length);
157         }
158
159         crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
160         eeprom.crc32 = cpu_to_be32(crc);
161
162 #if defined(DEBUG)
163         puts("Tricorder EEPROM content:\n");
164         print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
165 #endif
166
167         eeprom_init(CONFIG_SYS_EEPROM_BUS_NUM);
168
169         ret = eeprom_write(devaddr, 0, (unsigned char *)&eeprom,
170                         TRICORDER_EEPROM_SIZE);
171         if (ret)
172                 printf("Tricorder: Could not write EEPROM content!\n");
173
174         ret = eeprom_read(devaddr, 0, (unsigned char *)&eeprom_verify,
175                         TRICORDER_EEPROM_SIZE);
176         if (ret)
177                 printf("Tricorder: Could not read EEPROM content!\n");
178
179         if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
180                 printf("Tricorder: Could not verify EEPROM content!\n");
181                 ret = 1;
182         }
183
184         return ret;
185 }
186
187 int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
188 {
189         if (argc == 3) {
190                 ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
191
192                 if (strcmp(argv[1], "read") == 0)
193                         return tricorder_eeprom_read(dev_addr);
194         } else if (argc == 6 || argc == 7) {
195                 ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
196                 char *name = argv[3];
197                 char *version = argv[4];
198                 char *serial = argv[5];
199                 char *interface = NULL;
200
201                 if (argc == 7)
202                         interface = argv[6];
203
204                 if (strcmp(argv[1], "write") == 0)
205                         return tricorder_eeprom_write(dev_addr, name, version,
206                                                       serial, interface);
207         }
208
209         return CMD_RET_USAGE;
210 }
211
212 U_BOOT_CMD(
213         tricordereeprom,        7,      1,      do_tricorder_eeprom,
214         "Tricorder EEPROM",
215         "read  devaddr\n"
216         "       - read Tricorder EEPROM at devaddr and print content\n"
217         "tricordereeprom write devaddr name version serial [interface]\n"
218         "       - write Tricorder EEPROM at devaddr with 'name', 'version'"
219         "and 'serial'\n"
220         "         optional add an HW interface parameter"
221 );
222 #endif /* CONFIG_SPL */