[v3 04/17] arm: socfpga: Add handoff data support for Intel N5X device
Siew Chin Lim
elly.siew.chin.lim at intel.com
Sun Jun 13 10:48:39 CEST 2021
From: Tien Fong Chee <tien.fong.chee at intel.com>
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 at intel.com>
Signed-off-by: Tien Fong Chee <tien.fong.chee at intel.com>
---
v3
- Adding helper function for getting endianness type.
v2:
- Enabled auto detect the endianness from the magic word
- Merged and simplifying the big and little endian flow
---
.../mach-socfpga/include/mach/handoff_soc64.h | 38 ++++-
arch/arm/mach-socfpga/system_manager_soc64.c | 18 +--
arch/arm/mach-socfpga/wrap_handoff_soc64.c | 132 +++++++++++++-----
3 files changed, 140 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
index 3750216a9a..902fc6bfb5 100644
--- a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2016-2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
*
*/
@@ -23,8 +23,36 @@
#define SOC64_HANDOFF_OFFSET_DATA 0x10
#define SOC64_HANDOFF_SIZE 4096
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_STRATIX10) || \
+ IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX)
#define SOC64_HANDOFF_BASE 0xFFE3F000
#define SOC64_HANDOFF_MISC (SOC64_HANDOFF_BASE + 0x610)
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define SOC64_HANDOFF_BASE 0xFFE5F000
+#define SOC64_HANDOFF_MISC (SOC64_HANDOFF_BASE + 0x630)
+
+/* DDR handoff */
+#define SOC64_HANDOFF_DDR_BASE 0xFFE5C000
+#define SOC64_HANDOFF_DDR_MAGIC 0x48524444
+#define SOC64_HANDOFF_DDR_UMCTL2_MAGIC 0x4C54434D
+#define SOC64_HANDOFF_DDR_UMCTL2_DDR4_TYPE 0x34524444
+#define SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_0_TYPE 0x3044504C
+#define SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_1_TYPE 0x3144504C
+#define SOC64_HANDOFF_DDR_MEMRESET_BASE (SOC64_HANDOFF_DDR_BASE + 0xC)
+#define SOC64_HANDOFF_DDR_UMCTL2_SECTION (SOC64_HANDOFF_DDR_BASE + 0x10)
+#define SOC64_HANDOFF_DDR_PHY_MAGIC 0x43594850
+#define SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC 0x45594850
+#define SOC64_HANDOFF_DDR_PHY_BASE_OFFSET 0x8
+#define SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET 0x8
+#define SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET 0xC
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_1D_SECTION 0xFFE50000
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_1D_SECTION 0xFFE58000
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_2D_SECTION 0xFFE44000
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_2D_SECTION 0xFFE4C000
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_LENGTH SZ_32K
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_LENGTH SZ_16K
+#endif
+
#define SOC64_HANDOFF_MUX (SOC64_HANDOFF_BASE + 0x10)
#define SOC64_HANDOFF_IOCTL (SOC64_HANDOFF_BASE + 0x1A0)
#define SOC64_HANDOFF_FPGA (SOC64_HANDOFF_BASE + 0x330)
@@ -52,11 +80,11 @@
#include <asm/types.h>
enum endianness {
LITTLE_ENDIAN = 0,
- BIG_ENDIAN
+ BIG_ENDIAN,
+ UNKNOWN_ENDIANNESS
};
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian);
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
- enum endianness big_endian);
+int socfpga_get_handoff_size(void *handoff_address);
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len);
#endif
#endif /* _HANDOFF_SOC64_H_ */
diff --git a/arch/arm/mach-socfpga/system_manager_soc64.c b/arch/arm/mach-socfpga/system_manager_soc64.c
index 3b5e774e2d..958bb5107b 100644
--- a/arch/arm/mach-socfpga/system_manager_soc64.c
+++ b/arch/arm/mach-socfpga/system_manager_soc64.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
*
*/
@@ -66,10 +66,10 @@ void populate_sysmgr_fpgaintf_module(void)
void populate_sysmgr_pinmux(void)
{
u32 len, i;
- u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX, BIG_ENDIAN);
- u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL, BIG_ENDIAN);
- u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA, BIG_ENDIAN);
- u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY, BIG_ENDIAN);
+ u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX);
+ u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL);
+ u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA);
+ u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY);
len = (len_mux > len_ioctl) ? len_mux : len_ioctl;
len = (len > len_fpga) ? len : len_fpga;
@@ -79,7 +79,7 @@ void populate_sysmgr_pinmux(void)
/* setup the pin sel */
len = (len_mux < SOC64_HANDOFF_MUX_LEN) ? len_mux : SOC64_HANDOFF_MUX_LEN;
- socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len, BIG_ENDIAN);
+ socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len);
for (i = 0; i < len; i = i + 2) {
writel(handoff_table[i + 1],
handoff_table[i] +
@@ -89,7 +89,7 @@ void populate_sysmgr_pinmux(void)
/* setup the pin ctrl */
len = (len_ioctl < SOC64_HANDOFF_IOCTL_LEN) ? len_ioctl : SOC64_HANDOFF_IOCTL_LEN;
- socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len, BIG_ENDIAN);
+ socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len);
for (i = 0; i < len; i = i + 2) {
writel(handoff_table[i + 1],
handoff_table[i] +
@@ -99,7 +99,7 @@ void populate_sysmgr_pinmux(void)
/* setup the fpga use */
len = (len_fpga < SOC64_HANDOFF_FPGA_LEN) ? len_fpga : SOC64_HANDOFF_FPGA_LEN;
- socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len, BIG_ENDIAN);
+ socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len);
for (i = 0; i < len; i = i + 2) {
writel(handoff_table[i + 1],
handoff_table[i] +
@@ -109,7 +109,7 @@ void populate_sysmgr_pinmux(void)
/* setup the IO delay */
len = (len_delay < SOC64_HANDOFF_DELAY_LEN) ? len_delay : SOC64_HANDOFF_DELAY_LEN;
- socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len, BIG_ENDIAN);
+ socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len);
for (i = 0; i < len; i = i + 2) {
writel(handoff_table[i + 1],
handoff_table[i] +
diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
index a7ad7a18ed..e7cb5ea89c 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 @@ int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
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);
-
- 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__);
-
- for (i = 0; i < table_len; i++) {
- temp = readl(handoff_address +
- SOC64_HANDOFF_OFFSET_DATA +
- (i * sizeof(u32)));
- *table_x32 = swab32(temp);
-
- if (!(i % 2))
- debug(" No.%d Addr 0x%08x: ", i,
- *table_x32);
- else
- debug(" 0x%08x\n", *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;
- }
+ ret = getting_endianness(handoff_address, &endian_t);
+ if (ret)
+ return ret;
+
+ temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
+ (i * sizeof(u32)));
+
+ 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;
+ }
+
+ debug(" No.%d Addr 0x%08x: ", i, *table_x32);
+
+ 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;
}
--
2.19.0
More information about the U-Boot
mailing list