1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Command for accessing Arcturus factory environment.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright 2013-2015 Arcturus Networks Inc.
5*4882a593Smuzhiyun * http://www.arcturusnetworks.com/products/ucp1020/
6*4882a593Smuzhiyun * by Oleksandr G Zhadan et al.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <common.h>
13*4882a593Smuzhiyun #include <div64.h>
14*4882a593Smuzhiyun #include <malloc.h>
15*4882a593Smuzhiyun #include <spi_flash.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <asm/io.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #ifndef CONFIG_SF_DEFAULT_SPEED
20*4882a593Smuzhiyun # define CONFIG_SF_DEFAULT_SPEED 1000000
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun #ifndef CONFIG_SF_DEFAULT_MODE
23*4882a593Smuzhiyun # define CONFIG_SF_DEFAULT_MODE SPI_MODE0
24*4882a593Smuzhiyun #endif
25*4882a593Smuzhiyun #ifndef CONFIG_SF_DEFAULT_CS
26*4882a593Smuzhiyun # define CONFIG_SF_DEFAULT_CS 0
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun #ifndef CONFIG_SF_DEFAULT_BUS
29*4882a593Smuzhiyun # define CONFIG_SF_DEFAULT_BUS 0
30*4882a593Smuzhiyun #endif
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define MAX_SERIAL_SIZE 15
33*4882a593Smuzhiyun #define MAX_HWADDR_SIZE 17
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define FIRM_ADDR1 (0x200 - sizeof(smac))
36*4882a593Smuzhiyun #define FIRM_ADDR2 (0x400 - sizeof(smac))
37*4882a593Smuzhiyun #define FIRM_ADDR3 (CONFIG_ENV_SECT_SIZE + 0x200 - sizeof(smac))
38*4882a593Smuzhiyun #define FIRM_ADDR4 (CONFIG_ENV_SECT_SIZE + 0x400 - sizeof(smac))
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static struct spi_flash *flash;
41*4882a593Smuzhiyun char smac[4][18];
42*4882a593Smuzhiyun
ishwaddr(char * hwaddr)43*4882a593Smuzhiyun static int ishwaddr(char *hwaddr)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun if (strlen(hwaddr) == MAX_HWADDR_SIZE)
46*4882a593Smuzhiyun if (hwaddr[2] == ':' &&
47*4882a593Smuzhiyun hwaddr[5] == ':' &&
48*4882a593Smuzhiyun hwaddr[8] == ':' &&
49*4882a593Smuzhiyun hwaddr[11] == ':' &&
50*4882a593Smuzhiyun hwaddr[14] == ':')
51*4882a593Smuzhiyun return 0;
52*4882a593Smuzhiyun return -1;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
set_arc_product(int argc,char * const argv[])55*4882a593Smuzhiyun static int set_arc_product(int argc, char *const argv[])
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun int err = 0;
58*4882a593Smuzhiyun char *mystrerr = "ERROR: Failed to save factory info in spi location";
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (argc != 5)
61*4882a593Smuzhiyun return -1;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /* Check serial number */
64*4882a593Smuzhiyun if (strlen(argv[1]) != MAX_SERIAL_SIZE)
65*4882a593Smuzhiyun return -1;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* Check HWaddrs */
68*4882a593Smuzhiyun if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
69*4882a593Smuzhiyun return -1;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun strcpy(smac[3], argv[1]);
72*4882a593Smuzhiyun strcpy(smac[2], argv[2]);
73*4882a593Smuzhiyun strcpy(smac[1], argv[3]);
74*4882a593Smuzhiyun strcpy(smac[0], argv[4]);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
77*4882a593Smuzhiyun CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /*
80*4882a593Smuzhiyun * Save factory defaults
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun if (spi_flash_write(flash, FIRM_ADDR1, sizeof(smac), smac)) {
84*4882a593Smuzhiyun printf("%s: %s [1]\n", __func__, mystrerr);
85*4882a593Smuzhiyun err++;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun if (spi_flash_write(flash, FIRM_ADDR2, sizeof(smac), smac)) {
88*4882a593Smuzhiyun printf("%s: %s [2]\n", __func__, mystrerr);
89*4882a593Smuzhiyun err++;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (spi_flash_write(flash, FIRM_ADDR3, sizeof(smac), smac)) {
93*4882a593Smuzhiyun printf("%s: %s [3]\n", __func__, mystrerr);
94*4882a593Smuzhiyun err++;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun if (spi_flash_write(flash, FIRM_ADDR4, sizeof(smac), smac)) {
98*4882a593Smuzhiyun printf("%s: %s [4]\n", __func__, mystrerr);
99*4882a593Smuzhiyun err++;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun if (err == 4) {
103*4882a593Smuzhiyun printf("%s: %s [ALL]\n", __func__, mystrerr);
104*4882a593Smuzhiyun return -2;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun return 0;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
get_arc_info(void)110*4882a593Smuzhiyun int get_arc_info(void)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun int location = 1;
113*4882a593Smuzhiyun char *myerr = "ERROR: Failed to read all 4 factory info spi locations";
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
116*4882a593Smuzhiyun CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (spi_flash_read(flash, FIRM_ADDR1, sizeof(smac), smac)) {
119*4882a593Smuzhiyun location++;
120*4882a593Smuzhiyun if (spi_flash_read(flash, FIRM_ADDR2, sizeof(smac), smac)) {
121*4882a593Smuzhiyun location++;
122*4882a593Smuzhiyun if (spi_flash_read(flash, FIRM_ADDR3, sizeof(smac),
123*4882a593Smuzhiyun smac)) {
124*4882a593Smuzhiyun location++;
125*4882a593Smuzhiyun if (spi_flash_read(flash, FIRM_ADDR4,
126*4882a593Smuzhiyun sizeof(smac), smac)) {
127*4882a593Smuzhiyun printf("%s: %s\n", __func__, myerr);
128*4882a593Smuzhiyun return -2;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun if (smac[3][0] != 0) {
134*4882a593Smuzhiyun if (location > 1)
135*4882a593Smuzhiyun printf("Using region %d\n", location);
136*4882a593Smuzhiyun printf("SERIAL: ");
137*4882a593Smuzhiyun if (smac[3][0] == 0xFF) {
138*4882a593Smuzhiyun printf("\t<not found>\n");
139*4882a593Smuzhiyun } else {
140*4882a593Smuzhiyun printf("\t%s\n", smac[3]);
141*4882a593Smuzhiyun env_set("SERIAL", smac[3]);
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun if (strcmp(smac[2], "00:00:00:00:00:00") == 0)
146*4882a593Smuzhiyun return 0;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun printf("HWADDR0:");
149*4882a593Smuzhiyun if (smac[2][0] == 0xFF) {
150*4882a593Smuzhiyun printf("\t<not found>\n");
151*4882a593Smuzhiyun } else {
152*4882a593Smuzhiyun char *ret = env_get("ethaddr");
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
155*4882a593Smuzhiyun env_set("ethaddr", smac[2]);
156*4882a593Smuzhiyun printf("\t%s (factory)\n", smac[2]);
157*4882a593Smuzhiyun } else {
158*4882a593Smuzhiyun printf("\t%s\n", ret);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
163*4882a593Smuzhiyun env_set("eth1addr", smac[2]);
164*4882a593Smuzhiyun env_set("eth2addr", smac[2]);
165*4882a593Smuzhiyun return 0;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun printf("HWADDR1:");
169*4882a593Smuzhiyun if (smac[1][0] == 0xFF) {
170*4882a593Smuzhiyun printf("\t<not found>\n");
171*4882a593Smuzhiyun } else {
172*4882a593Smuzhiyun char *ret = env_get("eth1addr");
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
175*4882a593Smuzhiyun env_set("eth1addr", smac[1]);
176*4882a593Smuzhiyun printf("\t%s (factory)\n", smac[1]);
177*4882a593Smuzhiyun } else {
178*4882a593Smuzhiyun printf("\t%s\n", ret);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (strcmp(smac[0], "00:00:00:00:00:00") == 0) {
183*4882a593Smuzhiyun env_set("eth2addr", smac[1]);
184*4882a593Smuzhiyun return 0;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun printf("HWADDR2:");
188*4882a593Smuzhiyun if (smac[0][0] == 0xFF) {
189*4882a593Smuzhiyun printf("\t<not found>\n");
190*4882a593Smuzhiyun } else {
191*4882a593Smuzhiyun char *ret = env_get("eth2addr");
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
194*4882a593Smuzhiyun env_set("eth2addr", smac[0]);
195*4882a593Smuzhiyun printf("\t%s (factory)\n", smac[0]);
196*4882a593Smuzhiyun } else {
197*4882a593Smuzhiyun printf("\t%s\n", ret);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
do_arc_cmd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])204*4882a593Smuzhiyun static int do_arc_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun const char *cmd;
207*4882a593Smuzhiyun int ret = -1;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun cmd = argv[1];
210*4882a593Smuzhiyun --argc;
211*4882a593Smuzhiyun ++argv;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (strcmp(cmd, "product") == 0) {
214*4882a593Smuzhiyun ret = set_arc_product(argc, argv);
215*4882a593Smuzhiyun goto done;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun if (strcmp(cmd, "info") == 0) {
218*4882a593Smuzhiyun ret = get_arc_info();
219*4882a593Smuzhiyun goto done;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun done:
222*4882a593Smuzhiyun if (ret == -1)
223*4882a593Smuzhiyun return CMD_RET_USAGE;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun return ret;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
229*4882a593Smuzhiyun "Arcturus product command sub-system",
230*4882a593Smuzhiyun "product serial hwaddr0 hwaddr1 hwaddr2 - save Arcturus factory env\n"
231*4882a593Smuzhiyun "info - show Arcturus factory env\n\n");
232