[U-Boot] [PATCH v2 1/3] 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.
Signed-off-by: Michal Simek michal.simek@xilinx.com Acked-by: Jagannadha Sutradharudu Teki jaganna@xilinx.com --- Changes in v2: - Use SPDX-License-Identifier instead of full license
arch/arm/cpu/armv7/zynq/Makefile | 1 + arch/arm/cpu/armv7/zynq/ddrc.c | 50 ++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-zynq/hardware.h | 8 +++++ arch/arm/include/asm/arch-zynq/sys_proto.h | 1 + board/xilinx/zynq/board.c | 2 ++ 5 files changed, 62 insertions(+) create mode 100644 arch/arm/cpu/armv7/zynq/ddrc.c
diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile index 388085d..f38b3b7 100644 --- a/arch/arm/cpu/armv7/zynq/Makefile +++ b/arch/arm/cpu/armv7/zynq/Makefile @@ -30,6 +30,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 8b8a91a..b0e713d 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -33,6 +33,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 { @@ -100,4 +101,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 2317121..2698846 100644 --- a/arch/arm/include/asm/arch-zynq/sys_proto.h +++ b/arch/arm/include/asm/arch-zynq/sys_proto.h @@ -30,6 +30,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); diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index b02c364..61a96b8 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -112,5 +112,7 @@ int dram_init(void) { gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+ zynq_ddrc_init(); + return 0; } -- 1.8.2.3

If you don't wait you will loose the first sent packet even all bits in emacps are correctly setup.
Signed-off-by: Michal Simek michal.simek@xilinx.com --- Changes in v2: None
arch/arm/cpu/armv7/zynq/slcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c index 52048c6..1c28e96 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/cpu/armv7/zynq/slcr.c @@ -86,7 +86,7 @@ void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk) /* Configure GEM_RCLK_CTRL */ writel(rclk, &slcr_base->gem0_rclk_ctrl); } - + udelay(100000); out: zynq_slcr_lock(); } -- 1.8.2.3

On Fri, Jul 26, 2013 at 11:33 AM, Michal Simek michal.simek@xilinx.com wrote:
If you don't wait you will loose the first sent packet even all bits in emacps are correctly setup.
Signed-off-by: Michal Simek michal.simek@xilinx.com
Changes in v2: None
arch/arm/cpu/armv7/zynq/slcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c index 52048c6..1c28e96 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/cpu/armv7/zynq/slcr.c @@ -86,7 +86,7 @@ void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk) /* Configure GEM_RCLK_CTRL */ writel(rclk, &slcr_base->gem0_rclk_ctrl); }
udelay(100000);
out: zynq_slcr_lock(); } -- 1.8.2.3
Acked-by: Jagannadha Sutradharudu Teki jaganna@xilinx.com
-- Thanks, Jagan.

Zynq can have axi ethernet and emaclite IPs in programmable logic.
Signed-off-by: Michal Simek michal.simek@xilinx.com
--- Changes in v2: None
board/xilinx/zynq/board.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 61a96b8..f9766a1 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -77,6 +77,23 @@ int board_eth_init(bd_t *bis) { u32 ret = 0;
+#ifdef CONFIG_XILINX_AXIEMAC + ret |= xilinx_axiemac_initialize(bis, XILINX_AXIEMAC_BASEADDR, + XILINX_AXIDMA_BASEADDR); +#endif +#ifdef CONFIG_XILINX_EMACLITE + u32 txpp = 0; + u32 rxpp = 0; +# ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG + txpp = 1; +# endif +# ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG + rxpp = 1; +# endif + ret |= xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR, + txpp, rxpp); +#endif + #if defined(CONFIG_ZYNQ_GEM) # if defined(CONFIG_ZYNQ_GEM0) ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR0, -- 1.8.2.3

On Fri, Jul 26, 2013 at 11:33 AM, Michal Simek michal.simek@xilinx.com wrote:
Zynq can have axi ethernet and emaclite IPs in programmable logic.
Signed-off-by: Michal Simek michal.simek@xilinx.com
Changes in v2: None
board/xilinx/zynq/board.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 61a96b8..f9766a1 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -77,6 +77,23 @@ int board_eth_init(bd_t *bis) { u32 ret = 0;
+#ifdef CONFIG_XILINX_AXIEMAC
ret |= xilinx_axiemac_initialize(bis, XILINX_AXIEMAC_BASEADDR,
XILINX_AXIDMA_BASEADDR);
+#endif +#ifdef CONFIG_XILINX_EMACLITE
u32 txpp = 0;
u32 rxpp = 0;
+# ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
txpp = 1;
+# endif +# ifdef CONFIG_XILINX_EMACLITE_RX_PING_PONG
rxpp = 1;
+# endif
ret |= xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR,
txpp, rxpp);
+#endif
#if defined(CONFIG_ZYNQ_GEM) # if defined(CONFIG_ZYNQ_GEM0) ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR0, -- 1.8.2.3
Acked-by: Jagannadha Sutradharudu Teki jaganna@xilinx.com
-- Thanks, Jagan.
participants (2)
-
Jagan Teki
-
Michal Simek