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