18b0044ffSOleksandr G Zhadan /*
28b0044ffSOleksandr G Zhadan * Command for accessing Arcturus factory environment.
38b0044ffSOleksandr G Zhadan *
48b0044ffSOleksandr G Zhadan * Copyright 2013-2015 Arcturus Networks Inc.
58b0044ffSOleksandr G Zhadan * http://www.arcturusnetworks.com/products/ucp1020/
68b0044ffSOleksandr G Zhadan * by Oleksandr G Zhadan et al.
78b0044ffSOleksandr G Zhadan *
88b0044ffSOleksandr G Zhadan * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
98b0044ffSOleksandr G Zhadan *
108b0044ffSOleksandr G Zhadan */
118b0044ffSOleksandr G Zhadan
128b0044ffSOleksandr G Zhadan #include <common.h>
138b0044ffSOleksandr G Zhadan #include <div64.h>
148b0044ffSOleksandr G Zhadan #include <malloc.h>
158b0044ffSOleksandr G Zhadan #include <spi_flash.h>
168b0044ffSOleksandr G Zhadan
178b0044ffSOleksandr G Zhadan #include <asm/io.h>
188b0044ffSOleksandr G Zhadan
198b0044ffSOleksandr G Zhadan #ifndef CONFIG_SF_DEFAULT_SPEED
208b0044ffSOleksandr G Zhadan # define CONFIG_SF_DEFAULT_SPEED 1000000
218b0044ffSOleksandr G Zhadan #endif
228b0044ffSOleksandr G Zhadan #ifndef CONFIG_SF_DEFAULT_MODE
238b0044ffSOleksandr G Zhadan # define CONFIG_SF_DEFAULT_MODE SPI_MODE0
248b0044ffSOleksandr G Zhadan #endif
258b0044ffSOleksandr G Zhadan #ifndef CONFIG_SF_DEFAULT_CS
268b0044ffSOleksandr G Zhadan # define CONFIG_SF_DEFAULT_CS 0
278b0044ffSOleksandr G Zhadan #endif
288b0044ffSOleksandr G Zhadan #ifndef CONFIG_SF_DEFAULT_BUS
298b0044ffSOleksandr G Zhadan # define CONFIG_SF_DEFAULT_BUS 0
308b0044ffSOleksandr G Zhadan #endif
318b0044ffSOleksandr G Zhadan
328b0044ffSOleksandr G Zhadan #define MAX_SERIAL_SIZE 15
338b0044ffSOleksandr G Zhadan #define MAX_HWADDR_SIZE 17
348b0044ffSOleksandr G Zhadan
358b0044ffSOleksandr G Zhadan #define FIRM_ADDR1 (0x200 - sizeof(smac))
368b0044ffSOleksandr G Zhadan #define FIRM_ADDR2 (0x400 - sizeof(smac))
378b0044ffSOleksandr G Zhadan #define FIRM_ADDR3 (CONFIG_ENV_SECT_SIZE + 0x200 - sizeof(smac))
388b0044ffSOleksandr G Zhadan #define FIRM_ADDR4 (CONFIG_ENV_SECT_SIZE + 0x400 - sizeof(smac))
398b0044ffSOleksandr G Zhadan
408b0044ffSOleksandr G Zhadan static struct spi_flash *flash;
418b0044ffSOleksandr G Zhadan char smac[4][18];
428b0044ffSOleksandr G Zhadan
ishwaddr(char * hwaddr)438b0044ffSOleksandr G Zhadan static int ishwaddr(char *hwaddr)
448b0044ffSOleksandr G Zhadan {
458b0044ffSOleksandr G Zhadan if (strlen(hwaddr) == MAX_HWADDR_SIZE)
468b0044ffSOleksandr G Zhadan if (hwaddr[2] == ':' &&
478b0044ffSOleksandr G Zhadan hwaddr[5] == ':' &&
488b0044ffSOleksandr G Zhadan hwaddr[8] == ':' &&
498b0044ffSOleksandr G Zhadan hwaddr[11] == ':' &&
508b0044ffSOleksandr G Zhadan hwaddr[14] == ':')
518b0044ffSOleksandr G Zhadan return 0;
528b0044ffSOleksandr G Zhadan return -1;
538b0044ffSOleksandr G Zhadan }
548b0044ffSOleksandr G Zhadan
set_arc_product(int argc,char * const argv[])558b0044ffSOleksandr G Zhadan static int set_arc_product(int argc, char *const argv[])
568b0044ffSOleksandr G Zhadan {
578b0044ffSOleksandr G Zhadan int err = 0;
588b0044ffSOleksandr G Zhadan char *mystrerr = "ERROR: Failed to save factory info in spi location";
598b0044ffSOleksandr G Zhadan
608b0044ffSOleksandr G Zhadan if (argc != 5)
618b0044ffSOleksandr G Zhadan return -1;
628b0044ffSOleksandr G Zhadan
638b0044ffSOleksandr G Zhadan /* Check serial number */
648b0044ffSOleksandr G Zhadan if (strlen(argv[1]) != MAX_SERIAL_SIZE)
658b0044ffSOleksandr G Zhadan return -1;
668b0044ffSOleksandr G Zhadan
678b0044ffSOleksandr G Zhadan /* Check HWaddrs */
688b0044ffSOleksandr G Zhadan if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
698b0044ffSOleksandr G Zhadan return -1;
708b0044ffSOleksandr G Zhadan
718b0044ffSOleksandr G Zhadan strcpy(smac[3], argv[1]);
728b0044ffSOleksandr G Zhadan strcpy(smac[2], argv[2]);
738b0044ffSOleksandr G Zhadan strcpy(smac[1], argv[3]);
748b0044ffSOleksandr G Zhadan strcpy(smac[0], argv[4]);
758b0044ffSOleksandr G Zhadan
768b0044ffSOleksandr G Zhadan flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
778b0044ffSOleksandr G Zhadan CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
788b0044ffSOleksandr G Zhadan
798b0044ffSOleksandr G Zhadan /*
808b0044ffSOleksandr G Zhadan * Save factory defaults
818b0044ffSOleksandr G Zhadan */
828b0044ffSOleksandr G Zhadan
838b0044ffSOleksandr G Zhadan if (spi_flash_write(flash, FIRM_ADDR1, sizeof(smac), smac)) {
848b0044ffSOleksandr G Zhadan printf("%s: %s [1]\n", __func__, mystrerr);
858b0044ffSOleksandr G Zhadan err++;
868b0044ffSOleksandr G Zhadan }
878b0044ffSOleksandr G Zhadan if (spi_flash_write(flash, FIRM_ADDR2, sizeof(smac), smac)) {
888b0044ffSOleksandr G Zhadan printf("%s: %s [2]\n", __func__, mystrerr);
898b0044ffSOleksandr G Zhadan err++;
908b0044ffSOleksandr G Zhadan }
918b0044ffSOleksandr G Zhadan
928b0044ffSOleksandr G Zhadan if (spi_flash_write(flash, FIRM_ADDR3, sizeof(smac), smac)) {
938b0044ffSOleksandr G Zhadan printf("%s: %s [3]\n", __func__, mystrerr);
948b0044ffSOleksandr G Zhadan err++;
958b0044ffSOleksandr G Zhadan }
968b0044ffSOleksandr G Zhadan
978b0044ffSOleksandr G Zhadan if (spi_flash_write(flash, FIRM_ADDR4, sizeof(smac), smac)) {
988b0044ffSOleksandr G Zhadan printf("%s: %s [4]\n", __func__, mystrerr);
998b0044ffSOleksandr G Zhadan err++;
1008b0044ffSOleksandr G Zhadan }
1018b0044ffSOleksandr G Zhadan
1028b0044ffSOleksandr G Zhadan if (err == 4) {
1038b0044ffSOleksandr G Zhadan printf("%s: %s [ALL]\n", __func__, mystrerr);
1048b0044ffSOleksandr G Zhadan return -2;
1058b0044ffSOleksandr G Zhadan }
1068b0044ffSOleksandr G Zhadan
1078b0044ffSOleksandr G Zhadan return 0;
1088b0044ffSOleksandr G Zhadan }
1098b0044ffSOleksandr G Zhadan
get_arc_info(void)1108b0044ffSOleksandr G Zhadan int get_arc_info(void)
1118b0044ffSOleksandr G Zhadan {
1128b0044ffSOleksandr G Zhadan int location = 1;
1138b0044ffSOleksandr G Zhadan char *myerr = "ERROR: Failed to read all 4 factory info spi locations";
1148b0044ffSOleksandr G Zhadan
1158b0044ffSOleksandr G Zhadan flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
1168b0044ffSOleksandr G Zhadan CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
1178b0044ffSOleksandr G Zhadan
1188b0044ffSOleksandr G Zhadan if (spi_flash_read(flash, FIRM_ADDR1, sizeof(smac), smac)) {
1198b0044ffSOleksandr G Zhadan location++;
1208b0044ffSOleksandr G Zhadan if (spi_flash_read(flash, FIRM_ADDR2, sizeof(smac), smac)) {
1218b0044ffSOleksandr G Zhadan location++;
1228b0044ffSOleksandr G Zhadan if (spi_flash_read(flash, FIRM_ADDR3, sizeof(smac),
1238b0044ffSOleksandr G Zhadan smac)) {
1248b0044ffSOleksandr G Zhadan location++;
1258b0044ffSOleksandr G Zhadan if (spi_flash_read(flash, FIRM_ADDR4,
1268b0044ffSOleksandr G Zhadan sizeof(smac), smac)) {
1278b0044ffSOleksandr G Zhadan printf("%s: %s\n", __func__, myerr);
1288b0044ffSOleksandr G Zhadan return -2;
1298b0044ffSOleksandr G Zhadan }
1308b0044ffSOleksandr G Zhadan }
1318b0044ffSOleksandr G Zhadan }
1328b0044ffSOleksandr G Zhadan }
1338b0044ffSOleksandr G Zhadan if (smac[3][0] != 0) {
1348b0044ffSOleksandr G Zhadan if (location > 1)
1358b0044ffSOleksandr G Zhadan printf("Using region %d\n", location);
1368b0044ffSOleksandr G Zhadan printf("SERIAL: ");
1378b0044ffSOleksandr G Zhadan if (smac[3][0] == 0xFF) {
1388b0044ffSOleksandr G Zhadan printf("\t<not found>\n");
1398b0044ffSOleksandr G Zhadan } else {
1408b0044ffSOleksandr G Zhadan printf("\t%s\n", smac[3]);
141382bee57SSimon Glass env_set("SERIAL", smac[3]);
1428b0044ffSOleksandr G Zhadan }
1438b0044ffSOleksandr G Zhadan }
1448b0044ffSOleksandr G Zhadan
1458b0044ffSOleksandr G Zhadan if (strcmp(smac[2], "00:00:00:00:00:00") == 0)
1468b0044ffSOleksandr G Zhadan return 0;
1478b0044ffSOleksandr G Zhadan
1488b0044ffSOleksandr G Zhadan printf("HWADDR0:");
1498b0044ffSOleksandr G Zhadan if (smac[2][0] == 0xFF) {
1508b0044ffSOleksandr G Zhadan printf("\t<not found>\n");
1518b0044ffSOleksandr G Zhadan } else {
152*00caae6dSSimon Glass char *ret = env_get("ethaddr");
1538b0044ffSOleksandr G Zhadan
1548b0044ffSOleksandr G Zhadan if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
155382bee57SSimon Glass env_set("ethaddr", smac[2]);
1568b0044ffSOleksandr G Zhadan printf("\t%s (factory)\n", smac[2]);
1578b0044ffSOleksandr G Zhadan } else {
1588b0044ffSOleksandr G Zhadan printf("\t%s\n", ret);
1598b0044ffSOleksandr G Zhadan }
1608b0044ffSOleksandr G Zhadan }
1618b0044ffSOleksandr G Zhadan
1628b0044ffSOleksandr G Zhadan if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
163382bee57SSimon Glass env_set("eth1addr", smac[2]);
164382bee57SSimon Glass env_set("eth2addr", smac[2]);
1658b0044ffSOleksandr G Zhadan return 0;
1668b0044ffSOleksandr G Zhadan }
1678b0044ffSOleksandr G Zhadan
1688b0044ffSOleksandr G Zhadan printf("HWADDR1:");
1698b0044ffSOleksandr G Zhadan if (smac[1][0] == 0xFF) {
1708b0044ffSOleksandr G Zhadan printf("\t<not found>\n");
1718b0044ffSOleksandr G Zhadan } else {
172*00caae6dSSimon Glass char *ret = env_get("eth1addr");
1738b0044ffSOleksandr G Zhadan
1748b0044ffSOleksandr G Zhadan if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
175382bee57SSimon Glass env_set("eth1addr", smac[1]);
1768b0044ffSOleksandr G Zhadan printf("\t%s (factory)\n", smac[1]);
1778b0044ffSOleksandr G Zhadan } else {
1788b0044ffSOleksandr G Zhadan printf("\t%s\n", ret);
1798b0044ffSOleksandr G Zhadan }
1808b0044ffSOleksandr G Zhadan }
1818b0044ffSOleksandr G Zhadan
1828b0044ffSOleksandr G Zhadan if (strcmp(smac[0], "00:00:00:00:00:00") == 0) {
183382bee57SSimon Glass env_set("eth2addr", smac[1]);
1848b0044ffSOleksandr G Zhadan return 0;
1858b0044ffSOleksandr G Zhadan }
1868b0044ffSOleksandr G Zhadan
1878b0044ffSOleksandr G Zhadan printf("HWADDR2:");
1888b0044ffSOleksandr G Zhadan if (smac[0][0] == 0xFF) {
1898b0044ffSOleksandr G Zhadan printf("\t<not found>\n");
1908b0044ffSOleksandr G Zhadan } else {
191*00caae6dSSimon Glass char *ret = env_get("eth2addr");
1928b0044ffSOleksandr G Zhadan
1938b0044ffSOleksandr G Zhadan if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
194382bee57SSimon Glass env_set("eth2addr", smac[0]);
1958b0044ffSOleksandr G Zhadan printf("\t%s (factory)\n", smac[0]);
1968b0044ffSOleksandr G Zhadan } else {
1978b0044ffSOleksandr G Zhadan printf("\t%s\n", ret);
1988b0044ffSOleksandr G Zhadan }
1998b0044ffSOleksandr G Zhadan }
2008b0044ffSOleksandr G Zhadan
2018b0044ffSOleksandr G Zhadan return 0;
2028b0044ffSOleksandr G Zhadan }
2038b0044ffSOleksandr G Zhadan
do_arc_cmd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2048b0044ffSOleksandr G Zhadan static int do_arc_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2058b0044ffSOleksandr G Zhadan {
2068b0044ffSOleksandr G Zhadan const char *cmd;
2078b0044ffSOleksandr G Zhadan int ret = -1;
2088b0044ffSOleksandr G Zhadan
2098b0044ffSOleksandr G Zhadan cmd = argv[1];
2108b0044ffSOleksandr G Zhadan --argc;
2118b0044ffSOleksandr G Zhadan ++argv;
2128b0044ffSOleksandr G Zhadan
2138b0044ffSOleksandr G Zhadan if (strcmp(cmd, "product") == 0) {
2148b0044ffSOleksandr G Zhadan ret = set_arc_product(argc, argv);
2158b0044ffSOleksandr G Zhadan goto done;
2168b0044ffSOleksandr G Zhadan }
2178b0044ffSOleksandr G Zhadan if (strcmp(cmd, "info") == 0) {
2188b0044ffSOleksandr G Zhadan ret = get_arc_info();
2198b0044ffSOleksandr G Zhadan goto done;
2208b0044ffSOleksandr G Zhadan }
2218b0044ffSOleksandr G Zhadan done:
2228b0044ffSOleksandr G Zhadan if (ret == -1)
2238b0044ffSOleksandr G Zhadan return CMD_RET_USAGE;
2248b0044ffSOleksandr G Zhadan
2258b0044ffSOleksandr G Zhadan return ret;
2268b0044ffSOleksandr G Zhadan }
2278b0044ffSOleksandr G Zhadan
2288b0044ffSOleksandr G Zhadan U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
2298b0044ffSOleksandr G Zhadan "Arcturus product command sub-system",
2308b0044ffSOleksandr G Zhadan "product serial hwaddr0 hwaddr1 hwaddr2 - save Arcturus factory env\n"
2318b0044ffSOleksandr G Zhadan "info - show Arcturus factory env\n\n");
232