arm: socfpga: Add handoff data support for Intel N5X device

N5X support both HPS handoff data and DDR handoff data.
Existing HPS handoff functions are restructured to support both existing
devices and N5X device.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
index a7ad7a1..e7cb5ea 100644
--- a/arch/arm/mach-socfpga/wrap_handoff_soc64.c
+++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -10,12 +10,64 @@
 #include <errno.h>
 #include "log.h"
 
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
+static enum endianness check_endianness(u32 handoff)
+{
+	switch (handoff) {
+	case SOC64_HANDOFF_MAGIC_BOOT:
+	case SOC64_HANDOFF_MAGIC_MUX:
+	case SOC64_HANDOFF_MAGIC_IOCTL:
+	case SOC64_HANDOFF_MAGIC_FPGA:
+	case SOC64_HANDOFF_MAGIC_DELAY:
+	case SOC64_HANDOFF_MAGIC_CLOCK:
+	case SOC64_HANDOFF_MAGIC_MISC:
+		return BIG_ENDIAN;
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
+		debug("%s: umctl2 handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+	case SOC64_HANDOFF_DDR_PHY_MAGIC:
+		debug("%s: PHY handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+	case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
+		debug("%s: PHY engine handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+#endif
+	default:
+		debug("%s: Unknown endianness!!\n", __func__);
+		return UNKNOWN_ENDIANNESS;
+	}
+}
+
+static int getting_endianness(void *handoff_address, enum endianness *endian_t)
+{
+	/* Checking handoff data is little endian ? */
+	*endian_t = check_endianness(readl(handoff_address));
+
+	if (*endian_t == UNKNOWN_ENDIANNESS) {
+		/* Trying to check handoff data is big endian? */
+		*endian_t = check_endianness(swab32(readl(handoff_address)));
+		if (*endian_t == UNKNOWN_ENDIANNESS) {
+			debug("%s: Cannot find HANDOFF MAGIC ", __func__);
+			debug("at addr 0x%p\n", (u32 *)handoff_address);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+int socfpga_get_handoff_size(void *handoff_address)
 {
 	u32 size;
+	int ret;
+	enum endianness endian_t;
+
+	ret = getting_endianness(handoff_address, &endian_t);
+	if (ret)
+		return ret;
 
 	size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
-	if (endian == BIG_ENDIAN)
+	if (endian_t == BIG_ENDIAN)
 		size = swab32(size);
 
 	size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
@@ -26,41 +78,53 @@
 	return size;
 }
 
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
-			 enum endianness big_endian)
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
 {
-	u32 temp, i;
+	u32 temp;
 	u32 *table_x32 = table;
+	u32 i = 0;
+	int ret;
+	enum endianness endian_t;
 
-	debug("%s: handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
+	ret = getting_endianness(handoff_address, &endian_t);
+	if (ret)
+		return ret;
 
-	if (big_endian) {
-		if (swab32(readl(SOC64_HANDOFF_BASE)) == SOC64_HANDOFF_MAGIC_BOOT) {
-			debug("Handoff table address = 0x%p ", table_x32);
-			debug("table length = 0x%x\n", table_len);
-			debug("%s: handoff data =\n{\n", __func__);
+	temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
+		    (i * sizeof(u32)));
 
-			for (i = 0; i < table_len; i++) {
-				temp = readl(handoff_address +
-					     SOC64_HANDOFF_OFFSET_DATA +
-					     (i * sizeof(u32)));
-				*table_x32 = swab32(temp);
+	if (endian_t == BIG_ENDIAN) {
+		debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
+		debug("Handoff table address = 0x%p ", table_x32);
+		debug("table length = 0x%x\n", table_len);
+		debug("%s: handoff data =\n{\n", __func__);
+		*table_x32 = swab32(temp);
+	} else if (endian_t == LITTLE_ENDIAN) {
+		debug(" {\n");
+		*table_x32 = temp;
+	}
 
-				if (!(i % 2))
-					debug(" No.%d Addr 0x%08x: ", i,
-					      *table_x32);
-				else
-					debug(" 0x%08x\n", *table_x32);
+	debug(" No.%d Addr 0x%08x: ", i, *table_x32);
 
-				table_x32++;
-			}
-			debug("\n}\n");
-		} else {
-			debug("%s: Cannot find SOC64_HANDOFF_MAGIC_BOOT ", __func__);
-			debug("at addr  0x%p\n", (u32 *)handoff_address);
-			return -EPERM;
-		}
+	for (i = 1; i < table_len; i++) {
+		table_x32++;
+
+		temp = readl(handoff_address +
+			     SOC64_HANDOFF_OFFSET_DATA +
+			     (i * sizeof(u32)));
+
+		if (endian_t == BIG_ENDIAN)
+			*table_x32 = swab32(temp);
+		else if (endian_t == LITTLE_ENDIAN)
+			*table_x32 = temp;
+
+		if (!(i % 2))
+			debug(" No.%d Addr 0x%08x: ", i,
+			      *table_x32);
+		else
+			debug(" 0x%08x\n", *table_x32);
 	}
+	debug("\n}\n");
 
 	return 0;
 }