n1sdp: add code for DDR ECC enablement and BL33 copy to DDR
authorManoj Kumar <manoj.kumar3@arm.com>
Fri, 21 Jun 2019 16:07:13 +0000 (17:07 +0100)
committerManoj Kumar <manoj.kumar3@arm.com>
Wed, 26 Jun 2019 13:07:51 +0000 (14:07 +0100)
N1SDP platform supports RDIMMs with ECC capability. To use the ECC
capability, the entire DDR memory space has to be zeroed out before
enabling the ECC bits in DMC620. Zeroing out several gigabytes of
memory from SCP is quite time consuming so functions are added that
zeros out the DDR memory from application processor which is
much faster compared to SCP. BL33 binary cannot be copied to DDR memory
before enabling ECC so this is also done by TF-A from IOFPGA-DDR3
memory to main DDR4 memory after ECC is enabled.

Original PLAT_PHY_ADDR_SPACE_SIZE was limited to 36-bits with which
the entire DDR space cannot be accessed as DRAM2 starts in base
0x8080000000. So these macros are redefined for all ARM platforms.

Change-Id: If09524fb65b421b7a368b1b9fc52c49f2ddb7846
Signed-off-by: Manoj Kumar <manoj.kumar3@arm.com>
13 files changed:
include/plat/arm/common/arm_def.h
plat/arm/board/fvp/include/platform_def.h
plat/arm/board/fvp_ve/include/platform_def.h
plat/arm/board/juno/include/platform_def.h
plat/arm/board/n1sdp/include/platform_def.h
plat/arm/board/n1sdp/n1sdp_bl31_setup.c
plat/arm/board/n1sdp/n1sdp_def.h [new file with mode: 0644]
plat/arm/board/n1sdp/n1sdp_plat.c
plat/arm/board/n1sdp/platform.mk
plat/arm/board/rde1edge/include/platform_def.h
plat/arm/board/rdn1edge/include/platform_def.h
plat/arm/board/sgi575/include/platform_def.h
plat/arm/board/sgm775/include/platform_def.h

index 69a9959ad6e057355d0e29348f2079b7d69b6670..ead1a8b3523c7a97dce921e683d0dfefc517e520 100644 (file)
  * Required platform porting definitions common to all ARM standard platforms
  *****************************************************************************/
 
-/*
- * We need to access DRAM2 from BL2 for PSCI_MEM_PROTECT for
- * AArch64 builds
- */
-#ifdef AARCH64
-#define PLAT_PHY_ADDR_SPACE_SIZE                       (1ULL << 36)
-#define PLAT_VIRT_ADDR_SPACE_SIZE                      (1ULL << 36)
-#else
-#define PLAT_PHY_ADDR_SPACE_SIZE                       (1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE                      (1ULL << 32)
-#endif
-
-
 /*
  * This macro defines the deepest retention state possible. A higher state
  * id will represent an invalid or a power down state.
index 2313ab0c265dba3e14e4134a6593e41134684244..207cd31d679a340fd55508a5b31b381d849e8005 100644 (file)
 
 #define PLAT_SP_PRI                    PLAT_RAS_PRI
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef AARCH64
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_DEF_H */
index 1b21c79d12dec8b338d847232fa50e73223536d3..b3b36726442817fc2da22bc1fff7b59209cdb772 100644 (file)
 
 #define PLAT_ARM_G0_IRQ_PROPS(grp)     ARM_G0_IRQ_PROPS(grp)
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef AARCH64
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_H */
index e096e33e3deaf790db1b5cce778092ea953f5b27..d693c26ad50b9811d284d67c19d9a23042a32c9e 100644 (file)
 /* System power domain level */
 #define CSS_SYSTEM_PWR_DMN_LVL         ARM_PWR_LVL2
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef AARCH64
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_DEF_H */
index 0964f56889dfe6832e312b79ea400abe160bb040..ff583a9095cb5e1552485fe4a7c7488d7ce71b48 100644 (file)
 #define PLAT_ARM_CRASH_UART_CLK_IN_HZ          PLAT_ARM_RUN_UART_CLK_IN_HZ
 
 #define PLAT_ARM_DRAM2_BASE                    ULL(0x8080000000)
