Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / board / Arcturus / ucp1020 / cmd_arc.c
1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3  * Command for accessing Arcturus factory environment.
4  *
5  * Copyright 2013-2019 Arcturus Networks Inc.
6  *           https://www.arcturusnetworks.com/products/
7  *           by Oleksandr G Zhadan et al.
8  *
9  */
10
11 #include <common.h>
12 #include <command.h>
13 #include <cpu_func.h>
14 #include <div64.h>
15 #include <env.h>
16 #include <flash.h>
17 #include <malloc.h>
18 #include <spi_flash.h>
19 #include <mmc.h>
20 #include <version.h>
21 #include <asm/io.h>
22 #include <linux/stringify.h>
23
24 static ulong fwenv_addr[MAX_FWENV_ADDR];
25 const char mystrerr[] = "ERROR: Failed to save factory info";
26
27 static int ishwaddr(char *hwaddr)
28 {
29         if (strlen(hwaddr) == MAX_HWADDR_SIZE)
30                 if (hwaddr[2] == ':' &&
31                     hwaddr[5] == ':' &&
32                     hwaddr[8] == ':' &&
33                     hwaddr[11] == ':' &&
34                     hwaddr[14] == ':')
35                         return 0;
36         return -1;
37 }
38
39 #if (FWENV_TYPE == FWENV_MMC)
40
41 static char smac[29][18] __attribute__ ((aligned(0x200)));      /* 1 MMC block is 512 bytes */
42
43 int set_mmc_arc_product(int argc, char *const argv[])
44 {
45         struct mmc *mmc;
46         u32 blk, cnt, n;
47         int i, err = 1;
48         void *addr;
49         const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
50
51         mmc = find_mmc_device(mmc_dev_num);
52         if (!mmc) {
53                 printf("No SD/MMC/eMMC card found\n");
54                 return 0;
55         }
56         if (mmc_init(mmc)) {
57                 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
58                        mmc_dev_num);
59                 return 0;
60         }
61         if (mmc_getwp(mmc) == 1) {
62                 printf("Error: card is write protected!\n");
63                 return CMD_RET_FAILURE;
64         }
65
66         /* Save factory defaults */
67         addr = (void *)smac;
68         cnt = 1;                /* One 512 bytes block */
69
70         for (i = 0; i < MAX_FWENV_ADDR; i++)
71                 if (fwenv_addr[i] != -1) {
72                         blk = fwenv_addr[i] / 512;
73                         n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
74                         if (n != cnt)
75                                 printf("%s: %s [%d]\n", __func__, mystrerr, i);
76                         else
77                                 err = 0;
78                 }
79         if (err)
80                 return -2;
81
82         return err;
83 }
84
85 static int read_mmc_arc_info(void)
86 {
87         struct mmc *mmc;
88         u32 blk, cnt, n;
89         int i;
90         void *addr;
91         const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
92
93         mmc = find_mmc_device(mmc_dev_num);
94         if (!mmc) {
95                 printf("No SD/MMC/eMMC card found\n");
96                 return 0;
97         }
98         if (mmc_init(mmc)) {
99                 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
100                        mmc_dev_num);
101                 return 0;
102         }
103
104         addr = (void *)smac;
105         cnt = 1;                /* One 512 bytes block */
106
107         for (i = 0; i < MAX_FWENV_ADDR; i++)
108                 if (fwenv_addr[i] != -1) {
109                         blk = fwenv_addr[i] / 512;
110                         n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
111                         flush_cache((ulong) addr, 512);
112                         if (n == cnt)
113                                 return (i + 1);
114                 }
115         return 0;
116 }
117 #endif
118
119 #if (FWENV_TYPE == FWENV_SPI_FLASH)
120
121 static struct spi_flash *flash;
122 static char smac[4][18];
123
124 int set_spi_arc_product(int argc, char *const argv[])
125 {
126         int i, err = 1;
127
128         flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
129                                 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
130         if (!flash) {
131                 printf("Failed to initialize SPI flash at %u:%u\n",
132                        CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS);
133                 return -1;
134         }
135
136         /* Save factory defaults */
137         for (i = 0; i < MAX_FWENV_ADDR; i++)
138                 if (fwenv_addr[i] != -1)
139                         if (spi_flash_write
140                             (flash, fwenv_addr[i], sizeof(smac), smac))
141                                 printf("%s: %s [%d]\n", __func__, mystrerr, i);
142                         else
143                                 err = 0;
144         if (err)
145                 return -2;
146
147         return err;
148 }
149
150 static int read_spi_arc_info(void)
151 {
152         int i;
153
154         flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
155                                 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
156         if (!flash) {
157                 printf("Failed to initialize SPI flash at %u:%u\n",
158                        CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS);
159                 return 0;
160         }
161         for (i = 0; i < MAX_FWENV_ADDR; i++)
162                 if (fwenv_addr[i] != -1)
163                         if (!spi_flash_read
164                             (flash, fwenv_addr[i], sizeof(smac), smac))
165                                 return (i + 1);
166         return 0;
167 }
168 #endif
169
170 #if (FWENV_TYPE == FWENV_NOR_FLASH)
171
172 static char smac[4][18];
173
174 int set_nor_arc_product(int argc, char *const argv[])
175 {
176         int i, err = 1;
177
178         /* Save factory defaults */
179         for (i = 0; i < MAX_FWENV_ADDR; i++)
180                 if (fwenv_addr[i] != -1) {
181                         ulong fwenv_end = fwenv_addr[i] + 4;
182
183                         flash_sect_roundb(&fwenv_end);
184                         flash_sect_protect(0, fwenv_addr[i], fwenv_end);
185                         if (flash_write
186                             ((char *)smac, fwenv_addr[i], sizeof(smac)))
187                                 printf("%s: %s [%d]\n", __func__, mystrerr, i);
188                         else
189                                 err = 0;
190                         flash_sect_protect(1, fwenv_addr[i], fwenv_end);
191                 }
192         if (err)
193                 return -2;
194
195         return err;
196 }
197
198 static int read_nor_arc_info(void)
199 {
200         int i;
201
202         for (i = 0; i < MAX_FWENV_ADDR; i++)
203                 if (fwenv_addr[i] != -1) {
204                         memcpy(smac, (void *)fwenv_addr[i], sizeof(smac));
205                         return (i + 1);
206                 }
207
208         return 0;
209 }
210 #endif
211
212 int set_arc_product(int argc, char *const argv[])
213 {
214         if (argc != 5)
215                 return -1;
216
217         /* Check serial number */
218         if (strlen(argv[1]) != MAX_SERIAL_SIZE)
219                 return -1;
220
221         /* Check HWaddrs */
222         if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
223                 return -1;
224
225         strcpy(smac[0], argv[1]);
226         strcpy(smac[1], argv[2]);
227         strcpy(smac[2], argv[3]);
228         strcpy(smac[3], argv[4]);
229
230 #if (FWENV_TYPE == FWENV_NOR_FLASH)
231         return set_nor_arc_product(argc, argv);
232 #endif
233 #if (FWENV_TYPE == FWENV_SPI_FLASH)
234         return set_spi_arc_product(argc, argv);
235 #endif
236 #if (FWENV_TYPE == FWENV_MMC)
237         return set_mmc_arc_product(argc, argv);
238 #endif
239         return -2;
240 }
241
242 static int read_arc_info(void)
243 {
244 #if (FWENV_TYPE == FWENV_NOR_FLASH)
245         return read_nor_arc_info();
246 #endif
247 #if (FWENV_TYPE == FWENV_SPI_FLASH)
248         return read_spi_arc_info();
249 #endif
250 #if (FWENV_TYPE == FWENV_MMC)
251         return read_mmc_arc_info();
252 #endif
253         return 0;
254 }
255
256 static int do_get_arc_info(void)
257 {
258         int l = read_arc_info();
259         char *oldserial = env_get("SERIAL");
260         char *oldversion = env_get("VERSION");
261
262         if (oldversion != NULL)
263                 if (strcmp(oldversion, U_BOOT_VERSION) != 0)
264                         oldversion = NULL;
265
266         if (l == 0) {
267                 printf("%s: failed to read factory info\n", __func__);
268                 return -2;
269         }
270
271         printf("\rSERIAL:  ");
272         if (smac[0][0] == EMPY_CHAR) {
273                 printf("<not found>\n");
274         } else {
275                 printf("%s\n", smac[0]);
276                 env_set("SERIAL", smac[0]);
277         }
278
279         if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
280                 env_set("ethaddr", NULL);
281                 env_set("eth1addr", NULL);
282                 env_set("eth2addr", NULL);
283                 goto done;
284         }
285
286         printf("HWADDR0: ");
287         if (smac[1][0] == EMPY_CHAR) {
288                 printf("<not found>\n");
289         } else {
290                 char *ret = env_get("ethaddr");
291
292                 if (ret == NULL) {
293                         env_set("ethaddr", smac[1]);
294                         printf("%s\n", smac[1]);
295                 } else if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
296                         env_set("ethaddr", smac[1]);
297                         printf("%s (factory)\n", smac[1]);
298                 } else {
299                         printf("%s\n", ret);
300                 }
301         }
302
303         if (strcmp(smac[2], "00:00:00:00:00:00") == 0) {
304                 env_set("eth1addr", NULL);
305                 env_set("eth2addr", NULL);
306                 goto done;
307         }
308
309         printf("HWADDR1: ");
310         if (smac[2][0] == EMPY_CHAR) {
311                 printf("<not found>\n");
312         } else {
313                 char *ret = env_get("eth1addr");
314
315                 if (ret == NULL) {
316                         env_set("ethaddr", smac[2]);
317                         printf("%s\n", smac[2]);
318                 } else if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
319                         env_set("eth1addr", smac[2]);
320                         printf("%s (factory)\n", smac[2]);
321                 } else {
322                         printf("%s\n", ret);
323                 }
324         }
325
326         if (strcmp(smac[3], "00:00:00:00:00:00") == 0) {
327                 env_set("eth2addr", NULL);
328                 goto done;
329         }
330
331         printf("HWADDR2: ");
332         if (smac[3][0] == EMPY_CHAR) {
333                 printf("<not found>\n");
334         } else {
335                 char *ret = env_get("eth2addr");
336
337                 if (ret == NULL) {
338                         env_set("ethaddr", smac[3]);
339                         printf("%s\n", smac[3]);
340                 } else if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
341                         env_set("eth2addr", smac[3]);
342                         printf("%s (factory)\n", smac[3]);
343                 } else {
344                         printf("%s\n", ret);
345                 }
346         }
347 done:
348         if (oldserial == NULL || oldversion == NULL) {
349                 if (oldversion == NULL)
350                         env_set("VERSION", U_BOOT_VERSION);
351                 env_save();
352         }
353
354         return 0;
355 }
356
357 static int init_fwenv(void)
358 {
359         int i, ret = -1;
360
361         fwenv_addr[0] = FWENV_ADDR1;
362         fwenv_addr[1] = FWENV_ADDR2;
363         fwenv_addr[2] = FWENV_ADDR3;
364         fwenv_addr[3] = FWENV_ADDR4;
365
366         for (i = 0; i < MAX_FWENV_ADDR; i++)
367                 if (fwenv_addr[i] != -1)
368                         ret = 0;
369         if (ret)
370                 printf("%s: No firmfare info storage address is defined\n",
371                        __func__);
372         return ret;
373 }
374
375 void get_arc_info(void)
376 {
377         if (!init_fwenv())
378                 do_get_arc_info();
379 }
380
381 static int do_arc_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
382                       char *const argv[])
383 {
384         const char *cmd;
385         int ret = -1;
386
387         cmd = argv[1];
388         --argc;
389         ++argv;
390
391         if (init_fwenv())
392                 return ret;
393
394         if (strcmp(cmd, "product") == 0)
395                 ret = set_arc_product(argc, argv);
396         else if (strcmp(cmd, "info") == 0)
397                 ret = do_get_arc_info();
398
399         if (ret == -1)
400                 return CMD_RET_USAGE;
401
402         return ret;
403 }
404
405 U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
406            "Arcturus product command sub-system",
407            "product serial hwaddr0 hwaddr1 hwaddr2    - save Arcturus factory env\n"
408            "info                                      - show Arcturus factory env\n\n");