summaryrefslogtreecommitdiff
path: root/arch/arm/mach-zynqmp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-zynqmp')
-rw-r--r--arch/arm/mach-zynqmp/Kconfig35
-rw-r--r--arch/arm/mach-zynqmp/Makefile1
-rw-r--r--arch/arm/mach-zynqmp/ecc_spl_init.c163
-rw-r--r--arch/arm/mach-zynqmp/handoff.c19
-rw-r--r--arch/arm/mach-zynqmp/include/mach/ecc_spl_init.h13
-rw-r--r--arch/arm/mach-zynqmp/include/mach/hardware.h2
-rwxr-xr-xarch/arm/mach-zynqmp/mkimage_fit_atf.sh59
-rw-r--r--arch/arm/mach-zynqmp/mp.c70
-rw-r--r--arch/arm/mach-zynqmp/spl.c4
9 files changed, 324 insertions, 42 deletions
diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig
index f1301f6661..39144d654e 100644
--- a/arch/arm/mach-zynqmp/Kconfig
+++ b/arch/arm/mach-zynqmp/Kconfig
@@ -92,6 +92,41 @@ config ZYNQMP_NO_DDR
This option configures MMU with no DDR to avoid speculative
access to DDR memory where DDR is not present.
+config SPL_ZYNQMP_DRAM_ECC_INIT
+ bool "Initialize DRAM ECC"
+ depends on SPL
+ help
+ This option initializes all memory to 0xdeadbeef. Must be set if your
+ memory is of ECC type.
+
+config SPL_ZYNQMP_DRAM_BANK1_BASE
+ depends on SPL_ZYNQMP_DRAM_ECC_INIT
+ hex "DRAM Bank1 address"
+ default 0x00000000
+ help
+ Start address of DRAM ECC bank1
+
+config SPL_ZYNQMP_DRAM_BANK1_LEN
+ depends on SPL_ZYNQMP_DRAM_ECC_INIT
+ hex "DRAM Bank1 size"
+ default 0x80000000
+ help
+ Size in bytes of the DRAM ECC bank1
+
+config SPL_ZYNQMP_DRAM_BANK2_BASE
+ depends on SPL_ZYNQMP_DRAM_ECC_INIT
+ hex "DRAM Bank2 address"
+ default 0x800000000
+ help
+ Start address of DRAM ECC bank2
+
+config SPL_ZYNQMP_DRAM_BANK2_LEN
+ depends on SPL_ZYNQMP_DRAM_ECC_INIT
+ hex "DRAM Bank2 size"
+ default 0x0
+ help
+ Size in bytes of the DRAM ECC bank2. A null size takes no action.
+
config SYS_MALLOC_F_LEN
default 0x600
diff --git a/arch/arm/mach-zynqmp/Makefile b/arch/arm/mach-zynqmp/Makefile
index 8a3b074724..eb6c5112b3 100644
--- a/arch/arm/mach-zynqmp/Makefile
+++ b/arch/arm/mach-zynqmp/Makefile
@@ -7,4 +7,5 @@ obj-y += clk.o
obj-y += cpu.o
obj-$(CONFIG_MP) += mp.o
obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o
+obj-$(CONFIG_SPL_ZYNQMP_DRAM_ECC_INIT) += ecc_spl_init.o
obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o
diff --git a/arch/arm/mach-zynqmp/ecc_spl_init.c b/arch/arm/mach-zynqmp/ecc_spl_init.c
new file mode 100644
index 0000000000..f547d8e3a5
--- /dev/null
+++ b/arch/arm/mach-zynqmp/ecc_spl_init.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2015 - 2020 Xilinx, Inc.
+ *
+ * Jorge Ramirez-Ortiz <jorge@foundries.io>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/ecc_spl_init.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+
+#define ZDMA_TRANSFER_MAX_LEN (0x3FFFFFFFU - 7U)
+#define ZDMA_CH_STATUS ((ADMA_CH0_BASEADDR) + 0x0000011CU)
+#define ZDMA_CH_STATUS_STATE_MASK 0x00000003U
+#define ZDMA_CH_STATUS_STATE_DONE 0x00000000U
+#define ZDMA_CH_STATUS_STATE_ERR 0x00000003U
+#define ZDMA_CH_CTRL0 ((ADMA_CH0_BASEADDR) + 0x00000110U)
+#define ZDMA_CH_CTRL0_POINT_TYPE_MASK (u32)0x00000040U
+#define ZDMA_CH_CTRL0_POINT_TYPE_NORMAL (u32)0x00000000U
+#define ZDMA_CH_CTRL0_MODE_MASK (u32)0x00000030U
+#define ZDMA_CH_CTRL0_MODE_WR_ONLY (u32)0x00000010U
+#define ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT ((ADMA_CH0_BASEADDR) + 0x00000188U)
+#define ZDMA_CH_WR_ONLY_WORD0 ((ADMA_CH0_BASEADDR) + 0x00000148U)
+#define ZDMA_CH_WR_ONLY_WORD1 ((ADMA_CH0_BASEADDR) + 0x0000014CU)
+#define ZDMA_CH_WR_ONLY_WORD2 ((ADMA_CH0_BASEADDR) + 0x00000150U)
+#define ZDMA_CH_WR_ONLY_WORD3 ((ADMA_CH0_BASEADDR) + 0x00000154U)
+#define ZDMA_CH_DST_DSCR_WORD0 ((ADMA_CH0_BASEADDR) + 0x00000138U)
+#define ZDMA_CH_DST_DSCR_WORD0_LSB_MASK 0xFFFFFFFFU
+#define ZDMA_CH_DST_DSCR_WORD1 ((ADMA_CH0_BASEADDR) + 0x0000013CU)
+#define ZDMA_CH_DST_DSCR_WORD1_MSB_MASK 0x0001FFFFU
+#define ZDMA_CH_SRC_DSCR_WORD2 ((ADMA_CH0_BASEADDR) + 0x00000130U)
+#define ZDMA_CH_DST_DSCR_WORD2 ((ADMA_CH0_BASEADDR) + 0x00000140U)
+#define ZDMA_CH_CTRL2 ((ADMA_CH0_BASEADDR) + 0x00000200U)
+#define ZDMA_CH_CTRL2_EN_MASK 0x00000001U
+#define ZDMA_CH_ISR ((ADMA_CH0_BASEADDR) + 0x00000100U)
+#define ZDMA_CH_ISR_DMA_DONE_MASK 0x00000400U
+#define ECC_INIT_VAL_WORD 0xDEADBEEFU
+
+#define ZDMA_IDLE_TIMEOUT_USEC 1000000
+#define ZDMA_DONE_TIMEOUT_USEC 5000000
+
+static void ecc_zdma_restore(void)
+{
+ /* Restore reset values for the DMA registers used */
+ writel(ZDMA_CH_CTRL0, 0x00000080U);
+ writel(ZDMA_CH_WR_ONLY_WORD0, 0x00000000U);
+ writel(ZDMA_CH_WR_ONLY_WORD1, 0x00000000U);
+ writel(ZDMA_CH_WR_ONLY_WORD2, 0x00000000U);
+ writel(ZDMA_CH_WR_ONLY_WORD3, 0x00000000U);
+ writel(ZDMA_CH_DST_DSCR_WORD0, 0x00000000U);
+ writel(ZDMA_CH_DST_DSCR_WORD1, 0x00000000U);
+ writel(ZDMA_CH_SRC_DSCR_WORD2, 0x00000000U);
+ writel(ZDMA_CH_DST_DSCR_WORD2, 0x00000000U);
+ writel(ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT, 0x00000000U);
+}
+
+static void ecc_dram_bank_init(u64 addr, u64 len)
+{
+ bool retry = true;
+ u32 timeout;
+ u64 bytes;
+ u32 size;
+ u64 src;
+ u32 reg;
+
+ if (!len)
+ return;
+retry:
+ bytes = len;
+ src = addr;
+ ecc_zdma_restore();
+ while (bytes > 0) {
+ size = bytes > ZDMA_TRANSFER_MAX_LEN ?
+ ZDMA_TRANSFER_MAX_LEN : (u32)bytes;
+
+ /* Wait until the DMA is in idle state */
+ timeout = ZDMA_IDLE_TIMEOUT_USEC;
+ do {
+ udelay(1);
+ reg = readl(ZDMA_CH_STATUS);
+ reg &= ZDMA_CH_STATUS_STATE_MASK;
+ if (!timeout--) {
+ puts("error, ECC DMA failed to idle\n");
+ goto done;
+ }
+
+ } while ((reg != ZDMA_CH_STATUS_STATE_DONE) &&
+ (reg != ZDMA_CH_STATUS_STATE_ERR));
+
+ /* Enable Simple (Write Only) Mode */
+ reg = readl(ZDMA_CH_CTRL0);
+ reg &= (ZDMA_CH_CTRL0_POINT_TYPE_MASK |
+ ZDMA_CH_CTRL0_MODE_MASK);
+ reg |= (ZDMA_CH_CTRL0_POINT_TYPE_NORMAL |
+ ZDMA_CH_CTRL0_MODE_WR_ONLY);
+ writel(reg, ZDMA_CH_CTRL0);
+
+ /* Fill in the data to be written */
+ writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD0);
+ writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD1);
+ writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD2);
+ writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD3);
+
+ /* Write Destination Address */
+ writel((u32)(src & ZDMA_CH_DST_DSCR_WORD0_LSB_MASK),
+ ZDMA_CH_DST_DSCR_WORD0);
+ writel((u32)((src >> 32) & ZDMA_CH_DST_DSCR_WORD1_MSB_MASK),
+ ZDMA_CH_DST_DSCR_WORD1);
+
+ /* Size to be Transferred. Recommended to set both src and dest sizes */
+ writel(size, ZDMA_CH_SRC_DSCR_WORD2);
+ writel(size, ZDMA_CH_DST_DSCR_WORD2);
+
+ /* DMA Enable */
+ reg = readl(ZDMA_CH_CTRL2);
+ reg |= ZDMA_CH_CTRL2_EN_MASK;
+ writel(reg, ZDMA_CH_CTRL2);
+
+ /* Check the status of the transfer by polling on DMA Done */
+ timeout = ZDMA_DONE_TIMEOUT_USEC;
+ do {
+ udelay(1);
+ reg = readl(ZDMA_CH_ISR);
+ reg &= ZDMA_CH_ISR_DMA_DONE_MASK;
+ if (!timeout--) {
+ puts("error, ECC DMA timeout\n");
+ goto done;
+ }
+ } while (reg != ZDMA_CH_ISR_DMA_DONE_MASK);
+
+ /* Clear DMA status */
+ reg = readl(ZDMA_CH_ISR);
+ reg |= ZDMA_CH_ISR_DMA_DONE_MASK;
+ writel(ZDMA_CH_ISR_DMA_DONE_MASK, ZDMA_CH_ISR);
+
+ /* Read the channel status for errors */
+ reg = readl(ZDMA_CH_STATUS);
+ if (reg == ZDMA_CH_STATUS_STATE_ERR) {
+ if (retry) {
+ retry = false;
+ goto retry;
+ }
+ puts("error, ECC DMA error\n");
+ break;
+ }
+
+ bytes -= size;
+ src += size;
+ }
+done:
+ ecc_zdma_restore();
+}
+
+void zynqmp_ecc_init(void)
+{
+ ecc_dram_bank_init(CONFIG_SPL_ZYNQMP_DRAM_BANK1_BASE,
+ CONFIG_SPL_ZYNQMP_DRAM_BANK1_LEN);
+ ecc_dram_bank_init(CONFIG_SPL_ZYNQMP_DRAM_BANK2_BASE,
+ CONFIG_SPL_ZYNQMP_DRAM_BANK2_LEN);
+}
diff --git a/arch/arm/mach-zynqmp/handoff.c b/arch/arm/mach-zynqmp/handoff.c
index 7d7ab9da6e..31346d9b2e 100644
--- a/arch/arm/mach-zynqmp/handoff.c
+++ b/arch/arm/mach-zynqmp/handoff.c
@@ -71,6 +71,7 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
uintptr_t fdt_addr)
{
struct xfsbl_atf_handoff_params *atfhandoffparams;
+ u32 index = 0;
atfhandoffparams = (void *)CONFIG_SPL_TEXT_BASE;
atfhandoffparams->magic[0] = 'X';
@@ -78,14 +79,22 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
atfhandoffparams->magic[2] = 'N';
atfhandoffparams->magic[3] = 'X';
- atfhandoffparams->num_entries = 0;
+ if (bl32_entry) {
+ atfhandoffparams->partition[index].entry_point = bl32_entry;
+ atfhandoffparams->partition[index].flags = FSBL_FLAGS_EL1 << FSBL_FLAGS_EL_SHIFT |
+ FSBL_FLAGS_SECURE << FSBL_FLAGS_TZ_SHIFT;
+ index++;
+ }
+
if (bl33_entry) {
- atfhandoffparams->partition[0].entry_point = bl33_entry;
- atfhandoffparams->partition[0].flags = FSBL_FLAGS_EL2 <<
- FSBL_FLAGS_EL_SHIFT;
- atfhandoffparams->num_entries++;
+ atfhandoffparams->partition[index].entry_point = bl33_entry;
+ atfhandoffparams->partition[index].flags = FSBL_FLAGS_EL2 <<
+ FSBL_FLAGS_EL_SHIFT;
+ index++;
}
+ atfhandoffparams->num_entries = index;
+
writel(CONFIG_SPL_TEXT_BASE, &pmu_base->gen_storage6);
return NULL;
diff --git a/arch/arm/mach-zynqmp/include/mach/ecc_spl_init.h b/arch/arm/mach-zynqmp/include/mach/ecc_spl_init.h
new file mode 100644
index 0000000000..b4b6fcf53b
--- /dev/null
+++ b/arch/arm/mach-zynqmp/include/mach/ecc_spl_init.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2015 - 2020 Xilinx, Inc.
+ *
+ * Jorge Ramirez-Ortiz <jorge@foundries.io>
+ */
+
+#ifndef __ARCH_ZYNQMP_ECC_INIT_H
+#define __ARCH_ZYNQMP_ECC_INIT_H
+
+void zynqmp_ecc_init(void);
+
+#endif
diff --git a/arch/arm/mach-zynqmp/include/mach/hardware.h b/arch/arm/mach-zynqmp/include/mach/hardware.h
index a798aa0eb9..3776499070 100644
--- a/arch/arm/mach-zynqmp/include/mach/hardware.h
+++ b/arch/arm/mach-zynqmp/include/mach/hardware.h
@@ -24,6 +24,8 @@
+ 0x00000114)
#define ZYNQMP_PS_SYSMON_ANALOG_BUS_VAL 0x00003210
+#define ADMA_CH0_BASEADDR 0xFFA80000
+
#define PS_MODE0 BIT(0)
#define PS_MODE1 BIT(1)
#define PS_MODE2 BIT(2)
diff --git a/arch/arm/mach-zynqmp/mkimage_fit_atf.sh b/arch/arm/mach-zynqmp/mkimage_fit_atf.sh
index 92e31849f8..592be7f670 100755
--- a/arch/arm/mach-zynqmp/mkimage_fit_atf.sh
+++ b/arch/arm/mach-zynqmp/mkimage_fit_atf.sh
@@ -8,16 +8,34 @@
BL33="u-boot-nodtb.bin"
[ -z "$BL31" ] && BL31="bl31.bin"
-# Can be also done as ${CROSS_COMPILE}readelf -l bl31.elf | awk '/Entry point/ { print $3 }'
+BL31_ELF="${BL31%.*}.elf"
+[ -f ${BL31_ELF} ] && ATF_LOAD_ADDR=`${CROSS_COMPILE}readelf -l "${BL31_ELF}" | \
+awk '/Entry point/ { print $3 }'`
+
[ -z "$ATF_LOAD_ADDR" ] && ATF_LOAD_ADDR="0xfffea000"
+ATF_LOAD_ADDR_LOW=`printf 0x%x $((ATF_LOAD_ADDR & 0xffffffff))`
+ATF_LOAD_ADDR_HIGH=`printf 0x%x $((ATF_LOAD_ADDR >> 32))`
+
+[ -z "$BL32" ] && BL32="tee.bin"
+BL32_ELF="${BL32%.*}.elf"
+[ -f ${BL32_ELF} ] && TEE_LOAD_ADDR=`${CROSS_COMPILE}readelf -l "${BL32_ELF}" | \
+awk '/Entry point/ { print $3 }'`
+
+[ -z "$TEE_LOAD_ADDR" ] && TEE_LOAD_ADDR="0x60000000"
+TEE_LOAD_ADDR_LOW=`printf 0x%x $((TEE_LOAD_ADDR & 0xffffffff))`
+TEE_LOAD_ADDR_HIGH=`printf 0x%x $((TEE_LOAD_ADDR >> 32))`
if [ -z "$BL33_LOAD_ADDR" ];then
BL33_LOAD_ADDR=`awk '/CONFIG_SYS_TEXT_BASE/ { print $3 }' include/generated/autoconf.h`
fi
+BL33_LOAD_ADDR_LOW=`printf 0x%x $((BL33_LOAD_ADDR & 0xffffffff))`
+BL33_LOAD_ADDR_HIGH=`printf 0x%x $((BL33_LOAD_ADDR >> 32))`
DTB_LOAD_ADDR=`awk '/CONFIG_XILINX_OF_BOARD_DTB_ADDR/ { print $3 }' include/generated/autoconf.h`
if [ ! -z "$DTB_LOAD_ADDR" ]; then
- DTB_LOAD="load = <$DTB_LOAD_ADDR>;"
+ DTB_LOAD_ADDR_LOW=`printf 0x%x $((DTB_LOAD_ADDR & 0xffffffff))`
+ DTB_LOAD_ADDR_HIGH=`printf 0x%x $((DTB_LOAD_ADDR >> 32))`
+ DTB_LOAD="load = <$DTB_LOAD_ADDR_HIGH $DTB_LOAD_ADDR_LOW>;"
else
DTB_LOAD=""
fi
@@ -49,8 +67,8 @@ cat << __HEADER_EOF
os = "u-boot";
arch = "arm64";
compression = "none";
- load = <$BL33_LOAD_ADDR>;
- entry = <$BL33_LOAD_ADDR>;
+ load = <$BL33_LOAD_ADDR_HIGH $BL33_LOAD_ADDR_LOW>;
+ entry = <$BL33_LOAD_ADDR_HIGH $BL33_LOAD_ADDR_LOW>;
hash {
algo = "md5";
};
@@ -66,8 +84,8 @@ cat << __ATF
os = "arm-trusted-firmware";
arch = "arm64";
compression = "none";
- load = <$ATF_LOAD_ADDR>;
- entry = <$ATF_LOAD_ADDR>;
+ load = <$ATF_LOAD_ADDR_HIGH $ATF_LOAD_ADDR_LOW>;
+ entry = <$ATF_LOAD_ADDR_HIGH $ATF_LOAD_ADDR_LOW>;
hash {
algo = "md5";
};
@@ -75,6 +93,24 @@ cat << __ATF
__ATF
fi
+if [ -f $BL32 ]; then
+cat << __TEE
+ tee {
+ description = "TEE firmware";
+ data = /incbin/("$BL32");
+ type = "firmware";
+ os = "tee";
+ arch = "arm64";
+ compression = "none";
+ load = <$TEE_LOAD_ADDR_HIGH $TEE_LOAD_ADDR_LOW>;
+ entry = <$TEE_LOAD_ADDR_HIGH $TEE_LOAD_ADDR_LOW>;
+ hash {
+ algo = "md5";
+ };
+ };
+__TEE
+fi
+
DEFAULT=1
cnt=1
for dtname in $DT
@@ -117,6 +153,16 @@ cat << __CONF_SECTION1_EOF
};
__CONF_SECTION1_EOF
else
+if [ -f $BL32 ]; then
+cat << __CONF_SECTION1_EOF
+ config_$cnt {
+ description = "$(basename $dtname .dtb)";
+ firmware = "atf";
+ loadables = "uboot", "tee";
+ fdt = "fdt_$cnt";
+ };
+__CONF_SECTION1_EOF
+else
cat << __CONF_SECTION1_EOF
config_$cnt {
description = "$(basename $dtname .dtb)";
@@ -126,6 +172,7 @@ cat << __CONF_SECTION1_EOF
};
__CONF_SECTION1_EOF
fi
+fi
cnt=$((cnt+1))
done
diff --git a/arch/arm/mach-zynqmp/mp.c b/arch/arm/mach-zynqmp/mp.c
index 656678a155..74783ae5a7 100644
--- a/arch/arm/mach-zynqmp/mp.c
+++ b/arch/arm/mach-zynqmp/mp.c
@@ -37,6 +37,8 @@
#define ZYNQMP_CORE_APU0 0
#define ZYNQMP_CORE_APU3 3
+#define ZYNQMP_CORE_RPU0 4
+#define ZYNQMP_CORE_RPU1 5
#define ZYNQMP_MAX_CORES 6
@@ -54,18 +56,20 @@ int cpu_reset(u32 nr)
return 0;
}
-static void set_r5_halt_mode(u8 halt, u8 mode)
+static void set_r5_halt_mode(u32 nr, u8 halt, u8 mode)
{
u32 tmp;
- tmp = readl(&rpu_base->rpu0_cfg);
- if (halt == HALT)
- tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
- else
- tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
- writel(tmp, &rpu_base->rpu0_cfg);
+ if (mode == LOCK || nr == ZYNQMP_CORE_RPU0) {
+ tmp = readl(&rpu_base->rpu0_cfg);
+ if (halt == HALT)
+ tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+ else
+ tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+ writel(tmp, &rpu_base->rpu0_cfg);
+ }
- if (mode == LOCK) {
+ if (mode == LOCK || nr == ZYNQMP_CORE_RPU1) {
tmp = readl(&rpu_base->rpu1_cfg);
if (halt == HALT)
tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
@@ -93,30 +97,34 @@ static void set_r5_tcm_mode(u8 mode)
writel(tmp, &rpu_base->rpu_glbl_ctrl);
}
-static void set_r5_reset(u8 mode)
+static void set_r5_reset(u32 nr, u8 mode)
{
u32 tmp;
tmp = readl(&crlapb_base->rst_lpd_top);
- tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
- ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+ if (mode == LOCK || nr == ZYNQMP_CORE_RPU0)
+ tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+ ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
- if (mode == LOCK)
- tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+ if (mode == LOCK || nr == ZYNQMP_CORE_RPU1)
+ tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+ ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK);
writel(tmp, &crlapb_base->rst_lpd_top);
}
-static void release_r5_reset(u8 mode)
+static void release_r5_reset(u32 nr, u8 mode)
{
u32 tmp;
tmp = readl(&crlapb_base->rst_lpd_top);
- tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
- ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+ if (mode == LOCK || nr == ZYNQMP_CORE_RPU0)
+ tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+ ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
- if (mode == LOCK)
- tmp &= ~ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+ if (mode == LOCK || nr == ZYNQMP_CORE_RPU1)
+ tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+ ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK);
writel(tmp, &crlapb_base->rst_lpd_top);
}
@@ -141,7 +149,7 @@ int cpu_disable(u32 nr)
val |= 1 << nr;
writel(val, &crfapb_base->rst_fpd_apu);
} else {
- set_r5_reset(LOCK);
+ set_r5_reset(nr, SPLIT);
}
return 0;
@@ -212,14 +220,14 @@ void initialize_tcm(bool mode)
{
if (!mode) {
set_r5_tcm_mode(LOCK);
- set_r5_halt_mode(HALT, LOCK);
+ set_r5_halt_mode(ZYNQMP_CORE_RPU0, HALT, LOCK);
enable_clock_r5();
- release_r5_reset(LOCK);
+ release_r5_reset(ZYNQMP_CORE_RPU0, LOCK);
} else {
set_r5_tcm_mode(SPLIT);
- set_r5_halt_mode(HALT, SPLIT);
+ set_r5_halt_mode(ZYNQMP_CORE_RPU1, HALT, SPLIT);
enable_clock_r5();
- release_r5_reset(SPLIT);
+ release_r5_reset(ZYNQMP_CORE_RPU1, SPLIT);
}
}
@@ -268,28 +276,28 @@ int cpu_release(u32 nr, int argc, char *const argv[])
if (!strncmp(argv[1], "lockstep", 8)) {
printf("R5 lockstep mode\n");
- set_r5_reset(LOCK);
+ set_r5_reset(nr, LOCK);
set_r5_tcm_mode(LOCK);
- set_r5_halt_mode(HALT, LOCK);
+ set_r5_halt_mode(nr, HALT, LOCK);
set_r5_start(boot_addr);
enable_clock_r5();
- release_r5_reset(LOCK);
+ release_r5_reset(nr, LOCK);
dcache_disable();
write_tcm_boot_trampoline(boot_addr_uniq);
dcache_enable();
- set_r5_halt_mode(RELEASE, LOCK);
+ set_r5_halt_mode(nr, RELEASE, LOCK);
} else if (!strncmp(argv[1], "split", 5)) {
printf("R5 split mode\n");
- set_r5_reset(SPLIT);
+ set_r5_reset(nr, SPLIT);
set_r5_tcm_mode(SPLIT);
- set_r5_halt_mode(HALT, SPLIT);
+ set_r5_halt_mode(nr, HALT, SPLIT);
set_r5_start(boot_addr);
enable_clock_r5();
- release_r5_reset(SPLIT);
+ release_r5_reset(nr, SPLIT);
dcache_disable();
write_tcm_boot_trampoline(boot_addr_uniq);
dcache_enable();
- set_r5_halt_mode(RELEASE, SPLIT);
+ set_r5_halt_mode(nr, RELEASE, SPLIT);
} else {
printf("Unsupported mode\n");
return 1;
diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
index 88386b23e5..8fcae2c6a6 100644
--- a/arch/arm/mach-zynqmp/spl.c
+++ b/arch/arm/mach-zynqmp/spl.c
@@ -15,6 +15,7 @@
#include <asm/io.h>
#include <asm/spl.h>
#include <asm/arch/hardware.h>
+#include <asm/arch/ecc_spl_init.h>
#include <asm/arch/psu_init_gpl.h>
#include <asm/arch/sys_proto.h>
@@ -22,6 +23,9 @@ void board_init_f(ulong dummy)
{
board_early_init_f();
board_early_init_r();
+#ifdef CONFIG_SPL_ZYNQMP_DRAM_ECC_INIT
+ zynqmp_ecc_init();
+#endif
}
static void ps_mode_reset(ulong mode)