-#define PLAT_ARM_DRAM2_SIZE                    ULL(0x780000000)
+#define PLAT_ARM_DRAM2_SIZE                    ULL(0xF80000000)
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. The access the complete DDR memory
+ * space the physical & virtual address space limits are extended to
+ * 40-bits.
+ */
+#ifndef AARCH32
+#define PLAT_PHY_ADDR_SPACE_SIZE               (1ULL << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE              (1ULL << 40)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE               (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE              (1ULL << 32)
+#endif
 
 #if CSS_USE_SCMI_SDS_DRIVER
 #define N1SDP_SCMI_PAYLOAD_BASE                        0x45400000
@@ -55,8 +70,8 @@
  * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
  * plat_arm_mmap array defined for each BL stage.
  */
-#define PLAT_ARM_MMAP_ENTRIES                  3
-#define MAX_XLAT_TABLES                                4
+#define PLAT_ARM_MMAP_ENTRIES                  6
+#define MAX_XLAT_TABLES                                7
 
 #define PLATFORM_STACK_SIZE                    0x400
 
 #define PLAT_ARM_G0_IRQ_PROPS(grp)             ARM_G0_IRQ_PROPS(grp)
 
 
-#define N1SDP_DEVICE_BASE                      (0x20000000)
-#define N1SDP_DEVICE_SIZE                      (0x30000000)
+#define N1SDP_DEVICE_BASE                      (0x08000000)
+#define N1SDP_DEVICE_SIZE                      (0x48000000)
 #define N1SDP_MAP_DEVICE                       MAP_REGION_FLAT(        \
                                                N1SDP_DEVICE_BASE,      \
                                                N1SDP_DEVICE_SIZE,      \
                                                MT_DEVICE | MT_RW | MT_SECURE)
 
+#define ARM_MAP_DRAM1                          MAP_REGION_FLAT(        \
+                                               ARM_DRAM1_BASE,         \
+                                               ARM_DRAM1_SIZE,         \
+                                               MT_MEMORY | MT_RW | MT_NS)
+
 /* GIC related constants */
 #define PLAT_ARM_GICD_BASE                     0x30000000
 #define PLAT_ARM_GICC_BASE                     0x2C000000
index 18a0deaba35cce0ba2f0eaf5dadcc52805ac94d9..a831b89f2ca91af1f2fc7d5f77204ae3c3b6378e 100644 (file)
@@ -8,8 +8,35 @@
 
 #include <drivers/arm/css/css_mhu_doorbell.h>
 #include <drivers/arm/css/scmi.h>
+#include <drivers/arm/css/sds.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
 #include <plat/arm/common/plat_arm.h>
 
+#include "n1sdp_def.h"
+
+/*
+ * Memory information structure stored in SDS.
+ * This structure holds the total DDR memory size which will be
+ * used when zeroing out the entire DDR memory before enabling
+ * the ECC capability in DMCs.
+ */
+struct n1sdp_mem_info {
+       uint32_t ddr_size_gb;
+};
+
+/*
+ * BL33 image information structure stored in SDS.
+ * This structure holds the source & destination addresses and
+ * the size of the BL33 image which will be loaded by BL31.
+ */
+struct n1sdp_bl33_info {
+       uint32_t bl33_src_addr;
+       uint32_t bl33_dst_addr;
+       uint32_t bl33_size;
+};
+
 static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
                .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE,
                .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
