powerpc/mpc85xx: Add board support for ucp1020

New QorIQ p1020 based board support from Arcturus Networks Inc.
http://www.arcturusnetworks.com/products/ucp1020/

Signed-off-by: Michael Durrant <mdurrant@arcturusnetworks.com>
Signed-off-by: Oleksandr G Zhadan <oleks@arcturusnetworks.com>
[York Sun: remove patman tags from commit message]
Reviewed-by: York Sun <yorksun@freescale.com>
diff --git a/board/Arcturus/ucp1020/cmd_arc.c b/board/Arcturus/ucp1020/cmd_arc.c
new file mode 100644
index 0000000..fa6b485
--- /dev/null
+++ b/board/Arcturus/ucp1020/cmd_arc.c
@@ -0,0 +1,231 @@
+/*
+ * Command for accessing Arcturus factory environment.
+ *
+ * Copyright 2013-2015 Arcturus Networks Inc.
+ *           http://www.arcturusnetworks.com/products/ucp1020/
+ *           by Oleksandr G Zhadan et al.
+ *
+ * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
+ *
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <malloc.h>
+#include <spi_flash.h>
+
+#include <asm/io.h>
+
+#ifndef CONFIG_SF_DEFAULT_SPEED
+#   define CONFIG_SF_DEFAULT_SPEED	1000000
+#endif
+#ifndef CONFIG_SF_DEFAULT_MODE
+#   define CONFIG_SF_DEFAULT_MODE	SPI_MODE0
+#endif
+#ifndef CONFIG_SF_DEFAULT_CS
+#   define CONFIG_SF_DEFAULT_CS		0
+#endif
+#ifndef CONFIG_SF_DEFAULT_BUS
+#   define CONFIG_SF_DEFAULT_BUS	0
+#endif
+
+#define MAX_SERIAL_SIZE 15
+#define MAX_HWADDR_SIZE 17
+
+#define FIRM_ADDR1 (0x200 - sizeof(smac))
+#define FIRM_ADDR2 (0x400 - sizeof(smac))
+#define FIRM_ADDR3 (CONFIG_ENV_SECT_SIZE + 0x200 - sizeof(smac))
+#define FIRM_ADDR4 (CONFIG_ENV_SECT_SIZE + 0x400 - sizeof(smac))
+
+static struct spi_flash *flash;
+char smac[4][18];
+
+static int ishwaddr(char *hwaddr)
+{
+	if (strlen(hwaddr) == MAX_HWADDR_SIZE)
+		if (hwaddr[2] == ':' &&
+		    hwaddr[5] == ':' &&
+		    hwaddr[8] == ':' &&
+		    hwaddr[11] == ':' &&
+		    hwaddr[14] == ':')
+			return 0;
+	return -1;
+}
+
+static int set_arc_product(int argc, char *const argv[])
+{
+	int err = 0;
+	char *mystrerr = "ERROR: Failed to save factory info in spi location";
+
+	if (argc != 5)
+		return -1;
+
+	/* Check serial number */
+	if (strlen(argv[1]) != MAX_SERIAL_SIZE)
+		return -1;
+
+	/* Check HWaddrs */
+	if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
+		return -1;
+
+	strcpy(smac[3], argv[1]);
+	strcpy(smac[2], argv[2]);
+	strcpy(smac[1], argv[3]);
+	strcpy(smac[0], argv[4]);
+
+	flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
+				CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
+
+	/*
+	 * Save factory defaults
+	 */
+
+	if (spi_flash_write(flash, FIRM_ADDR1, sizeof(smac), smac)) {
+		printf("%s: %s [1]\n", __func__, mystrerr);
+		err++;
+	}
+	if (spi_flash_write(flash, FIRM_ADDR2, sizeof(smac), smac)) {
+		printf("%s: %s [2]\n", __func__, mystrerr);
+		err++;
+	}
+
+	if (spi_flash_write(flash, FIRM_ADDR3, sizeof(smac), smac)) {
+		printf("%s: %s [3]\n", __func__, mystrerr);
+		err++;
+	}
+
+	if (spi_flash_write(flash, FIRM_ADDR4, sizeof(smac), smac)) {
+		printf("%s: %s [4]\n", __func__, mystrerr);
+		err++;
+	}
+
+	if (err == 4) {
+		printf("%s: %s [ALL]\n", __func__, mystrerr);
+		return -2;
+	}
+
+	return 0;
+}
+
+int get_arc_info(void)
+{
+	int location = 1;
+	char *myerr = "ERROR: Failed to read all 4 factory info spi locations";
+
+	flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
+				CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
+
+	if (spi_flash_read(flash, FIRM_ADDR1, sizeof(smac), smac)) {
+		location++;
+		if (spi_flash_read(flash, FIRM_ADDR2, sizeof(smac), smac)) {
+			location++;
+			if (spi_flash_read(flash, FIRM_ADDR3, sizeof(smac),
+					   smac)) {
+				location++;
+				if (spi_flash_read(flash, FIRM_ADDR4,
+						   sizeof(smac), smac)) {
+					printf("%s: %s\n", __func__, myerr);
+					return -2;
+				}
+			}
+		}
+	}
+	if (smac[3][0] != 0) {
+		if (location > 1)
+			printf("Using region %d\n", location);
+		printf("SERIAL: ");
+		if (smac[3][0] == 0xFF) {
+			printf("\t<not found>\n");
+		} else {
+			printf("\t%s\n", smac[3]);
+			setenv("SERIAL", smac[3]);
+		}
+	}
+
+	if (strcmp(smac[2], "00:00:00:00:00:00") == 0)
+		return 0;
+
+	printf("HWADDR0:");
+	if (smac[2][0] == 0xFF) {
+		printf("\t<not found>\n");
+	} else {
+		char *ret = getenv("ethaddr");
+
+		if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
+			setenv("ethaddr", smac[2]);
+			printf("\t%s (factory)\n", smac[2]);
+		} else {
+			printf("\t%s\n", ret);
+		}
+	}
+
+	if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
+		setenv("eth1addr", smac[2]);
+		setenv("eth2addr", smac[2]);
+		return 0;
+	}
+
+	printf("HWADDR1:");
+	if (smac[1][0] == 0xFF) {
+		printf("\t<not found>\n");
+	} else {
+		char *ret = getenv("eth1addr");
+
+		if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
+			setenv("eth1addr", smac[1]);
+			printf("\t%s (factory)\n", smac[1]);
+		} else {
+			printf("\t%s\n", ret);
+		}
+	}
+
+	if (strcmp(smac[0], "00:00:00:00:00:00") == 0) {
+		setenv("eth2addr", smac[1]);
+		return 0;
+	}
+
+	printf("HWADDR2:");
+	if (smac[0][0] == 0xFF) {
+		printf("\t<not found>\n");
+	} else {
+		char *ret = getenv("eth2addr");
+
+		if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
+			setenv("eth2addr", smac[0]);
+			printf("\t%s (factory)\n", smac[0]);
+		} else {
+			printf("\t%s\n", ret);
+		}
+	}
+
+	return 0;
+}
+
+static int do_arc_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	const char *cmd;
+	int ret = -1;
+
+	cmd = argv[1];
+	--argc;
+	++argv;
+
+	if (strcmp(cmd, "product") == 0) {
+		ret = set_arc_product(argc, argv);
+		goto done;
+	}
+	if (strcmp(cmd, "info") == 0) {
+		ret = get_arc_info();
+		goto done;
+	}
+done:
+	if (ret == -1)
+		return CMD_RET_USAGE;
+
+	return ret;
+}
+
+U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
+	   "Arcturus product command sub-system",
+	   "product serial hwaddr0 hwaddr1 hwaddr2    - save Arcturus factory env\n"
+	   "info                                      - show Arcturus factory env\n\n");