arm: socfpga: Add handoff data support for Intel N5X device
authorTien Fong Chee <tien.fong.chee@intel.com>
Tue, 10 Aug 2021 03:26:29 +0000 (11:26 +0800)
committerTien Fong Chee <tien.fong.chee@intel.com>
Tue, 24 Aug 2021 09:13:35 +0000 (17:13 +0800)
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>
arch/arm/mach-socfpga/include/mach/handoff_soc64.h
arch/arm/mach-socfpga/system_manager_soc64.c
arch/arm/mach-socfpga/wrap_handoff_soc64.c

index 3750216..902fc6b 100644 (file)
@@ -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>
  *
  */
 
 #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)
 #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_ */
index 3b5e774..958bb51 100644 (file)
@@ -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] +
index a7ad7a1..e7cb5ea 100644 (file)
@@ -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>
  *
  */
 
 #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;
 }