arm: mvebu: Add basic support for the Marvell Armada 375 SoC

This patch adds basic support for the Armada 375. Please note that
currently the SerDes and DDR3 init code for the A375 is not
included / enabled. This will be done in a later, follow-up patch.

Right now, this A375 mainline U-Boot can only be used by chainloading
it via the original Marvell U-Boot. This can be done via this
command:

=> tftpboot 00800000 a375/u-boot-dtb.bin;go 00800000

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Luka Perkov <luka.perkov@sartura.hr>
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index b96b81b..ac009a3 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -15,6 +15,7 @@
 obj-y	= cpu.o
 obj-y	+= dram.o
 ifndef CONFIG_SPL_BUILD
+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
 endif
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 30b175c..9913802 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -54,17 +54,57 @@
 	case SOC_MV78260_ID:
 	case SOC_MV78460_ID:
 		return MVEBU_SOC_AXP;
+
+	case SOC_88F6720_ID:
+		return MVEBU_SOC_A375;
+
 	case SOC_88F6810_ID:
 	case SOC_88F6820_ID:
 	case SOC_88F6828_ID:
 		return MVEBU_SOC_A38X;
 	}
+
 	return MVEBU_SOC_UNKNOWN;
 }
 
 #if defined(CONFIG_DISPLAY_CPUINFO)
 