@@ -27,3 +54,95 @@ const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
 {
        return css_scmi_override_pm_ops(ops);
 }
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP. BL33 binary cannot be copied to DDR memory
+ * before enabling ECC so copy_bl33 function is added to copy BL33 binary
+ * from IOFPGA-DDR3 memory to main DDR4 memory.
+ */
+
+void dmc_ecc_setup(uint32_t ddr_size_gb)
+{
+       uint64_t dram2_size;
+
+       dram2_size = (ddr_size_gb * 1024UL * 1024UL * 1024UL) -
+                       ARM_DRAM1_SIZE;
+
+       INFO("Zeroing DDR memories\n");
+       zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+       flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+       zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size);
+       flush_dcache_range(ARM_DRAM2_BASE, dram2_size);
+
+       INFO("Enabling ECC on DMCs\n");
+       mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN);
+       mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN);
+}
+
+void copy_bl33(uint32_t src, uint32_t dst, uint32_t size)
+{
+       uint32_t i;
+
+       INFO("Copying BL33 to DDR memory\n");
+       for (i = 0; i < size; i = i + 8)
+               mmio_write_64((dst + i), mmio_read_64(src + i));
+
+       for (i = 0; i < size; i = i + 8) {
+               if (mmio_read_64(src + i) != mmio_read_64(dst + i)) {
+                       ERROR("Copy failed!\n");
+                       panic();
+               }
+       }
+}
+
+void bl31_platform_setup(void)
+{
+       int ret;
+       struct n1sdp_mem_info mem_info;
+       struct n1sdp_bl33_info bl33_info;
+
+       arm_bl31_platform_setup();
+
+       ret = sds_init();
+       if (ret != SDS_OK) {
+               ERROR("SDS initialization failed\n");
+               panic();
+       }
+
+       ret = sds_struct_read(N1SDP_SDS_MEM_INFO_STRUCT_ID,
+                               N1SDP_SDS_MEM_INFO_OFFSET,
+                               &mem_info,
+                               N1SDP_SDS_MEM_INFO_SIZE,
+                               SDS_ACCESS_MODE_NON_CACHED);
+       if (ret != SDS_OK) {
+               ERROR("Error getting memory info from SDS\n");
+               panic();
+       }
+       dmc_ecc_setup(mem_info.ddr_size_gb);
+
+       ret = sds_struct_read(N1SDP_SDS_BL33_INFO_STRUCT_ID,
+                               N1SDP_SDS_BL33_INFO_OFFSET,
+                               &bl33_info,
+                               N1SDP_SDS_BL33_INFO_SIZE,
+                               SDS_ACCESS_MODE_NON_CACHED);
+       if (ret != SDS_OK) {
+               ERROR("Error getting BL33 info from SDS\n");
+               panic();
+       }
+       copy_bl33(bl33_info.bl33_src_addr,
+                       bl33_info.bl33_dst_addr,
+                       bl33_info.bl33_size);
+       /*
+        * Pass DDR memory size info to BL33. This method is followed as
+        * currently there is no BL1/BL2 involved in boot flow of N1SDP.
+        * When TBBR is implemented for N1SDP, this method should be removed
+        * and DDR memory size shoule be passed to BL33 using NT_FW_CONFIG
+        * passing mechanism.
+        */
+       mmio_write_32(N1SDP_DDR_MEM_INFO_BASE, mem_info.ddr_size_gb);
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_def.h b/plat/arm/board/n1sdp/n1sdp_def.h
new file mode 100644 (file)
index 0000000..b7f7213
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef N1SDP_DEF_H
+#define N1SDP_DEF_H
+
+/* Non-secure SRAM MMU mapping */
+#define N1SDP_NS_SRAM_BASE                     (0x06000000)
+#define N1SDP_NS_SRAM_SIZE                     (0x00010000)
+#define N1SDP_MAP_NS_SRAM                      MAP_REGION_FLAT(        \
+                                               N1SDP_NS_SRAM_BASE,     \
+                                               N1SDP_NS_SRAM_SIZE,     \
+                                               MT_DEVICE | MT_RW | MT_SECURE)
+
+/* SDS memory information defines */
+#define N1SDP_SDS_MEM_INFO_STRUCT_ID           8
+#define N1SDP_SDS_MEM_INFO_OFFSET              0
+#define N1SDP_SDS_MEM_INFO_SIZE                        4
+
+/* SDS BL33 image information defines */
+#define N1SDP_SDS_BL33_INFO_STRUCT_ID          9
+#define N1SDP_SDS_BL33_INFO_OFFSET             0
+#define N1SDP_SDS_BL33_INFO_SIZE               12
+
+/* DMC ERR0CTLR0 registers */
+#define N1SDP_DMC0_ERR0CTLR0_REG               0x4E000708
+#define N1SDP_DMC1_ERR0CTLR0_REG               0x4E100708
+
+/* DMC ECC enable bit in ERR0CTLR0 register */
+#define N1SDP_DMC_ERR0CTLR0_ECC_EN             0x1
+
+/* Base address of non-secure SRAM where DDR memory size will be filled */
+#define N1SDP_DDR_MEM_INFO_BASE                        0x06008000
+
+#endif /* N1SDP_DEF_H */
index f36f9e2532139e187b546d799678c3efdf3dd62c..a32ca7251a2f7ca4be07f84ec585b0456a1c4181 100644 (file)
@@ -12,6 +12,8 @@
 #include <plat/common/platform.h>
 #include <drivers/arm/sbsa.h>
 
