arm: mvebu: Add Marvell's integrated CPUs

Marvell's switch chips with integrated CPUs (collectively referred to as
MSYS) share common ancestry with the Armada SoCs. Some of the IP blocks
(e.g. xor) are located at different addresses and DFX server exists as a
separate target on the MBUS (on Armada-38x it's just part of the core
complex registers).

Signed-off-by: Chris Packham <judge.packham@gmail.com>
Reviewed-by: Stefan Roese <sr@denx.de>
Signed-off-by: Stefan Roese <sr@denx.de>
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index a46f13b..bb4ca56 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -46,7 +46,7 @@
 # Armada PLL frequency (used for NAND clock generation)
 config SYS_MVEBU_PLL_CLOCK
 	int
-	default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K
+	default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K || ARMADA_MSYS
 	default "1000000000" if ARMADA_38X || ARMADA_375
 
 # Armada XP/38x SoC types...
@@ -63,6 +63,22 @@
 	bool
 	select ARMADA_XP
 
+config ARMADA_MSYS
+	bool
+	select ARMADA_32BIT
+
+config 98DX4251
+	bool
+	select ARMADA_MSYS
+
+config 98DX3336
+	bool
+	select ARMADA_MSYS
+
+config 98DX3236
+	bool
+	select ARMADA_MSYS
+
 config 88F6820
 	bool
 	select ARMADA_38X
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index c0274a6..02d3ce2 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -25,6 +25,7 @@
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
+obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
 
 extra-y += kwbimage.cfg
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 5d3f553..9868462 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -23,6 +23,11 @@
 	/* NOR */
 	{ MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE,
 	  CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM },
+
+#ifdef CONFIG_ARMADA_MSYS
+	/* DFX */
+	{ MBUS_DFX_BASE, MBUS_DFX_SIZE, CPU_TARGET_DFX, 0 },
+#endif
 };
 
 void lowlevel_init(void)
@@ -121,6 +126,14 @@
 	{ 0x13,  0x0, 2000, 1000, 933 },
 	{ 0xff, 0xff,    0,    0,   0 }	/* 0xff marks end of array */
 };
+#elif defined(CONFIG_ARMADA_MSYS)
+static const struct sar_freq_modes sar_freq_tab[] = {
+	{  0x0,	0x0,  400,  400, 400 },
+	{  0x2, 0x0,  667,  333, 667 },
+	{  0x3, 0x0,  800,  400, 800 },
+	{  0x5, 0x0,  800,  400, 800 },
+	{ 0xff, 0xff,    0,   0,   0 }	/* 0xff marks end of array */
+};
 #else
 /* SAR frequency values for Armada XP */
 static const struct sar_freq_modes sar_freq_tab[] = {
@@ -144,7 +157,7 @@
 	u32 freq;
 	int i;
 
-#if defined(CONFIG_ARMADA_375)
+#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_MSYS)
 	val = readl(CONFIG_SAR2_REG);	/* SAR - Sample At Reset */
 #else
 	val = readl(CONFIG_SAR_REG);	/* SAR - Sample At Reset */
@@ -160,7 +173,7 @@
 #endif
 	for (i = 0; sar_freq_tab[i].val != 0xff; i++) {
 		if (sar_freq_tab[i].val == freq) {
-#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X)
+#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS)
 			*sar_freq = sar_freq_tab[i];
 			return;
 #else
@@ -270,6 +283,20 @@
 		}
 	}
 
+	if (mvebu_soc_family() == MVEBU_SOC_MSYS) {
+		switch (revid) {
+		case 3:
+			puts("A0");
+			break;
+		case 4:
+			puts("A1");
+			break;
+		default:
+			printf("?? (%x)", revid);
+			break;
+		}
+	}
+
 	get_sar_freq(&sar_freq);
 	printf(" at %d MHz\n", sar_freq.p_clk);
 
diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h
index 71c4f70..bbcfcfd 100644
--- a/arch/arm/mach-mvebu/include/mach/config.h
+++ b/arch/arm/mach-mvebu/include/mach/config.h
@@ -17,7 +17,7 @@
 #include <asm/arch/soc.h>
 
 #if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_375) \
-	|| defined(CONFIG_ARMADA_38X)
+	|| defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS)
 /*
  * Set this for the common xor register definitions needed in dram.c
  * for A38x as well here.
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 9e23043..b9153d8 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -34,6 +34,7 @@
 	CPU_TARGET_PCIE02 = 0x4,
 	CPU_TARGET_ETH01 = 0x7,
 	CPU_TARGET_PCIE13 = 0x8,
+	CPU_TARGET_DFX = 0x8,
 	CPU_TARGET_SASRAM = 0x9,
 	CPU_TARGET_SATA01 = 0xa, /* A38X */
 	CPU_TARGET_NAND = 0xd,
