aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorMichal Simek2013-06-17 14:37:01 +0200
committerMichal Simek2013-08-12 08:59:55 +0200
commit148ba55cc618eaca19d7c86bdc003a7a71ee3a92 (patch)
treeb16460d9e03b64975ea70c2629584c401991f466 /arch/arm/cpu
parenta78dac79ede7fbb4c9e816abc879655540c3f076 (diff)
zynq: Add new ddrc driver for ECC support
The first 1MB is not initialized by first stage bootloader. Check if memory is setup to 16bit mode and ECC is enabled. If it is, clear the first 1MB. Also u-boot should report only the half size of memory. Acked-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/armv7/zynq/Makefile1
-rw-r--r--arch/arm/cpu/armv7/zynq/ddrc.c50
2 files changed, 51 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile
index e5494f74898..de6b08157e9 100644
--- a/arch/arm/cpu/armv7/zynq/Makefile
+++ b/arch/arm/cpu/armv7/zynq/Makefile
@@ -14,6 +14,7 @@ LIB = $(obj)lib$(SOC).o
COBJS-y := timer.o
COBJS-y += cpu.o
+COBJS-y += ddrc.o
COBJS-y += slcr.o
COBJS := $(COBJS-y)
diff --git a/arch/arm/cpu/armv7/zynq/ddrc.c b/arch/arm/cpu/armv7/zynq/ddrc.c
new file mode 100644
index 00000000000..ba6a6aee5cb
--- /dev/null
+++ b/arch/arm/cpu/armv7/zynq/ddrc.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 - 2013 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012 - 2013 Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hardware.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Control regsiter bitfield definitions */
+#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK 0xC
+#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT 2
+#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT 1
+
+/* ECC scrub regsiter definitions */
+#define ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK 0x7
+#define ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED 0x4
+
+void zynq_ddrc_init(void)
+{
+ u32 width, ecctype;
+
+ width = readl(&ddrc_base->ddrc_ctrl);
+ width = (width & ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK) >>
+ ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT;
+ ecctype = (readl(&ddrc_base->ecc_scrub) &
+ ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK);
+
+ /* ECC is enabled when memory is in 16bit mode and it is enabled */
+ if ((ecctype == ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED) &&
+ (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT)) {
+ puts("Memory: ECC enabled\n");
+ /*
+ * Clear the first 1MB because it is not initialized from
+ * first stage bootloader. To get ECC to work all memory has
+ * been initialized by writing any value.
+ */
+ memset(0, 0, 1 * 1024 * 1024);
+ } else {
+ puts("Memory: ECC disabled\n");
+ }
+
+ if (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT)
+ gd->ram_size /= 2;
+}