+#include "n1sdp_def.h"
+
 /*
  * Table of regions to map using the MMU.
  * Replace or extend the below regions as required
@@ -20,6 +22,9 @@
 const mmap_region_t plat_arm_mmap[] = {
        ARM_MAP_SHARED_RAM,
        N1SDP_MAP_DEVICE,
+       N1SDP_MAP_NS_SRAM,
+       ARM_MAP_DRAM1,
+       ARM_MAP_DRAM2,
        {0}
 };
 
index d0c34c8fc291aca477f5b228760382f29d783003..986bd70a5cb621e5a67002950af137cecc565dfb 100644 (file)
@@ -32,7 +32,8 @@ BL31_SOURCES          :=      ${N1SDP_CPU_SOURCES}                    \
                                ${N1SDP_GIC_SOURCES}                    \
                                ${N1SDP_BASE}/n1sdp_bl31_setup.c                \
                                ${N1SDP_BASE}/n1sdp_topology.c          \
-                               ${N1SDP_BASE}/n1sdp_security.c
+                               ${N1SDP_BASE}/n1sdp_security.c          \
+                               drivers/arm/css/sds/sds.c
 
 
 # TF-A not required to load the SCP Images
index 3b3ade0cb2ad682c660d60fde5d378a6e88cf728..c62cda85eb3c0630a7ef5a788c5b196e1cfd03e6 100644 (file)
 
 #define CSS_SYSTEM_PWR_DMN_LVL         ARM_PWR_LVL3
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifndef AARCH32
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_DEF_H */
index 8480c08fea6f446c815b7df740155b3bf2ac16c8..2c7b8bda5650103d38fad2e0e85410a8a42f29f8 100644 (file)
 
 #define PLAT_MAX_PWR_LVL               ARM_PWR_LVL1
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifndef AARCH32
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_DEF_H */
index ec51c9e076e1cf07e411ce56cb027959c9918820..883403bb36de662e4c1e335dce0c82d0c05eced1 100644 (file)
 
 #define PLAT_MAX_PWR_LVL               ARM_PWR_LVL1
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifndef AARCH32
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_DEF_H */
index 8a3431b12de2a75ca390801bd32f56e176396826..3e1fdd129f039f5cadacddc703ec36b9aa5b930a 100644 (file)
 #define PLAT_MAX_CPUS_PER_CLUSTER      8
 #define PLAT_MAX_PE_PER_CPU            1
 
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifndef AARCH32
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE       (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (1ULL << 32)
+#endif
+
 #endif /* PLATFORM_DEF_H */