-#if defined(CONFIG_ARMADA_38X)
+#if defined(CONFIG_ARMADA_375)
+/* SAR frequency values for Armada 375 */
+static const struct sar_freq_modes sar_freq_tab[] = {
+	{  0,  0x0,  266,  133,  266 },
+	{  1,  0x0,  333,  167,  167 },
+	{  2,  0x0,  333,  167,  222 },
+	{  3,  0x0,  333,  167,  333 },
+	{  4,  0x0,  400,  200,  200 },
+	{  5,  0x0,  400,  200,  267 },
+	{  6,  0x0,  400,  200,  400 },
+	{  7,  0x0,  500,  250,  250 },
+	{  8,  0x0,  500,  250,  334 },
+	{  9,  0x0,  500,  250,  500 },
+	{ 10,  0x0,  533,  267,  267 },
+	{ 11,  0x0,  533,  267,  356 },
+	{ 12,  0x0,  533,  267,  533 },
+	{ 13,  0x0,  600,  300,  300 },
+	{ 14,  0x0,  600,  300,  400 },
+	{ 15,  0x0,  600,  300,  600 },
+	{ 16,  0x0,  666,  333,  333 },
+	{ 17,  0x0,  666,  333,  444 },
+	{ 18,  0x0,  666,  333,  666 },
+	{ 19,  0x0,  800,  400,  267 },
+	{ 20,  0x0,  800,  400,  400 },
+	{ 21,  0x0,  800,  400,  534 },
+	{ 22,  0x0,  900,  450,  300 },
+	{ 23,  0x0,  900,  450,  450 },
+	{ 24,  0x0,  900,  450,  600 },
+	{ 25,  0x0, 1000,  500,  500 },
+	{ 26,  0x0, 1000,  500,  667 },
+	{ 27,  0x0, 1000,  333,  500 },
+	{ 28,  0x0,  400,  400,  400 },
+	{ 29,  0x0, 1100,  550,  550 },
+	{ 0xff, 0xff,    0,   0,   0 }	/* 0xff marks end of array */
+};
+#elif defined(CONFIG_ARMADA_38X)
 /* SAR frequency values for Armada 38x */
 static const struct sar_freq_modes sar_freq_tab[] = {
 	{  0x0,  0x0,  666, 333, 333 },
@@ -98,9 +138,13 @@
 	u32 freq;
 	int i;
 
+#if defined(CONFIG_ARMADA_375)
+	val = readl(CONFIG_SAR2_REG);	/* SAR - Sample At Reset */
+#else
 	val = readl(CONFIG_SAR_REG);	/* SAR - Sample At Reset */
+#endif
 	freq = (val & SAR_CPU_FREQ_MASK) >> SAR_CPU_FREQ_OFFS;
-#if !defined(CONFIG_ARMADA_38X)
+#if defined(SAR2_CPU_FREQ_MASK)
 	/*
 	 * Shift CPU0 clock frequency select bit from SAR2 register
 	 * into correct position
@@ -110,7 +154,7 @@
 #endif
 	for (i = 0; sar_freq_tab[i].val != 0xff; i++) {
 		if (sar_freq_tab[i].val == freq) {
-#if defined(CONFIG_ARMADA_38X)
+#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X)
 			*sar_freq = sar_freq_tab[i];
 			return;
 #else
@@ -152,6 +196,9 @@
 	case SOC_MV78460_ID:
 		puts("MV78460-");
 		break;
+	case SOC_88F6720_ID:
+		puts("MV88F6720-");
+		break;
 	case SOC_88F6810_ID:
 		puts("MV88F6810-");
 		break;
@@ -180,6 +227,17 @@
 		}
 	}
 
+	if (mvebu_soc_family() == MVEBU_SOC_A375) {
+		switch (revid) {
+		case MV_88F67XX_A0_ID:
+			puts("A0");
+			break;
+		default:
+			printf("?? (%x)", revid);
+			break;
+		}
+	}
+
 	if (mvebu_soc_family() == MVEBU_SOC_A38X) {
 		switch (revid) {
 		case MV_88F68XX_Z1_ID:
diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h
index cc1fc5f..b8a8c62 100644
--- a/arch/arm/mach-mvebu/include/mach/config.h
+++ b/arch/arm/mach-mvebu/include/mach/config.h
@@ -17,7 +17,8 @@
 
 #include <asm/arch/soc.h>
 
-#if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_38X)
+#if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_375) \
+	|| defined(CONFIG_ARMADA_38X)
 /*
  * Set this for the common xor register definitions needed in dram.c
  * for A38x as well here.
@@ -78,8 +79,10 @@
 #ifdef CONFIG_CMD_NET
 #define CONFIG_CMD_MII
 #define CONFIG_MII		/* expose smi ove miiphy interface */
+#if !defined(CONFIG_ARMADA_375)
 #define CONFIG_MVNETA		/* Enable Marvell Gbe Controller Driver */
 #define CONFIG_PHYLIB
+#endif
 #define CONFIG_ENV_OVERWRITE	/* ethaddr can be reprogrammed */
 #define CONFIG_PHY_GIGE		/* GbE speed/duplex detect */
 #define CONFIG_ARP_TIMEOUT	200
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index dd58b4a..cbec876 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -61,6 +61,7 @@
 
 enum {
 	MVEBU_SOC_AXP,
+	MVEBU_SOC_A375,
 	MVEBU_SOC_A38X,
 	MVEBU_SOC_UNKNOWN,
 };
@@ -89,7 +90,11 @@
  * Ref: Datasheet sec:A.28
  */
 struct mvebu_system_registers {
+#if defined(CONFIG_ARMADA_375)
+	u8 pad1[0x54];
+#else
 	u8 pad1[0x60];
+#endif
 	u32 rstoutn_mask; /* 0x60 */
 	u32 sys_soft_rst; /* 0x64 */
 };
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index b317940..a12be2a 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -14,10 +14,14 @@
 #define SOC_MV78230_ID		0x7823
 #define SOC_MV78260_ID		0x7826
 #define SOC_MV78460_ID		0x7846
+#define SOC_88F6720_ID		0x6720
 #define SOC_88F6810_ID		0x6810
 #define SOC_88F6820_ID		0x6820
 #define SOC_88F6828_ID		0x6828
 
+/* A375 revisions */
+#define MV_88F67XX_A0_ID	0x3
+
 /* A38x revisions */
 #define MV_88F68XX_Z1_ID	0x0
 #define MV_88F68XX_A0_ID	0x4
@@ -106,7 +110,20 @@
 #define BOOTROM_ERR_MODE_MASK	(0xf << BOOTROM_ERR_MODE_OFFS)
 #define BOOTROM_ERR_MODE_UART	0x6
 
+#if defined(CONFIG_ARMADA_375)
+/* SAR values for Armada 375 */
+#define CONFIG_SAR_REG		(MVEBU_REGISTER(0xe8200))
+#define CONFIG_SAR2_REG		(MVEBU_REGISTER(0xe8204))
+
+#define SAR_CPU_FREQ_OFFS	17
+#define SAR_CPU_FREQ_MASK	(0x1f << SAR_CPU_FREQ_OFFS)
+
+#define BOOT_DEV_SEL_OFFS	3
+#define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
+
-#if defined(CONFIG_ARMADA_38X)
+#define BOOT_FROM_UART		0x30
+#define BOOT_FROM_SPI		0x38
+#elif defined(CONFIG_ARMADA_38X)
 /* SAR values for Armada 38x */
 #define CONFIG_SAR_REG		(MVEBU_REGISTER(0x18600))
 
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index 0879873..ac5bb2c 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -99,11 +99,14 @@
 
 	timer_init();
 
+	/* Armada 375 does not support SerDes and DDR3 init yet */
+#if !defined(CONFIG_ARMADA_375)
 	/* First init the serdes PHY's */
 	serdes_phy_config();
 
 	/* Setup DDR */
 	ddr3_init();
+#endif
 
 	/*
 	 * Return to the BootROM to continue the Marvell xmodem