@@ -79,6 +80,8 @@
 #define MBUS_PCI_IO_SIZE	(64 << 10)
 #define MBUS_SPI_BASE		0xF4000000
 #define MBUS_SPI_SIZE		(8 << 20)
+#define MBUS_DFX_BASE		0xF6000000
+#define MBUS_DFX_SIZE		(1 << 20)
 #define MBUS_BOOTROM_BASE	0xF8000000
 #define MBUS_BOOTROM_SIZE	(8 << 20)
 
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 01577f4..2d88c41 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -76,7 +76,11 @@
 #define MVEBU_NAND_BASE		(MVEBU_REGISTER(0xd0000))
 #define MVEBU_SDIO_BASE		(MVEBU_REGISTER(0xd8000))
 #define MVEBU_LCD_BASE		(MVEBU_REGISTER(0xe0000))
+#ifdef CONFIG_ARMADA_MSYS
+#define MVEBU_DFX_BASE		(MBUS_DFX_BASE)
+#else
 #define MVEBU_DFX_BASE		(MVEBU_REGISTER(0xe4000))
+#endif
 
 #define SOC_COHERENCY_FABRIC_CTRL_REG	(MVEBU_REGISTER(0x20200))
 #define MBUS_ERR_PROP_EN	(1 << 8)
@@ -149,6 +153,22 @@
 #define BOOT_FROM_SPI		0x32
 #define BOOT_FROM_MMC		0x30
 #define BOOT_FROM_MMC_ALT	0x31
+#elif defined(CONFIG_ARMADA_MSYS)
+/* SAR values for MSYS */
+#define CONFIG_SAR_REG		(MBUS_DFX_BASE  + 0xf8200)
+#define CONFIG_SAR2_REG		(MBUS_DFX_BASE  + 0xf8204)
+
+#define SAR_CPU_FREQ_OFFS	18
+#define SAR_CPU_FREQ_MASK	(0x7 << SAR_CPU_FREQ_OFFS)
+#define SAR_BOOT_DEVICE_OFFS	11
+#define SAR_BOOT_DEVICE_MASK	(0x7 << SAR_BOOT_DEVICE_OFFS)
+
+#define BOOT_DEV_SEL_OFFS	11
+#define BOOT_DEV_SEL_MASK	(0x7 << BOOT_DEV_SEL_OFFS)
+
+#define BOOT_FROM_NAND		0x1
+#define BOOT_FROM_UART		0x2
+#define BOOT_FROM_SPI		0x3
 #else
 /* SAR values for Armada XP */
 #define CONFIG_SAR_REG		(MVEBU_REGISTER(0x18230))
diff --git a/arch/arm/mach-mvebu/mbus.c b/arch/arm/mach-mvebu/mbus.c
index 7be67b7..c68e93b 100644
--- a/arch/arm/mach-mvebu/mbus.c
+++ b/arch/arm/mach-mvebu/mbus.c
@@ -344,6 +344,11 @@
 		}
 	}
 	mbus_dram_info.num_cs = cs;
+
+#if defined(CONFIG_ARMADA_MSYS)
+	/* Disable MBUS Err Prop - in order to avoid data aborts */
+	clrbits_le32(mbus->mbuswins_base + 0x200, BIT(8));
+#endif
 }
 
 static const struct mvebu_mbus_soc_data