arm64: mvebu: Add basic support for the Turris Mox board

This adds basic support for the Turris Mox board from CZ.NIC, which is
currently being crowdfunded on Indiegogo.

Turris Mox is as modular router based on the Armada 3720 SOC (same as
EspressoBin).

The basic module can be extended by different modules. The device tree
binary for the kernel can be dependent on which modules are connected,
and in what order. Because of this, the board specific code creates
in U-Boot a variable called module_topology, which carries this
information.

Signed-off-by: Marek Behun <marek.behun@nic.cz>
Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/board/CZ.NIC/turris_mox/MAINTAINERS b/board/CZ.NIC/turris_mox/MAINTAINERS
new file mode 100644
index 0000000..2b9c113
--- /dev/null
+++ b/board/CZ.NIC/turris_mox/MAINTAINERS
@@ -0,0 +1,6 @@
+TURRIS OMNIA BOARD
+M:	Marek Behún <marek.behun@nic.cz>
+S:	Maintained
+F:	board/CZ.NIC/turris_mox/
+F:	include/configs/turris_mox.h
+F:	configs/turris_mox_defconfig
diff --git a/board/CZ.NIC/turris_mox/Makefile b/board/CZ.NIC/turris_mox/Makefile
new file mode 100644
index 0000000..6197042
--- /dev/null
+++ b/board/CZ.NIC/turris_mox/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+
+obj-y	:= turris_mox.o
diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c
new file mode 100644
index 0000000..130d4c6
--- /dev/null
+++ b/board/CZ.NIC/turris_mox/turris_mox.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <clk.h>
+#include <spi.h>
+#include <linux/string.h>
+
+#ifdef CONFIG_WDT_ARMADA_3720
+#include <wdt.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_WDT_ARMADA_3720
+static struct udevice *watchdog_dev;
+
+void watchdog_reset(void)
+{
+	static ulong next_reset;
+	ulong now;
+
+	if (!watchdog_dev)
+		return;
+
+	now = timer_get_us();
+
+	/* Do not reset the watchdog too often */
+	if (now > next_reset) {
+		wdt_reset(watchdog_dev);
+		next_reset = now + 100000;
+	}
+}
+#endif
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+#ifdef CONFIG_WDT_ARMADA_3720
+	if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
+		printf("Cannot find Armada 3720 watchdog!\n");
+	} else {
+		printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n");
+		wdt_start(watchdog_dev, 180000, 0);
+	}
+#endif
+
+	return 0;
+}
+
+int last_stage_init(void)
+{
+	struct spi_slave *slave;
+	struct udevice *dev;
+	u8 din[10], dout[10];
+	int ret, i;
+	size_t len = 0;
+	char module_topology[128];
+
+	ret = spi_get_bus_and_cs(0, 1, 20000000, SPI_CPHA, "spi_generic_drv",
+				 "mox-modules@1", &dev, &slave);
+	if (ret)
+		goto fail;
+
+	ret = spi_claim_bus(slave);
+	if (ret)
+		goto fail_free;
+
+	memset(din, 0, 10);
+	memset(dout, 0, 10);
+
+	ret = spi_xfer(slave, 80, dout, din, SPI_XFER_ONCE);
+	if (ret)
+		goto fail_release;
+
+	if (din[0] != 0x00 && din[0] != 0xff)
+		goto fail_release;
+
+	printf("Module Topology:\n");
+	for (i = 1; i < 10 && din[i] != 0xff; ++i) {
+		u8 mid = din[i] & 0xf;
+		size_t mlen;
+		const char *mname = "";
+
+		switch (mid) {
+		case 0x1:
+			mname = "sfp-";
+			printf("% 4i: SFP Module\n", i);
+			break;
+		case 0x2:
+			mname = "pci-";
+			printf("% 4i: Mini-PCIe Module\n", i);
+			break;
+		case 0x3:
+			mname = "topaz-";
+			printf("% 4i: Topaz Switch Module\n", i);
+			break;
+		default:
+			printf("% 4i: unknown (ID %i)\n", i, mid);
+		}
+
+		mlen = strlen(mname);
+		if (len + mlen < sizeof(module_topology)) {
+			strcpy(module_topology + len, mname);
+			len += mlen;
+		}
+	}
+	printf("\n");
+
+	module_topology[len > 0 ? len - 1 : 0] = '\0';
+
+	env_set("module_topology", module_topology);
+
+fail_release:
+	spi_release_bus(slave);
+fail_free:
+	spi_free_slave(slave);
+fail:
+	if (ret)
+		printf("Cannot read module topology!\n");
+	return ret;
+}