diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/cpu/armv7/zynq/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/zynq/ddrc.c | 50 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-zynq/hardware.h | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-zynq/sys_proto.h | 1 |
4 files changed, 60 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile index e5494f7..de6b081 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 0000000..ba6a6ae --- /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; +} diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h index 25f0e3d..ca56d8a 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -17,6 +17,7 @@ #define ZYNQ_SDHCI_BASEADDR1 0xE0101000 #define ZYNQ_I2C_BASEADDR0 0xE0004000 #define ZYNQ_I2C_BASEADDR1 0xE0005000 +#define ZYNQ_DDRC_BASEADDR 0xF8006000 /* Reflect slcr offsets */ struct slcr_regs { @@ -84,4 +85,11 @@ struct scu_regs { #define scu_base ((struct scu_regs *)ZYNQ_SCU_BASEADDR) +struct ddrc_regs { + u32 ddrc_ctrl; /* 0x0 */ + u32 reserved[60]; + u32 ecc_scrub; /* 0xF4 */ +}; +#define ddrc_base ((struct ddrc_regs *)ZYNQ_DDRC_BASEADDR) + #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/include/asm/arch-zynq/sys_proto.h index 19a4eec..110de90 100644 --- a/arch/arm/include/asm/arch-zynq/sys_proto.h +++ b/arch/arm/include/asm/arch-zynq/sys_proto.h @@ -14,6 +14,7 @@ extern void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk); extern void zynq_slcr_devcfg_disable(void); extern void zynq_slcr_devcfg_enable(void); extern u32 zynq_slcr_get_idcode(void); +extern void zynq_ddrc_init(void); /* Driver extern functions */ extern int zynq_sdhci_init(u32 regbase); |